cooldiyer
驱动牛犊
驱动牛犊
  • 注册日期2008-01-01
  • 最后登录2016-01-09
  • 粉丝1
  • 关注0
  • 积分27分
  • 威望216点
  • 贡献值0点
  • 好评度3点
  • 原创分0分
  • 专家分0分
阅读:1653回复:3

passthru在不同网卡上运行,具然不兼容

楼主#
更多 发布于:2009-03-27 18:28
基于passthru做了个内核的端口转发程序,功能是如果指定IP连接到本机端口A,修改数据包目的端口到B,数据发送时,做相反处理

在本人的Realtek RTL8168/8111网卡,和朋友的一个intel网卡上测试成功,今天又测试,网卡类型是HP的XXX型号,
可以建立连接,但是安装此驱动的服务器能建立连接接收数据,不能发送数据,驱动调试,发现捕捉到数据包,成功修改,可就是
带PUSH标志的也就是携带发送数据的TCP包不能出去,ACK这些,用在三步握手的数据包,可以正常通信


本人不服,改用IOCTL_IP_SET_FIREWALL_HOOK方式过滤修改数据包,结果具然跟NDIS的passthru测试结果一样,有些机器成功,有些不能


在passthru里,我修改了PtReceive, PtReceiveComplete里的数据包,,发送例程里,我修改了MpSend, MpSendPackets,尽管我知道这两个只会调用后者,但能拦的地方全拦了
我先直接修改packet链表指向的缓冲区,后来就复制一份修改,效果一样,都不行.............
TCP.检验和绝对计算正确.....不是这的原因,可是这情况,郁闷一星期了.....能建立连接,服务器只能接收,不能发送给对方.....
高手请指点迷津.

由于接收正常,我只帖发送时的修改主过程,大大们分析下原因.郁闷的要死了

        do
        {
            ULONG    TotalPacketLength;
            PVOID MemoryVA;
                PNDIS_BUFFER PktBuffer = NULL;
            NdisAcquireSpinLock(&pAdapt->Lock);
            //
            // If the below miniport is going to low power state, stop sending down any packet.
            //
            if (pAdapt->PTDeviceState > NdisDeviceStateD0)
            {
                NdisReleaseSpinLock(&pAdapt->Lock);
                Status = NDIS_STATUS_FAILURE;
                break;
            }
            pAdapt->OutstandingSends++;
            NdisReleaseSpinLock(&pAdapt->Lock);
            
            NdisAllocatePacket(&Status,
                               &MyPacket,
                               pAdapt->SendPacketPoolHandle);

            //////////////////////////////////////////////////////////////////////////
            // add
            if(Status != NDIS_STATUS_SUCCESS)
            {
                return ;
            }

    
                NdisQueryPacket(Packet, NULL, NULL, NULL, &TotalPacketLength);

    
                Status = NdisAllocateMemory(&MemoryVA, TotalPacketLength, 0, HighestAcceptableMax);
                if(Status == NDIS_STATUS_FAILURE)
                {
                    // Release the memory
                    NdisFreeMemory(MemoryVA,
                        TotalPacketLength, //Maybe add a checksum length
                        0);
                    return ;
                }
                NdisAllocateBuffer(&Status, &PktBuffer,pAdapt->SendPacketPoolHandle, MemoryVA, TotalPacketLength);//Maybe add a checksum length
                
                CopyPktToBuf(Packet, MemoryVA);
                NdisChainBufferAtBack(MyPacket, PktBuffer);


                // BEGIN_PTEX_FILTER
                //
                // 调用修改封包的函数
                //
                FltDirectProcessPacket(MemoryVA, TotalPacketLength, TRUE);
                // END_PTEX_FILTER
                
            //////////////////////////////////////////////////////////////////////////

            if (Status == NDIS_STATUS_SUCCESS)
            {
                PSEND_RSVD        SendRsvd;

                PNDIS_PACKET_EXTENSION Old, New;

                SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved);
                SendRsvd->OriginalPkt = Packet;

                MyPacket->Private.Flags = NdisGetPacketFlags(Packet);
 
 //               MyPacket->Private.Head = Packet->Private.Head;
   //             MyPacket->Private.Tail = Packet->Private.Tail;

                NdisSetPacketFlags(MyPacket, NDIS_FLAGS_DONT_LOOPBACK);

                Old = NDIS_PACKET_EXTENSION_FROM_PACKET(Packet);
                New = NDIS_PACKET_EXTENSION_FROM_PACKET(MyPacket);
                
                New->NdisPacketInfo[TcpIpChecksumPacketInfo] = Old->NdisPacketInfo[TcpIpChecksumPacketInfo];
                New->NdisPacketInfo[IpSecPacketInfo] = Old->NdisPacketInfo[IpSecPacketInfo];
                New->NdisPacketInfo[TcpLargeSendPacketInfo] = Old->NdisPacketInfo[TcpLargeSendPacketInfo];
                New->NdisPacketInfo[ClassificationHandlePacketInfo] = Old->NdisPacketInfo[ClassificationHandlePacketInfo];
                New->NdisPacketInfo[Ieee8021pPriority] = Old->NdisPacketInfo[Ieee8021pPriority];
#ifdef WIN9X
                //
                // Work around the fact that NDIS does not initialize this
                // to FALSE on Win9x.
                //
                MyPacket->Private.ValidCounts = FALSE;
#endif // WIN9X

                //
                // Copy the OOB data from the original packet to the new
                // packet.
                //
                NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket),
                            NDIS_OOB_DATA_FROM_PACKET(Packet),
                            sizeof(NDIS_PACKET_OOB_DATA));
                //
                // Copy relevant parts of the per packet info into the new packet
                //
