阅读:1998回复:7
如何用ndis实现包的转发?
想做透明的防火墙,需要将一块网卡传来的数据发送到另外一块网卡上.我在PtReceive里调用下面这个过程,将包发送到其他网卡.可是在NdisSend调用的时候就死机,不知道是不是我的包建立错误,哪位大哥指教一下......
void IPF_BroadcastData ( IN NDIS_HANDLE MiniportAdapterHandle, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookAheadBuffer, IN UINT LookAheadBufferSize ) { NDIS_STATUS Status; PNDIS_PACKET MyPacket; PADAPT p = pAdaptList; while( p ) { if( p->MiniportHandle != MiniportAdapterHandle ) { NdisDprAllocatePacket( &Status, &MyPacket, p->SendPacketPoolHandle ); if( Status == NDIS_STATUS_SUCCESS ) { PSEND_RSVD Resvd; PNDIS_BUFFER pHeaderBuffer, pDataBuffer; NdisAllocateBuffer( &Status, &pHeaderBuffer, p->SendBufferPoolHandle, HeaderBuffer, HeaderBufferSize ); NdisChainBufferAtBack( MyPacket, pHeaderBuffer ); NdisAllocateBuffer( &Status, &pDataBuffer, p->SendBufferPoolHandle, LookAheadBuffer, LookAheadBufferSize ); NdisChainBufferAtBack( MyPacket, pDataBuffer ); MyPacket->Private.Head->Next = NULL; MyPacket->Private.Tail = NULL; Resvd = ( PSEND_RSVD )( MyPacket->MiniportReserved ); Resvd->OriginalPkt = NULL; NDIS_SET_PACKET_HEADER_SIZE( MyPacket, HeaderBufferSize ); NdisSetPacketFlags( MyPacket, ( UINT )p->Medium ); NdisSend( &Status, p->BindingHandle, MyPacket ); DbgPrint(\"Receive on %X, send to %X ... status = %d\\n\",MiniportAdapterHandle,p->MiniportHandle,Status); NdisFreeBuffer( pDataBuffer ); NdisFreeBuffer( pHeaderBuffer ); NdisDprFreePacket( MyPacket ); } } p = p->Next; } } [编辑 - 4/17/03 by dshadow79] |
|
沙发#
发布于:2003-04-17 17:49
谁指点一下啊,急死了……
|
|
板凳#
发布于:2003-04-18 15:24
没有人知道吗?
|
|
地板#
发布于:2003-04-18 16:28
呵呵,以前有个哥们和你做过类似的工作,你去找一下吧,好象是说由于NDIS_SEND返回pending的时候需要调用ptSendComplete来释放你分配的各种资源,然而默认的ptSenComplete里面释放资源的方法是和MpSend里面的分配方法配套的,所以需要把这两个函数都改掉。
另外,我有一个弱智问题:为什么转发包的时候要用两块网卡呢,一块不可以么? |
|
地下室#
发布于:2003-12-01 21:56
老兄的问题解决了,我也遇到同样的问题,可以将你的代码与我一份吗?
|
|
5楼#
发布于:2003-12-02 09:39
这种情况最好起个系统线程专门负责发送,而接收函数里只是把数据包挂在一个待处理的链上,这样不但可以从事务上分得很清楚,也会带来一些效率的提升,以及更好的出错处理机制.
发送线程从链上Pop数据包下来进行发送,考虑的更合理些,使用标准的生产者消费者模型是最好,简单点,一个双链表也没有什么问题. 如果允许丢包的话,可以在发送线程处理不过来而导致循环链表满的时候,将链表头的包丢弃,这样即便发送出现问题,也不会影响接收. |
|
|
6楼#
发布于:2003-12-02 09:43
另外,个人经验,使用系统线程的时候最好自己起,使用ExInitializeWorkItem和ExQueueWorkItem处理好像不是什么好主意,效率会严重降低/参数使用CriticalWorkQueue的情况下/.
|
|
|
7楼#
发布于:2003-12-03 00:17
这么老的帖子也能被翻出来……
那个东西是商业产品的一部分,代码不好公开,我只把自己遇到的问题说一下,实际代码还得自己写咯 先是发送包的时候,一定要设置包的标志,在xp下要设置NDIS_FLAGS_DONT_LOOPBACK标志,2k下的标志没有公开,得自己定义 #define NDIS_FLAGS_SKIP_LOOPBACK_W2K 0x00000400。这些标志使得ndis不将这些包loopback(关于什么是loopback,自己查一下吧) 如果不设置这些标志,发送的包又返回提交上来,再发送再提交,会堆栈溢出的 再就是在PtReceive/PtReceivePacket里面,我推荐建立全新的包然后把数据拷贝出来,再发送,这样不会占用底层的rfd,而且统一处理起来也比较方便。如果直接使用底层提交上来的包,实际使用的也就是底层miniport的rfd(receive frame descriptor),这个数量是很有限的,发送释放不及的话不见得效率高,而且逻辑上n麻烦,得考虑n多因素。PtReceive/PtReceivePacket的返回值也值得注意,不然还得return packet 然后就是在PtSendComplete里释放返回的包,这个没啥说的了 还有,如果想做成透明方式,单单实现上面是不够的。驱动两边的主机互相发送信息,mac地址跟驱动绑定的网卡完全无关,所以不会提交上来由驱动转发--这个常规解决方法是来个路由,还有个偷懒的办法,就是把驱动绑定的网卡全设成混杂 说的很罗索,呵呵,都是自己摸索的,希望对你有用 :cool: |
|