diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2009-07-02 16:08:30 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2009-07-02 16:08:30 +0000 |
commit | 45ac9fc274972f19a47bf3a4912e265b916209d6 (patch) | |
tree | 06369305c893a4dc648402e03d2b03c766ca072f /usr.sbin/ppp | |
parent | 4f2c710a4bf3d30bf94f45ef5108a0b5cbbf09dd (diff) |
Rewrite the sysctl handlers to use libc functions (getifaddrs and
if_indextoname) instead of looking at the sysctl data directly. This makes
the code a lot simpler and actually work. Tested by many (todd@, sthen@, and
a few people on tech@). OK sthen@, deraadt@
Diffstat (limited to 'usr.sbin/ppp')
-rw-r--r-- | usr.sbin/ppp/ppp/arp.c | 128 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/iface.c | 133 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/iface.h | 3 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/route.c | 110 |
4 files changed, 88 insertions, 286 deletions
diff --git a/usr.sbin/ppp/ppp/arp.c b/usr.sbin/ppp/ppp/arp.c index 5deab1b29dc..a3483d8ab50 100644 --- a/usr.sbin/ppp/ppp/arp.c +++ b/usr.sbin/ppp/ppp/arp.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $OpenBSD: arp.c,v 1.15 2008/05/06 06:34:10 claudio Exp $ + * $OpenBSD: arp.c,v 1.16 2009/07/02 16:08:29 claudio Exp $ * */ @@ -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; } diff --git a/usr.sbin/ppp/ppp/iface.c b/usr.sbin/ppp/ppp/iface.c index 9d332d48e17..a30d95de099 100644 --- a/usr.sbin/ppp/ppp/iface.c +++ b/usr.sbin/ppp/ppp/iface.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: iface.c,v 1.28 2009/06/25 15:59:28 claudio Exp $ + * $OpenBSD: iface.c,v 1.29 2009/07/02 16:08:29 claudio Exp $ */ #include <sys/param.h> @@ -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 = 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 */ + if (ifa->ifa_addr->sa_family == AF_INET +#ifndef NOINET6 + || ifa->ifa_addr->sa_family == AF_INET6 +#endif + ) { + /* Record the address */ + + addr = (struct iface_addr *) + realloc(iface->addr, (iface->addrs + 1) * sizeof iface->addr[0]); + if (addr == NULL) break; - if (ifm->ifm_version != RTM_VERSION) - continue; + iface->addr = addr; - if (iface != NULL && ifam->ifam_addrs & RTA_IFA) { - /* Found a configured interface ! */ - iface_ParseHdr(ifam, sa); + addr += iface->addrs; + iface->addrs++; - if (sa[RTAX_IFA] && (sa[RTAX_IFA]->sa_family == AF_INET -#ifndef NOINET6 - || sa[RTAX_IFA]->sa_family == AF_INET6 -#endif - )) { - /* 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); - } - } + 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; } @@ -701,19 +652,3 @@ 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; -} diff --git a/usr.sbin/ppp/ppp/iface.h b/usr.sbin/ppp/ppp/iface.h index e04a5a9144f..8f42ab0ea72 100644 --- a/usr.sbin/ppp/ppp/iface.h +++ b/usr.sbin/ppp/ppp/iface.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: iface.h,v 1.8 2001/08/19 23:22:17 brian Exp $ + * $OpenBSD: iface.h,v 1.9 2009/07/02 16:08:29 claudio Exp $ */ struct ifa_msghdr; @@ -62,4 +62,3 @@ extern int iface_Show(struct cmdargs const *); 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]); diff --git a/usr.sbin/ppp/ppp/route.c b/usr.sbin/ppp/ppp/route.c index 5b644de9028..7d43f6f1915 100644 --- a/usr.sbin/ppp/ppp/route.c +++ b/usr.sbin/ppp/ppp/route.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: route.c,v 1.37 2009/06/25 15:59:28 claudio Exp $ + * $OpenBSD: route.c,v 1.38 2009/07/02 16:08:29 claudio Exp $ */ #include <sys/param.h> @@ -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 */ - - 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; - - 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; + static char ifname[IF_NAMESIZE]; + char *ifn; - 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; - } + ifn = if_indextoname(idx, ifname); - 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 |