第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_vhl1字节版本(4位)+ 首部长度(4位)
ip_tos1字节服务类型
ip_len2字节总长度(首部+数据)
ip_id2字节标识(分片用)
ip_off2字节标志(3位)+ 片偏移(13位)
ip_ttl1字节生存时间
ip_p1字节协议(TCP=6, UDP=17, ICMP=1等)
ip_sum2字节首部检验和
ip_src4字节源IP地址
ip_dst4字节目的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输入的验证:

  1. 版本验证

    • 必须是IPv4(版本=4)
    • 不是则丢弃
  2. 首部长度验证

    • 至少20字节
    • 不超过总长度
  3. 总长度验证

    • 至少和首部一样长
    • 不超过接收的长度
  4. 检验和验证

    • 计算检验和
    • 必须为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
调用接口输出

源地址选择

源地址的选择:

  1. 如果应用指定了源地址,用指定的
  2. 否则根据输出接口选择
    • 用输出接口的地址作为源地址
  3. 多宿主主机的情况
    • 选择最合适的地址

源地址通常是输出接口的地址。


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首部

  1. 结构

    • 版本、首部长度
    • 服务类型、总长度
    • 标识、标志、片偏移
    • TTL、协议、检验和
    • 源地址、目的地址
    • 选项(可选)
  2. ip结构

    • 内核中的C结构
    • 对应IP首部
  3. 常用宏

    • IP_V、IP_HL
    • IP_OFF
    • IP_MF、IP_DF

IP输入处理

  1. ip_input

    • IP输入的入口
    • 从链路层接收
  2. 验证

    • 版本、长度
    • 检验和
    • 不通过就丢弃
  3. 分用

    • 根据协议号
    • 交给上层协议

IP输出处理

  1. ip_output

    • IP输出的入口
    • 上层调用
  2. 源地址选择

    • 指定的或接口地址
  3. TTL设置

    • 默认值
    • 应用可修改

IP转发

  1. ip_forward

    • 转发功能
    • 路由器功能
  2. TTL处理

    • 减1
    • 为0则丢弃
  3. 检验和更新

    • 增量计算
    • 提高效率

IP选项

  1. 选项类型

    • 记录路径
    • 时间戳
    • 源站选路
    • 等等
  2. 处理时机

    • 输入时
    • 输出时
    • 转发时

关键概念

  1. IP首部

    • 20字节基本首部
    • 选项最多40字节
  2. ip_input

    • 输入处理
    • 验证、分用
  3. ip_output

    • 输出处理
    • 构造首部、选路
  4. ip_forward

    • 转发处理
    • TTL减1
  5. IP选项

    • 扩展IP功能
    • 各种选项

网际协议