]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 715] Fix multicast issues under Linux
authorHarlan Stenn <stenn@ntp.org>
Mon, 9 Oct 2006 10:35:20 +0000 (06:35 -0400)
committerHarlan Stenn <stenn@ntp.org>
Mon, 9 Oct 2006 10:35:20 +0000 (06:35 -0400)
bk: 452a25e8rpWTsmlx5ZpCGCWqxsvbNQ

NEWS
libisc/ifiter_ioctl.c

diff --git a/NEWS b/NEWS
index 0d14d891a5761923e7e6af5089c24445cd4c5eb1..6717868f721a9e345daaed33b8d036fe6f598ee1 100644 (file)
--- 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.
index 9bb07baf6d169c6d866d72364a23c3ede983683e..e069560b0e4978535a1337e62acd4fa0f48b4acf 100644 (file)
@@ -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)
+        * <addr6:32> <ifindex:2> <prefix:2> <scope:2> <flags:2> <name:8>
+        */
        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;