IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 附加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的例子,这里面也有一些坑代码,找了好久没有找到。

#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 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

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-03-21 21:30:49  更:2022-03-21 21:33:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:20:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码