get local ipv6 addresses on linux
authorKen Raeburn <raeburn@mit.edu>
Sun, 10 Feb 2002 07:07:19 +0000 (07:07 +0000)
committerKen Raeburn <raeburn@mit.edu>
Sun, 10 Feb 2002 07:07:19 +0000 (07:07 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@14138 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/krb5/os/ChangeLog
src/lib/krb5/os/localaddr.c

index b0fa0bc7f47970de93e0732cb0df76024d82d25f..dc12af652782bdfd320c355c6bc0af0ea48d1fcc 100644 (file)
@@ -1,3 +1,12 @@
+2002-02-10  Ken Raeburn  <raeburn@mit.edu>
+
+       * localaddr.c (LINUX_IPV6_HACK) [__linux__&& KRB5_USE_INET6]:
+       Define macro.
+       (get_linux_ipv6_addrs) [LINUX_IPV6_HACK]: New function, reads
+       addresses from /proc/net/if_inet6.
+       (foreach_localaddr) [!HAVE_IFADDRS_H && !SIOCGLIFNUM &&
+       LINUX_IPV6_HACK]: Include ipv6 addresses.
+
 2002-01-09  Ken Raeburn  <raeburn@mit.edu>
 
        * hst_realm.c (EAFNOSUPPORT): On Windows, translate to
index fc40d7e9e1ea3c9cc148b64d5d6f587eb5232512..e315a7696b42474e16c6b8ceee7211571349d4e6 100644 (file)
 #include <stddef.h>
 #include <ctype.h>
 
+#if defined(__linux__) && defined(KRB5_USE_INET6)
+#define LINUX_IPV6_HACK
+#endif
+
 #if defined(TEST) || defined(DEBUG)
 # define FAI_PREFIX krb5int
 # include "fake-addrinfo.c"
@@ -268,6 +272,68 @@ get_lifconf (int af, int s, size_t *lenp, /*@out@*/ char *buf)
 }
 #endif
 
+#ifdef LINUX_IPV6_HACK
+/* Hack workaround until they get a real interface for this.  */
+struct linux_ipv6_addr_list {
+    struct sockaddr_in6 addr;
+    struct linux_ipv6_addr_list *next;
+};
+static struct linux_ipv6_addr_list *
+get_linux_ipv6_addrs ()
+{
+    struct linux_ipv6_addr_list *lst = 0;
+    FILE *f;
+
+    /* _PATH_PROCNET_IFINET6 */
+    f = fopen("/proc/net/if_inet6", "r");
+    if (f) {
+       char ifname[21];
+       int idx, pfxlen, scope, dadstat;
+       struct in6_addr a6;
+       struct linux_ipv6_addr_list *nw;
+       int i, addrbyte[16];
+
+       while (fscanf(f,
+                     "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x"
+                     " %2x %2x %2x %2x %20s\n",
+                     &addrbyte[0], &addrbyte[1], &addrbyte[2], &addrbyte[3],
+                     &addrbyte[4], &addrbyte[5], &addrbyte[6], &addrbyte[7],
+                     &addrbyte[8], &addrbyte[9], &addrbyte[10], &addrbyte[11],
+                     &addrbyte[12], &addrbyte[13], &addrbyte[14],
+                     &addrbyte[15],
+                     &idx, &pfxlen, &scope, &dadstat, ifname) != EOF) {
+           for (i = 0; i < 16; i++)
+               a6.s6_addr[i] = addrbyte[i];
+           if (scope != 0)
+               continue;
+#if 0
+           switch (scope) {
+           case 0:
+           default:
+               break;
+           case IPV6_ADDR_LINKLOCAL:
+           case IPV6_ADDR_SITELOCAL:
+           case IPV6_ADDR_COMPATv4:
+           case IPV6_ADDR_LOOPBACK:
+               continue;
+           }
+#endif
+           nw = malloc (sizeof (struct linux_ipv6_addr_list));
+           if (nw == 0)
+               continue;
+           memset (nw, 0, sizeof (*nw));
+           nw->addr.sin6_addr = a6;
+           nw->addr.sin6_family = AF_INET6;
+           /* Ignore other fields, we don't actually use them here.  */
+           nw->next = lst;
+           lst = nw;
+       }
+       fclose (f);
+    }
+    return lst;
+}
+#endif
+
 /* Return value is errno if internal stuff failed, otherwise zero,
    even in the case where a called function terminated the iteration.
 
@@ -508,6 +574,10 @@ punt:
 #ifdef SIOCGIFNUM
     int numifs = -1;
 #endif
+#ifdef LINUX_IPV6_HACK
+    struct linux_ipv6_addr_list *linux_ipv6_addrs = get_linux_ipv6_addrs ();
+    struct linux_ipv6_addr_list *lx_v6;
+#endif
 
     s = socket (USE_AF, USE_TYPE, USE_PROTO);
     if (s < 0)
@@ -622,12 +692,18 @@ punt:
        /*@=moduncon@*/
     }
 
+#ifdef LINUX_IPV6_HACK
+    for (lx_v6 = linux_ipv6_addrs; lx_v6; lx_v6 = lx_v6->next)
+       if ((*pass1fn) (data, (struct sockaddr *) &lx_v6->addr))
+           goto punt;
+#endif
+
     /*@-moduncon@*/
     if (betweenfn != NULL && (*betweenfn)(data))
        goto punt;
     /*@=moduncon@*/
 
-    if (pass2fn)
+    if (pass2fn) {
        for (i = 0; i < n; i+= ifreq_size(*ifr) ) {
            ifr = (struct ifreq *)((caddr_t) buf+i);
 
@@ -640,11 +716,24 @@ punt:
                goto punt;
            /*@=moduncon@*/
        }
+#ifdef LINUX_IPV6_HACK
+       for (lx_v6 = linux_ipv6_addrs; lx_v6; lx_v6 = lx_v6->next)
+           if ((*pass2fn) (data, (struct sockaddr *) &lx_v6->addr))
+               goto punt;
+#endif
+    }
  punt:
     /*@-moduncon@*/
     closesocket(s);
     /*@=moduncon@*/
     free (buf);
+#ifdef LINUX_IPV6_HACK
+    while (linux_ipv6_addrs) {
+       lx_v6 = linux_ipv6_addrs->next;
+       free (linux_ipv6_addrs);
+       linux_ipv6_addrs = lx_v6;
+    }
+#endif
 
     return retval;
 #endif /* not HAVE_IFADDRS_H */