阅读:2486回复:11
passthru修改中校验和计算问题
求救:
我在学习NDIS中间层程序开发,当然最好的起点是从passthru开始了,但我在学习中遇到了一个始终解决不了的问题,对专家来说可能不是问题,但我却很久都没能解决,请大家帮忙。 我能成功的在ptSendPockets函数中修改以太网包头,但我想修改IP包头,于是就遇到了一个IP包头的校验和的计算问题,我查阅了RFC的相关资料,也得到了计算的源码,应该是没有问题的。但是当我用此方法计算的校验和修改包头时却怎么也不成功。 我用的是windows 2000的DDK中的passthru例子,我的方法是在MpSendPackets中修改IP包头,然后在PtReceive中还原它,也就是简单的加密工作。我已经能正确的找到IP包头的位置,而且可以正确读取各个字段,修改的校验和的位置也应该是正确的,方法也应该是正确的,因为在不修改包头的情况下计算的校验和值和原来包头的校验和是相等的,但是就是在我认为一切都没有问题的情况下却怎么也调不通。最奇怪的是我在不修改包头的任何字段的情况下重新计算IP包头校验和,而且得到的值和原来的一样,然后重新给校验和字段赋值,PtReceive中什么也不做,这样也不通,到底为什么?同样的值嘛,只是一个是原来的字段的拷贝,另一个是重新计算的,用原来的拷贝进行赋值就可以,用重新计算的就不可以!!! 真是太奇怪了,希望大家给予帮忙!我已经折腾了好几天了,谢谢大家! |
|
最新喜欢:xiaoji... |
沙发#
发布于:2004-08-10 18:21
请问各位大侠,那里可以得到应用passthru.sys和sFilter.dll的完整的应用层例程,就像winpcap用到packet.sys和packet.dll一样,在此谢过各位
|
|
板凳#
发布于:2004-08-10 22:17
我也是想用passthru来做
可是我对接收到的数据包的格式等还没有弄懂,不知道怎么能准确定位 请指教一二吧,减少我的痛苦吧 我的邮箱是:li_juan1979@163.com :( |
|
地板#
发布于:2004-08-11 10:21
建议你去看看《用TCP/IP进行网际互连》第二卷中计算校验和的源代码,我几个月前也遇到了与你一样的问题。我印象中是在计算校验和
之前要先给校验和字段置0,然后再计算。不好意思,记不太清楚了。 |
|
地下室#
发布于:2004-08-11 13:09
我的校验和计算方法是正确的,因为在不改变包头的情况下计算的值和原来一样。
我现在猜想是不是我没有重新对数据进行打包造成的,但DDK上说在不改变数据包长度的情况下是可以的。 现在的问题是IP协议栈把我的数据包给丢掉了,因为在对端已经接收到了我所发送的数据包。 |
|
5楼#
发布于:2004-08-11 17:08
收索一下以前的贴子,我贴过源码的。
|
|
6楼#
发布于:2004-08-12 11:06
终于等到asmsys大佬的出现了,谢谢你关注我的这个问题。
我想请教你一个问题,在不对数据包重新打包的情况下可不可以修改IP包头,然后计算一下IP校验和就可以了?修改以太网包头是可以的。DDK上说只要不改变数据包的长度是可以直接修改的,不知我的理解是否有误? 我现在把源码贴上来,您给看一下: MPSendPackets( IN NDIS_HANDLE MiniportAdapterContext, IN PPNDIS_PACKET PacketArray, IN UINT NumberOfPackets ) { struct ip IPHeader; ULONG NumberOfBytesRead; USHORT IPHeaderLen; USHORT IpCkSum,IpCkSum1; //略 FltReadOnPacket( Packet, &IPHeader, sizeof( IPHeader ), sizeof( struct ether_header ), &NumberOfBytesRead );//读取IP包头 DbgPrint("IP包头长度=%d",IPHeader.ip_hl); DbgPrint("版本=%d",IPHeader.ip_v); DbgPrint("IP包长度=%d",IPHeader.ip_len); DbgPrint("生存时间=%d",IPHeader.ip_ttl); DbgPrint("协议=%d",IPHeader.ip_p); DbgPrint("头部校验和=%d",IPHeader.ip_sum); DbgPrint("源IP地址=%d",IPHeader.ip_src); DbgPrint("目的IP地址=%d",IPHeader.ip_dst); IpCkSum=IPHeader.ip_sum;//先暂存一下校验和 IPHeaderLen=(IPHeader.ip_hl)*4; IPHeader.ip_sum = 0; // Clear old IP checksum value. IpCkSum1=GetIPChecksum((PUSHORT)(&IPHeader), IPHeaderLen); DbgPrint("头部校验和=%d",IPHeader.ip_sum);//这时=0 DbgPrint("头部校验和=%d",IpCkSum); IPHeader.ip_sum = IpCkSum1; //我用DbgPrint看到 IpCkSum1和IpCkSum是相等的,但如果用IpCkSum就可以,用 IpCkSum1就不行,奇怪不? DbgPrint("头部校验和1=%d",IpCkSum1); DbgPrint("重新计算后头部校验和=%d",IPHeader.ip_sum); FltWriteOnPacket( Packet, &IPHeader, sizeof( IPHeader ), sizeof( struct ether_header ), &NumberOfBytesRead );//写回原来的数据包中 DbgPrint("写入字节数=%d",NumberOfBytesRead); //略 } USHORT GetIPChecksum(PUSHORT pIPH, USHORT usIPHdr) { ULONG cksum = 0; while (usIPHdr > 1) { cksum += *pIPH++; usIPHdr -= sizeof(USHORT); } cksum = (((cksum >> 16) | (cksum << 16)) + cksum) >> 16; return (USHORT)~cksum; } 这里一个特别奇怪的问题是计算后的校验和和原来的校验和是相等的,但只要一用重新计算的校验和来代替原来的值就不行,为什么? 试验中发现数据包实际已经发送出去了,但是好像却在对端的IP 层被丢掉了。 |
|
7楼#
发布于:2004-08-12 14:02
我敢肯定用GetIPChecksum()计算出的IpCkSum1和原来的IpCkSum绝对不一样。因为你的GetIPChecksum()函数不对。不能只对现有的数据计算,要加一个伪头的(看一下TCP/IP卷1)。我以前贴的源代码是久经考验的产品级代码,绝对没有问题。
|
|
8楼#
发布于:2004-08-13 11:09
大佬能不能再帖一下,或者发送到邮箱shiyonglin@263.net,另外问一下,你说的加伪头是否是在对数据重新打包的情况(也就是重新分配缓冲区)下作的,是不是在不重新打包的情况下没办法实现IP包头的修改!!
能否把你的邮箱地址给我,我可以直接向您请教! |
|
9楼#
发布于:2004-08-13 12:29
http://www.driverdevelop.com/forum/viewthread.php?tid=65893
|
|
10楼#
发布于:2004-08-13 18:12
本人在<通讯世界网>上看到一片文章,<基于IMD的包过滤防火墙原理与实现>,按照他的方法在PtReceive和PtReceivePacket中加入对ICMP包的过滤,并且成功安装编译后的passthru.sys,在设备中已经加入Simple Filter Miniport,应该已经生效,但我从别的机器Ping我的机子,仍能Ping通,并且没有打印信息输出,请问各位大侠何故.
|
|
11楼#
发布于:2007-06-19 11:53
asmsys说的伪头部好像没有必要加吧,人家楼主只是修改了IP头部的数据,又没有涉及到UDP/TCP数据包,另外asmsys大牛贴出来的代号好像只是重新计算了UDP数据包的校验和,并没有考虑修改IP数据包后的校验和问题
|
|
|