xczc10@sina.cn
驱动牛犊
驱动牛犊
  • 注册日期2012-12-06
  • 最后登录2012-12-23
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望171点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2116回复:13

版主,请进,帮我看看这个问题,先谢了

楼主#
更多 发布于:2012-12-12 16:17


 这个例子是对接收到的数据包进行修改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和包内容再转发的代码发给我学习一下
   真的非常感谢了。
      
xczc10@sina.cn
驱动牛犊
驱动牛犊
  • 注册日期2012-12-06
  • 最后登录2012-12-23
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望171点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2012-12-12 22:20
自己来顶,大哥们,来看看吧
znsoft
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2023-10-25
  • 粉丝300
  • 关注6
  • 积分910分
  • 威望14796点
  • 贡献值7点
  • 好评度2410点
  • 原创分5分
  • 专家分100分
  • 社区居民
  • 最爱沙发
  • 社区明星
板凳#
发布于:2012-12-12 22:38
没发现你的疑问。。。
http://www.zndev.com 免费源码交换网 ----------------------------- 软件创造价值,驱动提供力量! 淡泊以明志,宁静以致远。 ---------------------------------- 勤用搜索,多查资料,先搜再问。
xczc10@sina.cn
驱动牛犊
驱动牛犊
  • 注册日期2012-12-06
  • 最后登录2012-12-23
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望171点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2012-12-13 10:29
回 znsoft 的帖子
znsoft:没发现你的疑问。。。 (2012-12-12 22:38)

我的疑问是,上面的代码如何修改包头的 IP,在组建自己的包,在转发到我指定的外网IP主机
能解释一下吗,我很想知道其中的原理,请版主。。。。
zhangfresh
驱动牛犊
驱动牛犊
  • 注册日期2008-07-21
  • 最后登录2023-01-09
  • 粉丝1
  • 关注2
  • 积分94分
  • 威望871点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
  • 社区居民
地下室#
发布于: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>,看其中相关的几个章节,就清楚多了
xczc10@sina.cn
驱动牛犊
驱动牛犊
  • 注册日期2012-12-06
  • 最后登录2012-12-23
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望171点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2012-12-13 14:45
回 zhangfresh 的帖子
zhangfresh:----------------->这个for循环再这里是什么意思?
这个报文的长度是i,i是这个packet里面的各个buffer的BufLength累加起来的。for循环把报文的每个字节打印出来。

;---->如何修改成我需要的目的地ip?
从代码看,inmap是根据源ip算出来的目的ip,这是这个代码所在的项目的 .. (2012-12-13 11:28)

我对协议不是怎么熟练,但是上面说的那个for循环,估计是我标记错了,不好意思。
恩,我在看看网络协议。还是谢谢你
xczc10@sina.cn
驱动牛犊
驱动牛犊
  • 注册日期2012-12-06
  • 最后登录2012-12-23
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望171点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2012-12-14 14:32
回 zhangfresh 的帖子
zhangfresh:----------------->这个for循环再这里是什么意思?
这个报文的长度是i,i是这个packet里面的各个buffer的BufLength累加起来的。for循环把报文的每个字节打印出来。

;---->如何修改成我需要的目的地ip?
从代码看,inmap是根据源ip算出来的目的ip,这是这个代码所在的项目的 .. (2012-12-13 11:28)

还有几个问题想请教一下:
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函数大概是用来做什么的?源代码里面没有定义这样的函数,具体的说上面那些代码是不完整的,还有一个定义不在源代码里面。

麻烦你帮我在看看了
zhangfresh
驱动牛犊
驱动牛犊
  • 注册日期2008-07-21
  • 最后登录2023-01-09
  • 粉丝1
  • 关注2
  • 积分94分
  • 威望871点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
  • 社区居民
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、端口的业务逻辑,你不用管它。照你自己的业务需求写一个。
xczc10@sina.cn
驱动牛犊
驱动牛犊
  • 注册日期2012-12-06
  • 最后登录2012-12-23
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望171点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2012-12-14 23:44
回 zhangfresh 的帖子
zhangfresh:整个tcp、udp的报文结构你不熟啊。

报文里面包含了以太头14字节。
tcp报文结构:
目的mac6字节+源mac6字节+报文类型2字节+20字节ip头+tcp头+tcp内容
....... (2012-12-14 15:57)

大哥,我是刚接触这方面,所以有很多不懂的,还望多多指教呢
刚刚听你这样一解释,我就全都明白了,很多时候学后面的,把之前的都忘记了,唉。

能加一下我的QQ吗,不懂的地方还可以像你请教了。
QQ:2528714442
xczc10@sina.cn
驱动牛犊
驱动牛犊
  • 注册日期2012-12-06
  • 最后登录2012-12-23
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望171点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2012-12-20 13:23
回 zhangfresh 的帖子
zhangfresh:整个tcp、udp的报文结构你不熟啊。

报文里面包含了以太头14字节。
tcp报文结构:
目的mac6字节+源mac6字节+报文类型2字节+20字节ip头+tcp头+tcp内容
....... (2012-12-14 15:57)

InMapping 这个函数式怎么写呢?刚接触NDIS,希望在帮忙一下了
xczc10@sina.cn
驱动牛犊
驱动牛犊
  • 注册日期2012-12-06
  • 最后登录2012-12-23
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望171点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2012-12-23 11:16
回 zhangfresh 的帖子
zhangfresh:整个tcp、udp的报文结构你不熟啊。

报文里面包含了以太头14字节。
tcp报文结构:
目的mac6字节+源mac6字节+报文类型2字节+20字节ip头+tcp头+tcp内容
....... (2012-12-14 15:57)

tcp报文结构:
目的mac6字节+源mac6字节+报文类型2字节+20字节ip头+tcp头+tcp内容

udp报文结构类似:
目的mac6字节+源mac6字节+报文类型2字节+20字节ip头+udp头+udp内容

如果说一个完整的包,以太头+偏移字节(IP头的字节)+偏移TCP头的字节,就到了数据区的起始地址了吗?我这样理解是不是对的呢
iihacker
论坛版主
论坛版主
  • 注册日期2010-01-07
  • 最后登录2017-08-16
  • 粉丝5
  • 关注8
  • 积分377分
  • 威望1941点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
  • 社区居民
11楼#
发布于:2012-12-30 15:52
1 解析原始包,得到数据buf
2  解析ip段中的ip地址,进行修改
3  进行ip校验和
4  把重组的buf组包成packet,
5  发送这个重组的packet  - ndissend
6  丢弃原始包(返回错误信息)
7 释放内存
NDIS 1群74755180 NDIS 2群182802097 交换机软硬件技术群 187471475 FPGA PCI PCIE 群187471817
iihacker
论坛版主
论坛版主
  • 注册日期2010-01-07
  • 最后登录2017-08-16
  • 粉丝5
  • 关注8
  • 积分377分
  • 威望1941点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
  • 社区居民
12楼#
发布于:2012-12-30 15:52
再加上你们上面的讨论就够了。祝你好运
NDIS 1群74755180 NDIS 2群182802097 交换机软硬件技术群 187471475 FPGA PCI PCIE 群187471817
CooSet
驱动牛犊
驱动牛犊
  • 注册日期2012-12-23
  • 最后登录2013-06-06
  • 粉丝0
  • 关注0
  • 积分2分
  • 威望101点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2013-03-05 17:35
回 iihacker 的帖子
iihacker:再加上你们上面的讨论就够了。祝你好运 (2012-12-30 15:52)

版主,有这方面的代码吗?能贴出来吗。谢谢了
游客

返回顶部