From: Harlan Stenn Date: Mon, 9 Oct 2006 10:35:20 +0000 (-0400) Subject: [Bug 715] Fix multicast issues under Linux X-Git-Tag: NTP_4_2_3P53~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=53693ff24e3b9a7929de94629faad2b277f917be;p=thirdparty%2Fntp.git [Bug 715] Fix multicast issues under Linux bk: 452a25e8rpWTsmlx5ZpCGCWqxsvbNQ --- diff --git a/NEWS b/NEWS index 0d14d891a..6717868f7 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,4 @@ +* [Bug 715] Fix a multicast issue under Linux. * [Bug 690] Fix a Windows DNS lookup buffer overflow. * [Bug 670] Resolved a Windows issue with the dynamic interface rescan code. * K&R C support is being deprecated. diff --git a/libisc/ifiter_ioctl.c b/libisc/ifiter_ioctl.c index 9bb07baf6..e069560b0 100644 --- a/libisc/ifiter_ioctl.c +++ b/libisc/ifiter_ioctl.c @@ -446,8 +446,10 @@ static isc_result_t linux_if_inet6_current(isc_interfaceiter_t *iter) { char address[33]; char name[IF_NAMESIZE+1]; + char strbuf[ISC_STRERRORSIZE]; struct in6_addr addr6; - int ifindex, prefix, flag3, flag4; + struct ifreq ifreq; + int ifindex, prefix, scope, flags; int res; unsigned int i; @@ -459,8 +461,13 @@ linux_if_inet6_current(isc_interfaceiter_t *iter) { return (ISC_R_FAILURE); } + /* + * Format for /proc/net/if_inet6: + * (see iface_proc_info() in net/ipv6/addrconf.c) + * + */ res = sscanf(iter->entry, "%32[a-f0-9] %x %x %x %x %16s\n", - address, &ifindex, &prefix, &flag3, &flag4, name); + address, &ifindex, &prefix, &scope, &flags, name); if (res != 6) { UNEXPECTED_ERROR(__FILE__, __LINE__, "/proc/net/if_inet6:sscanf() -> %d (expected 6)", @@ -480,12 +487,43 @@ linux_if_inet6_current(isc_interfaceiter_t *iter) { addr6.s6_addr[i] = byte; } iter->current.af = AF_INET6; - iter->current.flags = INTERFACE_F_UP; - isc_netaddr_fromin6(&iter->current.address, &addr6); - if (isc_netaddr_islinklocal(&iter->current.address)) { - isc_netaddr_setzone(&iter->current.address, - (isc_uint32_t)ifindex); + /* iter->current.ifindex = ifindex; */ + iter->current.flags = 0; + + memset(&ifreq, 0, sizeof(ifreq)); + INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name)); + strncpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name)); + + if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "%s: getting interface flags: %s", + ifreq.ifr_name, strbuf); + return (ISC_R_IGNORE); } + + if ((ifreq.ifr_flags & IFF_UP) != 0) + iter->current.flags |= INTERFACE_F_UP; +#ifdef IFF_POINTOPOINT + if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0) + iter->current.flags |= INTERFACE_F_POINTTOPOINT; +#endif + if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0) + iter->current.flags |= INTERFACE_F_LOOPBACK; + if ((ifreq.ifr_flags & IFF_BROADCAST) != 0) + iter->current.flags |= INTERFACE_F_BROADCAST; +#ifdef IFF_MULTICAST + if ((ifreq.ifr_flags & IFF_MULTICAST) != 0) + iter->current.flags |= INTERFACE_F_MULTICAST; +#endif + + /* + * enable_multicast_if() requires scopeid for setsockopt, + * so associate address with their corresponding ifindex. + */ + isc_netaddr_fromin6(&iter->current.address, &addr6); + isc_netaddr_setzone(&iter->current.address, (isc_uint32_t)ifindex); + for (i = 0; i < 16; i++) { if (prefix > 8) { addr6.s6_addr[i] = 0xff;