2011-09-19 166 views
11

我维护GPSD,这是一种广泛部署的开源服务守护程序,可监视GPS和其他大地测量传感器。它在IPv4和IPv6上侦听端口2947上的客户端应用程序连接。为了安全和隐私,它通常只监听环回地址,但守护进程有一个-G选项,用于监听任何地址。如何使用C套接字监听所有IPV6地址API

问题:-G选项适用于IPv4,但我无法弄清楚如何使它适用于IPv6。基于各种教程实例应该工作的方法不是,反而产生一个提示地址已被使用的错误。我正在寻求帮助来解决这个问题,从那些经验丰富的IPv6网络编程人员。

相关的代码是http://git.berlios.de/cgi-bin/gitweb.cgi?p=gpsd;a=blob;f=gpsd.c;h=ee2156caf03ca23405f57f3e04e9ef306a75686f;hb=HEAD

这段代码在IPv4的下两个-G和非-G情况下正常工作,因为很容易用netstat -l验证。

现在在“case AF_INET6:”之后查看第398行。 listen_global选项由-G设置;当错误时,代码成功。这里目前是下面的注释,从一个默默无闻的贡献者继承,上面写着这样的:

/* else */ 
     /* BAD: sat.sa_in6.sin6_addr = in6addr_any; 
    * the simple assignment will not work (except as an initializer) 
    * because sin6_addr is an array not a simple type 
    * we could do something like this: 
    * memcpy(sat.sa_in6.sin6_addr, in6addr_any, sizeof(sin6_addr)); 
    * BUT, all zeros is IPv6 wildcard, and we just zeroed the array 
    * so really nothing to do here 
    */ 

据我已经看过了各种实例教程,分配“sat.sa_in6.sin6_addr = IN6ADDR_ANY;”是(尽管评论)是正确的,并且它编译。但是,使用-G启动失败,声称监听地址已被使用。

赋值“sat.sa_in6.sin6_addr = in6addr_any;”名义上在这里正确吗?还有什么,如果有的话,我是否错过了?

+0

您是否尝试过守护进程? – jpalecek

回答

19

该地址已被使用的原因是因为在许多IPv6网络堆栈上,默认情况下IPv6套接字将同时监听IPv4和IPv6。 IPv4连接将被透明处理并映射到subset of the IPv6 space。但是,这意味着您无法绑定到与IPv4套接字相同的端口上的IPv6套接字,而无需更改IPv6套接字上的设置。合理?

只是这样做你的电话之前,bind(这是从我的一个项目采取):

int on = 1; 
if (addr->sa_family == AF_INET6) { 
    r = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); 
    if (r) 
     /* error */ 
} 

不幸的是,对于IPV6_V6ONLY跨平台没有默认值 - 这基本上意味着你总是需要除非你不关心其他平台,否则明确地打开或关闭它。 Linux的离开它关闭默认情况下Windows离开它在默认情况下...

+1

Linux默认实际来自sysctl。所以你不能依靠那里的默认。但是,如果系统管理员没有改变它,它默认关闭。 (off是IMO最合理的默认设置)。 –

+1

您的回答是正确的,我的错误已修复。谢谢。 – ESR

1

从随机Linux系统的包含文件一看,in6addr_any声明,像这样:

extern const struct in6_addr in6addr_any;  /* :: */ 
extern const struct in6_addr in6addr_loopback; /* ::1 */ 
#define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } } 

所以,也许亲近INIT阵列混淆了在GPSD源中留下该评论的人。实际的类型显然是struct in6_addr,这是可分配的。

我看了一下,发现一些暗示,如果IPv4已经在监听“任何”地址,IPv6也不能。也许这就是你咬的东西。

+0

您的诊断的第二部分是正确的(请参阅Dietrich Epp的回复),我怀疑您对第一部分也是正确的。 – ESR