#ifndef WIN9X
                NdisIMCopySendPerPacketInfo(MyPacket, Packet);
#endif

                //
                // Copy the Media specific information
                //
                NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet,
                                                    &MediaSpecificInfo,
                                                    &MediaSpecificInfoSize);

                if (MediaSpecificInfo || MediaSpecificInfoSize)
                {
                    NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket,
                                                        MediaSpecificInfo,
                                                        MediaSpecificInfoSize);
                }

                NdisSend(&Status,
                         pAdapt->BindingHandle,
                         MyPacket);

                if (Status != NDIS_STATUS_PENDING)
                {
#ifndef WIN9X
                    NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket);
#endif
                    NdisUnchainBufferAtBack(MyPacket,&PktBuffer);
                    NdisFreeBuffer(PktBuffer);
                    NdisFreeMemory(MemoryVA,
                        TotalPacketLength, //Maybe add a checksum length
                        0);

                    NdisFreePacket(MyPacket);
                    ADAPT_DECR_PENDING_SENDS(pAdapt);
                }
            }
            else
            {
                //
                // The driver cannot allocate a packet.
                //
                ADAPT_DECR_PENDING_SENDS(pAdapt);
            }
        }
        while (FALSE);
cooldiyer
驱动牛犊
驱动牛犊
  • 注册日期2008-01-01
  • 最后登录2016-01-09
  • 粉丝1
  • 关注0
  • 积分27分
  • 威望216点
  • 贡献值0点
  • 好评度3点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2009-03-27 20:33
兄弟们帮帮忙啊...这问题已经郁闷了我一星期了
cooldiyer
驱动牛犊
驱动牛犊
  • 注册日期2008-01-01
  • 最后登录2016-01-09
  • 粉丝1
  • 关注0
  • 积分27分
  • 威望216点
  • 贡献值0点
  • 好评度3点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2009-03-28 00:31
用driverstudio又做了一个,结果还是一样,哭啊,具体代码如下

