LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1404|回复: 6

构造tcp和ip包的问题

[复制链接]
发表于 2005-11-3 17:36:43 | 显示全部楼层 |阅读模式

  1. void send_segment(struct iphdr *ih, struct tcphdr *th, char *data, int dlen) {
  2.         char buf[65536];
  3.         struct {  
  4.                 unsigned long saddr, daddr;
  5.                 char mbz;
  6.                 char ptcl;
  7.                 unsigned short tcpl;
  8.         } ph;
  9.        
  10.         struct sockaddr_in sin;       
  11.        
  12.         ph.saddr=ih->saddr;
  13.         ph.daddr=ih->daddr;
  14.         ph.mbz=0;
  15.         ph.ptcl=IPPROTO_TCP;
  16.         ph.tcpl=htons(sizeof(*th)+dlen);
  17.         [color=red]
  18.         memcpy(buf, &ph, sizeof(ph));
  19.         memcpy(buf+sizeof(ph), th, sizeof(*th));
  20.         memcpy(buf+sizeof(ph)+sizeof(*th), data, dlen);
  21.         memset(buf+sizeof(ph)+sizeof(*th)+dlen, 0, 4);
  22.         th->check=ip_sum(buf, (sizeof(ph)+sizeof(*th)+dlen+1)&~1);
  23.        
  24.         memcpy(buf, ih, 4*ih->ihl);
  25.         memcpy(buf+4*ih->ihl, th, sizeof(*th));
  26.         memcpy(buf+4*ih->ihl+sizeof(*th), data, dlen);
  27.         memset(buf+4*ih->ihl+sizeof(*th)+dlen, 0, 4);
  28.         [/color]
  29.         ih->check=ip_sum(buf, (4*ih->ihl + sizeof(*th)+ dlen + 1) & ~1);
  30.         memcpy(buf, ih, 4*ih->ihl);
  31.        
  32.         sin.sin_family=AF_INET;
  33.         sin.sin_port=th->dest;
  34.         sin.sin_addr.s_addr=ih->daddr;
  35.        
  36.         if(sendto(sock, buf, 4*ih->ihl + sizeof(*th)+ dlen, 0, &sin, sizeof(sin))<0) {
  37.                 printf("*sight* Error sending packet...\n");
  38.                 exit(1);
  39.         }
  40. }
复制代码
发表于 2005-11-3 18:24:09 | 显示全部楼层
问题呢?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-11-3 18:25:22 | 显示全部楼层
问题在这里
上面红色的部分
第一部分是构造tcp包吧,然后把所有的内容,tcp的头部和数据复制在buf里,然后校验和。
得到了tcp要求的校验和值
第二部分构造ip包,同tcp一样,得到了校验和。我没理解错吧~
问题是,我没明白为啥要把memcpy(buf, &ph, sizeof(ph)); ph这个结构的东西算在tcp里。
tcp包的构造按照协议来说应该是tcp头部(20字节)+数据
memcpy(buf, &ph, sizeof(ph));是不是没意思?难道是为了处理传说中的伪头部?

那么第二个处理ip包的呢?memcpy(buf, ih, 4*ih->ihl);完全不明白为什么要这样写了
为什么要把ip包的内容写到buf里,长度是4倍的ip包长?


还有
memset(buf+sizeof(ph)+sizeof(*th)+dlen, 0, 4);
为什么要在最后怎么来一下?
回复 支持 反对

使用道具 举报

发表于 2005-11-3 23:28:36 | 显示全部楼层
Post by dancingpig
问题在这里
上面红色的部分
第一部分是构造tcp包吧,然后把所有的内容,tcp的头部和数据复制在buf里,然后校验和。
得到了tcp要求的校验和值
第二部分构造ip包,同tcp一样,得到了校验和。我没理解错吧~

红字(也是一本小说的名字 :hungry )的第一部分只是为了得到tcp的checksum,那些拷贝只是临时了,tcp checksum得到之后buf里的那些东东就没用了,所以红字第二部分就把buf区覆盖重写了,把真正的数据报写进buf.

问题是,我没明白为啥要把memcpy(buf, &ph, sizeof(ph)); ph这个结构的东西算在tcp里。
tcp包的构造按照协议来说应该是tcp头部(20字节)+数据
memcpy(buf, &ph, sizeof(ph));是不是没意思?难道是为了处理传说中的伪头部?

memcpy(buf, &ph, sizeof(ph));  是把pseudo header(ph)拷本进buf内存区,为后面计算tcp checksum作准备。

那么第二个处理ip包的呢?memcpy(buf, ih, 4*ih->ihl);完全不明白为什么要这样写了
为什么要把ip包的内容写到buf里,长度是4倍的ip包长?

ih->ihl的值表示ip首部有多少个32位字,比如ihl = 5, 就表示首部的长度是4*5字节,所以要乘以4。


还有
memset(buf+sizeof(ph)+sizeof(*th)+dlen, 0, 4);
为什么要在最后怎么来一下?

这个地方我也不太理解,似乎是把数据结束后的内存区的32比特置0,不知是何目的,莫非是一种特殊的应用层协议?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-11-4 09:50:38 | 显示全部楼层
谢谢,研究ing
ih->ihl的值表示ip首部有多少个32位字,比如ihl = 5, 就表示首部的长度是4*5字节,所以要乘以4。
这里是不是你打错了?如果按照后面写的例子来看,你意思是ihl表示的是一个字节,4*5那就是20字节了。应该不是32位字吧~~~
回复 支持 反对

使用道具 举报

发表于 2005-11-4 10:47:11 | 显示全部楼层
Post by dancingpig
谢谢,研究ing
ih->ihl的值表示ip首部有多少个32位字,比如ihl = 5, 就表示首部的长度是4*5字节,所以要乘以4。
这里是不是你打错了?如果按照后面写的例子来看,你意思是ihl表示的是一个字节,4*5那就是20字节了。应该不是32位字吧~~~

hoho,刚好又路过 :cool:

没那么难理解吧,ihl = 5表示ip报头有5个32比特,就是20字节罗;一般都是这样,因为option段多数是空,所以ip首部多是20字节,ihl = 5是最常见的了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-11-4 12:59:31 | 显示全部楼层
哦酱紫啊~原来4,32bit/8转成4字节,然后5倍,酱紫啊,明白乐
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表