第8章 IP:网际协议
所属:TCP/IP详解 卷2:实现 来源:TCP/IP详解 卷2:实现
本章描述IP层的实现,包括IP首部结构、IP输入处理、IP输出处理、IP转发和IP选项处理等。
8.1 引言
IP层的作用
IP层的作用:
- 提供无连接的数据报服务
- 负责寻址和选路
- 分片和重装
- 尽力而为的服务
- 不保证可靠交付
IP是TCP/IP协议栈的核心。
本章讨论的内容
本章讨论的内容:
- IP首部结构
- IP输入处理(ip_input)
- IP输出处理(ip_output)
- IP转发(ip_forward)
- IP选项处理
- IP分片与重装(下一章详细讲)
本章讨论IP层的基本实现。
8.2 IP首部
IP首部结构
IP首部的结构:
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|版本|首部长度| 服务类型 | 总长度 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 标识 |标志| 片偏移 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 生存时间 | 协议 | 首部检验和 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 源地址 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 目的地址 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 选项(如果有) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据(如果有) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
ip结构
内核中的IP首部结构:
struct ip {
u_char ip_vhl; /* 版本和首部长度 */
u_char ip_tos; /* 服务类型 */
u_short ip_len; /* 总长度 */
u_short ip_id; /* 标识 */
u_short ip_off; /* 标志和片偏移 */
u_char ip_ttl; /* 生存时间 */
u_char ip_p; /* 协议 */
u_short ip_sum; /* 首部检验和 */
struct in_addr ip_src; /* 源地址 */
struct in_addr ip_dst; /* 目的地址 */
};字段说明
| 字段 | 大小 | 说明 |
|---|---|---|
| ip_vhl | 1字节 | 版本(4位)+ 首部长度(4位) |
| ip_tos | 1字节 | 服务类型 |
| ip_len | 2字节 | 总长度(首部+数据) |
| ip_id | 2字节 | 标识(分片用) |
| ip_off | 2字节 | 标志(3位)+ 片偏移(13位) |
| ip_ttl | 1字节 | 生存时间 |
| ip_p | 1字节 | 协议(TCP=6, UDP=17, ICMP=1等) |
| ip_sum | 2字节 | 首部检验和 |
| ip_src | 4字节 | 源IP地址 |
| ip_dst | 4字节 | 目的IP地址 |
IP首部最小20字节,选项最多40字节。
常用的宏
常用的IP宏:
| 宏 | 说明 |
|---|---|
| IP_V(ip) | 获取版本号 |
| IP_HL(ip) | 获取首部长度(以4字节为单位) |
| IP_OFF(ip) | 获取片偏移 |
| IP_MF | 更多分片标志 |
| IP_DF | 不分片标志 |
| IP_RF | 保留标志 |
宏方便访问各个字段。
8.3 IP输入处理
ip_input函数
IP输入处理(ip_input):
- 从链路层收到IP数据报
- 验证IP首部
- 处理选项
- 判断是本机还是转发
- 分用给上层协议
ip_input是IP层输入的入口。
输入处理流程
IP输入的处理流程:
收到IP数据报
|
v
验证版本和长度
|
v
验证检验和
|
v
处理IP选项
|
v
目的地址是本机?
|
+---> 是 → 分用给上层协议
| |
| +---> TCP → tcp_input
| +---> UDP → udp_input
| +---> ICMP → icmp_input
| +---> 其他 → 原始IP
|
+---> 否 → 转发(ip_forward)
验证步骤
IP输入的验证:
-
版本验证
- 必须是IPv4(版本=4)
- 不是则丢弃
-
首部长度验证
- 至少20字节
- 不超过总长度
-
总长度验证
- 至少和首部一样长
- 不超过接收的长度
-
检验和验证
- 计算检验和
- 必须为0
- 不对则丢弃
验证不通过就丢弃。
分用
IP分用(demultiplexing):
- 根据ip_p字段(协议号)分用
- 找到对应的上层协议
- 交给上层处理
常见的协议号:
- 1:ICMP
- 2:IGMP
- 6:TCP
- 17:UDP
- … 还有很多
分用把数据交给正确的上层协议。
8.4 IP输出处理
ip_output函数
IP输出处理(ip_output):
- 上层协议调用
- 添加IP首部
- 处理选项
- 选路
- 可能分片
- 交给接口发送
ip_output是IP层输出的入口。
输出处理流程
IP输出的处理流程:
上层调用ip_output
|
v
构造IP首部
|
v
处理IP选项
|
v
选路,确定下一跳和输出接口
|
v
需要分片?
|
+---> 是 → 分片(ip_insertoptions等)
|
+---> 否 → 继续
|
v
计算检验和
|
v
调用接口输出
源地址选择
源地址的选择:
- 如果应用指定了源地址,用指定的
- 否则根据输出接口选择
- 用输出接口的地址作为源地址
- 多宿主主机的情况
- 选择最合适的地址
源地址通常是输出接口的地址。
TTL设置
TTL的设置:
- 默认值(通常64)
- 应用可以修改
- 多播默认TTL=1
- 原始IP可以自己设置
TTL限制分组的跳数。
8.5 IP转发
ip_forward函数
IP转发(ip_forward):
- 目的不是本机
- 需要转发出去
- 路由器的功能
- 需要开启GATEWAY选项
转发是路由器的核心功能。
转发流程
IP转发的流程:
目的不是本机
|
v
检查是否允许转发
|
+---> 不允许 → 丢弃,发ICMP不可达
|
+---> 允许 → 继续
|
v
TTL减1
|
v
TTL为0?
|
+---> 是 → 丢弃,发ICMP超时
|
+---> 否 → 继续
|
v
查找选路表
|
v
找到路由?
|
+---> 否 → 丢弃,发ICMP不可达
|
+---> 是 → 继续
|
v
重新计算检验和
|
v
可能需要重定向
|
v
调用接口输出
TTL处理
TTL的处理:
- 转发时TTL减1
- TTL为0则丢弃
- 发送ICMP超时报文
- 防止分组无限循环
TTL防止路由循环。
检验和更新
检验和的更新:
- TTL变了,检验和也要变
- 可以用增量计算
- 不需要重新计算整个首部
- 提高效率
增量计算提高转发效率。
8.6 IP选项处理
选项的类型
常见的IP选项:
- 记录路径
- 时间戳
- 源站选路(宽松和严格)
- 安全选项
- 等等
选项扩展IP的功能。
选项的处理
选项处理的时机:
- 输入时处理:ip_dooptions
- 输出时添加:应用设置
- 转发时处理:更新选项
选项在输入、输出、转发时都要处理。
8.7 小结
IP首部
-
结构
- 版本、首部长度
- 服务类型、总长度
- 标识、标志、片偏移
- TTL、协议、检验和
- 源地址、目的地址
- 选项(可选)
-
ip结构
- 内核中的C结构
- 对应IP首部
-
常用宏
- IP_V、IP_HL
- IP_OFF
- IP_MF、IP_DF
IP输入处理
-
ip_input
- IP输入的入口
- 从链路层接收
-
验证
- 版本、长度
- 检验和
- 不通过就丢弃
-
分用
- 根据协议号
- 交给上层协议
IP输出处理
-
ip_output
- IP输出的入口
- 上层调用
-
源地址选择
- 指定的或接口地址
-
TTL设置
- 默认值
- 应用可修改
IP转发
-
ip_forward
- 转发功能
- 路由器功能
-
TTL处理
- 减1
- 为0则丢弃
-
检验和更新
- 增量计算
- 提高效率
IP选项
-
选项类型
- 记录路径
- 时间戳
- 源站选路
- 等等
-
处理时机
- 输入时
- 输出时
- 转发时
关键概念
-
IP首部
- 20字节基本首部
- 选项最多40字节
-
ip_input
- 输入处理
- 验证、分用
-
ip_output
- 输出处理
- 构造首部、选路
-
ip_forward
- 转发处理
- TTL减1
-
IP选项
- 扩展IP功能
- 各种选项