changeset 12576:ab8aacaead3f

PSARC/2010/142 libinetcfg removal 6949257 libinetcfg removal 6944403 nwe_if_state structure misses the netmask info 6951482 stale ipmgmtd door handle can cause libipadm interfaces to fail
author Anurag S. Maskey <Anurag.Maskey@Oracle.COM>
date Mon, 07 Jun 2010 14:10:14 -0400
parents 6d803152496b
children 98b7657d1987
files exception_lists/packaging usr/src/Makefile.lint usr/src/Targetdirs usr/src/cmd/cmd-inet/lib/nwamd/Makefile usr/src/cmd/cmd-inet/lib/nwamd/conditions.c usr/src/cmd/cmd-inet/lib/nwamd/dlpi_events.c usr/src/cmd/cmd-inet/lib/nwamd/door_if.c usr/src/cmd/cmd-inet/lib/nwamd/enm.c usr/src/cmd/cmd-inet/lib/nwamd/events.c usr/src/cmd/cmd-inet/lib/nwamd/events.h usr/src/cmd/cmd-inet/lib/nwamd/known_wlans.c usr/src/cmd/cmd-inet/lib/nwamd/loc.c usr/src/cmd/cmd-inet/lib/nwamd/main.c usr/src/cmd/cmd-inet/lib/nwamd/ncp.c usr/src/cmd/cmd-inet/lib/nwamd/ncp.h usr/src/cmd/cmd-inet/lib/nwamd/ncu.c usr/src/cmd/cmd-inet/lib/nwamd/ncu.h usr/src/cmd/cmd-inet/lib/nwamd/ncu_ip.c usr/src/cmd/cmd-inet/lib/nwamd/ncu_phys.c usr/src/cmd/cmd-inet/lib/nwamd/routing_events.c usr/src/cmd/cmd-inet/lib/nwamd/util.c usr/src/cmd/cmd-inet/usr.lib/vrrpd/Makefile usr/src/cmd/cmd-inet/usr.lib/vrrpd/vrrpd.c usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c usr/src/cmd/cmd-inet/usr.sbin/nwamadm/nwamadm.c usr/src/lib/Makefile usr/src/lib/libinetcfg/Makefile usr/src/lib/libinetcfg/Makefile.com usr/src/lib/libinetcfg/common/inetcfg.c usr/src/lib/libinetcfg/common/inetcfg.h usr/src/lib/libinetcfg/common/llib-linetcfg usr/src/lib/libinetcfg/common/mapfile-vers usr/src/lib/libinetcfg/i386/Makefile usr/src/lib/libinetcfg/libinetcfg.xcl usr/src/lib/libinetcfg/sparc/Makefile usr/src/lib/libipadm/common/ipadm_addr.c usr/src/lib/libipadm/common/libipadm.c usr/src/lib/libipadm/common/libipadm.h usr/src/lib/libipadm/common/mapfile-vers usr/src/lib/libnwam/common/libnwam.h usr/src/pkg/manifests/system-library.mf usr/src/tools/scripts/bfu.sh
diffstat 42 files changed, 1165 insertions(+), 4099 deletions(-) [+]
line wrap: on
line diff
--- a/exception_lists/packaging	Mon Jun 07 10:04:00 2010 -0700
+++ b/exception_lists/packaging	Mon Jun 07 14:10:14 2010 -0400
@@ -258,17 +258,6 @@
 usr/lib/llib-lpkg
 usr/lib/llib-lpkg.ln
 #
-# These files are installed in the proto area by the build of libinetcfg.
-# Only the shared object is shipped.
-#
-lib/libinetcfg.so
-lib/llib-linetcfg
-lib/llib-linetcfg.ln
-usr/include/inetcfg.h
-usr/lib/libinetcfg.so
-usr/lib/llib-linetcfg
-usr/lib/llib-linetcfg.ln
-#
 # Don't ship header files private to libipmp and in.mpathd
 #
 usr/include/ipmp_query_impl.h
--- a/usr/src/Makefile.lint	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/Makefile.lint	Mon Jun 07 14:10:14 2010 -0400
@@ -371,7 +371,6 @@
 	lib/libhotplug \
 	lib/libidmap \
 	lib/libilb \
-	lib/libinetcfg \
 	lib/libinetsvc \
 	lib/libinetutil \
 	lib/libinstzones \
--- a/usr/src/Targetdirs	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/Targetdirs	Mon Jun 07 14:10:14 2010 -0400
@@ -870,8 +870,6 @@
 $(ROOT)/usr/lib/libfdisk.so:=		REALPATH=../../lib/libfdisk.so.1
 $(ROOT)/usr/lib/libgen.so.1:=		REALPATH=../../lib/libgen.so.1
 $(ROOT)/usr/lib/libgen.so:=		REALPATH=../../lib/libgen.so.1
-$(ROOT)/usr/lib/libinetcfg.so.1:=	REALPATH=../../lib/libinetcfg.so.1
-$(ROOT)/usr/lib/libinetcfg.so:=		REALPATH=../../lib/libinetcfg.so.1
 $(ROOT)/usr/lib/libinetutil.so.1:=	REALPATH=../../lib/libinetutil.so.1
 $(ROOT)/usr/lib/libinetutil.so:=	REALPATH=../../lib/libinetutil.so.1
 $(ROOT)/usr/lib/libintl.so.1:=		REALPATH=../../lib/libintl.so.1
@@ -994,8 +992,6 @@
 $(ROOT)/usr/lib/llib-lfdisk:=		REALPATH=../../lib/llib-lfdisk
 $(ROOT)/usr/lib/llib-lgen.ln:=		REALPATH=../../lib/llib-lgen.ln
 $(ROOT)/usr/lib/llib-lgen:=		REALPATH=../../lib/llib-lgen
-$(ROOT)/usr/lib/llib-linetcfg.ln:=	REALPATH=../../lib/llib-linetcfg.ln
-$(ROOT)/usr/lib/llib-linetcfg:=		REALPATH=../../lib/llib-linetcfg
 $(ROOT)/usr/lib/llib-linetutil.ln:=	REALPATH=../../lib/llib-linetutil.ln
 $(ROOT)/usr/lib/llib-linetutil:=	REALPATH=../../lib/llib-linetutil
 $(ROOT)/usr/lib/llib-lintl.ln:=		REALPATH=../../lib/llib-lintl.ln
@@ -1470,8 +1466,6 @@
 	/usr/lib/libelf.so.1 \
 	/usr/lib/libgen.so \
 	/usr/lib/libgen.so.1 \
-	/usr/lib/libinetcfg.so \
-	/usr/lib/libinetcfg.so.1 \
 	/usr/lib/libinetutil.so \
 	/usr/lib/libinetutil.so.1 \
 	/usr/lib/libintl.so \
@@ -1588,8 +1582,6 @@
 	/usr/lib/llib-lelf.ln \
 	/usr/lib/llib-lgen \
 	/usr/lib/llib-lgen.ln \
-	/usr/lib/llib-linetcfg \
-	/usr/lib/llib-linetcfg.ln \
 	/usr/lib/llib-linetutil \
 	/usr/lib/llib-linetutil.ln \
 	/usr/lib/llib-lintl \
--- a/usr/src/cmd/cmd-inet/lib/nwamd/Makefile	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/Makefile	Mon Jun 07 14:10:14 2010 -0400
@@ -52,7 +52,7 @@
 ROOTCMDDIR=	$(ROOTFS_LIBDIR)/inet
 
 LDLIBS +=	-ldhcpagent -ldhcputil -ldladm -ldlpi -lgen \
-		-linetcfg -linetutil -lkstat -lnsl -lnvpair -lnwam \
+		-linetutil -lipadm -lkstat -lnsl -lnvpair -lnwam \
 		-lsecdb -lscf -lsocket -lsysevent -lumem -luutil
 
 #
--- a/usr/src/cmd/cmd-inet/lib/nwamd/conditions.c	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/conditions.c	Mon Jun 07 14:10:14 2010 -0400
@@ -20,25 +20,20 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <arpa/inet.h>
 #include <ctype.h>
 #include <errno.h>
 #include <inet/ip.h>
-#include <inetcfg.h>
 #include <libdladm.h>
 #include <libdllink.h>
 #include <libdlwlan.h>
 #include <netdb.h>
-#include <netinet/in.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/socket.h>
-#include <sys/types.h>
 
 #include <libnwam.h>
 #include "conditions.h"
@@ -405,6 +400,36 @@
 	return (B_TRUE);
 }
 
+/*
+ * Given a string representation of an IPv4 or IPv6 address returns the
+ * sockaddr representation. Note that 'sockaddr' should point at the correct
+ * sockaddr structure for the address family (sockaddr_in for AF_INET or
+ * sockaddr_in6 for AF_INET6) or alternatively at a sockaddr_storage
+ * structure.
+ */
+static struct sockaddr_storage *
+nwamd_str2sockaddr(sa_family_t af, const char *straddr,
+    struct sockaddr_storage *addr)
+{
+	struct sockaddr_in *sin;
+	struct sockaddr_in6 *sin6;
+	int err;
+
+	if (af == AF_INET) {
+		sin = (struct sockaddr_in *)addr;
+		sin->sin_family = AF_INET;
+		err = inet_pton(AF_INET, straddr, &sin->sin_addr);
+	} else if (af == AF_INET6) {
+		sin6 = (struct sockaddr_in6 *)addr;
+		sin6->sin6_family = AF_INET6;
+		err = inet_pton(AF_INET6, straddr, &sin6->sin6_addr);
+	} else {
+		errno = EINVAL;
+		return (NULL);
+	}
+	return (err == 1 ? addr : NULL);
+}
+
 struct nwamd_ipaddr_condition_walk_arg {
 	nwam_condition_t condition;
 	struct sockaddr_storage sockaddr;
@@ -413,41 +438,25 @@
 };
 
 static int
-check_ipaddr(icfg_if_t *intf, void *arg)
+check_ipaddr(sa_family_t family, struct ifaddrs *ifa, void *arg)
 {
 	struct nwamd_ipaddr_condition_walk_arg *wa = arg;
-	struct sockaddr_storage sockaddr;
-	icfg_handle_t h;
-	socklen_t addrlen = intf->if_protocol == AF_INET ?
-	    sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6);
-	int prefixlen = 0;
 	boolean_t match = B_FALSE;
 	uchar_t *addr1, *addr2;
 
-	if (icfg_open(&h, intf) != ICFG_SUCCESS)
-		return (0);
-
-	if (icfg_get_addr(h, (struct sockaddr *)&sockaddr, &addrlen,
-	    &prefixlen, B_TRUE) != ICFG_SUCCESS) {
-		nlog(LOG_ERR, "check_ipaddr: icfg_get_addr: %s",
-		    strerror(errno));
-		return (0);
-	}
-
-	if (intf->if_protocol == AF_INET) {
+	if (family == AF_INET) {
 		addr1 = (uchar_t *)&(((struct sockaddr_in *)
-		    &sockaddr)->sin_addr.s_addr);
+		    ifa->ifa_addr)->sin_addr.s_addr);
 		addr2 = (uchar_t *)&(((struct sockaddr_in *)
 		    &(wa->sockaddr))->sin_addr.s_addr);
 	} else {
 		addr1 = (uchar_t *)&(((struct sockaddr_in6 *)
-		    &sockaddr)->sin6_addr.s6_addr);
+		    ifa->ifa_addr)->sin6_addr.s6_addr);
 		addr2 = (uchar_t *)&(((struct sockaddr_in6 *)
 		    &(wa->sockaddr))->sin6_addr.s6_addr);
 	}
 
 	match = prefixmatch(addr1, addr2, wa->prefixlen);
-	icfg_close(h);
 
 	nlog(LOG_DEBUG, "check_ipaddr: match %d\n", match);
 	switch (wa->condition) {
@@ -470,11 +479,10 @@
 test_condition_ip_address(nwam_condition_t condition,
     const char *ip_address_string)
 {
-	int proto;
+	sa_family_t family;
 	char *copy, *ip_address, *prefixlen_string, *lasts;
-	socklen_t addrlen = sizeof (struct sockaddr_in);
-	socklen_t addr6len = sizeof (struct sockaddr_in6);
 	struct nwamd_ipaddr_condition_walk_arg wa;
+	struct ifaddrs *ifap, *ifa;
 
 	if ((copy = strdup(ip_address_string)) == NULL)
 		return (B_FALSE);
@@ -486,17 +494,17 @@
 
 	prefixlen_string = strtok_r(NULL, " \t", &lasts);
 
-	if (icfg_str_to_sockaddr(AF_INET, ip_address,
-	    (struct sockaddr *)&(wa.sockaddr), &addrlen) == ICFG_SUCCESS) {
-		proto = AF_INET;
+	if (nwamd_str2sockaddr(AF_INET, ip_address, &wa.sockaddr) != NULL) {
+		family = AF_INET;
 		wa.prefixlen = IP_ABITS;
-	} else if (icfg_str_to_sockaddr(AF_INET6, ip_address,
-	    (struct sockaddr *)&(wa.sockaddr), &addr6len) == ICFG_SUCCESS) {
-		proto = AF_INET6;
+	} else if (nwamd_str2sockaddr(AF_INET6, ip_address, &wa.sockaddr)
+	    != NULL) {
+		family = AF_INET6;
 		wa.prefixlen = IPV6_ABITS;
 	} else {
 		nlog(LOG_ERR, "test_condition_ip_address: "
-		    "icfg_str_to_sockaddr: %s", strerror(errno));
+		    "nwamd_str2sockaddr failed for %s: %s", ip_address,
+		    strerror(errno));
 		free(copy);
 		return (B_FALSE);
 	}
@@ -519,10 +527,20 @@
 		free(copy);
 		return (B_FALSE);
 	}
+	free(copy);
 
-	(void) icfg_iterate_if(proto, ICFG_PLUMBED, &wa, check_ipaddr);
-
-	free(copy);
+	if (getifaddrs(&ifa) == -1) {
+		nlog(LOG_ERR, "test_condition_ip_address: "
+		    "getifaddrs failed: %s", strerror(errno));
+		return (wa.res);
+	}
+	for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) {
+		if (ifap->ifa_addr->ss_family != family)
+			continue;
+		if (check_ipaddr(family, ifap, &wa) == 1)
+			break;
+	}
+	freeifaddrs(ifa);
 
 	return (wa.res);
 }
--- a/usr/src/cmd/cmd-inet/lib/nwamd/dlpi_events.c	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/dlpi_events.c	Mon Jun 07 14:10:14 2010 -0400
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <arpa/inet.h>
@@ -106,7 +105,7 @@
 
 	assert(ncu != NULL && ncu->ncu_type == NWAM_NCU_TYPE_LINK);
 
-	link = &ncu->ncu_node.u_link;
+	link = &ncu->ncu_link;
 
 	/* Already running? */
 	if (link->nwamd_link_dlpi_thread != 0) {
@@ -157,16 +156,15 @@
 	nlog(LOG_DEBUG, "nwamd_dlpi_delete_link: ncu %p (%s) type %d",
 	    ncu, obj->nwamd_object_name, ncu != NULL ? ncu->ncu_type : -1);
 
-	if (ncu->ncu_node.u_link.nwamd_link_dlpi_thread != 0) {
+	if (ncu->ncu_link.nwamd_link_dlpi_thread != 0) {
 		(void) pthread_cancel(
-		    ncu->ncu_node.u_link.nwamd_link_dlpi_thread);
-		(void) pthread_join(ncu->ncu_node.u_link.nwamd_link_dlpi_thread,
-		    NULL);
-		ncu->ncu_node.u_link.nwamd_link_dlpi_thread = 0;
+		    ncu->ncu_link.nwamd_link_dlpi_thread);
+		(void) pthread_join(ncu->ncu_link.nwamd_link_dlpi_thread, NULL);
+		ncu->ncu_link.nwamd_link_dlpi_thread = 0;
 		/* Unset properties before closing */
 		nwamd_set_unset_link_properties(ncu, B_FALSE);
 	}
 
-	dlpi_close(ncu->ncu_node.u_link.nwamd_link_dhp);
-	ncu->ncu_node.u_link.nwamd_link_dhp = NULL;
+	dlpi_close(ncu->ncu_link.nwamd_link_dhp);
+	ncu->ncu_link.nwamd_link_dhp = NULL;
 }
--- a/usr/src/cmd/cmd-inet/lib/nwamd/door_if.c	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/door_if.c	Mon Jun 07 14:10:14 2010 -0400
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <auth_attr.h>
@@ -188,7 +187,7 @@
 	}
 
 	ncu = obj->nwamd_object_data;
-	link = &ncu->ncu_node.u_link;
+	link = &ncu->ncu_link;
 	num_wlans = link->nwamd_link_wifi_scan.nwamd_wifi_scan_curr_num;
 
 	if (num_wlans > 0) {
--- a/usr/src/cmd/cmd-inet/lib/nwamd/enm.c	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/enm.c	Mon Jun 07 14:10:14 2010 -0400
@@ -20,14 +20,12 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <arpa/inet.h>
 #include <errno.h>
 #include <inet/ip.h>
-#include <inetcfg.h>
 #include <libdladm.h>
 #include <libdllink.h>
 #include <libdlwlan.h>
--- a/usr/src/cmd/cmd-inet/lib/nwamd/events.c	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/events.c	Mon Jun 07 14:10:14 2010 -0400
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <atomic.h>
@@ -369,7 +368,7 @@
 
 nwamd_event_t
 nwamd_event_init_if_state(const char *linkname, uint32_t flags,
-    uint32_t addr_added, uint32_t index, struct sockaddr *addr)
+    uint32_t addr_added, struct sockaddr *addr, struct sockaddr *netmask)
 {
 	nwamd_event_t event;
 	nwam_error_t err;
@@ -394,7 +393,6 @@
 	    linkname,
 	    sizeof (event->event_msg->nwe_data.nwe_if_state.nwe_name));
 	event->event_msg->nwe_data.nwe_if_state.nwe_flags = flags;
-	event->event_msg->nwe_data.nwe_if_state.nwe_index = index;
 	event->event_msg->nwe_data.nwe_if_state.nwe_addr_added = addr_added;
 	event->event_msg->nwe_data.nwe_if_state.nwe_addr_valid = (addr != NULL);
 
@@ -403,6 +401,12 @@
 		    addr->sa_family == AF_INET ? sizeof (struct sockaddr_in) :
 		    sizeof (struct sockaddr_in6));
 	}
+	if (netmask != NULL) {
+		bcopy(netmask,
+		    &(event->event_msg->nwe_data.nwe_if_state.nwe_netmask),
+		    netmask->sa_family == AF_INET ?
+		    sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6));
+	}
 
 	return (event);
 }
--- a/usr/src/cmd/cmd-inet/lib/nwamd/events.h	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/events.h	Mon Jun 07 14:10:14 2010 -0400
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #ifndef _EVENTS_H
@@ -102,7 +101,7 @@
 extern nwamd_event_t nwamd_event_init_link_action(const char *, nwam_action_t);
 extern nwamd_event_t nwamd_event_init_link_state(const char *, boolean_t);
 extern nwamd_event_t nwamd_event_init_if_state(const char *, uint32_t,
-    uint32_t, uint32_t, struct sockaddr *);
+    uint32_t, struct sockaddr *, struct sockaddr *);
 extern nwamd_event_t nwamd_event_init_wlan(const char *, int32_t, boolean_t,
     nwam_wlan_t *, uint_t);
 extern nwamd_event_t nwamd_event_init_ncu_check(void);
--- a/usr/src/cmd/cmd-inet/lib/nwamd/known_wlans.c	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/known_wlans.c	Mon Jun 07 14:10:14 2010 -0400
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <ctype.h>
@@ -501,7 +500,7 @@
 		return (0);
 
 	/* network selection will be done only if possible */
-	if (ncu_data->ncu_node.u_link.nwamd_link_media == DL_WIFI)
+	if (ncu_data->ncu_link.nwamd_link_media == DL_WIFI)
 		(void) nwamd_wlan_scan(ncu_data->ncu_name);
 	return (0);
 }
--- a/usr/src/cmd/cmd-inet/lib/nwamd/loc.c	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/loc.c	Mon Jun 07 14:10:14 2010 -0400
@@ -26,7 +26,6 @@
 #include <arpa/inet.h>
 #include <errno.h>
 #include <inet/ip.h>
-#include <inetcfg.h>
 #include <libdladm.h>
 #include <libdllink.h>
 #include <libdlwlan.h>
--- a/usr/src/cmd/cmd-inet/lib/nwamd/main.c	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/main.c	Mon Jun 07 14:10:14 2010 -0400
@@ -25,7 +25,6 @@
 
 #include <errno.h>
 #include <fcntl.h>
-#include <inetcfg.h>
 #include <libdllink.h>
 #include <libintl.h>
 #include <libnwam.h>
@@ -55,6 +54,7 @@
 
 boolean_t fg = B_FALSE;
 dladm_handle_t dld_handle = NULL;
+ipadm_handle_t ipadm_handle = NULL;
 boolean_t shutting_down = B_FALSE;
 
 sigset_t original_sigmask;
@@ -317,7 +317,8 @@
 	int c;
 	uint64_t version;
 	nwamd_event_t event;
-	dladm_status_t rc;
+	dladm_status_t drc;
+	ipadm_status_t irc;
 	uid_t uid = getuid();
 
 	/*
@@ -367,13 +368,17 @@
 	 * then one must have *all* privs in order to open /dev/dld, which
 	 * is one of the steps performed in dladm_open().
 	 */
-	rc = dladm_open(&dld_handle);
-	if (rc != DLADM_STATUS_OK) {
+	drc = dladm_open(&dld_handle);
+	if (drc != DLADM_STATUS_OK) {
 		char status_str[DLADM_STRSIZE];
-		(void) dladm_status2str(rc, status_str);
-		pfail("failed to open dladm handle: %s", status_str);
+		pfail("failed to open dladm handle: %s",
+		    dladm_status2str(drc, status_str));
 	}
 
+	irc = ipadm_open(&ipadm_handle, 0);
+	if (irc != IPADM_SUCCESS)
+		pfail("failed to open ipadm handle: %s", ipadm_status2str(irc));
+
 	/*
 	 * Create the event queue before starting event sources, including
 	 * signal handling, so we are ready to handle incoming events.  Also
@@ -462,6 +467,7 @@
 	 */
 	nwamd_event_handler();
 
+	ipadm_close(ipadm_handle);
 	dladm_close(dld_handle);
 
 	return (EXIT_SUCCESS);
--- a/usr/src/cmd/cmd-inet/lib/nwamd/ncp.c	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/ncp.c	Mon Jun 07 14:10:14 2010 -0400
@@ -237,11 +237,11 @@
 	uint64_t priority;
 	nwamd_ncu_t *ncu = object->nwamd_object_data;
 
-	if (ncu->ncu_node.u_link.nwamd_link_activation_mode !=
+	if (ncu->ncu_link.nwamd_link_activation_mode !=
 	    NWAM_ACTIVATION_MODE_PRIORITIZED)
 		return (0);
 
-	priority = ncu->ncu_node.u_link.nwamd_link_priority_group;
+	priority = ncu->ncu_link.nwamd_link_priority_group;
 
 	if (priority >= cbarg->minpriority && priority < cbarg->currpriority) {
 		cbarg->found = B_TRUE;
@@ -340,21 +340,21 @@
 		    "skipping interface NCU %s", name);
 		return (0);
 	}
-	if (!wa->manual && ncu->ncu_node.u_link.nwamd_link_activation_mode !=
+	if (!wa->manual && ncu->ncu_link.nwamd_link_activation_mode !=
 	    NWAM_ACTIVATION_MODE_PRIORITIZED) {
 		nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: "
 		    "skipping non-prioritized NCU %s", name);
 		return (0);
 	}
-	if (wa->manual && ncu->ncu_node.u_link.nwamd_link_activation_mode !=
+	if (wa->manual && ncu->ncu_link.nwamd_link_activation_mode !=
 	    NWAM_ACTIVATION_MODE_MANUAL) {
 		nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: "
 		    "skipping non-manual NCU %s", name);
 		return (0);
 	}
 
-	priority_group = ncu->ncu_node.u_link.nwamd_link_priority_group;
-	priority_mode = ncu->ncu_node.u_link.nwamd_link_priority_mode;
+	priority_group = ncu->ncu_link.nwamd_link_priority_group;
+	priority_mode = ncu->ncu_link.nwamd_link_priority_mode;
 	/* Only work with NCUs in the requested priority-group */
 	if (!wa->manual && priority_group != wa->priority_group) {
 		nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: "
--- a/usr/src/cmd/cmd-inet/lib/nwamd/ncp.h	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/ncp.h	Mon Jun 07 14:10:14 2010 -0400
@@ -20,14 +20,12 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #ifndef _NCP_H
 #define	_NCP_H
 
-#include <inetcfg.h>
 #include <libdladm.h>
 #include <libdlpi.h>
 #include <libdlwlan.h>
--- a/usr/src/cmd/cmd-inet/lib/nwamd/ncu.c	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/ncu.c	Mon Jun 07 14:10:14 2010 -0400
@@ -51,6 +51,8 @@
 
 #define	VBOX_IFACE_PREFIX	"vboxnet"
 
+static void populate_ip_ncu_properties(nwam_ncu_handle_t, nwamd_ncu_t *);
+
 /*
  * Find ncu of specified type for link/interface name.
  */
@@ -149,7 +151,7 @@
 	}
 
 	ncu = object->nwamd_object_data;
-	link = &ncu->ncu_node.u_link;
+	link = &ncu->ncu_link;
 
 	switch (object->nwamd_object_aux_state) {
 	case NWAM_AUX_STATE_INITIALIZED:
@@ -217,8 +219,16 @@
 			 * would be good to try and minimize configuration
 			 * changes.
 			 */
-			nwamd_unplumb_interface(ncu, 0, AF_INET);
-			nwamd_unplumb_interface(ncu, 0, AF_INET6);
+			nwamd_unplumb_interface(ncu, AF_INET);
+			nwamd_unplumb_interface(ncu, AF_INET6);
+
+			/*
+			 * We may be restarting the state machine.  Re-read
+			 * the IP NCU properties as the ipadm_addrobj_t in
+			 * nwamd_if_address should not be reused.
+			 */
+			populate_ip_ncu_properties(object->nwamd_object_handle,
+			    ncu);
 
 			/*
 			 * Enqueue a WAITING_FOR_ADDR aux state change so that
@@ -231,26 +241,14 @@
 			    object_name, NWAM_STATE_OFFLINE_TO_ONLINE,
 			    NWAM_AUX_STATE_IF_WAITING_FOR_ADDR);
 
-			if (ncu->ncu_node.u_if.nwamd_if_ipv4)
-				nwamd_plumb_interface(ncu, 0, AF_INET);
-
-			if (ncu->ncu_node.u_if.nwamd_if_ipv6)
-				nwamd_plumb_interface(ncu, 0, AF_INET6);
+			if (ncu->ncu_if.nwamd_if_ipv4)
+				nwamd_plumb_interface(ncu, AF_INET);
 
-			/*
-			 * Configure addresses.  Configure any static addresses
-			 * and start DHCP if required.  If DHCP is not required,
-			 * do a DHCPINFORM to get other networking config
-			 * parameters.  RTM_NEWADDRs - translated into IF_STATE
-			 * events - will then finish the job of bringing us
-			 * online.
-			 */
+			if (ncu->ncu_if.nwamd_if_ipv6)
+				nwamd_plumb_interface(ncu, AF_INET6);
+
+			/* Configure addresses */
 			nwamd_configure_interface_addresses(ncu);
-
-			if (ncu->ncu_node.u_if.nwamd_if_dhcp_requested)
-				nwamd_start_dhcp(ncu);
-			else
-				nwamd_dhcp_inform(ncu);
 		}
 		break;
 
@@ -440,8 +438,8 @@
 			 * until we reconnect to a different WLAN (i.e. with
 			 * a different ESSID).
 			 */
-			nwamd_unplumb_interface(ncu, 0, AF_INET);
-			nwamd_unplumb_interface(ncu, 0, AF_INET6);
+			nwamd_unplumb_interface(ncu, AF_INET);
+			nwamd_unplumb_interface(ncu, AF_INET6);
 		}
 		if (object->nwamd_object_state != NWAM_STATE_OFFLINE) {
 			nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
@@ -471,11 +469,11 @@
 			nwamd_dlpi_delete_link(object);
 		} else {
 			/* Unplumb here. */
-			if (ncu->ncu_node.u_if.nwamd_if_ipv4) {
-				nwamd_unplumb_interface(ncu, 0, AF_INET);
+			if (ncu->ncu_if.nwamd_if_ipv4) {
+				nwamd_unplumb_interface(ncu, AF_INET);
 			}
-			if (ncu->ncu_node.u_if.nwamd_if_ipv6) {
-				nwamd_unplumb_interface(ncu, 0, AF_INET6);
+			if (ncu->ncu_if.nwamd_if_ipv6) {
+				nwamd_unplumb_interface(ncu, AF_INET6);
 			}
 			/* trigger location condition checking */
 			nwamd_create_triggered_condition_check_event(0);
@@ -658,13 +656,12 @@
 		    "populate_link_ncu_properties: could not get %s value: %s",
 		    NWAM_NCU_PROP_ACTIVATION_MODE, nwam_strerror(err));
 	} else {
-		ncu_data->ncu_node.u_link.nwamd_link_activation_mode =
-		    uintval[0];
+		ncu_data->ncu_link.nwamd_link_activation_mode = uintval[0];
 		nwam_value_free(ncu_prop);
 	}
 
 	/* priority-group and priority-mode for prioritized activation */
-	if (ncu_data->ncu_node.u_link.nwamd_link_activation_mode ==
+	if (ncu_data->ncu_link.nwamd_link_activation_mode ==
 	    NWAM_ACTIVATION_MODE_PRIORITIZED) {
 		/* ncus with prioritized activation are always enabled */
 		ncu_data->ncu_enabled = B_TRUE;
@@ -675,7 +672,7 @@
 			    "could not get %s value: %s",
 			    NWAM_NCU_PROP_PRIORITY_MODE, nwam_strerror(err));
 		} else {
-			ncu_data->ncu_node.u_link.nwamd_link_priority_mode =
+			ncu_data->ncu_link.nwamd_link_priority_mode =
 			    uintval[0];
 			nwam_value_free(ncu_prop);
 		}
@@ -687,7 +684,7 @@
 			    "could not get %s value: %s",
 			    NWAM_NCU_PROP_PRIORITY_GROUP, nwam_strerror(err));
 		} else {
-			ncu_data->ncu_node.u_link.nwamd_link_priority_group =
+			ncu_data->ncu_link.nwamd_link_priority_group =
 			    uintval[0];
 			nwam_value_free(ncu_prop);
 		}
@@ -699,12 +696,10 @@
 		nlog(LOG_DEBUG,
 		    "populate_link_ncu_properties: could not get %s value: %s",
 		    NWAM_NCU_PROP_LINK_MAC_ADDR, nwam_strerror(err));
-		ncu_data->ncu_node.u_link.nwamd_link_mac_addr = NULL;
+		ncu_data->ncu_link.nwamd_link_mac_addr = NULL;
 	} else {
-		ncu_data->ncu_node.u_link.nwamd_link_mac_addr =
-		    strdup(*mac_addr);
-		ncu_data->ncu_node.u_link.nwamd_link_mac_addr_len =
-		    strlen(*mac_addr);
+		ncu_data->ncu_link.nwamd_link_mac_addr = strdup(*mac_addr);
+		ncu_data->ncu_link.nwamd_link_mac_addr_len = strlen(*mac_addr);
 		nwam_value_free(ncu_prop);
 	}
 
@@ -714,34 +709,35 @@
 		nlog(LOG_DEBUG,
 		    "populate_link_ncu_properties: could not get %s value: %s",
 		    NWAM_NCU_PROP_LINK_MTU, nwam_strerror(err));
-		ncu_data->ncu_node.u_link.nwamd_link_mtu = 0;
+		ncu_data->ncu_link.nwamd_link_mtu = 0;
 	} else {
-		ncu_data->ncu_node.u_link.nwamd_link_mtu = uintval[0];
+		ncu_data->ncu_link.nwamd_link_mtu = uintval[0];
 		nwam_value_free(ncu_prop);
 	}
 
 	/* link-autopush */
 	if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop,
