From fbbeb39659d02bb968bbfbf1dd7200def1255ebd Mon Sep 17 00:00:00 2001
From: claudio <>
Date: Fri, 23 Oct 2015 13:09:19 +0000
Subject: Switch if_nameindex(3) to use the new NET_RT_IFNAMES sysctl to get
 the list of interface names. At the same time switch if_nametoindex(3) and
 if_indextoname(3) to use if_nameindex(3) instead of getifaddrs(3).
 if_nameindex(3) exposes much less then getifaddrs(3) and is allowed by
 pledge(2). With and OK deraadt@

---
 src/lib/libc/net/if_indextoname.c | 37 ++++++----------
 src/lib/libc/net/if_nameindex.c   | 93 +++++++++++++++++++--------------------
 src/lib/libc/net/if_nametoindex.c | 31 ++++++-------
 3 files changed, 73 insertions(+), 88 deletions(-)

(limited to 'src/lib')

diff --git a/src/lib/libc/net/if_indextoname.c b/src/lib/libc/net/if_indextoname.c
index f1c65966df..affa42551e 100644
--- a/src/lib/libc/net/if_indextoname.c
+++ b/src/lib/libc/net/if_indextoname.c
@@ -1,7 +1,8 @@
-/*	$OpenBSD: if_indextoname.c,v 1.10 2015/09/14 10:47:01 guenther Exp $	*/
+/*	$OpenBSD: if_indextoname.c,v 1.11 2015/10/23 13:09:19 claudio Exp $	*/
 /*	$KAME: if_indextoname.c,v 1.6 2000/11/07 22:33:25 jinmei Exp $	*/
 
 /*-
+ * Copyright (c) 2015 Claudio Jeker <claudio@openbsd.org>
  * Copyright (c) 1997, 2000
  *	Berkeley Software Design, Inc.  All rights reserved.
  *
@@ -28,9 +29,7 @@
 
 #include <sys/types.h>
 #include <sys/socket.h>
-#include <net/if_dl.h>
 #include <net/if.h>
-#include <ifaddrs.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
@@ -59,29 +58,21 @@
 char *
 if_indextoname(unsigned int ifindex, char *ifname)
 {
-	struct ifaddrs *ifaddrs, *ifa;
-	int error = 0;
+	struct if_nameindex *ifni, *ifni2;
 
-	if (getifaddrs(&ifaddrs) < 0)
-		return(NULL);	/* getifaddrs properly set errno */
+	if ((ifni = if_nameindex()) == NULL)
+		return NULL;
 
-	for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
-		if (ifa->ifa_addr &&
-		    ifa->ifa_addr->sa_family == AF_LINK &&
-		    ifindex == ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index)
-			break;
+	for (ifni2 = ifni; ifni2->if_index != 0; ifni2++) {
+		if (ifni2->if_index == ifindex) {
+			strlcpy(ifname, ifni2->if_name, IFNAMSIZ);
+			if_freenameindex(ifni);
+			return ifname;
+		}
 	}
 
-	if (ifa == NULL) {
-		error = ENXIO;
-		ifname = NULL;
-	}
-	else
-		strlcpy(ifname, ifa->ifa_name, IFNAMSIZ);
-
-	freeifaddrs(ifaddrs);
-
-	errno = error;
-	return(ifname);
+	if_freenameindex(ifni);
+	errno = ENXIO;
+	return NULL;
 }
 DEF_WEAK(if_indextoname);
