1. V4,V6头部差异
IP源路径选项:
对于IPV4,由于IP头部长度字段为4位,最大可以表示15,那么限制了IPV4的头部总长度为15*4 = 60字节。前10字节为固定的头部部分,所以最多有40个字节用来填充选项字段。
对于IPV6,固定长度的40字节的IPV6头部和传输层头部之间可以有扩展头部。
2. V4,6头部选项字段填充和获取使用setsockopt和getsockopt,传入参数level,optname,buf,buf长度。
用setsockopt来设置IP选项后,在该套接口上发送所有IP数据报都将包含这些选项。
清除选项用setsockopt,第四个参数设置成NULL,或者第五个参数设置成0.
4. 注意区分宽松和严格源路径选项。
5. 填充选项时,传送给setsockopt的缓冲区格式为:len = 3+IP地址长度(包括dstip)
|NOP + CODE + LEN +PTR +ip1 + ip2 。。。 +ip9+ dstip| 共44字节,最多有10个地址,不过ip1在IP数据报即将发送出去的时候,由内核移动到IP数据报的宿地址字段。
dstip为IP数据报的最终宿地址。
CODE指定源路径是宽松还是严格的。
LEN指定选项的字节长度,包括3字节的选项头部和dstip,这就已经有了7个字节了。
对于由一个IP地址构成的源路径,len = 7 +4 =11;
对于由二个IP地址构成的源路径,len = 7 +4 +4 =15;最多可以有9个IP,故最大可以为43.
ptr是一个指针(有点类似计数指针,并不是代表内存中的某个区域),表示下一个待处理IP的偏移量,初始值为4,表示指向第一个IP地址;
distip和NOP不属于源路径;
/*建立一个源路径选项,初始化还没有加入IP进去*/
u_char *creat_src_route(int type){
optr = (u_char *)malloc(44);
bzero(optr, 44);
*optr++ = IPOPT_NOP;
*optr++ = type ? 0x83 : 0x889;
lenptr = optr++;
*lenptr = 3;
*optr++ = 4;
return (optr-4);
}
/*添加地址到源路径,并更新选项中的len,并且optr指针指向下一个需要添加IP的位置*/
int add_src_route(const char *host){
struct addrinfo hints, *addrinfo;
struct sockaddr_in *addr;
bzero(&hints, sizeof(hints));
hints.ai_family = AF_INET;
if(getaddrinfo(host, NULL, &hints, &addrinfo) < 0 ){
err_sys("getaddrinfo");
memcpy(addr,(struct sockaddr_in *)addrinfo->ai_addr, sizeof(struct sockaddr_in));
*optr = addr->sin_addr;
optr ++= sizeof(struct in_addr);
*lenptr += sizeof(struct in_addr);
return (*lenptr+1);
}
6获取选项时,得到以下格式:
|ip1 + NOP+CODE+LEN+PTR+ip2+ip3+...+ip9+dstip|,会根据5中的源路径进行逆转。
getsockopt返回的buf指向第一个字节
源路径选项
最新推荐文章于 2023-12-31 17:03:28 发布