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 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Linux 下C/C++实现发送ICMP和ICMPv6(报文分析) -> 正文阅读

[系统运维]Linux 下C/C++实现发送ICMP和ICMPv6(报文分析)

当终端系统无法到达目的地的IP数据包时,为了方便获取诊断信息。一种称为Internet控制消息协议(ICMP)的特殊协议与IP结合使用,以提供与IP协议层配置和IP数据包处理相关的诊断和控制信息。主要的原因是IP协议没有内置机制,在源设备发送的数据包无法到达目标时通知源设备。对于错误报告和控制,它取决于ICMP协议。

ICMP和ICMPv6的报头格式

下图显示了ICMPv4和ICMPv6消息的格式。前4个字节对所有消息都具有相同的格式,但其余的字节因消息而异。

类型字段用于确定特定的报文,ICMPv4和ICMPv6的该字段值并不相同;代码字段进一步肯定报文的含义,ICMPv4和ICMPv6的该字段值并不相同;校验和字段用于确定报文信息的正确性。

  • Wireshark抓包获取ICMP(以Echo (ping)request为例):

我们日常使用最多的ping,就是响应请求(Type=8)和应答(Type=0),一台主机向一个节点发送一个Type=8的ICMP报文,如果途中没有异常(例如被路由器丢弃、目标不回应ICMP或传输失败),则目标返回Type=0的ICMP报文,说明这台主机存在,更详细的tracert通过计算 ICMP报文通过的节点来确定主机与目标之间的网络距离。


对于ICMPv4,信息消息包括:

回声请求(类型8)
回音回复(类型0)
路由器播发(类型9)
路由器请求(类型10)

路由器广告和路由器请求统称为路由器发现。最常见的错误消息类型包括:

目标无法访问(类型3)
重定向(类型5)
超过时间(类型11)
参数问题(类型12)

  • Wireshark抓包获取ICMPv6(以Echo (ping)request为例):


类型:标识ICMPv6报文类型,它的值根据报文的内容来确定。
代码:用于确定ICMPv6进一步的信息,对同一类型的报文进行了更详细的分类。
校验和:用于检测ICMPv6的报文是否正确传送。
报文体:用于返回出错的参数和记录出错报文的片段,帮助源结点判断错误的原因。或是其它参数。

类型字段值为128 ,表示该ICMPv6信息报文中的回送请求报文。代码字段在发送端置为0校验和字段在计算之前被置0.标识字段与序列号字段用于在回送请求报文与回送应答报文之间建立对应关系。数据字段是诊断的内容,为8b的整数倍。

在ICMPv6中,与ICMPv4中一样,消息被分组为信息类和错误类。

然而,在ICMPv6中,所有错误消息的类型字段的高位都有一个0。因此,ICMPv6类型0到127都是错误,类型128到255都是信息性的。许多信息性消息是请求/回复对。

Linux发送ECHO request消息C/C++代码实现

...
int main(int argc, char *argv[])
{
	...
	 for (int i=1; i<argc; ++i) 
	 {
		const char *const arg = argv[i];
	
		union 
		{
		  	struct sockaddr_in  sin;
		  	struct sockaddr_in6 sin6;
		} u;
		bzero(&u, sizeof(u));
	
	   if (0 == strcmp("--help", arg)) 
	{
	     	print_usage();
	     	return 0;
	   } 
	else if (0 == strcmp("--version", arg)) 
	{
	     	print_version();
	     	return 0;
	   }
	else if ((0 == strcmp("--dry-run", arg)) || (0 == strcmp("-n", arg))) 
	{
	     	dry_run = true;
	     	continue;
	   } 
	else if (0 == strcmp("--loop", arg)) 
	{
	     	do_loop = true;
	     	continue;
	   } 
	else if (0 == strcmp("-qq", arg)) 
	{
	      switch (verbosity) 
	      {
		      case VERB_NORMAL:
		        	verbosity = VERB_MUTE;
		        break;
		      default:
		        	error_exit("Illegal use of -qq");
	      }
	     continue;
	   } 
	else if ((0 == strcmp("--quiet", arg)) || (0 == strcmp("-q", arg))) 
	{
	      switch (verbosity) 
		  {
		      case VERB_NORMAL:
		        	verbosity = VERB_QUIET;
		        break;
		      case VERB_QUIET:
		        	verbosity = VERB_MUTE;
		        break;
		      default:
		        	error_exit("Illegal use of --quiet/-q");
	      }
	     continue;
	   } 
	else if (0 == strcmp("-vv", arg)) 
	{
	      switch (verbosity) 
	      {
	      	case VERB_NORMAL:
	        	verbosity = VERB_VERY;
	        break;
	      	default:
	        	error_exit("Illegal use of -vv");
	      }
	     continue;
	   } 
	else if ((0 == strcmp("--verbose", arg)) || (0 == strcmp("-v", arg))) 
	{
	      switch (verbosity) 
		  {
		      case VERB_NORMAL:
		        	verbosity = VERB_VERBOSE;
		        break;
		      case VERB_VERBOSE:
		        	verbosity = VERB_VERY;
		        break;
		      default:
		        	error_exit("Illegal use of --verbose/-v");
	      }
	     		continue;
	   } 
	else if (1 == inet_pton(AF_INET6, arg, &u.sin6.sin6_addr)) 
	{
	      enlarge_array(arg);
	      u.sin6.sin6_family = AF_INET6;
	      memcpy(&tasks[task_cnt].sas, &u.sin6, sizeof(u.sin6));
	   } 
	else if (1 == inet_pton(AF_INET, arg, &u.sin.sin_addr)) 
	{
	      enlarge_array(arg);
	      u.sin.sin_family = AF_INET;
	      memcpy(&tasks[task_cnt].sas, &u.sin, sizeof(u.sin));
	   } 
	else 
	{
	     	  error_exitf("Cannot parse address: %s", arg);
	   }
	
	   tasks[task_cnt].delay.tv_sec  = 0;
	   tasks[task_cnt].delay.tv_nsec = 500000000;
	   ++task_cnt;
	 }


...

  return 0;
}
...

发送回显请求将一个ICMP(IPv4)或ICMPv6(IPv6)回显请求分别发送到一个地址列表,而无需等待回显回复数据包。每0.5秒发送一个数据包。或者,在无限循环中重复发送数据包。

运行结果:


tcpdump抓取ICMP ECHO request消息:


使用

./send_echo_request -q --loop 39.156.66.10

使用-q选项可以抑制信息回显在终端。

tcpdump抓取ICMP ECHO request消息:
在这里插入图片描述
发送ICMPv6 echo request消息:


tcpdump抓包
tcpdump -i ens33 “icmp6 && ip6[40] == 128”

总结

在IPv4中,Internet控制报文协议ICMP向源节点报告关于向目的地传输IP数据包过程中的错误和信息。在IPv6中,ICMPv6除了提供ICMPv4常用的功能之外,还是其它一些功能的基础,如邻接点发现、无状态地址配置(包括重复地址检测)、PMTU发现等。最后写个测试例子来发送回显请求,并且进行抓包分析。有助于理解ICMP和ICMPv6

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-10-17 13:11:55  更:2022-10-17 13:13:43 
 
开发: 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/25 18:26:56-

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