第14章 选路套接字

所属:TCP/IP详解 卷2:实现 来源:TCP/IP详解 卷2:实现

本章描述选路套接字(routing socket)的实现,包括选路消息格式、消息类型、选路套接字的使用等。


14.1 引言

什么是选路套接字

选路套接字(routing socket):

  • AF_ROUTE域
  • SOCK_RAW类型
  • 进程和内核之间交换选路信息
  • 可以添加、删除、查询路由
  • 可以接收选路变化通知

选路套接字是用户态和内核态交换选路信息的接口。


选路套接字的用途

主要用途:

  1. route命令

    • 添加、删除、修改、查询路由
    • 最常用的工具
  2. 路由守护进程

    • routed、gated等
    • 运行路由协议
    • 动态更新选路表
  3. 网络管理工具

    • 监控选路表变化
    • 统计路由信息
  4. 监听网络变化

    • 接口状态变化
    • 地址变化
    • 路由变化

选路套接字是管理选路的标准接口。


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地址位图:

  • 每一位表示是否包含某个地址
  • 地址按位的顺序排列在消息后面

常见的地址位:

位宏说明
0RTA_DST目的地址
1RTA_GATEWAY网关地址
2RTA_NETMASK网络掩码
3RTA_GENMASK通用掩码
4RTA_IFP接口地址
5RTA_IFA接口地址
6RTA_AUTHOR作者
7RTA_BRD广播地址或目的地址

位图表示后面跟着哪些地址。


消息的完整格式

完整的选路消息:

+---------------------------+
|      rt_msghdr 头部       |
+---------------------------+
|      目的地址(如果有)    |
+---------------------------+
|      网关地址(如果有)    |
+---------------------------+
|      网络掩码(如果有)    |
+---------------------------+
|      ... 其他地址 ...      |
+---------------------------+
  • 头部是固定的rt_msghdr
  • 后面跟着各个地址
  • 地址的有无由rtm_addrs位图决定
  • 地址按位的顺序排列

地址是变长的,由位图决定。


14.4 使用选路套接字

创建选路套接字

创建选路套接字:

int s = socket(AF_ROUTE, SOCK_RAW, 0);
  • 域:AF_ROUTE
  • 类型:SOCK_RAW
  • 协议:0(通常)

创建很简单。


发送消息(添加路由)

添加路由的步骤:

  1. 构造消息

    • 填充rt_msghdr
    • 设置类型为RTM_ADD
    • 设置地址位图
    • 后面跟着各个地址
  2. 发送消息

    • 调用write或sendto
    • 把消息发给内核
  3. 接收回复

    • 内核处理后回复
    • rtm_errno表示结果
    • rtm_seq匹配请求

进程发请求,内核回复结果。


接收消息

接收选路消息:

  1. 创建套接字

    • socket(AF_ROUTE, SOCK_RAW, 0)
  2. 接收消息

    • 调用read或recvfrom
    • 收到内核发送的消息
  3. 处理消息

    • 解析rt_msghdr
    • 根据类型处理
    • 解析后面的地址

可以监听各种网络事件。


查询路由

查询路由(RTM_GET):

  1. 构造RTM_GET消息
  2. 填入目的地址
  3. 发送给内核
  4. 内核回复路由信息
  5. 解析回复的消息

用RTM_GET查询路由。


14.5 选路消息的处理

内核处理选路消息

内核收到进程消息的处理:

  1. 接收消息

    • 从选路套接字收到
    • 验证消息格式
  2. 解析消息

    • 解析rt_msghdr
    • 解析各个地址
  3. 根据类型处理

    • RTM_ADD → 添加路由
    • RTM_DELETE → 删除路由
    • RTM_CHANGE → 修改路由
    • RTM_GET → 查询路由
  4. 回复结果

    • 构造回复消息
    • 设置rtm_errno
    • 发回给进程

内核处理请求并回复。


内核发送的消息

内核主动发送的消息:

  1. 接口状态变化

    • RTM_IFINFO
    • 接口UP/DOWN
    • 接口标志变化
  2. 地址变化

    • RTM_NEWADDR
    • RTM_DELADDR
    • 接口添加/删除地址
  3. ICMP重定向

    • RTM_REDIRECT
    • 收到ICMP重定向
  4. 路由查找失败

    • RTM_MISS
    • 查找路由失败

内核会通知各种网络事件。


14.6 小结

选路套接字概述

  1. 什么是选路套接字

    • AF_ROUTE域
    • SOCK_RAW类型
    • 进程和内核交换选路信息
  2. 用途

    • route命令
    • 路由守护进程
    • 网络管理工具
    • 监听网络变化

选路消息

  1. 消息类型

    • RTM_ADD / RTM_DELETE / RTM_CHANGE / RTM_GET
    • RTM_REDIRECT / RTM_MISS
    • RTM_IFINFO / RTM_IFANNOUNCE
    • RTM_NEWADDR / RTM_DELADDR
  2. 消息方向

    • 进程 → 内核:请求操作
    • 内核 → 进程:通知事件

消息格式

  1. rt_msghdr头部

    • rtm_msglen:总长度
    • rtm_type:消息类型
    • rtm_flags:标志
    • rtm_addrs:地址位图
    • rtm_pid / rtm_seq / rtm_errno
  2. 地址位图

    • 每一位表示一个地址
    • 地址按位的顺序排列
    • RTA_DST / RTA_GATEWAY / RTA_NETMASK等
  3. 完整格式

    • 头部 + 各个地址
    • 变长消息
    • 由位图决定

使用选路套接字

  1. 创建套接字

    • socket(AF_ROUTE, SOCK_RAW, 0)
  2. 发送消息

    • 构造消息
    • write/sendto发送
    • 接收回复
  3. 接收消息

    • read/recvfrom接收
    • 解析消息
    • 处理事件
  4. 查询路由

    • RTM_GET
    • 发送查询
    • 接收结果

选路消息的处理

  1. 内核处理请求

    • 接收消息
    • 解析消息
    • 执行操作
    • 回复结果
  2. 内核发送通知

    • 接口变化
    • 地址变化
    • 重定向
    • 查找失败

关键概念

  1. 选路套接字

    • AF_ROUTE
    • 用户态和内核态交换选路信息
    • 管理选路的接口
  2. 选路消息

    • rt_msghdr头部
    • 地址位图
    • 变长格式
  3. 消息类型

    • 请求类型:增删改查
    • 通知类型:各种事件
  4. 使用方式

    • 发送请求
    • 接收通知
    • 路由守护进程使用

选路套接字