BOOLEAN FltDirectProcessPacket(PVOID pPacketContent, UINT nPacketLength, BOOLEAN bIncludeETHdr)
{
    //////////////////////////////////////////////////////////////////////////
    // modify it
    struct libnet_ip_hdr *    iph_p = NULL;
    struct libnet_tcp_hdr *    tcph = NULL;
    BOOLEAN    isPacketModify = FALSE;
    
    // 没有设置端口映射
    if (0 == KernelPortMap.IpAddr)
    {
        return isPacketModify;
    }
    
    T.Trace(__FUNCTION__"\n");
    // 不是IP协议
    if (bIncludeETHdr && 0x8 != ((struct libnet_ethernet_hdr *)pPacketContent)->ether_type)
    {
        return isPacketModify;
    }
    
    if (nPacketLength < LIBNET_IP_H)
    {
        return isPacketModify;
    }
    
    iph_p = bIncludeETHdr ? (struct libnet_ip_hdr *)((char *)pPacketContent + sizeof(struct libnet_ethernet_hdr)) : (struct libnet_ip_hdr *)pPacketContent;
    
    if (IPPROTO_TCP != iph_p->ip_p)
    {
        return isPacketModify;
    }
    
    
    tcph = (struct libnet_tcp_hdr *)((char *)iph_p + (iph_p->ip_hl << 2));
    
    // 防止溢出
    if (nPacketLength < (LIBNET_IP_H + LIBNET_TCP_H))
    {
        return isPacketModify;
    }
    
    if (/*iph_p->ip_src.s_addr == KernelPortMap.IpAddr && */tcph->th_dport == KernelPortMap.OrgPort)
    {
        T.Trace("libnet_do_checksum\n");
        tcph->th_dport = KernelPortMap.MapPort;
        libnet_do_checksum((u_char *)iph_p, IPPROTO_TCP, ntohs(iph_p->ip_len) - LIBNET_TCP_H);
        isPacketModify = TRUE;
    }
    if (/*iph_p->ip_dst.s_addr == KernelPortMap.IpAddr && */tcph->th_sport == KernelPortMap.MapPort)
    {
        T.Trace("libnet_do_checksum\n");
        tcph->th_sport = KernelPortMap.OrgPort;
        libnet_do_checksum((u_char *)iph_p, IPPROTO_TCP, ntohs(iph_p->ip_len) - LIBNET_TCP_H);
        isPacketModify = TRUE;
    }
    
    return    isPacketModify;
}

VOID FltProcessPackage(KNdisPacket& Packet)
{
    T.Trace(__FUNCTION__"\n");

    UINT    nTotalLength = Packet.QueryTotalLength();
    PUCHAR    lpPacket = new UCHAR[nTotalLength];
    
    if (!lpPacket)
        return;
    
    UINT nBufCnt = Packet.QueryBufferCount();
    KNdisBuffer ndisBuffer = Packet.QueryFirstBuffer();  
    UINT offset = 0;
    for(UINT i = 0; i < nBufCnt; i++)
    {
        if (ndisBuffer.IsValid())
        {
            PUCHAR src = (PUCHAR)ndisBuffer.Address();
            UINT len = ndisBuffer.Length();
            NdisMoveMemory(lpPacket + offset, src, len);
            offset = offset + len;
            ndisBuffer = ndisBuffer.GetNext();
        }
    }
    
    // 如果修改了
    if (FltDirectProcessPacket(lpPacket, nTotalLength, TRUE))
    {
        ndisBuffer = Packet.QueryFirstBuffer();  
        offset = 0;
        for(UINT i = 0; i < nBufCnt; i++)
        {
            if(ndisBuffer.IsValid())
            {
                PUCHAR src = (PUCHAR)ndisBuffer.Address();
                UINT len = ndisBuffer.Length();
                NdisMoveMemory(src, lpPacket + offset, len);
                offset = offset + len;
                ndisBuffer = ndisBuffer.GetNext();
            }
        }
    }
    
    delete lpPacket;
}
//////////////////////////////////////////////////////////////////////
// Constructor
kpmAdapter::kpmAdapter()
{
    // TODO: initialize your private data members
    //       Do NOT call any NDIS functions in here. Defer to Initialize()

    m_BufferPool.Initialize(8);

    KernelPortMap.IpAddr = inet_addr("192.168.1.100");
    KernelPortMap.OrgPort = htons(81);
    KernelPortMap.MapPort = htons(82);
}

//////////////////////////////////////////////////////////////////////
// Destructor
kpmAdapter::~kpmAdapter()
{
    // TODO: deallocate all the resources allocated in constructor/Initialize()
    //
}

