2019独角兽企业重金招聘Python工程师标准>>>
ICMP 报文由 IP 层负责传输,ICMP 报文的格式如下:
类型: 1 byte,用于指定 ICMP 报文的类型.
代码: 1 byte,用于进一步描述 ICMP 报文为何生成.
检验和: 2 bytes,使用的算法与 IP 首部检验和算法相同,覆盖了整个 ICMP 报文.
其他内容: 不同类型和代码的 ICMP 报文有不同的内容.
ICMP 目的不可达
报文格式:
类型: 1 byte,取值为 3.
代码: 1 byte,取值为 [0,16)
检验和: 2 byte,
未用位: 4 byte,必须置 0,但当代码字段的值为4('需要分片但设置了不分片比特')时,允许路由器把外出接口的 MTU 填在这个32 bit字的低 16 bit中.
引起该 ICMP 差错报文的 IP 数据包的IP 首部(包括选项)+数据部分的前8字节(正好将 TCP,UDP 的端口号也包含了其中).
ICMP 回显
ICMP 回显请求,应答报文的格式:
类型: 1 byte
代码: 1 byte
检验和: 2 byte
标识符: 2 byte
序列号: 2 byte
额外的数据请求报文的取值:{8;0;算法生成;任意设置;任意设置;...}
应答报文的取值:{0;0;算法生成;不变;不变;不变}
ICMP 地址掩码请求/应答
用于无盘主机在引导过程中获取自己所处子网的子网掩码.此时分组格式:
ICMP 地址掩码格式:
类型: 1 byte,
代码: 1 byte,
检验和: 2 byte,
标识符: 2 byte,
序列号: 2 byte,
子网掩码: 4 byte.
请求格式:{17;0;算法生成;可能是随机生成;可能是随机生成;0}
应答格式:{18;0;算法生成;不变;不变;子网掩码}
其中应答格式中的'子网掩码'必须是必须是'收到 ICMP 地址掩码请求'的网络接口的子网掩码,因为一个主机可能具有多个网络接口,每一个网络接口具有不同的掩码,如:
# icmpaddrmask 用于向主机名为 argv[1] 的主机发送 ICMP 地址掩码请求
sun$ icmpaddrmask sun # 此时 ICMP 地址掩码请求会转交给环回接口,所以返回的是环回接口的地址掩码.
received mask= ff000000, from 140.252.13.33
sun$ icmpaddrmask localhost # 此时 ICMP 地址掩码请求直接交给环回接口,
received mask= ff000000, from 127.0.0.
ICMP 时间戳请求/应答
允许主机向另一个主机查询当前的时间,下面的'时间戳'是指自午夜(不是 1900-01-01 00:00:00 了)开始计算的毫秒数,协调的统一时间 UTC.此时 ICMP 报文格式:
类型: 1 byte,
代码: 1 byte,
检验和: 2 byte,
标识符: 2 byte,
序列号: 2 byte,
发起时间戳: 4 byte
接受时间戳: 4 byte
传送时间戳: 4 byte# 请求格式:
{13;0;算法生成;可能是随机生成;可能是随机生成;发送'ICMP 时间戳请求报文'时的时间戳;0(TODO 不确定),0 }
# 应答格式:
{14,0,算法生成,不变,不变,不变,接受到'ICMP 时间戳请求报文'时的时间戳,发送'ICMP 时间戳应答报文'时的时间戳};
根据 ICMP 时间戳应答报文的内容与 RTT 调整时间:
var orig; /* 发起时间戳 */
var recv; /* 接受时间戳 */
var xmit; /* 传送时间戳 */
var rtt; /* RTT,往返时间,假设 RTT 的一半用于请求报文的传输,另一半用于应答报文的传输 */
则本机时间应该加上 recv-(orig+rtt/2);
若干个概念
日期服务程序,以人们可读的格式返回当前的时间和日期,是一行 ASCII 字符.
时间服务程序,返回的是一个 32 bit 的二制进数值,表示自 UTC,1900年1月1日午夜起算的秒数
NTP,采用先进的技术来保证 LAN 或 WAN 上的一组主机的时钟误差在毫秒级以内.
BSD 系统对 ICMP 报文的处理
仅当作一个参考.对处理方法的解释:
若处理方法指明为'用户进程',则报文就被传送到所有在内核中登记的用户进程,以读取收到的 ICMP 报文.如果不存在任何这样的用户进程,那么报文就悄悄地被丢弃
若处理方法指明为'内核',则 ICMP 报文就由内核来处理,在处理完毕之后,内核会将该 ICMP 报文拷贝给'感兴趣'的用户进程(即已经在内核中登记的用户进程)
若标明的是引号内的一串字符,那么它就是对应的 Unix 差错,即 errno 的字符串描述.如当内核收到类型为3,代码为3的 ICMP 差错报文时,内核会根据差错报文中带有的端口号来找到引起差错的用户进程,然后让该用户进程中的 errno 变量取值为'连接被拒绝'.