第11章 ICMP:Internet控制报文协议
所属:TCP/IP详解 卷2:实现 来源:TCP/IP详解 卷2:实现
本章描述ICMP协议的内核实现,包括ICMP报文类型、ICMP输入处理、ICMP输出处理和ICMP差错报文等。
11.1 引言
ICMP的作用
ICMP(Internet Control Message Protocol):
- Internet控制报文协议
- 传递网络层的控制信息
- 报告错误和状态
- 诊断工具(ping、traceroute等)
- IP协议的一部分,协议号1
ICMP用于网络控制和诊断。
ICMP的特点
ICMP的特点:
- 封装在IP数据报中
- 协议号1
- 不保证可靠交付
- 不产生ICMP的ICMP(防止雪崩)
- 差错报文包含原IP首部和前8字节数据
ICMP是IP的辅助协议。
本章讨论的内容
本章讨论的内容:
- ICMP报文类型
- ICMP输入处理(icmp_input)
- ICMP输出处理(icmp_output)
- ICMP差错报文
- ICMP查询报文
- ICMP与上层协议的交互
本章讨论ICMP的内核实现。
11.2 ICMP报文类型
ICMP报文分类
ICMP报文分为两大类:
-
差错报文(Error Messages)
- 报告错误
- 如目的不可达、超时、重定向等
-
查询报文(Query Messages)
- 请求-应答模式
- 如回显请求/应答、时间戳请求/应答等
差错报文报告错误,查询报文用于诊断。
常见的ICMP报文
常见的ICMP报文类型:
| 类型 | 代码 | 名称 | 类别 |
|---|---|---|---|
| 0 | 0 | 回显应答(Echo Reply) | 查询 |
| 3 | 0-15 | 目的不可达(Destination Unreachable) | 差错 |
| 4 | 0 | 源抑制(Source Quench) | 差错 |
| 5 | 0-3 | 重定向(Redirect) | 差错 |
| 8 | 0 | 回显请求(Echo Request) | 查询 |
| 9 | 0 | 路由器通告(Router Advertisement) | 查询 |
| 10 | 0 | 路由器请求(Router Solicitation) | 查询 |
| 11 | 0-1 | 超时(Time Exceeded) | 差错 |
| 12 | 0-1 | 参数问题(Parameter Problem) | 差错 |
| 13 | 0 | 时间戳请求(Timestamp Request) | 查询 |
| 14 | 0 | 时间戳应答(Timestamp Reply) | 查询 |
| 15 | 0 | 信息请求(Information Request) | 查询 |
| 16 | 0 | 信息应答(Information Reply) | 查询 |
| 17 | 0 | 地址掩码请求(Address Mask Request) | 查询 |
| 18 | 0 | 地址掩码应答(Address Mask Reply) | 查询 |
有很多种ICMP报文类型。
ICMP报文格式
ICMP报文的通用格式:
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 类型 | 代码 | 检验和 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| 内容(可变) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
字段说明:
- 类型:8位,报文类型
- 代码:8位,进一步细分
- 检验和:16位,ICMP报文的检验和
- 内容:可变,取决于类型和代码
ICMP封装在IP数据报中。
差错报文的内容
差错报文包含:
- 原IP首部
- 原数据报的前8字节数据
- 这样上层协议可以匹配是哪个数据报出错了
为什么是前8字节:
- TCP/UDP的端口号在前8字节
- 可以找到对应的套接字
- 上层可以处理错误
差错报文包含原数据的一部分。
11.3 ICMP输入处理
icmp_input函数
ICMP输入处理(icmp_input):
- IP层分用后调用
- 处理收到的ICMP报文
- 验证检验和
- 根据类型分别处理
- 有些交给应用(原始套接字)
- 有些内核自己处理
icmp_input是ICMP输入的入口。
输入处理流程
ICMP输入的处理流程:
收到ICMP报文
|
v
验证检验和
|
v
根据类型和代码处理
|
+---> 查询报文(回显请求等)
| |
| +---> 内核处理,生成应答
|
+---> 差错报文(不可达、超时等)
| |
| +---> 通知上层协议
| +---> 通知原始套接字
|
+---> 其他
|
+---> 交给原始套接字
查询报文的处理
回显请求(ping)的处理:
- 收到回显请求
- 验证
- 生成回显应答
- 类型从8改成0
- 交换源目地址
- 数据部分不变
- 重新计算检验和
- 发送回去
ping的应答由内核处理。
差错报文的处理
差错报文的处理:
- 解析差错报文
- 提取原IP首部和前8字节数据
- 找到对应的上层协议
- 通知上层协议
- TCP:tcp_ctlinput
- UDP:udp_ctlinput
- 通知原始套接字
差错报文中包含原数据的一部分。
11.4 ICMP输出处理
icmp_error函数
ICMP差错报文发送(icmp_error):
- 内核需要发送ICMP差错时调用
- 构造ICMP报文
- 包含原IP首部和前8字节数据
- 发送出去
icmp_error发送差错报文。
什么时候发送ICMP差错
发送ICMP差错的情况:
-
目的不可达
- 主机不可达
- 端口不可达
- 协议不可达
- 需要分片但DF置位
- 等等
-
超时
- TTL=0
- 分片重装超时
-
参数问题
- IP首部有问题
-
源抑制
- 拥塞时发送(现在很少用)
-
重定向
- 路由优化时发送
各种错误情况都可能发送ICMP。
不发送ICMP的情况
不发送ICMP差错的情况:
-
ICMP差错报文
- ICMP差错不产生ICMP差错
- 防止雪崩效应
-
广播或多播
- 目的是广播或多播地址
- 不发送ICMP差错
-
链路层广播
- 不是单播的帧
- 不发送
-
源地址不是单播
- 源地址是广播、多播、0等
- 不发送
-
第一个分片之后的分片
- 不是第一个分片
- 不发送
有些情况不发送ICMP,防止问题扩大。
11.5 ICMP与上层协议
ICMP与TCP
ICMP差错对TCP的影响:
- 目的不可达 → 连接可能失败
- 超时 → 可能是路由问题
- 源抑制 → 降低发送速率
- TCP会根据ICMP错误调整
处理方式:
- tcp_ctlinput函数
- 根据ICMP类型和代码处理
- 可能导致连接复位
- 可能记录错误
TCP会处理ICMP差错。
ICMP与UDP
ICMP差错对UDP的影响:
- 端口不可达 → 应用可能收到错误
- 其他错误 → 应用可能收到
处理方式:
- udp_ctlinput函数
- 通知对应的套接字
- 应用可以用recvfrom等收到错误
UDP也会处理ICMP差错。
原始套接字
原始套接字与ICMP:
- 进程可以用原始套接字接收ICMP
- ping、traceroute等工具用
- 需要特殊权限
原始套接字可以直接处理ICMP。
11.6 小结
ICMP概述
-
作用
- 控制报文协议
- 报告错误和状态
- 诊断工具
-
特点
- 封装在IP中
- 协议号1
- 不保证可靠
- 差错不产生差错
ICMP报文类型
-
分类
- 差错报文
- 查询报文
-
常见类型
- 回显请求/应答
- 目的不可达
- 超时
- 重定向
- 时间戳
- 等等
-
格式
- 类型、代码、检验和
- 内容可变
ICMP输入处理
-
icmp_input
- ICMP输入入口
- 验证检验和
- 按类型处理
-
查询报文
- 内核处理
- 生成应答
-
差错报文
- 通知上层协议
- 通知原始套接字
ICMP输出处理
-
icmp_error
- 发送差错报文
- 包含原数据的一部分
-
发送时机
- 目的不可达
- 超时
- 参数问题
- 重定向
- 等等
-
不发送的情况
- ICMP差错不产生差错
- 广播多播不发送
- 源地址不对不发送
ICMP与上层
-
与TCP
- tcp_ctlinput
- 影响连接
-
与UDP
- udp_ctlinput
- 通知套接字
-
与原始套接字
- 可以直接收发ICMP
- ping等工具用
关键概念
-
ICMP
- 控制报文协议
- 报告错误
- 诊断工具
-
报文类型
- 差错和查询
- 各种类型
-
icmp_input
- 输入处理
- 按类型处理
-
icmp_error
- 输出差错
- 有很多限制
-
与上层交互
- 通知TCP/UDP
- 原始套接字