第14章 选路套接字
所属:TCP/IP详解 卷2:实现 来源:TCP/IP详解 卷2:实现
本章描述选路套接字(routing socket)的实现,包括选路消息格式、消息类型、选路套接字的使用等。
14.1 引言
什么是选路套接字
选路套接字(routing socket):
- AF_ROUTE域
- SOCK_RAW类型
- 进程和内核之间交换选路信息
- 可以添加、删除、查询路由
- 可以接收选路变化通知
选路套接字是用户态和内核态交换选路信息的接口。
选路套接字的用途
主要用途:
-
route命令
- 添加、删除、修改、查询路由
- 最常用的工具
-
路由守护进程
- routed、gated等
- 运行路由协议
- 动态更新选路表
-
网络管理工具
- 监控选路表变化
- 统计路由信息
-
监听网络变化
- 接口状态变化
- 地址变化
- 路由变化
选路套接字是管理选路的标准接口。
14.2 选路消息
消息类型
选路消息的类型:
| 类型 | 名称 | 说明 |
|---|---|---|
| RTM_ADD | 添加路由 | 添加一条路由 |
| RTM_DELETE | 删除路由 | 删除一条路由 |
| RTM_CHANGE | 修改路由 | 修改路由参数 |
| RTM_GET | 查询路由 | 查询路由信息 |
| RTM_REDIRECT | 重定向 | ICMP重定向通知 |
| RTM_MISS | 查找失败 | 查找路由失败通知 |
| RTM_IFINFO | 接口信息 | 接口状态变化 |
| RTM_IFANNOUNCE | 接口通知 | 接口添加/删除 |
| RTM_NEWADDR | 新地址 | 接口添加地址 |
| RTM_DELADDR | 删除地址 | 接口删除地址 |
有很多种消息类型,覆盖各种选路相关的操作。
消息方向
消息的方向:
| 方向 | 消息类型 | 说明 |
|---|---|---|
| 进程 → 内核 | RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET | 进程请求操作 |
| 内核 → 进程 | RTM_REDIRECT, RTM_MISS, RTM_IFINFO, … | 内核通知事件 |
进程可以发请求,也可以收通知。
14.3 消息格式
rt_msghdr结构
选路消息的通用头部:
struct rt_msghdr {
u_short rtm_msglen; /* 消息总长度 */
u_char rtm_version; /* 版本 */
u_char rtm_type; /* 消息类型 */
u_short rtm_index; /* 接口索引 */
int rtm_flags; /* 标志 */
int rtm_addrs; /* 地址位图 */
pid_t rtm_pid; /* 发送进程PID */
int rtm_seq; /* 序列号 */
int rtm_errno; /* 错误码 */
int rtm_use; /* 使用计数 */
u_long rtm_inits; /* 初始化标志 */
/* ... 后面跟着地址 ... */
};字段说明
| 字段 | 说明 |
|---|---|
| rtm_msglen | 消息总长度,包括头部和后面的地址 |
| rtm_version | 版本号 |
| rtm_type | 消息类型(RTM_ADD等) |
| rtm_index | 接口索引 |
| rtm_flags | 路由标志(RTF_UP等) |
| rtm_addrs | 地址位图,表示后面有哪些地址 |
| rtm_pid | 发送进程的PID |
| rtm_seq | 序列号,用于匹配请求和回复 |
| rtm_errno | 错误码,0表示成功 |
| rtm_use | 使用计数 |
| rtm_inits | 初始化标志 |
rt_msghdr是消息的固定头部。
地址位图
rtm_addrs地址位图:
- 每一位表示是否包含某个地址
- 地址按位的顺序排列在消息后面
常见的地址位:
| 位 | 宏 | 说明 |
|---|---|---|
| 0 | RTA_DST | 目的地址 |
| 1 | RTA_GATEWAY | 网关地址 |
| 2 | RTA_NETMASK | 网络掩码 |
| 3 | RTA_GENMASK | 通用掩码 |
| 4 | RTA_IFP | 接口地址 |
| 5 | RTA_IFA | 接口地址 |
| 6 | RTA_AUTHOR | 作者 |
| 7 | RTA_BRD | 广播地址或目的地址 |
位图表示后面跟着哪些地址。
消息的完整格式
完整的选路消息:
+---------------------------+
| rt_msghdr 头部 |
+---------------------------+
| 目的地址(如果有) |
+---------------------------+
| 网关地址(如果有) |
+---------------------------+
| 网络掩码(如果有) |
+---------------------------+
| ... 其他地址 ... |
+---------------------------+
- 头部是固定的rt_msghdr
- 后面跟着各个地址
- 地址的有无由rtm_addrs位图决定
- 地址按位的顺序排列
地址是变长的,由位图决定。
14.4 使用选路套接字
创建选路套接字
创建选路套接字:
int s = socket(AF_ROUTE, SOCK_RAW, 0);- 域:AF_ROUTE
- 类型:SOCK_RAW
- 协议:0(通常)
创建很简单。
发送消息(添加路由)
添加路由的步骤:
-
构造消息
- 填充rt_msghdr
- 设置类型为RTM_ADD
- 设置地址位图
- 后面跟着各个地址
-
发送消息
- 调用write或sendto
- 把消息发给内核
-
接收回复
- 内核处理后回复
- rtm_errno表示结果
- rtm_seq匹配请求
进程发请求,内核回复结果。
接收消息
接收选路消息:
-
创建套接字
- socket(AF_ROUTE, SOCK_RAW, 0)
-
接收消息
- 调用read或recvfrom
- 收到内核发送的消息
-
处理消息
- 解析rt_msghdr
- 根据类型处理
- 解析后面的地址
可以监听各种网络事件。
查询路由
查询路由(RTM_GET):
- 构造RTM_GET消息
- 填入目的地址
- 发送给内核
- 内核回复路由信息
- 解析回复的消息
用RTM_GET查询路由。
14.5 选路消息的处理
内核处理选路消息
内核收到进程消息的处理:
-
接收消息
- 从选路套接字收到
- 验证消息格式
-
解析消息
- 解析rt_msghdr
- 解析各个地址
-
根据类型处理
- RTM_ADD → 添加路由
- RTM_DELETE → 删除路由
- RTM_CHANGE → 修改路由
- RTM_GET → 查询路由
-
回复结果
- 构造回复消息
- 设置rtm_errno
- 发回给进程
内核处理请求并回复。
内核发送的消息
内核主动发送的消息:
-
接口状态变化
- RTM_IFINFO
- 接口UP/DOWN
- 接口标志变化
-
地址变化
- RTM_NEWADDR
- RTM_DELADDR
- 接口添加/删除地址
-
ICMP重定向
- RTM_REDIRECT
- 收到ICMP重定向
-
路由查找失败
- RTM_MISS
- 查找路由失败
内核会通知各种网络事件。
14.6 小结
选路套接字概述
-
什么是选路套接字
- AF_ROUTE域
- SOCK_RAW类型
- 进程和内核交换选路信息
-
用途
- route命令
- 路由守护进程
- 网络管理工具
- 监听网络变化
选路消息
-
消息类型
- RTM_ADD / RTM_DELETE / RTM_CHANGE / RTM_GET
- RTM_REDIRECT / RTM_MISS
- RTM_IFINFO / RTM_IFANNOUNCE
- RTM_NEWADDR / RTM_DELADDR
-
消息方向
- 进程 → 内核:请求操作
- 内核 → 进程:通知事件
消息格式
-
rt_msghdr头部
- rtm_msglen:总长度
- rtm_type:消息类型
- rtm_flags:标志
- rtm_addrs:地址位图
- rtm_pid / rtm_seq / rtm_errno
-
地址位图
- 每一位表示一个地址
- 地址按位的顺序排列
- RTA_DST / RTA_GATEWAY / RTA_NETMASK等
-
完整格式
- 头部 + 各个地址
- 变长消息
- 由位图决定
使用选路套接字
-
创建套接字
- socket(AF_ROUTE, SOCK_RAW, 0)
-
发送消息
- 构造消息
- write/sendto发送
- 接收回复
-
接收消息
- read/recvfrom接收
- 解析消息
- 处理事件
-
查询路由
- RTM_GET
- 发送查询
- 接收结果
选路消息的处理
-
内核处理请求
- 接收消息
- 解析消息
- 执行操作
- 回复结果
-
内核发送通知
- 接口变化
- 地址变化
- 重定向
- 查找失败
关键概念
-
选路套接字
- AF_ROUTE
- 用户态和内核态交换选路信息
- 管理选路的接口
-
选路消息
- rt_msghdr头部
- 地址位图
- 变长格式
-
消息类型
- 请求类型:增删改查
- 通知类型:各种事件
-
使用方式
- 发送请求
- 接收通知
- 路由守护进程使用