当前位置:   article > 正文

附加IP报文option字段_ip option

ip option

对于IPv4报文,头部长这样:

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |Version|  IHL  |Type of Service|          Total Length         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         Identification        |Flags|      Fragment Offset    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Time to Live |    Protocol   |         Header Checksum       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                       Source Address                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Destination Address                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Options                    |    Padding    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

一般都不会附加特殊的选项信息,对于Header Length 就是5,ip头部的总长度也就是20个字节。

最近有需求需要附加一点额外的信息,先从ip的option入手看看能不能实现。

首先直接写代码测试这个头部分信息

有两种方式

当使用 setsockopt 设置 IP 选项时,将在该套接字上的所有 IP 数据报上发送指定的选项。这适用于 TCP、UDP 和原始 IP 套接字。要清除这些选项,请调用 setsockopt 并指定空指针作为第四个参数或值 0 作为第五个参数(长度)。

原始 IP 套接字设置 IP_HDRINCL 套接字选项,但是这个IP 选项好像某些情况下不适用。

刚开始不清楚这一点,折腾了好久,把原始套接字的代码贴上来

代码是网上修改别人的原始套接字发送ICMP的例子,这里面也有一些坑代码,找了好久没有找到。

  1. #include <stdio.h>
  2. #include <winsock2.h>
  3. #include <ws2tcpip.h>
  4. #include <time.h>
  5. #include <iostream>
  6. #include <windows.h>
  7. #pragma comment(lib,"ws2_32.lib")
  8. using namespace std;
  9. const int IP_Header_min_lenght = 20;
  10. /*
  11. Ver 4
  12. Hlen 4
  13. 1
  14. Servicetype 8
  15. 1
  16. Total length 16
  17. 2
  18. Identifier 16
  19. 2
  20. flag and frag offset 16
  21. 2
  22. TimeToLive 8
  23. 1
  24. Prorocol 8
  25. CHECKSUM 16
  26. SRC ADDR 32
  27. DES ADDR 32
  28. 160/8=20
  29. */
  30. #pragma pack(push,1)
  31. typedef struct ip_hdr //定义IP首部
  32. {
  33. unsigned char h_verlen; //4位首部长度,4位IP版本号
  34. unsigned char tos; //8位服务类型TOS
  35. unsigned short total_len; //16位总长度(字节)
  36. unsigned short ident; //16位标识
  37. unsigned short frag_and_flags; //3位标志位
  38. unsigned char ttl; //8位生存时间 TTL
  39. unsigned char proto; //8位协议 (TCP, UDP 或其他)
  40. unsigned short checksum; //16位IP首部校验和
  41. unsigned int sourceIP; //32位源IP地址
  42. unsigned int destIP; //32位目的IP地址
  43. }IPHEADER;
  44. typedef struct tsd_hdr //定义TCP伪首部
  45. {
  46. unsigned long saddr; //源地址
  47. unsigned long daddr; //目的地址
  48. char mbz;
  49. char ptcl; //协议类型
  50. unsigned short tcpl; //TCP长度
  51. }PSDHEADER;
  52. typedef struct tcp_hdr //定义TCP首部
  53. {
  54. USHORT th_sport; //16位源端口
  55. USHORT th_dport; //16位目的端口
  56. unsigned int th_seq; //32位序列号
  57. unsigned int th_ack; //32位确认号
  58. unsigned char th_lenres; //4位首部长度/6位保留字
  59. unsigned char th_flag; //6位标志位
  60. USHORT th_win; //16位窗口大小
  61. USHORT th_sum; //16位校验和
  62. USHORT th_urp; //16位紧急数据偏移量
  63. }TCPHEADER;
  64. typedef struct icmp_hdr
  65. {
  66. unsigned char icmp_type; // 类型
  67. unsigned char icmp_code; // 代码
  68. unsigned short icmp_checksum; // 校验和
  69. unsigned short icmp_id; // ID号,设为PID
  70. unsigned short icmp_sequence; // 序列号
  71. unsigned long icmp_timestamp; // 时间戳
  72. } ICMP_HDR, *PICMP_HDR;
  73. #pragma pack(pop)
  74. unsigned short CheckSum(USHORT* buff, int size)
  75. {
  76. unsigned long cksum = 0;
  77. while (size > 1)
  78. {
  79. cksum += *buff++;
  80. size -= sizeof(USHORT);
  81. }
  82. // 是奇数
  83. if (size)
  84. {
  85. cksum += *(UCHAR*)buff;
  86. }
  87. //32位的chsum高16位和低16位相加,然后取反
  88. cksum = (cksum >> 16) + (cksum & 0xffff);
  89. cksum += (cksum >> 16);
  90. return (USHORT)(~cksum);
  91. }
  92. bool SetTimeout(SOCKET sRaw, int nTime)
  93. {
  94. int ret = setsockopt(sRaw, SOL_SOCKET, SO_RCVTIMEO, (char*)&nTime, sizeof(nTime));
  95. return ret != SOCKET_ERROR;
  96. }
  97. double GetTickCountA()
  98. {
  99. __int64 Freq = 0;
  100. __int64 Count = 0;
  101. if (QueryPerformanceFrequency((LARGE_INTEGER*)&Freq) && Freq > 0 && QueryPerformanceCounter((LARGE_INTEGER*)&Count))
  102. {
  103. //乘以1000,把秒化为毫秒
  104. return (double)Count / (double)Freq * 1000.0;
  105. }
  106. return 0.0;
  107. }
  108. int main()
  109. {
  110. char website_name[] = "10.19.11.221";// www.baidu.com www.google.com
  111. char *DestIp;
  112. double succ = 0;
  113. double fail = 0;
  114. int min_RTT = 999999999;
  115. int max_RTT = -1;
  116. int sum_RTT = 0;
  117. DestIp = (char*)malloc(20 * sizeof(char));
  118. //初始化WindowsSocketsAPI
  119. WSADATA wsaData;
  120. WORD sockVersion = MAKEWORD(2, 2);//声明版本 2.2
  121. WSAStartup(sockVersion, &wsaData);//启动
  122. //获取IP地址
  123. struct hostent *curr_hostent = gethostbyname(website_name);
  124. DestIp = inet_ntoa(*(struct in_addr*)curr_hostent->h_addr_list[0]);
  125. DestIp = (char *)"10.19.11.221";
  126. printf("正在ping %s:[%s] \n", website_name, DestIp);
  127. //printf("%s\n",curr_hostent->h_addr_list[0]);
  128. //printf("%s\n",inet_ntoa(*(struct in_addr*)curr_hostent->h_addr_list[0]));
  129. if (!curr_hostent) {
  130. puts("Get IP address error!");
  131. //system("pause");
  132. // exit(0);
  133. }
  134. //创立套接字
  135. SOCKET sRaw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);//AF_INET=ipv4 SOCK_RAW ICMP协议
  136. BOOL flag = true;
  137. if (setsockopt(sRaw, IPPROTO_IP, IP_HDRINCL, (char *)&flag, sizeof(flag)) == SOCKET_ERROR)
  138. {
  139. printf("setsockopt IP_HDRINCL error! ");
  140. return false;
  141. }
  142. SetTimeout(sRaw, 1000);
  143. // 设置目的地址
  144. SOCKADDR_IN dest;
  145. dest.sin_family = AF_INET;//ipv4地址家族
  146. // dest.sin_port = htons(0);//将整型变量从主机字节顺序转变成网络字节顺序
  147. dest.sin_addr.S_un.S_addr = inet_addr(DestIp);
  148. // 创建ICMP数据包并填写
  149. //ip 选项部分4字节
  150. const int i_len_total = sizeof(IPHEADER) + 12 + sizeof(ICMP_HDR) + 32;//...
  151. char buff[i_len_total];
  152. IPHEADER* ipHeader = (IPHEADER*)buff;
  153. //ipHeader->h_verlen = (4 << 4 | sizeof(ipHeader) / sizeof(unsigned long));
  154. ipHeader->h_verlen = 0x40 + (sizeof(IPHEADER) / 4 + 3); //...
  155. ipHeader->tos=0;
  156. ipHeader->total_len = /*htons*/(i_len_total);
  157. ipHeader->ident = 1;
  158. ipHeader->frag_and_flags = 0;
  159. ipHeader->ttl = 120;
  160. ipHeader->proto = IPPROTO_ICMP;
  161. ipHeader->checksum = 0;
  162. ipHeader->sourceIP = inet_addr("10.18.11.223"); //src ip
  163. ipHeader->destIP = inet_addr( "10.19.11.221" ); //dest ip
  164. char optionPacket_2[] = {
  165. '\x01', '\x01', '\x01', '\x01',
  166. '\x83', '\x07', '\x08', '\xC0',
  167. '\xA8', '\x7E', '\x80', '\x00'
  168. };
  169. int optionLength = 12;
  170. memcpy(buff + sizeof(IPHEADER), optionPacket_2, optionLength);
  171. //ipHeader->checksum = CheckSum((unsigned short*)ipHeader, sizeof(IPHEADER) /*+ 4*/);
  172. ICMP_HDR* pIcmp = (ICMP_HDR*)(buff + sizeof(IPHEADER)+ 12);//...
  173. pIcmp->icmp_type = 8; // 请求一个ICMP回显
  174. pIcmp->icmp_code = 0;
  175. pIcmp->icmp_id = (unsigned short)GetCurrentProcessId();
  176. unsigned short nSeq = 0;
  177. char recvBuf[1024];
  178. SOCKADDR_IN from;
  179. int nLen = sizeof(from);
  180. for (int o = 0; o < 9999999; o++)
  181. {
  182. int nRet;
  183. pIcmp->icmp_checksum = 0;//为了后续checksum函数正常 需要先置位0
  184. pIcmp->icmp_timestamp = GetTickCountA();
  185. pIcmp->icmp_sequence = nSeq++;
  186. pIcmp->icmp_checksum = CheckSum((unsigned short*)pIcmp, sizeof(ICMP_HDR) + 32);
  187. //发送包
  188. nRet = sendto(sRaw, buff, i_len_total, 0, (SOCKADDR *)&dest, sizeof(dest));//发送
  189. if (nRet == SOCKET_ERROR)
  190. {
  191. printf(" sendto() failed: %d \n", ::WSAGetLastError());
  192. return -1;
  193. }
  194. //接收包
  195. nRet = recvfrom(sRaw, recvBuf, 1024, 0, (sockaddr*)&from, &nLen);
  196. if (nRet == SOCKET_ERROR)
  197. {
  198. if (WSAGetLastError() == WSAETIMEDOUT)
  199. {
  200. printf(" Request timed out\n");
  201. fail++;
  202. continue;
  203. }
  204. fail++;
  205. printf(" Failed. Error code: %d\n", WSAGetLastError());
  206. return -1;
  207. }
  208. // 解析包
  209. int nTick = GetTickCountA();
  210. if (nRet < IP_Header_min_lenght + sizeof(ICMP_HDR))
  211. {
  212. printf(" Returned too few bytes from %s \n", inet_ntoa(from.sin_addr));
  213. fail++;
  214. }
  215. // 接收包中包含IP头,所以加20得到ICMP头
  216. ICMP_HDR* pRecvIcmp = (ICMP_HDR*)(recvBuf + IP_Header_min_lenght); // (ICMP_HDR*)(recvBuf + sizeof(IPHeader));
  217. if (pRecvIcmp->icmp_type != 0) // 回显
  218. {
  219. if (pRecvIcmp->icmp_type == 3) // 回显
  220. {
  221. printf(" Unreachable\n"); fail++;
  222. }
  223. else if (pRecvIcmp->icmp_type == 4) // 回显
  224. {
  225. printf(" Origin suppression \n"); fail++;
  226. }
  227. else if (pRecvIcmp->icmp_type == 5) // 回显
  228. {
  229. printf(" Redirect \n"); fail++;
  230. }
  231. else if (pRecvIcmp->icmp_type == 8) // 回显
  232. {
  233. printf(" Echo request\n"); fail++;
  234. }
  235. else if (pRecvIcmp->icmp_type == 9) // 回显
  236. {
  237. printf(" Router announcement\n"); fail++;
  238. }
  239. else if (pRecvIcmp->icmp_type == 10) // 回显
  240. {
  241. printf(" Router request \n"); fail++;
  242. }
  243. else if (pRecvIcmp->icmp_type == 11) // 回显
  244. {
  245. printf(" Time out \n"); fail++;
  246. }
  247. else if (pRecvIcmp->icmp_type == 17) // 回显
  248. {
  249. printf(" Address subnet request\n"); fail++;
  250. }
  251. else if (pRecvIcmp->icmp_type == 18) // 回显
  252. {
  253. printf(" Address subnet response\n"); fail++;
  254. }
  255. return -1;
  256. }
  257. succ++;
  258. printf(" 来自 %s的回复: ", inet_ntoa(from.sin_addr));
  259. printf(" 字节=%d bytes :", nRet, inet_ntoa(from.sin_addr));
  260. printf(" 时间= %d ms", nTick - pRecvIcmp->icmp_timestamp);
  261. printf(" TTL= %d \n", *(recvBuf + 8));
  262. min_RTT = min(min_RTT, (int)(nTick - pRecvIcmp->icmp_timestamp));
  263. max_RTT = max(max_RTT, (int)(nTick - pRecvIcmp->icmp_timestamp));
  264. sum_RTT = sum_RTT + nTick - pRecvIcmp->icmp_timestamp;
  265. Sleep(1000);//一秒
  266. }
  267. printf("数据包丢失率:%lf", fail * 100 / (succ + fail));
  268. cout << "%" << endl;
  269. printf("最小 RTT = %d ms \n", min_RTT);
  270. printf("最大 RTT = %d ms\n", max_RTT);
  271. printf("平均 RTT = %d ms\n", sum_RTT / 10);
  272. return 0;
  273. }

