Ndis过滤驱动:拷贝NetBufferList数据

今天我们来看看如何拷贝NBL中的数据。有时候需要更改数据包中的某些数据,就需要用到此功能(能直接在原来的nBL上更改,然后发送吗?)。

 

  1. 新建一个NBL作为你自己要存放拷贝数据的结构:
     pCopyNBL = allocateNetBuffAndNetBufferList(pFilter, dataLength);//Defined by self
     这个其实是一个自定义的函数,用来分配一个空的NBL.具体代码见后面~
  2. 这里考虑有很多个NBL,而且每个NB中包含多个MDL.所以拿到原始NBL的第一个NB
    pCurrentNB = NET_BUFFER_LIST_FIRST_NB(pCurrentNBL);//The first NB
     再得到第一个NB的第一个MDL:
    pMDL = NET_BUFFER_FIRST_MDL(pCurrentNB);
     最后得到MDL中有用数据:包括分析offset,以及dataLength,起始地址等:
    mdlOffset = NET_BUFFER_DATA_OFFSET(pCurrentNB);//I am not sure
    ...
     NdisQueryMdl( pMDL,(PVOID *)&pData,&dataBufferLength,NormalPagePriority);
                    if(pData == NULL)
                    {
                        DEBUGP(DL_TEST,("pData is NULL ---Fail \n"));
                        break;
                    }
     
  3. 同理我们得到我们自定义NBL中的MDL(只有一个),同时拿到起始地址:
    pCopyMDL  =  NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(pCopyNBL));
    ....
    NdisQueryMdl(pCopyMDL,(PVOID *)&pNewBuffer, &newBufferLength,NormalPagePriority);
                if(pNewBuffer == NULL)
                {
                    DEBUGP(DL_TEST,("pNewBuffer is NULL ---Fail \n"));
                    break;
                }
     
  4. 然后把pData的数据拷贝到pNewBuffer中,这里注意拷贝的长度:
    bytesToCopy = dataBufferLength - mdlOffset;
                    if(bytesToCopy > newBufferLength)
                    {
                        bytesToCopy = newBufferLength;
                    }
                    NdisMoveMemory((pNewBuffer + offset),(pData + mdlOffset), bytesToCopy);//copy data
                    newBufferLength -= bytesToCopy;
                    offset += bytesToCopy;
                    mdlOffset = 0;//CurrentMdlOffset is used only for the first Mdl processed. For the remaining Mdls, it is 0.
     这里mdlOffset=0,是指以后以后连续的MDL中没有unused 数据。就是整个MDL中的数据都是我们要的。
  5. 然后循环这个NB中所有的MDL.每个NB拷贝完之后,设置NB的datalength:
            NET_BUFFER_DATA_LENGTH(NET_BUFFER_LIST_FIRST_NB(pCopyNBL)) = dataLength;
            pCopyNBL->SourceHandle = pCurrentNBL->SourceHandle;
    
     
  6. 循环所有的NBL,把每个NBL串起来:
    if(pNewNetBufferLists == NULL)
            {
                pNewNetBufferLists = pCopyNBLTail = pCopyNBL;
            }
            else
            {
                NET_BUFFER_LIST_NEXT_NBL(pCopyNBLTail) = pCopyNBL;
            }
    
            pCurrentNBL = NET_BUFFER_LIST_NEXT_NBL(pCurrentNBL);
    
     
  7. 结束拷贝~附上NBL分配函数代码:
    PNET_BUFFER_LIST allocateNetBuffAndNetBufferList(
        IN  PMS_FILTER pFilter,
        IN  ULONG BufferSize
    )
    {
        PMDL  pMDL =  NULL;
        PUCHAR pMDLAddress =NULL;
        PNET_BUFFER_LIST pNetBufferList = NULL;
        DEBUGP(DL_TEST,("==============>allocateNetBuffAndNetBufferList\n"));
        pMDLAddress = (PUCHAR)NdisAllocateMemoryWithTagPriority(pFilter->FilterHandle,BufferSize,FILTER_ALLOC_TAG, LowPoolPriority);
        NdisZeroMemory(pMDLAddress, BufferSize);
        do
        {
            pMDL = NdisAllocateMdl(pFilter->FilterHandle, pMDLAddress, BufferSize);
            if(pMDL == NULL)
            {
                DEBUGP(DL_TEST,("PMDL Fail....\n"));
                break;
            }
    
            pNetBufferList = NdisAllocateNetBufferAndNetBufferList(
                                 pFilter->SendNetBufferListPool,
                                 sizeof(FILTER_SEND_NETBUFLIST_RSVD), //Request control offset delta
                                 0,           // back fill size
                                 pMDL,
                                 0,          // Data offset
                                 BufferSize);
            if(pNetBufferList == NULL)
            {
                NdisFreeMdl(pMDL);
                break;
            }
        }
        while(FALSE);
        DEBUGP(DL_TEST,("<==============allocateNetBuffAndNetBufferList\n"));
        return pNetBufferList;
    }
     需要注意分配MDL,一定要使用NdisAllocateMemoryWithTagPriority分配一个空间地址~
  8. 最后是检查是否拷贝正确,参考了这里的代码(打印部分自行添加~):

    基于NDIS Filter 抓包:

  9. 效果图:
    Ndis过滤驱动:拷贝NetBufferList数据_第1张图片
     浏览百度的:
    Ndis过滤驱动:拷贝NetBufferList数据_第2张图片
     浏览Javaeye的:
    Ndis过滤驱动:拷贝NetBufferList数据_第3张图片
     
  10. 还有一些疑问:除了程序编译的时候还有三个Warning.就是好像我只考虑了每个NBL中只有一个NB的情况~可能还需要更多的测试~【今天我把NB也循环了,就是考虑一个NBL多个NB的情况,可是测试中发现一般都自由一个NB】

参考: http://www.osronline.com/showthread.cfm?link=180159

 

你可能感兴趣的:(数据结构,.net,百度)