////////////////////////////////////////////////////////////////////
// NDIS callback handlers
////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////
// kpmAdapter::OnInitialize
//
//    The framework calls this method when a new virtual NIC represented
//    by the kpmAdapter is created. At this time the binding to the
//  underlying real NIC is completed already. Most of the glue work has
//  been done by the framework, so this method could just return
//  NDIS_STATUS_SUCCESS to grant the creation of the filter. Or, it might
//  inspect the underlying medium type (Medium) and/or set-up
//  some private config parameters from the Registry (Config) before
//  returning.
//
// Parameters:
//        Medium
//            Reference to the KNdisMedium object which has a medium type
//            selected for the underlying binding by the real NIC
//        Config
//            Reference to miniport's KNdisConfig object used to query various
//            configuration parameters
//
// Return
//        NDIS_STATUS_SUCCESS        Proceed with the creation of the filter
//        NDIS_STATUS_XXXXXXX        Error. The framework rolls back and fails the
//                                miniport initialization.
// IRQL:
//        PASSIVE_LEVEL
// Return Mode:
//        Synchronous
//
NDIS_STATUS kpmAdapter::OnInitialize(const KNdisMedium& Medium, KNdisConfig& Config)
{
    T.Trace(__FUNCTION__" %s at %ws\n", Medium.Text(), GetBoundDeviceName());

    UNREFERENCED_PARAMETER(Config);

    return NDIS_STATUS_SUCCESS;
}

////////////////////////////////////////////////////////////////////
// kpmAdapter::OnHalt
//
// Either virtual NIC or underlying binding is being destroyed by NDIS
// Not much can we do here.
//
VOID kpmAdapter::OnHalt()
{
    T.Trace(__FUNCTION__"\n");
    // TODO: deinit private members
}

////////////////////////////////////////////////////////////////////
// kpmAdapter::OnSend
//
// Intercepts the upper-layer send. Here's where the filtering in
// the outgoing direction takes place. The filter is given a chance
// to examine the original packet submitted by a protocol (Original)
// and copy or modify or just drop it. The framework supplies a fresh
// packet descriptor (Repackaged) good for passing one packet down
// the binding. A filter that needs more packets (e.g. it implements
// some sort of repacketization) has to maintiain an internal packet
// pool and implement the OnSendComplete() handler.
//
// In LBFO case, the filter can choose forwarding the packet over
// an other filter's instance binding from the bundle of adapter instances.
//
//
// Parameters:
//        Original        -    Original packet descriptor supplied by NDIS
//        Repackaged        -    Framework-provided descriptor for repackaging
// Returns:
//  The return value determines the behaviour of the framework after
//  OnSend() is returned:
//        NDIS_STATUS_SUCCESS         Requests the framework to forward the
//                                 Repackaged packet down the binding
//        NDIS_STATUS_NOT_ACCEPTED Send nothing. Release resources and Return NDIS_STATUS_SUCCESS to NDIS
//        NDIS_STATUS_PENDING         Do nothing, Recycle nothing. Return NDIS_STATUS_PENDING to NDIS
//        NDIS_STATUS_XXX             Do nothing. Retutn this status to NDIS.
//
// NOTE: The Repackaged initiallly describes a packet with no chained buffers.
//         It is OK to return NDIS_STATUS_SUCCESS and leave the Repackaged empty.
//         This would mean the packet has been successfully "consumed" by the filter.
//
// KNOWN PROBLEM: Currently, one can't chain user-allocated buffers to the
//                  repackaged descriptor. I.e. only "in-place" modifications are possible
//                  Use a private packet/buffer pools and ForwardDown() if needed.
//
NDIS_STATUS kpmAdapter::OnSend(const KNdisPacket& Original, KNdisPacket& Repackaged)
{
    T.Trace(__FUNCTION__" %u bytes\n", Original.QueryTotalLength());

    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;

    // TODO: Filter based on packet's content, e.g.
    //       HEADER* Content = (HEADER*) Original.QueryFirstBuffer();
    //         . . .
    // This implementation simply points the Repackaged to the buffers of the
    // Original and returns.

    Repackaged.CloneDown(Original);

    FltProcessPackage(Repackaged);

    return Status;
}

