阅读:2203回复:13
版主,请进,帮我看看这个问题,先谢了这个例子是对接收到的数据包进行修改IP头,这个例子是在网上找到的,我想知道是怎么修改IP头的地址,和组建自己的包在转发到外网指定的IP。。。 。。希望各位朋友能帮我看看。 下面的代码是对包的接收,符合--->如果目的地址是本主机,并且源IP不是本网段地址,则转发给内网主机 符合--->如果目的地址不是广播地址,而且是外网地址,源地址是内网IP,则转发给外网 if(Status == NDIS_STATUS_SUCCESS) { //指定的地址分配 Status = NdisAllocateMemory(&pPacketContent, 2000, 0,HighestAcceptableMax); if(Status != NDIS_STATUS_SUCCESS) {return Status;} NdisZeroMemory (pPacketContent, 2000);//把申请的内存清零 //取得Packet->Private.Head中存储缓冲区的虚拟地址。 NdisQueryBufferSafe(Packet->Private.Head, &pBuf, &BufLength, 32 ); //NdisMoveMemory函数从协议提供的缓冲区中将数据转移到这一分段缓冲区中 NdisMoveMemory(pPacketContent, pBuf, BufLength); i = BufLength; pNext = Packet->Private.Head; for(;;) { if(pNext == Packet->Private.Tail) break; pNext = pNext->Next; if(pNext == NULL) break; // 取得Packet->Private.Head中存储缓冲区的虚拟地址。 NdisQueryBufferSafe(pNext,&pBuf,&BufLength,32); NdisMoveMemory(pPacketContent+i,pBuf,BufLength); i+=BufLength; } if(pPacketContent[12] == 8 && pPacketContent[13] == 0 ) //is ip packet { ULONG netip; pIPHeader = (PIP_HEADER)(pPacketContent+14); netip = pIPHeader->nSourIp & 0x00ffffff; //对收到的数据包进行过滤,只转发需要转发的包 if(pIPHeader->nDestIp == first->inip && netip != first->reip) //如果目的地址是本主机,并且源IP不是本网段地址,则转发给内网主机 { DbgPrint("\nTransInPacket...\n"); for(j=0;j<=i;j++) ----------------->这个for循环再这里是什么意思? DbgPrint("%x ",pPacketContent[j]); //修改发给内网的数据包头 transflag = TransIn(pPacketContent); ---->这里是调用TransIn函数修改包的数据ip,暂时还不知道是怎么修改的 } else if(pIPHeader->nDestIp != 0xffffffff && (pIPHeader->nDestIp & 0x00ffffff) != first->reip &&netip == first->reip)---这里参数很复杂,能解释一么 //如果目的地址不是广播地址,而且是外网地址,源地址是内网IP,则转发给外网 { DbgPrint("\nTransOutPacket...\n"); for(j=0;j<=i;j++) DbgPrint("%x ",pPacketContent[j]); //修改发给外网的数据包头 // transflag = TransOut(pPacketContent); //TransOut函数是一个自定义函数这里是调用TransIn函数修改包的数据ip,暂时还不知道是怎么修改 } } if(!transflag) { //按照原来的方式往上提交 NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1); } ///-下面是修改包IP的TransIn自定义函数 BOOLEAN TransIn(PUCHAR pPacketContent) { /* PortNode * inmap; PIP_HEADER pIPHeader; USHORT iphdrlen; PSDHDR psdhdr; UCHAR checkbuff[2000] = {0}; pIPHeader = (PIP_HEADER)(pPacketContent+14); iphdrlen = (pIPHeader->bVerAndHLen & 0x0f) * sizeof(ULONG); if(pIPHeader->bProtocol == 6) { PTCP_HEADER pTCPHeader; USHORT tcphdrlen; pTCPHeader = (PTCP_HEADER)(pPacketContent+14 + iphdrlen); //tcphdrlen = ((pTCPHeader->dataoffset & 0xf0) >> 4) * sizeof(ULONG); tcphdrlen = htons(pIPHeader->nTotalLength) - iphdrlen; inmap = InMapping(pIPHeader->ipSource,pTCPHeader->sourcePort, pTCPHeader->destinationPort); if(inmap == NULL) return FALSE; //修改目的地址和目的端口,校验和 pIPHeader->nDestIp = inmap->inip;---->如何修改成我需要的目的地ip? pTCPHeader->nDestPort = inmap->inport;如何修改成我需要的目的地端口? pIPHeader->nCheckSum = 0; pTCPHeader->nCheckSum = 0; 这2个nCheckSum 和nCheckSum =0是什么意思呢 //填充TCP伪首部 psdhdr.saddr = pIPHeader->nSourIp;--->填充TCP伪首部一定需要吗 psdhdr.daddr = pIPHeader->nDestIp; psdhdr.len = htons(tcphdrlen); psdhdr.mbz = 0; psdhdr.ptcl = 6; //计算TCP首部校验和 NdisMoveMemory(checkbuff,&psdhdr,sizeof(psdhdr)); NdisMoveMemory(checkbuff+sizeof(psdhdr),pTCPHeader,tcphdrlen); pTCPHeader->nCheckSum = CheckSum((USHORT *)checkbuff,sizeof(psdhdr)+tcphdrlen); //计算IP首部校验和 pIPHeader->nCheckSum = CheckSum((USHORT *)pIPHeader,iphdrlen); return TRUE; } else if(pIPHeader->bProtocol == 17) { PUDP_HEADER pUDPHeader; USHORT udplen; pUDPHeader = (PUDP_HEADER)(pPacketContent+14 + iphdrlen); //udplen = htons(pUDPHeader->len); udplen = htons(pUDPHeader->nLength); /* inmap = InMapping(pIPHeader->ipSource,pUDPHeader->sourcePort, pUDPHeader->destinationPort); if(inmap == NULL) return FALSE; //修改目的地址和目的端口,校验和 pIPHeader->nDestIp = inmap->inip; ---->为什么这里又要修改一次,目的地IP如何添加进去? pUDPHeader->nDestPort = inmap->inport; pIPHeader->nCheckSum = 0; pUDPHeader->nCheckSum = 0; //填充UDP伪首部 psdhdr.saddr = pIPHeader->nSourIp; psdhdr.daddr = pIPHeader->nDestIp; psdhdr.len = pUDPHeader->nLength; psdhdr.mbz = 0; psdhdr.ptcl = 17; //计算UDP校验和,包括所有UDP数据 NdisMoveMemory(checkbuff,&psdhdr,sizeof(psdhdr)); NdisMoveMemory(checkbuff+sizeof(psdhdr),pUDPHeader,udplen); pUDPHeader->nCheckSum = CheckSum((USHORT *)checkbuff,sizeof(psdhdr)+udplen); //计算IP首部校验和 pIPHeader->nCheckSum = CheckSum((USHORT *)pIPHeader,iphdrlen); return TRUE; } else return FALSE; */ DbgPrint("TransIn函数输出...\n"); } 对于这段代码,有很多的疑问,希望版主或者高人,能帮帮像我这样的菜鸟。。。或者有这样修改包ip和包内容再转发的代码发给我学习一下 真的非常感谢了。 |
|
沙发#
发布于:2012-12-12 22:20
自己来顶,大哥们,来看看吧
|
|
板凳#
发布于:2012-12-12 22:38
没发现你的疑问。。。
|
|
|
地板#
发布于:2012-12-13 10:29
回 znsoft 的帖子
znsoft:没发现你的疑问。。。 (2012-12-12 22:38) 我的疑问是,上面的代码如何修改包头的 IP,在组建自己的包,在转发到我指定的外网IP主机 能解释一下吗,我很想知道其中的原理,请版主。。。。 |
|
地下室#
发布于:2012-12-13 11:28
----------------->这个for循环再这里是什么意思?
这个报文的长度是i,i是这个packet里面的各个buffer的BufLength累加起来的。for循环把报文的每个字节打印出来。 ;---->如何修改成我需要的目的地ip? 从代码看,inmap是根据源ip算出来的目的ip,这是这个代码所在的项目的业务逻辑。你要把目的ip和端口,爱改成什么就改成什么。 ;--->填充TCP伪首部一定需要吗 这个计算校验码的算法要求的。你可以看看校验码的算法规定。 ---->为什么这里又要修改一次,目的地IP如何添加进去? 没有“又”,前面改的是TCP类报文的目的ip,这里改的是UDP报文的目的ip。还是那句话,目的ip根据你的业务需求,爱改成什么就改成什么。无非一段内存buffer,爱怎么改就怎么改,只要符合网络协议就可以了。 你对网络协议和C语法好像还不熟练。下载<TCP-IP详解卷1>,看其中相关的几个章节,就清楚多了 |
|
5楼#
发布于:2012-12-13 14:45
回 zhangfresh 的帖子
zhangfresh:----------------->这个for循环再这里是什么意思? 我对协议不是怎么熟练,但是上面说的那个for循环,估计是我标记错了,不好意思。 恩,我在看看网络协议。还是谢谢你 |
|
6楼#
发布于:2012-12-14 14:32
回 zhangfresh 的帖子
zhangfresh:----------------->这个for循环再这里是什么意思? 还有几个问题想请教一下: PIP_Header pIPHeader = (PIP_Header)(pPacketContent+14); USHORT iphdrlen = (pIPHeader->iphVerLen & 0x0f) * sizeof(ULONG); 在代码中,这两行代码的用途是做什么呢?我有点看不懂,难道pPacketContent这个包里没有包含以太头14个字节码。如果包含了,为什么还要加14呢 还有 pUDPHeader = (PUDP_HEADER)(pPacketContent+14 + iphdrlen); 为什么还要加一个iphdrlen长度? 这个inmap = InMapping(pIPHeader->ipSource,pUDPHeader->sourcePort, pUDPHeader->destinationPort); InMapping函数大概是用来做什么的?源代码里面没有定义这样的函数,具体的说上面那些代码是不完整的,还有一个定义不在源代码里面。 麻烦你帮我在看看了 |
|
7楼#
发布于:2012-12-14 15:57
整个tcp、udp的报文结构你不熟啊。
报文里面包含了以太头14字节。 tcp报文结构: 目的mac6字节+源mac6字节+报文类型2字节+20字节ip头+tcp头+tcp内容 udp报文结构类似: 目的mac6字节+源mac6字节+报文类型2字节+20字节ip头+udp头+udp内容 其实报文类型2字节和ip头之间,可能还有几个字节的vlan信息,很少见,可以先不研究(做实际产品要考虑,也很简单)。 ip头也不是固定长度20,具体长度等于这里的iphdrlen 。为什么是这样看书。网络上铺天盖地的这类信息,百度一把“tcp报文结构/协议”。做你这个驱动不懂tcp和udp报文结构是不行的。 so,报文开头偏移14字节就是ip头,ip头再偏移iphdrlen 字节就是udp头。 InMapping就是原来项目的修改ip、端口的业务逻辑,你不用管它。照你自己的业务需求写一个。 |
|
8楼#
发布于:2012-12-14 23:44
回 zhangfresh 的帖子
zhangfresh:整个tcp、udp的报文结构你不熟啊。 大哥,我是刚接触这方面,所以有很多不懂的,还望多多指教呢 刚刚听你这样一解释,我就全都明白了,很多时候学后面的,把之前的都忘记了,唉。 能加一下我的QQ吗,不懂的地方还可以像你请教了。 QQ:2528714442 |
|
9楼#
发布于:2012-12-20 13:23
回 zhangfresh 的帖子
zhangfresh:整个tcp、udp的报文结构你不熟啊。 InMapping 这个函数式怎么写呢?刚接触NDIS,希望在帮忙一下了 |
|
10楼#
发布于:2012-12-23 11:16
回 zhangfresh 的帖子
zhangfresh:整个tcp、udp的报文结构你不熟啊。 tcp报文结构: 目的mac6字节+源mac6字节+报文类型2字节+20字节ip头+tcp头+tcp内容 udp报文结构类似: 目的mac6字节+源mac6字节+报文类型2字节+20字节ip头+udp头+udp内容 如果说一个完整的包,以太头+偏移字节(IP头的字节)+偏移TCP头的字节,就到了数据区的起始地址了吗?我这样理解是不是对的呢 |
|
11楼#
发布于:2012-12-30 15:52
1 解析原始包,得到数据buf
2 解析ip段中的ip地址,进行修改 3 进行ip校验和 4 把重组的buf组包成packet, 5 发送这个重组的packet - ndissend 6 丢弃原始包(返回错误信息) 7 释放内存 |
|
|
12楼#
发布于:2012-12-30 15:52
再加上你们上面的讨论就够了。祝你好运
|
|
|
13楼#
发布于:2013-03-05 17:35
|
|