diff options
author | meem <none@none> | 2006-01-12 20:36:01 -0800 |
---|---|---|
committer | meem <none@none> | 2006-01-12 20:36:01 -0800 |
commit | 0406ceaaee37395222cc0d87df03b940c8946a5c (patch) | |
tree | 107ac95132e81f3dc57c9357572212aa3668fcef /usr/src/lib/libinetutil | |
parent | fea9cb91bd8e12d84069b4dab1268363668b4bff (diff) | |
download | illumos-joyent-0406ceaaee37395222cc0d87df03b940c8946a5c.tar.gz |
4659930 ip_anon_rcm`ifaddrlist() misbehaves when no interfaces are found
4803054 ip_anon_rcm`ifaddrlist() contains unsafe string strncpy() usage
6370980 ifaddrlist() needs to be fixed up and put in libinetutil
6372093 purge ip_anon_register()'s pathetic attempts to paper over 4659930
--HG--
rename : usr/src/cmd/cmd-inet/common/Makefile => deleted_files/usr/src/cmd/cmd-inet/common/Makefile
rename : usr/src/cmd/cmd-inet/common/ifaddrlist.h => deleted_files/usr/src/cmd/cmd-inet/common/ifaddrlist.h
rename : usr/src/cmd/cmd-inet/usr.sbin/ping/req.flg => deleted_files/usr/src/cmd/cmd-inet/usr.sbin/ping/req.flg
rename : usr/src/cmd/cmd-inet/usr.sbin/traceroute/req.flg => deleted_files/usr/src/cmd/cmd-inet/usr.sbin/traceroute/req.flg
rename : usr/src/cmd/cmd-inet/common/ifaddrlist.c => usr/src/lib/libinetutil/common/ifaddrlist.c
Diffstat (limited to 'usr/src/lib/libinetutil')
-rw-r--r-- | usr/src/lib/libinetutil/Makefile.com | 7 | ||||
-rw-r--r-- | usr/src/lib/libinetutil/common/ifaddrlist.c | 192 | ||||
-rw-r--r-- | usr/src/lib/libinetutil/common/libinetutil.h | 38 | ||||
-rw-r--r-- | usr/src/lib/libinetutil/spec/inetutil.spec | 8 |
4 files changed, 239 insertions, 6 deletions
diff --git a/usr/src/lib/libinetutil/Makefile.com b/usr/src/lib/libinetutil/Makefile.com index 0606c1dcff..d9e592c2df 100644 --- a/usr/src/lib/libinetutil/Makefile.com +++ b/usr/src/lib/libinetutil/Makefile.com @@ -20,7 +20,7 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -28,7 +28,7 @@ LIBRARY = libinetutil.a VERS = .1 -OBJECTS = octet.o inetutil4.o ifspec.o eh.o tq.o +OBJECTS = octet.o inetutil4.o ifspec.o ifaddrlist.o eh.o tq.o include ../../Makefile.lib @@ -38,7 +38,8 @@ include ../../Makefile.rootfs LIBS = $(DYNLIB) $(LINTLIB) SRCS = $(COMDIR)/octet.c $(SRCDIR)/inetutil4.c \ - $(SRCDIR)/ifspec.c $(SRCDIR)/eh.c $(SRCDIR)/tq.c + $(SRCDIR)/ifspec.c $(SRCDIR)/eh.c $(SRCDIR)/tq.c \ + $(SRCDIR)/ifaddrlist.c $(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC) LDLIBS += -lsocket -lc diff --git a/usr/src/lib/libinetutil/common/ifaddrlist.c b/usr/src/lib/libinetutil/common/ifaddrlist.c new file mode 100644 index 0000000000..383dc2afb0 --- /dev/null +++ b/usr/src/lib/libinetutil/common/ifaddrlist.c @@ -0,0 +1,192 @@ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1997 + * The Regents of the University of California. 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 the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory 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 + * 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 + * 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) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * 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. + * + * @(#) $Header: ifaddrlist.c,v 1.2 97/04/22 13:31:05 leres Exp $ (LBL) + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <alloca.h> +#include <errno.h> +#include <libinetutil.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/socket.h> +#include <sys/sockio.h> + +/* + * See <libinetutil.h> for a description of the programming interface. + */ +int +ifaddrlist(struct ifaddrlist **ipaddrp, int family, char *errbuf) +{ + struct ifaddrlist *ifaddrlist, *al; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + struct lifconf lifc; + struct lifnum lifn; + struct lifreq *lifrp; + int i, count, nlifr; + int fd; + const char *iocstr; + + if (family != AF_INET && family != AF_INET6) { + (void) strlcpy(errbuf, "invalid address family", ERRBUFSIZE); + return (-1); + } + + fd = socket(family, SOCK_DGRAM, 0); + if (fd == -1) { + (void) snprintf(errbuf, ERRBUFSIZE, "socket: %s", + strerror(errno)); + return (-1); + } + + /* + * Get the number of network interfaces of type `family'. + */ + lifn.lifn_family = family; + lifn.lifn_flags = 0; +again: + if (ioctl(fd, SIOCGLIFNUM, &lifn) == -1) { + (void) snprintf(errbuf, ERRBUFSIZE, "SIOCGLIFNUM: %s", + strerror(errno)); + (void) close(fd); + return (-1); + } + + /* + * Pad the interface count to detect when additional interfaces have + * been configured between SIOCGLIFNUM and SIOCGLIFCONF. + */ + lifn.lifn_count += 4; + + lifc.lifc_family = family; + lifc.lifc_len = lifn.lifn_count * sizeof (struct lifreq); + lifc.lifc_buf = alloca(lifc.lifc_len); + lifc.lifc_flags = 0; + + if (ioctl(fd, SIOCGLIFCONF, &lifc) == -1) { + (void) snprintf(errbuf, ERRBUFSIZE, "SIOCGLIFCONF: %s", + strerror(errno)); + (void) close(fd); + return (-1); + } + + /* + * If every lifr_req slot is taken, then additional interfaces must + * have been plumbed between the SIOCGLIFNUM and the SIOCGLIFCONF. + * Recalculate to make sure we didn't miss any interfaces. + */ + nlifr = lifc.lifc_len / sizeof (struct lifreq); + if (nlifr >= lifn.lifn_count) + goto again; + + /* + * Allocate the address list to return. + */ + ifaddrlist = calloc(nlifr, sizeof (struct ifaddrlist)); + if (ifaddrlist == NULL) { + (void) snprintf(errbuf, ERRBUFSIZE, "calloc: %s", + strerror(errno)); + (void) close(fd); + return (-1); + } + + /* + * Populate the address list by querying each underlying interface. + * If a query ioctl returns ENXIO, then the interface must have been + * removed after the SIOCGLIFCONF completed -- so we just ignore it. + */ + al = ifaddrlist; + count = 0; + for (lifrp = lifc.lifc_req, i = 0; i < nlifr; i++, lifrp++) { + (void) strlcpy(al->device, lifrp->lifr_name, LIFNAMSIZ); + + if (ioctl(fd, SIOCGLIFFLAGS, lifrp) == -1) { + if (errno == ENXIO) + continue; + iocstr = "SIOCGLIFFLAGS"; + goto fail; + } + al->flags = lifrp->lifr_flags; + + if (ioctl(fd, SIOCGLIFINDEX, lifrp) == -1) { + if (errno == ENXIO) + continue; + iocstr = "SIOCGLIFINDEX"; + goto fail; + } + al->index = lifrp->lifr_index; + + if (ioctl(fd, SIOCGLIFADDR, lifrp) == -1) { + if (errno == ENXIO) + continue; + iocstr = "SIOCGLIFADDR"; + goto fail; + } + + if (family == AF_INET) { + sin = (struct sockaddr_in *)&lifrp->lifr_addr; + al->addr.addr = sin->sin_addr; + } else { + sin6 = (struct sockaddr_in6 *)&lifrp->lifr_addr; + al->addr.addr6 = sin6->sin6_addr; + } + al++; + count++; + } + + (void) close(fd); + if (count == 0) { + free(ifaddrlist); + *ipaddrp = NULL; + return (0); + } + + *ipaddrp = ifaddrlist; + return (count); +fail: + (void) snprintf(errbuf, ERRBUFSIZE, "%s: %s: %s", iocstr, al->device, + strerror(errno)); + + free(ifaddrlist); + (void) close(fd); + return (-1); +} diff --git a/usr/src/lib/libinetutil/common/libinetutil.h b/usr/src/lib/libinetutil/common/libinetutil.h index 0213a23aa2..b21d54f56c 100644 --- a/usr/src/lib/libinetutil/common/libinetutil.h +++ b/usr/src/lib/libinetutil/common/libinetutil.h @@ -19,8 +19,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -30,7 +31,7 @@ #pragma ident "%Z%%M% %I% %E% SMI" /* - * Contains SMI-private API for general internet functionality + * Contains SMI-private API for general Internet functionality */ #ifdef __cplusplus @@ -60,6 +61,39 @@ extern boolean_t ifparse_ifspec(const char *, ifspec_t *); extern void get_netmask4(const struct in_addr *, struct in_addr *); /* + * Extended version of the classic BSD ifaddrlist() interface: + * + * int ifaddrlist(struct ifaddrlist **addrlistp, int af, char *errbuf); + * + * * addrlistp: Upon success, ifaddrlist() sets *addrlistp to a + * dynamically-allocated array of addresses. + * + * * af: Either AF_INET to obtain IPv4 addresses, or AF_INET6 to + * obtain IPv6 addresses. + * + * * errbuf: A caller-supplied buffer of ERRBUFSIZE. Upon failure, + * provides the reason for the failure. + * + * Upon success, ifaddrlist() returns the number of addresses in the array + * pointed to by `addrlistp'. If the count is 0, then `addrlistp' is NULL. + */ +union any_in_addr { + struct in6_addr addr6; + struct in_addr addr; +}; + +struct ifaddrlist { + int index; /* interface index */ + union any_in_addr addr; /* interface address */ + char device[LIFNAMSIZ + 1]; /* interface name */ + uint64_t flags; /* interface flags */ +}; + +#define ERRBUFSIZE 128 /* expected size of third argument */ + +extern int ifaddrlist(struct ifaddrlist **, int, char *); + +/* * Timer queues * * timer queues are a facility for managing timeouts in unix. in the diff --git a/usr/src/lib/libinetutil/spec/inetutil.spec b/usr/src/lib/libinetutil/spec/inetutil.spec index 33f4a27aff..25741fd0ef 100644 --- a/usr/src/lib/libinetutil/spec/inetutil.spec +++ b/usr/src/lib/libinetutil/spec/inetutil.spec @@ -1,5 +1,5 @@ # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # CDDL HEADER START @@ -52,6 +52,12 @@ declaration void get_netmask4(const struct in_addr *np, struct in_addr *sp) version SUNWprivate_1.1 end +function ifaddrlist +include <libinetutil.h> +declaration int ifaddrlist(struct ifaddrlist **, int, char *); +version SUNWprivate_1.1 +end + function ifparse_ifspec include <libinetutil.h> declaration boolean_t ifparse_ifspec(const char *ifname, ifspec_t *ifsp) |