summaryrefslogtreecommitdiff
path: root/usr/src/lib/libinetutil
diff options
context:
space:
mode:
authormeem <none@none>2006-01-12 20:36:01 -0800
committermeem <none@none>2006-01-12 20:36:01 -0800
commit0406ceaaee37395222cc0d87df03b940c8946a5c (patch)
tree107ac95132e81f3dc57c9357572212aa3668fcef /usr/src/lib/libinetutil
parentfea9cb91bd8e12d84069b4dab1268363668b4bff (diff)
downloadillumos-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.com7
-rw-r--r--usr/src/lib/libinetutil/common/ifaddrlist.c192
-rw-r--r--usr/src/lib/libinetutil/common/libinetutil.h38
-rw-r--r--usr/src/lib/libinetutil/spec/inetutil.spec8
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)