如果启用了IPv6的主机具有多个全局作用域地址,如何通过编程方式确定bind()
的首选地址
示例地址列表:
eth0 Link encap:Ethernet HWaddr 00:14:5e:bd:6d:da
inet addr:10.6.28.31 Bcast:10.6.28.255 Mask:255.255.255.0
inet6 addr: 2002:dce8:d28e:0:214:5eff:febd:6dda/64 Scope:Global
inet6 addr: fe80::214:5eff:febd:6dda/64 Scope:Link
inet6 addr: 2002:dce8:d28e::31/64 Scope:Global
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
在Solaris上,您可以使用接口标志来指示首选地址,并且可以通过SIOCGLIFCONF
以编程方式使用该地址
/usr/include/net/if.h:
#define IFF_PREFERRED 0x0400000000 /* Prefer as source address */
如接口列表所示:
eri0: flags=2104841<UP,RUNNING,MULTICAST,DHCP,ROUTER,IPv6> mtu 1500 index 2
inet6 fe80::203:baff:fe4e:6cc8/10
eri0:1: flags=402100841<UP,RUNNING,MULTICAST,ROUTER,IPv6,PREFERRED> mtu 1500 index 2
inet6 2002:dce8:d28e::36/64
不过,这不能移植到OSX、Linux、FreeBSD或Windows上。不过,从管理员的角度来看,基于UUID的适配器名称(取决于Windows版本)完全没有用,因此Windows很容易被释放。
For Linux this article详细介绍了如何通过修改参数preferred_lft
(其中lft
是“生命周期”的缩写)来加权内核的选择过程。但是,在SIOCGIFCONF
或getifaddrs()
的结果中,这个设置看起来并不方便。
因此,我希望绑定到eth0
、eri0
或任何可用的接口名称。选择有点严酷:
SO_BINDTODEVICE
绑定到适配器。这需要Linux上的CAP_NET_RAW
系统功能,对于适配器上的第一个IPv6接口的administrators.对于选项#6,我希望您通常更聪明,并采取这样的方法:如果只有链路本地作用域地址可用,则绑定到该地址,否则只绑定到可用的全局链接作用域地址。
当连接到另一台主机时,可以使用RFC 3484,但如您所见,所有选择都取决于与目的地址的匹配:
在某些情况下,我们可以在这里使用#7,但在上面的接口示例中,两个全局范围的接口都有64位前缀长度。
RFC 3484有以下相关行:
IPv6寻址体系结构5允许多个单播
要分配给接口的地址。这些地址可能具有
不同的可达性范围(本地链路、本地站点或全局)。
这些地址也可能是“首选”或“不推荐”的6。
链接是到RFC 2462的,类似地展开:
首选地址-分配给接口的地址,其使用不受上层协议的限制。优选地址可以用作从接口发送(或发往)的分组的源(或目的)地址。
但是没有以编程方式获取此详细信息的方法。
Props to RFC,它公开了一个Win32 SIO_ADDRESS_LIST_SORT,允许开发人员不仅使用RFC3484排序,而且考虑到任何系统管理员覆盖。Linux在getaddrinfo()
中有用于RFC3484排序的/etc/gai.conf
,但没有用于直接访问排序的API。Solaris有ipaddrsel
命令。OSX在10.7版本中加入了ip6addrctl
来效仿FreeBSD。
edit:在这个附加的IETF草案文档中列出并引用了与RFC3484排序有关的一些问题:
https://datatracker.ietf.org/doc/html/draft-axu-addr-sel-01
例如,
Solaris会为每个新的
分配给物理接口的地址。所以if_index也可以是
用于唯一标识特定于源地址的路由表
那个平台。其他操作系统的工作方式并不相同。
作者喜欢Solaris的方法,即为每个额外的IPv6接口赋予一个新的别名,这样eri0
将成为链路本地作用域地址,并且必须指定eri0:1
或eri0:2
等才能使用全局作用域地址。
显然,虽然这是一个很好的想法,但在相当长的一段时间内,人们不能指望看到其他操作系统发生变化。
发布于 2013-08-04 15:22:02
我不确定这是不是你要找的方向,但是...
仔细查看linux下的iproute包的ip
代码(ip/ipaddress.c
),可以发现ip
命令从struct ifaddrmsg
、成员ifa_flags
中挖掘出诸如primary
和secondary
之类的接口标志。ifaddmsg
似乎是通过man 7 netlink
中记录的struct nlmsghdr
获得的,并通过sendmsg
和recvmsg
与内核的交互使用,总体上听起来像是王室的痛苦,但至少是编程上的。主要的和次要的是否足够有用是另一个问题。
https://stackoverflow.com/questions/7202316
复制相似问题