diff options
Diffstat (limited to 'usr/src/lib')
27 files changed, 1159 insertions, 359 deletions
diff --git a/usr/src/lib/brand/native/zone/platform.xml b/usr/src/lib/brand/native/zone/platform.xml index f7030ba0a1..69e86cefd2 100644 --- a/usr/src/lib/brand/native/zone/platform.xml +++ b/usr/src/lib/brand/native/zone/platform.xml @@ -20,7 +20,7 @@ CDDL HEADER END - Copyright 2008 Sun Microsystems, Inc. All rights reserved. + Copyright 2009 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. DO NOT EDIT THIS FILE. @@ -97,6 +97,7 @@ <device match="ipf" ip-type="exclusive" /> <device match="ipl" ip-type="exclusive" /> <device match="iplookup" ip-type="exclusive" /> + <device match="ipmpstub" ip-type="exclusive" /> <device match="ipnat" ip-type="exclusive" /> <device match="ipscan" ip-type="exclusive" /> <device match="ipsecah" ip-type="exclusive" /> diff --git a/usr/src/lib/brand/sn1/zone/platform.xml b/usr/src/lib/brand/sn1/zone/platform.xml index 1659d8851c..b3bb0d7962 100644 --- a/usr/src/lib/brand/sn1/zone/platform.xml +++ b/usr/src/lib/brand/sn1/zone/platform.xml @@ -20,7 +20,7 @@ CDDL HEADER END - Copyright 2008 Sun Microsystems, Inc. All rights reserved. + Copyright 2009 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. DO NOT EDIT THIS FILE. @@ -101,6 +101,7 @@ <device match="ipf" ip-type="exclusive" /> <device match="ipl" ip-type="exclusive" /> <device match="iplookup" ip-type="exclusive" /> + <device match="ipmpstub" ip-type="exclusive" /> <device match="ipnat" ip-type="exclusive" /> <device match="ipscan" ip-type="exclusive" /> <device match="ipsecah" ip-type="exclusive" /> diff --git a/usr/src/lib/libbsm/common/adt.c b/usr/src/lib/libbsm/common/adt.c index 23f78b6247..d9947622d4 100644 --- a/usr/src/lib/libbsm/common/adt.c +++ b/usr/src/lib/libbsm/common/adt.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -2137,7 +2137,7 @@ adt_get_local_address(int family, struct ifaddrlist *al) int ifal_count; int i; - if ((ifal_count = ifaddrlist(&ifal, family, errbuf)) <= 0) { + if ((ifal_count = ifaddrlist(&ifal, family, 0, errbuf)) <= 0) { int serrno = errno; (void) snprintf(msg, sizeof (msg), "adt_get_local_address " diff --git a/usr/src/lib/libdlpi/common/libdlpi.c b/usr/src/lib/libdlpi/common/libdlpi.c index 14c4451081..d546807342 100644 --- a/usr/src/lib/libdlpi/common/libdlpi.c +++ b/usr/src/lib/libdlpi/common/libdlpi.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1109,7 +1109,7 @@ i_dlpi_open(const char *provider, int *fd, uint_t flags, boolean_t style1) /* open libdladm handle rather than taking it as input */ if (dladm_open(&handle) != DLADM_STATUS_OK) - return (DLPI_FAILURE); + goto fallback; if (dladm_dev2linkid(handle, device, &linkid) == DLADM_STATUS_OK) { @@ -1400,7 +1400,7 @@ i_dlpi_strgetmsg(dlpi_impl_t *dip, int msec, dlpi_msg_t *dlreplyp, void *databuf, size_t *datalenp, size_t *totdatalenp) { int retval; - int flags = 0; + int flags; int fd = dip->dli_fd; struct strbuf ctl, data; struct pollfd pfd; @@ -1437,16 +1437,17 @@ i_dlpi_strgetmsg(dlpi_impl_t *dip, int msec, dlpi_msg_t *dlreplyp, start = gethrtime() / (NANOSEC / MILLISEC); switch (poll(&pfd, 1, msec)) { - default: - if (pfd.revents & POLLHUP) - return (DL_SYSERR); - break; - case 0: - return (DLPI_ETIMEDOUT); - case -1: + default: + if (pfd.revents & POLLHUP) return (DL_SYSERR); + break; + case 0: + return (DLPI_ETIMEDOUT); + case -1: + return (DL_SYSERR); } + flags = 0; if ((retval = getmsg(fd, &ctl, &data, &flags)) < 0) return (DL_SYSERR); diff --git a/usr/src/lib/libinetcfg/common/inetcfg.c b/usr/src/lib/libinetcfg/common/inetcfg.c index 38beca5574..e1f09a881a 100644 --- a/usr/src/lib/libinetcfg/common/inetcfg.c +++ b/usr/src/lib/libinetcfg/common/inetcfg.c @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -743,7 +741,8 @@ icfg_set_flags(icfg_handle_t handle, uint64_t flags) struct lifreq lifr; uint64_t oflags; int ret; - int rtsock; + int rtsock = -1; + int aware = RTAW_UNDER_IPMP; (void) strlcpy(lifr.lifr_name, handle->ifh_interface.if_name, sizeof (lifr.lifr_name)); @@ -757,10 +756,16 @@ icfg_set_flags(icfg_handle_t handle, uint64_t flags) /* * Any time flags are changed on an interface that has IFF_UP set, * you'll get a routing socket message. We care about the status, - * though, only when the new flags are marked "up." + * though, only when the new flags are marked "up." Since we may be + * changing an IPMP test address, we enable RTAW_UNDER_IPMP. */ - rtsock = (flags & IFF_UP) ? - socket(PF_ROUTE, SOCK_RAW, ICFG_FAMILY(handle)) : -1; + if (flags & IFF_UP) { + rtsock = socket(PF_ROUTE, SOCK_RAW, ICFG_FAMILY(handle)); + if (rtsock != -1) { + (void) setsockopt(rtsock, SOL_ROUTE, RT_AWARE, &aware, + sizeof (aware)); + } + } lifr.lifr_flags = flags; if (ioctl(handle->ifh_sock, SIOCSLIFFLAGS, (caddr_t)&lifr) < 0) { @@ -993,7 +998,8 @@ icfg_set_addr(icfg_handle_t handle, const struct sockaddr *addr, struct lifreq lifr; uint64_t flags; int ret; - int rtsock; + int rtsock = -1; + int aware = RTAW_UNDER_IPMP; (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr)); if ((ret = to_sockaddr_storage(ICFG_FAMILY(handle), addr, addrlen, @@ -1002,15 +1008,19 @@ icfg_set_addr(icfg_handle_t handle, const struct sockaddr *addr, } /* - * Need to do check on duplicate address detection results if the - * interface is up. + * Need to check duplicate address detection results if the address is + * up. Since this may be an IPMP test address, enable RTAW_UNDER_IPMP. */ - if ((ret = icfg_get_flags(handle, &flags)) != ICFG_SUCCESS) { + if ((ret = icfg_get_flags(handle, &flags)) != ICFG_SUCCESS) return (ret); - } - rtsock = (flags & IFF_UP) ? - socket(PF_ROUTE, SOCK_RAW, ICFG_FAMILY(handle)) : -1; + if (flags & IFF_UP) { + rtsock = socket(PF_ROUTE, SOCK_RAW, ICFG_FAMILY(handle)); + if (rtsock != -1) { + (void) setsockopt(rtsock, SOL_ROUTE, RT_AWARE, &aware, + sizeof (aware)); + } + } (void) strlcpy(lifr.lifr_name, handle->ifh_interface.if_name, sizeof (lifr.lifr_name)); diff --git a/usr/src/lib/libinetutil/Makefile.com b/usr/src/lib/libinetutil/Makefile.com index 810f24bd71..cd3a0d6e33 100644 --- a/usr/src/lib/libinetutil/Makefile.com +++ b/usr/src/lib/libinetutil/Makefile.com @@ -19,15 +19,13 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# -LIBRARY = libinetutil.a -VERS = .1 -OBJECTS = octet.o inetutil4.o ifspec.o ifaddrlist.o eh.o tq.o +LIBRARY = libinetutil.a +VERS = .1 +OBJECTS = octet.o inetutil.o ifspec.o ifaddrlist.o ifaddrlistx.o eh.o tq.o include ../../Makefile.lib @@ -38,9 +36,9 @@ LIBS = $(DYNLIB) $(LINTLIB) SRCDIR = ../common COMDIR = $(SRC)/common/net/dhcp -SRCS = $(COMDIR)/octet.c $(SRCDIR)/inetutil4.c \ +SRCS = $(COMDIR)/octet.c $(SRCDIR)/inetutil.c \ $(SRCDIR)/ifspec.c $(SRCDIR)/eh.c $(SRCDIR)/tq.c \ - $(SRCDIR)/ifaddrlist.c + $(SRCDIR)/ifaddrlist.c $(SRCDIR)/ifaddrlistx.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 index 383dc2afb0..fa67a0fc37 100644 --- a/usr/src/lib/libinetutil/common/ifaddrlist.c +++ b/usr/src/lib/libinetutil/common/ifaddrlist.c @@ -1,5 +1,5 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -38,9 +38,6 @@ * @(#) $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> @@ -54,9 +51,9 @@ * See <libinetutil.h> for a description of the programming interface. */ int -ifaddrlist(struct ifaddrlist **ipaddrp, int family, char *errbuf) +ifaddrlist(struct ifaddrlist **ipaddrp, int family, uint_t flags, char *errbuf) { - struct ifaddrlist *ifaddrlist, *al; + struct ifaddrlist *ifaddrlist = NULL, *al = NULL; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; struct lifconf lifc; @@ -64,31 +61,28 @@ ifaddrlist(struct ifaddrlist **ipaddrp, int family, char *errbuf) struct lifreq *lifrp; int i, count, nlifr; int fd; - const char *iocstr; + const char *opstr; + (void) memset(&lifc, 0, sizeof (lifc)); 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); + if ((fd = socket(family, SOCK_DGRAM, 0)) == -1) { + opstr = "socket"; + goto fail; } /* * Get the number of network interfaces of type `family'. */ lifn.lifn_family = family; - lifn.lifn_flags = 0; + lifn.lifn_flags = flags; again: if (ioctl(fd, SIOCGLIFNUM, &lifn) == -1) { - (void) snprintf(errbuf, ERRBUFSIZE, "SIOCGLIFNUM: %s", - strerror(errno)); - (void) close(fd); - return (-1); + opstr = "SIOCGLIFNUM"; + goto fail; } /* @@ -97,16 +91,17 @@ again: */ lifn.lifn_count += 4; + lifc.lifc_flags = flags; 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 ((lifc.lifc_buf = realloc(lifc.lifc_buf, lifc.lifc_len)) == NULL) { + opstr = "realloc"; + goto fail; + } if (ioctl(fd, SIOCGLIFCONF, &lifc) == -1) { - (void) snprintf(errbuf, ERRBUFSIZE, "SIOCGLIFCONF: %s", - strerror(errno)); - (void) close(fd); - return (-1); + opstr = "SIOCGLIFCONF"; + goto fail; } /* @@ -121,12 +116,9 @@ 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); + if ((ifaddrlist = calloc(nlifr, sizeof (struct ifaddrlist))) == NULL) { + opstr = "calloc"; + goto fail; } /* @@ -142,7 +134,7 @@ again: if (ioctl(fd, SIOCGLIFFLAGS, lifrp) == -1) { if (errno == ENXIO) continue; - iocstr = "SIOCGLIFFLAGS"; + opstr = "SIOCGLIFFLAGS"; goto fail; } al->flags = lifrp->lifr_flags; @@ -150,7 +142,7 @@ again: if (ioctl(fd, SIOCGLIFINDEX, lifrp) == -1) { if (errno == ENXIO) continue; - iocstr = "SIOCGLIFINDEX"; + opstr = "SIOCGLIFINDEX"; goto fail; } al->index = lifrp->lifr_index; @@ -158,7 +150,7 @@ again: if (ioctl(fd, SIOCGLIFADDR, lifrp) == -1) { if (errno == ENXIO) continue; - iocstr = "SIOCGLIFADDR"; + opstr = "SIOCGLIFADDR"; goto fail; } @@ -174,6 +166,7 @@ again: } (void) close(fd); + free(lifc.lifc_buf); if (count == 0) { free(ifaddrlist); *ipaddrp = NULL; @@ -183,9 +176,14 @@ again: *ipaddrp = ifaddrlist; return (count); fail: - (void) snprintf(errbuf, ERRBUFSIZE, "%s: %s: %s", iocstr, al->device, - strerror(errno)); - + if (al == NULL) { + (void) snprintf(errbuf, ERRBUFSIZE, "%s: %s", opstr, + strerror(errno)); + } else { + (void) snprintf(errbuf, ERRBUFSIZE, "%s: %s: %s", opstr, + al->device, strerror(errno)); + } + free(lifc.lifc_buf); free(ifaddrlist); (void) close(fd); return (-1); diff --git a/usr/src/lib/libinetutil/common/ifaddrlistx.c b/usr/src/lib/libinetutil/common/ifaddrlistx.c new file mode 100644 index 0000000000..ce85c5521f --- /dev/null +++ b/usr/src/lib/libinetutil/common/ifaddrlistx.c @@ -0,0 +1,168 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#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> + +/* + * Create a list of the addresses on physical interface `ifname' with at least + * one of the flags in `set' set and all of the flags in `clear' clear. + * Return the number of items in the list, or -1 on failure. + */ +int +ifaddrlistx(const char *ifname, uint64_t set, uint64_t clear, + ifaddrlistx_t **ifaddrsp) +{ + struct lifconf lifc; + struct lifnum lifn; + struct lifreq *lifrp; + ifaddrlistx_t *ifaddrp, *ifaddrs = NULL; + int i, nlifr, naddr = 0; + char *cp; + uint_t flags; + int s4, s6 = -1; + boolean_t isv6; + int save_errno; + struct sockaddr_storage addr; + + (void) memset(&lifc, 0, sizeof (lifc)); + flags = LIFC_NOXMIT | LIFC_ALLZONES | LIFC_TEMPORARY | LIFC_UNDER_IPMP; + + /* + * We need both IPv4 and IPv6 sockets to query both IPv4 and IPv6 + * interfaces below. + */ + if ((s4 = socket(AF_INET, SOCK_DGRAM, 0)) == -1 || + (s6 = socket(AF_INET6, SOCK_DGRAM, 0)) == -1) { + goto fail; + } + + /* + * Get the number of network interfaces of type `family'. + */ + lifn.lifn_family = AF_UNSPEC; + lifn.lifn_flags = flags; +again: + if (ioctl(s4, SIOCGLIFNUM, &lifn) == -1) + goto fail; + + /* + * Pad the interface count to detect when additional interfaces have + * been configured between SIOCGLIFNUM and SIOCGLIFCONF. + */ + lifn.lifn_count += 4; + + lifc.lifc_flags = flags; + lifc.lifc_family = AF_UNSPEC; + lifc.lifc_len = lifn.lifn_count * sizeof (struct lifreq); + if ((lifc.lifc_buf = realloc(lifc.lifc_buf, lifc.lifc_len)) == NULL) + goto fail; + + if (ioctl(s4, SIOCGLIFCONF, &lifc) == -1) + goto fail; + + /* + * 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; + + /* + * Populate the ifaddrlistx by querying each matching interface. If a + * query ioctl returns ENXIO, then the interface must have been + * removed after the SIOCGLIFCONF completed -- so we just ignore it. + */ + for (lifrp = lifc.lifc_req, i = 0; i < nlifr; i++, lifrp++) { + if ((cp = strchr(lifrp->lifr_name, ':')) != NULL) + *cp = '\0'; + + if (strcmp(lifrp->lifr_name, ifname) != 0) + continue; + + if (cp != NULL) + *cp = ':'; + + addr = lifrp->lifr_addr; + isv6 = addr.ss_family == AF_INET6; + if (ioctl(isv6 ? s6 : s4, SIOCGLIFFLAGS, lifrp) == -1) { + if (errno == ENXIO) + continue; + goto fail; + } + + if (set != 0 && ((lifrp->lifr_flags & set) == 0) || + (lifrp->lifr_flags & clear) != 0) + continue; + + /* + * We've got a match; allocate a new record. + */ + if ((ifaddrp = malloc(sizeof (ifaddrlistx_t))) == NULL) + goto fail; + + (void) strlcpy(ifaddrp->ia_name, lifrp->lifr_name, LIFNAMSIZ); + ifaddrp->ia_flags = lifrp->lifr_flags; + ifaddrp->ia_addr = addr; + ifaddrp->ia_next = ifaddrs; + ifaddrs = ifaddrp; + naddr++; + } + + (void) close(s4); + (void) close(s6); + free(lifc.lifc_buf); + *ifaddrsp = ifaddrs; + return (naddr); +fail: + save_errno = errno; + (void) close(s4); + (void) close(s6); + free(lifc.lifc_buf); + ifaddrlistx_free(ifaddrs); + errno = save_errno; + return (-1); +} + +/* + * Free the provided ifaddrlistx_t. + */ +void +ifaddrlistx_free(ifaddrlistx_t *ifaddrp) +{ + ifaddrlistx_t *next_ifaddrp; + + for (; ifaddrp != NULL; ifaddrp = next_ifaddrp) { + next_ifaddrp = ifaddrp->ia_next; + free(ifaddrp); + } +} diff --git a/usr/src/lib/libinetutil/common/inetutil4.c b/usr/src/lib/libinetutil/common/inetutil.c index ff5607e192..195d080b79 100644 --- a/usr/src/lib/libinetutil/common/inetutil4.c +++ b/usr/src/lib/libinetutil/common/inetutil.c @@ -18,13 +18,12 @@ * * CDDL HEADER END */ + /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <unistd.h> #include <netinet/in.h> #include <libinetutil.h> @@ -32,7 +31,7 @@ extern int getnetmaskbyaddr(const struct in_addr, struct in_addr *); /* - * Generic internet (v4) functions. + * Internet utility functions. */ /* @@ -67,3 +66,32 @@ get_netmask4(const struct in_addr *n_addrp, struct in_addr *s_addrp) else s_addrp->s_addr = IN_CLASSE_NET; } + +/* + * Checks if the IP addresses `ssp1' and `ssp2' are equal. + */ +boolean_t +sockaddrcmp(const struct sockaddr_storage *ssp1, + const struct sockaddr_storage *ssp2) +{ + struct in_addr addr1, addr2; + const struct in6_addr *addr6p1, *addr6p2; + + if (ssp1->ss_family != ssp2->ss_family) + return (B_FALSE); + + if (ssp1 == ssp2) + return (B_TRUE); + + switch (ssp1->ss_family) { + case AF_INET: + addr1 = ((const struct sockaddr_in *)ssp1)->sin_addr; + addr2 = ((const struct sockaddr_in *)ssp2)->sin_addr; + return (addr1.s_addr == addr2.s_addr); + case AF_INET6: + addr6p1 = &((const struct sockaddr_in6 *)ssp1)->sin6_addr; + addr6p2 = &((const struct sockaddr_in6 *)ssp2)->sin6_addr; + return (IN6_ARE_ADDR_EQUAL(addr6p1, addr6p2)); + } + return (B_FALSE); +} diff --git a/usr/src/lib/libinetutil/common/libinetutil.h b/usr/src/lib/libinetutil/common/libinetutil.h index b21d54f56c..0bece07e07 100644 --- a/usr/src/lib/libinetutil/common/libinetutil.h +++ b/usr/src/lib/libinetutil/common/libinetutil.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -21,15 +20,13 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _LIBINETUTIL_H #define _LIBINETUTIL_H -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Contains SMI-private API for general Internet functionality */ @@ -59,11 +56,14 @@ typedef struct { extern boolean_t ifparse_ifspec(const char *, ifspec_t *); extern void get_netmask4(const struct in_addr *, struct in_addr *); +extern boolean_t sockaddrcmp(const struct sockaddr_storage *, + const struct sockaddr_storage *); /* * Extended version of the classic BSD ifaddrlist() interface: * - * int ifaddrlist(struct ifaddrlist **addrlistp, int af, char *errbuf); + * int ifaddrlist(struct ifaddrlist **addrlistp, int af, uint_t flags, + * char *errbuf); * * * addrlistp: Upon success, ifaddrlist() sets *addrlistp to a * dynamically-allocated array of addresses. @@ -71,6 +71,9 @@ extern void get_netmask4(const struct in_addr *, struct in_addr *); * * af: Either AF_INET to obtain IPv4 addresses, or AF_INET6 to * obtain IPv6 addresses. * + * * flags: LIFC_* flags that control the classes of interfaces that + * will be visible. + * * * errbuf: A caller-supplied buffer of ERRBUFSIZE. Upon failure, * provides the reason for the failure. * @@ -89,9 +92,43 @@ struct ifaddrlist { uint64_t flags; /* interface flags */ }; -#define ERRBUFSIZE 128 /* expected size of third argument */ +#define ERRBUFSIZE 128 /* expected size of fourth argument */ + +extern int ifaddrlist(struct ifaddrlist **, int, uint_t, char *); -extern int ifaddrlist(struct ifaddrlist **, int, char *); +/* + * Similar to ifaddrlist(), but returns a linked-list of addresses for a + * *specific* interface name, and allows specific address flags to be matched + * against. A linked list is used rather than an array so that information + * can grow over time without affecting binary compatibility. Also, leaves + * error-handling up to the caller. Returns the number of ifaddrlistx's + * chained through ifaddrp. + * + * int ifaddrlistx(const char *ifname, uint64_t set, uint64_t clear, + * ifaddrlistx_t **ifaddrp); + * + * * ifname: Interface name to match against. + * + * * set: One or more flags that must be set on the address for + * it to be returned. + * + * * clear: Flags that must be clear on the address for it to be + * returned. + * + * * ifaddrp: Upon success, ifaddrlistx() sets *ifaddrp to the head + * of a dynamically-allocated array of ifaddrlistx structures. + * + * Once done, the caller must free `ifaddrp' by calling ifaddrlistx_free(). + */ +typedef struct ifaddrlistx { + struct ifaddrlistx *ia_next; + char ia_name[LIFNAMSIZ]; + uint64_t ia_flags; + struct sockaddr_storage ia_addr; +} ifaddrlistx_t; + +extern int ifaddrlistx(const char *, uint64_t, uint64_t, ifaddrlistx_t **); +extern void ifaddrlistx_free(ifaddrlistx_t *); /* * Timer queues diff --git a/usr/src/lib/libinetutil/common/mapfile-vers b/usr/src/lib/libinetutil/common/mapfile-vers index 51c168fcc4..c9a7829fdb 100644 --- a/usr/src/lib/libinetutil/common/mapfile-vers +++ b/usr/src/lib/libinetutil/common/mapfile-vers @@ -19,17 +19,17 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# SUNWprivate_1.1 { global: get_netmask4; hexascii_to_octet; ifaddrlist; + ifaddrlistx; + ifaddrlistx_free; ifparse_ifspec; iu_adjust_timer; iu_cancel_timer; @@ -48,6 +48,7 @@ SUNWprivate_1.1 { iu_tq_destroy; iu_unregister_event; octet_to_hexascii; + sockaddrcmp; local: *; }; diff --git a/usr/src/lib/libipmp/Makefile b/usr/src/lib/libipmp/Makefile index 188c49c073..5d52f304dc 100644 --- a/usr/src/lib/libipmp/Makefile +++ b/usr/src/lib/libipmp/Makefile @@ -19,15 +19,13 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# include $(SRC)/lib/Makefile.lib -HDRS = ipmp.h ipmp_mpathd.h ipmp_query.h ipmp_query_impl.h +HDRS = ipmp.h ipmp_admin.h ipmp_mpathd.h ipmp_query.h ipmp_query_impl.h HDRDIR = common SUBDIRS = $(MACH) diff --git a/usr/src/lib/libipmp/Makefile.com b/usr/src/lib/libipmp/Makefile.com index bea02659a8..d3065ae37c 100644 --- a/usr/src/lib/libipmp/Makefile.com +++ b/usr/src/lib/libipmp/Makefile.com @@ -19,20 +19,19 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# LIBRARY = libipmp.a VERS = .1 -OBJECTS = ipmp_query.o ipmp_mpathd.o ipmp.o +OBJECTS = ipmp_admin.o ipmp_query.o ipmp_mpathd.o ipmp.o include ../../Makefile.lib +include ../../Makefile.rootfs LIBS = $(DYNLIB) $(LINTLIB) -LDLIBS += -lsocket -lc +LDLIBS += -linetutil -lsocket -lc SRCDIR = ../common $(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC) diff --git a/usr/src/lib/libipmp/common/ipmp.c b/usr/src/lib/libipmp/common/ipmp.c index b9a7984889..cf9c3c7c3c 100644 --- a/usr/src/lib/libipmp/common/ipmp.c +++ b/usr/src/lib/libipmp/common/ipmp.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * IPMP general interfaces (PSARC/2002/615). */ @@ -34,6 +31,8 @@ #include <stdlib.h> #include <locale.h> #include <unistd.h> +#include <string.h> +#include <errno.h> #include "ipmp_impl.h" @@ -92,13 +91,15 @@ static char *errmsgs[IPMP_NERR] = { "operation failed", /* 1 IPMP_FAILURE */ "minimum failover redundancy not met", /* 2 IPMP_EMINRED */ "failback disabled", /* 3 IPMP_EFBDISABLED */ - "unable to completely fail back", /* 4 IPMP_EFBPARTIAL */ + "unknown IPMP data address", /* 4 IPMP_EUNKADDR */ "invalid argument", /* 5 IPMP_EINVAL */ "out of memory", /* 6 IPMP_ENOMEM */ "cannot contact in.mpathd", /* 7 IPMP_ENOMPATHD */ "unknown IPMP group", /* 8 IPMP_EUNKGROUP */ "interface is not using IPMP", /* 9 IPMP_EUNKIF */ - "unable to communicate with in.mpathd" /* 10 IPMP_EPROTO */ + "unable to communicate with in.mpathd", /* 10 IPMP_EPROTO */ + "interface has duplicate hardware address" + /* 11 IPMP_EHWADDRDUP */ }; /* @@ -110,5 +111,8 @@ ipmp_errmsg(int error) if (error >= IPMP_NERR || error < 0) return (dgettext(TEXT_DOMAIN, "<unknown error>")); + if (error == IPMP_FAILURE) + return (strerror(errno)); + return (dgettext(TEXT_DOMAIN, errmsgs[error])); } diff --git a/usr/src/lib/libipmp/common/ipmp.h b/usr/src/lib/libipmp/common/ipmp.h index 0112615a84..2ca0a9b2b9 100644 --- a/usr/src/lib/libipmp/common/ipmp.h +++ b/usr/src/lib/libipmp/common/ipmp.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,15 +19,13 @@ * CDDL HEADER END */ /* - * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _IPMP_H #define _IPMP_H -#pragma ident "%Z%%M% %I% %E% SMI" - /* * General IPMP-related definitions and functions. * @@ -50,13 +47,14 @@ enum { IPMP_FAILURE, /* operation failed (check errno) */ IPMP_EMINRED, /* minimum failover redundancy not met */ IPMP_EFBDISABLED, /* failback disabled */ - IPMP_EFBPARTIAL, /* unable to completely fail back */ + IPMP_EUNKADDR, /* unknown IPMP data address */ IPMP_EINVAL, /* invalid argument */ IPMP_ENOMEM, /* out of memory */ IPMP_ENOMPATHD, /* cannot contact in.mpathd */ IPMP_EUNKGROUP, /* unknown IPMP group */ IPMP_EUNKIF, /* interface is not using IPMP */ IPMP_EPROTO, /* unable to communicate with in.mpathd */ + IPMP_EHWADDRDUP, /* interface has duplicate hardware address */ IPMP_NERR /* number of error codes */ }; diff --git a/usr/src/lib/libipmp/common/ipmp_admin.c b/usr/src/lib/libipmp/common/ipmp_admin.c new file mode 100644 index 0000000000..8a282f5286 --- /dev/null +++ b/usr/src/lib/libipmp/common/ipmp_admin.c @@ -0,0 +1,104 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * IPMP administrative interfaces (see PSARC/2007/272). + */ + +#include <assert.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <sys/time.h> +#include <sys/types.h> + +#include "ipmp_impl.h" +#include "ipmp_mpathd.h" +#include "ipmp_admin.h" + +static int +ipmp_command(ipmp_handle_t handle, const void *req, uint_t reqsize) +{ + ipmp_state_t *statep = (ipmp_state_t *)handle; + mi_result_t result; + struct timeval end; + int save_errno; + int retval; + + if (gettimeofday(&end, NULL) == -1) + return (IPMP_FAILURE); + end.tv_sec += IPMP_REQTIMEOUT; + + assert(statep->st_fd == -1); + retval = ipmp_connect(&statep->st_fd); + if (retval != IPMP_SUCCESS) + return (retval); + + retval = ipmp_write(statep->st_fd, req, reqsize); + if (retval != IPMP_SUCCESS) + goto out; + + retval = ipmp_read(statep->st_fd, &result, sizeof (result), &end); + if (retval != IPMP_SUCCESS) + goto out; + + errno = result.me_sys_error; + retval = result.me_mpathd_error; +out: + save_errno = errno; + (void) close(statep->st_fd); + statep->st_fd = -1; + errno = save_errno; + return (retval); +} + +int +ipmp_offline(ipmp_handle_t handle, const char *ifname, uint_t minred) +{ + mi_offline_t mio; + + mio.mio_command = MI_OFFLINE; + mio.mio_min_redundancy = minred; + (void) strlcpy(mio.mio_ifname, ifname, LIFNAMSIZ); + return (ipmp_command(handle, &mio, sizeof (mio))); +} + +int +ipmp_undo_offline(ipmp_handle_t handle, const char *ifname) +{ + mi_undo_offline_t miu; + + miu.miu_command = MI_UNDO_OFFLINE; + (void) strlcpy(miu.miu_ifname, ifname, LIFNAMSIZ); + return (ipmp_command(handle, &miu, sizeof (miu))); +} + +int +ipmp_ping_daemon(ipmp_handle_t handle) +{ + mi_ping_t mip; + + mip.mip_command = MI_PING; + return (ipmp_command(handle, &mip, sizeof (mip))); +} diff --git a/usr/src/lib/libipmp/common/ipmp_admin.h b/usr/src/lib/libipmp/common/ipmp_admin.h new file mode 100644 index 0000000000..fa0986f7fa --- /dev/null +++ b/usr/src/lib/libipmp/common/ipmp_admin.h @@ -0,0 +1,50 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _IPMP_ADMIN_H +#define _IPMP_ADMIN_H + +#include <ipmp.h> +#include <sys/types.h> + +/* + * IPMP administrative interfaces. + * + * These interfaces may only be used within ON or after signing a contract + * with ON. For documentation, refer to PSARC/2007/272. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int ipmp_offline(ipmp_handle_t, const char *, uint_t); +extern int ipmp_undo_offline(ipmp_handle_t, const char *); +extern int ipmp_ping_daemon(ipmp_handle_t); + +#ifdef __cplusplus +} +#endif + +#endif /* _IPMP_ADMIN_H */ diff --git a/usr/src/lib/libipmp/common/ipmp_mpathd.c b/usr/src/lib/libipmp/common/ipmp_mpathd.c index ee1d35de33..e24de71017 100644 --- a/usr/src/lib/libipmp/common/ipmp_mpathd.c +++ b/usr/src/lib/libipmp/common/ipmp_mpathd.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -18,14 +17,11 @@ * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END - */ -/* - * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Low-level interfaces for communicating with in.mpathd(1M). * @@ -66,16 +62,16 @@ ipmp_connect(int *fdp) return (IPMP_FAILURE); /* - * Enable TCP_ANONPRIVBIND so the kernel will choose our source port. - * Since we're using loopback sockets, requiring use of privileged - * source ports is sufficient for security. + * If we have sufficient privilege, enable TCP_ANONPRIVBIND so the + * kernel will choose a privileged source port (since in.mpathd only + * accepts requests on loopback, this is sufficient for security). + * If not, drive on since MI_QUERY and MI_PING commands are allowed + * from non-privileged ports. */ - if (setsockopt(fd, IPPROTO_TCP, TCP_ANONPRIVBIND, &on, - sizeof (on)) == -1) - goto fail; + (void) setsockopt(fd, IPPROTO_TCP, TCP_ANONPRIVBIND, &on, sizeof (on)); /* - * Bind to a privileged port chosen by the kernel. + * Bind to a port chosen by the kernel. */ (void) memset(&sin, 0, sizeof (struct sockaddr_in)); sin.sin_port = htons(0); diff --git a/usr/src/lib/libipmp/common/ipmp_mpathd.h b/usr/src/lib/libipmp/common/ipmp_mpathd.h index 61ae71b78f..7df3b4fd92 100644 --- a/usr/src/lib/libipmp/common/ipmp_mpathd.h +++ b/usr/src/lib/libipmp/common/ipmp_mpathd.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -18,26 +17,17 @@ * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END - */ -/* - * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _IPMP_MPATHD_H #define _IPMP_MPATHD_H -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Definitions for the messaging protocol between in.mpathd and libipmp. - * This interface is loosely documented in PSARC/2000/306. - * - * PLEASE NOTE: Although this interface is officially consolidation-private, - * we will be reclassifying it as project-private in the future, and - * transitioning any existing consumers to use higher-level libipmp routines. - * - * Put another way: treat this as if it was project-private! + * This interface is project-private to the IPMP subsystem. */ #include <sys/types.h> @@ -49,33 +39,41 @@ extern "C" { #endif #define MPATHD_PORT 5999 -#define MPATHD_PATH "/usr/lib/inet/in.mpathd" +#define MPATHD_PATH "/lib/inet/in.mpathd" /* * Supported commands. */ enum { - MI_PING = 0, /* sanity test */ + MI_PING = 0, /* ping in.mpathd */ MI_OFFLINE = 1, /* offline the interface */ MI_UNDO_OFFLINE = 2, /* undo the offline */ - MI_SETOINDEX = 3, /* set original interface index */ - MI_QUERY = 4, /* query ipmp-related information */ + MI_QUERY = 3, /* query ipmp-related information */ MI_NCMD /* total number of commands */ }; /* * Types of information which can be requested and received (except for - * IPMP_IFLIST, which can only be received). + * IPMP_IFLIST and IPMP_ADDRLIST, which can only be received). */ typedef enum { IPMP_GROUPLIST = 1, IPMP_GROUPINFO = 2, IPMP_IFINFO = 3, IPMP_IFLIST = 4, - IPMP_SNAP = 5 + IPMP_SNAP = 5, + IPMP_ADDRLIST = 6, + IPMP_ADDRINFO = 7 } ipmp_infotype_t; /* + * Daemon ping request. + */ +typedef struct mi_ping { + uint32_t mip_command; +} mi_ping_t; + +/* * Interface offline request; `mio_ifname' is the interface to offline; * `mio_min_redundancy' is the minimum amount of usable interfaces after * offline that must exist for the operation to succeed. @@ -83,7 +81,6 @@ typedef enum { typedef struct mi_offline { uint32_t mio_command; char mio_ifname[LIFNAMSIZ]; - char mio_move_to_if[LIFNAMSIZ]; /* currently unused */ uint32_t mio_min_redundancy; } mi_offline_t; @@ -97,24 +94,12 @@ typedef struct mi_undo_offline { } mi_undo_offline_t; /* - * Set original interface index request: `mis_lifname' is the name of the - * logical interface that is having its index reset; `mis_new_pifname' is the - * name of the interface whose index will be associated with `mis_lifname'; - * `mis_iftype' is the interface type. - */ -typedef struct mi_setoindex { - uint32_t mis_command; - char mis_lifname[LIFNAMSIZ]; - char mis_new_pifname[LIFNAMSIZ]; - uint32_t mis_iftype; -} mi_setoindex_t; - -/* * Retrieve IPMP-related information: `miq_inforeq' is the type of information - * being request (see above for the list of types). If the request is for - * either IPMP_GROUPINFO or IPMP_IFINFO, then either `miq_grname' or - * `miq_ifname' should be set (respectively) to indicate the name of the - * group or interface to retrieve the information for. + * being request (see above for the list of types). If the request type is + * IPMP_GROUPINFO, then `miq_grname' indicates the group. If the request type + * is IPMP_IFINFO, then `miq_ifname' indicates the interface. If the request + * type is IPMP_ADDRINFO then `miq_grname' indicates the group and `miq_addr' + * indicates the address. */ typedef struct mi_query { uint32_t miq_command; @@ -123,6 +108,7 @@ typedef struct mi_query { char miqu_ifname[LIFNAMSIZ]; char miqu_grname[LIFGRNAMSIZ]; } miq_infodata; + struct sockaddr_storage miq_addr; } mi_query_t; #define miq_ifname miq_infodata.miqu_ifname #define miq_grname miq_infodata.miqu_grname @@ -132,10 +118,10 @@ typedef struct mi_query { * requirement for receiving any command. */ union mi_commands { - uint32_t mi_command; + uint32_t mi_command; + mi_ping_t mi_pcmd; mi_offline_t mi_ocmd; mi_undo_offline_t mi_ucmd; - mi_setoindex_t mi_scmd; mi_query_t mi_qcmd; }; @@ -147,18 +133,7 @@ typedef struct mi_result { uint32_t me_mpathd_error; /* Mpathd error */ } mi_result_t; -/* - * Legacy values for me_mpathd_error; the daemon now returns the IPMP - * error codes defined in <ipmp.h>, which are compatible with these error - * codes. These will be removed in the future. - */ -enum { - MPATHD_SUCCESS = 0, /* operation succeeded */ - MPATHD_SYS_ERROR = 1, /* check me_sys_error for the errno */ - MPATHD_MIN_RED_ERROR = 2, /* minimum redundancy not met */ - MPATHD_FAILBACK_DISABLED = 3, /* failback administratively disabled */ - MPATHD_FAILBACK_PARTIAL = 4 /* unable to completely failback */ -}; +#define IPMP_REQTIMEOUT 5 /* seconds */ extern int ipmp_connect(int *); extern int ipmp_read(int, void *, size_t, const struct timeval *); diff --git a/usr/src/lib/libipmp/common/ipmp_query.c b/usr/src/lib/libipmp/common/ipmp_query.c index 8a7dc7ee69..a0af2da578 100644 --- a/usr/src/lib/libipmp/common/ipmp_query.c +++ b/usr/src/lib/libipmp/common/ipmp_query.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -18,20 +17,18 @@ * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END - */ -/* - * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* - * IPMP query interfaces (PSARC/2002/615). + * IPMP query interfaces (see PSARC/2002/615 and PSARC/2007/272). */ #include <assert.h> #include <errno.h> +#include <libinetutil.h> #include <string.h> #include <stdlib.h> #include <unistd.h> @@ -41,13 +38,19 @@ #include "ipmp_mpathd.h" #include "ipmp_query_impl.h" -#define IPMP_REQTIMEOUT 5 /* seconds */ - static ipmp_ifinfo_t *ipmp_ifinfo_clone(ipmp_ifinfo_t *); +static ipmp_addrinfo_t *ipmp_addrinfo_clone(ipmp_addrinfo_t *); +static ipmp_addrlist_t *ipmp_addrlist_clone(ipmp_addrlist_t *); static ipmp_grouplist_t *ipmp_grouplist_clone(ipmp_grouplist_t *); static ipmp_groupinfo_t *ipmp_groupinfo_clone(ipmp_groupinfo_t *); +static ipmp_iflist_t *ipmp_iflist_create(uint_t, char (*)[LIFNAMSIZ]); +static void ipmp_freeiflist(ipmp_iflist_t *); +static ipmp_addrlist_t *ipmp_addrlist_create(uint_t, struct sockaddr_storage *); +static void ipmp_freeaddrlist(ipmp_addrlist_t *); static ipmp_groupinfo_t *ipmp_snap_getgroupinfo(ipmp_snap_t *, const char *); static ipmp_ifinfo_t *ipmp_snap_getifinfo(ipmp_snap_t *, const char *); +static ipmp_addrinfo_t *ipmp_snap_getaddrinfo(ipmp_snap_t *, const char *, + struct sockaddr_storage *); static int ipmp_snap_take(ipmp_state_t *, ipmp_snap_t **); static boolean_t ipmp_checktlv(ipmp_infotype_t, size_t, void *); static int ipmp_querydone(ipmp_state_t *, int); @@ -62,7 +65,7 @@ static int ipmp_querydone(ipmp_state_t *, int); */ static int ipmp_sendquery(ipmp_state_t *statep, ipmp_infotype_t type, const char *name, - struct timeval *endtp) + const void *addr, struct timeval *endtp) { mi_query_t query; mi_result_t result; @@ -72,6 +75,11 @@ ipmp_sendquery(ipmp_state_t *statep, ipmp_infotype_t type, const char *name, query.miq_inforeq = type; switch (type) { + case IPMP_ADDRINFO: + (void) strlcpy(query.miq_grname, name, LIFGRNAMSIZ); + query.miq_addr = *(struct sockaddr_storage *)addr; + break; + case IPMP_GROUPINFO: (void) strlcpy(query.miq_grname, name, LIFGRNAMSIZ); break; @@ -138,6 +146,61 @@ ipmp_readinfo(ipmp_state_t *statep, ipmp_infotype_t infotype, void **infop, } /* + * Using `statep', read in the remaining IPMP group information TLVs from + * in.mpathd into `grinfop' before the current time becomes `endtp'. Returns + * an IPMP error code. On failure, `grinfop' will have its original contents. + */ +static int +ipmp_readgroupinfo_lists(ipmp_state_t *statep, ipmp_groupinfo_t *grinfop, + const struct timeval *endtp) +{ + int retval; + ipmp_iflist_t *iflistp; + ipmp_addrlist_t *adlistp; + + retval = ipmp_readinfo(statep, IPMP_IFLIST, (void **)&iflistp, endtp); + if (retval != IPMP_SUCCESS) + return (retval); + + retval = ipmp_readinfo(statep, IPMP_ADDRLIST, (void **)&adlistp, endtp); + if (retval != IPMP_SUCCESS) { + ipmp_freeiflist(iflistp); + return (retval); + } + + grinfop->gr_iflistp = iflistp; + grinfop->gr_adlistp = adlistp; + return (IPMP_SUCCESS); +} + +/* + * Using `statep', read in the remaining IPMP interface information TLVs from + * in.mpathd into `ifinfop' before the current time becomes `endtp'. Returns + * an IPMP error code. On failure, `ifinfop' will have its original contents. + */ +static int +ipmp_readifinfo_lists(ipmp_state_t *statep, ipmp_ifinfo_t *ifinfop, + const struct timeval *endtp) +{ + int retval; + ipmp_addrlist_t *tlist4p, *tlist6p; + + retval = ipmp_readinfo(statep, IPMP_ADDRLIST, (void **)&tlist4p, endtp); + if (retval != IPMP_SUCCESS) + return (retval); + + retval = ipmp_readinfo(statep, IPMP_ADDRLIST, (void **)&tlist6p, endtp); + if (retval != IPMP_SUCCESS) { + ipmp_freeaddrlist(tlist4p); + return (retval); + } + + ifinfop->if_targinfo4.it_targlistp = tlist4p; + ifinfop->if_targinfo6.it_targlistp = tlist6p; + return (IPMP_SUCCESS); +} + +/* * Complete the query operation started in ipmp_sendquery(). The interface is * designed to be easy to use in the `return' statement of a function, and * thus returns the passed in `retval' and preserves `errno'. @@ -169,7 +232,7 @@ ipmp_getgrouplist(ipmp_handle_t handle, ipmp_grouplist_t **grlistpp) return (*grlistpp != NULL ? IPMP_SUCCESS : IPMP_ENOMEM); } - retval = ipmp_sendquery(statep, IPMP_GROUPLIST, NULL, &end); + retval = ipmp_sendquery(statep, IPMP_GROUPLIST, NULL, NULL, &end); if (retval != IPMP_SUCCESS) return (retval); @@ -196,7 +259,6 @@ ipmp_getgroupinfo(ipmp_handle_t handle, const char *name, ipmp_groupinfo_t **grinfopp) { ipmp_state_t *statep = handle; - ipmp_iflist_t *iflistp; int retval; struct timeval end; ipmp_groupinfo_t *grinfop; @@ -210,7 +272,7 @@ ipmp_getgroupinfo(ipmp_handle_t handle, const char *name, return (*grinfopp != NULL ? IPMP_SUCCESS : IPMP_ENOMEM); } - retval = ipmp_sendquery(statep, IPMP_GROUPINFO, name, &end); + retval = ipmp_sendquery(statep, IPMP_GROUPINFO, name, NULL, &end); if (retval != IPMP_SUCCESS) return (retval); @@ -218,11 +280,9 @@ ipmp_getgroupinfo(ipmp_handle_t handle, const char *name, if (retval != IPMP_SUCCESS) return (ipmp_querydone(statep, retval)); - retval = ipmp_readinfo(statep, IPMP_IFLIST, (void **)&iflistp, &end); + retval = ipmp_readgroupinfo_lists(statep, *grinfopp, &end); if (retval != IPMP_SUCCESS) free(*grinfopp); - else - (*grinfopp)->gr_iflistp = iflistp; return (ipmp_querydone(statep, retval)); } @@ -233,7 +293,8 @@ ipmp_getgroupinfo(ipmp_handle_t handle, const char *name, void ipmp_freegroupinfo(ipmp_groupinfo_t *grinfop) { - free(grinfop->gr_iflistp); + ipmp_freeaddrlist(grinfop->gr_adlistp); + ipmp_freeiflist(grinfop->gr_iflistp); free(grinfop); } @@ -259,11 +320,18 @@ ipmp_getifinfo(ipmp_handle_t handle, const char *name, ipmp_ifinfo_t **ifinfopp) return (*ifinfopp != NULL ? IPMP_SUCCESS : IPMP_ENOMEM); } - retval = ipmp_sendquery(statep, IPMP_IFINFO, name, &end); + retval = ipmp_sendquery(statep, IPMP_IFINFO, name, NULL, &end); if (retval != IPMP_SUCCESS) return (retval); retval = ipmp_readinfo(statep, IPMP_IFINFO, (void **)ifinfopp, &end); + if (retval != IPMP_SUCCESS) + return (ipmp_querydone(statep, retval)); + + retval = ipmp_readifinfo_lists(statep, *ifinfopp, &end); + if (retval != IPMP_SUCCESS) + free(*ifinfopp); + return (ipmp_querydone(statep, retval)); } @@ -273,10 +341,52 @@ ipmp_getifinfo(ipmp_handle_t handle, const char *name, ipmp_ifinfo_t **ifinfopp) void ipmp_freeifinfo(ipmp_ifinfo_t *ifinfop) { + ipmp_freeaddrlist(ifinfop->if_targinfo4.it_targlistp); + ipmp_freeaddrlist(ifinfop->if_targinfo6.it_targlistp); free(ifinfop); } /* + * Using `handle', get the address information associated with address `addrp' + * on group `grname' and store the results in a dynamically allocated buffer + * pointed to by `*adinfopp'. Returns an IPMP error code. + */ +int +ipmp_getaddrinfo(ipmp_handle_t handle, const char *grname, + struct sockaddr_storage *addrp, ipmp_addrinfo_t **adinfopp) +{ + ipmp_state_t *statep = handle; + ipmp_addrinfo_t *adinfop; + int retval; + struct timeval end; + + if (statep->st_snap != NULL) { + adinfop = ipmp_snap_getaddrinfo(statep->st_snap, grname, addrp); + if (adinfop == NULL) + return (IPMP_EUNKADDR); + + *adinfopp = ipmp_addrinfo_clone(adinfop); + return (*adinfopp != NULL ? IPMP_SUCCESS : IPMP_ENOMEM); + } + + retval = ipmp_sendquery(statep, IPMP_ADDRINFO, grname, addrp, &end); + if (retval != IPMP_SUCCESS) + return (retval); + + retval = ipmp_readinfo(statep, IPMP_ADDRINFO, (void **)adinfopp, &end); + return (ipmp_querydone(statep, retval)); +} + +/* + * Free the address information pointed to by `adinfop'. + */ +void +ipmp_freeaddrinfo(ipmp_addrinfo_t *adinfop) +{ + free(adinfop); +} + +/* * Check if `buf' has a NUL byte in its first `bufsize' bytes. */ static boolean_t @@ -300,12 +410,25 @@ ipmp_checktlv(ipmp_infotype_t type, size_t len, void *value) ipmp_ifinfo_t *ifinfop; ipmp_grouplist_t *grlistp; ipmp_groupinfo_t *grinfop; + ipmp_addrlist_t *adlistp; unsigned int i; switch (type) { + case IPMP_ADDRINFO: + if (len != sizeof (ipmp_addrinfo_t)) + return (B_FALSE); + break; + + case IPMP_ADDRLIST: + adlistp = (ipmp_addrlist_t *)value; + if (len < IPMP_ADDRLIST_SIZE(0) || + len < IPMP_ADDRLIST_SIZE(adlistp->al_naddr)) + return (B_FALSE); + break; + case IPMP_IFLIST: iflistp = (ipmp_iflist_t *)value; - if (len < IPMP_IFLIST_MINSIZE || + if (len < IPMP_IFLIST_SIZE(0) || len < IPMP_IFLIST_SIZE(iflistp->il_nif)) return (B_FALSE); @@ -326,7 +449,7 @@ ipmp_checktlv(ipmp_infotype_t type, size_t len, void *value) case IPMP_GROUPLIST: grlistp = (ipmp_grouplist_t *)value; - if (len < IPMP_GROUPLIST_MINSIZE || + if (len < IPMP_GROUPLIST_SIZE(0) || len < IPMP_GROUPLIST_SIZE(grlistp->gl_ngroup)) return (B_FALSE); @@ -357,9 +480,8 @@ ipmp_checktlv(ipmp_infotype_t type, size_t len, void *value) } /* - * Create a group list with signature `sig' containing `ngroup' groups named - * by `groups'. Returns a pointer to the new group list on success, or NULL - * on failure. + * Create a group list; arguments match ipmp_grouplist_t fields. Returns a + * pointer to the new group list on success, or NULL on failure. */ ipmp_grouplist_t * ipmp_grouplist_create(uint64_t sig, unsigned int ngroup, @@ -392,13 +514,80 @@ ipmp_grouplist_clone(ipmp_grouplist_t *grlistp) } /* - * Create an interface information structure for interface `name' and - * associate `group', `state' and `type' with it. Returns a pointer to the - * interface information on success, or NULL on failure. + * Create target information; arguments match ipmp_targinfo_t fields. Returns + * a pointer to the new target info on success, or NULL on failure. + */ +ipmp_targinfo_t * +ipmp_targinfo_create(const char *name, struct sockaddr_storage *testaddrp, + ipmp_if_targmode_t targmode, uint_t ntarg, struct sockaddr_storage *targs) +{ + ipmp_targinfo_t *targinfop; + + targinfop = malloc(sizeof (ipmp_targinfo_t)); + if (targinfop == NULL) + return (NULL); + + targinfop->it_testaddr = *testaddrp; + targinfop->it_targmode = targmode; + targinfop->it_targlistp = ipmp_addrlist_create(ntarg, targs); + if (targinfop->it_targlistp == NULL) { + ipmp_freetarginfo(targinfop); + return (NULL); + } + (void) strlcpy(targinfop->it_name, name, LIFNAMSIZ); + + return (targinfop); +} + +/* + * Free the target information pointed to by `targinfop'. + */ +void +ipmp_freetarginfo(ipmp_targinfo_t *targinfop) +{ + free(targinfop->it_targlistp); + free(targinfop); +} + +/* + * Create an interface list; arguments match ipmp_iflist_t fields. Returns a + * pointer to the new interface list on success, or NULL on failure. + */ +static ipmp_iflist_t * +ipmp_iflist_create(uint_t nif, char (*ifs)[LIFNAMSIZ]) +{ + unsigned int i; + ipmp_iflist_t *iflistp; + + iflistp = malloc(IPMP_IFLIST_SIZE(nif)); + if (iflistp == NULL) + return (NULL); + + iflistp->il_nif = nif; + for (i = 0; i < nif; i++) + (void) strlcpy(iflistp->il_ifs[i], ifs[i], LIFNAMSIZ); + + return (iflistp); +} + +/* + * Free the interface list pointed to by `iflistp'. + */ +static void +ipmp_freeiflist(ipmp_iflist_t *iflistp) +{ + free(iflistp); +} + +/* + * Create an interface; arguments match ipmp_ifinfo_t fields. Returns a + * pointer to the new interface on success, or NULL on failure. */ ipmp_ifinfo_t * ipmp_ifinfo_create(const char *name, const char *group, ipmp_if_state_t state, - ipmp_if_type_t type) + ipmp_if_type_t type, ipmp_if_linkstate_t linkstate, + ipmp_if_probestate_t probestate, ipmp_if_flags_t flags, + ipmp_targinfo_t *targinfo4p, ipmp_targinfo_t *targinfo6p) { ipmp_ifinfo_t *ifinfop; @@ -408,8 +597,25 @@ ipmp_ifinfo_create(const char *name, const char *group, ipmp_if_state_t state, (void) strlcpy(ifinfop->if_name, name, LIFNAMSIZ); (void) strlcpy(ifinfop->if_group, group, LIFGRNAMSIZ); - ifinfop->if_state = state; - ifinfop->if_type = type; + + ifinfop->if_state = state; + ifinfop->if_type = type; + ifinfop->if_linkstate = linkstate; + ifinfop->if_probestate = probestate; + ifinfop->if_flags = flags; + ifinfop->if_targinfo4 = *targinfo4p; + ifinfop->if_targinfo6 = *targinfo6p; + + ifinfop->if_targinfo4.it_targlistp = + ipmp_addrlist_clone(targinfo4p->it_targlistp); + ifinfop->if_targinfo6.it_targlistp = + ipmp_addrlist_clone(targinfo6p->it_targlistp); + + if (ifinfop->if_targinfo4.it_targlistp == NULL || + ifinfop->if_targinfo6.it_targlistp == NULL) { + ipmp_freeifinfo(ifinfop); + return (NULL); + } return (ifinfop); } @@ -422,40 +628,41 @@ ipmp_ifinfo_t * ipmp_ifinfo_clone(ipmp_ifinfo_t *ifinfop) { return (ipmp_ifinfo_create(ifinfop->if_name, ifinfop->if_group, - ifinfop->if_state, ifinfop->if_type)); + ifinfop->if_state, ifinfop->if_type, ifinfop->if_linkstate, + ifinfop->if_probestate, ifinfop->if_flags, &ifinfop->if_targinfo4, + &ifinfop->if_targinfo6)); } /* - * Create a group named `name' with signature `sig', in state `state', and - * with the `nif' interfaces named by `ifs' as members. Returns a pointer + * Create a group; arguments match ipmp_groupinfo_t fields. Returns a pointer * to the new group on success, or NULL on failure. */ ipmp_groupinfo_t * -ipmp_groupinfo_create(const char *name, uint64_t sig, ipmp_group_state_t state, - unsigned int nif, char (*ifs)[LIFNAMSIZ]) +ipmp_groupinfo_create(const char *name, uint64_t sig, uint_t fdt, + ipmp_group_state_t state, uint_t nif, char (*ifs)[LIFNAMSIZ], + const char *grifname, const char *m4ifname, const char *m6ifname, + const char *bcifname, uint_t naddr, struct sockaddr_storage *addrs) { ipmp_groupinfo_t *grinfop; - ipmp_iflist_t *iflistp; - unsigned int i; grinfop = malloc(sizeof (ipmp_groupinfo_t)); if (grinfop == NULL) return (NULL); - iflistp = malloc(IPMP_IFLIST_SIZE(nif)); - if (iflistp == NULL) { - free(grinfop); + grinfop->gr_sig = sig; + grinfop->gr_fdt = fdt; + grinfop->gr_state = state; + grinfop->gr_iflistp = ipmp_iflist_create(nif, ifs); + grinfop->gr_adlistp = ipmp_addrlist_create(naddr, addrs); + if (grinfop->gr_iflistp == NULL || grinfop->gr_adlistp == NULL) { + ipmp_freegroupinfo(grinfop); return (NULL); } - - grinfop->gr_sig = sig; - grinfop->gr_state = state; - grinfop->gr_iflistp = iflistp; (void) strlcpy(grinfop->gr_name, name, LIFGRNAMSIZ); - - iflistp->il_nif = nif; - for (i = 0; i < nif; i++) - (void) strlcpy(iflistp->il_ifs[i], ifs[i], LIFNAMSIZ); + (void) strlcpy(grinfop->gr_ifname, grifname, LIFNAMSIZ); + (void) strlcpy(grinfop->gr_m4ifname, m4ifname, LIFNAMSIZ); + (void) strlcpy(grinfop->gr_m6ifname, m6ifname, LIFNAMSIZ); + (void) strlcpy(grinfop->gr_bcifname, bcifname, LIFNAMSIZ); return (grinfop); } @@ -467,9 +674,86 @@ ipmp_groupinfo_create(const char *name, uint64_t sig, ipmp_group_state_t state, ipmp_groupinfo_t * ipmp_groupinfo_clone(ipmp_groupinfo_t *grinfop) { + ipmp_addrlist_t *adlistp = grinfop->gr_adlistp; + return (ipmp_groupinfo_create(grinfop->gr_name, grinfop->gr_sig, - grinfop->gr_state, grinfop->gr_iflistp->il_nif, - grinfop->gr_iflistp->il_ifs)); + grinfop->gr_fdt, grinfop->gr_state, grinfop->gr_iflistp->il_nif, + grinfop->gr_iflistp->il_ifs, grinfop->gr_ifname, + grinfop->gr_m4ifname, grinfop->gr_m6ifname, grinfop->gr_bcifname, + adlistp->al_naddr, adlistp->al_addrs)); +} + +/* + * Create an address list; arguments match ipmp_addrlist_t fields. Returns + * a pointer to the new address list on success, or NULL on failure. + */ +static ipmp_addrlist_t * +ipmp_addrlist_create(uint_t naddr, struct sockaddr_storage *addrs) +{ + unsigned int i; + ipmp_addrlist_t *adlistp; + + adlistp = malloc(IPMP_ADDRLIST_SIZE(naddr)); + if (adlistp == NULL) + return (NULL); + + adlistp->al_naddr = naddr; + for (i = 0; i < naddr; i++) + adlistp->al_addrs[i] = addrs[i]; + + return (adlistp); +} + +/* + * Clone the address list named by `adlistp'. Returns a pointer to the clone + * on success, or NULL on failure. + */ +static ipmp_addrlist_t * +ipmp_addrlist_clone(ipmp_addrlist_t *adlistp) +{ + return (ipmp_addrlist_create(adlistp->al_naddr, adlistp->al_addrs)); +} + +/* + * Free the address list pointed to by `adlistp'. + */ +static void +ipmp_freeaddrlist(ipmp_addrlist_t *adlistp) +{ + free(adlistp); +} + +/* + * Create an address; arguments match ipmp_addrinfo_t fields. Returns a + * pointer to the new address on success, or NULL on failure. + */ +ipmp_addrinfo_t * +ipmp_addrinfo_create(struct sockaddr_storage *addrp, ipmp_addr_state_t state, + const char *group, const char *binding) +{ + ipmp_addrinfo_t *adinfop; + + adinfop = malloc(sizeof (ipmp_addrinfo_t)); + if (adinfop == NULL) + return (NULL); + + adinfop->ad_addr = *addrp; + adinfop->ad_state = state; + (void) strlcpy(adinfop->ad_group, group, LIFGRNAMSIZ); + (void) strlcpy(adinfop->ad_binding, binding, LIFNAMSIZ); + + return (adinfop); +} + +/* + * Clone the address information named by `adinfop'. Returns a pointer to + * the clone on success, or NULL on failure. + */ +ipmp_addrinfo_t * +ipmp_addrinfo_clone(ipmp_addrinfo_t *adinfop) +{ + return (ipmp_addrinfo_create(&adinfop->ad_addr, adinfop->ad_state, + adinfop->ad_group, adinfop->ad_binding)); } /* @@ -523,8 +807,10 @@ ipmp_snap_create(void) snap->sn_grlistp = NULL; snap->sn_grinfolistp = NULL; snap->sn_ifinfolistp = NULL; + snap->sn_adinfolistp = NULL; snap->sn_ngroup = 0; snap->sn_nif = 0; + snap->sn_naddr = 0; return (snap); } @@ -536,6 +822,7 @@ void ipmp_snap_free(ipmp_snap_t *snap) { ipmp_ifinfolist_t *iflp, *ifnext; + ipmp_addrinfolist_t *adlp, *adnext; ipmp_groupinfolist_t *grlp, *grnext; ipmp_freegrouplist(snap->sn_grlistp); @@ -552,6 +839,12 @@ ipmp_snap_free(ipmp_snap_t *snap) free(iflp); } + for (adlp = snap->sn_adinfolistp; adlp != NULL; adlp = adnext) { + adnext = adlp->adl_next; + ipmp_freeaddrinfo(adlp->adl_adinfop); + free(adlp); + } + free(snap); } @@ -612,6 +905,34 @@ ipmp_snap_addifinfo(ipmp_snap_t *snap, ipmp_ifinfo_t *ifinfop) } /* + * Add the address information in `adinfop' to the snapshot named by `snap'. + * Returns an IPMP error code. + */ +int +ipmp_snap_addaddrinfo(ipmp_snap_t *snap, ipmp_addrinfo_t *adinfop) +{ + ipmp_addrinfolist_t *adlp; + + /* + * Any duplicate addresses should've already been weeded by in.mpathd. + */ + if (ipmp_snap_getaddrinfo(snap, adinfop->ad_group, + &adinfop->ad_addr) != NULL) + return (IPMP_EPROTO); + + adlp = malloc(sizeof (ipmp_addrinfolist_t)); + if (adlp == NULL) + return (IPMP_ENOMEM); + + adlp->adl_adinfop = adinfop; + adlp->adl_next = snap->sn_adinfolistp; + snap->sn_adinfolistp = adlp; + snap->sn_naddr++; + + return (IPMP_SUCCESS); +} + +/* * Retrieve the information for the group `name' in snapshot `snap'. * Returns a pointer to the group information on success, or NULL on failure. */ @@ -647,6 +968,26 @@ ipmp_snap_getifinfo(ipmp_snap_t *snap, const char *name) } /* + * Retrieve the information for the address `addrp' on group `grname' in + * snapshot `snap'. Returns a pointer to the address information on success, + * or NULL on failure. + */ +static ipmp_addrinfo_t * +ipmp_snap_getaddrinfo(ipmp_snap_t *snap, const char *grname, + struct sockaddr_storage *addrp) +{ + ipmp_addrinfolist_t *adlp; + + for (adlp = snap->sn_adinfolistp; adlp != NULL; adlp = adlp->adl_next) { + if (strcmp(grname, adlp->adl_adinfop->ad_group) == 0 && + sockaddrcmp(addrp, &adlp->adl_adinfop->ad_addr)) + break; + } + + return (adlp != NULL ? adlp->adl_adinfop : NULL); +} + +/* * Using `statep', take a snapshot of the IPMP subsystem and if successful * return it in a dynamically allocated snapshot pointed to by `*snapp'. * Returns an IPMP error code. @@ -656,7 +997,6 @@ ipmp_snap_take(ipmp_state_t *statep, ipmp_snap_t **snapp) { ipmp_snap_t *snap, *osnap; ipmp_infotype_t type; - ipmp_iflist_t *iflistp; int retval; size_t len; void *infop; @@ -666,7 +1006,7 @@ ipmp_snap_take(ipmp_state_t *statep, ipmp_snap_t **snapp) if (snap == NULL) return (IPMP_ENOMEM); - retval = ipmp_sendquery(statep, IPMP_SNAP, NULL, &end); + retval = ipmp_sendquery(statep, IPMP_SNAP, NULL, NULL, &end); if (retval != IPMP_SUCCESS) { ipmp_snap_free(snap); return (retval); @@ -679,12 +1019,11 @@ ipmp_snap_take(ipmp_state_t *statep, ipmp_snap_t **snapp) } /* - * Using the information in the passed `osnap' snapshot, build up our - * own snapshot. If we receive more than one grouplist, or more than - * the expected number of interfaces or groups, then bail out. Note - * that there's only so much we can do to check that the information - * sent by in.mpathd makes sense. We know there will always be at - * least one TLV (IPMP_GROUPLIST). + * Using the information in the `osnap' snapshot, build up our own + * snapshot. We know there will always be at least one TLV (for + * IPMP_GROUPLIST). If we receive anything illogical (e.g., more than + * the expected number of interfaces), then bail out. However, to a + * large extent we have to trust the information sent by in.mpathd. */ do { infop = NULL; @@ -711,7 +1050,32 @@ ipmp_snap_take(ipmp_state_t *statep, ipmp_snap_t **snapp) retval = IPMP_EPROTO; break; } + + /* + * Read in V4 and V6 targlist TLVs that follow. + */ + retval = ipmp_readifinfo_lists(statep, infop, &end); + if (retval != IPMP_SUCCESS) + break; + retval = ipmp_snap_addifinfo(snap, infop); + if (retval != IPMP_SUCCESS) { + ipmp_freeifinfo(infop); + infop = NULL; + } + break; + + case IPMP_ADDRINFO: + if (snap->sn_naddr == osnap->sn_naddr) { + retval = IPMP_EPROTO; + break; + } + + retval = ipmp_snap_addaddrinfo(snap, infop); + /* + * NOTE: since we didn't call ipmp_read*info_lists(), + * no need to use ipmp_freeaddrinfo() on failure. + */ break; case IPMP_GROUPINFO: @@ -721,18 +1085,17 @@ ipmp_snap_take(ipmp_state_t *statep, ipmp_snap_t **snapp) } /* - * An IPMP_IFLIST TLV always follows the - * IPMP_GROUPINFO TLV; read it in. + * Read in IPMP groupinfo list TLVs that follow. */ - retval = ipmp_readinfo(statep, IPMP_IFLIST, - (void **)&iflistp, &end); + retval = ipmp_readgroupinfo_lists(statep, infop, &end); if (retval != IPMP_SUCCESS) break; - ((ipmp_groupinfo_t *)infop)->gr_iflistp = iflistp; retval = ipmp_snap_addgroupinfo(snap, infop); - if (retval != IPMP_SUCCESS) - free(iflistp); + if (retval != IPMP_SUCCESS) { + ipmp_freegroupinfo(infop); + infop = NULL; + } break; default: @@ -747,7 +1110,8 @@ fail: return (ipmp_querydone(statep, retval)); } } while (snap->sn_grlistp == NULL || snap->sn_nif < osnap->sn_nif || - snap->sn_ngroup < osnap->sn_ngroup); + snap->sn_ngroup < osnap->sn_ngroup || + snap->sn_naddr < osnap->sn_naddr); free(osnap); *snapp = snap; diff --git a/usr/src/lib/libipmp/common/ipmp_query.h b/usr/src/lib/libipmp/common/ipmp_query.h index d92554887a..160f561dd2 100644 --- a/usr/src/lib/libipmp/common/ipmp_query.h +++ b/usr/src/lib/libipmp/common/ipmp_query.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -18,17 +17,14 @@ * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END - */ -/* - * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _IPMP_QUERY_H #define _IPMP_QUERY_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/types.h> #include <sys/socket.h> /* needed by <net/if.h> */ #include <net/if.h> /* for LIF*NAMSIZ */ @@ -38,7 +34,7 @@ * IPMP query interfaces. * * These interfaces may only be used within ON or after signing a contract - * with ON. For documentation, refer to PSARC/2002/615. + * with ON. For documentation, refer to PSARC/2002/615 and PSARC/2007/272. */ #ifdef __cplusplus @@ -46,6 +42,43 @@ extern "C" { #endif /* + * Assorted enumerations used in the data types described below. + */ +typedef enum ipmp_if_probestate { + IPMP_PROBE_OK, /* probes detect no problems */ + IPMP_PROBE_FAILED, /* probes detect failure */ + IPMP_PROBE_UNKNOWN, /* probe detection unavailable */ + IPMP_PROBE_DISABLED /* probe detection disabled */ +} ipmp_if_probestate_t; + +typedef enum ipmp_if_linkstate { + IPMP_LINK_UP, /* link detects up */ + IPMP_LINK_DOWN, /* link detects down */ + IPMP_LINK_UNKNOWN /* link detection unavailable */ +} ipmp_if_linkstate_t; + +typedef enum ipmp_if_flags { + IPMP_IFFLAG_INACTIVE = 0x1, + IPMP_IFFLAG_HWADDRDUP = 0x2, + IPMP_IFFLAG_ACTIVE = 0x4, + IPMP_IFFLAG_DOWN = 0x8 +} ipmp_if_flags_t; + +typedef enum ipmp_addr_state { + IPMP_ADDR_UP, /* address is up */ + IPMP_ADDR_DOWN /* address is down */ +} ipmp_addr_state_t; + +typedef enum ipmp_if_targmode { + IPMP_TARG_DISABLED, /* use of targets is disabled */ + IPMP_TARG_ROUTES, /* route-learned targets */ + IPMP_TARG_MULTICAST /* multicast-learned targets */ +} ipmp_if_targmode_t; + +#define IPMP_LIST_SIZE(listtype, elsize, nel) \ + ((sizeof (ipmp_ ## listtype ## _t) - (elsize)) + ((nel) * (elsize))) + +/* * Data type describing a list of IPMP groups. */ typedef struct ipmp_grouplist { @@ -54,8 +87,8 @@ typedef struct ipmp_grouplist { char gl_groups[1][LIFGRNAMSIZ]; } ipmp_grouplist_t; -#define IPMP_GROUPLIST_MINSIZE (sizeof (ipmp_grouplist_t) - LIFGRNAMSIZ) -#define IPMP_GROUPLIST_SIZE(ngr) (IPMP_GROUPLIST_MINSIZE + (ngr) * LIFGRNAMSIZ) +#define IPMP_GROUPLIST_SIZE(ngr) \ + IPMP_LIST_SIZE(grouplist, LIFGRNAMSIZ, ngr) /* * Data type describing a list of interfaces. @@ -65,8 +98,19 @@ typedef struct ipmp_iflist { char il_ifs[1][LIFNAMSIZ]; } ipmp_iflist_t; -#define IPMP_IFLIST_MINSIZE (sizeof (ipmp_iflist_t) - LIFNAMSIZ) -#define IPMP_IFLIST_SIZE(nif) (IPMP_IFLIST_MINSIZE + (nif) * LIFNAMSIZ) +#define IPMP_IFLIST_SIZE(nif) \ + IPMP_LIST_SIZE(iflist, LIFNAMSIZ, nif) + +/* + * Data type describing a list of addresses. + */ +typedef struct ipmp_addrlist { + unsigned int al_naddr; + struct sockaddr_storage al_addrs[1]; +} ipmp_addrlist_t; + +#define IPMP_ADDRLIST_SIZE(naddr) \ + IPMP_LIST_SIZE(addrlist, sizeof (struct sockaddr_storage), naddr) /* * Data type describing the state of an IPMP group. @@ -76,18 +120,49 @@ typedef struct ipmp_groupinfo { uint64_t gr_sig; ipmp_group_state_t gr_state; ipmp_iflist_t *gr_iflistp; + ipmp_addrlist_t *gr_adlistp; + char gr_ifname[LIFNAMSIZ]; + char gr_m4ifname[LIFNAMSIZ]; + char gr_m6ifname[LIFNAMSIZ]; + char gr_bcifname[LIFNAMSIZ]; + unsigned int gr_fdt; } ipmp_groupinfo_t; /* + * Data type describing IPMP target information for a particular interface. + */ +typedef struct ipmp_targinfo { + char it_name[LIFNAMSIZ]; + struct sockaddr_storage it_testaddr; + ipmp_if_targmode_t it_targmode; + ipmp_addrlist_t *it_targlistp; +} ipmp_targinfo_t; + +/* * Data type describing the IPMP-related state of an interface. */ typedef struct ipmp_ifinfo { - char if_name[LIFNAMSIZ]; - char if_group[LIFGRNAMSIZ]; - ipmp_if_state_t if_state; - ipmp_if_type_t if_type; + char if_name[LIFNAMSIZ]; + char if_group[LIFGRNAMSIZ]; + ipmp_if_state_t if_state; + ipmp_if_type_t if_type; + ipmp_if_linkstate_t if_linkstate; + ipmp_if_probestate_t if_probestate; + ipmp_if_flags_t if_flags; + ipmp_targinfo_t if_targinfo4; + ipmp_targinfo_t if_targinfo6; } ipmp_ifinfo_t; +/* + * Data type describing an IPMP data address. + */ +typedef struct ipmp_addrinfo { + struct sockaddr_storage ad_addr; + ipmp_addr_state_t ad_state; + char ad_group[LIFGRNAMSIZ]; + char ad_binding[LIFNAMSIZ]; +} ipmp_addrinfo_t; + typedef enum { IPMP_QCONTEXT_LIVE, IPMP_QCONTEXT_SNAP @@ -100,6 +175,9 @@ extern int ipmp_getgroupinfo(ipmp_handle_t, const char *, ipmp_groupinfo_t **); extern void ipmp_freegroupinfo(ipmp_groupinfo_t *); extern int ipmp_getifinfo(ipmp_handle_t, const char *, ipmp_ifinfo_t **); extern void ipmp_freeifinfo(ipmp_ifinfo_t *); +extern int ipmp_getaddrinfo(ipmp_handle_t, const char *, + struct sockaddr_storage *, ipmp_addrinfo_t **); +extern void ipmp_freeaddrinfo(ipmp_addrinfo_t *); #ifdef __cplusplus } diff --git a/usr/src/lib/libipmp/common/ipmp_query_impl.h b/usr/src/lib/libipmp/common/ipmp_query_impl.h index 03ecb5cd84..6ac5c3ca27 100644 --- a/usr/src/lib/libipmp/common/ipmp_query_impl.h +++ b/usr/src/lib/libipmp/common/ipmp_query_impl.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -18,17 +17,14 @@ * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END - */ -/* - * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _IPMP_QUERY_IMPL_H #define _IPMP_QUERY_IMPL_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <ipmp_query.h> /* @@ -58,14 +54,24 @@ typedef struct ipmp_ifinfolist { } ipmp_ifinfolist_t; /* + * List of ipmp_addrinfo_t structures. + */ +typedef struct ipmp_addrinfolist { + struct ipmp_addrinfolist *adl_next; + ipmp_addrinfo_t *adl_adinfop; +} ipmp_addrinfolist_t; + +/* * Snapshot of IPMP state. */ typedef struct ipmp_snap { ipmp_grouplist_t *sn_grlistp; ipmp_groupinfolist_t *sn_grinfolistp; ipmp_ifinfolist_t *sn_ifinfolistp; + ipmp_addrinfolist_t *sn_adinfolistp; unsigned int sn_ngroup; unsigned int sn_nif; + unsigned int sn_naddr; } ipmp_snap_t; /* @@ -74,17 +80,28 @@ typedef struct ipmp_snap { extern ipmp_snap_t *ipmp_snap_create(void); extern void ipmp_snap_free(ipmp_snap_t *); extern int ipmp_snap_addifinfo(ipmp_snap_t *, ipmp_ifinfo_t *); +extern int ipmp_snap_addaddrinfo(ipmp_snap_t *, ipmp_addrinfo_t *); extern int ipmp_snap_addgroupinfo(ipmp_snap_t *, ipmp_groupinfo_t *); /* - * IPMP structure creation routines. + * IPMP structure creation/destruction routines. */ extern ipmp_ifinfo_t *ipmp_ifinfo_create(const char *, const char *, - ipmp_if_state_t, ipmp_if_type_t); -extern ipmp_groupinfo_t *ipmp_groupinfo_create(const char *, uint64_t, - ipmp_group_state_t, unsigned int, char (*)[LIFNAMSIZ]); + ipmp_if_state_t, ipmp_if_type_t, ipmp_if_linkstate_t, ipmp_if_probestate_t, + ipmp_if_flags_t, ipmp_targinfo_t *, ipmp_targinfo_t *); +extern ipmp_groupinfo_t *ipmp_groupinfo_create(const char *, uint64_t, uint_t, + ipmp_group_state_t, uint_t, char (*)[LIFNAMSIZ], const char *, + const char *, const char *, const char *, uint_t, + struct sockaddr_storage *); extern ipmp_grouplist_t *ipmp_grouplist_create(uint64_t, unsigned int, char (*)[LIFGRNAMSIZ]); +extern ipmp_addrinfo_t *ipmp_addrinfo_create(struct sockaddr_storage *, + ipmp_addr_state_t, const char *, const char *); +extern ipmp_targinfo_t *ipmp_targinfo_create(const char *, + struct sockaddr_storage *, ipmp_if_targmode_t, uint_t, + struct sockaddr_storage *); +extern void ipmp_freetarginfo(ipmp_targinfo_t *); + #ifdef __cplusplus } diff --git a/usr/src/lib/libipmp/common/llib-lipmp b/usr/src/lib/libipmp/common/llib-lipmp index a16011745a..a22eec5d66 100644 --- a/usr/src/lib/libipmp/common/llib-lipmp +++ b/usr/src/lib/libipmp/common/llib-lipmp @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,15 +19,14 @@ * CDDL HEADER END */ /* - * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* LINTLIBRARY */ /* PROTOLIB1 */ #include <ipmp.h> +#include <ipmp_admin.h> #include <ipmp_mpathd.h> #include <ipmp_query_impl.h> diff --git a/usr/src/lib/libipmp/common/mapfile-vers b/usr/src/lib/libipmp/common/mapfile-vers index a4052bfcd3..8c93248338 100644 --- a/usr/src/lib/libipmp/common/mapfile-vers +++ b/usr/src/lib/libipmp/common/mapfile-vers @@ -19,32 +19,39 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# SUNWprivate_1.1 { global: + ipmp_addrinfo_create; ipmp_close; ipmp_errmsg; + ipmp_freeaddrinfo; ipmp_freegroupinfo; ipmp_freegrouplist; ipmp_freeifinfo; + ipmp_freetarginfo; + ipmp_getaddrinfo; ipmp_getgroupinfo; ipmp_getgrouplist; ipmp_getifinfo; ipmp_groupinfo_create; ipmp_grouplist_create; ipmp_ifinfo_create; + ipmp_offline; ipmp_open; + ipmp_ping_daemon; ipmp_read; ipmp_setqcontext; + ipmp_snap_addaddrinfo; ipmp_snap_addgroupinfo; ipmp_snap_addifinfo; ipmp_snap_create; ipmp_snap_free; + ipmp_targinfo_create; + ipmp_undo_offline; ipmp_write; ipmp_writetlv; local: diff --git a/usr/src/lib/libnsl/nss/netdir_inet_sundry.c b/usr/src/lib/libnsl/nss/netdir_inet_sundry.c index 742e7408b2..4e9473a8cf 100644 --- a/usr/src/lib/libnsl/nss/netdir_inet_sundry.c +++ b/usr/src/lib/libnsl/nss/netdir_inet_sundry.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * lib/libnsl/nss/netdir_inet_sundry.c @@ -39,8 +38,6 @@ * Copied mostly from erstwhile lib/nametoaddr/tcpip/tcpip.c. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "mt.h" #include <stdlib.h> #include <stdio.h> @@ -69,9 +66,6 @@ #include <syslog.h> #include <values.h> #include <limits.h> -#ifdef DEBUG -#include <stdio.h> -#endif #include <nss_dbdefs.h> #include "nss.h" @@ -151,8 +145,8 @@ __inet_taddr2uaddr(struct netconfig *tp, struct netbuf *addr) /* LINTED pointer cast */ sa6 = (struct sockaddr_in6 *)(addr->buf); myport = ntohs(sa6->sin6_port); - if (inet_ntop(AF_INET6, (void *)sa6->sin6_addr.s6_addr, - tmp, sizeof (tmp)) == 0) { + if (inet_ntop(AF_INET6, sa6->sin6_addr.s6_addr, tmp, + sizeof (tmp)) == NULL) { _nderror = ND_BADARG; return (NULL); } @@ -400,7 +394,7 @@ getifnum: continue; if_info[n_ifs].if_address = - ((struct sockaddr_in *)&lifr->lifr_addr)->sin_addr; + ((struct sockaddr_in *)&lifr->lifr_addr)->sin_addr; if (nss_ioctl(AF_INET, SIOCGLIFFLAGS, lifr) < 0) continue; @@ -413,7 +407,7 @@ getifnum: continue; if_info[n_ifs].if_netmask = - ((struct sockaddr_in *)&lifr->lifr_addr)->sin_addr; + ((struct sockaddr_in *)&lifr->lifr_addr)->sin_addr; n_ifs++; } free(buf); @@ -528,21 +522,12 @@ get_best_match(struct in_addr addr) if_addr = ntohl(ifn->if_address.s_addr); /* host order */ /* - * Checking if the interface selected is FAILED or DEPRECATED. - * In case IFF_FAILED or IFF_DEPRECATED flag for the interface - * is set, we move on to the next interface in the list. - * Refer IPMP(IP Multi Pathing) for more details. - */ - - if ((ifn->if_flags & (IFF_FAILED | IFF_DEPRECATED)) != 0) - continue; - - /* * set initial count to first bit set in netmask, with * zero being the number of the least significant bit. */ - for (count = 0, mask = netmask; mask && ((mask & 1) == 0); - count++, mask >>= 1); + count = 0; + for (mask = netmask; mask && ((mask & 1) == 0); mask >>= 1) + count++; /* * Set limit so that we don't try to match prefixes shorter @@ -570,12 +555,6 @@ get_best_match(struct in_addr addr) * (2) the best partial subnet match * (3) the first non-loopback && non-PPP interface * (4) the first non-loopback interface (PPP is OK) - * - * While checking for condition (3) and (4), we also look - * if the interface we are returning is neither FAILED - * nor DEPRECATED. In case there are no interface - * available, which are neither FAILED nor DEPRECRATED, - * we return 0. */ found = FALSE; while (netmask && count < subnet_count) { @@ -607,8 +586,7 @@ get_best_match(struct in_addr addr) */ if (bestmatch == NULL) { for (ifn = if_info; ifn < (if_info + n_ifs); ifn++) { - if ((ifn->if_flags & (IFF_LOOPBACK | - IFF_FAILED | IFF_DEPRECATED)) == 0) { + if ((ifn->if_flags & IFF_LOOPBACK) == 0) { bestmatch = ifn; /* @@ -619,10 +597,6 @@ get_best_match(struct in_addr addr) * list... */ if ((ifn->if_flags & IFF_POINTOPOINT) == 0) { -#ifdef DEBUG - (void) printf("found !loopback && !non-PPP interface: %s\n", - inet_ntoa(ifn->if_address)); -#endif break; } } @@ -701,9 +675,9 @@ select_server_addr(union any_in_addr *dst_addr, int family, } /* open a UDP socket */ - if ((tmp_fd = _so_socket(family, SOCK_DGRAM, 0, - NULL, SOV_SOCKBSD)) < 0) { - syslog(LOG_ERR, "selsect_server_addr:connect failed\n"); + tmp_fd = _so_socket(family, SOCK_DGRAM, 0, NULL, SOV_SOCKBSD); + if (tmp_fd < 0) { + syslog(LOG_ERR, "select_server_addr: connect failed\n"); return (FALSE); } @@ -716,15 +690,16 @@ select_server_addr(union any_in_addr *dst_addr, int family, * message, as it'll try to send the probe packet out and will * receive ICMP unreachable. */ - if (family == AF_INET) + if (family == AF_INET) { src_addr->addr.s_addr = INADDR_ANY; - else + } else { /* * Since in6addr_any is not in the scope * use the following hack */ (void) memset(src_addr->addr6.s6_addr, - 0, sizeof (struct in6_addr)); + 0, sizeof (struct in6_addr)); + } (void) close(tmp_fd); free(sock); return (FALSE); @@ -732,7 +707,7 @@ select_server_addr(union any_in_addr *dst_addr, int family, /* get the local sock info */ if (_so_getsockname(tmp_fd, sock, &sock_len, SOV_DEFAULT) < 0) { - syslog(LOG_ERR, "selsect_server_addr:getsockname failed\n"); + syslog(LOG_ERR, "select_server_addr: getsockname failed\n"); (void) close(tmp_fd); free(sock); return (FALSE); @@ -799,11 +774,6 @@ inet_netdir_mergeaddr(struct netconfig *tp, char *ruaddr, char *uaddr) clientaddr.s_addr = inet_addr(ruaddr); -#ifdef DEBUG - (void) printf("client's address is %s and %s\n", - ruaddr, inet_ntoa(clientaddr)); -#endif - /* We know cp is not NULL due to the check above */ *cp = '.'; /* Put the dot back in the IP addr */ @@ -895,28 +865,22 @@ inet_netdir_mergeaddr(struct netconfig *tp, char *ruaddr, char *uaddr) FALSE) return (NULL); server_addr.sin6_addr = out_addr.addr6; + } else { + (void) memcpy(&server_addr, &sa, sizeof (server_addr)); } - else - (void) memcpy(&server_addr, &sa, - sizeof (struct sockaddr_in6)); -#ifdef DEBUG - printf("%s\n", inet_ntop(af, out_addr.addr6.s6_addr, - tmp, sizeof (tmp))); -#endif - - if (inet_ntop(af, server_addr.sin6_addr.s6_addr, - tmp, sizeof (tmp)) == NULL) { + + if (inet_ntop(af, server_addr.sin6_addr.s6_addr, tmp, + sizeof (tmp)) == NULL) { _nderror = ND_NOHOST; return (NULL); } /* now extract the port info */ if ((dot = strrchr(uaddr, '.')) != 0) { + char *p = --dot; - char *p; - - p = --dot; - while (*p-- != '.'); + while (*p-- != '.') + ; p++; (void) strcat(tmp + strlen(tmp), p); _nderror = ND_OK; @@ -1051,7 +1015,7 @@ bindresvport(struct netconfig *nconf, int fd, struct netbuf *addr) * this, if the caller has set this option before calling * bindresvport(), it will be unset. Better be safe... */ - *optval = 0; + *optval = 0; resp.flags = 0; resp.opt.buf = (char *)reqbuf; resp.opt.maxlen = sizeof (reqbuf); diff --git a/usr/src/lib/libsocket/inet/interface_id.c b/usr/src/lib/libsocket/inet/interface_id.c index 2a512b025f..88854fe9da 100644 --- a/usr/src/lib/libsocket/inet/interface_id.c +++ b/usr/src/lib/libsocket/inet/interface_id.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdio.h> #include <ctype.h> #include <string.h> @@ -120,6 +117,9 @@ if_indextoname(uint32_t ifindex, char *ifname) int numifs; size_t bufsize; boolean_t found; + uint_t flags; + + flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES | LIFC_UNDER_IPMP; /* A interface index of 0 is invalid */ if (ifindex == 0) { @@ -137,14 +137,19 @@ if_indextoname(uint32_t ifindex, char *ifname) /* Prepare to send a SIOCGLIFNUM request message */ lifn.lifn_family = AF_UNSPEC; - lifn.lifn_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES; + lifn.lifn_flags = flags; if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) < 0) { int save_err = errno; (void) close(s); errno = save_err; return (NULL); } - numifs = lifn.lifn_count; + + /* + * NOTE: "+ 10" sleaze mitigates new IP interfaces showing up between + * the SIOCGLIFNUM and the SIOCGLIFCONF. + */ + numifs = lifn.lifn_count + 10; /* * Provide enough buffer to obtain the interface @@ -161,7 +166,7 @@ if_indextoname(uint32_t ifindex, char *ifname) return (NULL); } lifc.lifc_family = AF_UNSPEC; - lifc.lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES; + lifc.lifc_flags = flags; lifc.lifc_len = bufsize; lifc.lifc_buf = buf; if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0) { diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c index dabc2e0929..62ebedf522 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c @@ -1936,7 +1936,7 @@ dyndns_update_core(char *fqdn) return (-1); do { - if (ni.ni_nic.nic_sysflags & (IFF_STANDBY | IFF_PRIVATE)) + if (ni.ni_nic.nic_sysflags & IFF_PRIVATE) continue; addr.s_addr = ni.ni_nic.nic_ip; @@ -2003,7 +2003,7 @@ dyndns_clear_rev_zone(char *fqdn) return (-1); do { - if (ni.ni_nic.nic_sysflags & (IFF_STANDBY | IFF_PRIVATE)) + if (ni.ni_nic.nic_sysflags & IFF_PRIVATE) continue; addr.s_addr = ni.ni_nic.nic_ip; |