So ppp(8) did insane routing message handling in its sysctl handlers. The
worst thing about them are that their actually not needed and better
replaced with libc functions (getifaddrs and if_nametoindex).

This diff is not haevily tested (my last ppp usage is years ago) so I'm
hopeing people with ppp(8) issues could give this a whirl and see if it
fixes the problems.
-- 
:wq Claudio

Index: ppp/arp.c
===================================================================
RCS file: /cvs/src/usr.sbin/ppp/ppp/arp.c,v
retrieving revision 1.15
diff -u -p -r1.15 arp.c
--- ppp/arp.c   6 May 2008 06:34:10 -0000       1.15
+++ ppp/arp.c   30 Jun 2009 14:52:53 -0000
@@ -38,6 +38,7 @@
 #include <sys/un.h>
 
 #include <errno.h>
+#include <ifaddrs.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -229,93 +230,58 @@ int
 arp_EtherAddr(int s, struct in_addr ipaddr, struct sockaddr_dl *hwaddr,
               int verbose)
 {
-  int mib[6], skip;
-  size_t needed;
-  char *buf, *ptr, *end;
-  struct if_msghdr *ifm;
-  struct ifa_msghdr *ifam;
-  struct sockaddr_dl *dl;
-  struct sockaddr *sa[RTAX_MAX];
-
-  mib[0] = CTL_NET;
-  mib[1] = PF_ROUTE;
-  mib[2] = 0;
-  mib[3] = 0;
-  mib[4] = NET_RT_IFLIST;
-  mib[5] = 0;
-
-  if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
-    log_Printf(LogERROR, "arp_EtherAddr: sysctl: estimate: %s\n",
-              strerror(errno));
-    return 0;
-  }
-
-  if ((buf = malloc(needed)) == NULL)
-    return 0;
+  struct sockaddr_dl *dl = NULL;
+  struct ifaddrs *ifa, *ifap;
+  int skip = 1;
 
-  if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
-    free(buf);
+  if (getifaddrs(&ifap) != 0) {
+    log_Printf(LogERROR, "arp_EtherAddr: getifaddrs: %s\n", strerror(errno));
     return 0;
   }
-  end = buf + needed;
 
