OpenBSD: fix lookup of network interfaces
authorAntoine Verheijen <antoine@ualberta.ca>
Mon, 8 Feb 2010 22:23:03 +0000 (15:23 -0700)
committerDerrick Brashear <shadow@dementia.org>
Tue, 9 Feb 2010 16:26:23 +0000 (08:26 -0800)
Starting with OpenBSD 4.2, the interface list returned by sysctl using
NET_RT_IFLIST contains multiple versions of the data. This really
messes up the rx_getAllAddr_internal() routine that returns a list of
valid interfaces for the system (to the point where none are returned).

This change adds a routine that cleans up the data returned by sysctl
so it returns only a single (the most current) version of the data.
That stops afsd (among others) from being cranky when it starts up.

Change-Id: Ief1df0d2c3eb241c45b439a785ddb67d3afe992c
Reviewed-on: http://gerrit.openafs.org/1274
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>
(cherry picked from commit d06bc699f2e3848da8ce9a7fa20ac99db630bd1b)
Change-Id: I3c1f0b96b579784c6702ade34e33a3348fe82885
Reviewed-on: http://gerrit.openafs.org/1259

src/rx/rx_getaddr.c

index 76c3f35..8ee4ce2 100644 (file)
@@ -142,6 +142,32 @@ rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
 ** the buffer has to be passed in by the caller
 */
 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+#if defined(AFS_OBSD42_ENV)
+void
+ifm_fixversion(char *buffer, size_t *size) {
+    struct if_msghdr *ifm;
+    char *b = buffer;
+    char *s, *t;
+
+    if ((t = malloc(*size)) != NULL) {
+       memcpy(t, buffer, *size);
+
+       for (s = t; s < t + *size; s += ifm->ifm_msglen) {
+           ifm = (struct if_msghdr *)s;
+
+           if (ifm->ifm_version == RTM_VERSION) {
+               memcpy(b, ifm, ifm->ifm_msglen);
+               b += ifm->ifm_msglen;
+           }
+       }
+
+       free(t);
+
+       *size = b - buffer;
+    }
+}
+#endif
+
 int
 rx_getAllAddr_internal(afs_int32 buffer[], int maxSize, int loopbacks)
 {
@@ -168,6 +194,9 @@ rx_getAllAddr_internal(afs_int32 buffer[], int maxSize, int loopbacks)
        free(buf);
        return 0;
     }
+#if defined(AFS_OBSD42_ENV)
+    ifm_fixversion(buf, &needed);
+#endif
     lim = buf + needed;
     next = buf;
     while (next < lim) {
@@ -252,6 +281,9 @@ rxi_getAllAddrMaskMtu(afs_int32 addrBuffer[], afs_int32 maskBuffer[],
        free(buf);
        return 0;
     }
+#if defined(AFS_OBSD42_ENV)
+    ifm_fixversion(buf, &needed);
+#endif
     s = socket(PF_INET, SOCK_DGRAM, 0);
     if (s < 0)
        return 0;