-	    &ncu_data->ncu_node.u_link.nwamd_link_autopush,
-	    &ncu_data->ncu_node.u_link.nwamd_link_num_autopush,
+	    &ncu_data->ncu_link.nwamd_link_autopush,
+	    &ncu_data->ncu_link.nwamd_link_num_autopush,
 	    NWAM_NCU_PROP_LINK_AUTOPUSH)) != NWAM_SUCCESS) {
 		nlog(LOG_DEBUG,
 		    "populate_link_ncu_properties: could not get %s value: %s",
 		    NWAM_NCU_PROP_LINK_AUTOPUSH, nwam_strerror(err));
-		ncu_data->ncu_node.u_link.nwamd_link_num_autopush = 0;
+		ncu_data->ncu_link.nwamd_link_num_autopush = 0;
 	}
 }
 
 static void
 populate_ip_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data)
 {
-	nwamd_if_t *nif = &ncu_data->ncu_node.u_if;
+	nwamd_if_t *nif = &ncu_data->ncu_if;
 	struct nwamd_if_address **nifa, *nifai, *nifait;
-	char *prefix;
 	boolean_t static_addr = B_FALSE;
 	uint64_t *addrsrcvalue;
 	nwam_value_t ncu_prop;
 	nwam_error_t err;
+	ipadm_addrobj_t ipaddr;
+	ipadm_status_t ipstatus;
 	char **addrvalue;
 	uint_t numvalues;
 	uint64_t *ipversion;
@@ -783,6 +779,7 @@
 	for (nifai = nif->nwamd_if_list; nifai != NULL; nifai = nifait) {
 		nifait = nifai->next;
 		nifai->next = NULL;
+		ipadm_destroy_addrobj(nifai->ipaddr);
 		free(nifai);
 	}
 	nif->nwamd_if_list = NULL;
@@ -813,14 +810,38 @@
 		nwam_value_free(ncu_prop);
 	}
 	if (nif->nwamd_if_dhcp_requested) {
+		ipstatus = ipadm_create_addrobj(IPADM_ADDR_DHCP,
+		    ncu_data->ncu_name, &ipaddr);
+		if (ipstatus != IPADM_SUCCESS) {
+			nlog(LOG_ERR, "populate_ip_ncu_properties: "
+			    "ipadm_create_addrobj failed for v4 dhcp: %s",
+			    ipadm_status2str(ipstatus));
+			goto skip_ipv4_dhcp;
+		}
+
+		ipstatus = ipadm_set_wait_time(ipaddr, ncu_wait_time);
+		if (ipstatus != IPADM_SUCCESS) {
+			nlog(LOG_ERR, "populate_ip_ncu_properties: "
+			    "ipadm_set_wait_time failed for v4 dhcp: %s",
+			    ipadm_status2str(ipstatus));
+			ipadm_destroy_addrobj(ipaddr);
+			goto skip_ipv4_dhcp;
+		}
 		if ((*nifa = calloc(sizeof (**nifa), 1)) != NULL) {
-			(*nifa)->address.sa_family = AF_INET;
-			(*nifa)->dhcp_if = B_TRUE;
+			(*nifa)->family = AF_INET;
+			(*nifa)->ipaddr_atype = IPADM_ADDR_DHCP;
+			(*nifa)->ipaddr = ipaddr;
 			nifa = &((*nifa)->next);
 			*nifa = NULL;
+		} else {
+			nlog(LOG_ERR, "populate_ip_ncu_properties: "
+			    "couldn't allocate nwamd address for v4 dhcp: %s",
+			    strerror(errno));
+			ipadm_destroy_addrobj(ipaddr);
 		}
 	}
 
+skip_ipv4_dhcp:
 	/* ipv4-addr */
 	if (static_addr) {
 		if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue,
@@ -829,28 +850,46 @@
 			    "could not get %s value; %s",
 			    NWAM_NCU_PROP_IPV4_ADDR, nwam_strerror(err));
 		} else {
-			struct sockaddr_in *s;
-
 			for (i = 0; i < numvalues; i++) {
-				if ((*nifa = calloc(sizeof (**nifa), 1))
-				    == NULL) {
-					nlog(LOG_ERR, "couldn't allocate nwamd"
-					    "address");
+				ipstatus = ipadm_create_addrobj(
+				    IPADM_ADDR_STATIC, ncu_data->ncu_name,
+				    &ipaddr);
+				if (ipstatus != IPADM_SUCCESS) {
+					nlog(LOG_ERR,
+					    "populate_ip_ncu_properties: "
+					    "ipadm_create_addrobj failed "
+					    "for %s: %s", addrvalue[i],
+					    ipadm_status2str(ipstatus));
 					continue;
 				}
-				(*nifa)->address.sa_family = AF_INET;
-				/*LINTED*/
-				s = (struct sockaddr_in *)&(*nifa)->address;
-				s->sin_family = AF_INET;
-				s->sin_port = 0;
-				prefix = strchr(addrvalue[i], '/');
-				if (prefix != NULL) {
-					*prefix++ = 0;
-					(*nifa)->prefix = atoi(prefix);
+				/* ipadm_set_addr takes <addr>[/<mask>] */
+				ipstatus = ipadm_set_addr(ipaddr, addrvalue[i],
+				    AF_INET);
+				if (ipstatus != IPADM_SUCCESS) {
+					nlog(LOG_ERR,
+					    "populate_ip_ncu_properties: "
+					    "ipadm_set_addr failed for %s: %s",
+					    addrvalue[i],
+					    ipadm_status2str(ipstatus));
+					ipadm_destroy_addrobj(ipaddr);
+					continue;
 				}
-				(void) inet_pton(AF_INET, addrvalue[i],
-				    &(s->sin_addr));
-				nifa = &((*nifa)->next);
+
+				if ((*nifa = calloc(sizeof (**nifa), 1))
+				    != NULL) {
+					(*nifa)->family = AF_INET;
+					(*nifa)->ipaddr_atype =
+					    IPADM_ADDR_STATIC;
+					(*nifa)->ipaddr = ipaddr;
+					nifa = &((*nifa)->next);
+				} else {
+					nlog(LOG_ERR,
+					    "populate_ip_ncu_properties: "
+					    "couldn't allocate nwamd address "
+					    "for %s: %s", addrvalue[i],
+					    strerror(errno));
+					ipadm_destroy_addrobj(ipaddr);
+				}
 			}
 			*nifa = NULL;
 
@@ -870,7 +909,6 @@
 	}
 
 skip_ipv4:
-
 	if (!nif->nwamd_if_ipv6)
 		goto skip_ipv6;
 
@@ -899,23 +937,58 @@
 		}
 		nwam_value_free(ncu_prop);
 	}
-	if (nif->nwamd_if_stateful_requested) {
+	/*
+	 * Both stateful and stateless share the same nwamd_if_address because
+	 * only one ipaddr for both of these addresses can be created.
+	 * ipadm_create_addr() adds both addresses from the same ipaddr.
+	 */
+	if (nif->nwamd_if_stateful_requested ||
+	    nif->nwamd_if_stateless_requested) {
+		ipstatus = ipadm_create_addrobj(IPADM_ADDR_IPV6_ADDRCONF,
+		    ncu_data->ncu_name, &ipaddr);
+		if (ipstatus != IPADM_SUCCESS) {
+			nlog(LOG_ERR, "populate_ip_ncu_properties: "
+			    "ipadm_create_addrobj failed for v6 "
+			    "stateless/stateful: %s",
+			    ipadm_status2str(ipstatus));
+			goto skip_ipv6_addrconf;
+		}
+		/* create_addrobj sets both stateless and stateful to B_TRUE */
+		if (!nif->nwamd_if_stateful_requested) {
+			ipstatus = ipadm_set_stateful(ipaddr, B_FALSE);
+			if (ipstatus != IPADM_SUCCESS) {
+				nlog(LOG_ERR, "populate_ip_ncu_properties: "
+				    "ipadm_set_stateful failed for v6: %s",
+				    ipadm_status2str(ipstatus));
+				ipadm_destroy_addrobj(ipaddr);
+				goto skip_ipv6_addrconf;
+			}
+		}
+		if (!nif->nwamd_if_stateless_requested) {
+			ipstatus = ipadm_set_stateless(ipaddr, B_FALSE);
+			if (ipstatus != IPADM_SUCCESS) {
+				nlog(LOG_ERR, "populate_ip_ncu_properties: "
+				    "ipadm_set_stateless failed for v6: %s",
+				    ipadm_status2str(ipstatus));
+				ipadm_destroy_addrobj(ipaddr);
+				goto skip_ipv6_addrconf;
+			}
+		}
 		if ((*nifa = calloc(sizeof (**nifa), 1)) != NULL) {
-			(*nifa)->address.sa_family = AF_INET6;
-			(*nifa)->dhcp_if = B_TRUE;
+			(*nifa)->family = AF_INET6;
+			(*nifa)->ipaddr_atype = IPADM_ADDR_IPV6_ADDRCONF;
+			(*nifa)->ipaddr = ipaddr;
 			nifa = &((*nifa)->next);
 			*nifa = NULL;
-		}
-	}
-	if (nif->nwamd_if_stateless_requested) {
-		if ((*nifa = calloc(sizeof (**nifa), 1)) != NULL) {
-			(*nifa)->address.sa_family = AF_INET6;
-			(*nifa)->stateless_if = B_TRUE;
-			nifa = &((*nifa)->next);
-			*nifa = NULL;
+		} else {
+			nlog(LOG_ERR, "populate_ip_ncu_properties: "
+			    "couldn't allocate nwamd address for "
+			    "v6 stateless/stateful: %s", strerror(errno));
+			ipadm_destroy_addrobj(ipaddr);
 		}
 	}
 
+skip_ipv6_addrconf:
 	/* ipv6-addr */
 	if (static_addr) {
 		if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue,
@@ -924,28 +997,46 @@
 			    "could not get %s value; %s",
 			    NWAM_NCU_PROP_IPV6_ADDR, nwam_strerror(err));
 		} else {
-			struct sockaddr_in6 *s;
-
 			for (i = 0; i < numvalues; i++) {
-				if ((*nifa = calloc(sizeof (**nifa), 1))
-				    == NULL) {
-					nlog(LOG_ERR, "couldn't allocate nwamd"
-					    "address");
+				ipstatus = ipadm_create_addrobj(
+				    IPADM_ADDR_STATIC, ncu_data->ncu_name,
+				    &ipaddr);
+				if (ipstatus != IPADM_SUCCESS) {
+					nlog(LOG_ERR,
+					    "populate_ip_ncu_properties: "
+					    "ipadm_create_addrobj failed "
+					    "for %s: %s", addrvalue[i],
+					    ipadm_status2str(ipstatus));
 					continue;
 				}
-				(*nifa)->address.sa_family = AF_INET6;
-				/*LINTED*/
-				s = (struct sockaddr_in6 *)&(*nifa)->address;
-				s->sin6_family = AF_INET6;
-				s->sin6_port = 0;
-				prefix = strchr(addrvalue[i], '/');
-				if (prefix != NULL) {
-					*prefix++ = 0;
-					(*nifa)->prefix = atoi(prefix);
+				/* ipadm_set_addr takes <addr>[/<mask>] */
+				ipstatus = ipadm_set_addr(ipaddr, addrvalue[i],
+				    AF_INET6);
+				if (ipstatus != IPADM_SUCCESS) {
+					nlog(LOG_ERR,
+					    "populate_ip_ncu_properties: "
+					    "ipadm_set_addr failed for %s: %s",
+					    addrvalue[i],
+					    ipadm_status2str(ipstatus));
+					ipadm_destroy_addrobj(ipaddr);
+					continue;
 				}
-				(void) inet_pton(AF_INET6, addrvalue[i],
-				    &(s->sin6_addr));
-				nifa = &((*nifa)->next);
+
+				if ((*nifa = calloc(sizeof (**nifa), 1))
+				    != NULL) {
+					(*nifa)->family = AF_INET6;
+					(*nifa)->ipaddr_atype =
+					    IPADM_ADDR_STATIC;
+					(*nifa)->ipaddr = ipaddr;
+					nifa = &((*nifa)->next);
+				} else {
+					nlog(LOG_ERR,
+					    "populate_ip_ncu_properties: "
+					    "couldn't allocate nwamd address "
+					    "for %s: %s", addrvalue[i],
+					    strerror(errno));
+					ipadm_destroy_addrobj(ipaddr);
+				}
 			}
 			*nifa = NULL;
 
@@ -984,15 +1075,15 @@
 
 	/* Initialize link/interface-specific data */
 	if (rv->ncu_type == NWAM_NCU_TYPE_LINK) {
-		(void) bzero(&rv->ncu_node.u_link, sizeof (nwamd_link_t));
+		(void) bzero(&rv->ncu_link, sizeof (nwamd_link_t));
 		(void) dladm_name2info(dld_handle, name,
-		    &rv->ncu_node.u_link.nwamd_link_id, NULL, NULL,
-		    &rv->ncu_node.u_link.nwamd_link_media);
+		    &rv->ncu_link.nwamd_link_id, NULL, NULL,
+		    &rv->ncu_link.nwamd_link_media);
 		(void) pthread_mutex_init(
-		    &rv->ncu_node.u_link.nwamd_link_wifi_mutex, NULL);
-		rv->ncu_node.u_link.nwamd_link_wifi_priority = MAXINT;
+		    &rv->ncu_link.nwamd_link_wifi_mutex, NULL);
+		rv->ncu_link.nwamd_link_wifi_priority = MAXINT;
 	} else {
-		(void) bzero(&rv->ncu_node.u_if, sizeof (nwamd_if_t));
+		(void) bzero(&rv->ncu_if, sizeof (nwamd_if_t));
 	}
 
 	return (rv);
@@ -1005,7 +1096,7 @@
 		assert(ncu->ncu_type == NWAM_NCU_TYPE_LINK ||
 		    ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE);
 		if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) {
-			struct nwamd_link *l = &ncu->ncu_node.u_link;
+			struct nwamd_link *l = &ncu->ncu_link;
 			int i;
 
 			free(l->nwamd_link_wifi_key);
@@ -1015,12 +1106,13 @@
 		} else if (ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE) {
 			struct nwamd_if_address *nifa;
 
-			nifa = ncu->ncu_node.u_if.nwamd_if_list;
+			nifa = ncu->ncu_if.nwamd_if_list;
 			while (nifa != NULL) {
 				struct nwamd_if_address *n;
 
 				n = nifa;
 				nifa = nifa->next;
+				ipadm_destroy_addrobj(n->ipaddr);
 				free(n);
 			}
 		}
@@ -1638,7 +1730,7 @@
 			    NWAM_AUX_STATE_CONDITIONS_NOT_MET;
 		}
 	} else {
-		nwamd_link_t *link = &ncu->ncu_node.u_link;
+		nwamd_link_t *link = &ncu->ncu_link;
 
 		/*
 		 * Refresh NCU.  Deal with disabled cases first, moving NCUs
@@ -1689,7 +1781,7 @@
 
 		switch (type) {
 		case NWAM_NCU_TYPE_LINK:
-			if (ncu->ncu_node.u_link.nwamd_link_media == DL_WIFI) {
+			if (ncu->ncu_link.nwamd_link_media == DL_WIFI) {
 				/*
 				 * Do rescan.  If the current state and the
 				 * active priority-group do not allow wireless
@@ -1926,7 +2018,7 @@
 	if (is_link)
 		(void) strlcpy(linkname, ncu->ncu_name, sizeof (linkname));
 	prioritized = (ncu->ncu_type == NWAM_NCU_TYPE_LINK &&
-	    ncu->ncu_node.u_link.nwamd_link_activation_mode ==
+	    ncu->ncu_link.nwamd_link_activation_mode ==
 	    NWAM_ACTIVATION_MODE_PRIORITIZED);
 	enabled = ncu->ncu_enabled;
 
--- a/usr/src/cmd/cmd-inet/lib/nwamd/ncu.h	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/ncu.h	Mon Jun 07 14:10:14 2010 -0400
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #ifndef _NCU_H
@@ -29,10 +28,11 @@
 
 #include <dhcpagent_ipc.h>
 #include <dhcpagent_util.h>
-#include <inetcfg.h>
 #include <libdladm.h>
 #include <libdlpi.h>
 #include <libdlwlan.h>
+#include <libinetutil.h>
+#include <libipadm.h>
 #include <libnwam.h>
 #include <libnwam_priv.h>
 #include <libuutil.h>
@@ -111,13 +111,12 @@
 } nwamd_link_t;
 
 struct nwamd_if_address {
-	size_t prefix;
-	struct sockaddr address;
-	char pad[sizeof (struct sockaddr_storage)];
+	sa_family_t family;
+	ipadm_addr_type_t ipaddr_atype;
+	ipadm_addrobj_t ipaddr;
 	boolean_t configured;
-	boolean_t dhcp_if;
-	boolean_t stateless_if;
-	char ifname[LIFNAMSIZ];
+	struct sockaddr_storage conf_addr;	/* address configured for */
+	struct sockaddr_storage conf_stateless_addr; /* this nwamd_if_address */
 	struct nwamd_if_address *next;
 };
 
@@ -156,7 +155,7 @@
 struct nwamd_dhcp_thread_arg {
 	char *name;
 	dhcp_ipc_type_t type;
-	int timeout;
+	ipadm_addrobj_t ipaddr;
 	volatile uint32_t *guard;
 };
 
@@ -171,10 +170,11 @@
 #define	NWAMD_READONLY_RETRY_INTERVAL		5
 
 /*
- * This dladm handle is opened before interfaces are initialized and
- * closed only when nwamd shuts down.
+ * This dladm and ipadm handles are opened before interfaces are initialized
+ * and closed only when nwamd shuts down.
  */
 extern dladm_handle_t dld_handle;
+extern ipadm_handle_t ipadm_handle;
 
 extern nwamd_object_t nwamd_ncu_object_find(nwam_ncu_type_t, const char *);
 extern void nwamd_log_ncus(void);
@@ -196,7 +196,8 @@
 
 /* Link functions */
 extern link_state_t nwamd_get_link_state(const char *);
-extern char *nwamd_sockaddr_to_str(const struct sockaddr *, char *, size_t);
+extern const char *nwamd_sockaddr_to_str(const struct sockaddr *, char *,
+    size_t);
 extern void nwamd_propogate_link_up_down_to_ip(const char *, boolean_t);
 extern void nwamd_set_unset_link_properties(nwamd_ncu_t *, boolean_t);
 /* DLPI event hooking */
@@ -204,12 +205,9 @@
 extern void nwamd_dlpi_delete_link(nwamd_object_t);
 
 /* IP functions */
-extern void nwamd_update_addresses_unconfigured(nwamd_ncu_t *, sa_family_t);
 extern boolean_t nwamd_static_addresses_configured(nwamd_ncu_t *, sa_family_t);
-extern void nwamd_plumb_interface(nwamd_ncu_t *, uint_t, int);
-extern void nwamd_unplumb_interface(nwamd_ncu_t *, uint_t, int);
-extern void nwamd_start_dhcp(nwamd_ncu_t *);
-extern void nwamd_dhcp_inform(nwamd_ncu_t *);
+extern void nwamd_plumb_interface(nwamd_ncu_t *, sa_family_t);
+extern void nwamd_unplumb_interface(nwamd_ncu_t *, sa_family_t);
 extern boolean_t nwamd_dhcp_managing(int, nwamd_ncu_t *);
 extern void nwamd_configure_interface_addresses(nwamd_ncu_t *);
 extern char *nwamd_get_dhcpinfo_data(const char *, char *);
@@ -230,6 +228,4 @@
 
 extern void nwamd_walk_physical_configuration(void);
 
-char *nwamd_link_to_ifname(const char *, int, char *, int);
-
 #endif /* _NCU_H */
--- a/usr/src/cmd/cmd-inet/lib/nwamd/ncu_ip.c	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/ncu_ip.c	Mon Jun 07 14:10:14 2010 -0400
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <arpa/inet.h>
@@ -32,13 +31,9 @@
 #include <dhcpagent_util.h>
 #include <errno.h>
 #include <execinfo.h>
-#include <inetcfg.h>
 #include <libnwam.h>
-#include <netinet/in.h>
 #include <stdlib.h>
 #include <strings.h>
-#include <sys/socket.h>
-#include <sys/types.h>
 #include <ucontext.h>
 #include <unistd.h>
 #include <libscf.h>
@@ -57,30 +52,41 @@
 #define	STATELESS_RUNNING	(IFF_RUNNING | IFF_UP | IFF_ADDRCONF)
 #define	DHCP_RUNNING		(IFF_RUNNING | IFF_UP | IFF_DHCPRUNNING)
 
-static void *start_dhcp_thread(void *);
-static void nwamd_down_interface(const char *, uint_t, int);
+static void nwamd_dhcp(const char *, ipadm_addrobj_t, dhcp_ipc_type_t);
+static void nwamd_down_interface(const char *, ipadm_addr_type_t, const char *);
 static boolean_t stateless_running(const nwamd_ncu_t *);
 
-char *
-nwamd_sockaddr_to_str(const struct sockaddr *sockaddr, char *str, size_t len)
+/*
+ * Given a sockaddr representation of an IPv4 or IPv6 address returns the
+ * string representation. Note that 'sockaddr' should point at the correct
+ * sockaddr structure for the address family (sockaddr_in for AF_INET or
+ * sockaddr_in6 for AF_INET6) or alternatively at a sockaddr_storage
+ * structure.
+ */
+static const char *
+nwamd_sockaddr2str(const struct sockaddr *addr, char *str, size_t len)
 {
-	if (icfg_sockaddr_to_str(sockaddr->sa_family, sockaddr, str, len) !=
-	    ICFG_SUCCESS) {
+	struct sockaddr_in *sin;
+	struct sockaddr_in6 *sin6;
+	const char *straddr;
+
+	if (addr == NULL)
 		return (NULL);
+
+	if (addr->sa_family == AF_INET) {
+		/* LINTED E_BAD_PTR_CAST_ALIGN */
+		sin = (struct sockaddr_in *)addr;
+		straddr = inet_ntop(AF_INET, (void *)&sin->sin_addr, str, len);
+	} else if (addr->sa_family == AF_INET6) {
+		/* LINTED E_BAD_PTR_CAST_ALIGN */
+		sin6 = (struct sockaddr_in6 *)addr;
+		straddr = inet_ntop(AF_INET6, (void *)&sin6->sin6_addr, str,
+		    len);
 	} else {
-		return (str);
+		errno = EINVAL;
+		return (NULL);
 	}
-}
-
-static void
-nwamd_log_if_address(int severity, struct nwamd_if_address *nifa)
-{
-	char str[INET6_ADDRSTRLEN];
-
-	nlog(severity, "%s address %s is %s",
-	    nifa->address.sa_family == AF_INET ? "IPv4" : "IPv6",
-	    nwamd_sockaddr_to_str(&nifa->address, str, sizeof (str)),
-	    nifa->configured ? "configured" : "not configured");
+	return (straddr != NULL ? str : NULL);
 }
 
 void
@@ -214,169 +220,9 @@
 }
 
 void
