在实际的工作中,往往会因为内核版本的发布时间不同而造成某些协议的不支持不同步的问题。最近在实际的工作中就发现了,由于协议更新,导致的高版本内核某些协议的与低版本的协议不一致,具体体现在对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