summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
authormeem <Peter.Memishian@Sun.COM>2009-01-06 20:16:25 -0500
committermeem <Peter.Memishian@Sun.COM>2009-01-06 20:16:25 -0500
commite11c3f44f531fdff80941ce57c065d2ae861cefc (patch)
treee921e957d727a9596275a1119fd627ef2ecca47d /usr/src/lib
parent732675dd38771d280fdc276731344e9652071753 (diff)
downloadillumos-joyent-e11c3f44f531fdff80941ce57c065d2ae861cefc.tar.gz
PSARC/2007/272 Project Clearview: IPMP Rearchitecture
PSARC/2008/773 IPQoS if_groupname Selector Removal PSARC/2009/001 Move in.mpathd into /lib/inet 6783149 Clearview IPMP Rearchitecture 4472956 libipmp should provide administrative interfaces 4494577 ipmp is opaque - there's no way to get current status 4509788 IPMP's usage of interface flags is not backward compatible 4509869 IPMP's address move mechanism needs to be transparent to applications 4531232 "in.rdiscd: sendto: Bad file number" seen during IPMP DR 4533876 new instances of interfaces under ipmp are generated with each dr/op 4699003 in.mpathd should squawk if interfaces in a group have the same hwaddr 4704937 SUNW_ip_rcm.so is sloppy with strings 4713308 IPMP shouldn't failover unconfigured logical interfaces 4785694 non-homogeneous IPMP group does not do failback 4850407 if_mpadm and IPMP DR failure 5015757 ip can panic with ASSERT(attach_ill == ipif->ipif_ill) failure 5086201 in.ndpd's phyint_reach_random() spews "SIOCSLIFLNKINFO Invalid argument" 6184000 routes cannot be created on failed interfaces 6246564 if_mpadm -r <ifname> doesn't bring up IPv6 link-local data address 6359058 SIOCLIFFAILBACK repeatedly fails with EAGAIN; in.mpathd fills logs 6359536 enabling STANDBY on an interface with no test address acts oddly 6378487 in.dhcpd doesn't work well in an IPMP setup 6462335 cannot offline to IPMP interfaces that have no probe targets 6516992 in.routed spews "Address already in use" during IPMP address move 6518460 ip_rcm`update_pif() must remain calm when logical interfaces disappear 6549957 failed IP interfaces at boot may go unreported 6591186 rpcbind can't deal with indirect calls if all addresses are deprecated 6667143 NCE_F_UNSOL_ADV broken 6698480 IGMP version not retained during IPMP failover 6726235 IPMP group failure can sometimes lead to an extra failover 6726645 in.routed skips DEPRECATED addresses even when no others exist 6738310 ip_ndp_recover() checks IPIF_CONDEMNED on the wrong ipif flags field 6739454 system panics at sdpib`sdp_rts_announce 6739531 IPv6 DAD doesn't work well with IPMP 6740719 in.mpathd may fail to switch to router target mode 6743260 ipif_resolver_up() can fail and leave ARP bringup pending 6746613 ip's DL_NOTE_SDU_SIZE logic mishandles ill_max_frag < ill_max_mtu 6748145 in.ndpd's IPv6 link-local hardware address mappings can go stale 6753560 ilg_delete_all() can race with ill_delete_tail() when ilg_ill changes 6755987 stillborn IFF_POINTOPOINT in.mpathd logic should be hauled out 6775126 SUBDIRS ipsecutils element does not in order be 6775811 NCEs can get stuck in ND_INCOMPLETE if ARP fails when IPMP is in-use 6777496 receive-side ILL_HCKSUM_CAPABLE checks look at the wrong ill 6781488 IPSQ timer restart logic can deadlock under stress 6781883 ip_ndp_find_solicitation() can be passed adverts, and has API issues 6784852 RPCIB, SDP, and RDS all break when vanity naming is used 6786048 IPv6 ND probes create IREs with incorrect source addresses 6786091 I_PLINK handling in IP must not request reentry via ipsq_try_enter() 6786711 IPQoS if_groupname selector needs to go 6787091 assertion failure in ipcl_conn_cleanup() due to non-NULL conn_ilg 6789235 INADDR_ANY ILMs can trigger an assertion failure in IPMP environments 6789502 ipif_resolver_up() calls after ipif_ndp_up() clobber ipif_addr_ready 6789718 ip6.tun0 cannot be plumbed in a non-global-zone post-6745288 6789732 libdlpi may get stuck in i_dlpi_strgetmsg() 6789870 ipif6_dup_recovery() may operate on a freed ipif, corrupting memory 6789874 ipnet_nicevent_cb() may call taskq_dispatch() on a bogus taskq 6790310 in.mpathd may core with "phyint_inst_timer: invalid state 4" --HG-- rename : usr/src/lib/libinetutil/common/inetutil4.c => usr/src/lib/libinetutil/common/inetutil.c rename : usr/src/uts/common/inet/vni/vni.c => usr/src/uts/common/inet/dlpistub/dlpistub.c rename : usr/src/uts/common/inet/vni/vni.conf => usr/src/uts/common/inet/dlpistub/dlpistub.conf rename : usr/src/uts/common/inet/vni/vni_impl.h => usr/src/uts/common/inet/dlpistub/dlpistub_impl.h rename : usr/src/uts/intel/vni/Makefile => usr/src/uts/intel/dlpistub/Makefile rename : usr/src/uts/sparc/vni/Makefile => usr/src/uts/sparc/dlpistub/Makefile
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/brand/native/zone/platform.xml3
-rw-r--r--usr/src/lib/brand/sn1/zone/platform.xml3
-rw-r--r--usr/src/lib/libbsm/common/adt.c4
-rw-r--r--usr/src/lib/libdlpi/common/libdlpi.c21
-rw-r--r--usr/src/lib/libinetcfg/common/inetcfg.c38
-rw-r--r--usr/src/lib/libinetutil/Makefile.com14
-rw-r--r--usr/src/lib/libinetutil/common/ifaddrlist.c68
-rw-r--r--usr/src/lib/libinetutil/common/ifaddrlistx.c168
-rw-r--r--usr/src/lib/libinetutil/common/inetutil.c (renamed from usr/src/lib/libinetutil/common/inetutil4.c)36
-rw-r--r--usr/src/lib/libinetutil/common/libinetutil.h55
-rw-r--r--usr/src/lib/libinetutil/common/mapfile-vers7
-rw-r--r--usr/src/lib/libipmp/Makefile6
-rw-r--r--usr/src/lib/libipmp/Makefile.com9
-rw-r--r--usr/src/lib/libipmp/common/ipmp.c20
-rw-r--r--usr/src/lib/libipmp/common/ipmp.h12
-rw-r--r--usr/src/lib/libipmp/common/ipmp_admin.c104
-rw-r--r--usr/src/lib/libipmp/common/ipmp_admin.h50
-rw-r--r--usr/src/lib/libipmp/common/ipmp_mpathd.c26
-rw-r--r--usr/src/lib/libipmp/common/ipmp_mpathd.h81
-rw-r--r--usr/src/lib/libipmp/common/ipmp_query.c498
-rw-r--r--usr/src/lib/libipmp/common/ipmp_query.h112
-rw-r--r--usr/src/lib/libipmp/common/ipmp_query_impl.h41
-rw-r--r--usr/src/lib/libipmp/common/llib-lipmp10
-rw-r--r--usr/src/lib/libipmp/common/mapfile-vers13
-rw-r--r--usr/src/lib/libnsl/nss/netdir_inet_sundry.c92
-rw-r--r--usr/src/lib/libsocket/inet/interface_id.c23
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c4
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;