-nwamd_dhcp_release(const char *ifname)
-{
-	dhcp_ipc_reply_t *reply = NULL;
-	dhcp_ipc_request_t *request;
-	int rc;
-
-	/* Now allocate and send the request */
-	request = dhcp_ipc_alloc_request(DHCP_RELEASE, ifname, NULL, 0,
-	    DHCP_TYPE_NONE);
-	if (request == NULL) {
-		nlog(LOG_DEBUG, "nwamd_dhcp_release: dhcp_ipc_alloc_request : "
-		    "%s", strerror(errno));
-		return;
-	}
-	rc = dhcp_ipc_make_request(request, &reply, 1);
-	free(request);
-	free(reply);
-	reply = NULL;
-	if (rc != 0) {
-		/* Fall back to drop request */
-		request = dhcp_ipc_alloc_request(DHCP_DROP, ifname, NULL, 0,
-		    DHCP_TYPE_NONE);
-		if (request == NULL) {
-			nlog(LOG_DEBUG, "nwamd_dhcp_release: "
-			    "dhcp_ipc_alloc_request : %s", strerror(errno));
-			return;
-		}
-		(void) dhcp_ipc_make_request(request, &reply, 1);
-		free(request);
-		free(reply);
-	}
-}
-
-static boolean_t
-add_ip_address(const char *ifname, struct nwamd_if_address *nifa,
-    boolean_t logical_if)
-{
-	icfg_handle_t h, newh;
-	icfg_if_t intf;
-	uint64_t flags;
-	int rc;
-	struct sockaddr_in bcastaddr;
-	char str[INET6_ADDRSTRLEN];
-
-	(void) strlcpy(intf.if_name, ifname, sizeof (intf.if_name));
-	intf.if_protocol = nifa->address.sa_family;
-
-	nlog(LOG_DEBUG, "add_ip_address: %s address %s for link %s",
-	    logical_if ? "adding" : "setting",
-	    nwamd_sockaddr_to_str(&nifa->address, str, sizeof (str)),
-	    intf.if_name);
-
-	if (icfg_open(&h, &intf) != ICFG_SUCCESS) {
-		nlog(LOG_ERR, "add_ip_address: icfg_open failed on %s", ifname);
-		return (B_FALSE);
-	}
-	/*
-	 * When working with the physical interface, we need to be careful
-	 * to set the prefixlen and broadcast addresses before setting the
-	 * IP address, otherwise RTM_DELADDRs for the old broadcast/netmask
-	 * will confuse us into thinking we've lost the address we've just
-	 * assigned.
-	 */
-	if (logical_if) {
-		rc = icfg_add_addr(h, &newh,
-		    (const struct sockaddr *)&nifa->address,
-		    intf.if_protocol == AF_INET ?
-		    sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6));
-	} else {
-		newh = h;
-
-		/* Make sure DHCP is no longer running */
-		if (icfg_get_flags(newh, &flags) == ICFG_SUCCESS) {
-			if (flags & IFF_DHCPRUNNING) {
-				nlog(LOG_DEBUG, "add_ip_address: "
-				    "turning off DHCP for %s", ifname);
-				nwamd_dhcp_release(ifname);
-			}
-		}
-		/*
-		 * Set interface IFF_UP if not already.  Do this and
-		 * setting of prefixlen/broadcast addresses as otherwise
-		 * these can trigger an RTM_DELADDR that makes it appear
-		 * that the address has gone away.
-		 */
-		rc = icfg_set_addr(newh,
-		    (const struct sockaddr *)&nifa->address,
-		    intf.if_protocol == AF_INET ?
-		    sizeof (struct sockaddr_in) :
-		    sizeof (struct sockaddr_in6));
-	}
-	if (rc != ICFG_SUCCESS) {
-		nlog(LOG_DEBUG, "add_ip_address: add of ipaddr failed "
-		    "for %s: %d", ifname, rc);
-		goto out;
-	}
-
-	if (nifa->prefix != 0) {
-		if ((rc = icfg_set_prefixlen(newh, nifa->prefix))
-		    != ICFG_SUCCESS) {
-			nlog(LOG_ERR, "add_ip_address: icfg_set_prefix %d "
-			    "failed on %s: %s", nifa->prefix, ifname,
-			    icfg_errmsg(rc));
-		} else if (intf.if_protocol == AF_INET) {
-			/* Set broadcast address based on address, prefixlen */
-			bcastaddr.sin_addr.s_addr =
-			/*LINTED*/
-			    ((struct sockaddr_in *)&nifa->address)
-			    ->sin_addr.s_addr |
-			    htonl(0xffffffff >> nifa->prefix);
-
-			if ((rc = icfg_set_broadcast(newh, &bcastaddr))
-			    != ICFG_SUCCESS) {
-				nlog(LOG_ERR, "add_ip_address: "
-				    "icfg_set_broadcast(%s) failed on %s: %s",
-				    inet_ntoa(bcastaddr.sin_addr), ifname,
-				    icfg_errmsg(rc));
-			}
-		}
-	}
-	if (rc == ICFG_SUCCESS) {
-		if (icfg_get_flags(newh, &flags) == ICFG_SUCCESS) {
-			if ((flags & IFF_UP) == 0)
-				rc = icfg_set_flags(newh, flags | IFF_UP);
-		} else {
-			nlog(LOG_DEBUG, "add_ip_address: couldn't bring up %s",
-			    ifname);
-		}
-	}
-
-out:
-	/* Check if address was a duplicate */
-	if (rc == ICFG_DAD_FOUND || (flags & IFF_DUPLICATE) != 0) {
-		char *object_name;
-		nwam_error_t err;
-
-		nlog(LOG_INFO, "add_ip_address: "
-		    "duplicate address detected on %s", ifname);
-		if ((err = nwam_ncu_name_to_typed_name(ifname,
-		    NWAM_NCU_TYPE_INTERFACE, &object_name)) == NWAM_SUCCESS) {
-			nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
-			    object_name, NWAM_STATE_MAINTENANCE,
-			    NWAM_AUX_STATE_IF_DUPLICATE_ADDR);
-			free(object_name);
-		} else {
-			nlog(LOG_ERR, "add_ip_address: could not "
-			    "create state event for %s: %s", ifname,
-			    nwam_strerror(err));
-		}
-		rc = ICFG_DAD_FOUND;
-	}
-
-	if (h != newh)
-		icfg_close(newh);
-	icfg_close(h);
-
-	return (rc == ICFG_SUCCESS);
-}
-
-void
 nwamd_add_default_routes(nwamd_ncu_t *ncu)
 {
-	nwamd_if_t *nif = &ncu->ncu_node.u_if;
+	nwamd_if_t *nif = &ncu->ncu_if;
 	char str[INET6_ADDRSTRLEN];
 
 	if (nif->nwamd_if_ipv4 && nif->nwamd_if_ipv4_default_route_set) {
@@ -389,8 +235,8 @@
 		v4mask.sin_family = AF_INET;
 
 		nlog(LOG_DEBUG, "nwamd_add_default_routes: adding default "
-		    "route %s", nwamd_sockaddr_to_str
-		    ((struct sockaddr *)&nif->nwamd_if_ipv4_default_route, str,
+		    "route %s", nwamd_sockaddr2str((struct sockaddr *)
+		    &nif->nwamd_if_ipv4_default_route, str,
 		    sizeof (str)));
 		nwamd_add_route((struct sockaddr *)&v4dest,
 		    (struct sockaddr *)&v4mask,
@@ -408,8 +254,8 @@
 		v6mask.sin6_family = AF_INET6;
 
 		nlog(LOG_DEBUG, "nwamd_add_default_routes: adding default "
-		    "route %s", nwamd_sockaddr_to_str
-		    ((struct sockaddr *)&nif->nwamd_if_ipv6_default_route, str,
+		    "route %s", nwamd_sockaddr2str((struct sockaddr *)
+		    &nif->nwamd_if_ipv6_default_route, str,
 		    sizeof (str)));
 		nwamd_add_route((struct sockaddr *)&v6dest,
 		    (struct sockaddr *)&v6mask,
@@ -418,154 +264,82 @@
 	}
 }
 
-void
-nwamd_dhcp_inform(nwamd_ncu_t *ncu)
-{
-	struct nwamd_dhcp_thread_arg *arg;
-	char *name = NULL;
-	pthread_attr_t attr;
-
-	arg = malloc(sizeof (*arg));
-	if (arg == NULL) {
-		nlog(LOG_ERR, "nwamd_dhcp_inform: error allocating memory "
-		    "for dhcp request");
-		free(name);
-		return;
-	}
-
-	arg->name = strdup(ncu->ncu_name);
-	arg->type = DHCP_INFORM;
-	arg->timeout = DHCP_IPC_WAIT_DEFAULT;
-
-	(void) pthread_attr_init(&attr);
-	(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-	if (pthread_create(NULL, &attr, start_dhcp_thread, arg) == -1) {
-		nlog(LOG_ERR, "Cannot start dhcp thread");
-		free(name);
-		free(arg);
-		(void) pthread_attr_destroy(&attr);
-		return;
-	}
-	(void) pthread_attr_destroy(&attr);
-}
-
-static boolean_t
-addresses_match(const struct sockaddr *addr1, const struct sockaddr *addr2)
-{
-	if (addr1->sa_family != addr2->sa_family)
-		return (B_FALSE);
-
-	switch (addr1->sa_family) {
-	case AF_INET:
-		/*LINTED*/
-		return (memcmp(&((struct sockaddr_in *)addr1)->sin_addr,
-		/*LINTED*/
-		    &((struct sockaddr_in *)addr2)->sin_addr,
-		    sizeof (struct in_addr)) == 0);
-	case AF_INET6:
-		/*LINTED*/
-		return (memcmp(&((struct sockaddr_in6 *)addr1)->sin6_addr,
-		/*LINTED*/
-		    &((struct sockaddr_in6 *)addr2)->sin6_addr,
-		    sizeof (struct in6_addr)) == 0);
-	default:
-		return (B_FALSE);
-	}
-}
-
 /*
  * Returns the nwamd_if_address structure for the given static address,
  * NULL if not found.
  */
 static struct nwamd_if_address *
-find_static_address(const struct sockaddr *addr, const nwamd_ncu_t *ncu)
+find_static_address(const struct sockaddr_storage *addr, const nwamd_ncu_t *ncu)
 {
-	struct nwamd_if_address *n, *nifa = ncu->ncu_node.u_if.nwamd_if_list;
+	struct nwamd_if_address *nifap, *nifa = ncu->ncu_if.nwamd_if_list;
+	struct sockaddr_storage saddr;
 	char str[INET6_ADDRSTRLEN];
 
-	nlog(LOG_DEBUG, "find_static_address %s",
-	    nwamd_sockaddr_to_str(addr, str, sizeof (str)));
-	for (n = nifa; n != NULL; n = n->next) {
-		if (addresses_match(addr, &n->address))
-			return (n);
+	nlog(LOG_DEBUG, "find_static_address: %s",
+	    nwamd_sockaddr2str((struct sockaddr *)addr, str, sizeof (str)));
+	for (nifap = nifa; nifap != NULL; nifap = nifap->next) {
+		if (nifap->ipaddr_atype != IPADM_ADDR_STATIC ||
+		    ipadm_get_addr(nifap->ipaddr, &saddr) != IPADM_SUCCESS)
+			continue;
+
+		if (sockaddrcmp(addr, &saddr))
+			return (nifap);
 	}
 	return (NULL);
 }
 
 /*
  * Returns the nwamd_if_address structure representing the non-static address
- * in the NCU.  dhcp is used to detemrine if the DHCP (stateful for v6)
- * structure is needed or the stateless/autoconf structure for the given
- * family.  dhcp should be B_TRUE if looking for v4.  Will only return the
- * nwamd_if_address if the relevant address is configured (v4 DHCP, v6
- * stateless/stateful) for the NCU.
- *
- * Returns NULL if structure is not found.
+ * in the NCU.  For IPv6, both stateless and stateful (DHCPv6) share the same
+ * nwamd_if_address.  Will only return the nwamd_if_address if the relevant
+ * address is configured (v4 DHCP, v6 either stateless or stateless) for the
+ * NCU.  Returns NULL if the structure is not found.
  */
 static struct nwamd_if_address *
-find_nonstatic_address(const nwamd_ncu_t *ncu, ushort_t family, boolean_t dhcp)
+find_nonstatic_address(const nwamd_ncu_t *ncu, sa_family_t family)
 {
-	struct nwamd_if_address *n, *nifa = ncu->ncu_node.u_if.nwamd_if_list;
-	const nwamd_if_t *u_if = &ncu->ncu_node.u_if;
+	struct nwamd_if_address *nifap, *nifa = ncu->ncu_if.nwamd_if_list;
+	const nwamd_if_t *u_if = &ncu->ncu_if;
 
-	nlog(LOG_DEBUG, "find_nonstatic_address: %s",
-	    dhcp ? "dhcp" : "stateless");
-	for (n = nifa; n != NULL; n = n->next) {
+	nlog(LOG_DEBUG, "find_nonstatic_address for %s %s",
+	    (family == AF_INET ? "IPv4" : "IPv6"),  ncu->ncu_name);
+	for (nifap = nifa; nifap != NULL; nifap = nifap->next) {
+		if (nifap->ipaddr_atype == IPADM_ADDR_STATIC)
+			continue;
+
 		if (family == AF_INET) {
-			if (!dhcp)
-				return (NULL);
-			if (n->address.sa_family == family && n->dhcp_if &&
-			    u_if->nwamd_if_dhcp_configured)
-				return (n);
+			if (nifap->ipaddr_atype == IPADM_ADDR_DHCP &&
+			    u_if->nwamd_if_dhcp_requested)
+				return (nifap);
 		} else if (family == AF_INET6) {
-			if (n->address.sa_family == family) {
-				if (dhcp && n->dhcp_if &&
-				    u_if->nwamd_if_stateful_configured)
-					return (n);
-				else if (!dhcp && n->stateless_if &&
-				    u_if->nwamd_if_stateless_configured)
-					return (n);
-			}
+			if (nifap->ipaddr_atype == IPADM_ADDR_IPV6_ADDRCONF &&
+			    (u_if->nwamd_if_stateful_requested ||
+			    u_if->nwamd_if_stateless_requested))
+				return (nifap);
 		}
 	}
 	return (NULL);
 }
 
 /*
- * Sets "configured" nwam_if_address value for corresponding address.
- * Used when we process IF_STATE events to handle RTM_NEWADDR/DELADDRs.
+ * Returns the nwamd_if_address structure that configured the given address,
+ * NULL if not found.
  */
-static boolean_t
-update_address_configured_value(const struct sockaddr *configured_addr,
-    nwamd_ncu_t *ncu, boolean_t configured)
+static struct nwamd_if_address *
+find_configured_address(const struct sockaddr_storage *addr,
+    const nwamd_ncu_t *ncu)
 {
-	struct nwamd_if_address *n;
+	struct nwamd_if_address *nifap, *nifa = ncu->ncu_if.nwamd_if_list;
 	char str[INET6_ADDRSTRLEN];
 
-	nlog(LOG_DEBUG, "update_address_configured_value(%s, %s, %s)",
-	    nwamd_sockaddr_to_str(configured_addr, str, sizeof (str)),
-	    ncu->ncu_name, configured ? "configure" : "unconfigure");
-	n = find_static_address(configured_addr, ncu);
-	if (n) {
-		n->configured = configured;
-		nlog(LOG_DEBUG, "update_address_configured_value: marking "
-		    "address %s",
-		    nwamd_sockaddr_to_str(&n->address, str, sizeof (str)));
-		return (B_TRUE);
+	nlog(LOG_DEBUG, "find_configured_address: %s",
+	    nwamd_sockaddr2str((struct sockaddr *)addr, str, sizeof (str)));
+	for (nifap = nifa; nifap != NULL; nifap = nifap->next) {
+		if (sockaddrcmp(addr, &nifap->conf_addr) ||
+		    sockaddrcmp(addr, &nifap->conf_stateless_addr))
+			return (nifap);
 	}
-	return (B_FALSE);
-}
-
-void
-nwamd_update_addresses_unconfigured(nwamd_ncu_t *ncu, sa_family_t af)
-{
-	struct nwamd_if_address *n, *nifa = ncu->ncu_node.u_if.nwamd_if_list;
-
-	for (n = nifa; n != NULL; n = n->next)
-		if (af == AF_UNSPEC || n->address.sa_family == af) {
-			n->configured = B_FALSE;
-			nwamd_log_if_address(LOG_DEBUG, n);
-		}
+	return (NULL);
 }
 
 /*
@@ -576,9 +350,11 @@
 {
 	struct nwamd_if_address *n;
 
-	for (n = ncu->ncu_node.u_if.nwamd_if_list; n != NULL; n = n->next) {
-		if ((family == AF_UNSPEC || family == n->address.sa_family) &&
-		    n->configured && !n->dhcp_if && !n->stateless_if)
+	for (n = ncu->ncu_if.nwamd_if_list; n != NULL; n = n->next) {
+		if (n->ipaddr_atype != IPADM_ADDR_STATIC)
+			continue;
+		if ((family == AF_UNSPEC || family == n->family) &&
+		    n->configured)
 			return (B_TRUE);
 	}
 	nlog(LOG_DEBUG, "no static addresses configured for %s", ncu->ncu_name);
@@ -595,36 +371,25 @@
 boolean_t
 nwamd_dhcp_managing(int protocol, nwamd_ncu_t *ncu)
 {
-	icfg_if_t *iflist;
-	icfg_handle_t ifh;
-	int numif, i;
-	struct sockaddr_storage addr;
-	socklen_t len;
-	int prefixlen;
+	struct sockaddr_storage *addr;
 	uint64_t flags;
 	boolean_t rv = B_FALSE;
-
-	if (icfg_get_if_list(&iflist, &numif, protocol, ICFG_PLUMBED) !=
-	    ICFG_SUCCESS) {
-		return (B_TRUE);
-	}
-	for (i = 0; i < numif; i++) {
-		if (strncmp(iflist[i].if_name, ncu->ncu_name,
-		    strlen(ncu->ncu_name)) != 0)
-				continue;
+	ipadm_addr_info_t *addrinfo, *a;
+	ipadm_status_t ipstatus;
 
-		if (icfg_open(&ifh, &iflist[i]) != ICFG_SUCCESS)
-			continue;
+	if ((ipstatus = ipadm_addr_info(ipadm_handle, ncu->ncu_name, &addrinfo,
+	    0, 0)) != IPADM_SUCCESS) {
+		nlog(LOG_ERR, "nwamd_dhcp_managing: "
+		    "ipadm_addr_info failed for %s: %s",
+		    ncu->ncu_name, ipadm_status2str(ipstatus));
+		return (B_FALSE);
+	}
 
+	for (a = addrinfo; a != NULL; a = IA_NEXT(a)) {
 		/* is this address an expected static one? */
-		len = sizeof (addr);
-		if (icfg_get_addr(ifh, (struct sockaddr *)&addr, &len,
-		    &prefixlen, B_FALSE) != ICFG_SUCCESS ||
-		    find_static_address((struct sockaddr *)&addr, ncu)
-		    != NULL) {
-			icfg_close(ifh);
+		addr = a->ia_ifa.ifa_addr;
+		if (find_static_address(addr, ncu) != NULL)
 			continue;
-		}
 
 		/*
 		 * For IPv4, DHCPRUNNING flag is set when dhcpagent is in
@@ -635,31 +400,32 @@
 		 * as not being managed by DHCP and skip checking of flags.
 		 */
 		if ((protocol == AF_INET &&
-		    ((struct sockaddr_in *)&addr)->sin_addr.s_addr ==
+		    ((struct sockaddr_in *)addr)->sin_addr.s_addr ==
 		    INADDR_ANY) ||
 		    (protocol == AF_INET6 &&
 		    IN6_IS_ADDR_LINKLOCAL(
-		    &((struct sockaddr_in6 *)&addr)->sin6_addr))) {
-			icfg_close(ifh);
+		    &((struct sockaddr_in6 *)addr)->sin6_addr))) {
 			continue;
 		}
 
-		if (icfg_get_flags(ifh, &flags) == ICFG_SUCCESS &&
-		    (flags & IFF_DHCPRUNNING)) {
+		flags = a->ia_ifa.ifa_flags;
+		if (flags & IFF_DHCPRUNNING) {
 			/*
 			 * If we get here we have an address that has the
 			 * DHCP flag set and isn't an expected static address.
 			 */
-			icfg_close(ifh);
 			rv = B_TRUE;
 			break;
 		}
 	}
 
-	icfg_free_if_list(iflist);
+	ipadm_free_addr_info(addrinfo);
 	return (rv);
 }
 
+/*
+ * Return B_TRUE if IPv4 is requested in the given NCU.
+ */
 static boolean_t
 nwamd_v4_requested(nwamd_ncu_t *ncu)
 {
@@ -667,22 +433,27 @@
 	nwamd_if_t *u_if;
 
 	anyv4_requested = B_FALSE;
-	u_if = &ncu->ncu_node.u_if;
+	u_if = &ncu->ncu_if;
 	if (u_if->nwamd_if_dhcp_requested) {
 		anyv4_requested = B_TRUE;
 	} else {
-		struct nwamd_if_address *a;
-		for (a = u_if->nwamd_if_list;
-		    a != NULL && a->address.sa_family != AF_INET;
-		    a = a->next)
-			/* Empty loop body */;
-		if (a != NULL)
+		struct nwamd_if_address *n;
+
+		for (n = u_if->nwamd_if_list; n != NULL; n = n->next) {
+			if (n->family == AF_INET &&
+			    n->ipaddr_atype == IPADM_ADDR_STATIC)
+				break;
+		}
+		if (n != NULL)
 			anyv4_requested = B_TRUE;
 	}
 
 	return (anyv4_requested);
 }
 
+/*
+ * Returns B_TRUE if IPv6 is requested in the given NCU.
+ */
 static boolean_t
 nwamd_v6_requested(nwamd_ncu_t *ncu)
 {
@@ -690,17 +461,19 @@
 	nwamd_if_t *u_if;
 
 	anyv6_requested = B_FALSE;
-	u_if = &ncu->ncu_node.u_if;
+	u_if = &ncu->ncu_if;
 	if (u_if->nwamd_if_stateful_requested ||
 	    u_if->nwamd_if_stateless_requested) {
 		anyv6_requested = B_TRUE;
 	} else {
-		struct nwamd_if_address *a;
-		for (a = u_if->nwamd_if_list;
-		    a != NULL && a->address.sa_family != AF_INET6;
-		    a = a->next)
-			/* Empty loop body */;
-		if (a != NULL)
+		struct nwamd_if_address *n;
+
+		for (n = u_if->nwamd_if_list; n != NULL; n = n->next) {
+			if (n->family == AF_INET6 &&
+			    n->ipaddr_atype == IPADM_ADDR_STATIC)
+				break;
+		}
+		if (n != NULL)
 			anyv6_requested = B_TRUE;
 	}
 
@@ -771,171 +544,229 @@
 	interface_ncu_up_down(ncu, B_FALSE);
 }
 
-/* Callback to find if DHCP is running on the interface index */
-static int
-flags_set_for_ifindex_cb(icfg_if_t *intf, void *arg, uint64_t flags_wanted)
+static boolean_t
+stateless_running(const nwamd_ncu_t *ncu)
 {
-	int *indexp = arg;
-	icfg_handle_t h;
-	int index;
-	uint64_t flags = 0;
+	ipadm_addr_info_t *ainfo, *ainfop;
+	ipadm_status_t ipstatus;
+	boolean_t rv = B_FALSE;
+	uint64_t flags;
 
-	if (icfg_open(&h, intf) != ICFG_SUCCESS) {
-		nlog(LOG_ERR, "flags_set_for_ifindex_cb: icfg_open failed");
-		return (0);
-	}
-	if (icfg_get_index(h, &index) != ICFG_SUCCESS) {
-		nlog(LOG_ERR,
-		    "flags_set_for_ifindex_cb: icfg_get_index failed");
-		icfg_close(h);
-		return (0);
-	}
-	if (index != *indexp) {
-		icfg_close(h);
-		return (0);
+	if ((ipstatus = ipadm_addr_info(ipadm_handle, ncu->ncu_name, &ainfo,
+	    0, 0)) != IPADM_SUCCESS) {
+		nlog(LOG_ERR, "stateless_running: "
+		    "ipadm_addr_info failed for %s: %s",
+		    ncu->ncu_name, ipadm_status2str(ipstatus));
+		return (B_FALSE);
 	}
 
-	if (icfg_get_flags(h, &flags) != ICFG_SUCCESS) {
-		nlog(LOG_ERR,
-		    "flags_set_for_ifindex_cb: icfg_get_flags failed");
+	for (ainfop = ainfo; ainfop != NULL; ainfop = IA_NEXT(ainfop)) {
+		if (ainfop->ia_ifa.ifa_addr->ss_family != AF_INET6)
+			continue;
+		flags = ainfop->ia_ifa.ifa_flags;
+		if (flags & STATELESS_RUNNING) {
+			rv = B_TRUE;
+			break;
+		}
 	}
-	icfg_close(h);
-	return ((flags & flags_wanted) == flags_wanted);
+	ipadm_free_addr_info(ainfo);
+	return (rv);
 }
 
-static int
-stateless_running_for_ifindex_cb(icfg_if_t *intf, void *arg)
+/*
+ * Returns the addrinfo associated with the given address.  There is always
+ * only one addrinfo for each address.
+ */
+static boolean_t
+addrinfo_for_addr(const struct sockaddr_storage *caddr, const char *ifname,
+    ipadm_addr_info_t **ainfo)
 {
-	return (flags_set_for_ifindex_cb(intf, arg,
-	    IFF_RUNNING | IFF_ADDRCONF | IFF_UP));
+	ipadm_addr_info_t *addrinfo, *ainfop, *last = NULL;
+	ipadm_status_t ipstatus;
+
+	ipstatus = ipadm_addr_info(ipadm_handle, ifname, &addrinfo, 0, 0);
+	if (ipstatus != IPADM_SUCCESS) {
+		nlog(LOG_INFO, "addrinfo_for_addr: "
+		    "ipadm_addr_info failed for %s: %s",
+		    ifname, ipadm_status2str(ipstatus));
+		return (B_FALSE);
+	}
+
+	*ainfo = NULL;
+	for (ainfop = addrinfo; ainfop != NULL; ainfop = IA_NEXT(ainfop)) {
+		/*
+		 * If addresses match, rearrange pointers so that addrinfo
+		 * does not contain a, and return a.
+		 */
+		if (sockaddrcmp(ainfop->ia_ifa.ifa_addr, caddr)) {
+			if (last != NULL)
+				last->ia_ifa.ifa_next = ainfop->ia_ifa.ifa_next;
+			else
+				addrinfo = IA_NEXT(ainfop);
+
+			ainfop->ia_ifa.ifa_next = NULL;
+			*ainfo = ainfop;
+			break;
+		}
+		last = ainfop;
+	}
+	ipadm_free_addr_info(addrinfo);
+	return (*ainfo == NULL ? B_FALSE : B_TRUE);
 }
 
 /*
- * Is autoconf running on the interface with specified ifindex?
+ * Returns B_TRUE if the addrinfo associated with the given ipaddr using its
+ * aobjname is found.  An addrinfo list is created and returned in ainfo.
+ * Stateless and stateful IPv6 addrinfo have the same aobjname, thus the need
+ * to create a list of addrinfo.
  */
 static boolean_t
-stateless_running_for_ifindex(int ifindex)
-{
-	return (icfg_iterate_if(AF_INET6, ICFG_PLUMBED, &ifindex,
-	    stateless_running_for_ifindex_cb) != 0);
-}
-
-static boolean_t
-stateless_running(const nwamd_ncu_t *ncu)
+addrinfo_for_ipaddr(ipadm_addrobj_t ipaddr, const char *ifname,
+    ipadm_addr_info_t **ainfo)
 {
-	int index;
-	icfg_if_t intf;
-	icfg_handle_t ifh;
+	char aobjname[IPADM_AOBJSIZ];
+	ipadm_addr_info_t *addrinfo, *ainfop;
+	ipadm_addr_info_t *last = NULL;
+	ipadm_status_t ipstatus;
 
-	intf.if_protocol = AF_INET6;
-	(void) strlcpy(intf.if_name, ncu->ncu_name, sizeof (intf.if_name));
-	if (icfg_open(&ifh, &intf) != ICFG_SUCCESS) {
-		nlog(LOG_ERR, "stateless_running: icfg_open(%s) failed",
-		    ncu->ncu_name);
+	ipstatus = ipadm_get_aobjname(ipaddr, aobjname, sizeof (aobjname));
+	if (ipstatus != IPADM_SUCCESS)
+		return (B_FALSE);
+
+	ipstatus = ipadm_addr_info(ipadm_handle, ifname, &addrinfo, 0, 0);
+	if (ipstatus != IPADM_SUCCESS) {
+		nlog(LOG_INFO, "addrinfo_for_ipaddr: "
+		    "ipadm_addr_info failed for %s: %s",
+		    ifname, ipadm_status2str(ipstatus));
 		return (B_FALSE);
 	}
 
-	if (icfg_get_index(ifh, &index) != ICFG_SUCCESS) {
-		nlog(LOG_ERR, "stateless_running: icfg_get_index(%s) failed",
-		    ncu->ncu_name);
-		return (B_FALSE);
+	*ainfo = NULL;
+	ainfop = addrinfo;
+	while (ainfop != NULL) {
+		/* If aobjnames match, rearrange pointers to create new list */
+		if (strcmp(ainfop->ia_aobjname, aobjname) == 0) {
+			ipadm_addr_info_t *match = ainfop;
+
+			ainfop = IA_NEXT(ainfop); /* move iterator */
+			if (last != NULL)
+				last->ia_ifa.ifa_next = match->ia_ifa.ifa_next;
+			else
+				addrinfo = ainfop;
+			if (*ainfo == NULL)
+				match->ia_ifa.ifa_next = NULL;
+			else
+				match->ia_ifa.ifa_next = &(*ainfo)->ia_ifa;
+			*ainfo = match;
+		} else {
+			last = ainfop;
+			ainfop = IA_NEXT(ainfop);
+		}
+	}
+	ipadm_free_addr_info(addrinfo);
+	return (*ainfo == NULL ? B_FALSE : B_TRUE);
+}
+
+/*
+ * Add the address provided in the nwamd_if_address.  If DHCP is required,
+ * start DHCP.  If a static address is configured, create the address; then do
+ * a DHCP_INFORM (in a separate thread) to get other networking configuration
+ * parameters.  RTM_NEWADDRs - translated into IF_STATE events - will then
+ * finish the job of bringing the NCU online.
+ */
+static boolean_t
+add_ip_address(const char *ifname, const struct nwamd_if_address *nifa)
+{
+	ipadm_status_t ipstatus;
+	ipadm_addr_info_t *addrinfo = NULL;
+	uint64_t flags;
+
+	if (nifa->ipaddr_atype == IPADM_ADDR_DHCP) {
+		/*
+		 * To make getting a DHCP address asynchronous, call
+		 * ipadm_create_addr() in a new thread.
+		 */
+		nlog(LOG_DEBUG, "add_ip_address: "
+		    "adding IPv4 DHCP address on %s", ifname);
+		nwamd_dhcp(ifname, nifa->ipaddr, DHCP_START);
+	} else {
+		nlog(LOG_DEBUG, "add_ip_address: adding %s address on %s",
+		    (nifa->ipaddr_atype == IPADM_ADDR_STATIC ?
+		    "STATIC" : "IPv6 ADDRCONF"), ifname);
+		if ((ipstatus = ipadm_create_addr(ipadm_handle, nifa->ipaddr,
+		    IPADM_OPT_ACTIVE | IPADM_OPT_UP)) != IPADM_SUCCESS) {
+			nlog(LOG_ERR, "add_ip_address: "
+			    "ipadm_create_addr failed on %s: %s",
+			    ifname, ipadm_status2str(ipstatus));
+			return (B_FALSE);
+		}
+		/*
+		 * When creating a static address, ipadm_create_addr() returns
+		 * SUCCESS even if duplicate address is detected.  Retrieve
+		 * the addrinfo to get the flags.
+		 */
+		if (nifa->ipaddr_atype == IPADM_ADDR_STATIC) {
+			/*
+			 * Since we are configuring a static address, there
+			 * will be just *ONE* addrinfo with the aobjname in
+			 * nifa->ipaddr.
+			 */
+			if (!addrinfo_for_ipaddr(nifa->ipaddr, ifname,
+			    &addrinfo)) {
+				nlog(LOG_ERR, "add_ip_address: "
+				    "could not find addrinfo on %s", ifname);
+				return (B_FALSE);
+			}
+
+			flags = addrinfo->ia_ifa.ifa_flags;
+			ipadm_free_addr_info(addrinfo);
+			if (flags & IFF_DUPLICATE) {
+				char *object_name;
+				nwam_error_t err;
+
+				nlog(LOG_INFO, "add_ip_address: "
+				    "duplicate address detected on %s", ifname);
+				if ((err = nwam_ncu_name_to_typed_name(ifname,
+				    NWAM_NCU_TYPE_INTERFACE, &object_name))
+				    == NWAM_SUCCESS) {
+					nwamd_object_set_state(
+					    NWAM_OBJECT_TYPE_NCU,
+					    object_name, NWAM_STATE_MAINTENANCE,
+					    NWAM_AUX_STATE_IF_DUPLICATE_ADDR);
+					free(object_name);
+				} else {
+					nlog(LOG_ERR, "add_ip_address: "
+					    "could not create state event "
+					    "for %s: %s",
+					    ifname, nwam_strerror(err));
+				}
+				return (B_FALSE);
+			}
+			/* Do DHCP_INFORM using async ipadm_refresh_addr() */
+			nwamd_dhcp(ifname, nifa->ipaddr, DHCP_INFORM);
+		}
 	}
 
-	icfg_close(ifh);
-
-	return (stateless_running_for_ifindex(index));
+	return (B_TRUE);
 }
 
+/*
+ * Adds addresses for the given NCU.
+ */
 void
 nwamd_configure_interface_addresses(nwamd_ncu_t *ncu)
 {
-	struct nwamd_if_address *nifa = ncu->ncu_node.u_if.nwamd_if_list;
-	struct nwamd_if_address *n;
-	int num_configured_v4 = 0;
-	boolean_t add_logical_if;
+	struct nwamd_if_address *nifap, *nifa = ncu->ncu_if.nwamd_if_list;
 
 	nlog(LOG_DEBUG, "nwamd_configure_interface_addresses(%s)",
 	    ncu->ncu_name);
 
-	/*
-	 * Add static addresses.  For IPv4, we only use the physical interface
-	 * (i.e. not a logical interface) if DHCP has not been requested and
-	 * this is the first address to be configured.
-	 */
-	for (n = nifa; n != NULL; n = n->next) {
-		if (n->configured || n->dhcp_if || n->stateless_if)
+	for (nifap = nifa; nifap != NULL; nifap = nifap->next) {
+		if (nifap->configured)
 			continue;
-		switch (n->address.sa_family) {
-		case AF_INET:
-			add_logical_if = (num_configured_v4 > 0 ||
-			    ncu->ncu_node.u_if.nwamd_if_dhcp_requested);
-			num_configured_v4++;
-			break;
-		case AF_INET6:
-			add_logical_if = B_TRUE;
-			break;
-		}
-		n->configured = add_ip_address(ncu->ncu_name, n,
-		    add_logical_if);
-	}
-}
-
-static int
-lifnum_from_ifname(const char *ifname)
-{
-	char *lifstr = strchr(ifname, ':');
-
-	if (lifstr != NULL) {
-		lifstr++;
-		return (atoi(lifstr));
-	}
-	return (0);
-}
 
-/*
- * Copies the ifname (with lifnum) associated with the given address.
- * Returns B_TRUE if a match is found, B_FASLE otherwise.
- */
-static boolean_t
-ifname_for_addr(const struct sockaddr *caddr, char *ifname, int len)
-{
-	struct sockaddr_in6 addr;
-	int numif, i, prefixlen;
-	icfg_if_t *iflist;
-	icfg_handle_t ifh;
-	socklen_t slen;
-
-	if (icfg_get_if_list(&iflist, &numif, caddr->sa_family, ICFG_PLUMBED)
-	    != ICFG_SUCCESS) {
-		nlog(LOG_DEBUG, "ifname_for_addr: icfg_get_if_list failed");
-		return (B_FALSE);
+		nifap->configured = add_ip_address(ncu->ncu_name, nifap);
 	}
-
-	for (i = 0; i < numif; i++) {
-		if (icfg_open(&ifh, &iflist[i]) != ICFG_SUCCESS) {
-			nlog(LOG_ERR, "ifname_for_addr: icfg_open %s failed",
-			    iflist[i].if_name);
-			continue;
-		}
-
-		slen = sizeof (addr);
-		if (icfg_get_addr(ifh, (struct sockaddr *)&addr,
-		    &slen, &prefixlen, B_FALSE) != ICFG_SUCCESS) {
-			nlog(LOG_ERR, "ifname_for_addr: "
-			    "icfg_get_addr %s failed", iflist[i].if_name);
-		} else {
-			/* Compare addresses */
-			if (addresses_match((struct sockaddr *)&addr, caddr)) {
-				(void) strlcpy(ifname, iflist[i].if_name, len);
-				icfg_close(ifh);
-				icfg_free_if_list(iflist);
-				return (B_TRUE);
-			}
-		}
-		icfg_close(ifh);
-	}
-	icfg_free_if_list(iflist);
-	return (B_FALSE);
 }
 
 /*
@@ -1001,95 +832,144 @@
 
 	if (evm->nwe_data.nwe_if_state.nwe_addr_valid) {
 		struct nwam_event_if_state *if_state;
-		boolean_t stateless_running;
-		char addrstr[INET6_ADDRSTRLEN], ifname[LIFNAMSIZ];
-		boolean_t v4dhcp_running;
-		boolean_t v6dhcp_running;
-		struct nwamd_if_address *nifa;
-		struct sockaddr *addr;
-		boolean_t static_addr;
-		icfg_if_t intf;
-		icfg_handle_t ifh;
+		char addrstr[INET6_ADDRSTRLEN];
+		boolean_t static_addr, addr_added;
+		boolean_t v4dhcp_running, v6dhcp_running, stateless_running;
+		ipadm_addr_info_t *ai = NULL, *addrinfo = NULL;
+		boolean_t stateless_ai_found = B_FALSE;
+		boolean_t stateful_ai_found = B_FALSE;
+		struct nwamd_if_address *nifa = NULL;
 		nwamd_if_t *u_if;
+		struct sockaddr_storage *addr, *ai_addr = 0;
 		ushort_t family;
 		uint64_t flags = 0;
-		int lifnum;
 
 		if_state = &evm->nwe_data.nwe_if_state;
-		u_if = &ncu->ncu_node.u_if;
+		u_if = &ncu->ncu_if;
 		family = if_state->nwe_addr.ss_family;
-		addr = (struct sockaddr *)&if_state->nwe_addr;
+		addr = &if_state->nwe_addr;
+		addr_added = if_state->nwe_addr_added;
 
 		nlog(LOG_DEBUG,
 		    "nwamd_ncu_handle_if_state_event: addr %s %s",
-		    nwamd_sockaddr_to_str(addr, addrstr, sizeof (addrstr)),
-		    evm->nwe_data.nwe_if_state.nwe_addr_added ?
-		    "added" : "removed");
+		    nwamd_sockaddr2str((struct sockaddr *)addr, addrstr,
+		    sizeof (addrstr)), addr_added ? "added" : "removed");
 
-		/* determine the interface name with lifnum */
-		if (if_state->nwe_addr_added) {
-			/* figure out the ifname for the address */
-			if (!ifname_for_addr(addr, ifname, sizeof (ifname))) {
+		/*
+		 * Need to get flags for this interface.  Get the addrinfo for
+		 * the address that generated this IF_STATE event.
+		 */
+		if (addr_added) {
+			/*
+			 * Address was added.  Find the addrinfo for this
+			 * address and the nwamd_if_address corresponding to
+			 * this address.
+			 */
+			if (!addrinfo_for_addr(addr, ncu->ncu_name, &ai)) {
 				nlog(LOG_ERR,
-				    "nwamd_ncu_handle_if_state_event:"
-				    "could not find ifname for %s", addrstr);
+				    "nwamd_ncu_handle_if_state_event: "
+				    "addrinfo doesn't exist for %s", addrstr);
 				nwamd_event_do_not_send(event);
-				goto exit;
+				goto valid_done;
 			}
-		} else {
+			addrinfo = ai;
+			flags = addrinfo->ia_ifa.ifa_flags;
+			ai_addr = addrinfo->ia_ifa.ifa_addr;
+
+			if (addrinfo->ia_atype == IPADM_ADDR_IPV6_ADDRCONF ||
+			    addrinfo->ia_atype == IPADM_ADDR_DHCP)
+				nifa = find_nonstatic_address(ncu, family);
+			else if (addrinfo->ia_atype == IPADM_ADDR_STATIC)
+				nifa = find_static_address(addr, ncu);
+
 			/*
-			 * Figure out the ifname that had the address that was
-			 * removed.  The address is already gone from the
-			 * interface, so cannot walk the interface list.
+			 * If nwamd_if_address is not found, then this address
+			 * isn't one that nwamd created.  Remove it.
 			 */
-			struct nwamd_if_address *n;
-
-			if ((n = find_static_address(addr, ncu)) == NULL &&
-			    (n = find_nonstatic_address(ncu, family, B_TRUE))
-			    == NULL &&
-			    (n = find_nonstatic_address(ncu, family, B_FALSE))
-			    == NULL) {
+			if (nifa == NULL) {
 				nlog(LOG_ERR,
 				    "nwamd_ncu_handle_if_state_event: "
-				    "could not find nwamd_if_address for %s",
-				    addrstr);
+				    "address %s not managed by nwam added, "
+				    "removing it", addrstr);
+				nwamd_down_interface(addrinfo->ia_aobjname,
+				    addrinfo->ia_atype, ncu->ncu_name);
 				nwamd_event_do_not_send(event);
-				goto exit;
+				goto valid_done;
 			}
-			(void) strlcpy(ifname, n->ifname, sizeof (ifname));
-		}
+
+			/* check flags to determine how intf is configured */
+			stateless_running = (family == AF_INET6) &&
+			    ((flags & STATELESS_RUNNING) == STATELESS_RUNNING);
+			v4dhcp_running = (family == AF_INET) &&
+			    ((flags & DHCP_RUNNING) == DHCP_RUNNING);
+			v6dhcp_running = (family == AF_INET6) &&
+			    ((flags & DHCP_RUNNING) == DHCP_RUNNING);
+			static_addr = (addrinfo->ia_atype == IPADM_ADDR_STATIC);
 
-		nlog(LOG_DEBUG, "nwamd_ncu_handle_if_state_event: "
-		    "ifname for %s is %s", addrstr, ifname);
+			/* copy the configured address into nwamd_if_address */
+			if (stateless_running) {
+				(void) memcpy(&nifa->conf_stateless_addr,
+				    addrinfo->ia_ifa.ifa_addr,
+				    sizeof (struct sockaddr_storage));
+			} else {
+				(void) memcpy(&nifa->conf_addr,
+				    addrinfo->ia_ifa.ifa_addr,
+				    sizeof (struct sockaddr_storage));
+			}
 
-		/*
-		 * Get interface flags using nwe_ifname as it is logical
-		 * interface name.
-		 */
-		intf.if_protocol = family;
-		(void) strlcpy(intf.if_name, ifname, sizeof (intf.if_name));
-		lifnum = lifnum_from_ifname(intf.if_name);
+		} else {
+			/*
+			 * Address was removed.  Find the nwamd_if_address
+			 * that configured this address.
+			 */
+			nifa = find_configured_address(addr, ncu);
+			if (nifa == NULL) {
+				nlog(LOG_ERR,
+				    "nwamd_ncu_handle_if_state_event: "
+				    "address %s not managed by nwam removed, "
+				    "nothing to do", addrstr);
+				nwamd_event_do_not_send(event);
+				goto valid_done;
+			}
 
-		if (icfg_open(&ifh, &intf) != ICFG_SUCCESS) {
-			nlog(LOG_ERR, "nwamd_ncu_handle_if_state_event: can't "
-			    "find if %s", intf.if_name);
-			nwamd_event_do_not_send(event);
-			goto exit;
-		}
-		if (icfg_get_flags(ifh, &flags) != ICFG_SUCCESS) {
-			nlog(LOG_INFO, "nwamd_ncu_handle_if_state_event: can't "
-			    "get flags for %s", icfg_if_name(ifh));
-			/*
-			 * If the interface is unplumbed, icfg_get_flags()
-			 * will fail.  Don't exit, continue with empty flags.
-			 */
-			if (if_state->nwe_addr_added) {
-				icfg_close(ifh);
-				goto exit;
+			if (addrinfo_for_ipaddr(nifa->ipaddr, ncu->ncu_name,
+			    &ai)) {
+				ipadm_addr_info_t *a;
+				for (a = ai; a != NULL; a = IA_NEXT(a)) {
+					/*
+					 * Since multiple addrinfo can have
+					 * the same ipaddr, find the one for
+					 * the address that generated this
+					 * state event.
+					 */
+					if (sockaddrcmp(addr,
+					    a->ia_ifa.ifa_addr)) {
+						flags = a->ia_ifa.ifa_flags;
+						ai_addr = a->ia_ifa.ifa_addr;
+						addrinfo = a;
+					}
+					/*
+					 * Stateful and stateless IPv6
+					 * addrinfo have the same aobjname.
+					 * Use the flags to determine which
+					 * address is present in the system.
+					 */
+					if (family == AF_INET6) {
+						stateless_ai_found =
+						    (a->ia_ifa.ifa_flags &
+						    STATELESS_RUNNING);
+						stateful_ai_found =
+						    (a->ia_ifa.ifa_flags &
+						    DHCP_RUNNING);
+					}
+				}
 			}
 		}
 
-		if (family == AF_INET && !if_state->nwe_addr_added) {
+		/* Set the flags in the event for listeners */
+		evm->nwe_data.nwe_if_state.nwe_flags = flags;
+
+		if (family == AF_INET && !addr_added) {
 			/*
 			 * Check for failure due to CR 6745448: if we get a
 			 * report that an address has been deleted, then check
@@ -1100,68 +980,64 @@
 			 * (which aren't smart enough to avoid dead
 			 * interfaces).
 			 */
-			/*LINTED*/
 			if (((struct sockaddr_in *)addr)->sin_addr.s_addr
-			    == INADDR_ANY) {
-				socklen_t slen;
-				struct sockaddr_in s;
-				int pfxlen;
+			    == INADDR_ANY && ai_addr != 0) {
+				struct sockaddr_in *a;
+				char astr[INET6_ADDRSTRLEN];
+				a = (struct sockaddr_in *)ai_addr;
 
 				if ((flags & IFF_UP) &&
 				    !(flags & IFF_RUNNING) &&
-				    icfg_get_addr(ifh, (struct sockaddr *)&s,
-				    &slen, &pfxlen, B_FALSE) == ICFG_SUCCESS &&
-				    s.sin_addr.s_addr != INADDR_ANY) {
-					nlog(LOG_DEBUG, "bug workaround: "
-					    "clear out addr %s on %s",
-					    inet_ntoa(s.sin_addr), ifname);
-					s.sin_addr.s_addr = INADDR_ANY;
-					(void) icfg_set_addr(ifh,
-					    (const struct sockaddr *)&s, slen);
+				    a->sin_addr.s_addr != INADDR_ANY) {
+					nlog(LOG_DEBUG,
+					    "nwamd_ncu_handle_if_state_event: "
+					    "bug workaround: clear out addr "
+					    "%s on %s", nwamd_sockaddr2str
+					    ((struct sockaddr *)a, astr,
+					    sizeof (astr)),
+					    ncu->ncu_name);
+					nwamd_down_interface(
+					    addrinfo->ia_aobjname,
+					    IPADM_ADDR_DHCP, ncu->ncu_name);
 				}
-				icfg_close(ifh);
-				goto exit;
+				goto valid_done;
 			}
 		}
 
 		/*
-		 * Has address really been removed? Sometimes spurious
+		 * If we received an RTM_NEWADDR and the IFF_UP flags has not
+		 * been set, ignore this IF_STATE event.  Once the IFF_UP flag
+		 * is set, we'll get another RTM_NEWADDR message.
+		 */
+		if (addr_added & !(flags & IFF_UP)) {
+			nlog(LOG_INFO, "nwamd_ncu_handle_if_state_event: "
+			    "address %s added on %s without IFF_UP flag (%x), "
+			    "ignoring IF_STATE event",
+			    addrstr, ncu->ncu_name, flags);
+			nwamd_event_do_not_send(event);
+			goto valid_done;
+		}
+
+		/*
+		 * Has the address really been removed?  Sometimes spurious
 		 * RTM_DELADDRs are generated, so we need to ensure that
 		 * the address is really gone.  If IFF_DUPLICATE is set,
 		 * we're getting the RTM_DELADDR due to DAD, so don't test
 		 * in that case.
 		 */
-		if (!if_state->nwe_addr_added && !(flags & IFF_DUPLICATE)) {
-			struct sockaddr_storage ifaddr;
-			socklen_t len;
-			int plen;
-
-			len = family == AF_INET ? sizeof (struct sockaddr_in) :
-			    sizeof (struct sockaddr_in6);
-			if (icfg_get_addr(ifh, (struct sockaddr *)&ifaddr, &len,
-			    &plen, B_FALSE) == ICFG_SUCCESS &&
-			    addresses_match(addr, (struct sockaddr *)&ifaddr)) {
-				nlog(LOG_DEBUG,
+		if (!addr_added && !(flags & IFF_DUPLICATE)) {
+			if (ai_addr != 0 && sockaddrcmp(addr, ai_addr)) {
+				nlog(LOG_INFO,
 				    "nwamd_ncu_handle_if_state_event: "
 				    "address %s is not really gone from %s, "
 				    "ignoring IF_STATE event",
-				    addrstr, intf.if_name);
-				icfg_close(ifh);
+				    addrstr, ncu->ncu_name);
 				nwamd_event_do_not_send(event);
-				goto exit;
+				goto valid_done;
 			}
 		}
-		icfg_close(ifh);
 
-		stateless_running = (family == AF_INET6) &&
-		    ((flags & STATELESS_RUNNING) == STATELESS_RUNNING);
-		v4dhcp_running = (family == AF_INET) &&
-		    ((flags & DHCP_RUNNING) == DHCP_RUNNING);
-		v6dhcp_running = (family == AF_INET6) &&
-		    ((flags & DHCP_RUNNING) == DHCP_RUNNING);
-		static_addr = (find_static_address(addr, ncu) != NULL);
-
-		if (if_state->nwe_addr_added) {
+		if (addr_added) {
 			/*
 			 * Address has been added.
 			 *
@@ -1170,63 +1046,27 @@
 			 * address but by the time we got here we don't really
 			 * want it and need to remove it.
 			 *
-			 * [Note that since we use DHCP inform on interfaces
-			 * with static addresses that they will also have the
-			 * DHCP flag set on the interface.]
-			 *
 			 * Once we decide we want the address adjust the ncu
 			 * state accordingly.  For example if this address is
 			 * enough move online.
 			 */
-
-			/* Figure out if we want to keep this address. */
-			if (static_addr) {
-				nifa = find_static_address(addr, ncu);
-				assert(nifa != NULL);
-				nifa->configured = B_TRUE;
-				(void) strlcpy(nifa->ifname, ifname,
-				    sizeof (nifa->ifname));
-			} else if (u_if->nwamd_if_dhcp_requested &&
-			    v4dhcp_running) {
+			if (u_if->nwamd_if_dhcp_requested && v4dhcp_running) {
 				u_if->nwamd_if_dhcp_configured = B_TRUE;
-				nifa = find_nonstatic_address(ncu, family,
-				    B_TRUE);
-				assert(nifa != NULL);
-				(void) strlcpy(nifa->ifname, ifname,
-				    sizeof (nifa->ifname));
 			} else if (u_if->nwamd_if_stateful_requested &&
 			    v6dhcp_running) {
 				u_if->nwamd_if_stateful_configured = B_TRUE;
-				nifa = find_nonstatic_address(ncu, family,
-				    B_TRUE);
-				assert(nifa != NULL);
-				(void) strlcpy(nifa->ifname, ifname,
-				    sizeof (nifa->ifname));
 			} else if (u_if->nwamd_if_stateless_requested &&
 			    stateless_running) {
 				u_if->nwamd_if_stateless_configured = B_TRUE;
-				nifa = find_nonstatic_address(ncu, family,
-				    B_FALSE);
-				assert(nifa != NULL);
-				(void) strlcpy(nifa->ifname, ifname,
-				    sizeof (nifa->ifname));
-			} else {
+			} else if (!static_addr) {
 				/*
 				 * This is something we didn't expect.  Remove
-				 * it by unplumbing the logical interface.
+				 * the address.
 				 */
-				if (u_if->nwamd_if_dhcp_requested &&
-				    v4dhcp_running)
-					nwamd_dhcp_release(ncu->ncu_name);
-				if (lifnum == 0) {
-					nwamd_down_interface(ncu->ncu_name,
-					    lifnum, family);
-					interface_ncu_down(ncu);
-				} else {
-					nwamd_unplumb_interface(ncu, lifnum,
-					    family);
-				}
-				goto exit;
+				nwamd_down_interface(addrinfo->ia_aobjname,
+				    addrinfo->ia_atype, ncu->ncu_name);
+				nifa->configured = B_FALSE;
+				goto valid_done;
 			}
 
 			/*
@@ -1235,8 +1075,7 @@
 			 * v4 is configured or a v6 address if only v6 is
 			 * configured.
 			 */
-			(void) update_address_configured_value(addr, ncu,
-			    B_TRUE);
+			nifa->configured = B_TRUE;
 			if (state != NWAM_STATE_ONLINE)
 				interface_ncu_up(ncu);
 
@@ -1255,6 +1094,7 @@
 				    "event: refresh of %s "
 				    "failed", NET_LOC_FMRI);
 			}
+
 		} else if (state == NWAM_STATE_ONLINE ||
 		    state == NWAM_STATE_OFFLINE_TO_ONLINE) {
 			/*
@@ -1267,21 +1107,24 @@
 			 * We can get RTM_DELADDRs for duplicate addresses
 			 * so deal with this seperately.
 			 */
-			if (static_addr) {
-				(void) update_address_configured_value(addr,
-				    ncu, B_FALSE);
-			} else if (family == AF_INET) {
+			nifa->configured = B_FALSE;
+
+			if (!static_addr && family == AF_INET) {
 				u_if->nwamd_if_dhcp_configured = B_FALSE;
-			} else if (family == AF_INET6) {
+			} else if (!static_addr && family == AF_INET6) {
 				/*
-				 * The address is already gone.  I'm not sure
-				 * how we figure out if this address is
-				 * stateful (DHCP) or stateless.  When we
-				 * are managing IPv6 more explicitly this will
-				 * have to be done more carefully.
+				 * The address is already gone.  When looking
+				 * for the addrinfo (using aobjname in
+				 * ipaddr), we found addrinfo for either one
+				 * or both stateless and stateful.  Using the
+				 * flags we determined whether each was
+				 * configured or not.  Update the flags here
+				 * accordingly.
 				 */
-				u_if->nwamd_if_stateful_configured = B_FALSE;
-				u_if->nwamd_if_stateless_configured = B_FALSE;
+				u_if->nwamd_if_stateful_configured =
+				    stateless_ai_found;
+				u_if->nwamd_if_stateless_configured =
+				    stateful_ai_found;
 			}
 
 			if (flags & IFF_DUPLICATE) {
@@ -1297,8 +1140,9 @@
 				interface_ncu_down(ncu);
 			}
 		}
+valid_done:
+		ipadm_free_addr_info(ai);
 	}
-exit:
 	nwamd_object_release(ncu_obj);
 }
 
@@ -1320,140 +1164,104 @@
 }
 
 /*
- * This function downs any logical interface and just zeros the address off of
- * the physical interface (logical interface 0).  If you want to unplumb 0 then
- * you need to call nwamd_unplumb_interface() directly.
+ * Remove the address in the given aobjname.  IPADM_OPT_RELEASE is specified
+ * for a DHCP address and specifies that the DHCP lease should also be released.
+ * ifname is only used for nlog().
  */
 static void
-nwamd_down_interface(const char *linkname, uint_t lifnum, int family)
+nwamd_down_interface(const char *aobjname, ipadm_addr_type_t atype,
+    const char *ifname)
 {
-	uint64_t flags;
-	icfg_if_t intf;
-	icfg_handle_t h;
-	icfg_error_t rc;
+	ipadm_status_t ipstatus;
+	uint32_t rflags = (atype == IPADM_ADDR_DHCP ? IPADM_OPT_RELEASE : 0);
 
-	if (linkname == NULL) {
-		nlog(LOG_ERR, "nwamd_down_interface: linkname null");
-		return;
+	nlog(LOG_DEBUG, "nwamd_down_interface: %s [aobjname = %s]",
+	    ifname, aobjname);
+	if ((ipstatus = ipadm_delete_addr(ipadm_handle, aobjname,
+	    IPADM_OPT_ACTIVE | rflags)) != IPADM_SUCCESS) {
+		nlog(LOG_ERR, "nwamd_down_interface: "
+		    "ipadm_delete_addr failed on %s: %s",
+		    ifname, ipadm_status2str(ipstatus));
 	}
-
-	(void) nwamd_link_to_ifname(linkname, lifnum, intf.if_name,
-	    sizeof (intf.if_name));
-	intf.if_protocol = family;
+}
 
-	rc = icfg_open(&h, &intf);
-	if (rc != ICFG_SUCCESS) {
-		nlog(LOG_ERR, "nwamd_down_interface: icfg_open failed for %s: "
-		    "%s", intf.if_name, icfg_errmsg(rc));
-		return;
-	}
+static void
+unconfigure_addresses(nwamd_ncu_t *ncu, sa_family_t af)
+{
+	struct nwamd_if_address *nifap, *nifa = ncu->ncu_if.nwamd_if_list;
 
-	if (lifnum == 0) {
-		struct sockaddr_in6 addr;
+	for (nifap = nifa; nifap != NULL; nifap = nifap->next)
+		if (af == AF_UNSPEC || nifap->family == af)
+			nifap->configured = B_FALSE;
+}
+
+static void
+dhcp_release(const char *ifname)
+{
+	ipadm_addr_info_t *ainfo, *ainfop;
 
-		(void) memset(&addr, 0, sizeof (addr));
-		addr.sin6_family = family;
-		if (icfg_set_addr(h, (struct sockaddr *)&addr,
-		    family == AF_INET ? sizeof (struct sockaddr_in) :
-		    sizeof (struct sockaddr_in6)) != ICFG_SUCCESS)
-			nlog(LOG_ERR, "nwamd_down_interface couldn't zero "
-			    "address on %s", h->ifh_interface.if_name);
-	} else {
-		if (icfg_get_flags(h, &flags) == ICFG_SUCCESS) {
-			if (icfg_set_flags(h, flags & ~IFF_UP) != ICFG_SUCCESS)
-				nlog(LOG_ERR, "nwamd_down_interface: couldn't "
-				    "bring %s down", h->ifh_interface.if_name);
-		} else {
-			nlog(LOG_ERR, "nwamd_down_interface: icfg_get_flags "
-			    "failed on %s", h->ifh_interface.if_name);
-		}
+	if (ipadm_addr_info(ipadm_handle, ifname, &ainfo, 0, 0)
+	    != IPADM_SUCCESS)
+		return;
+
+	for (ainfop = ainfo; ainfop != NULL; ainfop = IA_NEXT(ainfop)) {
+		if (ainfop->ia_atype == IPADM_ADDR_DHCP)
+			nwamd_down_interface(ainfop->ia_aobjname,
+			    ainfop->ia_atype, ifname);
 	}
-
-	icfg_close(h);
+	ipadm_free_addr_info(ainfo);
 }
 
 static void
-nwamd_plumb_unplumb_interface(nwamd_ncu_t *ncu, uint_t lifnum,
-    int af, boolean_t plumb)
+nwamd_plumb_unplumb_interface(nwamd_ncu_t *ncu, sa_family_t af, boolean_t plumb)
 {
-	uint64_t flags;
-	icfg_if_t intf;
-	icfg_handle_t h;
-	icfg_error_t rc;
-	nwamd_if_t *u_if;
-	const char *linkname = ncu->ncu_name;
+	char *ifname = ncu->ncu_name;
+	nwamd_if_t *u_if = &ncu->ncu_if;
+	ipadm_status_t ipstatus;
+
+	nlog(LOG_DEBUG, "nwamd_plumb_unplumb_interface: %s %s %s",
+	    (plumb ? "plumb" : "unplumb"), (af == AF_INET ? "IPv4" : "IPv6"),
+	    ifname);
 
-	if (linkname == NULL) {
-		nlog(LOG_ERR, "nwamd_plumb_unplumb_interface: linkname null");
-		return;
+	if (plumb) {
+		ipstatus = ipadm_create_if(ipadm_handle, ifname, af,
+		    IPADM_OPT_ACTIVE);
+	} else {
+		/* release DHCP address, if any */
+		if (af == AF_INET)
+			dhcp_release(ifname);
+		ipstatus = ipadm_delete_if(ipadm_handle, ifname, af,
+		    IPADM_OPT_ACTIVE);
 	}
 
-	(void) nwamd_link_to_ifname(linkname, lifnum, intf.if_name,
-	    sizeof (intf.if_name));
-	intf.if_protocol = af;
-
-	nlog(LOG_DEBUG, "nwamd_plumb_unplumb_interface: %s %s on link %s",
-	    plumb ? "plumbing" : "unplumbing",
-	    af == AF_INET ? "IPv4" : "IPv6", linkname);
-
-	/*
-	 * Before unplumbing, do a DHCP release if lifnum is 0.  Otherwise
-	 * dhcpagent can get confused.
-	 */
-	if (!plumb && af == AF_INET && lifnum == 0)
-		nwamd_dhcp_release(ncu->ncu_name);
-
-	rc = icfg_open(&h, &intf);
-	if (rc != ICFG_SUCCESS) {
-		nlog(LOG_ERR, "nwamd_plumb_unplumb_interface: "
-		    "icfg_open failed for %s: %s", intf.if_name,
-		    icfg_errmsg(rc));
-		return;
-	}
-	rc = plumb ? icfg_plumb(h) : icfg_unplumb(h);
-
-	if (rc != ICFG_SUCCESS) {
-		if ((plumb && rc != ICFG_EXISTS) ||
-		    (!plumb && rc != ICFG_NO_EXIST)) {
+	if (ipstatus != IPADM_SUCCESS) {
+		if ((plumb && ipstatus != IPADM_IF_EXISTS) ||
+		    (!plumb && ipstatus != IPADM_ENXIO)) {
 			nlog(LOG_ERR, "nwamd_plumb_unplumb_interface: "
 			    "%s %s failed for %s: %s",
-			    plumb ? "plumb" : "unplumb",
-			    af == AF_INET ? "IPv4" : "IPv6",
-			    intf.if_name, icfg_errmsg(rc));
-		}
-	} else if (plumb) {
-		if (icfg_get_flags(h, &flags) == ICFG_SUCCESS &&
-		    (flags & IFF_UP) == 0) {
-			if (icfg_set_flags(h, flags | IFF_UP) != ICFG_SUCCESS)
-				nlog(LOG_ERR, "nwamd_plumb_unplumb_interface: "
-				    "couldn't bring %s up",
-				    h->ifh_interface.if_name);
-		} else {
-			nlog(LOG_ERR, "nwamd_plumb_unplumb_interface: "
-			    "icfg_get_flags failed on %s",
-			    h->ifh_interface.if_name);
+			    (plumb ? "plumb" : "unplumb"),
+			    (af == AF_INET ? "IPv4" : "IPv6"),
+			    ifname, ipadm_status2str(ipstatus));
 		}
 	}
 
-	u_if = &ncu->ncu_node.u_if;
+	/* Unset flags */
 	if (!plumb) {
-		nwamd_update_addresses_unconfigured(ncu, af);
+		unconfigure_addresses(ncu, af);
 		switch (af) {
-			case AF_INET:
-				u_if->nwamd_if_dhcp_configured = B_FALSE;
-				break;
-			case AF_INET6:
-				u_if->nwamd_if_stateful_configured = B_FALSE;
-				u_if->nwamd_if_stateless_configured = B_FALSE;
-				break;
+		case AF_INET:
+			u_if->nwamd_if_dhcp_configured = B_FALSE;
+			break;
+		case AF_INET6:
+			u_if->nwamd_if_stateful_configured = B_FALSE;
+			u_if->nwamd_if_stateless_configured = B_FALSE;
+			break;
 		}
 	}
-
-	icfg_close(h);
 }
 
 void
-nwamd_plumb_interface(nwamd_ncu_t *ncu, uint_t lifnum, int af)
+nwamd_plumb_interface(nwamd_ncu_t *ncu, sa_family_t af)
 {
 	/*
 	 * We get all posssible privs by calling nwamd_deescalate().  During
@@ -1461,80 +1269,88 @@
 	 * because we don't have access to /etc/security/device_policy yet.
 	 */
 	nwamd_escalate();
-	nwamd_plumb_unplumb_interface(ncu, lifnum, af, B_TRUE);
+	nwamd_plumb_unplumb_interface(ncu, af, B_TRUE);
 	nwamd_deescalate();
 }
 
 void
-nwamd_unplumb_interface(nwamd_ncu_t *ncu, uint_t lifnum, int af)
+nwamd_unplumb_interface(nwamd_ncu_t *ncu, sa_family_t af)
 {
-	nwamd_plumb_unplumb_interface(ncu, lifnum, af, B_FALSE);
+	nwamd_plumb_unplumb_interface(ncu, af, B_FALSE);
 }
 
 static void *
 start_dhcp_thread(void *arg)
 {
-	struct nwamd_dhcp_thread_arg *thread_arg;
-	dhcp_ipc_reply_t *reply = NULL;
-	dhcp_ipc_request_t *request;
+	struct nwamd_dhcp_thread_arg *thread_arg = arg;
+	nwamd_object_t ncu_obj;
 	dhcp_ipc_type_t type;
-	int timeout;
 	char *name;
-	int rc, retries = 0;
+	ipadm_addrobj_t ipaddr;
+	ipadm_status_t ipstatus;
+	int retries = 0;
 
-	thread_arg = (struct nwamd_dhcp_thread_arg *)arg;
-	timeout = thread_arg->timeout;
 	name = thread_arg->name;
 	type = thread_arg->type;
+	ipaddr = thread_arg->ipaddr;
 
-	/* Try starting agent, though it may already be there */
-	nwamd_escalate();
-	rc = dhcp_start_agent(DHCP_IPC_MAX_WAIT);
-	nwamd_deescalate();
-	if (rc == -1) {
-		nlog(LOG_DEBUG, "Unable to start %s", DHCP_AGENT_PATH);
-		goto failed;
-	}
 retry:
-	/* Now allocate and send the request */
-	request = dhcp_ipc_alloc_request(type, name, NULL, 0,
-	    DHCP_TYPE_NONE);
-	if (request == NULL) {
-		nlog(LOG_DEBUG, "start_dhcp: dhcp_ipc_alloc_request : %s",
-		    strerror(errno));
-		goto failed;
+	/* Make sure the NCU is in appropriate state for DHCP command */
+	ncu_obj = nwamd_ncu_object_find(NWAM_NCU_TYPE_INTERFACE, name);
+	if (ncu_obj == NULL) {
+		nlog(LOG_ERR, "start_dhcp: no IP object %s");
+		return (NULL);
 	}
 
-	rc = dhcp_ipc_make_request(request, &reply, timeout);
-	free(request);
-	if (rc != 0) {
-		nlog(LOG_DEBUG, "start_dhcp %s: %s", name,
-		    dhcp_ipc_strerror(rc));
-		goto failed;
+	if (ncu_obj->nwamd_object_state != NWAM_STATE_OFFLINE_TO_ONLINE &&
+	    ncu_obj->nwamd_object_state != NWAM_STATE_ONLINE) {
+		nlog(LOG_INFO, "start_dhcp: IP NCU %s is in invalid state "
+		    "for DHCP command", ncu_obj->nwamd_object_name);
+		nwamd_object_release(ncu_obj);
+		return (NULL);
 	}
+	nwamd_object_release(ncu_obj);
+
+	switch (type) {
+	case DHCP_INFORM:
+	{
+		char aobjname[IPADM_AOBJSIZ];
 
-	rc = reply->return_code;
-	if (rc != 0) {
-		if (rc == DHCP_IPC_E_TIMEOUT && timeout == 0) {
-			goto failed;
+		if ((ipstatus = ipadm_get_aobjname(ipaddr, aobjname,
+		    sizeof (aobjname))) != IPADM_SUCCESS) {
+			nlog(LOG_ERR, "start_dhcp: "
+			    "ipadm_get_aobjname failed for %s: %s",
+			    name, ipadm_status2str(ipstatus));
+			goto done;
 		}
+		ipstatus = ipadm_refresh_addr(ipadm_handle, aobjname,
+		    IPADM_OPT_ACTIVE | IPADM_OPT_INFORM);
 
-		/*
-		 * DHCP timed out: change state for this NCU and enqueue
-		 * event to check NCU priority-groups.  Only care for
-		 * DHCP requests (not informs).
-		 */
-		if (rc == DHCP_IPC_E_TIMEOUT && type != DHCP_INFORM) {
+		break;
+	}
+	case DHCP_START:
+	{
+		ipstatus = ipadm_create_addr(ipadm_handle, ipaddr,
+		    IPADM_OPT_ACTIVE);
+
+		if (ipstatus == IPADM_DHCP_IPC_TIMEOUT) {
+			/*
+			 * DHCP timed out: change state for this NCU and enqueue
+			 * event to check NCU priority-groups.  Only care for
+			 * DHCP requests (not informs).
+			 */
 			char *object_name;
 
 			nlog(LOG_INFO, "start_dhcp: DHCP timed out for %s",
 			    name);
+
 			if (nwam_ncu_name_to_typed_name(name,
 			    NWAM_NCU_TYPE_INTERFACE, &object_name)
 			    != NWAM_SUCCESS) {
 				nlog(LOG_ERR, "start_dhcp: "
-				    "nwam_ncu_name_to_typed_name failed");
-				goto failed;
+				    "nwam_ncu_name_to_typed_name failed "
+				    "for %s", name);
+				goto done;
 			}
 			nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
 			    object_name, NWAM_STATE_OFFLINE_TO_ONLINE,
@@ -1542,133 +1358,63 @@
 			nwamd_create_ncu_check_event(0);
 
 			free(object_name);
-			goto failed;
-
-		} else if (rc == DHCP_IPC_E_RUNNING) {
-			/*
-			 * DHCP is already running.  Check if IP address is
-			 * already configured on the interface.
-			 */
-
-			icfg_handle_t h;
-			icfg_if_t intf;
-			struct sockaddr_in sin;
-			socklen_t alen = sizeof (struct sockaddr_in);
-			int plen, index;
-			uint64_t flags;
-			nwamd_event_t ip_event;
-
-			nlog(LOG_ERR, "start_dhcp: DHCP already running on %s",
-			    name);
-
-			(void) strlcpy(intf.if_name, name,
-			    sizeof (intf.if_name));
-			intf.if_protocol = AF_INET;
-
-			if (icfg_open(&h, &intf) != ICFG_SUCCESS) {
-				nlog(LOG_ERR, "start_dhcp: "
-				    "icfg_open failed on %s", name);
-				goto failed;
-			}
+			goto done;
 
-			/* Get address */
-			if (icfg_get_addr(h, (struct sockaddr *)&sin, &alen,
-			    &plen, B_FALSE) != ICFG_SUCCESS) {
-				nlog(LOG_ERR, "start_dhcp: "
-				    "icfg_get_addr failed on %s: %s",
-				    name, strerror(errno));
-				goto bail;
-			}
-			/* Check if 0.0.0.0 */
-			if (sin.sin_addr.s_addr == INADDR_ANY) {
-				nlog(LOG_ERR, "start_dhcp: empty address on %s",
-				    name);
-				goto bail;
-			}
-
-			/* valid address exists, get the flags, index of intf */
-			if (icfg_get_flags(h, &flags) != ICFG_SUCCESS) {
-				nlog(LOG_ERR, "start_dhcp: "
-				    "icfg_get_flags failed on %s", name);
-				goto bail;
-			}
-			if (icfg_get_index(h, &index) != ICFG_SUCCESS) {
-				nlog(LOG_ERR, "start_dhcp: "
-				    "icfg_get_index failed on %s", name);
-				goto bail;
-			}
-
-			/* synthesize an IF_STATE event with the intf's flags */
-			ip_event = nwamd_event_init_if_state(name, flags,
-			    B_TRUE, index, (struct sockaddr *)&sin);
-			if (ip_event != NULL)
-				nwamd_event_enqueue(ip_event);
-bail:
-			icfg_close(h);
-			goto failed;
-
-		} else if ((rc == DHCP_IPC_E_SOCKET ||
-		    rc == DHCP_IPC_E_INVIF) && retries++ < NWAMD_DHCP_RETRIES) {
+		} else if (ipstatus == IPADM_DHCP_IPC_ERROR &&
+		    retries++ < NWAMD_DHCP_RETRIES) {
 			/*
 			 * Retry DHCP request as we may have been unplumbing
 			 * as part of the configuration phase.
 			 */
-			nlog(LOG_ERR, "start_dhcp %s: %s; will retry in %d sec",
-			    name, dhcp_ipc_strerror(rc),
-			    rc == DHCP_IPC_E_INVIF ?
-			    NWAMD_DHCP_RETRY_WAIT_TIME : 0);
-			if (rc == DHCP_IPC_E_INVIF)
-				(void) sleep(NWAMD_DHCP_RETRY_WAIT_TIME);
+			nlog(LOG_ERR, "start_dhcp: will retry on %s in %d sec",
+			    name, NWAMD_DHCP_RETRY_WAIT_TIME);
+			(void) sleep(NWAMD_DHCP_RETRY_WAIT_TIME);
 			goto retry;
-		} else {
-			nlog(LOG_ERR, "start_dhcp %s: %s", name,
-			    dhcp_ipc_strerror(rc));
-			goto failed;
 		}
+		break;
+	}
+	default:
+		nlog(LOG_ERR, "start_dhcp: invalid dhcp_ipc_type_t: %d", type);
+		goto done;
 	}
 
-	/* If status was the command, then output the results */
-	if (DHCP_IPC_CMD(type) == DHCP_STATUS) {
-		nlog(LOG_DEBUG, "%s", dhcp_status_hdr_string());
-		nlog(LOG_DEBUG, "%s", dhcp_status_reply_to_string(reply));
+	if (ipstatus != IPADM_SUCCESS) {
+		nlog(LOG_ERR, "start_dhcp: ipadm_%s_addr failed for %s: %s",
+		    (type == DHCP_START ? "create" : "refresh"),
+		    name, ipadm_status2str(ipstatus));
 	}
 
-failed:
-	free(reply);
-	if (arg != NULL) {
-		free(name);
-		free(arg);
-	}
+done:
+	free(name);
+	free(arg);
 	return (NULL);
 }
 
-void
-nwamd_start_dhcp(nwamd_ncu_t *ncu)
+static void
+nwamd_dhcp(const char *ifname, ipadm_addrobj_t ipaddr, dhcp_ipc_type_t cmd)
 {
 	struct nwamd_dhcp_thread_arg *arg;
-	char *name = NULL;
 	pthread_attr_t attr;
 
-	nlog(LOG_DEBUG, "nwamd_start_dhcp: starting DHCP for %s %d",
-	    ncu->ncu_name, ncu->ncu_type);
+	nlog(LOG_DEBUG, "nwamd_dhcp: starting DHCP %s thread for %s",
+	    dhcp_ipc_type_to_string(cmd), ifname);
 
 	arg = malloc(sizeof (*arg));
 	if (arg == NULL) {
-		nlog(LOG_ERR, "nwamd_start_dhcp: error allocating memory "
-		    "for dhcp request");
-		free(name);
+		nlog(LOG_ERR, "nwamd_dhcp: error allocating memory for "
+		    "dhcp request");
 		return;
 	}
 
-	arg->name = strdup(ncu->ncu_name);
-	arg->type = DHCP_START;
-	arg->timeout = ncu_wait_time;
+	arg->name = strdup(ifname);
+	arg->type = cmd;
+	arg->ipaddr = ipaddr;
 
 	(void) pthread_attr_init(&attr);
 	(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 	if (pthread_create(NULL, &attr, start_dhcp_thread, arg) == -1) {
-		nlog(LOG_ERR, "nwamd_start_dhcp: cannot start dhcp thread");
-		free(name);
+		nlog(LOG_ERR, "nwamd_dhcp: cannot start dhcp thread");
+		free(arg->name);
 		free(arg);
 		(void) pthread_attr_destroy(&attr);
 		return;
--- a/usr/src/cmd/cmd-inet/lib/nwamd/ncu_phys.c	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/ncu_phys.c	Mon Jun 07 14:10:14 2010 -0400
@@ -33,7 +33,6 @@
 #include <libdllink.h>
 #include <libdlstat.h>
 #include <libdlwlan.h>
-#include <libinetutil.h>
 #include <libnwam.h>
 #include <limits.h>
 #include <pthread.h>
@@ -61,17 +60,6 @@
  * Mostly WiFi code.
  */
 
-char *
-nwamd_link_to_ifname(const char *linkname, int lifnum, char *ifname, int len)
-{
-	if (lifnum == 0) {
-		(void) strlcpy(ifname, linkname, len);
-	} else {
-		(void) snprintf(ifname, len, "%s:%d", linkname, lifnum);
-	}
-	return (ifname);
-}
-
 /*
  * Get link state from kstats. Used to determine initial link state for
  * cases where drivers do not support DL_NOTE_LINK_UP/DOWN.  If link
@@ -121,12 +109,11 @@
 void
 nwamd_set_unset_link_properties(nwamd_ncu_t *ncu, boolean_t set)
 {
-	dlpi_handle_t dh = ncu->ncu_node.u_link.nwamd_link_dhp;
-	char *addr = set ? ncu->ncu_node.u_link.nwamd_link_mac_addr : NULL;
-	uint64_t mtu = set ? ncu->ncu_node.u_link.nwamd_link_mtu : 0;
-	char **autopush = set ? ncu->ncu_node.u_link.nwamd_link_autopush : NULL;
-	uint_t num_autopush = set ?
-	    ncu->ncu_node.u_link.nwamd_link_num_autopush : 0;
+	dlpi_handle_t dh = ncu->ncu_link.nwamd_link_dhp;
+	char *addr = set ? ncu->ncu_link.nwamd_link_mac_addr : NULL;
+	uint64_t mtu = set ? ncu->ncu_link.nwamd_link_mtu : 0;
+	char **autopush = set ? ncu->ncu_link.nwamd_link_autopush : NULL;
+	uint_t num_autopush = set ? ncu->ncu_link.nwamd_link_num_autopush : 0;
 	uchar_t *hwaddr = NULL, curraddr[DLPI_PHYSADDR_MAX];
 	size_t hwaddrlen = DLPI_PHYSADDR_MAX;
 	int retval;
@@ -143,8 +130,8 @@
 	if (mtu == 0) {
 		cp = mtustr;
 		status = dladm_get_linkprop(dld_handle,
-		    ncu->ncu_node.u_link.nwamd_link_id, DLADM_PROP_VAL_DEFAULT,
-		    "mtu", &cp, &cnt);
+		    ncu->ncu_link.nwamd_link_id, DLADM_PROP_VAL_DEFAULT, "mtu",
+		    &cp, &cnt);
 		if (status != DLADM_STATUS_OK) {
 			nlog(LOG_ERR, "nwamd_set_unset_link_properties: "
 			    "dladm_get_linkprop failed: %s",
@@ -159,9 +146,8 @@
 
 	nlog(LOG_DEBUG, "nwamd_set_unset_link_properties: setting MTU of %s "
 	    "for link %s", mtustr, ncu->ncu_name);
-	status = dladm_set_linkprop(dld_handle,
-	    ncu->ncu_node.u_link.nwamd_link_id, "mtu", &cp, 1,
-	    DLADM_OPT_ACTIVE);
+	status = dladm_set_linkprop(dld_handle, ncu->ncu_link.nwamd_link_id,
+	    "mtu", &cp, 1, DLADM_OPT_ACTIVE);
 	if (status != DLADM_STATUS_OK) {
 		nlog(LOG_ERR, "nwamd_set_unset_link_properties: "
 		    "dladm_set_linkprop failed: %s",
@@ -170,9 +156,8 @@
 
 	nlog(LOG_DEBUG, "nwamd_set_unset_link_properties: setting %d "
 	    "autopush module for link %s", num_autopush, ncu->ncu_name);
-	status = dladm_set_linkprop(dld_handle,
-	    ncu->ncu_node.u_link.nwamd_link_id, "autopush", autopush,
-	    num_autopush, DLADM_OPT_ACTIVE);
+	status = dladm_set_linkprop(dld_handle, ncu->ncu_link.nwamd_link_id,
+	    "autopush", autopush, num_autopush, DLADM_OPT_ACTIVE);
 	if (status != DLADM_STATUS_OK) {
 		nlog(LOG_ERR, "nwamd_set_unset_link_properties: "
 		    "dladm_set_linkprop failed for autopush property: %s",
@@ -432,7 +417,7 @@
 		return (NWAM_ENTITY_NOT_FOUND);
 	}
 	ncu = ncu_obj->nwamd_object_data;
-	link = &ncu->ncu_node.u_link;
+	link = &ncu->ncu_link;
 
 	nlog(LOG_DEBUG, "nwamd_wlan_set_key: running for link %s", linkname);
 	/*
@@ -629,17 +614,17 @@
 {
 	nwamd_ncu_t *ncu = object->nwamd_object_data;
 
-	if (ncu->ncu_node.u_link.nwamd_link_media != DL_WIFI)
+	if (ncu->ncu_link.nwamd_link_media != DL_WIFI)
 		return (B_FALSE);
 
 	(void) pthread_mutex_lock(&active_ncp_mutex);
 	if (object->nwamd_object_state == NWAM_STATE_DISABLED ||
 	    ((object->nwamd_object_state == NWAM_STATE_OFFLINE ||
 	    object->nwamd_object_state == NWAM_STATE_ONLINE_TO_OFFLINE) &&
-	    ncu->ncu_node.u_link.nwamd_link_activation_mode ==
+	    ncu->ncu_link.nwamd_link_activation_mode ==
 	    NWAM_ACTIVATION_MODE_PRIORITIZED &&
 	    (current_ncu_priority_group == INVALID_PRIORITY_GROUP ||
-	    ncu->ncu_node.u_link.nwamd_link_priority_group >
+	    ncu->ncu_link.nwamd_link_priority_group >
 	    current_ncu_priority_group))) {
 		(void) pthread_mutex_unlock(&active_ncp_mutex);
 		return (B_FALSE);
@@ -659,7 +644,7 @@
 nwamd_set_selected_connected(nwamd_ncu_t *ncu, boolean_t selected,
     boolean_t connected)
 {
-	nwamd_link_t *link = &ncu->ncu_node.u_link;
+	nwamd_link_t *link = &ncu->ncu_link;
 	nwamd_wifi_scan_t *s = &link->nwamd_link_wifi_scan;
 	int i;
 	boolean_t trigger_scan_event = B_FALSE;
@@ -780,7 +765,7 @@
 		return (NWAM_ENTITY_NOT_FOUND);
 	}
 	ncu = ncu_obj->nwamd_object_data;
-	link = &ncu->ncu_node.u_link;
+	link = &ncu->ncu_link;
 
 	/*
 	 * If wireless selection is not possible because of the current
@@ -932,7 +917,7 @@
 find_best_wlan_cb(nwam_known_wlan_handle_t kwh, void *data)
 {
 	nwamd_ncu_t *ncu = data;
-	nwamd_link_t *link = &ncu->ncu_node.u_link;
+	nwamd_link_t *link = &ncu->ncu_link;
 	nwamd_wifi_scan_t *s = &link->nwamd_link_wifi_scan;
 	nwam_error_t err;
 	char *name = NULL;
@@ -1163,7 +1148,7 @@
 nwamd_wlan_connected(nwamd_object_t ncu_obj)
 {
 	nwamd_ncu_t *ncu = ncu_obj->nwamd_object_data;
-	nwamd_link_t *link = &ncu->ncu_node.u_link;
+	nwamd_link_t *link = &ncu->ncu_link;
 	dladm_wlan_linkattr_t attr;
 	char essid[DLADM_STRSIZE];
 	char bssid[DLADM_STRSIZE];
@@ -1274,7 +1259,7 @@
 	}
 
 	ncu = ncu_obj->nwamd_object_data;
-	link = &ncu->ncu_node.u_link;
+	link = &ncu->ncu_link;
 
 	/*
 	 * It is possible multiple scan threads have queued up waiting for the
@@ -1339,7 +1324,7 @@
 		return (NULL);
 	}
 	ncu = ncu_obj->nwamd_object_data;
-	link = &ncu->ncu_node.u_link;
+	link = &ncu->ncu_link;
 
 	/* For new scan data, add key info from known WLANs */
 	for (i = 0; i < s.nwamd_wifi_scan_curr_num; i++) {
@@ -1522,7 +1507,7 @@
 	}
 
 	ncu = ncu_obj->nwamd_object_data;
-	link = &ncu->ncu_node.u_link;
+	link = &ncu->ncu_link;
 
 	if (!wireless_selection_possible(ncu_obj)) {
 		nlog(LOG_DEBUG, "wlan_connect_thread: %s in invalid state or "
@@ -1623,7 +1608,7 @@
 	}
 
 	ncu = ncu_obj->nwamd_object_data;
-	link = &ncu->ncu_node.u_link;
+	link = &ncu->ncu_link;
 
 	if (autoconf)
 		link->nwamd_link_wifi_autoconf = B_TRUE;
@@ -1719,7 +1704,7 @@
 			break;
 		}
 		ncu = ncu_obj->nwamd_object_data;
-		link = &ncu->ncu_node.u_link;
+		link = &ncu->ncu_link;
 
 		/* If the NCU is DISABLED/OFFLINE, exit the monitoring thread */
 		if (ncu_obj->nwamd_object_state == NWAM_STATE_OFFLINE ||
@@ -1810,7 +1795,7 @@
 		return;
 	}
 	ncu = ncu_obj->nwamd_object_data;
-	link = &ncu->ncu_node.u_link;
+	link = &ncu->ncu_link;
 	evm = event->event_msg;
 
 	/*
--- a/usr/src/cmd/cmd-inet/lib/nwamd/routing_events.c	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/routing_events.c	Mon Jun 07 14:10:14 2010 -0400
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <arpa/inet.h>
@@ -38,7 +37,6 @@
 #include <sys/fcntl.h>
 #include <unistd.h>
 
-#include <inetcfg.h>
 #include <libnwam.h>
 #include "events.h"
 #include "ncp.h"
@@ -101,8 +99,6 @@
 		return ("CHGADDR");
 	case RTM_FREEADDR:
 		return ("FREEADDR");
-	case RTM_IFINFO:
-		return ("IFINFO");
 	default:
 		(void) snprintf(typestr, sizeof (typestr), "type %d", type);
 		return (typestr);
@@ -117,10 +113,9 @@
 	union rtm_buf buffer;
 	struct rt_msghdr *rtm;
 	struct ifa_msghdr *ifa;
-	struct if_msghdr *ifm;
 	char *addrs, *if_name;
 	struct sockaddr_dl *addr_dl;
-	struct sockaddr *addr;
+	struct sockaddr *addr, *netmask;
 	nwamd_event_t ip_event;
 
 	nlog(LOG_DEBUG, "v4 routing socket %d", v4_sock);
@@ -169,7 +164,6 @@
 			nlog(LOG_DEBUG, "v4 routing message %s: "
 			    "index %d flags %x", rtmtype_str(rtm->rtm_type),
 			    ifa->ifam_index, ifa->ifam_flags);
-			printaddrs(ifa->ifam_addrs, addrs);
 
 			if ((addr = (struct sockaddr *)getaddr(RTA_IFA,
 			    ifa->ifam_addrs, addrs)) == NULL)
@@ -184,6 +178,10 @@
 				break;
 			}
 
+			if ((netmask = (struct sockaddr *)getaddr(RTA_NETMASK,
+			    ifa->ifam_addrs, addrs)) == NULL)
+				break;
+
 			if ((addr_dl = (struct sockaddr_dl *)getaddr
 			    (RTA_IFP, ifa->ifam_addrs, addrs)) == NULL)
 				break;
@@ -205,57 +203,17 @@
 				break;
 			}
 
+			printaddrs(ifa->ifam_addrs, addrs);
+
 			/* Create and enqueue IF_STATE event */
 			ip_event = nwamd_event_init_if_state(if_name,
 			    ifa->ifam_flags,
 			    (rtm->rtm_type == RTM_NEWADDR ||
 			    rtm->rtm_type == RTM_CHGADDR ? B_TRUE : B_FALSE),
-			    ifa->ifam_index, addr);
+			    addr, netmask);
 			if (ip_event != NULL)
 				nwamd_event_enqueue(ip_event);
 			break;
-
-		case RTM_IFINFO:
-
-			ifm = (void *)rtm;
-			addrs = (char *)ifm + sizeof (*ifm);
-			nlog(LOG_DEBUG, "v4 routing message %s: "
-			    "index %d flags %x", rtmtype_str(rtm->rtm_type),
-			    ifm->ifm_index, ifm->ifm_flags);
-			printaddrs(ifm->ifm_addrs, addrs);
-
-			if ((addr_dl = (struct sockaddr_dl *)getaddr(RTA_IFP,
-			    ifm->ifm_addrs, addrs)) == NULL)
-				break;
-			/*
-			 * We don't use the lladdr in this structure so we can
-			 * run over it.
-			 */
-			addr_dl->sdl_data[addr_dl->sdl_nlen] = 0;
-			if_name = addr_dl->sdl_data; /* no lifnum */
-
-			if (ifm->ifm_index == 0) {
-				nlog(LOG_DEBUG, "tossing index 0 message");
-				break;
-			}
-			if (ifm->ifm_type != RTM_IFINFO) {
-				nlog(LOG_DEBUG,
-				    "routing_events_v4: unhandled type %d",
-				    ifm->ifm_type);
-				break;
-			}
-
-			/* Create and enqueue IF_STATE event */
-			ip_event = nwamd_event_init_if_state(if_name,
-			    ifm->ifm_flags, B_FALSE, ifm->ifm_index, NULL);
-			if (ip_event != NULL)
-				nwamd_event_enqueue(ip_event);
-			break;
-
-		default:
-			nlog(LOG_DEBUG, "v4 routing message %s discarded",
-			    rtmtype_str(rtm->rtm_type));
-			break;
 		}
 	}
 	/* NOTREACHED */
@@ -270,10 +228,9 @@
 	union rtm_buf buffer;
 	struct rt_msghdr *rtm;
 	struct ifa_msghdr *ifa;
-	struct if_msghdr *ifm;
 	char *addrs, *if_name;
 	struct sockaddr_dl *addr_dl;
-	struct sockaddr *addr;
+	struct sockaddr *addr, *netmask;
 	nwamd_event_t ip_event;
 
 	nlog(LOG_DEBUG, "v6 routing socket %d", v6_sock);
@@ -323,13 +280,19 @@
 			nlog(LOG_DEBUG, "v6 routing message %s: "
 			    "index %d flags %x", rtmtype_str(rtm->rtm_type),
 			    ifa->ifam_index, ifa->ifam_flags);
-			printaddrs(ifa->ifam_addrs, addrs);
 
 			if ((addr = (struct sockaddr *)getaddr(RTA_IFA,
 			    ifa->ifam_addrs, addrs)) == NULL)
 				break;
 
-			/* Ignore messages for link local address */
+			/* Ignore routing socket messages for :: & linklocal */
+			/*LINTED*/
+			if (IN6_IS_ADDR_UNSPECIFIED(
+			    &((struct sockaddr_in6 *)addr)->sin6_addr)) {
+				nlog(LOG_INFO, "routing_events_v6: "
+				    "tossing message for ::");
+				break;
+			}
 			/*LINTED*/
 			if (IN6_IS_ADDR_LINKLOCAL(
 			    &((struct sockaddr_in6 *)addr)->sin6_addr)) {
@@ -338,6 +301,11 @@
 				break;
 			}
 
+			if ((netmask =
+			    (struct sockaddr *)getaddr(RTA_NETMASK,
+			    ifa->ifam_addrs, addrs)) == NULL)
+				break;
+
 			if ((addr_dl = (struct sockaddr_dl *)getaddr
 			    (RTA_IFP, ifa->ifam_addrs, addrs)) == NULL)
 				break;
@@ -359,57 +327,18 @@
 				break;
 			}
 
+			printaddrs(ifa->ifam_addrs, addrs);
+
 			/* Create and enqueue IF_STATE event */
 			ip_event = nwamd_event_init_if_state(if_name,
 			    ifa->ifam_flags,
 			    (rtm->rtm_type == RTM_NEWADDR ||
 			    rtm->rtm_type == RTM_CHGADDR ? B_TRUE : B_FALSE),
-			    ifa->ifam_index, addr);
+			    addr, netmask);
 			if (ip_event != NULL)
 				nwamd_event_enqueue(ip_event);
 			break;
 
-		case RTM_IFINFO:
-
-			ifm = (void *)rtm;
-			addrs = (char *)ifm + sizeof (*ifm);
-			nlog(LOG_DEBUG, "v6 routing message %s: "
-			    "index %d flags %x", rtmtype_str(rtm->rtm_type),
-			    ifm->ifm_index, ifm->ifm_flags);
-			printaddrs(ifm->ifm_addrs, addrs);
-
-			if ((addr_dl = (struct sockaddr_dl *)getaddr(RTA_IFP,
-			    ifm->ifm_addrs, addrs)) == NULL)
-				break;
-			/*
-			 * We don't use the lladdr in this structure so we can
-			 * run over it.
-			 */
-			addr_dl->sdl_data[addr_dl->sdl_nlen] = 0;
-			if_name = addr_dl->sdl_data; /* no lifnum */
-
-			if (ifm->ifm_index == 0) {
-				nlog(LOG_DEBUG, "tossing index 0 message");
-				break;
-			}
-			if (ifm->ifm_type != RTM_IFINFO) {
-				nlog(LOG_DEBUG,
-				    "routing_events_v6: unhandled type %d",
-				    ifm->ifm_type);
-				break;
-			}
-
-			/* Create and enqueue IF_STATE event */
-			ip_event = nwamd_event_init_if_state(if_name,
-			    ifm->ifm_flags, B_FALSE, ifm->ifm_index, NULL);
-			if (ip_event != NULL)
-				nwamd_event_enqueue(ip_event);
-			break;
-
-		default:
-			nlog(LOG_DEBUG, "v6 routing message %s discarded",
-			    rtmtype_str(rtm->rtm_type));
-			break;
 		}
 	}
 	/* NOTREACHED */
@@ -458,26 +387,18 @@
 	struct rt_msghdr *rtm = (struct rt_msghdr *)rtbuf;
 	void *addrs = rtbuf + sizeof (struct rt_msghdr);
 	struct sockaddr_dl sdl;
-	icfg_if_t intf;
-	icfg_handle_t h;
 	int rlen, index;
 	int af;
 
 	af = gateway->sa_family;
 
-	/* set interface for default route to be associated with */
-	(void) strlcpy(intf.if_name, ifname, sizeof (intf.if_name));
-	intf.if_protocol = af;
-	if (icfg_open(&h, &intf) != ICFG_SUCCESS) {
-		nlog(LOG_ERR, "nwamd_add_route: "
-		    "icfg_open failed on %s", ifname);
+	/* retrieve the index value for the interface */
+	if ((index = if_nametoindex(ifname)) == 0) {
+		nlog(LOG_ERR, "nwamd_add_route: if_nametoindex failed on %s",
+		    ifname);
 		return;
 	}
-	if (icfg_get_index(h, &index) != ICFG_SUCCESS) {
-		nlog(LOG_ERR, "nwamd_add_route: "
-		    "icfg_get_index failed on %s", ifname);
-	}
-	icfg_close(h);
+
 	(void) bzero(&sdl, sizeof (struct sockaddr_dl));
 	sdl.sdl_family = AF_LINK;
 	sdl.sdl_index = index;
--- a/usr/src/cmd/cmd-inet/lib/nwamd/util.c	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/util.c	Mon Jun 07 14:10:14 2010 -0400
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -35,7 +34,6 @@
 
 #include <assert.h>
 #include <errno.h>
-#include <inetcfg.h>
 #include <libdllink.h>
 #include <limits.h>
 #include <libscf.h>
--- a/usr/src/cmd/cmd-inet/usr.lib/vrrpd/Makefile	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/usr.lib/vrrpd/Makefile	Mon Jun 07 14:10:14 2010 -0400
@@ -19,8 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
 #
 
 PROG=		vrrpd
@@ -45,7 +44,7 @@
 # via the SUS standards.  Further, C99 support requires SUSv3 or higher.
 #
 CPPFLAGS += -D_XOPEN_SOURCE=600 -D__EXTENSIONS__
-LDLIBS += -lvrrpadm -lsocket -lnsl -ldladm -linetutil -lsysevent -lnvpair -lsecdb -linetcfg
+LDLIBS += -lvrrpadm -lsocket -lnsl -ldladm -linetutil -lipadm -lsysevent -lnvpair -lsecdb
 LINTFLAGS += -erroff=E_INCONS_ARG_DECL2  -erroff=E_INCONS_ARG_USED2
 
 #
--- a/usr/src/cmd/cmd-inet/usr.lib/vrrpd/vrrpd.c	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/usr.lib/vrrpd/vrrpd.c	Mon Jun 07 14:10:14 2010 -0400
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <sys/types.h>
@@ -41,7 +40,6 @@
 #include <libsysevent.h>
 #include <limits.h>
 #include <locale.h>
-#include <inetcfg.h>
 #include <arpa/inet.h>
 #include <signal.h>
 #include <assert.h>
@@ -51,6 +49,7 @@
 #include <priv_utils.h>
 #include <libdllink.h>
 #include <libdlvnic.h>
+#include <libipadm.h>
 #include <pwd.h>
 #include <libvrrpadm.h>
 #include <net/route.h>
@@ -89,6 +88,7 @@
 	iu_event_id_t	vrt_eid;	/* event ID */
 } vrrpd_rtsock_t;
 
+static ipadm_handle_t	vrrp_ipadm_handle = NULL;	/* libipadm handle */
 static int		vrrp_logflag = 0;
 boolean_t		vrrp_debug_level = 0;
 iu_eh_t			*vrrpd_eh = NULL;
@@ -216,7 +216,7 @@
 
 static void vrrpd_init_ipcache(int);
 static void vrrpd_update_ipcache(int);
-static int vrrpd_walk_ipaddr(icfg_if_t *, void *);
+static ipadm_status_t vrrpd_walk_addr_info(int);
 static vrrp_err_t vrrpd_add_ipaddr(char *, int, vrrp_addr_t *,
     int, uint64_t);
 static vrrp_ip_t *vrrpd_select_primary(vrrp_intf_t *);
@@ -796,6 +796,12 @@
 		goto fail;
 	}
 
+	/* Open the libipadm handle */
+	if (ipadm_open(&vrrp_ipadm_handle, 0) != IPADM_SUCCESS) {
+		vrrp_log(VRRP_ERR, "vrrpd_init(): ipadm_open() failed");
+		goto fail;
+	}
+
 	/*
 	 * Build the list of interfaces and IP addresses. Also, start the time
 	 * to scan the interfaces/IP addresses periodically.
@@ -852,6 +858,8 @@
 	vrrpd_vh = NULL;
 	assert(TAILQ_EMPTY(&vrrp_vr_list));
 	assert(TAILQ_EMPTY(&vrrp_intf_list));
+
+	ipadm_close(vrrp_ipadm_handle);
 }
 
 static void
@@ -1460,11 +1468,8 @@
 again:
 	vrrpd_init_ipcache(af);
 
-	/*
-	 * If interface index changes, walk again.
-	 */
-	if (icfg_iterate_if(af, ICFG_PLUMBED, NULL,
-	    vrrpd_walk_ipaddr) != ICFG_SUCCESS)
+	/* If interface index changes, walk again. */
+	if (vrrpd_walk_addr_info(af) != IPADM_SUCCESS)
 		goto again;
 
 	vrrpd_update_ipcache(af);
@@ -1544,86 +1549,74 @@
 }
 
 /*
- * Walk all the IP addresses on the given interface and update its
- * addresses list. Return ICFG_FAILURE if it is required to walk
+ * Walk all the IP addresses of the given family and update its
+ * addresses list. Return IPADM_FAILURE if it is required to walk
  * all the interfaces again (one of the interface index changes in between).
  */
-/* ARGSUSED */
-static int
-vrrpd_walk_ipaddr(icfg_if_t *intf, void *arg)
+static ipadm_status_t
+vrrpd_walk_addr_info(int af)
 {
-	icfg_handle_t	ih;
-	int		ifindex;
-	vrrp_addr_t	addr;
-	socklen_t	addrlen = (socklen_t)sizeof (struct sockaddr_in6);
-	int		prefixlen;
-	uint64_t	flags;
-	int		err = ICFG_SUCCESS;
-
-	vrrp_log(VRRP_DBG0, "vrrpd_walk_ipaddr(%s, %s)", intf->if_name,
-	    af_str(intf->if_protocol));
-
-	if (icfg_open(&ih, intf) != ICFG_SUCCESS) {
-		vrrp_log(VRRP_ERR, "vrrpd_walk_ipaddr(%s, %s): icfg_open() "
-		    "failed: %s", intf->if_name, af_str(intf->if_protocol),
-		    strerror(errno));
-		return (err);
-	}
-
-	if (icfg_get_flags(ih, &flags) != ICFG_SUCCESS) {
-		if (errno != ENXIO && errno != ENOENT) {
-			vrrp_log(VRRP_ERR, "vrrpd_walk_ipaddr(%s, %s): "
-			    "icfg_get_flags() failed %s", intf->if_name,
-			    af_str(intf->if_protocol), strerror(errno));
-		}
-		goto done;
+	ipadm_addr_info_t	*ainfo, *ainfop;
+	ipadm_status_t		ipstatus;
+	char			*lifname;
+	vrrp_addr_t		*addr;
+	int			ifindex;
+	uint64_t		flags;
+
+	vrrp_log(VRRP_DBG0, "vrrpd_walk_addr_info(%s)", af_str(af));
+
+	ipstatus = ipadm_addr_info(vrrp_ipadm_handle, NULL, &ainfo, 0, 0);
+	if (ipstatus != IPADM_SUCCESS) {
+		vrrp_log(VRRP_ERR, "vrrpd_walk_addr_info(%s): "
+		    "ipadm_addr_info() failed: %s",
+		    af_str(af), ipadm_status2str(ipstatus));
+		return (IPADM_SUCCESS);
 	}
 
-	/*
-	 * skip virtual/IPMP/P2P interfaces.
-	 */
-	if ((flags & (IFF_VIRTUAL|IFF_IPMP|IFF_POINTOPOINT)) != 0) {
-		vrrp_log(VRRP_DBG0, "vrrpd_walk_ipaddr(%s, %s) skipped",
-		    intf->if_name, af_str(intf->if_protocol));
-		goto done;
-	}
-
-	if (icfg_get_index(ih, &ifindex) != ICFG_SUCCESS) {
-		if (errno != ENXIO && errno != ENOENT) {
-			vrrp_log(VRRP_ERR, "vrrpd_walk_ipaddr(%s, %s) "
-			    "icfg_get_index() failed: %s", intf->if_name,
-			    af_str(intf->if_protocol), strerror(errno));
+	for (ainfop = ainfo; ainfop != NULL; ainfop = IA_NEXT(ainfop)) {
+		if (ainfop->ia_ifa.ifa_addr->ss_family != af)
+			continue;
+
+		lifname = ainfop->ia_ifa.ifa_name;
+		flags = ainfop->ia_ifa.ifa_flags;
+		addr = (vrrp_addr_t *)ainfop->ia_ifa.ifa_addr;
+
+		vrrp_log(VRRP_DBG0, "vrrpd_walk_addr_info(%s): %s",
+		    af_str(af), lifname);
+
+		/* Skip virtual/IPMP/P2P interfaces */
+		if (flags & (IFF_VIRTUAL|IFF_IPMP|IFF_POINTOPOINT)) {
+			vrrp_log(VRRP_DBG0, "vrrpd_walk_addr_info(%s): "
+			    "skipped %s", af_str(af), lifname);
+			continue;
 		}
-		goto done;
+
+		/* Filter out the all-zero IP address */
+		if (VRRPADDR_UNSPECIFIED(af, addr))
+			continue;
+
+		if ((ifindex = if_nametoindex(lifname)) == 0) {
+			if (errno != ENXIO && errno != ENOENT) {
+				vrrp_log(VRRP_ERR, "vrrpd_walk_addr_info(%s): "
+				    "if_nametoindex() failed for %s: %s",
+				    af_str(af), lifname, strerror(errno));
+			}
+			break;
+		}
+
+		/*
+		 * The interface is unplumbed/replumbed during the walk.  Try
+		 * to walk the IP addresses one more time.
+		 */
+		if (vrrpd_add_ipaddr(lifname, af, addr, ifindex, flags)
+		    == VRRP_EAGAIN) {
+			ipstatus = IPADM_FAILURE;
+			break;
+		}
 	}
 
-	if (icfg_get_addr(ih, (struct sockaddr *)&addr, &addrlen,
-	    &prefixlen, _B_FALSE) != ICFG_SUCCESS) {
-		if (errno != ENXIO && errno != ENOENT) {
-			vrrp_log(VRRP_ERR, "vrrpd_walk_ipaddr(%s, %s) "
-			    "icfg_get_addr() failed: %s", intf->if_name,
-			    af_str(intf->if_protocol), strerror(errno));
-		}
-		goto done;
-	}
-
-	/*
-	 * Filter out the all-zero IP address.
-	 */
-	if (VRRPADDR_UNSPECIFIED(intf->if_protocol, &addr))
-		goto done;
-
-	/*
-	 * The interface is unplumbed/replumbed during we walk the IP
-	 * addresses. Try walk the IP addresses one more time.
-	 */
-	if (vrrpd_add_ipaddr(intf->if_name, intf->if_protocol,
-	    &addr, ifindex, flags) == VRRP_EAGAIN)
-		err = ICFG_FAILURE;
-
-done:
-	icfg_close(ih);
-	return (err);
+	ipadm_free_addr_info(ainfo);
+	return (ipstatus);
 }
 
 /*
--- a/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c	Mon Jun 07 14:10:14 2010 -0400
@@ -1264,7 +1264,7 @@
 	ipadm_status_t	status;
 	int		option;
 	uint32_t	flags =
-	    IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE|IPADM_OPT_UP;
+	    IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE|IPADM_OPT_UP|IPADM_OPT_V46;
 	char		*cp;
 	char		*atype = NULL;
 	char		*static_arg = NULL;
--- a/usr/src/cmd/cmd-inet/usr.sbin/nwamadm/nwamadm.c	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/cmd/cmd-inet/usr.sbin/nwamadm/nwamadm.c	Mon Jun 07 14:10:14 2010 -0400
@@ -36,6 +36,7 @@
 #include <assert.h>
 #include <errno.h>
 #include <libdlwlan.h>
+#include <libinetutil.h>
 #include <libnwam.h>
 #include <libscf.h>
 #include <locale.h>
@@ -123,8 +124,8 @@
 #define	STATE_WIDTH		15	/* width of STATE column */
 #define	AUXSTATE_WIDTH		36	/* width of AUXILIARY STATE column */
 
-#define	EVENT_WIDTH		22	/* width of EVENT column */
-#define	DESCRIPTION_WIDTH	56	/* width of DESCRIPTION column */
+#define	EVENT_WIDTH		15	/* width of EVENT column */
+#define	DESCRIPTION_WIDTH	64	/* width of DESCRIPTION column */
 
 /* id for columns of "nwamadm list" */
 typedef enum {
@@ -1108,9 +1109,12 @@
 		if (event->nwe_data.nwe_if_state.nwe_addr_valid) {
 			struct sockaddr_storage *address =
 			    &(event->nwe_data.nwe_if_state.nwe_addr);
+			struct sockaddr_storage *netmask =
+			    &(event->nwe_data.nwe_if_state.nwe_netmask);
 			struct sockaddr_in *v4addr;
 			struct sockaddr_in6 *v6addr;
 			char addrstr[NWAM_MAX_VALUE_LEN];
+			int plen = mask2plen(netmask);
 
 			switch (address->ss_family) {
 			case AF_INET:
@@ -1125,14 +1129,12 @@
 				break;
 			}
 			(void) snprintf(statestr, sizeof (statestr),
-			    "index %d flags 0x%x address %s",
-			    event->nwe_data.nwe_if_state.nwe_index,
-			    event->nwe_data.nwe_if_state.nwe_flags, addrstr);
+			    "flags %x addr %s/%d",
+			    event->nwe_data.nwe_if_state.nwe_flags,
+			    addrstr, plen);
 		} else {
 			(void) snprintf(statestr, sizeof (statestr),
-			    "(%d) flags %x",
-			    event->nwe_data.nwe_if_state.nwe_index,
-			    event->nwe_data.nwe_if_state.nwe_flags);
+			    "flags %x", event->nwe_data.nwe_if_state.nwe_flags);
 		}
 		state = statestr;
 		break;
--- a/usr/src/lib/Makefile	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/lib/Makefile	Mon Jun 07 14:10:14 2010 -0400
@@ -108,7 +108,6 @@
 	libwanboot	\
 	libwanbootutil	\
 	libcryptoutil	\
-	libinetcfg	\
 	libinetutil	\
 	libipadm	\
 	libipmp		\
@@ -328,7 +327,6 @@
 	libgrubmgmt	\
 	libgss		\
 	libidmap	\
-	libinetcfg	\
 	libipmp		\
 	libilb		\
 	libinetutil	\
@@ -413,7 +411,6 @@
 	libgen		\
 	libipadm	\
 	libipsecutil	\
-	libinetcfg	\
 	libinetsvc	\
 	libinetutil	\
 	libinstzones	\
@@ -593,7 +590,6 @@
 libfstyp:	libnvpair
 libelfsign:	libcryptoutil libkmf
 libidmap:	libadutils libldap5 libavl libsldap
-libinetcfg:	libnsl libsocket libdlpi libinetutil
 libipadm:	libnsl libinetutil libsocket libdlpi libnvpair libdhcpagent \
 		libdladm libsecdb
 libiscsit:	libc libnvpair libstmf libuuid libnsl
--- a/usr/src/lib/libinetcfg/Makefile	Mon Jun 07 10:04:00 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-#
-# 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 2010 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-
-include $(SRC)/lib/Makefile.lib
-
-HDRS =		inetcfg.h
-SRCS =		inetcfg.c
-HDRDIR =	common
-SUBDIRS =	$(MACH)
-POFILE =	libinetcfg.po
-MSGFILES =	common/inetcfg.c
-XGETFLAGS =	-a -x libinetcfg.xcl
-
-all :=		TARGET = all
-clean :=	TARGET = clean
-clobber :=	TARGET = clobber
-install :=	TARGET = install
-lint :=		TARGET = lint
-
-.KEEP_STATE:
-
-all clean clobber install lint: $(SUBDIRS)
-
-install_h:	$(ROOTHDRS)
-
-check:		$(CHECKHDRS)
-
-$(POFILE):	pofile_MSGFILES
-
-_msg:		$(MSGDOMAINPOFILE)
-
-$(SUBDIRS): FRC
-	@cd $@; pwd; $(MAKE) $(TARGET)
-
-FRC:
-
-include $(SRC)/Makefile.msg.targ
-include $(SRC)/lib/Makefile.targ
--- a/usr/src/lib/libinetcfg/Makefile.com	Mon Jun 07 10:04:00 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-#
-# 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 2010 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-
-LIBRARY = libinetcfg.a
-VERS    = .1
-OBJECTS = inetcfg.o
-
-include ../../Makefile.lib
-
-# install this library in the root filesystem
-include ../../Makefile.rootfs
-
-LIBS =		$(DYNLIB) $(LINTLIB)
-
-LDLIBS +=	-lc -lnsl -lsocket -ldladm -ldlpi -linetutil
-
-SRCDIR =	../common
-$(LINTLIB) :=	SRCS = $(SRCDIR)/$(LINTSRC)
-
-CFLAGS +=	$(CCVERBOSE)
-CPPFLAGS +=	-I$(SRCDIR) -D_REENTRANT
-
-.KEEP_STATE:
-
-all:		$(LIBS)
-
-lint:		lintcheck
-
-include $(SRC)/lib/Makefile.targ
--- a/usr/src/lib/libinetcfg/common/inetcfg.c	Mon Jun 07 10:04:00 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2259 +0,0 @@
-/*
- * 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 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stropts.h>
-#include <sys/sockio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/varargs.h>
-#include <net/route.h>
-#include <netinet/in.h>
-#include <inet/ip.h>
-#include <arpa/inet.h>
-#include <libintl.h>
-#include <libdladm.h>
-#include <libdllink.h>
-#include <libdlpi.h>
-#include <libinetutil.h>
-#include <zone.h>
-
-#include <inetcfg.h>
-
-#define	ICFG_SOCKADDR_LEN(protocol) \
-	(protocol == AF_INET) ? \
-	    (socklen_t)sizeof (struct sockaddr_in) : \
-	    (socklen_t)sizeof (struct sockaddr_in6)
-
-#define	ICFG_LOGICAL_SEP	':'
-#define	LOOPBACK_IF		"lo0"
-#define	ARP_MOD_NAME		"arp"
-
-/*
- * Maximum amount of time (in milliseconds) to wait for Duplicate Address
- * Detection to complete in the kernel.
- */
-#define	DAD_WAIT_TIME	5000
-
-/* error codes and text descriiption */
-static struct icfg_error_info {
-	icfg_error_t	error_code;
-	const char	*error_desc;
-} icfg_errors[] = {
-	{ ICFG_SUCCESS,		"No error occurred" },
-	{ ICFG_FAILURE,		"Generic failure" },
-	{ ICFG_NO_MEMORY,	"Insufficient memory" },
-	{ ICFG_NOT_TUNNEL,	"Tunnel operation attempted on non-tunnel" },
-	{ ICFG_NOT_SET,		"Could not return non-existent value" },
-	{ ICFG_BAD_ADDR,	"Invalid address" },
-	{ ICFG_BAD_PROTOCOL,	"Wrong protocol family for operation" },
-	{ ICFG_DAD_FAILED,	"Duplicate address detection failure" },
-	{ ICFG_DAD_FOUND,	"Duplicate address detected" },
-	{ ICFG_IF_UP,		"Interface is up" },
-	{ ICFG_EXISTS,		"Interface already exists" },
-	{ ICFG_NO_EXIST,	"Interface does not exist" },
-	{ ICFG_INVALID_ARG,	"Invalid argument" },
-	{ ICFG_INVALID_NAME,	"Invalid name" },
-	{ ICFG_DLPI_INVALID_LINK, "Link does not exist" },
-	{ ICFG_DLPI_FAILURE,	"DLPI error" },
-	{ ICFG_NO_PLUMB_IP,	"Could not plumb IP stream" },
-	{ ICFG_NO_PLUMB_ARP,	"Could not plumb ARP stream" },
-	{ ICFG_NO_UNPLUMB_IP,	"Could not unplumb IP stream" },
-	{ ICFG_NO_UNPLUMB_ARP,	"Could not unplumb ARP stream" },
-	{ ICFG_NO_IP_MUX,	"No IP mux set" },
-	{ 0,			NULL }
-};
-
-/* convert libdlpi error to libinetcfg error */
-icfg_error_t
-dlpi_error_to_icfg_error(int err)
-{
-	switch (err) {
-	case DLPI_SUCCESS:
-		return (ICFG_SUCCESS);
-	case DLPI_ELINKNAMEINVAL:
-		return (ICFG_INVALID_NAME);
-	case DLPI_ENOLINK:
-	case DLPI_EBADLINK:
-		return (ICFG_DLPI_INVALID_LINK);
-	case DLPI_EINVAL:
-	case DLPI_ENOTSTYLE2:
-	case DLPI_EBADMSG:
-	case DLPI_EINHANDLE:
-	case DLPI_EVERNOTSUP:
-	case DLPI_EMODENOTSUP:
-		return (ICFG_INVALID_ARG);
-	case DL_BADADDR:
-		return (ICFG_BAD_ADDR);
-	case DL_SYSERR:
-		switch (errno) {
-		case ENOMEM:
-			return (ICFG_NO_MEMORY);
-		case EINVAL:
-			return (ICFG_INVALID_ARG);
-		}
-		/* FALLTHROUGH */
-	case DLPI_FAILURE:
-	default:
-		return (ICFG_DLPI_FAILURE);
-	}
-}
-
-/*
- * Copies an an IPv4 or IPv6 address from a sockaddr_storage
- * structure into the appropriate sockaddr structure for the
- * address family (sockaddr_in for AF_INET or sockaddr_in6 for
- * AF_INET6) and verifies that the structure size is large enough
- * for the copy.
- *
- * Returns: ICFG_SUCCESS or ICFG_FAILURE.
- */
-static int
-to_sockaddr(sa_family_t af, struct sockaddr *addr,
-    socklen_t *addrlen, const struct sockaddr_storage *ssaddr)
-{
-	socklen_t len;
-
-	assert((af == AF_INET) || (af == AF_INET6));
-
-	len = ICFG_SOCKADDR_LEN(af);
-	if (*addrlen < len) {
-		errno = ENOSPC;
-		return (ICFG_FAILURE);
-	}
-
-	(void) memcpy(addr, ssaddr, len);
-	*addrlen = len;
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Copies an an IPv4 or IPv6 address frrom its sockaddr structure
- * into a sockaddr_storage structure and does a simple size of
- * structure verification.
- *
- * Returns: ICFG_SUCCESS or ICFG_FAILURE.
- */
-static int
-to_sockaddr_storage(sa_family_t af, const struct sockaddr *addr,
-    socklen_t addrlen, struct sockaddr_storage *ssaddr)
-{
-	socklen_t len;
-
-	assert((af == AF_INET) || (af == AF_INET6));
-
-	len = ICFG_SOCKADDR_LEN(af);
-	if (addrlen < len) {
-		errno = EINVAL;
-		return (ICFG_FAILURE);
-	}
-
-	(void) memcpy(ssaddr, addr, len);
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Return the appropriate error message for a given ICFG error.
- */
-const char *
-icfg_errmsg(int errcode)
-{
-	int i;
-
-	for (i = 0; icfg_errors[i].error_desc != NULL; i++) {
-		if (errcode == icfg_errors[i].error_code)
-			return (dgettext(TEXT_DOMAIN,
-			    icfg_errors[i].error_desc));
-	}
-
-	return (dgettext(TEXT_DOMAIN, "<unknown error>"));
-}
-
-/*
- * Opens the an interface as defined by the interface argument and returns
- * a handle to the interface via the 'handle' argument. The caller is
- * responsible for freeing resources allocated by this API by calling the
- * icfg_close() API.
- *
- * Returns: ICFG_SUCCESS, ICFG_NO_MEMORY or ICFG_FAILURE.
- */
-int
-icfg_open(icfg_handle_t *handle, const icfg_if_t *interface)
-{
-	icfg_handle_t loc_handle;
-	int sock;
-	sa_family_t family;
-	int syserr;
-
-	/*
-	 * Make sure that a valid protocol family was specified.
-	 */
-	if ((interface->if_protocol != AF_INET) &&
-	    (interface->if_protocol != AF_INET6)) {
-		errno = EINVAL;
-		return (ICFG_FAILURE);
-	}
-
-	family = interface->if_protocol;
-
-	if ((loc_handle = calloc(1, sizeof (struct icfg_handle))) == NULL) {
-		return (ICFG_NO_MEMORY);
-	}
-
-	if ((sock = socket(family, SOCK_DGRAM, 0)) < 0) {
-		syserr = errno;
-		free(loc_handle);
-		errno = syserr;
-		return (ICFG_FAILURE);
-	}
-
-	loc_handle->ifh_sock = sock;
-	loc_handle->ifh_interface = *interface;
-
-	*handle = loc_handle;
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Closes the interface opened by icfg_open() and releases all resources
- * associated with the handle.
- */
-void
-icfg_close(icfg_handle_t handle)
-{
-	(void) close(handle->ifh_sock);
-	free(handle);
-}
-
-/*
- * Retrieves the interface name associated with the handle passed in.
- */
-const char *
-icfg_if_name(icfg_handle_t handle)
-{
-	return (handle->ifh_interface.if_name);
-}
-
-/*
- * Retrieves the protocol associated with the handle passed in.
- */
-static int
-icfg_if_protocol(icfg_handle_t handle)
-{
-	return (handle->ifh_interface.if_protocol);
-}
-
-/*
- * Any time that flags are changed on an interface where either the new or the
- * existing flags have IFF_UP set, we'll get at least one RTM_IFINFO message to
- * announce the flag status.  Typically, there are two such messages: one
- * saying that the interface is going down, and another saying that it's coming
- * back up.
- *
- * We wait here for that second message, which can take one of two forms:
- * either IFF_UP or IFF_DUPLICATE.  If something's amiss with the kernel,
- * though, we don't wait forever.  (Note that IFF_DUPLICATE is a high-order
- * bit, and we can't see it in the routing socket messages.)
- */
-static int
-dad_wait(icfg_handle_t handle, int rtsock)
-{
-	struct pollfd fds[1];
-	union {
-		struct if_msghdr ifm;
-		char buf[1024];
-	} msg;
-	int index;
-	int retv;
-	uint64_t flags;
-	hrtime_t starttime, now;
-
-	fds[0].fd = rtsock;
-	fds[0].events = POLLIN;
-	fds[0].revents = 0;
-
-	if ((retv = icfg_get_index(handle, &index)) != ICFG_SUCCESS)
-		return (retv);
-
-	starttime = gethrtime();
-	for (;;) {
-		now = gethrtime();
-		now = (now - starttime) / 1000000;
-		if (now >= DAD_WAIT_TIME)
-			break;
-		if (poll(fds, 1, DAD_WAIT_TIME - (int)now) <= 0)
-			break;
-		if (read(rtsock, &msg, sizeof (msg)) <= 0)
-			break;
-		if (msg.ifm.ifm_type != RTM_IFINFO)
-			continue;
-		/* Note that ifm_index is just 16 bits */
-		if (index == msg.ifm.ifm_index && (msg.ifm.ifm_flags & IFF_UP))
-			return (ICFG_SUCCESS);
-		if ((retv = icfg_get_flags(handle, &flags)) != ICFG_SUCCESS)
-			return (retv);
-		if (flags & IFF_DUPLICATE)
-			return (ICFG_DAD_FOUND);
-	}
-	return (ICFG_DAD_FAILED);
-}
-
-/*
- * Sets the flags for the interface represented by the 'handle'
- * argument to the value contained in the 'flags' argument.
- *
- * If the new flags value will transition the interface from "down" to "up,"
- * then duplicate address detection is performed by the kernel.  This routine
- * waits to get the outcome of that test.
- *
- * Returns: ICFG_SUCCESS, ICFG_DAD_FOUND, ICFG_DAD_FAILED or ICFG_FAILURE.
- */
-int
-icfg_set_flags(icfg_handle_t handle, uint64_t flags)
-{
-	struct lifreq lifr;
-	uint64_t oflags;
-	int ret;
-	int rtsock = -1;
-	int aware = RTAW_UNDER_IPMP;
-
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = icfg_if_protocol(handle);
-
-	if ((ret = icfg_get_flags(handle, &oflags)) != ICFG_SUCCESS)
-		return (ret);
-	if (oflags == flags)
-		return (ICFG_SUCCESS);
-
-	/*
-	 * 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."  Since we may be
-	 * changing an IPMP test address, we enable RTAW_UNDER_IPMP.
-	 */
-	if (flags & IFF_UP) {
-		rtsock = socket(PF_ROUTE, SOCK_RAW, icfg_if_protocol(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) {
-		if (rtsock != -1)
-			(void) close(rtsock);
-		return (ICFG_FAILURE);
-	}
-
-	if (rtsock == -1) {
-		return (ICFG_SUCCESS);
-	} else {
-		ret = dad_wait(handle, rtsock);
-		(void) close(rtsock);
-		return (ret);
-	}
-}
-
-/*
- * Sets the metric value for the interface represented by the
- * 'handle' argument to the value contained in the 'metric'
- *  argument.
- *
- * Returns: ICFG_SUCCESS or ICFG_FAILURE.
- */
-int
-icfg_set_metric(icfg_handle_t handle, int metric)
-{
-	struct lifreq lifr;
-
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = icfg_if_protocol(handle);
-	lifr.lifr_metric = metric;
-
-	if (ioctl(handle->ifh_sock, SIOCSLIFMETRIC, (caddr_t)&lifr) < 0) {
-		return (ICFG_FAILURE);
-	}
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Sets the mtu value for the interface represented by the
- * 'handle' argument to the value contained in the 'mtu'
- * argument.
- *
- * Returns: ICFG_SUCCESS or ICFG_FAILURE.
- */
-int
-icfg_set_mtu(icfg_handle_t handle, uint_t mtu)
-{
-	struct lifreq lifr;
-
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = icfg_if_protocol(handle);
-	lifr.lifr_mtu = mtu;
-
-	if (ioctl(handle->ifh_sock, SIOCSLIFMTU, (caddr_t)&lifr) < 0) {
-		return (ICFG_FAILURE);
-	}
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Sets the index value for the interface represented by the
- * 'handle' argument to the value contained in the 'index'
- * argument.
- *
- * Returns: ICFG_SUCCESS or ICFG_FAILURE.
- */
-int
-icfg_set_index(icfg_handle_t handle, int index)
-{
-	struct lifreq lifr;
-
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = icfg_if_protocol(handle);
-	lifr.lifr_index = index;
-
-	if (ioctl(handle->ifh_sock, SIOCSLIFINDEX, (caddr_t)&lifr) < 0) {
-		return (ICFG_FAILURE);
-	}
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Sets the netmask address for the interface represented by
- * 'handle'.
- *
- * The handle must represent an IPv4 interface.
- *
- * The address will be set to the value pointed to by 'addr'.
- *
- * Returns: ICFG_SUCCESS, ICFG_BAD_PROTOCOL or ICFG_FAILURE.
- */
-int
-icfg_set_netmask(icfg_handle_t handle, const struct sockaddr_in *addr)
-{
-	struct lifreq lifr;
-	int ret;
-
-	if (icfg_if_protocol(handle) != AF_INET) {
-		return (ICFG_BAD_PROTOCOL);
-	}
-
-	(void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
-	if ((ret = to_sockaddr_storage(icfg_if_protocol(handle),
-	    (struct sockaddr *)addr, sizeof (*addr),
-	    &lifr.lifr_addr)) != ICFG_SUCCESS) {
-		return (ret);
-	}
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = AF_INET;
-
-	if (ioctl(handle->ifh_sock, SIOCSLIFNETMASK, (caddr_t)&lifr) < 0) {
-		return (ICFG_FAILURE);
-	}
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Sets the broadcast address for the interface represented by
- * 'handle'.
- *
- * The handle must represent an IPv4 interface.
- *
- * The address will be set to the value pointed to by 'addr'.
- *
- * Returns: ICFG_SUCCESS, ICFG_BAD_PROTOCOL or ICFG_FAILURE.
- */
-int
-icfg_set_broadcast(icfg_handle_t handle, const struct sockaddr_in *addr)
-{
-	struct lifreq lifr;
-	int ret;
-
-	if (icfg_if_protocol(handle) != AF_INET) {
-		return (ICFG_BAD_PROTOCOL);
-	}
-
-	(void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
-	if ((ret = to_sockaddr_storage(icfg_if_protocol(handle),
-	    (struct sockaddr *)addr, sizeof (*addr),
-	    &lifr.lifr_addr)) != ICFG_SUCCESS) {
-		return (ret);
-	}
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = AF_INET;
-
-	if (ioctl(handle->ifh_sock, SIOCSLIFBRDADDR, (caddr_t)&lifr) < 0) {
-		return (ICFG_FAILURE);
-	}
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Sets the prefixlen value for the interface represented by the handle
- * argument to the value contained in the 'prefixlen' argument. The
- * prefixlen is actually stored internally as a netmask value and the API
- * will convert the value contained in 'prefixlen' into the correct netmask
- * value according to the protocol family of the interface.
- *
- * Returns: ICFG_SUCCESS or ICFG_FAILURE.
- */
-int
-icfg_set_prefixlen(icfg_handle_t handle, int prefixlen)
-{
-	struct lifreq lifr;
-
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-
-	if (plen2mask(prefixlen, icfg_if_protocol(handle),
-	    &lifr.lifr_addr) != 0) {
-		return (ICFG_FAILURE);
-	}
-
-	if (ioctl(handle->ifh_sock, SIOCSLIFNETMASK, (caddr_t)&lifr) < 0)
-		return (ICFG_FAILURE);
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Sets the address for the interface represented by 'handle'.
- *
- * The 'addr' argument points to either a sockaddr_in structure
- * (for IPv4) or a sockaddr_in6 structure (for IPv6) that holds
- * the IP address. The 'addrlen' argument gives the length of the
- * 'addr' structure.
- *
- * If the interface is an IPv6 interface and the interface is
- * already in the "up" state, then duplicate address detection
- * is performed before the address is set and is set only if no
- * duplicate address is detected.
- *
- * Returns: ICFG_SUCCESS, ICFG_FAILURE, ICFG_DAD_FOUND, ICFG_DAD_FAILED
- *          or ICFG_FAILURE.
- */
-int
-icfg_set_addr(icfg_handle_t handle, const struct sockaddr *addr,
-    socklen_t addrlen)
-{
-	struct lifreq lifr;
-	uint64_t flags;
-	int ret;
-	int rtsock = -1;
-	int aware = RTAW_UNDER_IPMP;
-
-	(void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
-	if ((ret = to_sockaddr_storage(icfg_if_protocol(handle), addr, addrlen,
-	    &lifr.lifr_addr)) != ICFG_SUCCESS) {
-		return (ret);
-	}
-
-	/*
-	 * 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)
-		return (ret);
-
-	if (flags & IFF_UP) {
-		rtsock = socket(PF_ROUTE, SOCK_RAW, icfg_if_protocol(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));
-	lifr.lifr_addr.ss_family = icfg_if_protocol(handle);
-
-	if (ioctl(handle->ifh_sock, SIOCSLIFADDR, (caddr_t)&lifr) < 0) {
-		if (rtsock != -1)
-			(void) close(rtsock);
-		return (ICFG_FAILURE);
-	}
-
-	if (rtsock == -1) {
-		return (ICFG_SUCCESS);
-	} else {
-		ret = dad_wait(handle, rtsock);
-		(void) close(rtsock);
-		return (ret);
-	}
-}
-
-/*
- * Sets the token for the interface represented by 'handle'.
- *
- * The handle must represent an IPv6 interface.
- *
- * The token will be set to the value contained in 'addr' and
- * its associated prefixlen will be set to 'prefixlen'.
- *
- * Returns: ICFG_SUCCESS, ICFG_BAD_PROTOCOL or ICFG_FAILURE.
- */
-int
-icfg_set_token(icfg_handle_t handle, const struct sockaddr_in6 *addr,
-    int prefixlen)
-{
-	struct lifreq lifr;
-	int ret;
-
-	if (icfg_if_protocol(handle) != AF_INET6) {
-		return (ICFG_BAD_PROTOCOL);
-	}
-
-	(void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
-	if ((ret = to_sockaddr_storage(icfg_if_protocol(handle),
-	    (struct sockaddr *)addr, sizeof (*addr),
-	    &lifr.lifr_addr)) != ICFG_SUCCESS) {
-		return (ret);
-	}
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = icfg_if_protocol(handle);
-	lifr.lifr_addrlen = prefixlen;
-
-	if (ioctl(handle->ifh_sock, SIOCSLIFTOKEN, (caddr_t)&lifr) < 0) {
-		return (ICFG_FAILURE);
-	}
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Sets the subnet address for the interface represented by 'handle'.
- *
- * The 'addr' argument points to either a sockaddr_in structure
- * (for IPv4) or a sockaddr_in6 structure (for IPv6) that holds
- * the IP address. The 'addrlen' argument gives the length of the
- * 'addr' structure.
- *
- * The prefixlen of the subnet address will be set to 'prefixlen'.
- *
- * Returns: ICFG_SUCCESS or ICFG_FAILURE.
- */
-int
-icfg_set_subnet(icfg_handle_t handle, const struct sockaddr *addr,
-    socklen_t addrlen, int prefixlen)
-{
-	struct lifreq lifr;
-	int ret;
-
-	(void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = icfg_if_protocol(handle);
-
-	if ((ret = to_sockaddr_storage(icfg_if_protocol(handle), addr, addrlen,
-	    &lifr.lifr_addr)) != ICFG_SUCCESS) {
-		return (ret);
-	}
-	lifr.lifr_addrlen = prefixlen;
-
-	if (ioctl(handle->ifh_sock, SIOCSLIFSUBNET, (caddr_t)&lifr) < 0) {
-		return (ICFG_FAILURE);
-	}
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Sets the destination address for the interface represented by
- * 'handle'.
- *
- * The 'addr' argument points to either a sockaddr_in structure
- * (for IPv4) or a sockaddr_in6 structure (for IPv6) that holds
- * the IP address. The 'addrlen' argument gives the length of the
- * 'addr' structure.
- *
- * Returns: ICFG_SUCCESS or ICFG_FAILURE.
- */
-int
-icfg_set_dest_addr(icfg_handle_t handle, const struct sockaddr *addr,
-    socklen_t addrlen)
-{
-	struct lifreq lifr;
-	int ret;
-
-	(void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = icfg_if_protocol(handle);
-
-	if ((ret = to_sockaddr_storage(icfg_if_protocol(handle), addr, addrlen,
-	    &lifr.lifr_addr)) != ICFG_SUCCESS) {
-		return (ret);
-	}
-
-	if (ioctl(handle->ifh_sock, SIOCSLIFDSTADDR, (caddr_t)&lifr) < 0) {
-		return (ICFG_FAILURE);
-	}
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Returns the address and prefixlen of the interface represented
- * by 'handle'.
- *
- * The 'addr' argument is a result parameter that is filled in with
- * the requested address. The format of the 'addr' parameter is
- * determined by the address family of the interface.
- *
- * The 'addrlen' argument is a value-result parameter. Initially, it
- * contains the amount of space pointed to by 'addr'; on return it
- * contains the length in bytes of the address returned.
- *
- * Note that if 'addrlen' is not large enough for the returned address
- * value, then ICFG_FAILURE will be returned and errno will be set to ENOSPC.
- *
- * If the 'force' argument is set to B_TRUE, then non-critical errors in
- * obtaining the address will be ignored and the address will be set to
- * all 0's. Non-critical errors consist of EADDRNOTAVAIL, EAFNOSUPPORT,
- * and ENXIO.
- *
- * Returns: ICFG_SUCCESS or ICFG_FAILURE.
- */
-int
-icfg_get_addr(icfg_handle_t handle, struct sockaddr *addr, socklen_t *addrlen,
-    int *prefixlen, boolean_t force)
-{
-	struct lifreq lifr;
-	int ret;
-
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = icfg_if_protocol(handle);
-
-	if (ioctl(handle->ifh_sock, SIOCGLIFADDR, (caddr_t)&lifr) < 0) {
-		if (force && ((errno == EADDRNOTAVAIL) ||
-		    (errno == EAFNOSUPPORT) || (errno == ENXIO))) {
-			(void) memset(&lifr.lifr_addr, 0,
-			    sizeof (lifr.lifr_addr));
-		} else {
-			return (ICFG_FAILURE);
-		}
-	}
-
-	if ((ret = to_sockaddr(icfg_if_protocol(handle), addr, addrlen,
-	    &lifr.lifr_addr)) != ICFG_SUCCESS) {
-		return (ret);
-	}
-	*prefixlen = lifr.lifr_addrlen;
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Returns the token address and the token prefixlen of the
- * interface represented by 'handle'.
- *
- * The 'addr' argument is a result parameter that is filled in
- * with the requested address.
- *
- * The 'prefixlen' argument is a result paramter that is filled
- * in with the token prefixlen.
- *
- * If the 'force' argument is set to B_TRUE, then non-critical errors in
- * obtaining the token address will be ignored and the address will be set
- * to all 0's. Non-critical errors consist of EADDRNOTAVAIL and EINVAL.
- *
- * Returns: ICFG_SUCCESS, ICFG_BAD_PROTOCOL or ICFG_FAILURE.
- */
-int
-icfg_get_token(icfg_handle_t handle, struct sockaddr_in6 *addr,
-    int *prefixlen, boolean_t force)
-{
-	struct lifreq lifr;
-	socklen_t addrlen = sizeof (*addr);
-
-	if (icfg_if_protocol(handle) != AF_INET6) {
-		return (ICFG_BAD_PROTOCOL);
-	}
-
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = icfg_if_protocol(handle);
-
-	if (ioctl(handle->ifh_sock, SIOCGLIFTOKEN, (caddr_t)&lifr) < 0) {
-		if (force && ((errno == EADDRNOTAVAIL) || (errno == EINVAL))) {
-			(void) memset(&lifr.lifr_addr, 0,
-			    sizeof (lifr.lifr_addr));
-		} else {
-			return (ICFG_FAILURE);
-		}
-	}
-
-	*prefixlen = lifr.lifr_addrlen;
-	return (to_sockaddr(icfg_if_protocol(handle), (struct sockaddr *)addr,
-	    &addrlen, &lifr.lifr_addr));
-}
-
-/*
- * Returns the subnet address and the subnet prefixlen of the interface
- * represented by 'handle'.
- *
- * The 'addr' argument is a result parameter that is filled in with
- * the requested address. The format of the 'addr' parameter is
- * determined by the address family of the interface.
- *
- * The 'addrlen' argument is a value-result parameter. Initially, it
- * contains the amount of space pointed to by 'addr'; on return it
- * contains the length in bytes of the address returned.
- *
- * Note that if 'addrlen' is not large enough for the returned address
- * value, then ICFG_FAILURE will be returned and errno will be set to ENOSPC.
- *
- * If the 'force' argument is set to B_TRUE, then non-critical errors in
- * obtaining the address will be ignored and the address will be set to all
- * 0's. Non-critical errors consist of EADDRNOTAVAIL, EAFNOSUPPORT,and ENXIO.
- *
- * Returns: ICFG_SUCCESS or ICFG_FAILURE.
- */
-int
-icfg_get_subnet(icfg_handle_t handle, struct sockaddr *addr,
-    socklen_t *addrlen, int *prefixlen, boolean_t force)
-{
-	struct lifreq lifr;
-	int ret;
-
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = icfg_if_protocol(handle);
-
-	if (ioctl(handle->ifh_sock, SIOCGLIFSUBNET, (caddr_t)&lifr) < 0) {
-		if (force && ((errno == EADDRNOTAVAIL) ||
-		    (errno == EAFNOSUPPORT) || (errno == ENXIO))) {
-			(void) memset(&lifr.lifr_addr, 0,
-			    sizeof (lifr.lifr_addr));
-		} else {
-			return (ICFG_FAILURE);
-		}
-	}
-
-	if ((ret = to_sockaddr(icfg_if_protocol(handle), addr, addrlen,
-	    &lifr.lifr_addr)) != ICFG_SUCCESS) {
-		return (ret);
-	}
-	*prefixlen = lifr.lifr_addrlen;
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Returns the netmask address of the interface represented by 'handle'.
- *
- * The handle must represent an IPv4 interface.
- *
- * The 'addr' argument is a result parameter that is filled in with
- * the requested address.
- *
- * If no netmask address has been set for the interface, an address of
- * all 0's will be returned.
- *
- * Returns: ICFG_SUCCESS, ICFG_BAD_PROTOCOL or ICFG_FAILURE.
- */
-int
-icfg_get_netmask(icfg_handle_t handle, struct sockaddr_in *addr)
-{
-	struct lifreq lifr;
-	socklen_t addrlen = sizeof (*addr);
-
-	if (icfg_if_protocol(handle) != AF_INET) {
-		return (ICFG_BAD_PROTOCOL);
-	}
-
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = icfg_if_protocol(handle);
-
-	if (ioctl(handle->ifh_sock, SIOCGLIFNETMASK, (caddr_t)&lifr) < 0) {
-		if (errno != EADDRNOTAVAIL) {
-			return (ICFG_FAILURE);
-		}
-		(void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
-	}
-
-	return (to_sockaddr(icfg_if_protocol(handle), (struct sockaddr *)addr,
-	    &addrlen, &lifr.lifr_addr));
-}
-
-/*
- * Returns the broadcast address of the interface represented by 'handle'.
- *
- * The handle must represent an IPv4 interface.
- *
- * The 'addr' argument is a result parameter that is filled in with
- * the requested address.
- *
- * If no broadcast address has been set for the interface, an address
- * of all 0's will be returned.
- *
- * Returns: ICFG_SUCCESS, ICFG_BAD_PROTOCOL or ICFG_FAILURE.
- */
-int
-icfg_get_broadcast(icfg_handle_t handle, struct sockaddr_in *addr)
-{
-	struct lifreq lifr;
-	socklen_t addrlen = sizeof (*addr);
-
-	if (icfg_if_protocol(handle) != AF_INET) {
-		return (ICFG_BAD_PROTOCOL);
-	}
-
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = icfg_if_protocol(handle);
-
-	if (ioctl(handle->ifh_sock, SIOCGLIFBRDADDR, (caddr_t)&lifr) < 0) {
-		if (errno != EADDRNOTAVAIL) {
-			return (ICFG_FAILURE);
-		}
-		(void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
-	}
-
-	return (to_sockaddr(icfg_if_protocol(handle), (struct sockaddr *)addr,
-	    &addrlen, &lifr.lifr_addr));
-}
-
-/*
- * Returns the destination address of the interface represented
- * by 'handle'.
- *
- * The 'addr' argument is a result parameter that is filled in with
- * the requested address. The format of the 'addr' parameter is
- * determined by the address family of the interface.
- *
- * The 'addrlen' argument is a value-result parameter. Initially, it
- * contains the amount of space pointed to by 'addr'; on return it
- * contains the length in bytes of the address returned.
- *
- * Note that if 'addrlen' is not large enough for the returned address
- * value, then ICFG_FAILURE will be returned and errno will be set to
- * ENOSPC.
- *
- * If no destination address has been set for the interface, an address
- * of all 0's will be returned.
- *
- * Returns: ICFG_SUCCESS or ICFG_FAILURE.
- */
-int
-icfg_get_dest_addr(icfg_handle_t handle, struct sockaddr *addr,
-    socklen_t *addrlen)
-{
-	struct lifreq lifr;
-
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = icfg_if_protocol(handle);
-
-	if (ioctl(handle->ifh_sock, SIOCGLIFDSTADDR, (caddr_t)&lifr) < 0) {
-		if (errno != EADDRNOTAVAIL) {
-			return (ICFG_FAILURE);
-		}
-		/* No destination address set yet */
-		(void) memset(&lifr.lifr_dstaddr, 0,
-		    sizeof (lifr.lifr_dstaddr));
-	}
-
-	return (to_sockaddr(icfg_if_protocol(handle), addr, addrlen,
-	    &lifr.lifr_addr));
-}
-
-/*
- * Returns the groupname, if any, of the interface represented by the handle
- * argument into the buffer pointed to by the 'groupname' argument. The size
- * of the groupname buffer is expected to be of 'len' bytes in length and
- * should be large enough to receive the groupname of the interface
- * (i.e., LIFNAMSIZ).
- *
- * Returns: ICFG_SUCCESS, ICFG_NOT_SET or ICFG_FAILURE.
- */
-int
-icfg_get_groupname(icfg_handle_t handle, char *groupname, size_t len)
-{
-	struct lifreq lifr;
-
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = icfg_if_protocol(handle);
-
-	(void) memset(lifr.lifr_groupname, 0, sizeof (lifr.lifr_groupname));
-
-	if (ioctl(handle->ifh_sock, SIOCGLIFGROUPNAME, (caddr_t)&lifr) < 0) {
-		return (ICFG_FAILURE);
-	}
-
-	if (strlen(lifr.lifr_groupname) > 0) {
-		(void) strlcpy(groupname, lifr.lifr_groupname, len);
-	} else {
-		return (ICFG_NOT_SET);
-	}
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Returns the groupinfo, if any, associated with the group identified in
- * the gi_grname field of the passed-in lifgr structure.  Upon successful
- * return, the lifgr structure will be populated with the associated
- * group info.
- *
- * Returns: ICFG_SUCCESS or ICFG_FAILURE.
- */
-static int
-icfg_get_groupinfo(icfg_handle_t handle, lifgroupinfo_t *lifgr)
-{
-	if (ioctl(handle->ifh_sock, SIOCGLIFGROUPINFO, lifgr) < 0)
-		return (ICFG_FAILURE);
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Returns the flags value of the interface represented by the handle
- * argument into the buffer pointed to by the 'flags' argument.
- *
- * Returns: ICFG_SUCCESS, ICFG_NO_EXIST or ICFG_FAILURE.
- */
-int
-icfg_get_flags(icfg_handle_t handle, uint64_t *flags)
-{
-	struct lifreq lifr;
-
-	if (flags == NULL)
-		return (ICFG_INVALID_ARG);
-
-	(void) memset(&lifr, 0, sizeof (lifr));
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = icfg_if_protocol(handle);
-
-	if (ioctl(handle->ifh_sock, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
-		if (errno == ENXIO)
-			return (ICFG_NO_EXIST);
-		else
-			return (ICFG_FAILURE);
-	}
-	*flags = lifr.lifr_flags;
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Returns the metric value of the interface represented by the handle
- * argument into the buffer pointed to by the 'metric' argument.
- *
- * Returns: ICFG_SUCCESS or ICFG_FAILURE.
- */
-int
-icfg_get_metric(icfg_handle_t handle, int *metric)
-{
-	struct lifreq lifr;
-
-	if (metric == NULL)
-		return (ICFG_INVALID_ARG);
-
-	(void) memset(&lifr, 0, sizeof (lifr));
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = icfg_if_protocol(handle);
-
-	if (ioctl(handle->ifh_sock, SIOCGLIFMETRIC, (caddr_t)&lifr) < 0) {
-		return (ICFG_FAILURE);
-	}
-	*metric = lifr.lifr_metric;
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Returns the mtu value of the interface represented by the handle
- * argument into the buffer pointed to by the 'mtu' argument.
- *
- * Returns: ICFG_SUCCESS or ICFG_FAILURE.
- */
-int
-icfg_get_mtu(icfg_handle_t handle, uint_t *mtu)
-{
-	struct lifreq lifr;
-
-	if (mtu == NULL)
-		return (ICFG_INVALID_ARG);
-
-	(void) memset(&lifr, 0, sizeof (lifr));
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = icfg_if_protocol(handle);
-
-	if (ioctl(handle->ifh_sock, SIOCGLIFMTU, (caddr_t)&lifr) < 0) {
-		return (ICFG_FAILURE);
-	}
-	*mtu = lifr.lifr_mtu;
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Returns the index value of the interface represented by the handle
- * argument into the buffer pointed to by the 'index' argument.
- *
- * Returns: ICFG_SUCCESS or ICFG_FAILURE.
- */
-int
-icfg_get_index(icfg_handle_t handle, int *index)
-{
-	struct lifreq lifr;
-
-	if (index == NULL)
-		return (ICFG_INVALID_ARG);
-
-	(void) memset(&lifr, 0, sizeof (lifr));
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	lifr.lifr_addr.ss_family = icfg_if_protocol(handle);
-
-	if (ioctl(handle->ifh_sock, SIOCGLIFINDEX, (caddr_t)&lifr) < 0) {
-		return (ICFG_FAILURE);
-	}
-	*index = lifr.lifr_index;
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Walks a list of interfaces and for  each  interface  found,  the
- * caller-supplied function 'callback()' is invoked. The iteration will be
- * interrupted if the caller-supplied function does not return  ICFG_SUCCESS.
- *
- * The 'proto' argument is used by the caller to define which interfaces are
- * to be walked by the API. The possible values for 'proto' are AF_INET,
- * AF_INET6, and AF_UNSPEC.
- *
- * The 'arg' argument is a pointer to caller-specific data.
- *
- * Returns: ICFG_SUCCESS, ICFG_FAILURE or error code returned by callback().
- */
-int
-icfg_iterate_if(int proto, int type, void *arg,
-    int (*callback)(icfg_if_t *interface, void *arg))
-{
-	icfg_if_t	*if_ids;
-	int		len;
-	int		i;
-	int		ret;
-
-	ret = icfg_get_if_list(&if_ids, &len, proto, type);
-	if (ret != ICFG_SUCCESS) {
-		return (ret);
-	}
-
-	for (i = 0; i < len; i++) {
-		if ((ret = callback(&if_ids[i], arg)) != ICFG_SUCCESS) {
-			break;
-		}
-	}
-
-	icfg_free_if_list(if_ids);
-
-	return (ret);
-
-}
-
-/*
- * Returns a list of currently plumbed interfaces. The list of interfaces is
- * returned as an array of icfg_if_t structures. The number of interfaces in
- * the array will be returned via the 'numif' argument. Since the array of
- * interfaces is allocated by this API, the caller is responsible for freeing
- * the memory associated with this array by calling icfg_free_if_list().
- *
- * The 'proto' argument is used by the caller to define which interfaces are
- * to be listed by the API. The possible values for proto are AF_INET,
- * AF_INET6, and AF_UNSPEC.
- *
- * Returns: ICFG_SUCCESS, ICFG_BAD_PROTOCOL, ICFG_NO_MEMORY or ICFG_FAILURE.
- */
-static int
-get_plumbed_if_list(icfg_if_t **list, int *numif, int proto) {
-	int sock;
-	struct lifconf lifc;
-	struct lifnum lifn;
-	struct lifreq *lifrp;
-	char *buf;
-	unsigned bufsize;
-	icfg_if_t *loc_list;
-	int num;
-	sa_family_t lifc_family;
-	int lifc_flags = LIFC_NOXMIT;
-	int syserr;
-	int i;
-
-	/*
-	 * Validate the protocol family.
-	 */
-	if ((proto != AF_UNSPEC) &&
-	    (proto != AF_INET) &&
-	    (proto != AF_INET6)) {
-		errno = EINVAL;
-		return (ICFG_BAD_PROTOCOL);
-	}
-	lifc_family = proto;
-
-	/*
-	 * Open a socket. Note that the AF_INET domain seems to
-	 * support both IPv4 and IPv6.
-	 */
-	if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-		return (ICFG_FAILURE);
-	}
-
-	/*
-	 * Get the number of interfaces and allocate a buffer
-	 * large enough to allow the interfaces to be enumerated.
-	 */
-	lifn.lifn_family = lifc_family;
-	lifn.lifn_flags = lifc_flags;
-	if (ioctl(sock, SIOCGLIFNUM, (char *)&lifn) < 0) {
-		syserr = errno;
-		(void) close(sock);
-		errno = syserr;
-		return (ICFG_FAILURE);
-	}
-	num = lifn.lifn_count;
-	bufsize = num * sizeof (struct lifreq);
-	buf = malloc(bufsize);
-	if (buf == NULL) {
-		syserr = errno;
-		(void) close(sock);
-		errno = syserr;
-		return (ICFG_NO_MEMORY);
-	}
-
-	/*
-	 * Obtain a list of the interfaces.
-	 */
-	lifc.lifc_family = lifc_family;
-	lifc.lifc_flags = lifc_flags;
-	lifc.lifc_len = bufsize;
-	lifc.lifc_buf = buf;
-	if (ioctl(sock, SIOCGLIFCONF, (char *)&lifc) < 0) {
-		syserr = errno;
-		(void) close(sock);
-		free(buf);
-		errno = syserr;
-		return (ICFG_FAILURE);
-	}
-	(void) close(sock);
-
-	bufsize = num * sizeof (icfg_if_t);
-	loc_list = malloc(bufsize);
-	if (loc_list == NULL) {
-		syserr = errno;
-		free(buf);
-		errno = syserr;
-		return (ICFG_NO_MEMORY);
-	}
-
-	lifrp = lifc.lifc_req;
-	for (i = 0; i < num; i++, lifrp++) {
-		(void) strlcpy(loc_list[i].if_name, lifrp->lifr_name,
-		    sizeof (loc_list[i].if_name));
-		if (lifrp->lifr_addr.ss_family == AF_INET) {
-			loc_list[i].if_protocol = AF_INET;
-		} else {
-			loc_list[i].if_protocol = AF_INET6;
-		}
-	}
-
-	*list = loc_list;
-	*numif = num;
-
-	free(buf);
-
-	return (ICFG_SUCCESS);
-}
-
-typedef struct linklist {
-	struct linklist	*ll_next;
-	char		ll_name[DLPI_LINKNAME_MAX];
-} linklist_t;
-
-typedef struct linkwalk {
-	linklist_t	*lw_list;
-	int		lw_num;
-	int		lw_err;
-} linkwalk_t;
-
-static boolean_t
-add_link_list(const char *link, void *arg)
-{
-	linkwalk_t	*lwp = (linkwalk_t *)arg;
-	linklist_t	*entry = NULL;
-
-	if ((entry = calloc(1, sizeof (linklist_t))) == NULL) {
-		lwp->lw_err = ENOMEM;
-		return (B_TRUE);
-	}
-	(void) strlcpy(entry->ll_name, link, DLPI_LINKNAME_MAX);
-
-	if (lwp->lw_list == NULL)
-		lwp->lw_list = entry;
-	else
-		lwp->lw_list->ll_next = entry;
-
-	lwp->lw_num++;
-	return (B_FALSE);
-}
-
-/*
- * Returns a list of data links that can be plumbed. The list of interfaces is
- * returned as an array of icfg_if_t structures. The number of interfaces in
- * the array will be returned via the 'numif' argument.
- *
- * Returns: ICFG_SUCCESS, ICFG_NO_MEMORY or ICFG_FAILURE.
- */
-static int
-get_link_list(icfg_if_t **listp, int *numif) {
-
-	linkwalk_t	lw = {NULL, 0, 0};
-	linklist_t	*entry, *next;
-	icfg_if_t	*list;
-	int		save_errno = 0;
-	int		ret = ICFG_FAILURE;
-
-	dlpi_walk(add_link_list, &lw, 0);
-	if (lw.lw_err != 0) {
-		errno = lw.lw_err;
-		goto done;
-	}
-	if (lw.lw_num == 0) {
-		/* no links found, nothing else to do */
-		*listp = NULL;
-		*numif = 0;
-		return (ICFG_SUCCESS);
-	}
-
-	list = calloc(lw.lw_num, sizeof (icfg_if_t));
-	if (list == NULL) {
-		ret = ICFG_NO_MEMORY;
-		goto done;
-	}
-
-	*listp = list;
-	for (entry = lw.lw_list; entry != NULL; entry = entry->ll_next) {
-		(void) strlcpy(list->if_name, entry->ll_name,
-		    sizeof (list->if_name));
-		list->if_protocol = AF_UNSPEC;
-		list++;
-	}
-	*numif = lw.lw_num;
-	ret = ICFG_SUCCESS;
-
-done:
-	save_errno = errno;
-	for (entry = lw.lw_list; entry != NULL; entry = next) {
-		next = entry->ll_next;
-		free(entry);
-	}
-	errno = save_errno;
-	return (ret);
-}
-
-/*
- * Returns a list of network interfaces. The list of
- * interfaces is returned as an array of icfg_if_t structures.
- * The number of interfaces in the array will be returned via
- * the 'numif' argument. Since the array of interfaces is
- * allocated by this API, the caller is responsible for freeing
- * the memory associated with this array by calling
- * icfg_free_if_list().
- *
- * The 'proto' argument is used by the caller to define which
- * interfaces are to be listed by the API. The possible values
- * for 'proto' are AF_INET, AF_INET6, and AF_UNSPEC.
- *
- * The 'type' argument is used by the caller specify whether
- * to enumerate installed network interfaces or plumbed
- * network interfaces. The value for 'type' can be ICFG_PLUMBED
- * or ICFG_INSTALLED.
- */
-int
-icfg_get_if_list(icfg_if_t **list, int *numif, int proto, int type)
-{
-	if (list == NULL || numif == NULL)
-		return (ICFG_INVALID_ARG);
-
-	*list = NULL;
-	*numif = 0;
-
-	if (type == ICFG_PLUMBED) {
-		return (get_plumbed_if_list(list, numif, proto));
-	} else if (type == ICFG_INSTALLED) {
-		return (get_link_list(list, numif));
-	} else {
-		errno = EINVAL;
-		return (ICFG_FAILURE);
-	}
-}
-
-/*
- * Frees the memory allocated by icfg_get_list().
- */
-void
-icfg_free_if_list(icfg_if_t *list)
-{
-	free(list);
-	list = NULL;
-}
-
-/*
- * Determines whether or not an interface name represents
- * a logical interface or not.
- *
- * Returns: B_TRUE if logical, B_FALSE if not.
- *
- * Note: this API can be vastly improved once interface naming
- * is resolved in the future. This will do for now.
- */
-boolean_t
-icfg_is_logical(icfg_handle_t handle)
-{
-	return (strchr(icfg_if_name(handle), ICFG_LOGICAL_SEP)
-	    != NULL);
-}
-
-/*
- * Determines whether or not an interface name represents a loopback
- * interface or not.
- *
- * Returns: B_TRUE if loopback, B_FALSE if not.
- */
-static boolean_t
-icfg_is_loopback(icfg_handle_t handle)
-{
-	return (strcmp(icfg_if_name(handle), LOOPBACK_IF) == 0);
-}
-
-/*
- * Given a sockaddr representation of an IPv4 or IPv6 address returns the
- * string representation. Note that 'sockaddr' should point at the correct
- * sockaddr structure for the address family (sockaddr_in for AF_INET or
- * sockaddr_in6 for AF_INET6) or alternatively at a sockaddr_storage
- * structure.
- *
- * Returns: ICFG_SUCCESS or ICFG_FAILURE.
- */
-int
-icfg_sockaddr_to_str(sa_family_t af, const struct sockaddr *sockaddr,
-    char *straddr, size_t len)
-{
-	const void *addr = sockaddr;
-	struct sockaddr_in *sin;
-	struct sockaddr_in6 *sin6;
-	const char *str;
-	int ret = ICFG_FAILURE;
-
-	if (af == AF_INET) {
-		sin = (struct sockaddr_in *)addr;
-		str = inet_ntop(AF_INET, (void *)&sin->sin_addr, straddr, len);
-	} else if (af == AF_INET6) {
-		sin6 = (struct sockaddr_in6 *)addr;
-		str = inet_ntop(AF_INET6, (void *)&sin6->sin6_addr, straddr,
-		    len);
-	} else {
-		errno = EINVAL;
-		return (ICFG_FAILURE);
-	}
-
-	if (str != NULL) {
-		ret = ICFG_SUCCESS;
-	}
-
-	return (ret);
-}
-
-/*
- * Given a string representation of an IPv4 or IPv6 address returns the
- * sockaddr representation. Note that 'sockaddr' should point at the correct
- * sockaddr structure for the address family (sockaddr_in for AF_INET or
- * sockaddr_in6 for AF_INET6) or alternatively at a sockaddr_storage
- * structure.
- *
- * Returns: ICFG_SUCCESS, ICFG_BAD_ADDR or ICFG_FAILURE.
- */
-int
-icfg_str_to_sockaddr(sa_family_t af, const char *straddr,
-	struct sockaddr *sockaddr, socklen_t *addrlen)
-{
-	void *addr = sockaddr;
-	struct sockaddr_in *sin;
-	struct sockaddr_in6 *sin6;
-	int ret;
-	int err;
-
-	if (af == AF_INET) {
-		if (*addrlen < sizeof (*sin)) {
-			errno = ENOSPC;
-			return (ICFG_FAILURE);
-		}
-		*addrlen = sizeof (*sin);
-		sin = (struct sockaddr_in *)addr;
-		sin->sin_family = AF_INET;
-		err = inet_pton(AF_INET, straddr, &sin->sin_addr);
-	} else if (af == AF_INET6) {
-		if (*addrlen < sizeof (*sin6)) {
-			errno = ENOSPC;
-			return (ICFG_FAILURE);
-		}
-		*addrlen = sizeof (*sin6);
-		sin6 = (struct sockaddr_in6 *)addr;
-		sin6->sin6_family = AF_INET6;
-		err = inet_pton(AF_INET6, straddr, &sin6->sin6_addr);
-	} else {
-		errno = EINVAL;
-		return (ICFG_FAILURE);
-	}
-
-	if (err == 0) {
-		ret = ICFG_BAD_ADDR;
-	} else if (err == 1) {
-		ret = ICFG_SUCCESS;
-	} else {
-		ret = ICFG_FAILURE;
-	}
-
-	return (ret);
-}
-
-/*
- * Adds the IP address contained in the 'addr' argument to the physical
- * interface represented by the handle passed in.  At present,
- * additional IP addresses assigned to a physical interface are
- * represented as logical interfaces.
- *
- * If the 'handle' argument is a handle to a physical interface, a logical
- * interface will be created, named by the next unused logical unit number
- * for that physical interface.
- *
- * If the 'handle' argument is a handle to an logical interface, then that
- * logical interface is the one that will be created.  If the logical
- * interface model is abandoned in the future, passing in a logical
- * interface name should result in ICFG_UNSUPPORTED being returned.
- *
- * If the 'new_handle' argument is not NULL, then a handle is created for the
- * new IP address alias and returned to the caller via 'new_handle'.
- * At present this handle refers to a logical interface, but in the future
- * it may represent an IP address alias, and be used for setting/retrieving
- * address-related information only.
- *
- *
- * Returns: ICFG_SUCCESS, ICFG_BAD_ADDR, ICFG_DAD_FOUND, ICFG_EXISTS
- *          or ICFG_FAILURE.
- */
-int
-icfg_add_addr(icfg_handle_t handle, icfg_handle_t *new_handle,
-    const struct sockaddr *addr, socklen_t addrlen)
-{
-	struct lifreq lifr;
-	size_t addrsize;
-	int ret = ICFG_SUCCESS;
-	icfg_handle_t loc_handle;
-
-	if (addr->sa_family != icfg_if_protocol(handle))
-		return (ICFG_BAD_ADDR);
-
-	switch (addr->sa_family) {
-	case AF_INET:
-		addrsize = sizeof (struct sockaddr_in);
-		break;
-	case AF_INET6:
-		addrsize = sizeof (struct sockaddr_in6);
-		break;
-	default:
-		return (ICFG_BAD_ADDR);
-	}
-
-	if (addrlen < addrsize) {
-		errno = ENOSPC;
-		return (ICFG_FAILURE);
-	}
-
-	/*
-	 * See comments in ifconfig.c as to why this dance is necessary.
-	 */
-	(void) memset(&lifr, 0, sizeof (lifr));
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-
-	if (ioctl(handle->ifh_sock, SIOCLIFADDIF, (caddr_t)&lifr) < 0) {
-		if (errno == EEXIST)
-			return (ICFG_EXISTS);
-		else
-			return (ICFG_FAILURE);
-	}
-
-	/* Create the handle for the new interface name. */
-	ret = icfg_open(&loc_handle, &(handle->ifh_interface));
-	if (ret != ICFG_SUCCESS) {
-		return (ret);
-	}
-	(void) strlcpy(loc_handle->ifh_interface.if_name,
-	    lifr.lifr_name,
-	    sizeof (loc_handle->ifh_interface.if_name));
-
-	if (addr != NULL)
-		ret = icfg_set_addr(loc_handle, addr, addrsize);
-
-	if (new_handle != NULL)
-		*new_handle = loc_handle;
-	else
-		icfg_close(loc_handle);
-
-	return (ret);
-}
-
-/*
- * Removes specified IP address alias from physical interface. If the
- * If the 'handle' argument is a handle to a physical interface, then
- * the address alias removed must be specified by 'addr'.  If the
- * 'handle' argument is a handle for an IP address alias (currently
- * represented as a logical interface), then that address alias
- * (logical interface) is removed and the 'addr' argument is ignored.
- *
- * Under the logical interface model, an interface may only be removed
- * if the interface is 'down'.
- *
- * Returns: ICFG_SUCCESS, ICFG_BAD_ADDR, ICFG_IF_UP, ICFG_NO_EXIST,
- * or ICFG_FAILURE.
- */
-int
-icfg_remove_addr(icfg_handle_t handle, const struct sockaddr *addr,
-    socklen_t addrlen)
-{
-	struct lifreq lifr;
-	size_t addrsize;
-
-	switch (icfg_if_protocol(handle)) {
-	case AF_INET:
-		addrsize = sizeof (struct sockaddr_in);
-		break;
-	case AF_INET6:
-		addrsize = sizeof (struct sockaddr_in6);
-		break;
-	default:
-		return (ICFG_BAD_ADDR);
-	}
-
-	if (addr != NULL) {
-		if (addrlen < addrsize) {
-			errno = ENOSPC;
-			return (ICFG_FAILURE);
-		}
-		(void) memcpy(&lifr.lifr_addr, addr, addrsize);
-	} else {
-		(void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
-	}
-
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-
-	if (ioctl(handle->ifh_sock, SIOCLIFREMOVEIF, (caddr_t)&lifr) < 0)
-		return (ICFG_FAILURE);
-
-	return (ICFG_SUCCESS);
-}
-
-/*
- * Wrapper for sending a nontransparent I_STR ioctl().
- * Returns: Result from ioctl().
- *
- * Same as in usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c
- */
-static int
-strioctl(int s, int cmd, char *buf, int buflen)
-{
-	struct strioctl ioc;
-
-	(void) memset(&ioc, 0, sizeof (ioc));
-	ioc.ic_cmd = cmd;
-	ioc.ic_timout = 0;
-	ioc.ic_len = buflen;
-	ioc.ic_dp = buf;
-
-	return (ioctl(s, I_STR, (char *)&ioc));
-}
-
-/*
- * Open a stream on /dev/udp{,6}, pop off all undesired modules (note that
- * the user may have configured autopush to add modules above
- * udp), and push the arp module onto the resulting stream.
- * This is used to make IP+ARP be able to atomically track the muxid
- * for the I_PLINKed STREAMS, thus it isn't related to ARP running the ARP
- * protocol.
- *
- * Same as in usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c
- */
-static int
-open_arp_on_udp(char *udp_dev_name)
-{
-	int fd;
-
-	if ((fd = open(udp_dev_name, O_RDWR)) == -1)
-		return (-1);
-
-	errno = 0;
-	while (ioctl(fd, I_POP, 0) != -1)
-		;
-
-	if (errno == EINVAL && ioctl(fd, I_PUSH, ARP_MOD_NAME) != -1)
-		return (fd);
-
-	(void) close(fd);
-	return (-1);
-}
-
-/*
- * We need to plink both the arp-device stream and the arp-ip-device stream.
- * However the muxid is stored only in IP. Plumbing 2 streams individually
- * is not atomic, and if ifconfig is killed, the resulting plumbing can
- * be inconsistent. For eg. if only the arp stream is plumbed, we have lost
- * the muxid, and the half-baked plumbing can neither be unplumbed nor
- * replumbed, thus requiring a reboot. To avoid the above the following
- * scheme is used.
- *
- * We ask IP to enforce atomicity of plumbing the arp and IP streams.
- * This is done by pushing arp on to the mux (/dev/udp). ARP adds some
- * extra information in the I_PLINK and I_PUNLINK ioctls to let IP know
- * that the plumbing/unplumbing has to be done atomically. Ifconfig plumbs
- * the IP stream first, and unplumbs it last. The kernel (IP) does not
- * allow IP stream to be unplumbed without unplumbing arp stream. Similarly
- * it does not allow arp stream to be plumbed before IP stream is plumbed.
- * There is no need to use SIOCSLIFMUXID, since the whole operation is atomic,
- * and IP uses the info in the I_PLINK message to get the muxid.
- *
- * a. STREAMS does not allow us to use /dev/ip itself as the mux. So we use
- *    /dev/udp{,6}.
- * b. SIOCGLIFMUXID returns the muxid corresponding to the V4 or V6 stream
- *    depending on the open i.e. V4 vs V6 open. So we need to use /dev/udp
- *    or /dev/udp6 for SIOCGLIFMUXID and SIOCSLIFMUXID.
- * c. We need to push ARP in order to get the required kernel support for
- *    atomic plumbings. The actual work done by ARP is explained in arp.c
- *    Without pushing ARP, we will still be able to plumb/unplumb. But
- *    it is not atomic, and is supported by the kernel for backward
- *    compatibility for other utilities like atmifconfig etc. In this case
- *    the utility must use SIOCSLIFMUXID.
- *
- * Returns: ICFG_SUCCESS, ICFG_EXISTS, ICFG_BAD_ADDR, ICFG_FAILURE,
- * ICFG_DLPI_*, ICFG_NO_PLUMB_IP, ICFG_NO_PLUMB_ARP,
- * ICFG_NO_UNPLUMB_ARP
- */
-int
-icfg_plumb(icfg_handle_t handle)
-{
-	int ip_muxid;
-	int mux_fd, ip_fd, arp_fd;
-	uint_t ppa;
-	char *udp_dev_name;
-	char provider[DLPI_LINKNAME_MAX];
-	dlpi_handle_t dh_arp, dh_ip;
-	struct lifreq lifr;
-	int dlpi_ret, ret = ICFG_SUCCESS;
-	int saved_errno; /* to set errno after close() */
-	int dh_arp_ret; /* to track if dh_arp was successfully opened */
-	zoneid_t zoneid;
-
-	/* Logical and loopback interfaces are just added */
-	if (icfg_is_loopback(handle) || icfg_is_logical(handle))
-		return (icfg_add_addr(handle, NULL, NULL, 0));
-
-	/*
-	 * If we're running in the global zone, we need to
-	 * make sure this link is actually assigned to us.
-	 *
-	 * This is not an issue if we are not in the global
-	 * zone, as we simply can't see links we don't own.
-	 */
-	zoneid = getzoneid();
-	if (zoneid == GLOBAL_ZONEID) {
-		dladm_handle_t dlh;
-		dladm_status_t status;
-		datalink_id_t linkid;
-
-		if (dladm_open(&dlh) != DLADM_STATUS_OK)
-			return (ICFG_FAILURE);
-		status = dladm_name2info(dlh, icfg_if_name(handle), &linkid,
-		    NULL, NULL, NULL);
-		dladm_close(dlh);
-		if (status != DLADM_STATUS_OK)
-			return (ICFG_INVALID_ARG);
-		zoneid = ALL_ZONES;
-		if (zone_check_datalink(&zoneid, linkid) == 0)
-			return (ICFG_INVALID_ARG);
-	}
-
-	/*
-	 * We use DLPI_NOATTACH because the ip module will do the attach
-	 * itself for DLPI style-2 devices.
-	 */
-	if ((dlpi_ret = dlpi_open(icfg_if_name(handle), &dh_ip,
-	    DLPI_NOATTACH)) != DLPI_SUCCESS) {
-		return (dlpi_error_to_icfg_error(dlpi_ret));
-	}
-	if ((dlpi_ret = dlpi_parselink(icfg_if_name(handle), provider,
-	    &ppa)) != DLPI_SUCCESS) {
-		ret = dlpi_error_to_icfg_error(dlpi_ret);
-		goto done;
-	}
-
-	ip_fd = dlpi_fd(dh_ip);
-	if (ioctl(ip_fd, I_PUSH, IP_MOD_NAME) == -1) {
-		ret = ICFG_NO_PLUMB_IP;
-		goto done;
-	}
-
-	/*
-	 * Push the ARP module onto the interface stream. IP uses
-	 * this to send resolution requests up to ARP. We need to
-	 * do this before the SLIFNAME ioctl is sent down because
-	 * the interface becomes publicly known as soon as the SLIFNAME
-	 * ioctl completes. Thus some other process trying to bring up
-	 * the interface after SLIFNAME but before we have pushed ARP
-	 * could hang. We pop the module again later if it is not needed.
-	 */
-	if (ioctl(ip_fd, I_PUSH, ARP_MOD_NAME) == -1) {
-		ret = ICFG_NO_PLUMB_ARP;
-		goto done;
-	}
-
-	/*
-	 * Set appropriate IFF flags.  The kernel only allows us to
-	 * modify IFF_IPv[46], IFF_BROADCAST, and IFF_XRESOLV in the
-	 * SIOCSLIFNAME ioctl call; so we only need to set the ones
-	 * from that set that we care about.
-	 */
-	if (icfg_if_protocol(handle) == AF_INET6)
-		lifr.lifr_flags = IFF_IPV6;
-	else
-		lifr.lifr_flags = IFF_IPV4 | IFF_BROADCAST;
-
-	/* record the device and module names as interface name */
-	lifr.lifr_ppa = ppa;
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-
-	/* set the interface name */
-	if (ioctl(ip_fd, SIOCSLIFNAME, (char *)&lifr) == -1) {
-		if (errno == EALREADY)
-			ret = ICFG_EXISTS;
-		else
-			ret = ICFG_NO_PLUMB_IP;
-		goto done;
-	}
-
-	/* Get the full set of existing flags for this stream */
-	if (ioctl(ip_fd, SIOCGLIFFLAGS, (char *)&lifr) == -1) {
-		if (errno == ENXIO)
-			ret = ICFG_NO_EXIST;
-		else
-			ret = ICFG_FAILURE;
-		goto done;
-	}
-
-	/* Check if arp is not actually needed */
-	if (lifr.lifr_flags & (IFF_NOARP|IFF_IPV6)) {
-		if (ioctl(ip_fd, I_POP, 0) == -1) {
-			ret = ICFG_NO_UNPLUMB_ARP;
-			goto done;
-		}
-	}
-
-	/*
-	 * Open "/dev/udp" for use as a multiplexor to PLINK the
-	 * interface stream under. We use "/dev/udp" instead of "/dev/ip"
-	 * since STREAMS will not let you PLINK a driver under itself,
-	 * and "/dev/ip" is typically the driver at the bottom of
-	 * the stream for tunneling interfaces.
-	 */
-	if (icfg_if_protocol(handle) == AF_INET6)
-		udp_dev_name = UDP6_DEV_NAME;
-	else
-		udp_dev_name = UDP_DEV_NAME;
-
-	if ((mux_fd = open_arp_on_udp(udp_dev_name)) == -1) {
-		ret = ICFG_NO_PLUMB_ARP;
-		goto done;
-	}
-
-	/* Check if arp is not needed */
-	if (lifr.lifr_flags & (IFF_NOARP|IFF_IPV6)) {
-		/*
-		 * PLINK the interface stream so that ifconfig can exit
-		 * without tearing down the stream.
-		 */
-		if ((ip_muxid = ioctl(mux_fd, I_PLINK, ip_fd)) == -1) {
-			ret = ICFG_NO_PLUMB_IP;
-			goto done;
-		}
-		(void) close(mux_fd);
-		dlpi_close(dh_ip);
-		return (ICFG_SUCCESS);
-	}
-
-	/*
-	 * This interface does use ARP, so set up a separate stream
-	 * from the interface to ARP.
-	 *
-	 * Note: modules specified by the user are pushed
-	 * only on the interface stream, not on the ARP stream.
-	 *
-	 * We use DLPI_NOATTACH because the arp module will do the attach
-	 * itself for DLPI style-2 devices.
-	 */
-	if ((dh_arp_ret = dlpi_open(icfg_if_name(handle), &dh_arp,
-	    DLPI_NOATTACH)) != DLPI_SUCCESS) {
-		ret = dlpi_error_to_icfg_error(dh_arp_ret);
-		goto done;
-	}
-
-	arp_fd = dlpi_fd(dh_arp);
-	if (ioctl(arp_fd, I_PUSH, ARP_MOD_NAME) == -1) {
-		ret = ICFG_NO_PLUMB_ARP;
-		goto done;
-	}
-
-	/*
-	 * Tell ARP the name and unit number for this interface.
-	 * Note that arp has no support for transparent ioctls.
-	 */
-	if (strioctl(arp_fd, SIOCSLIFNAME, (char *)&lifr,
-	    sizeof (lifr)) == -1) {
-		ret = ICFG_NO_PLUMB_ARP;
-		goto done;
-	}
-	/*
-	 * PLINK the IP and ARP streams so that ifconfig can exit
-	 * without tearing down the stream.
-	 */
-	if ((ip_muxid = ioctl(mux_fd, I_PLINK, ip_fd)) == -1) {
-		ret = ICFG_NO_PLUMB_IP;
-		goto done;
-	}
-
-	if (ioctl(mux_fd, I_PLINK, arp_fd) == -1) {
-		(void) ioctl(mux_fd, I_PUNLINK, ip_muxid);
-		ret = ICFG_NO_PLUMB_ARP;
-	}
-
-done:
-	/* dlpi_close() may change errno, so save it */
-	saved_errno = errno;
-
-	dlpi_close(dh_ip);
-	if (dh_arp_ret == DLPI_SUCCESS)
-		dlpi_close(dh_arp);
-
-	if (mux_fd != -1)
-		(void) close(mux_fd);
-	if (ret != ICFG_SUCCESS)
-		errno = saved_errno;
-
-	return (ret);
-}
-
-static boolean_t
-ifaddr_down(ifaddrlistx_t *ifaddrp)
-{
-	icfg_handle_t addrh;
-	icfg_if_t addrif;
-	uint64_t addrflags;
-	boolean_t ret;
-
-	addrif.if_protocol = ifaddrp->ia_flags & IFF_IPV6 ? AF_INET6 : AF_INET;
-	(void) strlcpy(addrif.if_name, ifaddrp->ia_name,
-	    sizeof (addrif.if_name));
-	if (icfg_open(&addrh, &addrif) != ICFG_SUCCESS)
-		return (B_FALSE);
-
-	if (icfg_get_flags(addrh, &addrflags) != ICFG_SUCCESS)
-		return (B_FALSE);
-
-	addrflags &= ~IFF_UP;
-	if (icfg_set_flags(addrh, addrflags) != ICFG_SUCCESS) {
-		ret = B_FALSE;
-		goto done;
-	}
-
-	/*
-	 * Make sure that DAD activity (observable by IFF_DUPLICATE)
-	 * has also been stopped.  If we were successful in downing
-	 * the address, the get_flags will fail, as the addr will no
-	 * longer exist.
-	 */
-	if ((icfg_get_flags(addrh, &addrflags) == ICFG_SUCCESS) &&
-	    addrflags & IFF_DUPLICATE) {
-		struct sockaddr_storage ss;
-		socklen_t alen = sizeof (ss);
-		int plen;
-		/*
-		 * getting/setting the address resets DAD; and since
-		 * we've already turned off IFF_UP, DAD will remain
-		 * disabled.
-		 */
-		if ((icfg_get_addr(addrh, (struct sockaddr *)&ss, &alen, &plen,
-		    B_FALSE) != ICFG_SUCCESS) ||
-		    (icfg_set_addr(addrh, (struct sockaddr *)&ss, alen)
-		    != ICFG_SUCCESS)) {
-			ret = B_FALSE;
-			goto done;
-		}
-	}
-	ret = B_TRUE;
-done:
-	icfg_close(addrh);
-	return (ret);
-}
-
-/*
- * If this is a physical interface then remove it.
- * If it is a logical interface name use SIOCLIFREMOVEIF to
- * remove it. In both cases fail if it doesn't exist.
- *
- * Returns: ICFG_SUCCESS, ICFG_EXISTS, ICFG_NO_EXIST, ICFG_BAD_ADDR,
- * ICFG_FAILURE, ICFG_NO_UNPLUMB_IP, ICFG_NO_UNPLUMB_ARP,
- * ICFG_INVALID_ARG, ICFG_NO_IP_MUX
- *
- * Same as inetunplumb() in usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c
- */
-int
-icfg_unplumb(icfg_handle_t handle)
-{
-	int ip_muxid, arp_muxid;
-	int mux_fd;
-	int muxid_fd;
-	char *udp_dev_name;
-	uint64_t flags;
-	boolean_t changed_arp_muxid = B_FALSE;
-	int save_errno;
-	struct lifreq lifr;
-	int ret = ICFG_SUCCESS;
-	boolean_t v6 = (icfg_if_protocol(handle) == AF_INET6);
-
-	/* Make sure interface exists to start with */
-	if ((ret = icfg_get_flags(handle, &flags)) != ICFG_SUCCESS) {
-		return (ret);
-	}
-
-	if (icfg_is_loopback(handle) || icfg_is_logical(handle)) {
-		char *strptr = strchr(icfg_if_name(handle), ICFG_LOGICAL_SEP);
-
-		/* Can't unplumb logical interface zero */
-		if (strptr != NULL && strcmp(strptr, ":0") == 0)
-			return (ICFG_INVALID_ARG);
-
-		return (icfg_remove_addr(handle, NULL, 0));
-	}
-
-	/*
-	 * We used /dev/udp or udp6 to set up the mux. So we have to use
-	 * the same now for PUNLINK also.
-	 */
-	if (v6)
-		udp_dev_name = UDP6_DEV_NAME;
-	else
-		udp_dev_name = UDP_DEV_NAME;
-
-	if ((muxid_fd = open(udp_dev_name, O_RDWR)) == -1)
-		return (ICFG_NO_UNPLUMB_ARP);
-
-	if ((mux_fd = open_arp_on_udp(udp_dev_name)) == -1) {
-		ret = ICFG_NO_UNPLUMB_ARP;
-		goto done;
-	}
-
-	(void) strlcpy(lifr.lifr_name, icfg_if_name(handle),
-	    sizeof (lifr.lifr_name));
-	if (ioctl(muxid_fd, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
-		ret = ICFG_FAILURE;
-		goto done;
-	}
-	flags = lifr.lifr_flags;
-
-	/*
-	 * libinetcfg's only current consumer is nwamd; and we expect it to
-	 * be replaced before any other consumers come along.  NWAM does not
-	 * currently support creation of IPMP groups, so icfg_plumb(), for
-	 * example, does not do any IPMP-specific handling.  However, it's
-	 * possible nwamd might need to unplumb an IPMP group, so we include
-	 * IPMP group handling here.
-	 */
-again:
-	if (flags & IFF_IPMP) {
-		lifgroupinfo_t lifgr;
-		ifaddrlistx_t *ifaddrs, *ifaddrp;
-
-		/*
-		 * There are two reasons the I_PUNLINK can fail with EBUSY:
-		 * (1) if IP interfaces are in the group, or (2) if IPMP data
-		 * addresses are administratively up.  For case (1), we fail
-		 * here with a specific error message.  For case (2), we bring
-		 * down the addresses prior to doing the I_PUNLINK.  If the
-		 * I_PUNLINK still fails with EBUSY then the configuration
-		 * must have changed after our checks, in which case we branch
-		 * back up to `again' and rerun this logic.  The net effect is
-		 * that unplumbing an IPMP interface will only fail with EBUSY
-		 * if IP interfaces are in the group.
-		 */
-		ret = icfg_get_groupname(handle, lifgr.gi_grname, LIFGRNAMSIZ);
-		if (ret != ICFG_SUCCESS)
-			return (ret);
-
-		ret = icfg_get_groupinfo(handle, &lifgr);
-		if (ret != ICFG_SUCCESS)
-			return (ret);
-
-		/* make sure the group is empty */
-		if ((v6 && lifgr.gi_nv6 != 0) || (!v6 && lifgr.gi_nv4 != 0))
-			return (ICFG_INVALID_ARG);
-
-		/*
-		 * The kernel will fail the I_PUNLINK if the IPMP interface
-		 * has administratively up addresses; bring 'em down.
-		 */
-		if (ifaddrlistx(icfg_if_name(handle), IFF_UP|IFF_DUPLICATE,
-		    0, &ifaddrs) == -1)
-			return (ICFG_FAILURE);
-
-		ifaddrp = ifaddrs;
-		for (; ifaddrp != NULL; ifaddrp = ifaddrp->ia_next) {
-			if (((ifaddrp->ia_flags & IFF_IPV6) && !v6) ||
-			    (!(ifaddrp->ia_flags && IFF_IPV6) && v6))
-				continue;
-
-			if (!ifaddr_down(ifaddrp)) {
-				ifaddrlistx_free(ifaddrs);
-				return (ICFG_FAILURE);
-			}
-		}
-		ifaddrlistx_free(ifaddrs);
-	}
-
-	if (ioctl(muxid_fd, SIOCGLIFMUXID, (caddr_t)&lifr) < 0) {
-		ret = ICFG_NO_IP_MUX;
-		goto done;
-	}
-	arp_muxid = lifr.lifr_arp_muxid;
-	ip_muxid = lifr.lifr_ip_muxid;
-	/*
-	 * We don't have a good way of knowing whether the arp stream is
-	 * plumbed. We can't rely on IFF_NOARP because someone could
-	 * have turned it off later using "ifconfig xxx -arp".
-	 */
-	if (arp_muxid != 0) {
-		if (ioctl(mux_fd, I_PUNLINK, arp_muxid) < 0) {
-			/*
-			 * See the comment before the icfg_get_groupname() call.
-			 */
-			if (errno == EBUSY && (flags & IFF_IPMP))
-				goto again;
-
-			if ((errno == EINVAL) &&
-			    (flags & (IFF_NOARP | IFF_IPV6))) {
-				/*
-				 * Some plumbing utilities set the muxid to
-				 * -1 or some invalid value to signify that
-				 * there is no arp stream. Set the muxid to 0
-				 * before trying to unplumb the IP stream.
-				 * IP does not allow the IP stream to be
-				 * unplumbed if it sees a non-null arp muxid,
-				 * for consistency of IP-ARP streams.
-				 */
-				lifr.lifr_arp_muxid = 0;
-				(void) ioctl(muxid_fd, SIOCSLIFMUXID,
-				    (caddr_t)&lifr);
-				changed_arp_muxid = B_TRUE;
-			} else {
-				ret = ICFG_NO_UNPLUMB_ARP;
-			}
-		}
-	}
-
-	if (ioctl(mux_fd, I_PUNLINK, ip_muxid) < 0) {
-		if (changed_arp_muxid) {
-			/*
-			 * Some error occurred, and we need to restore
-			 * everything back to what it was.
-			 */
-			save_errno = errno;
-			lifr.lifr_arp_muxid = arp_muxid;
-			lifr.lifr_ip_muxid = ip_muxid;
-			(void) ioctl(muxid_fd, SIOCSLIFMUXID, (caddr_t)&lifr);
-			errno = save_errno;
-		}
-
-		/*
-		 * See the comment before the icfg_get_groupname() call.
-		 */
-		if (errno == EBUSY && (flags && IFF_IPMP))
-			goto again;
-
-		ret = ICFG_NO_UNPLUMB_IP;
-	}
-done:
-	/* close() may change errno, so save it */
-	save_errno = errno;
-
-	(void) close(muxid_fd);
-	if (mux_fd != -1)
-		(void) close(mux_fd);
-
-	if (ret != ICFG_SUCCESS)
-		errno = save_errno;
-
-	return (ret);
-}
--- a/usr/src/lib/libinetcfg/common/inetcfg.h	Mon Jun 07 10:04:00 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-/*
- * 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 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef	_INETCFG_H
-#define	_INETCFG_H
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <net/if.h>
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-/* error codes */
-typedef enum {
-	ICFG_SUCCESS,		/* No error occurred */
-	ICFG_FAILURE,		/* Generic failure */
-	ICFG_NO_MEMORY,		/* Insufficient memory */
-	ICFG_NOT_TUNNEL,	/* Tunnel operation attempted on non-tunnel */
-	ICFG_NOT_SET,		/* Could not return non-existent value */
-	ICFG_BAD_ADDR,		/* Invalid address */
-	ICFG_BAD_PROTOCOL,	/* Wrong protocol family for operation */
-	ICFG_DAD_FAILED,	/* Duplicate address detection failure */
-	ICFG_DAD_FOUND,		/* Duplicate address detected */
-	ICFG_IF_UP,		/* Interface is up */
-	ICFG_EXISTS,		/* Interface already exists */
-	ICFG_NO_EXIST,		/* Interface does not exist */
-	ICFG_INVALID_ARG,	/* Invalid argument */
-	ICFG_INVALID_NAME,	/* Invalid name */
-	ICFG_DLPI_INVALID_LINK, /* Invalid DLPI link */
-	ICFG_DLPI_FAILURE,	/* Generic DLPI failure */
-	ICFG_NO_PLUMB_IP,	/* Could not plumb IP stream */
-	ICFG_NO_PLUMB_ARP,	/* Could not plumb ARP stream */
-	ICFG_NO_UNPLUMB_IP,	/* Could not unplumb IP stream */
-	ICFG_NO_UNPLUMB_ARP,	/* Could not unplumb ARP stream */
-	ICFG_NO_IP_MUX		/* No IP mux set on the interface */
-} icfg_error_t;
-
-/* valid types for icfg_get_if_list() */
-#define	ICFG_PLUMBED	0
-#define	ICFG_INSTALLED	1
-
-typedef struct icfg_if {
-	char if_name[LIFNAMSIZ];	/* name of interface (eg., hme0) */
-	sa_family_t if_protocol;	/* IP protocol version */
-} icfg_if_t;
-
-typedef struct icfg_handle {
-	int ifh_sock;				/* socket to interface */
-	icfg_if_t ifh_interface;		/* interface definition */
-} *icfg_handle_t;
-
-/* retrieve error string */
-extern const char *icfg_errmsg(int);
-
-/* handle functions */
-extern int icfg_open(icfg_handle_t *, const icfg_if_t *);
-extern void icfg_close(icfg_handle_t);
-extern boolean_t icfg_is_logical(icfg_handle_t);
-
-/* get interface name */
-extern const char *icfg_if_name(icfg_handle_t);
-
-/* set interface properties */
-extern int icfg_set_flags(icfg_handle_t, uint64_t);
-extern int icfg_set_metric(icfg_handle_t, int);
-extern int icfg_set_mtu(icfg_handle_t, uint_t);
-extern int icfg_set_index(icfg_handle_t, int);
-extern int icfg_set_netmask(icfg_handle_t, const struct sockaddr_in *);
-extern int icfg_set_broadcast(icfg_handle_t, const struct sockaddr_in *);
-extern int icfg_set_prefixlen(icfg_handle_t, int);
-extern int icfg_set_addr(icfg_handle_t, const struct sockaddr *, socklen_t);
-extern int icfg_set_token(icfg_handle_t, const struct sockaddr_in6 *, int);
-extern int icfg_set_subnet(icfg_handle_t, const struct sockaddr *, socklen_t,
-    int);
-extern int icfg_set_dest_addr(icfg_handle_t, const struct sockaddr *,
-    socklen_t);
-
-/* get interface properties */
-extern int icfg_get_addr(icfg_handle_t, struct sockaddr *, socklen_t *, int *,
-    boolean_t);
-extern int icfg_get_token(icfg_handle_t, struct sockaddr_in6 *, int *,
-    boolean_t);
-extern int icfg_get_subnet(icfg_handle_t, struct sockaddr *, socklen_t *,
-    int *, boolean_t);
-extern int icfg_get_netmask(icfg_handle_t, struct sockaddr_in *);
-extern int icfg_get_broadcast(icfg_handle_t, struct sockaddr_in *);
-extern int icfg_get_dest_addr(icfg_handle_t, struct sockaddr *, socklen_t *);
-extern int icfg_get_groupname(icfg_handle_t, char *, size_t);
-extern int icfg_get_flags(icfg_handle_t, uint64_t *);
-extern int icfg_get_metric(icfg_handle_t, int *);
-extern int icfg_get_mtu(icfg_handle_t, uint_t *);
-extern int icfg_get_index(icfg_handle_t, int *);
-
-/* retrieve interface list or iterate over all interface lists */
-extern int icfg_get_if_list(icfg_if_t **, int *, int, int);
-extern void icfg_free_if_list(icfg_if_t *);
-extern int icfg_iterate_if(int, int, void *, int (*)(icfg_if_t *, void *));
-
-extern int icfg_sockaddr_to_str(sa_family_t, const struct sockaddr *,
-    char *, size_t);
-extern int icfg_str_to_sockaddr(sa_family_t, const char *, struct sockaddr *,
-    socklen_t *);
-
-/* plumb or unplumb interfaces, add or remove IP */
-extern int icfg_add_addr(icfg_handle_t, icfg_handle_t *,
-    const struct sockaddr *, socklen_t);
-extern int icfg_remove_addr(icfg_handle_t, const struct sockaddr *, socklen_t);
-
-extern int icfg_plumb(icfg_handle_t);
-extern int icfg_unplumb(icfg_handle_t);
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _INETCFG_H */
--- a/usr/src/lib/libinetcfg/common/llib-linetcfg	Mon Jun 07 10:04:00 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * 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 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-/* LINTLIBRARY */
-/* PROTOLIB1 */
-
-#include <inetcfg.h>
--- a/usr/src/lib/libinetcfg/common/mapfile-vers	Mon Jun 07 10:04:00 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-#
-# 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 2010 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#
-# MAPFILE HEADER START
-#
-# WARNING:  STOP NOW.  DO NOT MODIFY THIS FILE.
-# Object versioning must comply with the rules detailed in
-#
-#	usr/src/lib/README.mapfiles
-#
-# You should not be making modifications here until you've read the most current
-# copy of that file. If you need help, contact a gatekeeper for guidance.
-#
-# MAPFILE HEADER END
-#
-
-SUNWprivate_1.1 {
-    global:
-	icfg_add_addr;
-	icfg_close;
-	icfg_errmsg;
-	icfg_free_if_list;
-	icfg_get_addr;
-	icfg_get_broadcast;
-	icfg_get_dest_addr;
-	icfg_get_flags;
-	icfg_get_groupname;
-	icfg_get_if_list;
-	icfg_get_index;
-	icfg_get_metric;
-	icfg_get_mtu;
-	icfg_get_netmask;
-	icfg_get_subnet;
-	icfg_get_token;
-	icfg_if_name;
-	icfg_is_logical;
-	icfg_iterate_if;
-	icfg_open;
-	icfg_plumb;
-	icfg_remove_addr;
-	icfg_set_addr;
-	icfg_set_broadcast;
-	icfg_set_dest_addr;
-	icfg_set_flags;
-	icfg_set_index;
-	icfg_set_metric;
-	icfg_set_mtu;
-	icfg_set_netmask;
-	icfg_set_prefixlen;
-	icfg_set_subnet;
-	icfg_set_token;
-	icfg_sockaddr_to_str;
-	icfg_str_to_sockaddr;
-	icfg_unplumb;
-    local:
-	*;
-};
--- a/usr/src/lib/libinetcfg/i386/Makefile	Mon Jun 07 10:04:00 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-#
-# 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.
-#
-# 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 2002 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#ident	"%Z%%M%	%I%	%E% SMI"
-#
-# lib/libinetcfg/i386/Makefile
-
-include ../Makefile.com
-
-install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- a/usr/src/lib/libinetcfg/libinetcfg.xcl	Mon Jun 07 10:04:00 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-#
-# 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.
-#
-# 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 2002 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#ident	"%Z%%M%	%I%	%E% SMI"
-#
-msgid  "255.255.255.255"
-msgid  "%s%d"
-
--- a/usr/src/lib/libinetcfg/sparc/Makefile	Mon Jun 07 10:04:00 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-#
-# 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.
-#
-# 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 2002 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#ident	"%Z%%M%	%I%	%E% SMI"
-#
-# lib/libinetcfg/sparc/Makefile
-
-include ../Makefile.com
-
-install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- a/usr/src/lib/libipadm/common/ipadm_addr.c	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/lib/libipadm/common/ipadm_addr.c	Mon Jun 07 14:10:14 2010 -0400
@@ -1747,6 +1747,21 @@
 }
 
 /*
+ * Gets the static source address from the address object in `ipaddr'.
+ * Memory for `addr' should be already allocated by the caller.
+ */
+ipadm_status_t
+ipadm_get_addr(const ipadm_addrobj_t ipaddr, struct sockaddr_storage *addr)
+{
+	if (ipaddr == NULL || ipaddr->ipadm_atype != IPADM_ADDR_STATIC ||
+	    addr == NULL) {
+		return (IPADM_INVALID_ARG);
+	}
+	*addr = ipaddr->ipadm_static_addr;
+
+	return (IPADM_SUCCESS);
+}
+/*
  * Set up tunnel destination address in ipaddr by contacting DNS.
  * The function works similar to ipadm_set_addr().
  * The dst_addr must resolve to exactly one address. IPADM_BAD_ADDR is returned
@@ -2207,6 +2222,20 @@
 }
 
 /*
+ * Returns `aobjname' from the address object in `ipaddr'.
+ */
+ipadm_status_t
+ipadm_get_aobjname(const ipadm_addrobj_t ipaddr, char *aobjname, size_t len)
+{
+	if (ipaddr == NULL || aobjname == NULL)
+		return (IPADM_INVALID_ARG);
+	if (strlcpy(aobjname, ipaddr->ipadm_aobjname, len) >= len)
+		return (IPADM_INVALID_ARG);
+
+	return (IPADM_SUCCESS);
+}
+
+/*
  * Frees the address object in `ipaddr'.
  */
 void
@@ -2355,6 +2384,10 @@
  * if provided, will be ignored and replaced with the newly generated name.
  * The interface name provided has to be a logical interface name that
  * already exists. No new logical interface will be added in this function.
+ *
+ * If IPADM_OPT_V46 is passed in the flags, then both IPv4 and IPv6 interfaces
+ * are plumbed (if they haven't been already).  Otherwise, just the interface
+ * specified in `addr' is plumbed.
  */
 ipadm_status_t
 ipadm_create_addr(ipadm_handle_t iph, ipadm_addrobj_t addr, uint32_t flags)
@@ -2435,7 +2468,7 @@
 	}
 	if (status == IPADM_SUCCESS)
 		created_af = B_TRUE;
-	if (!is_6to4 && !legacy) {
+	if (!is_6to4 && !legacy && (flags & IPADM_OPT_V46)) {
 		other_af = (af == AF_INET ? AF_INET6 : AF_INET);
 		status = i_ipadm_create_if(iph, ifname, other_af, flags);
 		if (status != IPADM_SUCCESS && status != IPADM_IF_EXISTS) {
@@ -2672,7 +2705,7 @@
  * in the address object will be removed from the physical interface.
  * If the address type is IPADM_ADDR_DHCP, the flag IPADM_OPT_RELEASE specifies
  * whether the lease should be released. If IPADM_OPT_RELEASE is not
- * specified, the lease will be dropped. This option is ignored
+ * specified, the lease will be dropped. This option is not supported
  * for other address types.
  *
  * If the address type is IPADM_ADDR_IPV6_ADDRCONF, the link-local address and
@@ -3329,7 +3362,7 @@
 	boolean_t		af_exists, other_af_exists, a_exists;
 
 	if (ipaddr == NULL || flags == 0 || flags == IPADM_OPT_PERSIST ||
-	    (flags & ~(IPADM_COMMON_OPT_MASK|IPADM_OPT_UP))) {
+	    (flags & ~(IPADM_COMMON_OPT_MASK|IPADM_OPT_UP|IPADM_OPT_V46))) {
 		return (IPADM_INVALID_ARG);
 	}
 
--- a/usr/src/lib/libipadm/common/libipadm.c	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/lib/libipadm/common/libipadm.c	Mon Jun 07 14:10:14 2010 -0400
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <stdio.h>
@@ -858,6 +857,7 @@
 	door_arg_t	darg;
 	int		err;
 	ipmgmt_retval_t	rval, *rvalp;
+	boolean_t	reopen = B_FALSE;
 
 	if (rbufp == NULL) {
 		rvalp = &rval;
@@ -872,6 +872,7 @@
 	darg.rbuf = *rbufp;
 	darg.rsize = rsize;
 
+reopen:
 	(void) pthread_mutex_lock(&iph->iph_lock);
 	/* The door descriptor is opened if it isn't already */
 	if (iph->iph_door_fd == -1) {
@@ -883,8 +884,20 @@
 	}
 	(void) pthread_mutex_unlock(&iph->iph_lock);
 
-	if (door_call(iph->iph_door_fd, &darg) == -1)
+	if (door_call(iph->iph_door_fd, &darg) == -1) {
+		/*
+		 * Stale door descriptor is possible if ipmgmtd was restarted
+		 * since last iph_door_fd was opened, so try re-opening door
+		 * descriptor.
+		 */
+		if (!reopen && errno == EBADF) {
+			(void) close(iph->iph_door_fd);
+			iph->iph_door_fd = -1;
+			reopen = B_TRUE;
+			goto reopen;
+		}
 		return (errno);
+	}
 	err = ((ipmgmt_retval_t *)(void *)(darg.rbuf))->ir_err;
 	if (darg.rbuf != *rbufp) {
 		/*
--- a/usr/src/lib/libipadm/common/libipadm.h	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/lib/libipadm/common/libipadm.h	Mon Jun 07 14:10:14 2010 -0400
@@ -138,6 +138,9 @@
  *
  *  - IPADM_OPT_UP
  *	Used to bring up a static address on creation
+ *
+ *  - IPADM_OPT_V46
+ *      Used to plumb both IPv4 and IPv6 interfaces by ipadm_create_addr()
  */
 #define	IPADM_OPT_PERSIST	0x00000001
 #define	IPADM_OPT_ACTIVE	0x00000002
@@ -152,6 +155,7 @@
 #define	IPADM_OPT_RELEASE	0x00000400
 #define	IPADM_OPT_INFORM	0x00000800
 #define	IPADM_OPT_UP		0x00001000
+#define	IPADM_OPT_V46		0x00002000
 
 /* IPADM property class */
 #define	IPADMPROP_CLASS_MODULE	0x00000001	/* on 'protocol' only */
@@ -284,12 +288,16 @@
 extern ipadm_status_t	ipadm_create_addrobj(ipadm_addr_type_t, const char *,
 			    ipadm_addrobj_t *);
 extern void		ipadm_destroy_addrobj(ipadm_addrobj_t);
+extern ipadm_status_t   ipadm_get_aobjname(const ipadm_addrobj_t, char *,
+			    size_t);
 
 /* Functions to set fields in addrobj for static addresses */
 extern ipadm_status_t	ipadm_set_addr(ipadm_addrobj_t, const char *,
 			    sa_family_t);
 extern ipadm_status_t	ipadm_set_dst_addr(ipadm_addrobj_t, const char *,
 			    sa_family_t);
+extern ipadm_status_t   ipadm_get_addr(const ipadm_addrobj_t,
+			    struct sockaddr_storage *);
 
 /* Functions to set fields in addrobj for IPv6 addrconf */
 extern ipadm_status_t	ipadm_set_interface_id(ipadm_addrobj_t, const char *);
--- a/usr/src/lib/libipadm/common/mapfile-vers	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/lib/libipadm/common/mapfile-vers	Mon Jun 07 14:10:14 2010 -0400
@@ -56,7 +56,9 @@
 	ipadm_enable_if;
 	ipadm_free_addr_info;
 	ipadm_free_if_info;
+	ipadm_get_addr;
 	ipadm_get_addrprop;
+	ipadm_get_aobjname;
 	ipadm_get_ifprop;
 	ipadm_get_prop;
 	ipadm_if_enabled;
--- a/usr/src/lib/libnwam/common/libnwam.h	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/lib/libnwam/common/libnwam.h	Mon Jun 07 14:10:14 2010 -0400
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -1019,11 +1018,10 @@
 		struct nwam_event_if_state {
 			char nwe_name[NWAM_MAX_NAME_LEN];
 			uint32_t nwe_flags;
-			uint32_t nwe_index;
 			uint32_t nwe_addr_valid; /* boolean */
 			uint32_t nwe_addr_added; /* boolean */
 			struct sockaddr_storage nwe_addr;
-			/* might be longer then sizeof(if_state) for addr */
+			struct sockaddr_storage nwe_netmask;
 		} nwe_if_state;
 
 		struct nwam_event_link_state {
--- a/usr/src/pkg/manifests/system-library.mf	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/pkg/manifests/system-library.mf	Mon Jun 07 14:10:14 2010 -0400
@@ -182,7 +182,6 @@
 file path=lib/libelfsign.so.1
 $(i386_ONLY)file path=lib/libfdisk.so.1
 file path=lib/libgen.so.1
-file path=lib/libinetcfg.so.1
 file path=lib/libinetutil.so.1
 file path=lib/libintl.so.1
 file path=lib/libipadm.so.1
@@ -982,7 +981,6 @@
 link path=usr/lib/libgen.so.1 target=../../lib/libgen.so.1
 link path=usr/lib/libhotplug.so target=./libhotplug.so.1
 link path=usr/lib/libidmap.so target=./libidmap.so.1
-link path=usr/lib/libinetcfg.so.1 target=../../lib/libinetcfg.so.1
 link path=usr/lib/libinetutil.so.1 target=../../lib/libinetutil.so.1
 link path=usr/lib/libintl.so target=../../lib/libintl.so.1
 link path=usr/lib/libintl.so.1 target=../../lib/libintl.so.1
--- a/usr/src/tools/scripts/bfu.sh	Mon Jun 07 10:04:00 2010 -0700
+++ b/usr/src/tools/scripts/bfu.sh	Mon Jun 07 14:10:14 2010 -0400
@@ -6595,7 +6595,6 @@
 	    $usr/lib/libgen.a				\
 	    $usr/lib/libgenIO.a				\
 	    $usr/lib/libike.a				\
-	    $usr/lib/libinetcfg.a			\
 	    $usr/lib/libinetutil.a			\
 	    $usr/lib/libintl.a				\
 	    $usr/lib/libkstat.a				\