From c372ea7718760b6e392788f1434181dac16ba592 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Thu, 7 Mar 2002 22:40:24 +0000 Subject: Replace SIOCGIFCONF-using NRL versions with KAME versions that use getifaddrs(3). Fixes problems on LP64 platforms. --- lib/libc/net/if_indextoname.c | 155 +++++++++------------------- lib/libc/net/if_nameindex.c | 233 +++++++++++++++++++----------------------- lib/libc/net/if_nametoindex.c | 146 +++++++++----------------- 3 files changed, 201 insertions(+), 333 deletions(-) (limited to 'lib/libc') diff --git a/lib/libc/net/if_indextoname.c b/lib/libc/net/if_indextoname.c index 4f3990b4c26..f99e52e387e 100644 --- a/lib/libc/net/if_indextoname.c +++ b/lib/libc/net/if_indextoname.c @@ -1,26 +1,20 @@ -/* - * Copyright (c) 1998-1999, Craig Metz, All rights reserved. +/* $OpenBSD: if_indextoname.c,v 1.9 2002/03/07 22:40:23 millert Exp $ */ +/* $KAME: if_indextoname.c,v 1.6 2000/11/07 22:33:25 jinmei Exp $ */ + +/*- + * Copyright (c) 1997, 2000 + * Berkeley Software Design, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Craig Metz and - * by other contributors. - * 4. Neither the name of the author nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -28,112 +22,65 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * BSDI Id: if_indextoname.c,v 2.3 2000/04/17 22:38:05 dab Exp */ #include -#include #include -#include -#include #include -#include -#include +#include +#include +#include #include +#include -static char __name[IFNAMSIZ]; +/* + * From RFC 2533: + * + * The second function maps an interface index into its corresponding + * name. + * + * #include + * + * char *if_indextoname(unsigned int ifindex, char *ifname); + * + * The ifname argument must point to a buffer of at least IF_NAMESIZE + * bytes into which the interface name corresponding to the specified + * index is returned. (IF_NAMESIZE is also defined in and + * its value includes a terminating null byte at the end of the + * interface name.) This pointer is also the return value of the + * function. If there is no interface corresponding to the specified + * index, NULL is returned, and errno is set to ENXIO, if there was a + * system error (such as running out of memory), if_indextoname returns + * NULL and errno would be set to the proper value (e.g., ENOMEM). + */ char * -if_indextoname(unsigned int index, char *name) +if_indextoname(unsigned int ifindex, char *ifname) { - int i, fd = -1, extra, len = 0; - struct ifconf ifconf; - char lastname[IFNAMSIZ], iname[IFNAMSIZ], *retname = NULL, *inbuf; - struct sockaddr *sa; - void *p; - - ifconf.ifc_buf = 0; - - if (!name) - name = __name; + struct ifaddrs *ifaddrs, *ifa; + int error = 0; - if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) - goto ret; + if (getifaddrs(&ifaddrs) < 0) + return(NULL); /* getifaddrs properly set errno */ - /* - * Try ifc_len == 0 hack first, to get the actual length. - * If that fails, revert to a loop which grows the ifc_buf - * until it is sufficiently large. - */ - extra = sizeof(struct ifreq); - while (1) { - ifconf.ifc_len = len; - if (ioctl(fd, SIOCGIFCONF, (void *) &ifconf) == -1 && - ifconf.ifc_buf) - goto ret; - if (ifconf.ifc_buf && - ifconf.ifc_len + extra < len) + 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; - if (ifconf.ifc_buf) { - if (len == 0) - len = 4096; - ifconf.ifc_len = len *= 2; - } else { - len = ifconf.ifc_len; - extra = 0; - } - inbuf = realloc(ifconf.ifc_buf, ifconf.ifc_len); - if (inbuf == NULL) - goto ret; - ifconf.ifc_buf = inbuf; } - i = 0; - p = ifconf.ifc_buf; - len = ifconf.ifc_len; - lastname[0] = 0; - lastname[sizeof(lastname)-1] = 0; - iname[0] = 0; - - while (len > 0) { - if (len < (IFNAMSIZ + sizeof(struct sockaddr))) - goto ret; - if (strncmp(lastname, p, IFNAMSIZ)) { - if (i == index) - memcpy(iname, lastname, sizeof(iname)); - strlcpy(lastname, p, sizeof(lastname)); - i++; - } - len -= IFNAMSIZ; - p += IFNAMSIZ; - sa = p; - - if (sa->sa_family == AF_LINK) { - struct sockaddr_dl *sd = p; - - if (sd->sdl_index == index) { - strlcpy(name, lastname, IFNAMSIZ); - retname = name; - goto ret; - } - } - - if (len < sa->sa_len) - goto ret; - len -= sa->sa_len; - p += sa->sa_len; + if (ifa == NULL) { + error = ENXIO; + ifname = NULL; } + else + strlcpy(ifname, ifa->ifa_name, IFNAMSIZ); - if (i == index) - strlcpy(iname, lastname, sizeof(iname)); + freeifaddrs(ifaddrs); - if (iname[0]) { - strlcpy(name, iname, IFNAMSIZ); - retname = name; - } -ret: - if (fd != -1) - close(fd); - if (ifconf.ifc_buf) - free(ifconf.ifc_buf); - return (retname); + errno = error; + return(ifname); } diff --git a/lib/libc/net/if_nameindex.c b/lib/libc/net/if_nameindex.c index 2b85fbae959..3675a2a4507 100644 --- a/lib/libc/net/if_nameindex.c +++ b/lib/libc/net/if_nameindex.c @@ -1,26 +1,20 @@ -/* - * Copyright (c) 1998-1999, Craig Metz, All rights reserved. +/* $OpenBSD: if_nameindex.c,v 1.9 2002/03/07 22:40:23 millert Exp $ */ +/* $KAME: if_nameindex.c,v 1.7 2000/11/24 08:17:20 itojun Exp $ */ + +/*- + * Copyright (c) 1997, 2000 + * Berkeley Software Design, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Craig Metz and - * by other contributors. - * 4. Neither the name of the author nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -28,140 +22,119 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * BSDI Id: if_nameindex.c,v 2.3 2000/04/17 22:38:05 dab Exp */ -#include #include #include -#include -#include #include -#include -#include +#include +#include +#include #include +/* + * From RFC 2553: + * + * 4.3 Return All Interface Names and Indexes + * + * The if_nameindex structure holds the information about a single + * interface and is defined as a result of including the + * header. + * + * struct if_nameindex { + * unsigned int if_index; + * char *if_name; + * }; + * + * The final function returns an array of if_nameindex structures, one + * structure per interface. + * + * struct if_nameindex *if_nameindex(void); + * + * The end of the array of structures is indicated by a structure with + * an if_index of 0 and an if_name of NULL. The function returns a NULL + * pointer upon an error, and would set errno to the appropriate value. + * + * The memory used for this array of structures along with the interface + * names pointed to by the if_name members is obtained dynamically. + * This memory is freed by the next function. + * + * 4.4. Free Memory + * + * The following function frees the dynamic memory that was allocated by + * if_nameindex(). + * + * #include + * + * void if_freenameindex(struct if_nameindex *ptr); + * + * The argument to this function must be a pointer that was returned by + * if_nameindex(). + */ + struct if_nameindex * if_nameindex(void) { - int i, j, fd = -1, extra, len = 0; - struct if_nameindex *nameindex = NULL; - struct ifconf ifconf; - char lastname[IFNAMSIZ], *c, *inbuf; - struct if_nameindex *n; - struct sockaddr *sa; - void *p; - - ifconf.ifc_buf = NULL; + struct ifaddrs *ifaddrs, *ifa; + unsigned int ni; + size_t nbytes; + struct if_nameindex *ifni, *ifni2; + char *cp; - if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) - goto ret; + if (getifaddrs(&ifaddrs) < 0) + return(NULL); /* - * Try ifc_len == 0 hack first, to get the actual length. - * If that fails, revert to a loop which grows the ifc_buf - * until it is sufficiently large. + * First, find out how many interfaces there are, and how + * much space we need for the string names. */ - extra = sizeof(struct ifreq); - while (1) { - ifconf.ifc_len = len; - if (ioctl(fd, SIOCGIFCONF, (void *) &ifconf) == -1 && - ifconf.ifc_buf) - goto ret; - if (ifconf.ifc_buf && - ifconf.ifc_len + extra < len) - break; - if (ifconf.ifc_buf) { - if (len == 0) - len = 4096; - ifconf.ifc_len = len *= 2; - } else { - len = ifconf.ifc_len; - extra = 0; - } - inbuf = realloc(ifconf.ifc_buf, ifconf.ifc_len); - if (inbuf == NULL) - goto ret; - ifconf.ifc_buf = inbuf; - } - - i = sizeof(struct if_nameindex); - j = 0; - p = ifconf.ifc_buf; - len = ifconf.ifc_len; - lastname[0] = 0; - lastname[sizeof(lastname)-1] = 0; - - while (len > 0) { - if (len < (IFNAMSIZ + sizeof(struct sockaddr))) - goto ret; - if (strncmp(lastname, p, IFNAMSIZ)) { - strlcpy(lastname, p, sizeof(lastname)); - i += sizeof(struct if_nameindex); - j += strlen(lastname) + 1; + 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++; } - len -= IFNAMSIZ; - p += IFNAMSIZ; - sa = p; - - if (sa->sa_len < sizeof(struct sockaddr)) - sa->sa_len = sizeof(struct sockaddr); - - if (len < sa->sa_len) - goto ret; - len -= sa->sa_len; - p += sa->sa_len; - } - - nameindex = malloc(i + j); - if (nameindex == NULL) { - errno = ENOMEM; - goto ret; } - memset(nameindex, 0, i + j); - n = nameindex; - p = ifconf.ifc_buf; - c = (void *) nameindex + i; - i = 0; - len = ifconf.ifc_len; - lastname[0] = 0; - - while (len > 0) { - if (len < IFNAMSIZ + sizeof(struct sockaddr)) - goto ret; - if (strncmp(lastname, p, IFNAMSIZ)) { - if (i) { - if (!n->if_index) - n->if_index = i; - n++; - } - i++; - memcpy(lastname, p, sizeof(lastname)); - strlcpy(c, lastname, sizeof(lastname)); - n->if_name = c; - c += strlen(c) + 1; - } - len -= IFNAMSIZ; - p += IFNAMSIZ; - sa = p; + /* + * Next, 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; + if (ifni == NULL) + goto out; + cp += (ni + 1) * sizeof(struct if_nameindex); - if (len < sa->sa_len) - goto ret; - if (sa->sa_family == AF_LINK) { - struct sockaddr_dl *sd = (struct sockaddr_dl *)sa; - n->if_index = sd->sdl_index; + /* + * 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; } - len -= sa->sa_len; - p += sa->sa_len; } - - if (n->if_index == 0) - n->if_index = i; - -ret: - if (fd != -1) - close(fd); - if (ifconf.ifc_buf) - free(ifconf.ifc_buf); - return (nameindex); + /* + * Finally, don't forget to terminate the array. + */ + ifni2->if_index = 0; + ifni2->if_name = NULL; +out: + freeifaddrs(ifaddrs); + return(ifni); } diff --git a/lib/libc/net/if_nametoindex.c b/lib/libc/net/if_nametoindex.c index e7e8b6c22ae..8bd792b949c 100644 --- a/lib/libc/net/if_nametoindex.c +++ b/lib/libc/net/if_nametoindex.c @@ -1,26 +1,20 @@ -/* - * Copyright (c) 1998-1999, Craig Metz, All rights reserved. +/* $OpenBSD: if_nametoindex.c,v 1.8 2002/03/07 22:40:23 millert Exp $ */ +/* $KAME: if_nametoindex.c,v 1.5 2000/11/24 08:04:40 itojun Exp $ */ + +/*- + * Copyright (c) 1997, 2000 + * Berkeley Software Design, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Craig Metz and - * by other contributors. - * 4. Neither the name of the author nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -28,106 +22,60 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * BSDI Id: if_nametoindex.c,v 2.3 2000/04/17 22:38:05 dab Exp */ #include -#include #include -#include #include #include +#include +#include #include -#include #include -unsigned int -if_nametoindex(const char *name) +/* + * From RFC 2553: + * + * 4.1 Name-to-Index + * + * + * The first function maps an interface name into its corresponding + * index. + * + * #include + * + * unsigned int if_nametoindex(const char *ifname); + * + * If the specified interface name does not exist, the return value is + * 0, and errno is set to ENXIO. If there was a system error (such as + * running out of memory), the return value is 0 and errno is set to the + * proper value (e.g., ENOMEM). + */ + +unsigned int +if_nametoindex(const char *ifname) { - int i, fd = -1, extra, len = 0; - struct ifconf ifconf; - char lastname[IFNAMSIZ], *thisname, *inbuf; - unsigned int index = 0; - struct sockaddr *sa; - void *p; + struct ifaddrs *ifaddrs, *ifa; + unsigned int ni; - ifconf.ifc_buf = 0; + if (getifaddrs(&ifaddrs) < 0) + return(0); - if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) - goto ret; + ni = 0; - /* - * Try ifc_len == 0 hack first, to get the actual length. - * If that fails, revert to a loop which grows the ifc_buf - * until it is sufficiently large. - */ - extra = sizeof(struct ifreq); - while (1) { - ifconf.ifc_len = len; - if (ioctl(fd, SIOCGIFCONF, (void *) &ifconf) == -1 && - ifconf.ifc_buf) - goto ret; - if (ifconf.ifc_buf && - ifconf.ifc_len + extra < len) + 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; - if (ifconf.ifc_buf) { - if (len == 0) - len = 4096; - ifconf.ifc_len = len *= 2; - } else { - len = ifconf.ifc_len; - extra = 0; - } - inbuf = realloc(ifconf.ifc_buf, ifconf.ifc_len); - if (inbuf == NULL) - goto ret; - ifconf.ifc_buf = inbuf; - } - - i = 0; - p = ifconf.ifc_buf; - len = ifconf.ifc_len; - lastname[0] = 0; - lastname[sizeof(lastname)-1] = 0; - - while (len > 0) { - if (len < IFNAMSIZ + sizeof(struct sockaddr)) - goto ret; - - thisname = p; - if (strncmp(lastname, p, IFNAMSIZ)) { - if (!strcmp(lastname, name)) { - index = i; - goto ret; - } - memcpy(lastname, thisname, IFNAMSIZ); - i++; } - - len -= IFNAMSIZ; - p += IFNAMSIZ; - sa = (struct sockaddr *)p; - - if (!strncmp(thisname, name, IFNAMSIZ) && - sa->sa_family == AF_LINK) { - struct sockaddr_dl *sd = p; - - index = sd->sdl_index; - goto ret; - } - - if (len < sa->sa_len) - goto ret; - len -= sa->sa_len; - p += sa->sa_len; } - if (!strcmp(lastname, name)) - index = i; - -ret: - if (fd != -1) - close(fd); - if (ifconf.ifc_buf) - free(ifconf.ifc_buf); - return index; + freeifaddrs(ifaddrs); + if (!ni) + errno = ENXIO; + return(ni); } -- cgit v1.2.3