Ipv6地址分类与linux内核版本

610 阅读3分钟

在实际的工作中,往往会因为内核版本的发布时间不同而造成某些协议的不支持不同步的问题。最近在实际的工作中就发现了,由于协议更新,导致的高版本内核某些协议的与低版本的协议不一致,具体体现在对ipv6 设置静态条目时 输入

route -A inet6 add in6add gw in6add 

时,如果gw的地址填1000::1,2.6版本的内核会返回invalid augment,而4.4内核版本则不会。

首先这个问题我们很容易定位到内核版本的问题,内核网络模块的版本往往随着内核版本而不同。所以我们找到相关定义的函数。 在route.c的定义ioctl接口的函数中,有一个名为ip6_route_add的函数,

switch (cmd) {
    case SIOCADDRT:
        err = ip6_route_add(&cfg);
        break;
    case SIOCDELRT:
        err = ip6_route_del(&cfg);
        break;
    default:
        err = -EINVAL;
    }

其内部调用,

rt = ip6_route_info_create(cfg);
if (IS_ERR(rt)) {
    err = PTR_ERR(rt);
    rt = NULL;
    goto out;
}

通过读这个函数可以观察到,对于前一个参数,目的地址,对它的地址类型似乎并没有做特殊的限定,只对多播,和回环做了特殊判断,例如由于回环地址会导致内核循环,所以不能设置回环地址。

而对于gw,只限定于全球单播。

    const struct in6_addr *gw_addr;
    int gwa_type;

    gw_addr = &cfg->fc_gateway;
    gwa_type = ipv6_addr_type(gw_addr);

在ipv6_addr_type中,可以观察到,对ipv6地址的类型做了特殊的判断,并且观察到高版本和低版本的区别在于给in6的默认地址类型不统一

一个默认为unicast global

一个默认为unicast reserved

这时可以确认,原因是ipv6的global的地址定义在两版本内核中不一致。查阅相关的资料后得知: 高版本的内核基于RFC3513的标准来做判断,而低版本的内核则基于老版规则进行判断。

对于RFC2373:

Allocation                            Prefix         Fraction of
                                      (binary)       Address Space
-----------------------------------   --------       -------------
Reserved                              0000 0000      1/256
Unassigned                            0000 0001      1/256

Reserved for NSAP Allocation          0000 001       1/128
Reserved for IPX Allocation           0000 010       1/128

Unassigned                            0000 011       1/128
Unassigned                            0000 1         1/32
Unassigned                            0001           1/16

Aggregatable Global Unicast Addresses 001            1/8
Unassigned                            010            1/8
Unassigned                            011            1/8
Unassigned                            100            1/8
Unassigned                            101            1/8
Unassigned                            110            1/8

Unassigned                            1110           1/16
Unassigned                            1111 0         1/32
Unassigned                            1111 10        1/64
Unassigned                            1111 110       1/128
Unassigned                            1111 1110 0    1/512

Link-Local Unicast Addresses          1111 1110 10   1/1024
Site-Local Unicast Addresses          1111 1110 11   1/1024

Multicast Addresses                   1111 1111      1/256

对于RFC3513中的地址划分:

  Address type         Binary prefix        IPv6 notation   Section
  ------------         -------------        -------------   -------
  Unspecified          00...0  (128 bits)   ::/128          2.5.2
  Loopback             00...1  (128 bits)   ::1/128         2.5.3
   Multicast            11111111             FF00::/8        2.7
   Link-local unicast   1111111010           FE80::/10       2.5.6
   Site-local unicast   1111111011           FEC0::/10       2.5.6
   Global unicast       (everything else)

可见出现此问题的原因。

扩展:

在RFC3513中虽然放开了对全球单播地址的定义,却仍然规定了IANA的空间分配权限只局限与001开头的地址范围,也就是2、3开头。

虽然放开了定义,但是在RFC3513中也规定了地址格式
n bits	    m bits	    123-n-m bits
Prefix	    Sub-net id	    Interface id
其中要求interface i但是64位,即n+m = 64,所以在RFC3587中给出了新格式:
n bits	    64-n bits	    64 bits
Prefix	    Sub-net id	    Interface id