diff --git a/src/lib/libc/net/if_nameindex.c b/src/lib/libc/net/if_nameindex.c
index c5a771869b..11c544b20e 100644
--- a/src/lib/libc/net/if_nameindex.c
+++ b/src/lib/libc/net/if_nameindex.c
@@ -1,7 +1,8 @@
-/*	$OpenBSD: if_nameindex.c,v 1.10 2010/09/24 13:29:29 claudio Exp $	*/
+/*	$OpenBSD: if_nameindex.c,v 1.11 2015/10/23 13:09:19 claudio Exp $	*/
 /*	$KAME: if_nameindex.c,v 1.7 2000/11/24 08:17:20 itojun Exp $	*/
 
 /*-
+ * Copyright (c) 2015 Claudio Jeker <claudio@openbsd.org>
  * Copyright (c) 1997, 2000
  *	Berkeley Software Design, Inc.  All rights reserved.
  *
@@ -28,11 +29,11 @@
 
 #include <sys/types.h>
 #include <sys/socket.h>
-#include <net/if_dl.h>
+#include <sys/sysctl.h>
 #include <net/if.h>
-#include <ifaddrs.h>
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
 
 /*
  * From RFC 2553:
@@ -77,66 +78,62 @@
 struct if_nameindex *
 if_nameindex(void)
 {
-	struct ifaddrs *ifaddrs, *ifa;
-	unsigned int ni;
-	size_t nbytes;
-	struct if_nameindex *ifni, *ifni2;
+	struct if_nameindex_msg *ifnm = NULL;	
+	struct if_nameindex *ifni = NULL, *ifni2;
 	char *cp;
+	size_t nbytes, needed;
+	unsigned int ni, i;
+	int mib[6];
 
-	if (getifaddrs(&ifaddrs) < 0)
-		return(NULL);
+	mib[0] = CTL_NET;
+	mib[1] = PF_ROUTE;
+	mib[2] = 0;		/* protocol */
+	mib[3] = 0;		/* not used */
+	mib[4] = NET_RT_IFNAMES;
+	mib[5] = 0;		/* no flags */
+	while (1) {
+		struct if_nameindex_msg *buf = NULL;	
 
-	/*
-	 * First, find out how many interfaces there are, and how
-	 * much space we need for the string names.
-	 */
-	ni = 0;
-	nbytes = 0;
-	for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
-		if (ifa->ifa_addr &&
-		    ifa->ifa_addr->sa_family == AF_LINK) {
-			nbytes += strlen(ifa->ifa_name) + 1;
-			ni++;
+		if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
+			goto out;
+		if (needed == 0)
+			break;
+		if ((buf = realloc(ifnm, needed)) == NULL)
+			goto out;
+		ifnm = buf;
+		if (sysctl(mib, 6, ifnm, &needed, NULL, 0) == -1) {
+			if (errno == ENOMEM)
+				continue;
+			goto out;
 		}
+		break;
 	}
 
 	/*
-	 * Next, allocate a chunk of memory, use the first part
-	 * for the array of structures, and the last part for
-	 * the strings.
+	 * Allocate a chunk of memory, use the first part for the array of
+	 * structures, and the last part for the strings.
 	 */
-	cp = malloc((ni + 1) * sizeof(struct if_nameindex) + nbytes);
-	ifni = (struct if_nameindex *)cp;
+	ni = needed / sizeof(*ifnm);
+	ifni = calloc(ni + 1, sizeof(struct if_nameindex) + IF_NAMESIZE);
 	if (ifni == NULL)
 		goto out;
-	cp += (ni + 1) * sizeof(struct if_nameindex);
+	cp = (char *)(ifni + (ni + 1));
 
-	/*
-	 * Now just loop through the list of interfaces again,
-	 * filling in the if_nameindex array and making copies
-	 * of all the strings.
-	 */
 	ifni2 = ifni;
-	for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
-		if (ifa->ifa_addr &&
-		    ifa->ifa_addr->sa_family == AF_LINK) {
-			ifni2->if_index =
-			    ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index;
-			ifni2->if_name = cp;
-			nbytes = strlen(ifa->ifa_name) + 1;
-			memcpy(cp, ifa->ifa_name, nbytes);
-			ifni2++;
-			cp += nbytes;
-		}
+	for (i = 0; i < ni; i++) {
+		ifni2->if_index = ifnm[i].if_index;
+		/* don't care about truncation */
+		strlcpy(cp, ifnm[i].if_name, IF_NAMESIZE);
+		ifni2->if_name = cp;
+		ifni2++;
+		cp += IF_NAMESIZE;
 	}
-	/*
-	 * Finally, don't forget to terminate the array.
-	 */
+	/* Finally, terminate the array. */
 	ifni2->if_index = 0;
 	ifni2->if_name = NULL;
 out:
-	freeifaddrs(ifaddrs);
-	return(ifni);
+	free(ifnm);
+	return ifni;
 }
 
 void
@@ -144,3 +141,5 @@ if_freenameindex(struct if_nameindex *ptr)
 {
 	free(ptr);
 }
+DEF_WEAK(if_nameindex);
+DEF_WEAK(if_freenameindex);
diff --git a/src/lib/libc/net/if_nametoindex.c b/src/lib/libc/net/if_nametoindex.c
index 8b2cbf743f..7a4492e37d 100644
--- a/src/lib/libc/net/if_nametoindex.c
+++ b/src/lib/libc/net/if_nametoindex.c
@@ -1,7 +1,8 @@
-/*	$OpenBSD: if_nametoindex.c,v 1.9 2015/09/14 10:47:01 guenther Exp $	*/
+/*	$OpenBSD: if_nametoindex.c,v 1.10 2015/10/23 13:09:19 claudio Exp $	*/
 /*	$KAME: if_nametoindex.c,v 1.5 2000/11/24 08:04:40 itojun Exp $	*/
 
 /*-
+ * Copyright (c) 2015 Claudio Jeker <claudio@openbsd.org>
  * Copyright (c) 1997, 2000
  *	Berkeley Software Design, Inc.  All rights reserved.
  *
@@ -29,8 +30,6 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <net/if.h>
-#include <net/if_dl.h>
-#include <ifaddrs.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
@@ -57,26 +56,22 @@
 unsigned int
 if_nametoindex(const char *ifname)
 {
-	struct ifaddrs *ifaddrs, *ifa;
-	unsigned int ni;
+	struct if_nameindex *ifni, *ifni2;
+	unsigned int index;
 
-	if (getifaddrs(&ifaddrs) < 0)
+	if ((ifni = if_nameindex()) == NULL)
 		return(0);
 
-	ni = 0;
-
-	for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
-		if (ifa->ifa_addr &&
-		    ifa->ifa_addr->sa_family == AF_LINK &&
-		    strcmp(ifa->ifa_name, ifname) == 0) {
-			ni = ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index;
-			break;
+	for (ifni2 = ifni; ifni2->if_index != 0; ifni2++) {
+		if (strcmp(ifni2->if_name, ifname) == 0) {
+			index = ifni2->if_index;
+			if_freenameindex(ifni);
+			return index;
 		}
 	}
 
-	freeifaddrs(ifaddrs);
-	if (!ni)
-		errno = ENXIO;
-	return(ni);
+	if_freenameindex(ifni);
+	errno = ENXIO;
+	return 0;
 }
 DEF_WEAK(if_nametoindex);
-- 
cgit v1.2.3-55-g6feb