-  ptr = buf;
-  while (ptr < end) {
-    ifm = (struct if_msghdr *)ptr;             /* On if_msghdr */
-    if (ifm->ifm_type != RTM_IFINFO)
-      break;
-    ptr += ifm->ifm_msglen;
-    if (ifm->ifm_version != RTM_VERSION)
-      continue;
-    dl = (struct sockaddr_dl *)(ifm + 1);      /* Single _dl at end */
-    skip = (ifm->ifm_flags & (IFF_UP | IFF_BROADCAST | IFF_POINTOPOINT |
+  for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
+    if (ifa->ifa_addr->sa_family == AF_LINK) {
+      dl = (struct sockaddr_dl *)ifa->ifa_addr;
+      skip = (ifa->ifa_flags & (IFF_UP | IFF_BROADCAST | IFF_POINTOPOINT |
             IFF_NOARP | IFF_LOOPBACK)) != (IFF_UP | IFF_BROADCAST);
-    while (ptr < end) {
-      ifam = (struct ifa_msghdr *)ptr; /* Next ifa_msghdr (alias) */
-      if (ifam->ifam_type != RTM_NEWADDR)      /* finished ? */
-        break;
-      ptr += ifam->ifam_msglen;
-      if (ifam->ifam_version != RTM_VERSION)
-        continue;
-      if (skip || (ifam->ifam_addrs & (RTA_NETMASK|RTA_IFA)) !=
-          (RTA_NETMASK|RTA_IFA))
-        continue;
-      /* Found a candidate.  Do the addresses match ? */
-      if (log_IsKept(LogDEBUG) &&
-          ptr == (char *)ifm + ifm->ifm_msglen + ifam->ifam_msglen)
-        log_Printf(LogDEBUG, "%.*s interface is a candidate for proxy\n",
-                  dl->sdl_nlen, dl->sdl_data);
-
-      iface_ParseHdr(ifam, sa);
-
-      if (sa[RTAX_IFA]->sa_family == AF_INET) {
-        struct sockaddr_in *ifa, *netmask;
-
-        ifa = (struct sockaddr_in *)sa[RTAX_IFA];
-        netmask = (struct sockaddr_in *)sa[RTAX_NETMASK];
-
-        if (log_IsKept(LogDEBUG)) {
-          char a[16];
-
-          strncpy(a, inet_ntoa(netmask->sin_addr), sizeof a - 1);
-          a[sizeof a - 1] = '\0';
-          log_Printf(LogDEBUG, "Check addr %s, mask %s\n",
-                     inet_ntoa(ifa->sin_addr), a);
-        }
-
-        if ((ifa->sin_addr.s_addr & netmask->sin_addr.s_addr) ==
-            (ipaddr.s_addr & netmask->sin_addr.s_addr)) {
-          log_Printf(verbose ? LogPHASE : LogDEBUG,
-                     "Found interface %.*s for %s\n", dl->sdl_nlen,
-                     dl->sdl_data, inet_ntoa(ipaddr));
-          memcpy(hwaddr, dl, dl->sdl_len);
-          free(buf);
-          return 1;
-        }
+      continue;
+    }
+    if (skip)
+      /* Skip unusable interface */
+      continue;
+
+    /* Found a candidate.  Do the addresses match ? */
+    if (log_IsKept(LogDEBUG))
+      log_Printf(LogDEBUG, "%.*s interface is a candidate for proxy\n",
+                dl->sdl_nlen, dl->sdl_data);
+
+    if (ifa->ifa_addr->sa_family == AF_INET) {
+      struct sockaddr_in *addr, *netmask;
+
+      addr = (struct sockaddr_in *)ifa->ifa_addr;
+      netmask = (struct sockaddr_in *)ifa->ifa_netmask;
+
+      if (log_IsKept(LogDEBUG)) {
+        char a[16];
+
+        strncpy(a, inet_ntoa(netmask->sin_addr), sizeof a - 1);
+        a[sizeof a - 1] = '\0';
+        log_Printf(LogDEBUG, "Check addr %s, mask %s\n",
+                   inet_ntoa(addr->sin_addr), a);
+      }
+
+      if ((addr->sin_addr.s_addr & netmask->sin_addr.s_addr) ==
+          (ipaddr.s_addr & netmask->sin_addr.s_addr)) {
+        log_Printf(verbose ? LogPHASE : LogDEBUG,
+                   "Found interface %.*s for %s\n", dl->sdl_nlen,
+                   dl->sdl_data, inet_ntoa(ipaddr));
+        memcpy(hwaddr, dl, dl->sdl_len);
+        freeifaddrs(ifap);
+        return 1;
       }
     }
   }
-  free(buf);
+  freeifaddrs(ifap);
 
   return 0;
 }
Index: ppp/iface.c
===================================================================
RCS file: /cvs/src/usr.sbin/ppp/ppp/iface.c,v
retrieving revision 1.28
diff -u -p -r1.28 iface.c
--- ppp/iface.c 25 Jun 2009 15:59:28 -0000      1.28
+++ ppp/iface.c 30 Jun 2009 14:54:08 -0000
@@ -44,6 +44,7 @@
 #include <sys/un.h>
 
 #include <errno.h>
+#include <ifaddrs.h>
 #include <string.h>
 #include <stdarg.h>
 #include <stdio.h>
@@ -90,114 +91,64 @@ static const struct in6_addr in6mask128 
 struct iface *
 iface_Create(const char *name)
 {
-  int mib[6], maxtries, err;
-  size_t needed, namelen;
-  char *buf, *ptr, *end;
-  struct if_msghdr *ifm;
-  struct ifa_msghdr *ifam;
+  size_t namelen;
   struct sockaddr_dl *dl;
-  struct sockaddr *sa[RTAX_MAX];
+  struct ifaddrs *ifap, *ifa;
   struct iface *iface;
   struct iface_addr *addr;
 
-  mib[0] = CTL_NET;
-  mib[1] = PF_ROUTE;
-  mib[2] = 0;
-  mib[3] = 0;
-  mib[4] = NET_RT_IFLIST;
-  mib[5] = 0;
-
-  maxtries = 20;
-  err = 0;
-  do {
-    if (maxtries-- == 0 || (err && err != ENOMEM)) {
-      fprintf(stderr, "iface_Create: sysctl: %s\n", strerror(err));
-      return NULL;
-    }
-
-    if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
-      fprintf(stderr, "iface_Create: sysctl: estimate: %s\n",
-                strerror(errno));
-      return NULL;
-    }
-
-    if ((buf = (char *)malloc(needed)) == NULL) {
-      fprintf(stderr, "iface_Create: malloc failed: %s\n", strerror(errno));
-      return NULL;
-    }
-
-    if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
-      err = errno;
-      free(buf);
-      buf = NULL;
-    }
-  } while (buf == NULL);
+  if (getifaddrs(&ifap) != 0) {
+    fprintf(stderr, "iface_Create: getifaddrs: %s\n", strerror(errno));
+    return NULL;
+  }
 
-  ptr = buf;
-  end = buf + needed;
   iface = NULL;
   namelen = strlen(name);
 
-  while (ptr < end && iface == NULL) {
-    ifm = (struct if_msghdr *)ptr;                     /* On if_msghdr */
-    if (ifm->ifm_version != RTM_VERSION)
+  for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
+    if (strcmp(name, ifa->ifa_name))
       continue;
-    if (ifm->ifm_type != RTM_IFINFO)
-      break;
-    dl = (struct sockaddr_dl *)(ifm + 1);              /* Single _dl at end */
-    if (dl->sdl_nlen == namelen && !strncmp(name, dl->sdl_data, namelen)) {
+    if (ifa->ifa_addr->sa_family == AF_LINK) {
+      dl = (struct sockaddr_dl *)ifa->ifa_addr;
       iface = (struct iface *)malloc(sizeof *iface);
       if (iface == NULL) {
         fprintf(stderr, "iface_Create: malloc: %s\n", strerror(errno));
+        freeifaddrs(ifap);
         return NULL;
       }
       iface->name = strdup(name);
-      iface->index = ifm->ifm_index;
-      iface->flags = ifm->ifm_flags;
+      iface->index = if_nametoindex(name);
+      iface->flags = ifa->ifa_flags;
       iface->mtu = 0;
       iface->addrs = 0;
       iface->addr = NULL;
     }
-    ptr += ifm->ifm_msglen;                            /* First ifa_msghdr */
-    for (; ptr < end; ptr += ifam->ifam_msglen) {
-      ifam = (struct ifa_msghdr *)ptr;                 /* Next if address */
-
-      if (ifam->ifam_type != RTM_NEWADDR)              /* finished this if */
-        break;
-      if (ifm->ifm_version != RTM_VERSION)
-        continue;
-
-      if (iface != NULL && ifam->ifam_addrs & RTA_IFA) {
-        /* Found a configured interface ! */
-        iface_ParseHdr(ifam, sa);
 
-        if (sa[RTAX_IFA] && (sa[RTAX_IFA]->sa_family == AF_INET
+    if (ifa->ifa_addr->sa_family == AF_INET
 #ifndef NOINET6
-                             || sa[RTAX_IFA]->sa_family == AF_INET6
+        || ifa->ifa_addr->sa_family == AF_INET6
 #endif
-                             )) {
-          /* Record the address */
+       ) {
+      /* Record the address */
 
-          addr = (struct iface_addr *)
-            realloc(iface->addr, (iface->addrs + 1) * sizeof iface->addr[0]);
-          if (addr == NULL)
-            break;
-          iface->addr = addr;
-
-          addr += iface->addrs;
-          iface->addrs++;
-
-          ncprange_setsa(&addr->ifa, sa[RTAX_IFA], sa[RTAX_NETMASK]);
-          if (sa[RTAX_BRD])
-            ncpaddr_setsa(&addr->peer, sa[RTAX_BRD]);
-          else
-            ncpaddr_init(&addr->peer);
-        }
-      }
+      addr = (struct iface_addr *)
+        realloc(iface->addr, (iface->addrs + 1) * sizeof iface->addr[0]);
+      if (addr == NULL)
+        break;
+      iface->addr = addr;
+
+      addr += iface->addrs;
+      iface->addrs++;
+
+      ncprange_setsa(&addr->ifa, ifa->ifa_addr, ifa->ifa_netmask);
+      if (ifa->ifa_broadaddr)
+        ncpaddr_setsa(&addr->peer, ifa->ifa_broadaddr);
+      else
+        ncpaddr_init(&addr->peer);
     }
   }
 
-  free(buf);
+  freeifaddrs(ifap);
 
   return iface;
 }
@@ -700,20 +651,4 @@ iface_Show(struct cmdargs const *arg)
   }
 
   return 0;
-}
-
-void
-iface_ParseHdr(struct ifa_msghdr *ifam, struct sockaddr *sa[RTAX_MAX])
-{
-  char *wp;
-  int rtax;
-
-  wp = (char *)(ifam + 1);
-
-  for (rtax = 0; rtax < RTAX_MAX; rtax++)
-    if (ifam->ifam_addrs & (1 << rtax)) {
-      sa[rtax] = (struct sockaddr *)wp;
-      wp += ROUNDUP(sa[rtax]->sa_len);
-    } else
-      sa[rtax] = NULL;
 }
Index: ppp/iface.h
===================================================================
RCS file: /cvs/src/usr.sbin/ppp/ppp/iface.h,v
retrieving revision 1.8
diff -u -p -r1.8 iface.h
--- ppp/iface.h 19 Aug 2001 23:22:17 -0000      1.8
+++ ppp/iface.h 30 Jun 2009 14:51:03 -0000
@@ -62,4 +62,3 @@ extern int iface_Show(struct cmdargs con
 extern int iface_SetFlags(const char *, int);
 extern int iface_ClearFlags(const char *, int);
 extern void iface_Destroy(struct iface *);
-extern void iface_ParseHdr(struct ifa_msghdr *, struct sockaddr *[RTAX_MAX]);
Index: ppp/route.c
===================================================================
RCS file: /cvs/src/usr.sbin/ppp/ppp/route.c,v
retrieving revision 1.37
diff -u -p -r1.37 route.c
--- ppp/route.c 25 Jun 2009 15:59:28 -0000      1.37
+++ ppp/route.c 30 Jun 2009 14:03:36 -0000
@@ -204,113 +204,15 @@ static int route_nifs = -1;
 const char *
 Index2Nam(int idx)
 {
-  /*
-   * XXX: Maybe we should select() on the routing socket so that we can
-   *      notice interfaces that come & go (PCCARD support).
-   *      Or we could even support a signal that resets these so that
-   *      the PCCARD insert/remove events can signal ppp.
-   */
-  static char **ifs;           /* Figure these out once */
-  static int debug_done;       /* Debug once */
+  static char ifname[IF_NAMESIZE];
+  char *ifn;
 
-  if (idx > route_nifs || (idx > 0 && ifs[idx-1] == NULL)) {
-    int mib[6], have, had;
-    size_t needed;
-    char *buf, *ptr, *end;
-    struct sockaddr_dl *dl;
-    struct if_msghdr *ifm;
+  ifn = if_indextoname(idx, ifname);
 
-    if (ifs) {
-      free(ifs);
-      ifs = NULL;
-      route_nifs = 0;
-    }
-    debug_done = 0;
-
-    mib[0] = CTL_NET;
-    mib[1] = PF_ROUTE;
-    mib[2] = 0;
-    mib[3] = 0;
-    mib[4] = NET_RT_IFLIST;
-    mib[5] = 0;
-
-    if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
-      log_Printf(LogERROR, "Index2Nam: sysctl: estimate: %s\n",
-                 strerror(errno));
-      return NumStr(idx, NULL, 0);
-    }
-    if ((buf = malloc(needed)) == NULL)
-      return NumStr(idx, NULL, 0);
-    if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
-      free(buf);
-      return NumStr(idx, NULL, 0);
-    }
-    end = buf + needed;
-
-    have = 0;
-    for (ptr = buf; ptr < end; ptr += ifm->ifm_msglen) {
-      ifm = (struct if_msghdr *)ptr;
-      if (ifm->ifm_version != RTM_VERSION)
-        continue;
-      if (ifm->ifm_type != RTM_IFINFO)
-        continue;
-      dl = (struct sockaddr_dl *)(ifm + 1);
-      if (ifm->ifm_index > 0) {
-        if (ifm->ifm_index > have) {
-          char **newifs;
-
-          had = have;
-          have = ifm->ifm_index + 5;
-          if (had)
-            newifs = (char **)realloc(ifs, sizeof(char *) * have);
-          else
-            newifs = (char **)calloc(sizeof(char *), have);
-          if (!newifs) {
-            log_Printf(LogDEBUG, "Index2Nam: %s\n", strerror(errno));
-            route_nifs = 0;
-            if (ifs) {
-              free(ifs);
-              ifs = NULL;
-            }
-            free(buf);
-            return NumStr(idx, NULL, 0);
-          }
-          ifs = newifs;
-          memset(ifs + had, '\0', sizeof(char *) * (have - had));
-        }
-        if (ifs[ifm->ifm_index-1] == NULL) {
-          ifs[ifm->ifm_index-1] = (char *)malloc(dl->sdl_nlen+1);
-          if (ifs[ifm->ifm_index-1] == NULL)
-           log_Printf(LogDEBUG, "Skipping interface %d: Out of memory\n",
-                  ifm->ifm_index);
-         else {
-           memcpy(ifs[ifm->ifm_index-1], dl->sdl_data, dl->sdl_nlen);
-           ifs[ifm->ifm_index-1][dl->sdl_nlen] = '\0';
-           if (route_nifs < ifm->ifm_index)
-             route_nifs = ifm->ifm_index;
-         }
-        }
-      } else if (log_IsKept(LogDEBUG))
-        log_Printf(LogDEBUG, "Skipping out-of-range interface %d!\n",
-                  ifm->ifm_index);
-    }
-    free(buf);
-  }
-
-  if (log_IsKept(LogDEBUG) && !debug_done) {
-    int f;
-
-    log_Printf(LogDEBUG, "Found the following interfaces:\n");
-    for (f = 0; f < route_nifs; f++)
-      if (ifs[f] != NULL)
-        log_Printf(LogDEBUG, " Index %d, name \"%s\"\n", f+1, ifs[f]);
-    debug_done = 1;
-  }
-
-  if (idx < 1 || idx > route_nifs || ifs[idx-1] == NULL)
+  if (idx < 1 || ifn == NULL)
     return NumStr(idx, NULL, 0);
 
-  return ifs[idx-1];
+  return ifn;
 }
 
 void

Reply via email to