测试可以正常发送ip选项头

 

 但是这个头部能携带的信息有格式要求,并且信息有线,大部分软件都没有采用这个ip报文的option头部了,改为使用tcp、udp传输层协议的option字段了。所以这个ip option也就没有太大意义了。

以下是ip option的相关说明,翻译自RFC 791: Internet Protocol 第14页的内容

  Options:  variable

选项可能出现或不出现在数据报中。它们必须
    由所有 IP 模块(主机和网关)实现。可选
    的是它们在任何特定数据报中的传输,而不是它们的
    实现。

    在某些环境中,所有数据报都可能需要安全选项
    。

    选项字段的长度是可变的。可能有零个或多个
    选项。选项的格式有两种情况:

      情况 1:选项类型的单个八位字节。

      情况 2:一个选项类型八位字节、一个选项长度八位字节和
               实际的选项数据八位字节。

    option-length octet 计算 option-type octet 和
    option-length octet 以及 option-data octet。

    选项类型八位字节被视为具有 3 个字段:

      1 位复制标志、
      2 位选项类别、
      5 位选项编号。

    复制标志表示该选项被复制到分片时
    的所有分片中。

      0 = 未复制
      1 = 已复制

    选项类别为:

      0 = 控制
      1 = 保留供将来使用
      2 = 调试和测量
      3 = 保留供将来使用                                                        


    定义了以下 Internet 选项:

      类别号长度说明
      ----- ------ ------ ----------- 
        0 0 - 选项结束列表。   End of Option List
