赞
踩
对于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的例子,这里面也有一些坑代码,找了好久没有找到。
- #include <stdio.h>
- #include <winsock2.h>
- #include <ws2tcpip.h>
- #include <time.h>
- #include <iostream>
- #include <windows.h>
- #pragma comment(lib,"ws2_32.lib")
-
- using namespace std;
- const int IP_Header_min_lenght = 20;
- /*
- Ver 4
- Hlen 4
- 1
- Servicetype 8
- 1
- Total length 16
- 2
- Identifier 16
- 2
- flag and frag offset 16
- 2
- TimeToLive 8
- 1
- Prorocol 8
- CHECKSUM 16
- SRC ADDR 32
- DES ADDR 32
- 160/8=20
- */
-
- #pragma pack(push,1)
- typedef struct ip_hdr //定义IP首部
- {
- unsigned char h_verlen; //4位首部长度,4位IP版本号
- unsigned char tos; //8位服务类型TOS
- unsigned short total_len; //16位总长度(字节)
- unsigned short ident; //16位标识
- unsigned short frag_and_flags; //3位标志位
- unsigned char ttl; //8位生存时间 TTL
- unsigned char proto; //8位协议 (TCP, UDP 或其他)
- unsigned short checksum; //16位IP首部校验和
- unsigned int sourceIP; //32位源IP地址
- unsigned int destIP; //32位目的IP地址
- }IPHEADER;
-
- typedef struct tsd_hdr //定义TCP伪首部
- {
- unsigned long saddr; //源地址
- unsigned long daddr; //目的地址
- char mbz;
- char ptcl; //协议类型
- unsigned short tcpl; //TCP长度
- }PSDHEADER;
-
- typedef struct tcp_hdr //定义TCP首部
- {
- USHORT th_sport; //16位源端口
- USHORT th_dport; //16位目的端口
- unsigned int th_seq; //32位序列号
- unsigned int th_ack; //32位确认号
- unsigned char th_lenres; //4位首部长度/6位保留字
- unsigned char th_flag; //6位标志位
- USHORT th_win; //16位窗口大小
- USHORT th_sum; //16位校验和
- USHORT th_urp; //16位紧急数据偏移量
- }TCPHEADER;
- typedef struct icmp_hdr
- {
- unsigned char icmp_type; // 类型
- unsigned char icmp_code; // 代码
- unsigned short icmp_checksum; // 校验和
- unsigned short icmp_id; // ID号,设为PID
- unsigned short icmp_sequence; // 序列号
- unsigned long icmp_timestamp; // 时间戳
- } ICMP_HDR, *PICMP_HDR;
- #pragma pack(pop)
-
-
-
- unsigned short CheckSum(USHORT* buff, int size)
- {
- unsigned long cksum = 0;
- while (size > 1)
- {
- cksum += *buff++;
- size -= sizeof(USHORT);
- }
- // 是奇数
- if (size)
- {
- cksum += *(UCHAR*)buff;
- }
- // 将32位的chsum高16位和低16位相加,然后取反
- cksum = (cksum >> 16) + (cksum & 0xffff);
- cksum += (cksum >> 16);
- return (USHORT)(~cksum);
- }
-
- bool SetTimeout(SOCKET sRaw, int nTime)
- {
- int ret = setsockopt(sRaw, SOL_SOCKET, SO_RCVTIMEO, (char*)&nTime, sizeof(nTime));
- return ret != SOCKET_ERROR;
- }
-
- double GetTickCountA()
- {
- __int64 Freq = 0;
- __int64 Count = 0;
- if (QueryPerformanceFrequency((LARGE_INTEGER*)&Freq) && Freq > 0 && QueryPerformanceCounter((LARGE_INTEGER*)&Count))
- {
- //乘以1000,把秒化为毫秒
- return (double)Count / (double)Freq * 1000.0;
- }
- return 0.0;
- }
- int main()
- {
-
- char website_name[] = "10.19.11.221";// www.baidu.com www.google.com
- char *DestIp;
- double succ = 0;
- double fail = 0;
- int min_RTT = 999999999;
- int max_RTT = -1;
- int sum_RTT = 0;
- DestIp = (char*)malloc(20 * sizeof(char));
- //初始化WindowsSocketsAPI
- WSADATA wsaData;
- WORD sockVersion = MAKEWORD(2, 2);//声明版本 2.2
- WSAStartup(sockVersion, &wsaData);//启动
- //获取IP地址
- struct hostent *curr_hostent = gethostbyname(website_name);
- DestIp = inet_ntoa(*(struct in_addr*)curr_hostent->h_addr_list[0]);
- DestIp = (char *)"10.19.11.221";
- printf("正在ping %s:[%s] \n", website_name, DestIp);
- //printf("%s\n",curr_hostent->h_addr_list[0]);
- //printf("%s\n",inet_ntoa(*(struct in_addr*)curr_hostent->h_addr_list[0]));
- if (!curr_hostent) {
- puts("Get IP address error!");
- //system("pause");
- // exit(0);
- }
- //创立套接字
- SOCKET sRaw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);//AF_INET=ipv4 SOCK_RAW ICMP协议
-
-
- BOOL flag = true;
- if (setsockopt(sRaw, IPPROTO_IP, IP_HDRINCL, (char *)&flag, sizeof(flag)) == SOCKET_ERROR)
- {
- printf("setsockopt IP_HDRINCL error! ");
- return false;
- }
-
- SetTimeout(sRaw, 1000);
-
- // 设置目的地址
- SOCKADDR_IN dest;
- dest.sin_family = AF_INET;//ipv4地址家族
- // dest.sin_port = htons(0);//将整型变量从主机字节顺序转变成网络字节顺序
- dest.sin_addr.S_un.S_addr = inet_addr(DestIp);
- // 创建ICMP数据包并填写
-
- //ip 选项部分4字节
- const int i_len_total = sizeof(IPHEADER) + 12 + sizeof(ICMP_HDR) + 32;//...
- char buff[i_len_total];
-
- IPHEADER* ipHeader = (IPHEADER*)buff;
- //ipHeader->h_verlen = (4 << 4 | sizeof(ipHeader) / sizeof(unsigned long));
- ipHeader->h_verlen = 0x40 + (sizeof(IPHEADER) / 4 + 3); //...
- ipHeader->tos=0;
- ipHeader->total_len = /*htons*/(i_len_total);
- ipHeader->ident = 1;
- ipHeader->frag_and_flags = 0;
- ipHeader->ttl = 120;
- ipHeader->proto = IPPROTO_ICMP;
- ipHeader->checksum = 0;
- ipHeader->sourceIP = inet_addr("10.18.11.223"); //src ip
- ipHeader->destIP = inet_addr( "10.19.11.221" ); //dest ip
-
-
- char optionPacket_2[] = {
- '\x01', '\x01', '\x01', '\x01',
- '\x83', '\x07', '\x08', '\xC0',
- '\xA8', '\x7E', '\x80', '\x00'
- };
- int optionLength = 12;
-
- memcpy(buff + sizeof(IPHEADER), optionPacket_2, optionLength);
-
- //ipHeader->checksum = CheckSum((unsigned short*)ipHeader, sizeof(IPHEADER) /*+ 4*/);
-
- ICMP_HDR* pIcmp = (ICMP_HDR*)(buff + sizeof(IPHEADER)+ 12);//...
- pIcmp->icmp_type = 8; // 请求一个ICMP回显
- pIcmp->icmp_code = 0;
- pIcmp->icmp_id = (unsigned short)GetCurrentProcessId();
- unsigned short nSeq = 0;
- char recvBuf[1024];
- SOCKADDR_IN from;
- int nLen = sizeof(from);
- for (int o = 0; o < 9999999; o++)
- {
- int nRet;
- pIcmp->icmp_checksum = 0;//为了后续checksum函数正常 需要先置位0
- pIcmp->icmp_timestamp = GetTickCountA();
- pIcmp->icmp_sequence = nSeq++;
- pIcmp->icmp_checksum = CheckSum((unsigned short*)pIcmp, sizeof(ICMP_HDR) + 32);
- //发送包
- nRet = sendto(sRaw, buff, i_len_total, 0, (SOCKADDR *)&dest, sizeof(dest));//发送
- if (nRet == SOCKET_ERROR)
- {
- printf(" sendto() failed: %d \n", ::WSAGetLastError());
- return -1;
- }
- //接收包
- nRet = recvfrom(sRaw, recvBuf, 1024, 0, (sockaddr*)&from, &nLen);
- if (nRet == SOCKET_ERROR)
- {
- if (WSAGetLastError() == WSAETIMEDOUT)
- {
- printf(" Request timed out\n");
- fail++;
- continue;
- }
- fail++;
- printf(" Failed. Error code: %d\n", WSAGetLastError());
- return -1;
- }
- // 解析包
- int nTick = GetTickCountA();
- if (nRet < IP_Header_min_lenght + sizeof(ICMP_HDR))
- {
- printf(" Returned too few bytes from %s \n", inet_ntoa(from.sin_addr));
- fail++;
- }
- // 接收包中包含IP头,所以加20得到ICMP头
- ICMP_HDR* pRecvIcmp = (ICMP_HDR*)(recvBuf + IP_Header_min_lenght); // (ICMP_HDR*)(recvBuf + sizeof(IPHeader));
- if (pRecvIcmp->icmp_type != 0) // 回显
- {
- if (pRecvIcmp->icmp_type == 3) // 回显
- {
- printf(" Unreachable\n"); fail++;
- }
- else if (pRecvIcmp->icmp_type == 4) // 回显
- {
- printf(" Origin suppression \n"); fail++;
- }
- else if (pRecvIcmp->icmp_type == 5) // 回显
- {
- printf(" Redirect \n"); fail++;
- }
- else if (pRecvIcmp->icmp_type == 8) // 回显
- {
- printf(" Echo request\n"); fail++;
- }
- else if (pRecvIcmp->icmp_type == 9) // 回显
- {
- printf(" Router announcement\n"); fail++;
- }
- else if (pRecvIcmp->icmp_type == 10) // 回显
- {
- printf(" Router request \n"); fail++;
- }
- else if (pRecvIcmp->icmp_type == 11) // 回显
- {
- printf(" Time out \n"); fail++;
- }
- else if (pRecvIcmp->icmp_type == 17) // 回显
- {
- printf(" Address subnet request\n"); fail++;
- }
- else if (pRecvIcmp->icmp_type == 18) // 回显
- {
- printf(" Address subnet response\n"); fail++;
- }
- return -1;
- }
- succ++;
- printf(" 来自 %s的回复: ", inet_ntoa(from.sin_addr));
- printf(" 字节=%d bytes :", nRet, inet_ntoa(from.sin_addr));
- printf(" 时间= %d ms", nTick - pRecvIcmp->icmp_timestamp);
- printf(" TTL= %d \n", *(recvBuf + 8));
- min_RTT = min(min_RTT, (int)(nTick - pRecvIcmp->icmp_timestamp));
- max_RTT = max(max_RTT, (int)(nTick - pRecvIcmp->icmp_timestamp));
- sum_RTT = sum_RTT + nTick - pRecvIcmp->icmp_timestamp;
- Sleep(1000);//一秒
- }
- printf("数据包丢失率:%lf", fail * 100 / (succ + fail));
- cout << "%" << endl;
- printf("最小 RTT = %d ms \n", min_RTT);
- printf("最大 RTT = %d ms\n", max_RTT);
- printf("平均 RTT = %d ms\n", sum_RTT / 10);
-
- return 0;
- }
测试可以正常发送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 https://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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。