locked
How to extract packet at TCP inbound layer? RRS feed

  • Question

  • Hi,

    I am developing WFP driver first time. High level architecture is: Protocol TCP with IP filter is applied at TCP Inbound and Outbound layers.  Filter is working fine at Out bound layer fine but I am facing issue at In bound layer. 

    If my wfp driver  receives SYN+ACK TCP packet then NET_BUFFER_DATA_LENGTH always returns 0.

    Is it right behaviour?

    I figure out Retreat should be done on every incoming NetBuffer of NET_BFFER_LIST.

    NetBufferList is cloned and calling following piece of code for each NetBuffer of Cloned NetBufferList.

    Code snippet is:

    char pBuffer[1500] = "";

         status = NdisRetreatNetBufferDataStart(
                pClonedNetBuffer,
                (pPendedPkt->IpHeaderSize + pPendedPkt->TransportHeaderSize),
                0,
                NULL
                );

      pktLen = (pPendedPkt->IpHeaderSize + pPendedPkt->TransportHeaderSize);
        pDst = (PUCHAR)pBuffer;
        pSrc = NdisGetDataBuffer(pNetBuffer, pktLen pDst, 1, 0);
      if (pSrc == NULL)
            {
                NdisAdvanceNetBufferDataStart(pClonedNetBuffer,
                    (pPendedPkt->IpHeaderSize + pPendedPkt->TransportHeaderSize),
                    FALSE,
                    0
                    );
                return 0;
                }

            if (pSrc != pDst)
                {
                RtlCopyMemory((PUINT8)pBuffer, pSrc, pktLen);
                }

    I expect, pBuffer should have complete complete IP packet but I never get it.

    Could you please let me know where I am doing wrong?

    Regards,

    Anand Choubey


    • Edited by Anand Choubey Monday, March 24, 2014 8:13 AM I made question more clear about cloning.
    Monday, March 24, 2014 4:34 AM

All replies

  • Hi,

    I got the solution. Retreat should be done before cloning the net buffer list.

    Could you please explain why retreat should be done before cloning?

    Regards,

    Anand Choubey

    Thursday, March 27, 2014 5:18 AM
  • You should be able to do the retreat on the clone after cloning the original.  Our samples generally move the offset of the original, clone it, then advance the offset back on the original.

    Looking at the code, I don't see why you couldn't clone the original, and just retreat the offset on the clone.  You wouldn't advance the Net Buffer on the clone though, as when you inject, WFP expects the offset of the clone to be at the first header of the IP packet.

    In your code snippet, you are retreating the clone, and then advancing.  This would take you back to the offset of the original, which is not necessarily where WFP expects the injected NBLs offset to be.

    Hope this helps,


    Dusty Harper [MSFT]
    Microsoft Corporation
    ------------------------------------------------------------
    This posting is provided "AS IS", with NO warranties and confers NO rights
    ------------------------------------------------------------


    Thursday, March 27, 2014 8:29 PM
    Moderator
  • Hi Dusty!

    Great thanks for your reply! (I can safely say many WFP developers are writing code due to your help in this world.) 

    Retreat at cloning netbuffer is not working at my code.

    Let me take SYN+ACK Rx path: There is only one NET_BUFFER in NET_BUFFER_LIST.

    For SYN+ACK Rx Path: original NET_BUFFER DataLenght is zero (No data only headers) and offset is 0x3a (0xe+0x2c) i.e. eth header + IP and TCP header. 

    For cloned NET_BUFFER_LIST: clone NET_BUFFER DataLenght is zero and but offset becomes 0x5e. 

    I could not get how cloned NET_BUFFER becomes 0x5e?

    Cloning code is:

        status = FwpsAllocateCloneNetBufferList0(
                    pPendedPkt->pNetBufferList,
                    Globals.NetBufferListPool,
                    Globals.NetBufferPool,
                    0,
                    &pClonedNbl
                    );

     

    pNetBuffer = NET_BUFFER_LIST_FIRST_NB(pClonedNbl);

    Piggyback question:

    NdisRetreatNetBufferListDataStart retreats for all net buffers in list.  

    Does WFP/Ndis make sure aggregating same header length packets in one net buffer list since TCP/IP header size can vary packet to packet in same flow?

    Regards,

    Anand Choubey


    • Edited by Anand Choubey Friday, March 28, 2014 8:40 AM Improved question.
    Friday, March 28, 2014 6:17 AM
  • I finally had a chance to dig into this further.  Our suggestion of retreating is not a suggestion. It's actually reguired.  FwpsAllocateCloneNetBufferList wraps NdisAllocateCloneNetBufferList.  Diggingin into the Ndis API, I found that it actually only clones NBs from the data offset on.  I've requested that MSDN update it's documentation to reflect this.

    So to be clear, you MUST retreat the data offset of the original NET_BUFFER by the indicated size of the headers to get to the appropriate position within the packet. You then clone the NBL with FwpsAllocateCloneNetBufferList.  Once you have the clone, you need to advance thedata offset of the original NET_BUFFER by the same amount of bytes you initially retreated (returning the NBL to its original state ).

    Every NB indicated in the classify that have the transportHeaderSize available have that same transport header size.

    Hope this helps,


    Dusty Harper [MSFT]
    Microsoft Corporation
    ------------------------------------------------------------
    This posting is provided "AS IS", with NO warranties and confers NO rights
    ------------------------------------------------------------


    Tuesday, April 8, 2014 10:11 PM
    Moderator
  • At Outbound Transport is it ok to retreat by the IpHeader size and construct the ipheader with specific information and then reInject it back. ?  Since the IPHeader has not yet been constructed could I have it created in advance to effect the routing decision. 

    Or 

    Does WFP expect the offset to be at the start of TCP header when reinjecting at the outbound layer?

    Trying this mundane approach resulted in a bugcheck.

    Here is the code

    NdisRetreatNetBufferDataStart(
    NET_BUFFER_LIST_FIRST_NB(packet->netBufferList),
    sizeof(IP_HEADER),
    0,
    NULL
    );
    status = FwpsAllocateCloneNetBufferList(
    packet->netBufferList,
    NULL,
    NULL,
    0,
    &clonedNetBufferList
    );



    NdisAdvanceNetBufferDataStart(
    NET_BUFFER_LIST_FIRST_NB(packet->netBufferList),
    sizeof(IP_HEADER),
    0,
    NULL
    );

    //then using the cloned list to fetch me the loc of IP header.

          netBuffer = NET_BUFFER_LIST_FIRST_NB(clonedNetBufferList);
    ipheader = NdisGetDataBuffer(
    netBuffer,
    sizeof(IP_HEADER),
    NULL,
    1,
    0
    );

    //Setting the Source Ip on the packet so that it selects a particular interface of my choice

    ipheader->SrcIP = 3356141760;

    //Need to compute header checksum

    Comments plz???

    Friday, April 11, 2014 5:59 AM