此选项仅占用1 个八位字节;它没有长度字节。
        0 1 - 无操作。Nop
此选项仅占用 1 个八位字节;它没有长度字节。
        0 2 11 安全。Security (S field)
用于携带与 DOD 兼容的安全、分隔、用户组 (TCC) 和处理限制代码要求。
        0 3 变量。松散源路由。 Loose Source and Record Route
用于根据源提供的信息路由 Internet 数据报
                          。
        0 9 变量。严格的源路由。  Strict Source and Record Route
用于根据源提供的信息路由 Internet 数据报
                          。
        0 7 变量。记录路由。Record Route
用于跟踪Internet 数据报采用的路由。
        0 8 4 流 ID。 Stream Identifier 
用于携带流标识符。
        2 4 变量。互联网时间戳。 Internet Timestamp


    具体选项定义

      选项列表结束

        +--------+ 
        |00000000| 
        +--------+ 
          Type=0

        该选项表示选项列表的结束。
        根据Internet 标头长度,这可能
        与 Internet 标头的结尾不一致。这用于所有选项的结尾,而不是每个选项的结尾,并且仅
        在选项的结尾
        与 Internet 标头的结尾不一致
        时才需要使用。
        可能会因碎片或任何其他原因
        而被复制、引入或删除。


      无操作

        +--------+ 
        |00000001| 
        +--------+ 
          Type=1

        此选项可用于选项之间,例如,将
        后续选项的开头对齐在 32 位边界上。
        可能会因碎片或任何其他原因

        而被复制、引入或删除。
      安全
        此选项为主机提供一种发送安全、
        隔离、处理限制和 TCC(封闭用户


        组)参数。该选项的格式如下:

          +--------+--------+---//---+---//---+---/ /---+---//---+ 
          |10000010|00001011|SSS SSS|CCC CCC|HHH HHH| 台积电 | 
          +--------+--------+---//---+---//---+---//---+---/ /---+
           类型=130 长度=11

        安全性(S 字段):16 位

          指定 16 个安全级别之一(其中 8 个
          保留供将来使用)。

            00000000 00000000 - 未分类
            11110001 00110101 - 机密
            01111000 10011010 - EFTO 
            10111100 01001101 - MMMM 
            01011110 00100110 - PROG
            10101111 00010011  - 受限制
            11010111 10001000  - 秘密
            01101011 110001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010- 
            (保留供将来使用)
            10011010 11110001  - (保留供将来使用)
            01001101 01111101  - (保留供将来使用)
            00100100 10111101  - (保留用于将来使用)
            0010011 01011110 - (留作将来使用)
            10001001 10101111 - (留作将来使用) 
            11000100 11010110 - (留作将来使用) 11100010 01101011 - (
            留作将来使用)                                                            

        隔间(C 字段):16 位当传输的信息
          没有隔开

          时,使用全零值。隔间字段的其他值
          可以从国防情报局获得。

        处理限制(H 字段):16 位

          控制和释放标记的值是
          字母数字二合字母,并在国防
          情报局手册 DIAM 65-19,“标准安全
          标记”中定义。

        传输控制码(TCC 字段):24 位

          提供一种方法来隔离流量并定义
          订户之间的受控利益社区。TCC 值是
          三元组,可从 HQ DCA 代码 530

        获得。必须在分段时复制。该选项
        在一个数据报中最多出现一次。

      松源和记录路由

        +--------+--------+--------+---------//----- --+ 
        |10000011| 长度 | 指针| 路由数据 | 
        +--------+--------+--------+---------//--------+
         类型= 131

        松散源和记录路由 (LSRR) 选项为
        Internet 数据报的源提供路由
        网关在将
        数据报转发到目的地时使用的信息,并记录路由
        信息。

        该选项以选项类型代码开头。第二个八位位组
        是选项长度,包括选项类型代码和
        长度八位位组、指针八位位组和长度为 3 位的路由
        数据。第三个八位字节是指向路由数据的指针,
        指示开始下一个要
        处理的源地址的八位字节。指针是相对于这个选项的,
        指针的最小合法值是4。

        一个路由数据是由一系列互联网地址组成的。
        每个互联网地址是 32 位或 4 个八位字节。如果指针
        大于长度,则源路由为空(并且
        记录的路由已满),路由将基于
        目标地址字段。

        如果已到达目的地址域中的地址且
        指针不大于长度,
        则源路由中的下一个地址替换目的地址
        域中的地址,并且记录的路由地址替换源
        地址刚用过,指针加四。
        记录的路由地址是该数据报转发
        到的环境中已知

        的互联网模块自己的互联网地址。

        这个用记录的路由替换源路由的过程
        (尽管它与
        用作源路由的顺序相反)意味着选项(以及整个 IP 标头
        )保持恒定长度,如数据报
        通过互联网传输。

        此选项是松散源路由,因为
        允许网关或主机 IP 使用任意数量的其他
        中间网关的任意路由到达路由中的下一个地址。

        必须在碎片上复制。在一个数据报中最多出现一次
        。

      严格的源和记录路由

        +--------+--------+--------+---------//------ --+
        |10001001| 长度 | 指针| 路由数据 | 
        +--------+--------+--------+---------//--------+
         类型= 137

        严格的源和记录路由 (SSRR) 选项为
        互联网数据报的源提供了一种方法,以提供
        网关在将
        数据报转发到目的地时使用的路由信息​​,并记录路由
        信息。

        该选项以选项类型代码开头。第二个八位位组
        是选项长度,包括选项类型代码和
        长度八位位组、指针八位位组和长度为 3 位的路由
        数据。第三个八位字节是指向路由数据的指针
        指示开始下一个要
        处理的源地址的八位字节。指针是相对于这个选项的,
        指针的最小合法值是4。

        一个路由数据是由一系列互联网地址组成的。
        每个互联网地址是 32 位或 4 个八位字节。如果指针
        大于长度,则源路由为空(并且                                                       

        记录了完整的路由)并且路由将基于
        目标地址字段。

        如果已经到达目的地址域中的地址并且
        指针不大于长度,
        则源路由中的下一个地址替换目的地址
        域中的地址,记录的路由地址替换
        刚刚使用的源地址,指针增加了四。
        记录的路由地址是该数据报所在的环境中已知

        的 Internet 模块自己的 Internet地址
        被转发。

        这个用记录的路由替换源路由的过程
        (尽管它与
        用作源路由的顺序相反)意味着选项(以及整个 IP 标头
        )保持恒定长度,如数据报
        通过互联网传输。

        此选项是严格源路由,因为网关或主机IP 必须
        仅通过下一个地址中指示的直连网络
        将数据报直接发送到源路由
        中的下一个地址,才能到达
        路由中指定的下一个网关或主机。

        必须在碎片上复制。在一个数据报中最多出现一次
        。

      记录路由

        +--------+--------+--------+---------//--------+ 
        |00000111| 长度 | 指针| 路由数据 | 
        +--------+--------+--------+---------//--------+
          类型= 7

        记录路由选项提供了一种记录
        互联网数据报路由的方法。

        该选项以选项类型代码开头。第二个八位位组
        是选项长度,包括选项类型代码和
        长度八位位组、指针八位位组和长度为 3 位的路由
        数据。第三个八位字节是指向路由数据的指针
        指示开始存储路由
        地址的下一个区域的八位字节。指针是相对于这个选项的,
        指针的最小合法值是4。

        一条记录的路由是由一系列互联网地址组成的。
        每个互联网地址是 32 位或 4 个八位字节。如果指针为


        长度大于长度,记录的路由数据区已满。
        始发主机必须将此选项与
        足够大的路由数据区域组成,以容纳所有预期的地址。选项的
        大小不会因添加地址而改变。路由数据区的
        初始内容必须为零。

        当 Internet 模块路由数据报时,它会检查是否
        存在记录路由选项。如果是,则插入其
        在该
        数据报被转发到的环境中已知的自己的互联网地址
        ,从指针指示的八位字节开始记录的路由,并将指针增加
        四。

        如果路由数据区已满(指针超过
        长度),则转发数据报而不将地址
        插入记录的路由中。如果有一些空间但没有足够的
        空间来插入完整地址,则原始数据报被
        认为是错误的并被丢弃。在任何一种情况下,
        都可以将 ICMP 参数问题消息发送到源
        主机 [ 3 ]。

        不复制碎片,只进入第一个碎片。
        在一个数据报中最多出现一次。

      流标识符

        +--------+--------+--------+--------+ 
        |10001000|00000010| 流 ID | 
        +--------+--------+--------+--------+ 
         Type=136 Length=4

        该选项为
        通过不支持
        流概念的网络携带的 16 位 SATNET 流标识符。

        必须在碎片上复制。在一个数据报中最多出现一次
        。                                                            


      Internet 时间戳

        +--------+--------+--------+--------+ 
        |01000100| 长度 | 指针|oflw|flg| 
        +--------+--------+--------+--------+ 
        | 网址 | 
        +--------+--------+--------+--------+ 
        | 时间戳 | 
        +--------+--------+--------+--------+ 
        | . | 
                          . 
                          . 
        Type = 68

        选项长度是选项计数中的八位字节数
        类型、长度、指针和溢出/标志八位字节(最大
        长度 40)。

        指针是从该
        选项开始到时间戳结束的八位字节数加一(即,它指向
        开始下一个时间戳空间的八位字节)。最小的合法值为 5。当指针
        大于长度
        时,时间戳区域已满。
        溢出 (oflw) [4 位] 是
        由于空间不足而无法注册时间戳的 IP 模块的数量。
        标志 (flg) [4 位] 值为
          0 - 仅时间戳,存储在连续的 32 位字中,


          1 -- 每个时间戳都以
               注册实体的互联网地址开头,

          3 -- 互联网地址字段是预先指定的。IP模块只有在它自己的
               地址与下一个指定的互联网地址
               匹配时才注册它的时间戳。
        Timestamp 是一个右对齐的 32 位时间戳,
        从 UT 午夜开始以毫秒为单位。如果时间不能以
        毫秒为单位或不能提供相对于午夜 UT
        的时间,则可以插入任何时间作为时间戳,前提是
        时间戳字段的高位设置为 1 以指示
        使用非标准值。


        始发主机必须将此选项与
        足够大的时间戳数据区域组成,以保存所有
        预期的时间戳信息。选项的大小不会因为添加


        时间戳。时间戳数据区的初始内容
        必须为零或互联网地址/零对。

        如果时间戳数据区已满(指针超出
        长度),则转发数据报而不插入
        时间戳,但溢出计数加一。

        如果有一些空间但没有足够的空间
        来插入完整的时间戳,或者溢出计数本身溢出,则
        原始数据报被认为是错误的并被丢弃。
        在任何一种情况下,都可以将 ICMP 参数问题消息发送到
        源主机 [ 3 ]。

        分片时不会复制时间戳选项。它
        在第一个片段中携带。在一个数据报中最多出现一次
        。

  填充:变量

    互联网报头填充用于确保互联网
    报头以 32 位边界结束。填充为零。3.2 . 讨论
  协议的实施必须是稳健的。每个实现都
  必须期望与不同
  个人创建的其他实现互操作。虽然本规范的目标是明确的

  关于协议,可能会有不同的
  解释。一般来说,一个实现必须
  在其发送行为上是保守的,而在其接收行为上是自由的。也就是说
  ,它必须小心发送格式良好的数据报,但必须接受
  它可以解释的任何数据报(例如,不反对
  含义仍然清楚的技术错误)。

  基本的互联网服务是面向数据报的,并在网关处提供数据报的分段,并
  在目标主机中的目标互联网协议模块
  处进行重组。
  当然,网络内数据报的分段和重组
  或者通过网络网关之间的私有协议也是
  允许的,因为这对互联网协议和
  更高级别的协议是透明的。这种透明类型的分片和
  重组被称为“网络相关”(或内联网)分片
  ,这里不再进一步讨论。

  Internet 地址将源和目标区分为主机
  级别,并提供协议字段。假设每个
  协议将提供
  主机内所需的任何多路复用。  

--

我需求需要用到的安全性相关的要求目前已经于新的rfc文档中说明已经弃用了,不确定现在的某些交换机路由器等网络设备会不会丢弃这些带有option字段的数据;

对于ipv6更是没有这个选项字段了,取而代之的是

所以也不会采用这种方案。

其他更多得信息可以参考

RFC 791: Internet Protocol icon-default.png?t=M276https://www.rfc-editor.org/rfc/rfc791IPv4 Options_安静呆一会儿的博客-CSDN博客_ipv4 optionIPv4 allows up to 40 bytes of options to follow the fixed 20-byte header. Although 10 different options are defined, the most commonly used is the source route option. Accessto these options is throhttps://blog.csdn.net/u014211079/article/details/35987367?spm=1001.2101.3001.6650.7&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-7.pc_relevant_paycolumn_v3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-7.pc_relevant_paycolumn_v3&utm_relevant_index=11

这个是一个另外的例子代码icon-default.png?t=M276https://github.com/50u1w4y/50u1w4y.github.io/blob/d3ade0b17a0be3b7df84be2d96a4bd15b5c6c0dd/site/recurrence/code/CVE-2021-24074/test.cpp

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/386034
推荐阅读
相关标签
  

闽ICP备14008679号