////////////////////////////////////////////////////////////////////
// kpmAdapter::OnReceive
//
// Intercetpts lower-layer receive. Here's where the filtering in
// the incoming direction takes place. The filter is given a chance
// to examine the original packet indicated by the real NIC (Original)
// and copy or modify or just drop it. The framework supplies a fresh
// packet descriptor (Repackaged) good for passing one packet up to the
// protocols. A filter that needs more packets (e.g. it implements
// some sort of repacketization) has to maintiain an internal packet
// pool and implement the OnReturnPacket() handler.
//
// Parameters:
//        Original        -    Original packet descriptor from the underlying NIC
//        Repackaged        -    Framework-provided descriptor for repackaging
// Returns:
//  The return value determines the behaviour of the framework after
//  OnReceive() is returned:
//        NDIS_STATUS_SUCCESS        Requests the framework to forward the
//                                Repackaged packet up to the protocols
//        NDIS_STATUS_NOT_ACCEPTED Forward nothing. Release resources and Return NDIS_STATUS_SUCCESS to NDIS
//        NDIS_STATUS_XXX             Do nothing. Retutn this status to NDIS.
//
// NOTE: The Repackaged initiallly describes a packet with no chained buffers.
//         It is OK to return NDIS_STATUS_SUCCESS and leave the Repackaged empty.
//         This would mean the packet has been successfully "consumed" by the filter.
//
// KNOWN PROBLEM: Currently, one can't chain user-allocated buffers to the
//                  repackaged descriptor. I.e. only "in-place" modifications are possible
//                  Use a private packet/buffer pools and ForwardUp() when needed.
//
NDIS_STATUS kpmAdapter::OnReceive(const KNdisPacket& Original, KNdisPacket& Repackaged)
{
    T.Trace(__FUNCTION__" %u bytes\n", Original.QueryTotalLength());

    // TODO: Filter based on packet's content, e.g.
    //       HEADER* Content = (HEADER*) Original.QueryFirstBuffer();
    //         . . .
    // This implementation simply points the Repackaged to the buffers of the
    // Original and forwards it over the binding.

    Repackaged.CloneUp(Original);

    FltProcessPackage(Repackaged);
    return NDIS_STATUS_SUCCESS;
}

///////////////////////////////////////////////////////////////////////
// kpmAdapter::OnReceive (partial)
//
// Parameters:
//    PacketToAccept         - Non-initialized packet descriptor
//     HeaderBuffer         - Header pointer
//     HeaderBufferSize     - Header size being indicated
//     LookAheadBuffer      - Lookahead buffer pointer
//     LookaheadBufferSize  - Lookahead size being indicated
//     PacketSize           - Total packet size (not including the header)
// Returns:
//  The return value determines the behaviour of the framework after
//  OnReceive() is returned:
//        NDIS_STATUS_SUCCESS        Requests the framework to forward the
//                                Repackaged packet up to the protocols
//        NDIS_STATUS_NOT_ACCEPTED Forward nothing. Release resources and Return NDIS_STATUS_SUCCESS to NDIS
//        NDIS_STATUS_XXX             Do nothing. Retutn this status to NDIS.
// Comments:
//     The framework calls this version of OnReceive() when the underlying real NIC miniport
//    uses partial receive packet indications (e.g., see discussion on KNdisLookahead).
//  Non-bus mastering NIC miniports may use this form of packet indication.
//    If the client is interested in looking into the remainder of the packet, it could
//  assign the supplied empty PacketToAccept to a real packet descriptor allocated from a
//    private packet pool. Then the framework would attempt to TransferData into supplied
//  packet and call the filter's OnTransferComplete() method.
NDIS_STATUS kpmAdapter::OnReceive(
    IN OUT KNdisPartialPacket& PacketToAccept,
    IN PVOID HeaderBuffer, IN UINT HeaderBufferSize,
    IN PVOID LookAheadBuffer, IN UINT LookaheadBufferSize,
    IN UINT PacketSize)
{
    T.Trace(__FUNCTION__" Partial %u/%u%/%u bytes\n",
            HeaderBufferSize, LookaheadBufferSize, PacketSize);

    UNREFERENCED_PARAMETER(PacketToAccept);

    if(0x8 == ((struct libnet_ethernet_hdr *)HeaderBuffer)->ether_type) //is ip packet
    {
        FltDirectProcessPacket(LookAheadBuffer, LookaheadBufferSize, FALSE);
    }

    return NDIS_STATUS_SUCCESS;
}
wwwst
驱动牛犊
驱动牛犊
  • 注册日期2008-08-23
  • 最后登录2010-05-20
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望11点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2009-03-29 00:35
同问,,

狂顶作者。。。。。cool者

顶你。
游客

返回顶部