summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2009-07-02 16:08:30 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2009-07-02 16:08:30 +0000
commit45ac9fc274972f19a47bf3a4912e265b916209d6 (patch)
tree06369305c893a4dc648402e03d2b03c766ca072f /usr.sbin
parent4f2c710a4bf3d30bf94f45ef5108a0b5cbbf09dd (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')
-rw-r--r--usr.sbin/ppp/ppp/arp.c128
-rw-r--r--usr.sbin/ppp/ppp/iface.c133
-rw-r--r--usr.sbin/ppp/ppp/iface.h3
-rw-r--r--usr.sbin/ppp/ppp/route.c110
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