changeset 3871:5a1dfce6c5cc

PSARC 2007/140 libdladm restructure 6329535 the use_cache argument of macadm_walk function should be removed 6454340 macadm_walk leaks 6509525 wrong error code when adding/removing ports to/from an aggregation 6509532 aggregation deleting fails but system reports success 6518572 the reference to dls_vlan should be released if setzoneid fails 6520149 show-linkprop stops showing full list of link properties if it fails to display one property 6535220 potential complicated library dependency and code duplication between libdladm and its friends
author yz147064
date Wed, 21 Mar 2007 09:48:58 -0700
parents b083fcb4e287
children a16817aded85
files deleted_files/usr/src/lib/liblaadm/Makefile deleted_files/usr/src/lib/liblaadm/Makefile.com deleted_files/usr/src/lib/liblaadm/common/llib-llaadm deleted_files/usr/src/lib/liblaadm/common/mapfile-vers deleted_files/usr/src/lib/liblaadm/i386/Makefile deleted_files/usr/src/lib/liblaadm/sparc/Makefile deleted_files/usr/src/lib/libmacadm/Makefile deleted_files/usr/src/lib/libmacadm/Makefile.com deleted_files/usr/src/lib/libmacadm/common/libmacadm.c deleted_files/usr/src/lib/libmacadm/common/libmacadm.h deleted_files/usr/src/lib/libmacadm/common/llib-lmacadm deleted_files/usr/src/lib/libmacadm/common/mapfile-vers deleted_files/usr/src/lib/libmacadm/i386/Makefile deleted_files/usr/src/lib/libmacadm/sparc/Makefile deleted_files/usr/src/lib/libwladm/Makefile deleted_files/usr/src/lib/libwladm/Makefile.com deleted_files/usr/src/lib/libwladm/common/llib-lwladm deleted_files/usr/src/lib/libwladm/common/mapfile-vers deleted_files/usr/src/lib/libwladm/i386/Makefile deleted_files/usr/src/lib/libwladm/libwladm.xcl deleted_files/usr/src/lib/libwladm/sparc/Makefile usr/src/Makefile.lint usr/src/cmd/dladm/Makefile usr/src/cmd/dladm/dladm.c usr/src/cmd/rcm_daemon/Makefile.com usr/src/cmd/rcm_daemon/common/network_rcm.c usr/src/cmd/zoneadmd/vplat.c usr/src/lib/Makefile usr/src/lib/libdladm/Makefile usr/src/lib/libdladm/Makefile.com usr/src/lib/libdladm/common/libdladm.c usr/src/lib/libdladm/common/libdladm.h usr/src/lib/libdladm/common/libdlaggr.c usr/src/lib/libdladm/common/libdlaggr.h usr/src/lib/libdladm/common/libdllink.c usr/src/lib/libdladm/common/libdllink.h usr/src/lib/libdladm/common/libdlwlan.c usr/src/lib/libdladm/common/libdlwlan.h usr/src/lib/libdladm/common/libdlwlan_impl.h usr/src/lib/libdladm/common/linkprop.c usr/src/lib/libdladm/common/llib-ldladm usr/src/lib/libdladm/common/mapfile-vers usr/src/lib/libdladm/common/secobj.c usr/src/lib/liblaadm/Makefile usr/src/lib/liblaadm/Makefile.com usr/src/lib/liblaadm/common/liblaadm.c usr/src/lib/liblaadm/common/liblaadm.h usr/src/lib/liblaadm/common/llib-llaadm usr/src/lib/liblaadm/common/mapfile-vers usr/src/lib/liblaadm/i386/Makefile usr/src/lib/liblaadm/sparc/Makefile usr/src/lib/libmacadm/Makefile usr/src/lib/libmacadm/Makefile.com usr/src/lib/libmacadm/common/libmacadm.c usr/src/lib/libmacadm/common/libmacadm.h usr/src/lib/libmacadm/common/llib-lmacadm usr/src/lib/libmacadm/common/mapfile-vers usr/src/lib/libmacadm/i386/Makefile usr/src/lib/libmacadm/sparc/Makefile usr/src/lib/libwladm/Makefile usr/src/lib/libwladm/Makefile.com usr/src/lib/libwladm/common/libwladm.c usr/src/lib/libwladm/common/libwladm.h usr/src/lib/libwladm/common/libwladm_impl.h usr/src/lib/libwladm/common/llib-lwladm usr/src/lib/libwladm/common/mapfile-vers usr/src/lib/libwladm/i386/Makefile usr/src/lib/libwladm/libwladm.xcl usr/src/lib/libwladm/sparc/Makefile usr/src/pkgdefs/SUNWcslr/prototype_com usr/src/pkgdefs/etc/exception_list_i386 usr/src/pkgdefs/etc/exception_list_sparc usr/src/tools/scripts/bfu.sh usr/src/uts/common/io/dld/dld_drv.c
diffstat 74 files changed, 5974 insertions(+), 5881 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/liblaadm/Makefile	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,62 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+include $(SRC)/lib/Makefile.lib
+
+HDRS =		liblaadm.h
+HDRDIR =	common
+
+SUBDIRS =		$(MACH)
+
+POFILE =	liblaadm.po
+MSGFILES =	common/liblaadm.c
+
+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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/liblaadm/Makefile.com	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,53 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+LIBRARY = liblaadm.a
+VERS    = .1
+OBJECTS = liblaadm.o
+
+include ../../Makefile.lib
+
+# install this library in the root filesystem
+include ../../Makefile.rootfs
+
+LIBS =		$(DYNLIB) $(LINTLIB)
+
+LDLIBS +=	-lsocket -lc
+
+SRCDIR =	../common
+$(LINTLIB) :=	SRCS = $(SRCDIR)/$(LINTSRC)
+
+CFLAGS +=	$(CCVERBOSE)
+CPPFLAGS +=	-I$(SRCDIR) -D_REENTRANT
+
+.KEEP_STATE:
+
+all:		$(LIBS)
+
+lint:		lintcheck
+
+include $(SRC)/lib/Makefile.targ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/liblaadm/common/llib-llaadm	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,32 @@
+/*
+ * 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 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+/*LINTLIBRARY*/
+/*PROTOLIB1*/
+
+#include <liblaadm.h>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/liblaadm/common/mapfile-vers	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,49 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+SUNWprivate_1.1 {
+    global:
+	laadm_add;
+	laadm_create;
+	laadm_delete;
+	laadm_diag;
+	laadm_down;
+	laadm_lacp_mode_to_str;
+	laadm_lacp_timer_to_str;
+	laadm_mac_addr_to_str;
+	laadm_modify;
+	laadm_policy_to_str;
+	laadm_remove;
+	laadm_str_to_lacp_mode;
+	laadm_str_to_lacp_timer;
+	laadm_str_to_mac_addr;
+	laadm_str_to_policy;
+	laadm_up;
+	laadm_walk_sys;
+    local:
+	*;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/liblaadm/i386/Makefile	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,31 @@
+#
+# 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 2005 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/liblaadm/sparc/Makefile	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,31 @@
+#
+# 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 2005 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/libmacadm/Makefile	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,62 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+include $(SRC)/lib/Makefile.lib
+
+HDRS =		libmacadm.h
+HDRDIR =	common
+
+SUBDIRS =		$(MACH)
+
+POFILE =	libmacadm.po
+MSGFILES =	common/libmacadm.c
+
+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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/libmacadm/Makefile.com	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,53 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+LIBRARY = libmacadm.a
+VERS    = .1
+OBJECTS = libmacadm.o
+
+include ../../Makefile.lib
+
+# install this library in the root filesystem
+include ../../Makefile.rootfs
+
+LIBS =		$(DYNLIB) $(LINTLIB)
+
+LDLIBS +=	-ldevinfo -lc
+
+SRCDIR =	../common
+$(LINTLIB) :=	SRCS = $(SRCDIR)/$(LINTSRC)
+
+CFLAGS +=	$(CCVERBOSE)
+CPPFLAGS +=	-I$(SRCDIR) -D_REENTRANT
+
+.KEEP_STATE:
+
+all:		$(LIBS) fnamecheck
+
+lint:		lintcheck
+
+include $(SRC)/lib/Makefile.targ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/libmacadm/common/libmacadm.c	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,137 @@
+/*
+ * 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 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stropts.h>
+#include <sys/dld.h>
+#include <libdevinfo.h>
+
+#define	_KERNEL
+#include <sys/sysmacros.h>
+#undef	_KERNEL
+
+/*
+ * MAC Administration Library.
+ *
+ * This library is used by administration tools such as dladm(1M) to
+ * iterate through the list of MAC interfaces
+ *
+ */
+
+typedef struct macadm_dev {
+	char			md_name[MAXNAMELEN];
+	struct macadm_dev	*md_next;
+} macadm_dev_t;
+
+typedef struct macadm_walk {
+	macadm_dev_t		*mw_dev_list;
+} macadm_walk_t;
+
+/*
+ * Local callback invoked for each DDI_NT_NET node.
+ */
+/* ARGSUSED */
+static int
+i_macadm_apply(di_node_t node, di_minor_t minor, void *arg)
+{
+	macadm_walk_t	*mwp = arg;
+	macadm_dev_t	*mdp = mwp->mw_dev_list;
+	macadm_dev_t	**lastp = &mwp->mw_dev_list;
+	char		dev[MAXNAMELEN];
+
+	(void) snprintf(dev, MAXNAMELEN, "%s%d",
+	    di_driver_name(node), di_instance(node));
+
+	/*
+	 * Skip aggregations.
+	 */
+	if (strcmp("aggr", di_driver_name(node)) == 0)
+		return (DI_WALK_CONTINUE);
+
+	while (mdp) {
+		/*
+		 * Skip duplicates.
+		 */
+		if (strcmp(mdp->md_name, dev) == 0)
+			return (DI_WALK_CONTINUE);
+
+		lastp = &mdp->md_next;
+		mdp = mdp->md_next;
+	}
+
+	if ((mdp = malloc(sizeof (*mdp))) == NULL)
+		return (DI_WALK_CONTINUE);
+
+	(void) strlcpy(mdp->md_name, dev, MAXNAMELEN);
+	mdp->md_next = NULL;
+	*lastp = mdp;
+
+	return (DI_WALK_CONTINUE);
+}
+
+/*
+ * Invoke the specified callback for each DDI_NT_MAC node.
+ */
+int
+macadm_walk(void (*fn)(void *, const char *), void *arg,
+    boolean_t use_cache)
+{
+	di_node_t	root;
+	macadm_walk_t	mw;
+	macadm_dev_t	*mdp;
+	uint_t		flags;
+
+	if (use_cache) {
+		flags = DINFOCACHE;
+	} else {
+		flags = DINFOSUBTREE | DINFOMINOR | DINFOPROP | DINFOFORCE;
+	}
+
+	if ((root = di_init("/", flags)) == DI_NODE_NIL) {
+		return (-1);
+	}
+	mw.mw_dev_list = NULL;
+
+	(void) di_walk_minor(root, DDI_NT_NET, DI_CHECK_ALIAS, &mw,
+	    i_macadm_apply);
+
+	di_fini(root);
+
+	mdp = mw.mw_dev_list;
+	while (mdp) {
+		(*fn)(arg, mdp->md_name);
+		mdp = mdp->md_next;
+	}
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/libmacadm/common/libmacadm.h	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,46 @@
+/*
+ * 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 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _LIBMACADM_H
+#define	_LIBMACADM_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/types.h>
+#include <sys/mac.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+extern int	macadm_walk(void (*)(void *, const char *),
+    void *, boolean_t);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _LIBMACADM_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/libmacadm/common/llib-lmacadm	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,32 @@
+/*
+ * 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 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+/*LINTLIBRARY*/
+/*PROTOLIB1*/
+
+#include <libmacadm.h>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/libmacadm/common/mapfile-vers	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,33 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+SUNWprivate_1.1 {
+    global:
+	macadm_walk;
+    local:
+	*;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/libmacadm/i386/Makefile	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,31 @@
+#
+# 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 2005 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/libmacadm/sparc/Makefile	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,31 @@
+#
+# 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 2005 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/libwladm/Makefile	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,63 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+include $(SRC)/lib/Makefile.lib
+
+HDRS =		libwladm.h libwladm_impl.h
+HDRDIR =	common
+
+SUBDIRS =	$(MACH)
+
+POFILE =	libwladm.po
+MSGFILES =	common/libwladm.c
+XGETFLAGS =	-a -x libwladm.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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/libwladm/Makefile.com	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,51 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+LIBRARY = libwladm.a
+VERS    = .1
+OBJECTS = libwladm.o
+
+include ../../Makefile.lib
+# install this library in the root filesystem
+include ../../Makefile.rootfs
+
+LIBS =		$(DYNLIB) $(LINTLIB)
+LDLIBS +=	-ldevinfo -lsocket -lc
+
+SRCDIR =	../common
+$(LINTLIB) :=	SRCS = $(SRCDIR)/$(LINTSRC)
+
+CFLAGS +=	$(CCVERBOSE)
+CPPFLAGS +=	-I$(SRCDIR) -D_REENTRANT
+
+.KEEP_STATE:
+
+all:		$(LIBS)
+
+lint:		lintcheck
+
+include $(SRC)/lib/Makefile.targ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/libwladm/common/llib-lwladm	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,31 @@
+/*
+ * 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 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+/*LINTLIBRARY*/
+/*PROTOLIB1*/
+
+#include <libwladm.h>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/libwladm/common/mapfile-vers	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,60 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+SUNWprivate_1.1 {
+    global:
+	wladm_scan;
+	wladm_connect;
+	wladm_disconnect;
+	wladm_get_link_attr;
+	wladm_walk;
+	wladm_is_valid;
+	wladm_set_prop;
+	wladm_walk_prop;
+	wladm_get_prop;
+	wladm_essid2str;
+	wladm_bssid2str;
+	wladm_secmode2str;
+	wladm_strength2str;
+	wladm_mode2str;
+	wladm_speed2str;
+	wladm_auth2str;
+	wladm_bsstype2str;
+	wladm_linkstatus2str;
+	wladm_status2str;
+	wladm_str2essid;
+	wladm_str2bssid;
+	wladm_str2secmode;
+	wladm_str2strength;
+	wladm_str2mode;
+	wladm_str2speed;
+	wladm_str2auth;
+	wladm_str2bsstype;
+	wladm_str2linkstatus;
+    local:
+	*;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/libwladm/i386/Makefile	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,30 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/libwladm/libwladm.xcl	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,52 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+msgid  "a"
+msgid  "b"
+msgid  "g"
+msgid  "channel"
+msgid  "powermode"
+msgid  "radio"
+msgid  "speed"
+msgid  ""
+msgid  "%.*f"
+msgid  "%d"
+msgid  "%s"
+msgid  "%s%d"
+msgid  "%u"
+msgid  "/"
+msgid  "/dev/%s"
+msgid  "open"
+msgid  "shared"
+msgid  "bss"
+msgid  "ibss"
+msgid  "any"
+msgid  "on"
+msgid  "off"
+msgid  "fast"
+msgid  "max"
+msgid  "wep"
+msgid  "none"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/libwladm/sparc/Makefile	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,30 @@
+#
+# 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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- a/usr/src/Makefile.lint	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/Makefile.lint	Wed Mar 21 09:48:58 2007 -0700
@@ -337,10 +337,8 @@
 	lib/libiscsitgt \
 	lib/libkmf \
 	lib/libkstat \
-	lib/liblaadm \
 	lib/liblgrp \
 	lib/liblm \
-	lib/libmacadm \
 	lib/libmalloc \
 	lib/libmapmalloc \
 	lib/libmapid \
@@ -378,7 +376,6 @@
 	lib/libuutil \
 	lib/libwanboot \
 	lib/libwanbootutil \
-	lib/libwladm \
 	lib/libxnet \
 	lib/libzfs \
 	lib/libzfs_jni \
--- a/usr/src/cmd/dladm/Makefile	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/cmd/dladm/Makefile	Wed Mar 21 09:48:58 2007 -0700
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
@@ -35,8 +35,7 @@
 include ../Makefile.cmd
 
 XGETFLAGS += -a -x $(PROG).xcl
-LDLIBS += -ldladm -lmacadm -ldlpi -llaadm -lkstat -lwladm -lsecdb -lbsm \
-	  -linetutil
+LDLIBS += -ldladm -ldlpi -lkstat -lsecdb -lbsm -linetutil
 
 $(ROOTCFGFILES) := OWNER= dladm
 $(ROOTCFGFILES) := GROUP= sys
--- a/usr/src/cmd/dladm/dladm.c	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/cmd/dladm/dladm.c	Wed Mar 21 09:48:58 2007 -0700
@@ -46,10 +46,9 @@
 #include <auth_list.h>
 #include <libintl.h>
 #include <libdlpi.h>
-#include <libdladm.h>
-#include <liblaadm.h>
-#include <libmacadm.h>
-#include <libwladm.h>
+#include <libdllink.h>
+#include <libdlaggr.h>
+#include <libdlwlan.h>
 #include <libinetutil.h>
 #include <bsm/adt.h>
 #include <bsm/adt_event.h>
@@ -93,18 +92,6 @@
 	boolean_t	ms_parseable;
 } show_mac_state_t;
 
-typedef struct port_state {
-	char			*state_name;
-	aggr_port_state_t	state_num;
-} port_state_t;
-
-static port_state_t port_states[] = {
-	{"standby", AGGR_PORT_STATE_STANDBY },
-	{"attached", AGGR_PORT_STATE_ATTACHED }
-};
-
-#define	NPORTSTATES	(sizeof (port_states) / sizeof (port_state_t))
-
 typedef	void cmdfunc_t(int, char **);
 
 static cmdfunc_t do_show_link, do_show_dev, do_show_wifi;
@@ -124,20 +111,17 @@
 static void	get_mac_stats(const char *, pktsum_t *);
 static void	get_link_stats(const char *, pktsum_t *);
 static uint64_t	mac_ifspeed(const char *);
-static char	*mac_link_state(const char *);
-static char	*mac_link_duplex(const char *);
 static void	stats_total(pktsum_t *, pktsum_t *, pktsum_t *);
 static void	stats_diff(pktsum_t *, pktsum_t *, pktsum_t *);
+static const char	*mac_link_state(const char *);
+static const char	*mac_link_duplex(const char *);
 
 static boolean_t str2int(const char *, int *);
 static void	die(const char *, ...);
 static void	die_optdup(int);
 static void	die_opterr(int, int);
-static void	die_laerr(laadm_diag_t, const char *, ...);
-static void	die_wlerr(wladm_status_t, const char *, ...);
 static void	die_dlerr(dladm_status_t, const char *, ...);
 static void	warn(const char *, ...);
-static void	warn_wlerr(wladm_status_t, const char *, ...);
 static void	warn_dlerr(dladm_status_t, const char *, ...);
 
 typedef struct	cmd {
@@ -292,22 +276,22 @@
 static void
 do_create_aggr(int argc, char *argv[])
 {
-	char			option;
-	int			key;
-	uint32_t		policy = AGGR_POLICY_L4;
-	aggr_lacp_mode_t	lacp_mode = AGGR_LACP_OFF;
-	aggr_lacp_timer_t	lacp_timer = AGGR_LACP_TIMER_SHORT;
-	laadm_port_attr_db_t	port[MAXPORT];
-	uint_t			nport = 0;
-	uint8_t			mac_addr[ETHERADDRL];
-	boolean_t		mac_addr_fixed = B_FALSE;
-	boolean_t		P_arg = B_FALSE;
-	boolean_t		l_arg = B_FALSE;
-	boolean_t		t_arg = B_FALSE;
-	boolean_t		u_arg = B_FALSE;
-	boolean_t		T_arg = B_FALSE;
-	char			*altroot = NULL;
-	laadm_diag_t		diag = 0;
+	char				option;
+	int				key;
+	uint32_t			policy = AGGR_POLICY_L4;
+	aggr_lacp_mode_t		lacp_mode = AGGR_LACP_OFF;
+	aggr_lacp_timer_t		lacp_timer = AGGR_LACP_TIMER_SHORT;
+	dladm_aggr_port_attr_db_t	port[MAXPORT];
+	uint_t				nport = 0;
+	uint8_t				mac_addr[ETHERADDRL];
+	boolean_t			mac_addr_fixed = B_FALSE;
+	boolean_t			P_arg = B_FALSE;
+	boolean_t			l_arg = B_FALSE;
+	boolean_t			t_arg = B_FALSE;
+	boolean_t			u_arg = B_FALSE;
+	boolean_t			T_arg = B_FALSE;
+	char				*altroot = NULL;
+	dladm_status_t			status;
 
 	opterr = 0;
 	while ((option = getopt_long(argc, argv, ":d:l:P:R:tu:T:",
@@ -328,7 +312,7 @@
 				die_optdup(option);
 
 			P_arg = B_TRUE;
-			if (!laadm_str_to_policy(optarg, &policy))
+			if (!dladm_aggr_str2policy(optarg, &policy))
 				die("invalid policy '%s'", optarg);
 			break;
 		case 'u':
@@ -336,7 +320,7 @@
 				die_optdup(option);
 
 			u_arg = B_TRUE;
-			if (!laadm_str_to_mac_addr(optarg, &mac_addr_fixed,
+			if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed,
 			    mac_addr))
 				die("invalid MAC address '%s'", optarg);
 			break;
@@ -345,7 +329,7 @@
 				die_optdup(option);
 
 			l_arg = B_TRUE;
-			if (!laadm_str_to_lacp_mode(optarg, &lacp_mode))
+			if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode))
 				die("invalid LACP mode '%s'", optarg);
 			break;
 		case 'T':
@@ -353,7 +337,7 @@
 				die_optdup(option);
 
 			T_arg = B_TRUE;
-			if (!laadm_str_to_lacp_timer(optarg, &lacp_timer))
+			if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer))
 				die("invalid LACP timer value '%s'", optarg);
 			break;
 		case 't':
@@ -378,9 +362,10 @@
 	if (!str2int(argv[optind], &key) || key < 1)
 		die("invalid key value '%s'", argv[optind]);
 
-	if (laadm_create(key, nport, port, policy, mac_addr_fixed,
-	    mac_addr, lacp_mode, lacp_timer, t_arg, altroot, &diag) < 0)
-		die_laerr(diag, "create operation failed");
+	status = dladm_aggr_create(key, nport, port, policy, mac_addr_fixed,
+	    mac_addr, lacp_mode, lacp_timer, t_arg, altroot);
+	if (status != DLADM_STATUS_OK)
+		die_dlerr(status, "create operation failed");
 }
 
 static void
@@ -390,7 +375,7 @@
 	char			option;
 	boolean_t		t_arg = B_FALSE;
 	char			*altroot = NULL;
-	laadm_diag_t		diag = 0;
+	dladm_status_t		status;
 
 	opterr = 0;
 	while ((option = getopt_long(argc, argv, ":R:t", longopts,
@@ -415,20 +400,21 @@
 	if (!str2int(argv[optind], &key) || key < 1)
 		die("invalid key value '%s'", argv[optind]);
 
-	if (laadm_delete(key, t_arg, altroot, &diag) < 0)
-		die_laerr(diag, "delete operation failed");
+	status = dladm_aggr_delete(key, t_arg, altroot);
+	if (status != DLADM_STATUS_OK)
+		die_dlerr(status, "delete operation failed");
 }
 
 static void
 do_add_aggr(int argc, char *argv[])
 {
-	char			option;
-	int			key;
-	laadm_port_attr_db_t	port[MAXPORT];
-	uint_t			nport = 0;
-	boolean_t		t_arg = B_FALSE;
-	char			*altroot = NULL;
-	laadm_diag_t		diag = 0;
+	char				option;
+	int				key;
+	dladm_aggr_port_attr_db_t	port[MAXPORT];
+	uint_t				nport = 0;
+	boolean_t			t_arg = B_FALSE;
+	char				*altroot = NULL;
+	dladm_status_t			status;
 
 	opterr = 0;
 	while ((option = getopt_long(argc, argv, ":d:R:t", longopts,
@@ -466,32 +452,33 @@
 	if (!str2int(argv[optind], &key) || key < 1)
 		die("invalid key value '%s'", argv[optind]);
 
-	if (laadm_add(key, nport, port, t_arg, altroot, &diag) < 0) {
+	status = dladm_aggr_add(key, nport, port, t_arg, altroot);
+	if (status != DLADM_STATUS_OK) {
 		/*
-		 * checking ENOTSUP is a temporary workaround
+		 * checking DLADM_STATUS_NOTSUP is a temporary workaround
 		 * and should be removed once 6399681 is fixed.
 		 */
-		if (errno == ENOTSUP) {
+		if (status == DLADM_STATUS_NOTSUP) {
 			(void) fprintf(stderr,
 			    gettext("%s: add operation failed: %s\n"),
 			    progname,
 			    gettext("device capabilities don't match"));
 			exit(ENOTSUP);
 		}
-		die_laerr(diag, "add operation failed");
+		die_dlerr(status, "add operation failed");
 	}
 }
 
 static void
 do_remove_aggr(int argc, char *argv[])
 {
-	char			option;
-	int			key;
-	laadm_port_attr_db_t	port[MAXPORT];
-	uint_t			nport = 0;
-	boolean_t		t_arg = B_FALSE;
-	char			*altroot = NULL;
-	laadm_diag_t		diag = 0;
+	char				option;
+	int				key;
+	dladm_aggr_port_attr_db_t	port[MAXPORT];
+	uint_t				nport = 0;
+	boolean_t			t_arg = B_FALSE;
+	char				*altroot = NULL;
+	dladm_status_t			status;
 
 	opterr = 0;
 	while ((option = getopt_long(argc, argv, ":d:R:t",
@@ -529,8 +516,9 @@
 	if (!str2int(argv[optind], &key) || key < 1)
 		die("invalid key value '%s'", argv[optind]);
 
-	if (laadm_remove(key, nport, port, t_arg, altroot, &diag) < 0)
-		die_laerr(diag, "remove operation failed");
+	status = dladm_aggr_remove(key, nport, port, t_arg, altroot);
+	if (status != DLADM_STATUS_OK)
+		die_dlerr(status, "remove operation failed");
 }
 
 static void
@@ -546,47 +534,47 @@
 	uint8_t			modify_mask = 0;
 	boolean_t		t_arg = B_FALSE;
 	char			*altroot = NULL;
-	laadm_diag_t		diag = 0;
+	dladm_status_t		status;
 
 	opterr = 0;
 	while ((option = getopt_long(argc, argv, ":l:P:R:tu:T:", longopts,
 	    NULL)) != -1) {
 		switch (option) {
 		case 'P':
-			if (modify_mask & LAADM_MODIFY_POLICY)
+			if (modify_mask & DLADM_AGGR_MODIFY_POLICY)
 				die_optdup(option);
 
-			modify_mask |= LAADM_MODIFY_POLICY;
-
-			if (!laadm_str_to_policy(optarg, &policy))
+			modify_mask |= DLADM_AGGR_MODIFY_POLICY;
+
+			if (!dladm_aggr_str2policy(optarg, &policy))
 				die("invalid policy '%s'", optarg);
 			break;
 		case 'u':
-			if (modify_mask & LAADM_MODIFY_MAC)
+			if (modify_mask & DLADM_AGGR_MODIFY_MAC)
 				die_optdup(option);
 
-			modify_mask |= LAADM_MODIFY_MAC;
-
-			if (!laadm_str_to_mac_addr(optarg, &mac_addr_fixed,
+			modify_mask |= DLADM_AGGR_MODIFY_MAC;
+
+			if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed,
 			    mac_addr))
 				die("invalid MAC address '%s'", optarg);
 			break;
 		case 'l':
-			if (modify_mask & LAADM_MODIFY_LACP_MODE)
+			if (modify_mask & DLADM_AGGR_MODIFY_LACP_MODE)
 				die_optdup(option);
 
-			modify_mask |= LAADM_MODIFY_LACP_MODE;
-
-			if (!laadm_str_to_lacp_mode(optarg, &lacp_mode))
+			modify_mask |= DLADM_AGGR_MODIFY_LACP_MODE;
+
+			if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode))
 				die("invalid LACP mode '%s'", optarg);
 			break;
 		case 'T':
-			if (modify_mask & LAADM_MODIFY_LACP_TIMER)
+			if (modify_mask & DLADM_AGGR_MODIFY_LACP_TIMER)
 				die_optdup(option);
 
-			modify_mask |= LAADM_MODIFY_LACP_TIMER;
-
-			if (!laadm_str_to_lacp_timer(optarg, &lacp_timer))
+			modify_mask |= DLADM_AGGR_MODIFY_LACP_TIMER;
+
+			if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer))
 				die("invalid LACP timer value '%s'", optarg);
 			break;
 		case 't':
@@ -611,16 +599,17 @@
 	if (!str2int(argv[optind], &key) || key < 1)
 		die("invalid key value '%s'", argv[optind]);
 
-	if (laadm_modify(key, modify_mask, policy, mac_addr_fixed, mac_addr,
-	    lacp_mode, lacp_timer, t_arg, altroot, &diag) < 0)
-		die_laerr(diag, "modify operation failed");
+	status = dladm_aggr_modify(key, modify_mask, policy, mac_addr_fixed,
+	    mac_addr, lacp_mode, lacp_timer, t_arg, altroot);
+	if (status != DLADM_STATUS_OK)
+		die_dlerr(status, "modify operation failed");
 }
 
 static void
 do_up_aggr(int argc, char *argv[])
 {
 	int		key = 0;
-	laadm_diag_t	diag = 0;
+	dladm_status_t	status;
 
 	/* get aggregation key (optional last argument) */
 	if (argc == 2) {
@@ -630,12 +619,12 @@
 		usage();
 	}
 
-	if (laadm_up(key, NULL, &diag) < 0) {
+	if ((status = dladm_aggr_up(key, NULL)) != DLADM_STATUS_OK) {
 		if (key != 0) {
-			die_laerr(diag, "could not bring up aggregation '%u'",
+			die_dlerr(status, "could not bring up aggregation '%u'",
 			    key);
 		} else {
-			die_laerr(diag, "could not bring aggregations up");
+			die_dlerr(status, "could not bring aggregations up");
 		}
 	}
 }
@@ -643,7 +632,8 @@
 static void
 do_down_aggr(int argc, char *argv[])
 {
-	int	key = 0;
+	dladm_status_t	status;
+	int		key = 0;
 
 	/* get aggregation key (optional last argument) */
 	if (argc == 2) {
@@ -653,13 +643,12 @@
 		usage();
 	}
 
-	if (laadm_down(key) < 0) {
+	if ((status = dladm_aggr_down(key)) != DLADM_STATUS_OK) {
 		if (key != 0) {
-			die("could not bring down aggregation '%u': %s",
-			    key, strerror(errno));
+			die_dlerr(status,
+			    "could not bring down aggregation '%u'", key);
 		} else {
-			die("could not bring down aggregations: %s",
-			    strerror(errno));
+			die_dlerr(status, "could not bring down aggregations");
 		}
 	}
 }
@@ -819,9 +808,9 @@
 }
 
 static void
-dump_grp(laadm_grp_attr_sys_t	*grp, boolean_t parseable)
+dump_grp(dladm_aggr_grp_attr_t *grp, boolean_t parseable)
 {
-	char policy_str[LAADM_POLICY_STR_LEN];
+	char buf[DLADM_STRSIZE];
 	char addr_str[ETHERADDRL * 3];
 
 	if (!parseable) {
@@ -829,19 +818,19 @@
 		    grp->lg_key, grp->lg_key);
 
 		(void) printf(gettext("\tpolicy: %s"),
-		    laadm_policy_to_str(grp->lg_policy, policy_str));
+		    dladm_aggr_policy2str(grp->lg_policy, buf));
 
 		(void) printf(gettext("\taddress: %s (%s)\n"),
-		    laadm_mac_addr_to_str(grp->lg_mac, addr_str),
+		    dladm_aggr_macaddr2str(grp->lg_mac, addr_str),
 		    (grp->lg_mac_fixed) ? gettext("fixed") : gettext("auto"));
 	} else {
 		(void) printf("aggr key=%d", grp->lg_key);
 
 		(void) printf(" policy=%s",
-		    laadm_policy_to_str(grp->lg_policy, policy_str));
+		    dladm_aggr_policy2str(grp->lg_policy, buf));
 
 		(void) printf(" address=%s",
-		    laadm_mac_addr_to_str(grp->lg_mac, addr_str));
+		    dladm_aggr_macaddr2str(grp->lg_mac, addr_str));
 
 		(void) printf(" address-type=%s\n",
 		    (grp->lg_mac_fixed) ? "fixed" : "auto");
@@ -849,11 +838,13 @@
 }
 
 static void
-dump_grp_lacp(laadm_grp_attr_sys_t *grp, boolean_t parseable)
+dump_grp_lacp(dladm_aggr_grp_attr_t *grp, boolean_t parseable)
 {
-	const char *lacp_mode_str = laadm_lacp_mode_to_str(grp->lg_lacp_mode);
-	const char *lacp_timer_str =
-	    laadm_lacp_timer_to_str(grp->lg_lacp_timer);
+	char lacp_mode_str[DLADM_STRSIZE];
+	char lacp_timer_str[DLADM_STRSIZE];
+
+	(void) dladm_aggr_lacpmode2str(grp->lg_lacp_mode, lacp_mode_str);
+	(void) dladm_aggr_lacptimer2str(grp->lg_lacp_timer, lacp_timer_str);
 
 	if (!parseable) {
 		(void) printf(gettext("\t\tLACP mode: %s"), lacp_mode_str);
@@ -865,7 +856,7 @@
 }
 
 static void
-dump_grp_stats(laadm_grp_attr_sys_t *grp)
+dump_grp_stats(dladm_aggr_grp_attr_t *grp)
 {
 	(void) printf("key: %d", grp->lg_key);
 	(void) printf("\tipackets  rbytes      opackets	 obytes		 ");
@@ -888,49 +879,37 @@
 	    "state\n"));
 }
 
-static char *
-port_state_to_str(aggr_port_state_t state_num)
-{
-	int			i;
-	port_state_t		*state;
-
-	for (i = 0; i < NPORTSTATES; i++) {
-		state = &port_states[i];
-		if (state->state_num == state_num)
-			return (state->state_name);
-	}
-
-	return ("unknown");
-}
-
 static void
-dump_port(laadm_port_attr_sys_t *port, boolean_t parseable)
+dump_port(dladm_aggr_port_attr_t *port, boolean_t parseable)
 {
 	char *dev = port->lp_devname;
-	char buf[ETHERADDRL * 3];
+	char mac_addr[ETHERADDRL * 3];
+	char buf[DLADM_STRSIZE];
 
 	if (!parseable) {
-		(void) printf("	   %-9s\t%s", dev, laadm_mac_addr_to_str(
-		    port->lp_mac, buf));
+		(void) printf("	   %-9s\t%s", dev, dladm_aggr_macaddr2str(
+		    port->lp_mac, mac_addr));
 		(void) printf("\t %5uMb", (int)(mac_ifspeed(dev) /
 		    1000000ull));
 		(void) printf("\t%s", mac_link_duplex(dev));
 		(void) printf("\t%s", mac_link_state(dev));
-		(void) printf("\t%s\n", port_state_to_str(port->lp_state));
+		(void) printf("\t%s\n",
+		    dladm_aggr_portstate2str(port->lp_state, buf));
 
 	} else {
 		(void) printf(" device=%s address=%s", dev,
-		    laadm_mac_addr_to_str(port->lp_mac, buf));
+		    dladm_aggr_macaddr2str(port->lp_mac, mac_addr));
 		(void) printf(" speed=%u", (int)(mac_ifspeed(dev) /
 		    1000000ull));
 		(void) printf(" duplex=%s", mac_link_duplex(dev));
 		(void) printf(" link=%s", mac_link_state(dev));
-		(void) printf(" port=%s", port_state_to_str(port->lp_state));
+		(void) printf(" port=%s",
+		    dladm_aggr_portstate2str(port->lp_state, buf));
 	}
 }
 
 static void
-dump_port_lacp(laadm_port_attr_sys_t *port)
+dump_port_lacp(dladm_aggr_port_attr_t *port)
 {
 	aggr_lacp_state_t *state = &port->lp_lacp_state;
 
@@ -977,7 +956,7 @@
 }
 
 static int
-show_key(void *arg, laadm_grp_attr_sys_t *grp)
+show_key(void *arg, dladm_aggr_grp_attr_t *grp)
 {
 	show_grp_state_t	*state = (show_grp_state_t *)arg;
 	int			i;
@@ -1256,7 +1235,7 @@
 	state.gs_key = key;
 	state.gs_found = B_FALSE;
 
-	(void) laadm_walk_sys(show_key, &state);
+	(void) dladm_aggr_walk(show_key, &state);
 
 	if (key != 0 && !state.gs_found)
 		die("non-existent aggregation key '%u'", key);
@@ -1332,7 +1311,7 @@
 	}
 
 	if (dev == NULL)
-		(void) macadm_walk(show_dev, &state, B_TRUE);
+		(void) dladm_mac_walk(show_dev, &state);
 	else
 		show_dev(&state, dev);
 }
@@ -1391,7 +1370,7 @@
 
 	for (;;) {
 		state.gs_found = B_FALSE;
-		(void) laadm_walk_sys(show_key, &state);
+		(void) dladm_aggr_walk(show_key, &state);
 		if (state.gs_key != 0 && !state.gs_found)
 			die("non-existent aggregation key '%u'", key);
 
@@ -1423,7 +1402,7 @@
 
 		state.ms_donefirst = B_FALSE;
 		if (dev == NULL)
-			(void) macadm_walk(show_dev_stats, &state, B_TRUE);
+			(void) dladm_mac_walk(show_dev_stats, &state);
 		else
 			show_dev_stats(&state, dev);
 
@@ -1596,55 +1575,33 @@
 	return (ifspeed);
 }
 
-static char *
+static const char *
 mac_link_state(const char *dev)
 {
 	link_state_t	link_state;
-	char		*state_str = "unknown";
+	char		buf[DLADM_STRSIZE];
 
 	if (get_single_mac_stat(dev, "link_state", KSTAT_DATA_UINT32,
 	    &link_state) != 0) {
-		return (state_str);
+		return ("unknown");
 	}
 
-	switch (link_state) {
-	case LINK_STATE_UP:
-		state_str = "up";
-		break;
-	case LINK_STATE_DOWN:
-		state_str = "down";
-		break;
-	default:
-		break;
-	}
-
-	return (state_str);
+	return (dladm_linkstate2str(link_state, buf));
 }
 
 
-static char *
+static const char *
 mac_link_duplex(const char *dev)
 {
 	link_duplex_t	link_duplex;
-	char		*duplex_str = "unknown";
+	char		buf[DLADM_STRSIZE];
 
 	if (get_single_mac_stat(dev, "link_duplex", KSTAT_DATA_UINT32,
 	    &link_duplex) != 0) {
-		return (duplex_str);
+		return ("unknown");
 	}
 
-	switch (link_duplex) {
-	case LINK_DUPLEX_FULL:
-		duplex_str = "full";
-		break;
-	case LINK_DUPLEX_HALF:
-		duplex_str = "half";
-		break;
-	default:
-		break;
-	}
-
-	return (duplex_str);
+	return (dladm_linkduplex2str(link_duplex, buf));
 }
 
 #define	WIFI_CMD_SCAN	0x00000001
@@ -1659,17 +1616,17 @@
 } wifi_field_t;
 
 static wifi_field_t wifi_fields[] = {
-{ "link",	"LINK",		10,	0,			WIFI_CMD_ALL},
-{ "essid",	"ESSID",	19,	WLADM_WLAN_ATTR_ESSID,	WIFI_CMD_ALL},
-{ "bssid",	"BSSID/IBSSID", 17,	WLADM_WLAN_ATTR_BSSID,	WIFI_CMD_ALL},
-{ "ibssid",	"BSSID/IBSSID", 17,	WLADM_WLAN_ATTR_BSSID,	WIFI_CMD_ALL},
-{ "mode",	"MODE",		6,	WLADM_WLAN_ATTR_MODE,	WIFI_CMD_ALL},
-{ "speed",	"SPEED",	6,	WLADM_WLAN_ATTR_SPEED,	WIFI_CMD_ALL},
-{ "auth",	"AUTH",		8,	WLADM_WLAN_ATTR_AUTH,	WIFI_CMD_SHOW},
-{ "bsstype",	"BSSTYPE",	8,	WLADM_WLAN_ATTR_BSSTYPE, WIFI_CMD_ALL},
-{ "sec",	"SEC",		6,	WLADM_WLAN_ATTR_SECMODE, WIFI_CMD_ALL},
-{ "status",	"STATUS",	17,	WLADM_LINK_ATTR_STATUS, WIFI_CMD_SHOW},
-{ "strength",	"STRENGTH",	10,	WLADM_WLAN_ATTR_STRENGTH, WIFI_CMD_ALL}}
+{ "link",	"LINK",		10, 0,				WIFI_CMD_ALL},
+{ "essid",	"ESSID",	19, DLADM_WLAN_ATTR_ESSID,	WIFI_CMD_ALL},
+{ "bssid",	"BSSID/IBSSID", 17, DLADM_WLAN_ATTR_BSSID,	WIFI_CMD_ALL},
+{ "ibssid",	"BSSID/IBSSID", 17, DLADM_WLAN_ATTR_BSSID,	WIFI_CMD_ALL},
+{ "mode",	"MODE",		6,  DLADM_WLAN_ATTR_MODE,	WIFI_CMD_ALL},
+{ "speed",	"SPEED",	6,  DLADM_WLAN_ATTR_SPEED,	WIFI_CMD_ALL},
+{ "auth",	"AUTH",		8,  DLADM_WLAN_ATTR_AUTH,	WIFI_CMD_SHOW},
+{ "bsstype",	"BSSTYPE",	8,  DLADM_WLAN_ATTR_BSSTYPE,	WIFI_CMD_ALL},
+{ "sec",	"SEC",		6,  DLADM_WLAN_ATTR_SECMODE,	WIFI_CMD_ALL},
+{ "status",	"STATUS",	17, DLADM_WLAN_LINKATTR_STATUS,	WIFI_CMD_SHOW},
+{ "strength",	"STRENGTH",	10, DLADM_WLAN_ATTR_STRENGTH,	WIFI_CMD_ALL}}
 ;
 
 static char *all_scan_wifi_fields =
@@ -1853,9 +1810,9 @@
 
 static void
 print_wlan_attr(print_wifi_state_t *statep, wifi_field_t *wfp,
-    wladm_wlan_attr_t *attrp)
+    dladm_wlan_attr_t *attrp)
 {
-	char		buf[WLADM_STRSIZE];
+	char		buf[DLADM_STRSIZE];
 	const char	*str = "";
 
 	if (wfp->wf_mask == 0) {
@@ -1869,30 +1826,30 @@
 	}
 
 	switch (wfp->wf_mask) {
-	case WLADM_WLAN_ATTR_ESSID:
-		str = wladm_essid2str(&attrp->wa_essid, buf);
+	case DLADM_WLAN_ATTR_ESSID:
+		str = dladm_wlan_essid2str(&attrp->wa_essid, buf);
 		break;
-	case WLADM_WLAN_ATTR_BSSID:
-		str = wladm_bssid2str(&attrp->wa_bssid, buf);
+	case DLADM_WLAN_ATTR_BSSID:
+		str = dladm_wlan_bssid2str(&attrp->wa_bssid, buf);
 		break;
-	case WLADM_WLAN_ATTR_SECMODE:
-		str = wladm_secmode2str(&attrp->wa_secmode, buf);
+	case DLADM_WLAN_ATTR_SECMODE:
+		str = dladm_wlan_secmode2str(&attrp->wa_secmode, buf);
 		break;
-	case WLADM_WLAN_ATTR_STRENGTH:
-		str = wladm_strength2str(&attrp->wa_strength, buf);
+	case DLADM_WLAN_ATTR_STRENGTH:
+		str = dladm_wlan_strength2str(&attrp->wa_strength, buf);
 		break;
-	case WLADM_WLAN_ATTR_MODE:
-		str = wladm_mode2str(&attrp->wa_mode, buf);
+	case DLADM_WLAN_ATTR_MODE:
+		str = dladm_wlan_mode2str(&attrp->wa_mode, buf);
 		break;
-	case WLADM_WLAN_ATTR_SPEED:
-		str = wladm_speed2str(&attrp->wa_speed, buf);
+	case DLADM_WLAN_ATTR_SPEED:
+		str = dladm_wlan_speed2str(&attrp->wa_speed, buf);
 		(void) strlcat(buf, "Mb", sizeof (buf));
 		break;
-	case WLADM_WLAN_ATTR_AUTH:
-		str = wladm_auth2str(&attrp->wa_auth, buf);
+	case DLADM_WLAN_ATTR_AUTH:
+		str = dladm_wlan_auth2str(&attrp->wa_auth, buf);
 		break;
-	case WLADM_WLAN_ATTR_BSSTYPE:
-		str = wladm_bsstype2str(&attrp->wa_bsstype, buf);
+	case DLADM_WLAN_ATTR_BSSTYPE:
+		str = dladm_wlan_bsstype2str(&attrp->wa_bsstype, buf);
 		break;
 	}
 
@@ -1900,7 +1857,7 @@
 }
 
 static boolean_t
-print_scan_results(void *arg, wladm_wlan_attr_t *attrp)
+print_scan_results(void *arg, dladm_wlan_attr_t *attrp)
 {
 	print_wifi_state_t	*statep = arg;
 	int			i;
@@ -1924,26 +1881,26 @@
 scan_wifi(void *arg, const char *link)
 {
 	print_wifi_state_t	*statep = arg;
-	wladm_status_t		status;
+	dladm_status_t		status;
 
 	statep->ws_link = link;
-	status = wladm_scan(link, statep, print_scan_results);
-	if (status != WLADM_STATUS_OK)
-		die_wlerr(status, "cannot scan link '%s'", link);
+	status = dladm_wlan_scan(link, statep, print_scan_results);
+	if (status != DLADM_STATUS_OK)
+		die_dlerr(status, "cannot scan link '%s'", link);
 
 	return (B_TRUE);
 }
 
 static void
 print_link_attr(print_wifi_state_t *statep, wifi_field_t *wfp,
-    wladm_link_attr_t *attrp)
+    dladm_wlan_linkattr_t *attrp)
 {
-	char		buf[WLADM_STRSIZE];
+	char		buf[DLADM_STRSIZE];
 	const char	*str = "";
 
 	if (strcmp(wfp->wf_name, "status") == 0) {
 		if ((wfp->wf_mask & attrp->la_valid) != 0)
-			str = wladm_linkstatus2str(&attrp->la_status, buf);
+			str = dladm_wlan_linkstatus2str(&attrp->la_status, buf);
 		print_wifi_field(statep, wfp, str);
 		return;
 	}
@@ -1955,12 +1912,12 @@
 {
 	int			i;
 	print_wifi_state_t	*statep = arg;
-	wladm_link_attr_t	attr;
-	wladm_status_t		status;
-
-	status = wladm_get_link_attr(link, &attr);
-	if (status != WLADM_STATUS_OK)
-		die_wlerr(status, "cannot get link attributes for '%s'", link);
+	dladm_wlan_linkattr_t	attr;
+	dladm_status_t		status;
+
+	status = dladm_wlan_get_linkattr(link, &attr);
+	if (status != DLADM_STATUS_OK)
+		die_dlerr(status, "cannot get link attributes for '%s'", link);
 
 	if (statep->ws_header) {
 		statep->ws_header = B_FALSE;
@@ -1987,7 +1944,7 @@
 	boolean_t		(*callback)(void *, const char *);
 	uint_t			nfields;
 	print_wifi_state_t	state;
-	wladm_status_t		status;
+	dladm_status_t		status;
 
 	if (cmd == WIFI_CMD_SCAN)
 		callback = scan_wifi;
@@ -2029,9 +1986,9 @@
 	state.ws_nfields = nfields;
 
 	if (state.ws_link == NULL) {
-		status = wladm_walk(&state, callback);
-		if (status != WLADM_STATUS_OK)
-			die_wlerr(status, "cannot walk wifi links");
+		status = dladm_wlan_walk(&state, callback);
+		if (status != DLADM_STATUS_OK)
+			die_dlerr(status, "cannot walk wifi links");
 	} else {
 		(void) (*callback)(&state, state.ws_link);
 	}
@@ -2067,17 +2024,17 @@
 }
 
 static int
-parse_wep_keys(char *str, wladm_wep_key_t **keys, uint_t *key_countp)
+parse_wep_keys(char *str, dladm_wlan_wepkey_t **keys, uint_t *key_countp)
 {
-	uint_t		i;
-	split_t		*sp;
-	wladm_wep_key_t	*wk;
-
-	sp = split(str, WLADM_MAX_WEPKEYS, WLADM_MAX_WEPKEYNAME_LEN);
+	uint_t			i;
+	split_t			*sp;
+	dladm_wlan_wepkey_t	*wk;
+
+	sp = split(str, DLADM_WLAN_MAX_WEPKEYS, DLADM_WLAN_MAX_WEPKEYNAME_LEN);
 	if (sp == NULL)
 		return (-1);
 
-	wk = malloc(sp->s_nfields * sizeof (wladm_wep_key_t));
+	wk = malloc(sp->s_nfields * sizeof (dladm_wlan_wepkey_t));
 	if (wk == NULL)
 		goto fail;
 
@@ -2087,7 +2044,7 @@
 		dladm_status_t		status;
 
 		(void) strlcpy(wk[i].wk_name, sp->s_fields[i],
-		    WLADM_MAX_WEPKEYNAME_LEN);
+		    DLADM_WLAN_MAX_WEPKEYNAME_LEN);
 
 		wk[i].wk_idx = 1;
 		if ((s = strrchr(wk[i].wk_name, ':')) != NULL) {
@@ -2097,7 +2054,7 @@
 			wk[i].wk_idx = (uint_t)(s[1] - '0');
 			*s = '\0';
 		}
-		wk[i].wk_len = WLADM_MAX_WEPKEY_LEN;
+		wk[i].wk_len = DLADM_WLAN_MAX_WEPKEY_LEN;
 
 		status = dladm_get_secobj(wk[i].wk_name, &class,
 		    wk[i].wk_val, &wk[i].wk_len, 0);
@@ -2125,14 +2082,14 @@
 do_connect_wifi(int argc, char **argv)
 {
 	int			option;
-	wladm_wlan_attr_t	attr, *attrp;
-	wladm_status_t		status = WLADM_STATUS_OK;
-	int			timeout = WLADM_CONNECT_TIMEOUT_DEFAULT;
+	dladm_wlan_attr_t	attr, *attrp;
+	dladm_status_t		status = DLADM_STATUS_OK;
+	int			timeout = DLADM_WLAN_CONNECT_TIMEOUT_DEFAULT;
 	const char		*link = NULL;
-	wladm_wep_key_t		*keys = NULL;
+	dladm_wlan_wepkey_t	*keys = NULL;
 	uint_t			key_count = 0;
 	uint_t			flags = 0;
-	wladm_secmode_t		keysecmode = WLADM_SECMODE_NONE;
+	dladm_wlan_secmode_t	keysecmode = DLADM_WLAN_SECMODE_NONE;
 
 	opterr = 0;
 	(void) memset(&attr, 0, sizeof (attr));
@@ -2140,56 +2097,58 @@
 	    wifi_longopts, NULL)) != -1) {
 		switch (option) {
 		case 'e':
-			status = wladm_str2essid(optarg, &attr.wa_essid);
-			if (status != WLADM_STATUS_OK)
+			status = dladm_wlan_str2essid(optarg, &attr.wa_essid);
+			if (status != DLADM_STATUS_OK)
 				die("invalid ESSID '%s'", optarg);
 
-			attr.wa_valid |= WLADM_WLAN_ATTR_ESSID;
+			attr.wa_valid |= DLADM_WLAN_ATTR_ESSID;
 			/*
 			 * Try to connect without doing a scan.
 			 */
-			flags |= WLADM_OPT_NOSCAN;
+			flags |= DLADM_WLAN_CONNECT_NOSCAN;
 			break;
 		case 'i':
-			status = wladm_str2bssid(optarg, &attr.wa_bssid);
-			if (status != WLADM_STATUS_OK)
+			status = dladm_wlan_str2bssid(optarg, &attr.wa_bssid);
+			if (status != DLADM_STATUS_OK)
 				die("invalid BSSID %s", optarg);
 
-			attr.wa_valid |= WLADM_WLAN_ATTR_BSSID;
+			attr.wa_valid |= DLADM_WLAN_ATTR_BSSID;
 			break;
 		case 'a':
-			status = wladm_str2auth(optarg, &attr.wa_auth);
-			if (status != WLADM_STATUS_OK)
+			status = dladm_wlan_str2auth(optarg, &attr.wa_auth);
+			if (status != DLADM_STATUS_OK)
 				die("invalid authentication mode '%s'", optarg);
 
-			attr.wa_valid |= WLADM_WLAN_ATTR_AUTH;
+			attr.wa_valid |= DLADM_WLAN_ATTR_AUTH;
 			break;
 		case 'm':
-			status = wladm_str2mode(optarg, &attr.wa_mode);
-			if (status != WLADM_STATUS_OK)
+			status = dladm_wlan_str2mode(optarg, &attr.wa_mode);
+			if (status != DLADM_STATUS_OK)
 				die("invalid mode '%s'", optarg);
 
-			attr.wa_valid |= WLADM_WLAN_ATTR_MODE;
+			attr.wa_valid |= DLADM_WLAN_ATTR_MODE;
 			break;
 		case 'b':
-			status = wladm_str2bsstype(optarg, &attr.wa_bsstype);
-			if (status != WLADM_STATUS_OK)
+			if ((status = dladm_wlan_str2bsstype(optarg,
+			    &attr.wa_bsstype)) != DLADM_STATUS_OK) {
 				die("invalid bsstype '%s'", optarg);
-
-			attr.wa_valid |= WLADM_WLAN_ATTR_BSSTYPE;
+			}
+
+			attr.wa_valid |= DLADM_WLAN_ATTR_BSSTYPE;
 			break;
 		case 's':
-			status = wladm_str2secmode(optarg, &attr.wa_secmode);
-			if (status != WLADM_STATUS_OK)
+			if ((status = dladm_wlan_str2secmode(optarg,
+			    &attr.wa_secmode)) != DLADM_STATUS_OK) {
 				die("invalid security mode '%s'", optarg);
-
-			attr.wa_valid |= WLADM_WLAN_ATTR_SECMODE;
+			}
+
+			attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE;
 			break;
 		case 'k':
 			if (parse_wep_keys(optarg, &keys, &key_count) < 0)
 				die("invalid key(s) '%s'", optarg);
 
-			keysecmode = WLADM_SECMODE_WEP;
+			keysecmode = DLADM_WLAN_SECMODE_WEP;
 			break;
 		case 'T':
 			if (strcasecmp(optarg, "forever") == 0) {
@@ -2200,7 +2159,7 @@
 				die("invalid timeout value '%s'", optarg);
 			break;
 		case 'c':
-			flags |= WLADM_OPT_CREATEIBSS;
+			flags |= DLADM_WLAN_CONNECT_CREATEIBSS;
 			break;
 		default:
 			die_opterr(optopt, option);
@@ -2208,17 +2167,17 @@
 		}
 	}
 
-	if (keysecmode == WLADM_SECMODE_NONE) {
-		if ((attr.wa_valid & WLADM_WLAN_ATTR_SECMODE) != 0 &&
-		    attr.wa_secmode == WLADM_SECMODE_WEP)
+	if (keysecmode == DLADM_WLAN_SECMODE_NONE) {
+		if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0 &&
+		    attr.wa_secmode == DLADM_WLAN_SECMODE_WEP)
 			die("key required for security mode 'wep'");
 	} else {
-		if ((attr.wa_valid & WLADM_WLAN_ATTR_SECMODE) != 0 &&
+		if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0 &&
 		    attr.wa_secmode != keysecmode)
 			die("incompatible -s and -k options");
 	}
 	attr.wa_secmode = keysecmode;
-	attr.wa_valid |= WLADM_WLAN_ATTR_SECMODE;
+	attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE;
 
 	if (optind == (argc - 1))
 		link = argv[optind];
@@ -2230,7 +2189,7 @@
 
 		wcattr.wc_link = NULL;
 		wcattr.wc_count = 0;
-		(void) wladm_walk(&wcattr, do_count_wlan);
+		(void) dladm_wlan_walk(&wcattr, do_count_wlan);
 		if (wcattr.wc_count == 0) {
 			die("no wifi links are available");
 		} else if (wcattr.wc_count > 1) {
@@ -2241,17 +2200,17 @@
 	}
 	attrp = (attr.wa_valid == 0) ? NULL : &attr;
 again:
-	status = wladm_connect(link, attrp, timeout, keys, key_count, flags);
-	if (status != WLADM_STATUS_OK) {
-		if ((flags & WLADM_OPT_NOSCAN) != 0) {
+	if ((status = dladm_wlan_connect(link, attrp, timeout, keys,
+	    key_count, flags)) != DLADM_STATUS_OK) {
+		if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0) {
 			/*
 			 * Try again with scanning and filtering.
 			 */
-			flags &= ~WLADM_OPT_NOSCAN;
+			flags &= ~DLADM_WLAN_CONNECT_NOSCAN;
 			goto again;
 		}
 
-		if (status == WLADM_STATUS_NOTFOUND) {
+		if (status == DLADM_STATUS_NOTFOUND) {
 			if (attr.wa_valid == 0) {
 				die("no wifi networks are available");
 			} else {
@@ -2259,7 +2218,7 @@
 				    "criteria are available");
 			}
 		}
-		die_wlerr(status, "cannot connect link '%s'", link);
+		die_dlerr(status, "cannot connect link '%s'", link);
 	}
 	free(keys);
 }
@@ -2268,11 +2227,11 @@
 static boolean_t
 do_all_disconnect_wifi(void *arg, const char *link)
 {
-	wladm_status_t	status;
-
-	status = wladm_disconnect(link);
-	if (status != WLADM_STATUS_OK)
-		warn_wlerr(status, "cannot disconnect link '%s'", link);
+	dladm_status_t	status;
+
+	status = dladm_wlan_disconnect(link);
+	if (status != DLADM_STATUS_OK)
+		warn_dlerr(status, "cannot disconnect link '%s'", link);
 
 	return (B_TRUE);
 }
@@ -2283,7 +2242,7 @@
 	int			option;
 	const char		*link = NULL;
 	boolean_t		all_links = B_FALSE;
-	wladm_status_t		status;
+	dladm_status_t		status;
 	wlan_count_attr_t	wcattr;
 
 	opterr = 0;
@@ -2308,7 +2267,7 @@
 		if (!all_links) {
 			wcattr.wc_link = NULL;
 			wcattr.wc_count = 0;
-			(void) wladm_walk(&wcattr, do_count_wlan);
+			(void) dladm_wlan_walk(&wcattr, do_count_wlan);
 			if (wcattr.wc_count == 0) {
 				die("no wifi links are available");
 			} else if (wcattr.wc_count > 1) {
@@ -2317,13 +2276,14 @@
 			}
 			link = wcattr.wc_link;
 		} else {
-			(void) wladm_walk(&all_links, do_all_disconnect_wifi);
+			(void) dladm_wlan_walk(&all_links,
+			    do_all_disconnect_wifi);
 			return;
 		}
 	}
-	status = wladm_disconnect(link);
-	if (status != WLADM_STATUS_OK)
-		die_wlerr(status, "cannot disconnect link '%s'", link);
+	status = dladm_wlan_disconnect(link);
+	if (status != DLADM_STATUS_OK)
+		die_dlerr(status, "cannot disconnect link '%s'", link);
 }
 
 #define	MAX_PROPS		32
@@ -2347,9 +2307,11 @@
 	char		*ls_line;
 	char		**ls_propvals;
 	prop_list_t	*ls_proplist;
-	boolean_t	ls_parseable;
-	boolean_t	ls_persist;
-	boolean_t	ls_header;
+	uint32_t	ls_parseable : 1,
+			ls_persist : 1,
+			ls_header : 1,
+			ls_pad_bits : 29;
+	dladm_status_t	ls_status;
 } show_linkprop_state_t;
 
 static void
@@ -2447,15 +2409,22 @@
 	status = dladm_get_prop(statep->ls_link, type, propname,
 	    propvals, &valcnt);
 	if (status != DLADM_STATUS_OK) {
-		if (status == DLADM_STATUS_NOTSUP || statep->ls_persist) {
+		if (status == DLADM_STATUS_TEMPONLY) {
+			statep->ls_status = status;
+			return;
+		} else if (status == DLADM_STATUS_NOTSUP ||
+		    statep->ls_persist) {
 			valcnt = 1;
 			if (type == DLADM_PROP_VAL_CURRENT)
 				propvals = &unknown;
 			else
 				propvals = &notsup;
 		} else {
-			die_dlerr(status, "cannot get link property '%s'",
-			    propname);
+			statep->ls_status = status;
+			warn_dlerr(status,
+			    "cannot get link property '%s' for %s",
+			    propname, statep->ls_link);
+			return;
 		}
 	}
 
@@ -2488,9 +2457,6 @@
 	char			*ptr = statep->ls_line;
 	char			*lim = ptr + MAX_PROP_LINE;
 
-	if (statep->ls_persist && dladm_is_prop_temponly(propname, NULL))
-		return (B_TRUE);
-
 	if (statep->ls_parseable)
 		ptr += snprintf(ptr, lim - ptr, "LINK=\"%s\" ",
 		    statep->ls_link);
@@ -2505,10 +2471,24 @@
 	print_linkprop(statep, propname,
 	    statep->ls_persist ? DLADM_PROP_VAL_PERSISTENT :
 	    DLADM_PROP_VAL_CURRENT, "VALUE", "%-14s ", &ptr);
+
+	/*
+	 * If we failed to query the link property, for example, query
+	 * the persistent value of a non-persistable link property, simply
+	 * skip the output.
+	 */
+	if (statep->ls_status != DLADM_STATUS_OK)
+		return (B_TRUE);
+
 	print_linkprop(statep, propname, DLADM_PROP_VAL_DEFAULT,
 	    "DEFAULT", "%-14s ", &ptr);
+	if (statep->ls_status != DLADM_STATUS_OK)
+		return (B_TRUE);
+
 	print_linkprop(statep, propname, DLADM_PROP_VAL_MODIFIABLE,
 	    "POSSIBLE", "%-20s ", &ptr);
+	if (statep->ls_status != DLADM_STATUS_OK)
+		return (B_TRUE);
 
 	if (statep->ls_header) {
 		statep->ls_header = B_FALSE;
@@ -2558,6 +2538,7 @@
 		usage();
 
 	state.ls_proplist = proplist;
+	state.ls_status = DLADM_STATUS_OK;
 
 	if (state.ls_link == NULL) {
 		(void) dladm_walk(show_linkprop_onelink, &state);
@@ -2565,6 +2546,9 @@
 		show_linkprop_onelink(&state, state.ls_link);
 	}
 	free_props(proplist);
+
+	if (state.ls_status != DLADM_STATUS_OK)
+		exit(EXIT_FAILURE);
 }
 
 static void
@@ -2590,8 +2574,11 @@
 	 * (below) will proceed slowly unless we hold the link open.
 	 */
 	(void) snprintf(linkname, MAXPATHLEN, "/dev/%s", link);
-	if ((fd = open(linkname, O_RDWR)) < 0)
-		die("cannot open %s: %s", link, strerror(errno));
+	if ((fd = open(linkname, O_RDWR)) < 0) {
+		warn("cannot open %s: %s", link, strerror(errno));
+		statep->ls_status = DLADM_STATUS_NOTFOUND;
+		return;
+	}
 
 	buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) * MAX_PROP_VALS +
 	    MAX_PROP_LINE);
@@ -2607,15 +2594,13 @@
 	    (sizeof (char *) + DLADM_PROP_VAL_MAX) * MAX_PROP_VALS;
 
 	if (proplist != NULL) {
-		for (i = 0; i < proplist->pl_count; i++) {
-			if (!show_linkprop(statep,
-			    proplist->pl_info[i].pi_name))
-				break;
-		}
+		for (i = 0; i < proplist->pl_count; i++)
+			(void) show_linkprop(statep,
+			    proplist->pl_info[i].pi_name);
 	} else {
 		status = dladm_walk_prop(link, statep, show_linkprop);
 		if (status != DLADM_STATUS_OK)
-			die_dlerr(status, "show-linkprop");
+			warn_dlerr(status, "show-linkprop failed for %s", link);
 	}
 	(void) close(fd);
 	free(buf);
@@ -3354,22 +3339,6 @@
 
 /* PRINTFLIKE2 */
 static void
-warn_wlerr(wladm_status_t err, const char *format, ...)
-{
-	va_list alist;
-	char	errmsg[WLADM_STRSIZE];
-
-	format = gettext(format);
-	(void) fprintf(stderr, gettext("%s: warning: "), progname);
-
-	va_start(alist, format);
-	(void) vfprintf(stderr, format, alist);
-	va_end(alist);
-	(void) fprintf(stderr, ": %s\n", wladm_status2str(err, errmsg));
-}
-
-/* PRINTFLIKE2 */
-static void
 warn_dlerr(dladm_status_t err, const char *format, ...)
 {
 	va_list alist;
@@ -3386,46 +3355,6 @@
 
 /* PRINTFLIKE2 */
 static void
-die_laerr(laadm_diag_t diag, const char *format, ...)
-{
-	va_list alist;
-	char	*errstr = strerror(errno);
-
-	format = gettext(format);
-	(void) fprintf(stderr, "%s: ", progname);
-
-	va_start(alist, format);
-	(void) vfprintf(stderr, format, alist);
-	va_end(alist);
-
-	if (diag == 0)
-		(void) fprintf(stderr, ": %s\n", errstr);
-	else
-		(void) fprintf(stderr, ": %s (%s)\n", errstr, laadm_diag(diag));
-
-	exit(EXIT_FAILURE);
-}
-
-/* PRINTFLIKE2 */
-static void
-die_wlerr(wladm_status_t err, const char *format, ...)
-{
-	va_list alist;
-	char	errmsg[WLADM_STRSIZE];
-
-	format = gettext(format);
-	(void) fprintf(stderr, "%s: ", progname);
-
-	va_start(alist, format);
-	(void) vfprintf(stderr, format, alist);
-	va_end(alist);
-	(void) fprintf(stderr, ": %s\n", wladm_status2str(err, errmsg));
-
-	exit(EXIT_FAILURE);
-}
-
-/* PRINTFLIKE2 */
-static void
 die_dlerr(dladm_status_t err, const char *format, ...)
 {
 	va_list alist;
--- a/usr/src/cmd/rcm_daemon/Makefile.com	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/cmd/rcm_daemon/Makefile.com	Wed Mar 21 09:48:58 2007 -0700
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -106,7 +106,7 @@
 LDLIBS_MODULES = 
 SUNW_pool_rcm.so := LDLIBS_MODULES += -L$(ROOT)/usr/lib -lpool
 SUNW_svm_rcm.so	:= LDLIBS_MODULES += -L$(ROOT)/usr/lib -lmeta
-SUNW_network_rcm.so := LDLIBS_MODULES += -L$(ROOT)/lib -llaadm
+SUNW_network_rcm.so := LDLIBS_MODULES += -L$(ROOT)/lib -ldladm
 SUNW_ip_rcm.so := LDLIBS_MODULES += -L$(ROOT)/lib -linetutil
 SUNW_ip_anon_rcm.so := LDLIBS_MODULES += -L$(ROOT)/lib -linetutil
 
--- a/usr/src/cmd/rcm_daemon/common/network_rcm.c	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/cmd/rcm_daemon/common/network_rcm.c	Wed Mar 21 09:48:58 2007 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -41,7 +41,7 @@
 #include <libdevinfo.h>
 #include <sys/types.h>
 #include <net/if.h>
-#include <liblaadm.h>
+#include <libdlaggr.h>
 #include "rcm_module.h"
 
 /*
@@ -751,10 +751,10 @@
 } aggr_walker_state_t;
 
 static int
-aggr_walker(void *arg, laadm_grp_attr_sys_t *grp)
+aggr_walker(void *arg, dladm_aggr_grp_attr_t *grp)
 {
 	aggr_walker_state_t *state = arg;
-	laadm_port_attr_sys_t *port;
+	dladm_aggr_port_attr_t *port;
 	int i;
 
 	for (i = 0; i < grp->lg_nports; i++) {
@@ -782,7 +782,7 @@
 	(void) snprintf(state.dev_name, sizeof (state.dev_name), "%s%d",
 	    driver, ppa);
 
-	if (laadm_walk_sys(aggr_walker, &state) != 0) {
+	if (dladm_aggr_walk(aggr_walker, &state) != 0) {
 		rcm_log_message(RCM_ERROR, gettext("NET: cannot walk "
 		    "aggregations (%s)\n"), strerror(errno));
 		return (B_FALSE);
--- a/usr/src/cmd/zoneadmd/vplat.c	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/cmd/zoneadmd/vplat.c	Wed Mar 21 09:48:58 2007 -0700
@@ -76,7 +76,7 @@
 
 #include <sys/dlpi.h>
 #include <libdlpi.h>
-#include <libdladm.h>
+#include <libdllink.h>
 
 #include <inet/tcp.h>
 #include <arpa/inet.h>
--- a/usr/src/lib/Makefile	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/lib/Makefile	Wed Mar 21 09:48:58 2007 -0700
@@ -112,9 +112,7 @@
 	libkmf		\
 	libkstat	\
 	libkvm		\
-        liblaadm        \
 	liblm		\
-	libmacadm	\
 	libmalloc	\
 	libmapmalloc	\
 	libmtmalloc	\
@@ -185,7 +183,6 @@
 	madv		\
 	mpss		\
 	libdisasm	\
-	libwladm	\
 	libwrap		\
 	libxcurses	\
 	libxcurses2	\
@@ -295,7 +292,6 @@
 	libuutil	\
 	libwanboot	\
 	libwanbootutil	\
-	libwladm	\
 	libzfs		\
 	libzonecfg	\
 	lvm		\
@@ -350,8 +346,6 @@
 	libiscsitgt	\
 	libkstat	\
 	libkvm		\
-        liblaadm        \
-	libmacadm	\
 	libmail		\
 	libmd		\
 	libmtmalloc	\
@@ -386,7 +380,6 @@
 	libvolmgt	\
 	libumem		\
 	libuutil	\
-	libwladm	\
 	libwrap		\
 	libxcurses2	\
 	libzfs		\
@@ -475,8 +468,8 @@
 libdhcpagent:	libsocket libdhcputil libuuid libdlpi
 libdhcpsvc:	libinetutil
 libdhcputil:	libnsl libgen libinetutil libdlpi
+libdladm:	libdlpi libdevinfo libinetutil libsocket
 libdlpi:	libinetutil
-libdladm:	libdlpi libdevinfo libwladm libinetutil
 libdtrace:	libproc libgen libctf
 libdtrace_jni:	libuutil libdtrace
 libefi:		libuuid
@@ -487,7 +480,6 @@
 libkmf:		libcryptoutil pkcs11 openssl
 libnsl:		libmd5 libscf
 libmapid:	libresolv
-libmacadm:	libdevinfo
 libuuid:	libsocket
 libinetutil:	libsocket
 libsecdb:	libnsl
@@ -508,7 +500,6 @@
 libwanboot:	libnvpair libresolv libnsl libsocket libdevinfo libinetutil \
 		libdhcputil openssl
 libwanbootutil:	libnsl
-libwladm:	libdevinfo libsocket
 pam_modules:	libproject passwdutil $(SMARTCARD)
 libscf:		libuutil libmd
 libinetsvc:	libscf
--- a/usr/src/lib/libdladm/Makefile	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/lib/libdladm/Makefile	Wed Mar 21 09:48:58 2007 -0700
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -27,13 +27,15 @@
 
 include $(SRC)/lib/Makefile.lib
 
-HDRS =		libdladm.h libdladm_impl.h
+HDRS =		libdladm.h libdladm_impl.h libdllink.h libdlaggr.h	\
+		libdlwlan.h libdlwlan_impl.h
 HDRDIR =	common
 
 SUBDIRS =	$(MACH)
 
 POFILE =	libdladm.po
-MSGFILES =	common/libdladm.c common/linkprop.c common/secobj.c
+MSGFILES =	common/libdladm.c common/linkprop.c common/secobj.c	\
+		common/libdllink.c comon/libdlaggr.c common/libdlwlan.c
 XGETFLAGS =     -a -x libdladm.xcl
 
 all :=		TARGET = all
--- a/usr/src/lib/libdladm/Makefile.com	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/lib/libdladm/Makefile.com	Wed Mar 21 09:48:58 2007 -0700
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -27,7 +27,7 @@
 
 LIBRARY = libdladm.a
 VERS    = .1
-OBJECTS = libdladm.o secobj.o linkprop.o
+OBJECTS = libdladm.o secobj.o linkprop.o libdllink.o libdlaggr.o libdlwlan.o
 
 include ../../Makefile.lib
 
@@ -35,7 +35,7 @@
 include ../../Makefile.rootfs
 
 LIBS =		$(DYNLIB) $(LINTLIB)
-LDLIBS +=	-ldevinfo -ldlpi -lc -lwladm -linetutil
+LDLIBS +=	-ldevinfo -ldlpi -lc -linetutil -lsocket
 
 SRCDIR =	../common
 $(LINTLIB) :=	SRCS = $(SRCDIR)/$(LINTSRC)
--- a/usr/src/lib/libdladm/common/libdladm.c	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/lib/libdladm/common/libdladm.c	Wed Mar 21 09:48:58 2007 -0700
@@ -25,30 +25,16 @@
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
-#include <ctype.h>
 #include <unistd.h>
 #include <stropts.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <strings.h>
 #include <dirent.h>
-#include <net/if.h>
 #include <sys/stat.h>
-#include <sys/dld.h>
-#include <libdlpi.h>
-#include <libdevinfo.h>
+#include <libdladm.h>
 #include <libdladm_impl.h>
 #include <libintl.h>
-#include <sys/vlan.h>
-
-typedef struct dladm_dev {
-	char			dd_name[IFNAMSIZ];
-	struct dladm_dev	*dd_next;
-} dladm_dev_t;
-
-typedef struct dladm_walk {
-	dladm_dev_t		*dw_dev_list;
-} dladm_walk_t;
 
 static char		dladm_rootdir[MAXPATHLEN] = "/";
 
@@ -69,239 +55,6 @@
 	return (ioctl(fd, I_STR, &iocb));
 }
 
-/*
- * Return the attributes of the specified datalink from the DLD driver.
- */
-static int
-i_dladm_info(int fd, const char *name, dladm_attr_t *dap)
-{
-	dld_ioc_attr_t	dia;
-
-	if (strlen(name) >= IFNAMSIZ) {
-		errno = EINVAL;
-		return (-1);
-	}
-
-	(void) strlcpy(dia.dia_name, name, IFNAMSIZ);
-
-	if (i_dladm_ioctl(fd, DLDIOCATTR, &dia, sizeof (dia)) < 0)
-		return (-1);
-
-	(void) strlcpy(dap->da_dev, dia.dia_dev, MAXNAMELEN);
-	dap->da_max_sdu = dia.dia_max_sdu;
-	dap->da_vid = dia.dia_vid;
-
-	return (0);
-}
-
-/*
- * Adds a datalink to the array corresponding to arg.
- */
-static void
-i_dladm_nt_net_add(void *arg, char *name)
-{
-	dladm_walk_t	*dwp = arg;
-	dladm_dev_t	*ddp = dwp->dw_dev_list;
-	dladm_dev_t	**lastp = &dwp->dw_dev_list;
-
-	while (ddp) {
-		/*
-		 * Skip duplicates.
-		 */
-		if (strcmp(ddp->dd_name, name) == 0)
-			return;
-
-		lastp = &ddp->dd_next;
-		ddp = ddp->dd_next;
-	}
-
-	if ((ddp = malloc(sizeof (*ddp))) == NULL)
-		return;
-
-	(void) strlcpy(ddp->dd_name, name, IFNAMSIZ);
-	ddp->dd_next = NULL;
-	*lastp = ddp;
-}
-
-/*
- * Walker callback invoked for each DDI_NT_NET node.
- */
-static int
-i_dladm_nt_net_walk(di_node_t node, di_minor_t minor, void *arg)
-{
-	char		linkname[DLPI_LINKNAME_MAX];
-	dlpi_handle_t	dh;
-
-	if (dlpi_makelink(linkname, di_minor_name(minor),
-	    di_instance(node)) != DLPI_SUCCESS)
-		return (DI_WALK_CONTINUE);
-
-	if (dlpi_open(linkname, &dh, 0) == DLPI_SUCCESS) {
-		i_dladm_nt_net_add(arg, linkname);
-		dlpi_close(dh);
-	}
-	return (DI_WALK_CONTINUE);
-}
-
-/*
- * Hold a data-link.
- */
-static int
-i_dladm_hold_link(const char *name, zoneid_t zoneid, boolean_t docheck)
-{
-	int		fd;
-	dld_hold_vlan_t	dhv;
-
-	if (strlen(name) >= IFNAMSIZ) {
-		errno = EINVAL;
-		return (-1);
-	}
-
-	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
-		return (-1);
-
-	bzero(&dhv, sizeof (dld_hold_vlan_t));
-	(void) strlcpy(dhv.dhv_name, name, IFNAMSIZ);
-	dhv.dhv_zid = zoneid;
-	dhv.dhv_docheck = docheck;
-
-	if (i_dladm_ioctl(fd, DLDIOCHOLDVLAN, &dhv, sizeof (dhv)) < 0) {
-		int olderrno = errno;
-
-		(void) close(fd);
-		errno = olderrno;
-		return (-1);
-	}
-
-	(void) close(fd);
-	return (0);
-}
-
-/*
- * Release a data-link.
- */
-static int
-i_dladm_rele_link(const char *name, zoneid_t zoneid, boolean_t docheck)
-{
-	int		fd;
-	dld_hold_vlan_t	dhv;
-
-	if (strlen(name) >= IFNAMSIZ) {
-		errno = EINVAL;
-		return (-1);
-	}
-
-	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
-		return (-1);
-
-	bzero(&dhv, sizeof (dld_hold_vlan_t));
-	(void) strlcpy(dhv.dhv_name, name, IFNAMSIZ);
-	dhv.dhv_zid = zoneid;
-	dhv.dhv_docheck = docheck;
-
-	if (i_dladm_ioctl(fd, DLDIOCRELEVLAN, &dhv, sizeof (dhv)) < 0) {
-		int olderrno = errno;
-
-		(void) close(fd);
-		errno = olderrno;
-		return (-1);
-	}
-
-	(void) close(fd);
-	return (0);
-}
-
-/*
- * Invoke the specified callback function for each active DDI_NT_NET
- * node.
- */
-int
-dladm_walk(void (*fn)(void *, const char *), void *arg)
-{
-	di_node_t	root;
-	dladm_walk_t	dw;
-	dladm_dev_t	*ddp, *last_ddp;
-
-	if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL) {
-		errno = EFAULT;
-		return (-1);
-	}
-	dw.dw_dev_list = NULL;
-
-	(void) di_walk_minor(root, DDI_NT_NET, DI_CHECK_ALIAS, &dw,
-	    i_dladm_nt_net_walk);
-
-	di_fini(root);
-
-	ddp = dw.dw_dev_list;
-	while (ddp) {
-		fn(arg, ddp->dd_name);
-		last_ddp = ddp;
-		ddp = ddp->dd_next;
-		free(last_ddp);
-	}
-
-	return (0);
-}
-
-/*
- * Invoke the specified callback function for each vlan managed by dld
- */
-int
-dladm_walk_vlan(void (*fn)(void *, const char *), void *arg, const char *name)
-{
-	int		fd, bufsize, i;
-	int		nvlan = 4094;
-	dld_ioc_vlan_t	*iocp = NULL;
-	dld_vlan_info_t	*dvip;
-
-	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
-		return (-1);
-
-	bufsize = sizeof (dld_ioc_vlan_t) + nvlan * sizeof (dld_vlan_info_t);
-
-	if ((iocp = (dld_ioc_vlan_t *)calloc(1, bufsize)) == NULL)
-		return (-1);
-
-	(void) strlcpy((char *)iocp->div_name, name, IFNAMSIZ);
-	if (i_dladm_ioctl(fd, DLDIOCVLAN, iocp, bufsize) == 0) {
-		dvip = (dld_vlan_info_t *)(iocp + 1);
-		for (i = 0; i < iocp->div_count; i++)
-			(*fn)(arg, dvip[i].dvi_name);
-	}
-	/*
-	 * Note: Callers of dladm_walk_vlan() ignore the return
-	 * value of this routine. So ignoring ioctl failure case
-	 * and just returning 0.
-	 */
-	free(iocp);
-	(void) close(fd);
-	return (0);
-}
-
-
-/*
- * Returns the current attributes of the specified datalink.
- */
-int
-dladm_info(const char *name, dladm_attr_t *dap)
-{
-	int		fd;
-
-	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
-		return (-1);
-
-	if (i_dladm_info(fd, name, dap) < 0)
-		goto failed;
-
-	(void) close(fd);
-	return (0);
-
-failed:
-	(void) close(fd);
-	return (-1);
-}
-
 const char *
 dladm_status2str(dladm_status_t status, char *buf)
 {
@@ -356,6 +109,24 @@
 	case DLADM_STATUS_TEMPONLY:
 		s = "change cannot be persistent, specify -t please";
 		break;
+	case DLADM_STATUS_TIMEDOUT:
+		s = "operation timed out";
+		break;
+	case DLADM_STATUS_ISCONN:
+		s = "already connected";
+		break;
+	case DLADM_STATUS_NOTCONN:
+		s = "not connected";
+		break;
+	case DLADM_STATUS_REPOSITORYINVAL:
+		s = "invalid configuration repository";
+		break;
+	case DLADM_STATUS_MACADDRINVAL:
+		s = "invalid MAC address";
+		break;
+	case DLADM_STATUS_KEYINVAL:
+		s = "invalid key";
+		break;
 	default:
 		s = "<unknown error>";
 		break;
@@ -558,21 +329,3 @@
 	(void) closedir(dp);
 	return (DLADM_STATUS_OK);
 }
-
-/*
- * Do a "hold" operation to a link.
- */
-int
-dladm_hold_link(const char *name, zoneid_t zoneid, boolean_t docheck)
-{
-	return (i_dladm_hold_link(name, zoneid, docheck));
-}
-
-/*
- * Do a "release" operation to a link.
- */
-int
-dladm_rele_link(const char *name, zoneid_t zoneid, boolean_t docheck)
-{
-	return (i_dladm_rele_link(name, zoneid, docheck));
-}
--- a/usr/src/lib/libdladm/common/libdladm.h	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/lib/libdladm/common/libdladm.h	Wed Mar 21 09:48:58 2007 -0700
@@ -28,23 +28,17 @@
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/dls.h>
+/*
+ * This file includes structures, macros and common routines shared by all
+ * data-link administration, and routines which do not directly administrate
+ * links. For example, dladm_status2str().
+ */
 
 #ifdef	__cplusplus
 extern "C" {
 #endif
 
-typedef struct dladm_attr {
-	char		da_dev[MAXNAMELEN];
-	uint_t		da_max_sdu;
-	uint16_t	da_vid;
-} dladm_attr_t;
-
 #define	DLADM_STRSIZE		256
-#define	DLADM_SECOBJ_VAL_MAX	256
-#define	DLADM_PROP_VAL_MAX	256
 #define	DLADM_OPT_TEMP		0x00000001
 #define	DLADM_OPT_CREATE	0x00000002
 #define	DLADM_OPT_PERSIST	0x00000004
@@ -65,7 +59,13 @@
 	DLADM_STATUS_DBNOTFOUND,
 	DLADM_STATUS_DENIED,
 	DLADM_STATUS_IOERR,
-	DLADM_STATUS_TEMPONLY
+	DLADM_STATUS_TEMPONLY,
+	DLADM_STATUS_TIMEDOUT,
+	DLADM_STATUS_ISCONN,
+	DLADM_STATUS_NOTCONN,
+	DLADM_STATUS_REPOSITORYINVAL,
+	DLADM_STATUS_MACADDRINVAL,
+	DLADM_STATUS_KEYINVAL
 } dladm_status_t;
 
 typedef enum {
@@ -75,41 +75,8 @@
 	DLADM_PROP_VAL_PERSISTENT
 } dladm_prop_type_t;
 
-#define		DLADM_SECOBJ_CLASS_WEP	0
-typedef int	dladm_secobj_class_t;
-
-typedef void (dladm_walkcb_t)(void *, const char *);
-
-extern int	dladm_walk(dladm_walkcb_t *, void *);
-extern int	dladm_walk_vlan(dladm_walkcb_t *, void *, const char *);
-extern int	dladm_info(const char *, dladm_attr_t *);
-extern int	dladm_hold_link(const char *, zoneid_t, boolean_t);
-extern int	dladm_rele_link(const char *, zoneid_t, boolean_t);
-
-extern dladm_status_t	dladm_set_prop(const char *, const char *,
-			    char **, uint_t, uint_t, char **);
-extern dladm_status_t	dladm_get_prop(const char *, dladm_prop_type_t,
-			    const char *, char **, uint_t *);
-extern dladm_status_t	dladm_walk_prop(const char *, void *,
-			    boolean_t (*)(void *, const char *));
-extern boolean_t	dladm_is_prop_temponly(const char *, char **);
-
-extern dladm_status_t	dladm_set_secobj(const char *, dladm_secobj_class_t,
-			    uint8_t *, uint_t, uint_t);
-extern dladm_status_t	dladm_get_secobj(const char *, dladm_secobj_class_t *,
-			    uint8_t *, uint_t *, uint_t);
-extern dladm_status_t	dladm_unset_secobj(const char *, uint_t);
-extern dladm_status_t	dladm_walk_secobj(void *,
-			    boolean_t (*)(void *, const char *), uint_t);
-
 extern const char	*dladm_status2str(dladm_status_t, char *);
-extern const char	*dladm_secobjclass2str(dladm_secobj_class_t, char *);
-extern dladm_status_t	dladm_str2secobjclass(const char *,
-			    dladm_secobj_class_t *);
-
-extern dladm_status_t	dladm_init_linkprop(void);
-extern dladm_status_t	dladm_init_secobj(void);
-extern dladm_status_t	dladm_set_rootdir(const char *rootdir);
+extern dladm_status_t	dladm_set_rootdir(const char *);
 
 #ifdef	__cplusplus
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libdladm/common/libdlaggr.c	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,1725 @@
+/*
+ * 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 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stropts.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <strings.h>
+#include <libintl.h>
+#include <net/if_types.h>
+#include <net/if_dl.h>
+#include <libdlaggr.h>
+#include <libdladm_impl.h>
+
+/*
+ * Link Aggregation Administration Library.
+ *
+ * This library is used by administration tools such as dladm(1M) to
+ * configure link aggregations.
+ *
+ * Link aggregation configuration information is saved in a text
+ * file of the following format:
+ *
+ * <db-file>	::= <groups>*
+ * <group>	::= <key> <sep> <policy> <sep> <nports> <sep> <ports> <sep>
+ *		      <mac> <sep> <lacp-mode> <sep> <lacp-timer>
+ * <sep>	::= ' ' | '\t'
+ * <key>	::= <number>
+ * <nports>	::= <number>
+ * <ports>	::= <port> <m-port>*
+ * <m-port>	::= ',' <port>
+ * <port>	::= <devname>
+ * <devname>	::= <string>
+ * <port-num>	::= <number>
+ * <policy>	::= <pol-level> <m-pol>*
+ * <m-pol>	::= ',' <pol-level>
+ * <pol-level>	::= 'L2' | 'L3' | 'L4'
+ * <mac>	::= 'auto' | <mac-addr>
+ * <mac-addr>	::= <hex> ':' <hex> ':' <hex> ':' <hex> ':' <hex> ':' <hex>
+ * <lacp-mode>	::= 'off' | 'active' | 'passive'
+ * <lacp-timer>	::= 'short' | 'long'
+ */
+
+#define	DLADM_AGGR_DEV		"/devices/pseudo/aggr@0:" AGGR_DEVNAME_CTL
+#define	DLADM_AGGR_DB		"/etc/dladm/aggregation.conf"
+#define	DLADM_AGGR_DB_TMP	"/etc/dladm/aggregation.conf.new"
+#define	DLADM_AGGR_DB_LOCK	"/tmp/aggregation.conf.lock"
+
+#define	DLADM_AGGR_DB_PERMS	S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
+#define	DLADM_AGGR_DB_OWNER	15	/* "dladm" UID */
+#define	DLADM_AGGR_DB_GROUP	3	/* "sys" GID */
+
+/*
+ * The largest configurable aggregation key.  Because by default the key is
+ * used as the DLPI device PPA and default VLAN PPA's are calculated as
+ * ((1000 * vid) + PPA), the largest key can't be > 999.
+ */
+#define	DLADM_AGGR_MAX_KEY	999
+
+#define	BLANK_LINE(s)	((s[0] == '\0') || (s[0] == '#') || (s[0] == '\n'))
+
+/* Limits on buffer size for LAIOC_INFO request */
+#define	MIN_INFO_SIZE (4*1024)
+#define	MAX_INFO_SIZE (128*1024)
+
+#define	MAXPATHLEN	1024
+
+static uchar_t	zero_mac[] = {0, 0, 0, 0, 0, 0};
+
+/* configuration database entry */
+typedef struct dladm_aggr_grp_attr_db {
+	uint32_t	lt_key;
+	uint32_t	lt_policy;
+	uint32_t	lt_nports;
+	dladm_aggr_port_attr_db_t *lt_ports;
+	boolean_t	lt_mac_fixed;
+	uchar_t		lt_mac[ETHERADDRL];
+	aggr_lacp_mode_t lt_lacp_mode;
+	aggr_lacp_timer_t lt_lacp_timer;
+} dladm_aggr_grp_attr_db_t;
+
+typedef struct dladm_aggr_up {
+	uint32_t	lu_key;
+	boolean_t	lu_found;
+	int		lu_fd;
+} dladm_aggr_up_t;
+
+typedef struct dladm_aggr_down {
+	uint32_t	ld_key;
+	boolean_t	ld_found;
+} dladm_aggr_down_t;
+
+typedef struct dladm_aggr_modify_attr {
+	uint32_t	ld_policy;
+	boolean_t	ld_mac_fixed;
+	uchar_t		ld_mac[ETHERADDRL];
+	aggr_lacp_mode_t ld_lacp_mode;
+	aggr_lacp_timer_t ld_lacp_timer;
+} dladm_aggr_modify_attr_t;
+
+typedef struct policy_s {
+	char		*pol_name;
+	uint32_t	policy;
+} policy_t;
+
+static policy_t policies[] = {
+	{"L2",		AGGR_POLICY_L2},
+	{"L3",		AGGR_POLICY_L3},
+	{"L4",		AGGR_POLICY_L4}};
+
+#define	NPOLICIES	(sizeof (policies) / sizeof (policy_t))
+
+typedef struct dladm_aggr_lacpmode_s {
+	char		*mode_str;
+	aggr_lacp_mode_t mode_id;
+} dladm_aggr_lacpmode_t;
+
+static dladm_aggr_lacpmode_t lacp_modes[] = {
+	{"off", AGGR_LACP_OFF},
+	{"active", AGGR_LACP_ACTIVE},
+	{"passive", AGGR_LACP_PASSIVE}};
+
+#define	NLACP_MODES	(sizeof (lacp_modes) / sizeof (dladm_aggr_lacpmode_t))
+
+typedef struct dladm_aggr_lacptimer_s {
+	char		*lt_str;
+	aggr_lacp_timer_t lt_id;
+} dladm_aggr_lacptimer_t;
+
+static dladm_aggr_lacptimer_t lacp_timers[] = {
+	{"short", AGGR_LACP_TIMER_SHORT},
+	{"long", AGGR_LACP_TIMER_LONG}};
+
+#define	NLACP_TIMERS	(sizeof (lacp_timers) / sizeof (dladm_aggr_lacptimer_t))
+
+typedef struct dladm_aggr_port_state {
+	char			*state_str;
+	aggr_port_state_t	state_id;
+} dladm_aggr_port_state_t;
+
+static dladm_aggr_port_state_t port_states[] = {
+	{"standby", AGGR_PORT_STATE_STANDBY },
+	{"attached", AGGR_PORT_STATE_ATTACHED }
+};
+
+#define	NPORT_STATES	\
+	(sizeof (port_states) / sizeof (dladm_aggr_port_state_t))
+
+typedef struct delete_db_state {
+	uint32_t	ds_key;
+	boolean_t	ds_found;
+} delete_db_state_t;
+
+typedef struct modify_db_state {
+	uint32_t		us_key;
+	uint32_t		us_mask;
+	dladm_aggr_modify_attr_t *us_attr_new;
+	dladm_aggr_modify_attr_t *us_attr_old;
+	boolean_t		us_found;
+} modify_db_state_t;
+
+typedef struct add_db_state {
+	dladm_aggr_grp_attr_db_t *as_attr;
+	boolean_t	as_found;
+} add_db_state_t;
+
+static int i_dladm_aggr_fput_grp(FILE *, dladm_aggr_grp_attr_db_t *);
+
+static int
+i_dladm_aggr_strioctl(int fd, int cmd, void *ptr, int ilen)
+{
+	struct strioctl str;
+
+	str.ic_cmd = cmd;
+	str.ic_timout = 0;
+	str.ic_len = ilen;
+	str.ic_dp = ptr;
+
+	return (ioctl(fd, I_STR, &str));
+}
+
+/*
+ * Open and lock the aggregation configuration file lock. The lock is
+ * acquired as a reader (F_RDLCK) or writer (F_WRLCK).
+ */
+static int
+i_dladm_aggr_lock_db(short type)
+{
+	int lock_fd;
+	struct flock lock;
+	int errno_save;
+
+	if ((lock_fd = open(DLADM_AGGR_DB_LOCK, O_RDWR | O_CREAT | O_TRUNC,
+	    DLADM_AGGR_DB_PERMS)) < 0)
+		return (-1);
+
+	lock.l_type = type;
+	lock.l_whence = SEEK_SET;
+	lock.l_start = 0;
+	lock.l_len = 0;
+
+	if (fcntl(lock_fd, F_SETLKW, &lock) < 0) {
+		errno_save = errno;
+		(void) close(lock_fd);
+		(void) unlink(DLADM_AGGR_DB_LOCK);
+		errno = errno_save;
+		return (-1);
+	}
+	return (lock_fd);
+}
+
+/*
+ * Unlock and close the specified file.
+ */
+static void
+i_dladm_aggr_unlock_db(int fd)
+{
+	struct flock lock;
+
+	if (fd < 0)
+		return;
+
+	lock.l_type = F_UNLCK;
+	lock.l_whence = SEEK_SET;
+	lock.l_start = 0;
+	lock.l_len = 0;
+
+	(void) fcntl(fd, F_SETLKW, &lock);
+	(void) close(fd);
+	(void) unlink(DLADM_AGGR_DB_LOCK);
+}
+
+/*
+ * Walk through the groups defined on the system and for each group <grp>,
+ * invoke <fn>(<arg>, <grp>);
+ * Terminate the walk if at any time <fn> returns non-NULL value
+ */
+int
+dladm_aggr_walk(int (*fn)(void *, dladm_aggr_grp_attr_t *), void *arg)
+{
+	laioc_info_t *ioc;
+	laioc_info_group_t *grp;
+	laioc_info_port_t *port;
+	dladm_aggr_grp_attr_t attr;
+	int rc, i, j, bufsize, fd;
+	char *where;
+
+	if ((fd = open(DLADM_AGGR_DEV, O_RDWR)) == -1)
+		return (-1);
+
+	bufsize = MIN_INFO_SIZE;
+	ioc = (laioc_info_t *)calloc(1, bufsize);
+	if (ioc == NULL) {
+		(void) close(fd);
+		errno = ENOMEM;
+		return (-1);
+	}
+
+tryagain:
+	rc = i_dladm_aggr_strioctl(fd, LAIOC_INFO, ioc, bufsize);
+
+	if (rc != 0) {
+		if (errno == ENOSPC) {
+			/*
+			 * The LAIOC_INFO call failed due to a short
+			 * buffer. Reallocate the buffer and try again.
+			 */
+			bufsize *= 2;
+			if (bufsize <= MAX_INFO_SIZE) {
+				ioc = (laioc_info_t *)realloc(ioc, bufsize);
+				if (ioc != NULL) {
+					bzero(ioc, sizeof (bufsize));
+					goto tryagain;
+				}
+			}
+		}
+		goto bail;
+	}
+
+	/*
+	 * Go through each group returned by the aggregation driver.
+	 */
+	where = (char *)(ioc + 1);
+	for (i = 0; i < ioc->li_ngroups; i++) {
+		/* LINTED E_BAD_PTR_CAST_ALIGN */
+		grp = (laioc_info_group_t *)where;
+
+		attr.lg_key = grp->lg_key;
+		attr.lg_nports = grp->lg_nports;
+		attr.lg_policy = grp->lg_policy;
+		attr.lg_lacp_mode = grp->lg_lacp_mode;
+		attr.lg_lacp_timer = grp->lg_lacp_timer;
+
+		bcopy(grp->lg_mac, attr.lg_mac, ETHERADDRL);
+		attr.lg_mac_fixed = grp->lg_mac_fixed;
+
+		attr.lg_ports = malloc(grp->lg_nports *
+		    sizeof (dladm_aggr_port_attr_t));
+		if (attr.lg_ports == NULL) {
+			errno = ENOMEM;
+			goto bail;
+		}
+
+		where = (char *)(grp + 1);
+
+		/*
+		 * Go through each port that is part of the group.
+		 */
+		for (j = 0; j < grp->lg_nports; j++) {
+			/* LINTED E_BAD_PTR_CAST_ALIGN */
+			port = (laioc_info_port_t *)where;
+
+			bcopy(port->lp_devname, attr.lg_ports[j].lp_devname,
+			    MAXNAMELEN + 1);
+			bcopy(port->lp_mac, attr.lg_ports[j].lp_mac,
+			    ETHERADDRL);
+			attr.lg_ports[j].lp_state = port->lp_state;
+			attr.lg_ports[j].lp_lacp_state = port->lp_lacp_state;
+
+			where = (char *)(port + 1);
+		}
+
+		rc = fn(arg, &attr);
+		free(attr.lg_ports);
+		if (rc != 0)
+			goto bail;
+	}
+
+bail:
+	free(ioc);
+	(void) close(fd);
+	return (rc);
+}
+
+/*
+ * Parse one line of the link aggregation DB, and return the corresponding
+ * group. Memory for the ports associated with the aggregation may be
+ * allocated. It is the responsibility of the caller to free the lt_ports
+ * aggregation group attribute.
+ *
+ * Returns -1 on parsing failure, or 0 on success.
+ */
+static int
+i_dladm_aggr_parse_db(char *line, dladm_aggr_grp_attr_db_t *attr)
+{
+	char	*token;
+	int	i;
+	int	value;
+	char	*endp = NULL;
+	char	*lasts = NULL;
+
+	bzero(attr, sizeof (*attr));
+
+	/* key */
+	if ((token = strtok_r(line, " \t", &lasts)) == NULL)
+		goto failed;
+
+	errno = 0;
+	value = (int)strtol(token, &endp, 10);
+	if (errno != 0 || *endp != '\0')
+		goto failed;
+
+	attr->lt_key = value;
+
+	/* policy */
+	if ((token = strtok_r(NULL, " \t", &lasts)) == NULL ||
+	    !dladm_aggr_str2policy(token, &attr->lt_policy))
+		goto failed;
+
+	/* number of ports */
+	if ((token = strtok_r(NULL, " \t", &lasts)) == NULL)
+		return (-1);
+
+	errno = 0;
+	value = (int)strtol(token, &endp, 10);
+	if (errno != 0 || *endp != '\0')
+		goto failed;
+
+	attr->lt_nports = value;
+
+	/* ports */
+	if ((attr->lt_ports = malloc(attr->lt_nports *
+	    sizeof (dladm_aggr_port_attr_db_t))) == NULL)
+		goto failed;
+
+	for (i = 0; i < attr->lt_nports; i++) {
+		char *where, *devname;
+
+		/* port */
+		if ((token = strtok_r(NULL, ", \t\n", &lasts)) == NULL)
+			goto failed;
+
+		/*
+		 * device name: In a previous version of this file, a port
+		 * number could be specified using <devname>/<portnum>.
+		 * This syntax is unecessary and obsolete.
+		 */
+		if ((devname = strtok_r(token, "/", &where)) == NULL)
+			goto failed;
+		if (strlcpy(attr->lt_ports[i].lp_devname, devname,
+		    MAXNAMELEN) >= MAXNAMELEN)
+			goto failed;
+	}
+
+	/* unicast MAC address */
+	if ((token = strtok_r(NULL, " \t\n", &lasts)) == NULL ||
+	    !dladm_aggr_str2macaddr(token, &attr->lt_mac_fixed,
+	    attr->lt_mac))
+		goto failed;
+
+	/* LACP mode */
+	if ((token = strtok_r(NULL, " \t\n", &lasts)) == NULL ||
+	    !dladm_aggr_str2lacpmode(token, &attr->lt_lacp_mode))
+		attr->lt_lacp_mode = AGGR_LACP_OFF;
+
+	/* LACP timer */
+	if ((token = strtok_r(NULL, " \t\n", &lasts)) == NULL ||
+	    !dladm_aggr_str2lacptimer(token, &attr->lt_lacp_timer))
+		attr->lt_lacp_timer = AGGR_LACP_TIMER_SHORT;
+
+	return (0);
+
+failed:
+	free(attr->lt_ports);
+	attr->lt_ports = NULL;
+	return (-1);
+}
+
+/*
+ * Walk through the groups defined in the DB and for each group <grp>,
+ * invoke <fn>(<arg>, <grp>);
+ */
+static dladm_status_t
+i_dladm_aggr_walk_db(dladm_status_t (*fn)(void *, dladm_aggr_grp_attr_db_t *),
+    void *arg, const char *root)
+{
+	FILE *fp;
+	char line[MAXLINELEN];
+	dladm_aggr_grp_attr_db_t attr;
+	char *db_file;
+	char db_file_buf[MAXPATHLEN];
+	int lock_fd;
+	dladm_status_t status = DLADM_STATUS_OK;
+
+	if (root == NULL) {
+		db_file = DLADM_AGGR_DB;
+	} else {
+		(void) snprintf(db_file_buf, MAXPATHLEN, "%s%s", root,
+		    DLADM_AGGR_DB);
+		db_file = db_file_buf;
+	}
+
+	lock_fd = i_dladm_aggr_lock_db(F_RDLCK);
+
+	if ((fp = fopen(db_file, "r")) == NULL) {
+		status = dladm_errno2status(errno);
+		i_dladm_aggr_unlock_db(lock_fd);
+		return (status);
+	}
+
+	bzero(&attr, sizeof (attr));
+
+	while (fgets(line, MAXLINELEN, fp) != NULL) {
+		/* skip comments */
+		if (BLANK_LINE(line))
+			continue;
+
+		if (i_dladm_aggr_parse_db(line, &attr) != 0) {
+			status = DLADM_STATUS_REPOSITORYINVAL;
+			goto done;
+		}
+
+		if ((status = fn(arg, &attr)) != DLADM_STATUS_OK)
+			goto done;
+
+		free(attr.lt_ports);
+		attr.lt_ports = NULL;
+	}
+
+done:
+	free(attr.lt_ports);
+	(void) fclose(fp);
+	i_dladm_aggr_unlock_db(lock_fd);
+	return (status);
+}
+
+/*
+ * Send an add or remove command to the link aggregation driver.
+ */
+static dladm_status_t
+i_dladm_aggr_add_rem_sys(dladm_aggr_grp_attr_db_t *attr, int cmd)
+{
+	int i, rc, fd, len;
+	laioc_add_rem_t *iocp;
+	laioc_port_t *ports;
+	dladm_status_t status = DLADM_STATUS_OK;
+
+	len = sizeof (*iocp) + attr->lt_nports * sizeof (laioc_port_t);
+	iocp = malloc(len);
+	if (iocp == NULL) {
+		status = DLADM_STATUS_NOMEM;
+		goto done;
+	}
+
+	iocp->la_key = attr->lt_key;
+	iocp->la_nports = attr->lt_nports;
+	ports = (laioc_port_t *)(iocp + 1);
+
+	for (i = 0; i < attr->lt_nports; i++) {
+		if (strlcpy(ports[i].lp_devname,
+		    attr->lt_ports[i].lp_devname,
+		    MAXNAMELEN) >= MAXNAMELEN) {
+			status = DLADM_STATUS_BADARG;
+			goto done;
+		}
+	}
+
+	if ((fd = open(DLADM_AGGR_DEV, O_RDWR)) < 0) {
+		status = dladm_errno2status(errno);
+		goto done;
+	}
+
+	rc = i_dladm_aggr_strioctl(fd, cmd, iocp, len);
+	if (rc < 0) {
+		if (errno == EINVAL)
+			status = DLADM_STATUS_LINKINVAL;
+		else
+			status = dladm_errno2status(errno);
+	}
+
+	(void) close(fd);
+
+done:
+	free(iocp);
+	return (status);
+}
+
+/*
+ * Send a modify command to the link aggregation driver.
+ */
+static dladm_status_t
+i_dladm_aggr_modify_sys(uint32_t key, uint32_t mask,
+    dladm_aggr_modify_attr_t *attr)
+{
+	int rc, fd;
+	laioc_modify_t ioc;
+	dladm_status_t status = DLADM_STATUS_OK;
+
+	ioc.lu_key = key;
+
+	ioc.lu_modify_mask = 0;
+	if (mask & DLADM_AGGR_MODIFY_POLICY)
+		ioc.lu_modify_mask |= LAIOC_MODIFY_POLICY;
+	if (mask & DLADM_AGGR_MODIFY_MAC)
+		ioc.lu_modify_mask |= LAIOC_MODIFY_MAC;
+	if (mask & DLADM_AGGR_MODIFY_LACP_MODE)
+		ioc.lu_modify_mask |= LAIOC_MODIFY_LACP_MODE;
+	if (mask & DLADM_AGGR_MODIFY_LACP_TIMER)
+		ioc.lu_modify_mask |= LAIOC_MODIFY_LACP_TIMER;
+
+	ioc.lu_policy = attr->ld_policy;
+	ioc.lu_mac_fixed = attr->ld_mac_fixed;
+	bcopy(attr->ld_mac, ioc.lu_mac, ETHERADDRL);
+	ioc.lu_lacp_mode = attr->ld_lacp_mode;
+	ioc.lu_lacp_timer = attr->ld_lacp_timer;
+
+	if ((fd = open(DLADM_AGGR_DEV, O_RDWR)) < 0)
+		return (dladm_errno2status(errno));
+
+	rc = i_dladm_aggr_strioctl(fd, LAIOC_MODIFY, &ioc, sizeof (ioc));
+	if (rc < 0) {
+		if (errno == EINVAL)
+			status = DLADM_STATUS_MACADDRINVAL;
+		else
+			status = dladm_errno2status(errno);
+	}
+
+	(void) close(fd);
+	return (status);
+}
+
+/*
+ * Send a create command to the link aggregation driver.
+ */
+static dladm_status_t
+i_dladm_aggr_create_sys(int fd, dladm_aggr_grp_attr_db_t *attr)
+{
+	int i, rc, len;
+	laioc_create_t *iocp;
+	laioc_port_t *ports;
+	dladm_status_t status = DLADM_STATUS_OK;
+
+	len = sizeof (*iocp) + attr->lt_nports * sizeof (laioc_port_t);
+	iocp = malloc(len);
+	if (iocp == NULL)
+		return (DLADM_STATUS_NOMEM);
+
+	iocp->lc_key = attr->lt_key;
+	iocp->lc_nports = attr->lt_nports;
+	iocp->lc_policy = attr->lt_policy;
+	iocp->lc_lacp_mode = attr->lt_lacp_mode;
+	iocp->lc_lacp_timer = attr->lt_lacp_timer;
+
+	ports = (laioc_port_t *)(iocp + 1);
+
+	for (i = 0; i < attr->lt_nports; i++) {
+		if (strlcpy(ports[i].lp_devname,
+		    attr->lt_ports[i].lp_devname,
+		    MAXNAMELEN) >= MAXNAMELEN) {
+			free(iocp);
+			return (DLADM_STATUS_BADARG);
+		}
+	}
+
+	if (attr->lt_mac_fixed &&
+	    ((bcmp(zero_mac, attr->lt_mac, ETHERADDRL) == 0) ||
+	    (attr->lt_mac[0] & 0x01))) {
+		free(iocp);
+		return (DLADM_STATUS_MACADDRINVAL);
+	}
+
+	bcopy(attr->lt_mac, iocp->lc_mac, ETHERADDRL);
+	iocp->lc_mac_fixed = attr->lt_mac_fixed;
+
+	rc = i_dladm_aggr_strioctl(fd, LAIOC_CREATE, iocp, len);
+	if (rc < 0)
+		status = DLADM_STATUS_LINKINVAL;
+
+	free(iocp);
+	return (status);
+}
+
+/*
+ * Invoked to bring up a link aggregation group.
+ */
+static dladm_status_t
+i_dladm_aggr_up(void *arg, dladm_aggr_grp_attr_db_t *attr)
+{
+	dladm_aggr_up_t	*up = (dladm_aggr_up_t *)arg;
+	dladm_status_t	status;
+
+	if (up->lu_key != 0 && up->lu_key != attr->lt_key)
+		return (DLADM_STATUS_OK);
+
+	up->lu_found = B_TRUE;
+
+	status = i_dladm_aggr_create_sys(up->lu_fd, attr);
+	if (status != DLADM_STATUS_OK && up->lu_key != 0)
+		return (status);
+
+	return (DLADM_STATUS_OK);
+}
+
+/*
+ * Bring up a link aggregation group or all of them if the key is zero.
+ * If key is 0, walk may terminate early if any of the links fail
+ */
+dladm_status_t
+dladm_aggr_up(uint32_t key, const char *root)
+{
+	dladm_aggr_up_t up;
+	dladm_status_t status;
+
+	if ((up.lu_fd = open(DLADM_AGGR_DEV, O_RDWR)) < 0)
+		return (dladm_errno2status(errno));
+
+	up.lu_key = key;
+	up.lu_found = B_FALSE;
+
+	status = i_dladm_aggr_walk_db(i_dladm_aggr_up, &up, root);
+	if (status != DLADM_STATUS_OK) {
+		(void) close(up.lu_fd);
+		return (status);
+	}
+	(void) close(up.lu_fd);
+
+	/*
+	 * only return error if user specified key and key was
+	 * not found
+	 */
+	if (!up.lu_found && key != 0)
+		return (DLADM_STATUS_NOTFOUND);
+
+	return (DLADM_STATUS_OK);
+}
+/*
+ * Send a delete command to the link aggregation driver.
+ */
+static int
+i_dladm_aggr_delete_sys(int fd, dladm_aggr_grp_attr_t *attr)
+{
+	laioc_delete_t ioc;
+
+	ioc.ld_key = attr->lg_key;
+
+	return (i_dladm_aggr_strioctl(fd, LAIOC_DELETE, &ioc, sizeof (ioc)));
+}
+
+/*
+ * Invoked to bring down a link aggregation group.
+ */
+static int
+i_dladm_aggr_down(void *arg, dladm_aggr_grp_attr_t *attr)
+{
+	dladm_aggr_down_t *down = (dladm_aggr_down_t *)arg;
+	int fd, errno_save;
+
+	if (down->ld_key != 0 && down->ld_key != attr->lg_key)
+		return (0);
+
+	down->ld_found = B_TRUE;
+
+	if ((fd = open(DLADM_AGGR_DEV, O_RDWR)) < 0)
+		return (-1);
+
+	if (i_dladm_aggr_delete_sys(fd, attr) < 0 && down->ld_key != 0) {
+		errno_save = errno;
+		(void) close(fd);
+		errno = errno_save;
+		return (-1);
+	}
+
+	(void) close(fd);
+	return (0);
+}
+
+/*
+ * Bring down a link aggregation group or all of them if the key is zero.
+ * If key is 0, walk may terminate early if any of the links fail
+ */
+dladm_status_t
+dladm_aggr_down(uint32_t key)
+{
+	dladm_aggr_down_t down;
+
+	down.ld_key = key;
+	down.ld_found = B_FALSE;
+
+	if (dladm_aggr_walk(i_dladm_aggr_down, &down) < 0)
+		return (dladm_errno2status(errno));
+
+	/*
+	 * only return error if user specified key and key was
+	 * not found
+	 */
+	if (!down.ld_found && key != 0)
+		return (DLADM_STATUS_NOTFOUND);
+
+	return (DLADM_STATUS_OK);
+}
+
+/*
+ * For each group <grp> found in the DB, invokes <fn>(<grp>, <arg>).
+ *
+ * The following values can be returned by <fn>():
+ *
+ * -1: an error occured. This will cause the walk to be terminated,
+ *     and the original DB file to be preserved.
+ *
+ *  0: success and write. The walker will write the contents of
+ *     the attribute passed as argument to <fn>(), and continue walking
+ *     the entries found in the DB.
+ *
+ *  1: skip. The walker should not write the contents of the current
+ *     group attributes to the new DB, but should continue walking
+ *     the entries found in the DB.
+ */
+static dladm_status_t
+i_dladm_aggr_walk_rw_db(int (*fn)(void *, dladm_aggr_grp_attr_db_t *),
+    void *arg, const char *root)
+{
+	FILE *fp, *nfp;
+	int nfd, fn_rc, lock_fd;
+	char line[MAXLINELEN];
+	dladm_aggr_grp_attr_db_t attr;
+	char *db_file, *tmp_db_file;
+	char db_file_buf[MAXPATHLEN];
+	char tmp_db_file_buf[MAXPATHLEN];
+	dladm_status_t status;
+
+	if (root == NULL) {
+		db_file = DLADM_AGGR_DB;
+		tmp_db_file = DLADM_AGGR_DB_TMP;
+	} else {
+		(void) snprintf(db_file_buf, MAXPATHLEN, "%s%s", root,
+		    DLADM_AGGR_DB);
+		(void) snprintf(tmp_db_file_buf, MAXPATHLEN, "%s%s", root,
+		    DLADM_AGGR_DB_TMP);
+		db_file = db_file_buf;
+		tmp_db_file = tmp_db_file_buf;
+	}
+
+	if ((lock_fd = i_dladm_aggr_lock_db(F_WRLCK)) < 0)
+		return (dladm_errno2status(errno));
+
+	if ((fp = fopen(db_file, "r")) == NULL) {
+		status = dladm_errno2status(errno);
+		i_dladm_aggr_unlock_db(lock_fd);
+		return (status);
+	}
+
+	if ((nfd = open(tmp_db_file, O_WRONLY|O_CREAT|O_TRUNC,
+	    DLADM_AGGR_DB_PERMS)) == -1) {
+		status = dladm_errno2status(errno);
+		(void) fclose(fp);
+		i_dladm_aggr_unlock_db(lock_fd);
+		return (status);
+	}
+
+	if ((nfp = fdopen(nfd, "w")) == NULL) {
+		status = dladm_errno2status(errno);
+		(void) close(nfd);
+		(void) fclose(fp);
+		(void) unlink(tmp_db_file);
+		i_dladm_aggr_unlock_db(lock_fd);
+		return (status);
+	}
+
+	attr.lt_ports = NULL;
+
+	while (fgets(line, MAXLINELEN, fp) != NULL) {
+
+		/* skip comments */
+		if (BLANK_LINE(line)) {
+			if (fputs(line, nfp) == EOF) {
+				status = dladm_errno2status(errno);
+				goto failed;
+			}
+			continue;
+		}
+
+		if (i_dladm_aggr_parse_db(line, &attr) != 0) {
+			status = DLADM_STATUS_REPOSITORYINVAL;
+			goto failed;
+		}
+
+		fn_rc = fn(arg, &attr);
+
+		switch (fn_rc) {
+		case -1:
+			/* failure, stop walking */
+			status = dladm_errno2status(errno);
+			goto failed;
+		case 0:
+			/*
+			 * Success, write group attributes, which could
+			 * have been modified by fn().
+			 */
+			if (i_dladm_aggr_fput_grp(nfp, &attr) != 0) {
+				status = dladm_errno2status(errno);
+				goto failed;
+			}
+			break;
+		case 1:
+			/* skip current group */
+			break;
+		}
+
+		free(attr.lt_ports);
+		attr.lt_ports = NULL;
+	}
+
+	if (getuid() == 0 || geteuid() == 0) {
+		if (fchmod(nfd, DLADM_AGGR_DB_PERMS) == -1) {
+			status = dladm_errno2status(errno);
+			goto failed;
+		}
+
+		if (fchown(nfd, DLADM_AGGR_DB_OWNER,
+		    DLADM_AGGR_DB_GROUP) == -1) {
+			status = dladm_errno2status(errno);
+			goto failed;
+		}
+	}
+
+	if (fflush(nfp) == EOF) {
+		status = dladm_errno2status(errno);
+		goto failed;
+	}
+
+	(void) fclose(fp);
+	(void) fclose(nfp);
+
+	if (rename(tmp_db_file, db_file) == -1) {
+		status = dladm_errno2status(errno);
+		(void) unlink(tmp_db_file);
+		i_dladm_aggr_unlock_db(lock_fd);
+		return (status);
+	}
+
+	i_dladm_aggr_unlock_db(lock_fd);
+	return (DLADM_STATUS_OK);
+
+failed:
+	free(attr.lt_ports);
+	(void) fclose(fp);
+	(void) fclose(nfp);
+	(void) unlink(tmp_db_file);
+	i_dladm_aggr_unlock_db(lock_fd);
+
+	return (status);
+}
+
+/*
+ * Remove an entry from the DB.
+ */
+static int
+i_dladm_aggr_del_db_fn(void *arg, dladm_aggr_grp_attr_db_t *grp)
+{
+	delete_db_state_t *state = arg;
+
+	if (grp->lt_key != state->ds_key)
+		return (0);
+
+	state->ds_found = B_TRUE;
+
+	/* don't save matching group */
+	return (1);
+}
+
+static dladm_status_t
+i_dladm_aggr_del_db(dladm_aggr_grp_attr_db_t *attr, const char *root)
+{
+	delete_db_state_t state;
+	dladm_status_t status;
+
+	state.ds_key = attr->lt_key;
+	state.ds_found = B_FALSE;
+
+	status = i_dladm_aggr_walk_rw_db(i_dladm_aggr_del_db_fn, &state, root);
+	if (status != DLADM_STATUS_OK)
+		return (status);
+
+	if (!state.ds_found)
+		return (DLADM_STATUS_NOTFOUND);
+
+	return (DLADM_STATUS_OK);
+}
+
+/*
+ * Modify the properties of an existing group in the DB.
+ */
+static int
+i_dladm_aggr_modify_db_fn(void *arg, dladm_aggr_grp_attr_db_t *grp)
+{
+	modify_db_state_t *state = arg;
+	dladm_aggr_modify_attr_t *new_attr = state->us_attr_new;
+	dladm_aggr_modify_attr_t *old_attr = state->us_attr_old;
+
+	if (grp->lt_key != state->us_key)
+		return (0);
+
+	state->us_found = B_TRUE;
+
+	if (state->us_mask & DLADM_AGGR_MODIFY_POLICY) {
+		if (old_attr != NULL)
+			old_attr->ld_policy = grp->lt_policy;
+		grp->lt_policy = new_attr->ld_policy;
+	}
+
+	if (state->us_mask & DLADM_AGGR_MODIFY_MAC) {
+		if (old_attr != NULL) {
+			old_attr->ld_mac_fixed = grp->lt_mac_fixed;
+			bcopy(grp->lt_mac, old_attr->ld_mac, ETHERADDRL);
+		}
+		grp->lt_mac_fixed = new_attr->ld_mac_fixed;
+		bcopy(new_attr->ld_mac, grp->lt_mac, ETHERADDRL);
+	}
+
+	if (state->us_mask & DLADM_AGGR_MODIFY_LACP_MODE) {
+		if (old_attr != NULL)
+			old_attr->ld_lacp_mode = grp->lt_lacp_mode;
+		grp->lt_lacp_mode = new_attr->ld_lacp_mode;
+	}
+
+	if (state->us_mask & DLADM_AGGR_MODIFY_LACP_TIMER) {
+		if (old_attr != NULL)
+			old_attr->ld_lacp_timer = grp->lt_lacp_timer;
+		grp->lt_lacp_timer = new_attr->ld_lacp_timer;
+	}
+
+	/* save modified group */
+	return (0);
+}
+
+static dladm_status_t
+i_dladm_aggr_modify_db(uint32_t key, uint32_t mask,
+    dladm_aggr_modify_attr_t *new, dladm_aggr_modify_attr_t *old,
+    const char *root)
+{
+	modify_db_state_t state;
+	dladm_status_t status;
+
+	state.us_key = key;
+	state.us_mask = mask;
+	state.us_attr_new = new;
+	state.us_attr_old = old;
+	state.us_found = B_FALSE;
+
+	if ((status = i_dladm_aggr_walk_rw_db(i_dladm_aggr_modify_db_fn,
+	    &state, root)) != DLADM_STATUS_OK) {
+		return (status);
+	}
+
+	if (!state.us_found)
+		return (DLADM_STATUS_NOTFOUND);
+
+	return (DLADM_STATUS_OK);
+}
+
+/*
+ * Add ports to an existing group in the DB.
+ */
+static int
+i_dladm_aggr_add_db_fn(void *arg, dladm_aggr_grp_attr_db_t *grp)
+{
+	add_db_state_t *state = arg;
+	dladm_aggr_grp_attr_db_t *attr = state->as_attr;
+	void *ports;
+	int i, j;
+
+	if (grp->lt_key != attr->lt_key)
+		return (0);
+
+	state->as_found = B_TRUE;
+
+	/* are any of the ports to be added already members of the group? */
+	for (i = 0; i < grp->lt_nports; i++) {
+		for (j = 0; j < attr->lt_nports; j++) {
+			if (strcmp(grp->lt_ports[i].lp_devname,
+			    attr->lt_ports[j].lp_devname) == 0) {
+				errno = EEXIST;
+				return (-1);
+			}
+		}
+	}
+
+	/* add groups specified by attr to grp */
+	ports = realloc(grp->lt_ports, (grp->lt_nports +
+	    attr->lt_nports) * sizeof (dladm_aggr_port_attr_db_t));
+	if (ports == NULL)
+		return (-1);
+	grp->lt_ports = ports;
+
+	for (i = 0; i < attr->lt_nports; i++) {
+		if (strlcpy(grp->lt_ports[grp->lt_nports + i].lp_devname,
+		    attr->lt_ports[i].lp_devname, MAXNAMELEN + 1) >=
+		    MAXNAMELEN + 1)
+			return (-1);
+	}
+
+	grp->lt_nports += attr->lt_nports;
+
+	/* save modified group */
+	return (0);
+}
+
+static dladm_status_t
+i_dladm_aggr_add_db(dladm_aggr_grp_attr_db_t *attr, const char *root)
+{
+	add_db_state_t state;
+	dladm_status_t status;
+
+	state.as_attr = attr;
+	state.as_found = B_FALSE;
+
+	status = i_dladm_aggr_walk_rw_db(i_dladm_aggr_add_db_fn, &state, root);
+	if (status != DLADM_STATUS_OK)
+		return (status);
+
+	if (!state.as_found)
+		return (DLADM_STATUS_NOTFOUND);
+
+	return (DLADM_STATUS_OK);
+}
+
+/*
+ * Remove ports from an existing group in the DB.
+ */
+
+typedef struct remove_db_state {
+	dladm_aggr_grp_attr_db_t *rs_attr;
+	boolean_t	rs_found;
+} remove_db_state_t;
+
+static int
+i_dladm_aggr_remove_db_fn(void *arg, dladm_aggr_grp_attr_db_t *grp)
+{
+	remove_db_state_t *state = (remove_db_state_t *)arg;
+	dladm_aggr_grp_attr_db_t *attr = state->rs_attr;
+	int i, j, k, nremoved;
+	boolean_t match;
+
+	if (grp->lt_key != attr->lt_key)
+		return (0);
+
+	state->rs_found = B_TRUE;
+
+	/* remove the ports specified by attr from the group */
+	nremoved = 0;
+	k = 0;
+	for (i = 0; i < grp->lt_nports; i++) {
+		match = B_FALSE;
+		for (j = 0; j < attr->lt_nports && !match; j++) {
+			match = (strcmp(grp->lt_ports[i].lp_devname,
+			    attr->lt_ports[j].lp_devname) == 0);
+		}
+		if (match)
+			nremoved++;
+		else
+			grp->lt_ports[k++] = grp->lt_ports[i];
+	}
+
+	if (nremoved != attr->lt_nports) {
+		errno = ENOENT;
+		return (-1);
+	}
+
+	grp->lt_nports -= nremoved;
+
+	/* save modified group */
+	return (0);
+}
+
+static dladm_status_t
+i_dladm_aggr_remove_db(dladm_aggr_grp_attr_db_t *attr, const char *root)
+{
+	remove_db_state_t state;
+	dladm_status_t status;
+
+	state.rs_attr = attr;
+	state.rs_found = B_FALSE;
+
+	status = i_dladm_aggr_walk_rw_db(i_dladm_aggr_remove_db_fn,
+	    &state, root);
+	if (status != DLADM_STATUS_OK)
+		return (status);
+
+	if (!state.rs_found)
+		return (DLADM_STATUS_NOTFOUND);
+
+	return (DLADM_STATUS_OK);
+}
+
+/*
+ * Given a policy string, return a policy mask. Returns B_TRUE on
+ * success, or B_FALSE if an error occured during parsing.
+ */
+boolean_t
+dladm_aggr_str2policy(const char *str, uint32_t *policy)
+{
+	int i;
+	policy_t *pol;
+	char *token = NULL;
+	char *lasts;
+
+	*policy = 0;
+
+	while ((token = strtok_r((token == NULL) ? (char *)str : NULL, ",",
+	    &lasts)) != NULL) {
+		for (i = 0; i < NPOLICIES; i++) {
+			pol = &policies[i];
+			if (strcasecmp(token, pol->pol_name) == 0) {
+				*policy |= pol->policy;
+				break;
+			}
+		}
+		if (i == NPOLICIES)
+			return (B_FALSE);
+	}
+
+	return (B_TRUE);
+}
+
+/*
+ * Given a policy mask, returns a printable string, or NULL if the
+ * policy mask is invalid. It is the responsibility of the caller to
+ * free the returned string after use.
+ */
+char *
+dladm_aggr_policy2str(uint32_t policy, char *str)
+{
+	int i, npolicies = 0;
+	policy_t *pol;
+
+	str[0] = '\0';
+
+	for (i = 0; i < NPOLICIES; i++) {
+		pol = &policies[i];
+		if ((policy & pol->policy) != 0) {
+			npolicies++;
+			if (npolicies > 1)
+				(void) strcat(str, ",");
+			(void) strcat(str, pol->pol_name);
+		}
+	}
+
+	return (str);
+}
+
+/*
+ * Given a MAC address string, return the MAC address in the mac_addr
+ * array. If the MAC address was not explicitly specified, i.e. is
+ * equal to 'auto', zero out mac-addr and set mac_fixed to B_TRUE.
+ * Return B_FALSE if a syntax error was encountered, B_FALSE otherwise.
+ */
+boolean_t
+dladm_aggr_str2macaddr(const char *str, boolean_t *mac_fixed, uchar_t *mac_addr)
+{
+	uchar_t *conv_str;
+	int mac_len;
+
+	*mac_fixed = (strcmp(str, "auto") != 0);
+	if (!*mac_fixed) {
+		bzero(mac_addr, ETHERADDRL);
+		return (B_TRUE);
+	}
+
+	conv_str = _link_aton(str, &mac_len);
+	if (conv_str == NULL)
+		return (B_FALSE);
+
+	if (mac_len != ETHERADDRL) {
+		free(conv_str);
+		return (B_FALSE);
+	}
+
+	if ((bcmp(zero_mac, conv_str, ETHERADDRL) == 0) ||
+	    (conv_str[0] & 0x01)) {
+		free(conv_str);
+		return (B_FALSE);
+	}
+
+	bcopy(conv_str, mac_addr, ETHERADDRL);
+	free(conv_str);
+
+	return (B_TRUE);
+}
+
+/*
+ * Returns a string containing a printable representation of a MAC address.
+ */
+const char *
+dladm_aggr_macaddr2str(unsigned char *mac, char *buf)
+{
+	static char unknown_mac[] = {0, 0, 0, 0, 0, 0};
+
+	if (buf == NULL)
+		return (NULL);
+
+	if (bcmp(unknown_mac, mac, ETHERADDRL) == 0)
+		return (gettext("<unknown>"));
+	else
+		return (_link_ntoa(mac, buf, ETHERADDRL, IFT_OTHER));
+}
+
+/*
+ * Given a LACP mode string, find the corresponding LACP mode number. Returns
+ * B_TRUE if a match was found, B_FALSE otherwise.
+ */
+boolean_t
+dladm_aggr_str2lacpmode(const char *str, aggr_lacp_mode_t *lacp_mode)
+{
+	int i;
+	dladm_aggr_lacpmode_t *mode;
+
+	for (i = 0; i < NLACP_MODES; i++) {
+		mode = &lacp_modes[i];
+		if (strncasecmp(str, mode->mode_str,
+		    strlen(mode->mode_str)) == 0) {
+			*lacp_mode = mode->mode_id;
+			return (B_TRUE);
+		}
+	}
+
+	return (B_FALSE);
+}
+
+/*
+ * Given a LACP mode number, returns a printable string, or NULL if the
+ * LACP mode number is invalid.
+ */
+const char *
+dladm_aggr_lacpmode2str(aggr_lacp_mode_t mode_id, char *buf)
+{
+	int i;
+	dladm_aggr_lacpmode_t *mode;
+
+	for (i = 0; i < NLACP_MODES; i++) {
+		mode = &lacp_modes[i];
+		if (mode->mode_id == mode_id) {
+			(void) snprintf(buf, DLADM_STRSIZE, "%s",
+			    mode->mode_str);
+			return (buf);
+		}
+	}
+
+	(void) strlcpy(buf, "unknown", DLADM_STRSIZE);
+	return (buf);
+}
+
+/*
+ * Given a LACP timer string, find the corresponding LACP timer number. Returns
+ * B_TRUE if a match was found, B_FALSE otherwise.
+ */
+boolean_t
+dladm_aggr_str2lacptimer(const char *str, aggr_lacp_timer_t *lacp_timer)
+{
+	int i;
+	dladm_aggr_lacptimer_t *timer;
+
+	for (i = 0; i < NLACP_TIMERS; i++) {
+		timer = &lacp_timers[i];
+		if (strncasecmp(str, timer->lt_str,
+		    strlen(timer->lt_str)) == 0) {
+			*lacp_timer = timer->lt_id;
+			return (B_TRUE);
+		}
+	}
+
+	return (B_FALSE);
+}
+
+/*
+ * Given a LACP timer, returns a printable string, or NULL if the
+ * LACP timer number is invalid.
+ */
+const char *
+dladm_aggr_lacptimer2str(aggr_lacp_timer_t timer_id, char *buf)
+{
+	int i;
+	dladm_aggr_lacptimer_t *timer;
+
+	for (i = 0; i < NLACP_TIMERS; i++) {
+		timer = &lacp_timers[i];
+		if (timer->lt_id == timer_id) {
+			(void) snprintf(buf, DLADM_STRSIZE, "%s",
+			    timer->lt_str);
+			return (buf);
+		}
+	}
+
+	(void) strlcpy(buf, "unknown", DLADM_STRSIZE);
+	return (buf);
+}
+
+const char *
+dladm_aggr_portstate2str(aggr_port_state_t state_id, char *buf)
+{
+	int			i;
+	dladm_aggr_port_state_t	*state;
+
+	for (i = 0; i < NPORT_STATES; i++) {
+		state = &port_states[i];
+		if (state->state_id == state_id) {
+			(void) snprintf(buf, DLADM_STRSIZE, "%s",
+			    state->state_str);
+			return (buf);
+		}
+	}
+
+	(void) strlcpy(buf, "unknown", DLADM_STRSIZE);
+	return (buf);
+}
+
+#define	FPRINTF_ERR(fcall) if ((fcall) < 0) return (-1);
+
+/*
+ * Write the attribute of a group to the specified file. Returns 0 on
+ * success, -1 on failure.
+ */
+static int
+i_dladm_aggr_fput_grp(FILE *fp, dladm_aggr_grp_attr_db_t *attr)
+{
+	int i;
+	char addr_str[ETHERADDRL * 3];
+	char buf[DLADM_STRSIZE];
+
+	/* key, policy */
+	FPRINTF_ERR(fprintf(fp, "%d\t%s\t", attr->lt_key,
+	    dladm_aggr_policy2str(attr->lt_policy, buf)));
+
+	/* number of ports, ports */
+	FPRINTF_ERR(fprintf(fp, "%d\t", attr->lt_nports));
+	for (i = 0; i < attr->lt_nports; i++) {
+		if (i > 0)
+			FPRINTF_ERR(fprintf(fp, ","));
+		FPRINTF_ERR(fprintf(fp, "%s", attr->lt_ports[i].lp_devname));
+	}
+	FPRINTF_ERR(fprintf(fp, "\t"));
+
+	/* MAC address */
+	if (!attr->lt_mac_fixed) {
+		FPRINTF_ERR(fprintf(fp, "auto"));
+	} else {
+		FPRINTF_ERR(fprintf(fp, "%s",
+		    dladm_aggr_macaddr2str(attr->lt_mac, addr_str)));
+	}
+	FPRINTF_ERR(fprintf(fp, "\t"));
+
+	FPRINTF_ERR(fprintf(fp, "%s\t",
+	    dladm_aggr_lacpmode2str(attr->lt_lacp_mode, buf)));
+
+	FPRINTF_ERR(fprintf(fp, "%s\n",
+	    dladm_aggr_lacptimer2str(attr->lt_lacp_timer, buf)));
+
+	return (0);
+}
+
+static dladm_status_t
+i_dladm_aggr_create_db(dladm_aggr_grp_attr_db_t *attr, const char *root)
+{
+	FILE		*fp;
+	char		line[MAXLINELEN];
+	uint32_t	key;
+	int 		lock_fd;
+	char 		*db_file;
+	char 		db_file_buf[MAXPATHLEN];
+	char 		*endp = NULL;
+	dladm_status_t	status;
+
+	if (root == NULL) {
+		db_file = DLADM_AGGR_DB;
+	} else {
+		(void) snprintf(db_file_buf, MAXPATHLEN, "%s%s", root,
+		    DLADM_AGGR_DB);
+		db_file = db_file_buf;
+	}
+
+	if ((lock_fd = i_dladm_aggr_lock_db(F_WRLCK)) < 0)
+		return (dladm_errno2status(errno));
+
+	if ((fp = fopen(db_file, "r+")) == NULL &&
+	    (fp = fopen(db_file, "w")) == NULL) {
+		status = dladm_errno2status(errno);
+		i_dladm_aggr_unlock_db(lock_fd);
+		return (status);
+	}
+
+	/* look for existing group with same key */
+	while (fgets(line, MAXLINELEN, fp) != NULL) {
+		char *holder, *lasts;
+
+		/* skip comments */
+		if (BLANK_LINE(line))
+			continue;
+
+		/* ignore corrupted lines */
+		holder = strtok_r(line, " \t", &lasts);
+		if (holder == NULL)
+			continue;
+
+		/* port number */
+		errno = 0;
+		key = (int)strtol(holder, &endp, 10);
+		if (errno != 0 || *endp != '\0') {
+			status = DLADM_STATUS_REPOSITORYINVAL;
+			goto done;
+		}
+
+		if (key == attr->lt_key) {
+			/* group with key already exists */
+			status = DLADM_STATUS_EXIST;
+			goto done;
+		}
+	}
+
+	/*
+	 * If we get here, we've verified that no existing group with
+	 * the same key already exists. It's now time to add the
+	 * new group to the DB.
+	 */
+	if (i_dladm_aggr_fput_grp(fp, attr) != 0) {
+		status = dladm_errno2status(errno);
+		goto done;
+	}
+
+	status = DLADM_STATUS_OK;
+
+done:
+	(void) fclose(fp);
+	i_dladm_aggr_unlock_db(lock_fd);
+	return (status);
+}
+
+/*
+ * Create a new link aggregation group. Update the configuration
+ * file and bring it up.
+ */
+dladm_status_t
+dladm_aggr_create(uint32_t key, uint32_t nports,
+    dladm_aggr_port_attr_db_t *ports, uint32_t policy, boolean_t mac_addr_fixed,
+    uchar_t *mac_addr, aggr_lacp_mode_t lacp_mode, aggr_lacp_timer_t lacp_timer,
+    boolean_t tempop, const char *root)
+{
+	dladm_aggr_grp_attr_db_t attr;
+	dladm_status_t status;
+
+	if (key == 0 || key > DLADM_AGGR_MAX_KEY)
+		return (DLADM_STATUS_KEYINVAL);
+
+	attr.lt_key = key;
+	attr.lt_nports = nports;
+	attr.lt_ports = ports;
+	attr.lt_policy = policy;
+	attr.lt_mac_fixed = mac_addr_fixed;
+	if (attr.lt_mac_fixed)
+		bcopy(mac_addr, attr.lt_mac, ETHERADDRL);
+	else
+		bzero(attr.lt_mac, ETHERADDRL);
+	attr.lt_lacp_mode = lacp_mode;
+	attr.lt_lacp_timer = lacp_timer;
+
+	/* add the link aggregation group to the DB */
+	if (!tempop) {
+		status = i_dladm_aggr_create_db(&attr, root);
+		if (status != DLADM_STATUS_OK)
+			return (status);
+	} else {
+		dladm_aggr_up_t up;
+
+		up.lu_key = key;
+		up.lu_found = B_FALSE;
+		up.lu_fd = open(DLADM_AGGR_DEV, O_RDWR);
+		if (up.lu_fd < 0)
+			return (dladm_errno2status(errno));
+
+		status = i_dladm_aggr_up((void *)&up, &attr);
+		(void) close(up.lu_fd);
+		return (status);
+	}
+
+	/* bring up the link aggregation group */
+	status = dladm_aggr_up(key, root);
+	/*
+	 * If the operation fails because the aggregation already exists,
+	 * then only update the persistent configuration repository and
+	 * return success.
+	 */
+	if (status == DLADM_STATUS_EXIST)
+		status = DLADM_STATUS_OK;
+
+	if (status != DLADM_STATUS_OK && !tempop)
+		(void) i_dladm_aggr_del_db(&attr, root);
+
+	return (status);
+}
+
+/*
+ * Modify the parameters of an existing link aggregation group. Update
+ * the configuration file and pass the changes to the kernel.
+ */
+dladm_status_t
+dladm_aggr_modify(uint32_t key, uint32_t modify_mask, uint32_t policy,
+    boolean_t mac_fixed, uchar_t *mac_addr, aggr_lacp_mode_t lacp_mode,
+    aggr_lacp_timer_t lacp_timer, boolean_t tempop, const char *root)
+{
+	dladm_aggr_modify_attr_t new_attr, old_attr;
+	dladm_status_t status;
+
+	if (key == 0)
+		return (DLADM_STATUS_KEYINVAL);
+
+	if (modify_mask & DLADM_AGGR_MODIFY_POLICY)
+		new_attr.ld_policy = policy;
+
+	if (modify_mask & DLADM_AGGR_MODIFY_MAC) {
+		new_attr.ld_mac_fixed = mac_fixed;
+		bcopy(mac_addr, new_attr.ld_mac, ETHERADDRL);
+	}
+
+	if (modify_mask & DLADM_AGGR_MODIFY_LACP_MODE)
+		new_attr.ld_lacp_mode = lacp_mode;
+
+	if (modify_mask & DLADM_AGGR_MODIFY_LACP_TIMER)
+		new_attr.ld_lacp_timer = lacp_timer;
+
+	/* update the DB */
+	if (!tempop && ((status = i_dladm_aggr_modify_db(key, modify_mask,
+	    &new_attr, &old_attr, root)) != DLADM_STATUS_OK)) {
+		return (status);
+	}
+
+	status = i_dladm_aggr_modify_sys(key, modify_mask, &new_attr);
+	if (status != DLADM_STATUS_OK && !tempop) {
+		(void) i_dladm_aggr_modify_db(key, modify_mask, &old_attr,
+		    NULL, root);
+	}
+
+	return (status);
+}
+
+/*
+ * Delete a previously created link aggregation group.
+ */
+dladm_status_t
+dladm_aggr_delete(uint32_t key, boolean_t tempop, const char *root)
+{
+	dladm_aggr_grp_attr_db_t db_attr;
+	dladm_status_t status;
+
+	if (key == 0)
+		return (DLADM_STATUS_KEYINVAL);
+
+	if (tempop) {
+		dladm_aggr_down_t down;
+		dladm_aggr_grp_attr_t sys_attr;
+
+		down.ld_key = key;
+		down.ld_found = B_FALSE;
+		sys_attr.lg_key = key;
+		if (i_dladm_aggr_down((void *)&down, &sys_attr) < 0)
+			return (dladm_errno2status(errno));
+		else
+			return (DLADM_STATUS_OK);
+	} else {
+		status = dladm_aggr_down(key);
+
+		/*
+		 * Only continue to delete the configuration repository
+		 * either if we successfully delete the active aggregation
+		 * or if the aggregation is not found.
+		 */
+		if (status != DLADM_STATUS_OK &&
+		    status != DLADM_STATUS_NOTFOUND) {
+			return (status);
+		}
+	}
+
+	if (tempop)
+		return (DLADM_STATUS_OK);
+
+	db_attr.lt_key = key;
+	return (i_dladm_aggr_del_db(&db_attr, root));
+}
+
+/*
+ * Add one or more ports to an existing link aggregation.
+ */
+dladm_status_t
+dladm_aggr_add(uint32_t key, uint32_t nports, dladm_aggr_port_attr_db_t *ports,
+    boolean_t tempop, const char *root)
+{
+	dladm_aggr_grp_attr_db_t attr;
+	dladm_status_t status;
+
+	if (key == 0)
+		return (DLADM_STATUS_KEYINVAL);
+
+	bzero(&attr, sizeof (attr));
+	attr.lt_key = key;
+	attr.lt_nports = nports;
+	attr.lt_ports = ports;
+
+	if (!tempop &&
+	    ((status = i_dladm_aggr_add_db(&attr, root)) != DLADM_STATUS_OK)) {
+		return (status);
+	}
+
+	status = i_dladm_aggr_add_rem_sys(&attr, LAIOC_ADD);
+	if (status != DLADM_STATUS_OK && !tempop)
+		(void) i_dladm_aggr_remove_db(&attr, root);
+
+	return (status);
+}
+
+/*
+ * Remove one or more ports from an existing link aggregation.
+ */
+dladm_status_t
+dladm_aggr_remove(uint32_t key, uint32_t nports,
+    dladm_aggr_port_attr_db_t *ports, boolean_t tempop, const char *root)
+{
+	dladm_aggr_grp_attr_db_t attr;
+	dladm_status_t status;
+
+	if (key == 0)
+		return (DLADM_STATUS_KEYINVAL);
+
+	bzero(&attr, sizeof (attr));
+	attr.lt_key = key;
+	attr.lt_nports = nports;
+	attr.lt_ports = ports;
+
+	if (!tempop &&
+	    ((status = i_dladm_aggr_remove_db(&attr, root)) !=
+	    DLADM_STATUS_OK)) {
+		return (status);
+	}
+
+	status = i_dladm_aggr_add_rem_sys(&attr, LAIOC_REMOVE);
+	if (status != DLADM_STATUS_OK && !tempop)
+		(void) i_dladm_aggr_add_db(&attr, root);
+
+	return (status);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libdladm/common/libdlaggr.h	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,113 @@
+/*
+ * 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 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _LIBDLAGGR_H
+#define	_LIBDLAGGR_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+/*
+ * This file includes structures, macros and routines used by aggregation link
+ * administration.
+ */
+
+#include <sys/types.h>
+#include <sys/aggr.h>
+#include <libdladm.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * Modification flags sent with the LAIOC_MODIFY ioctl
+ */
+#define	DLADM_AGGR_MODIFY_POLICY		0x01
+#define	DLADM_AGGR_MODIFY_MAC			0x02
+#define	DLADM_AGGR_MODIFY_LACP_MODE		0x04
+#define	DLADM_AGGR_MODIFY_LACP_TIMER		0x08
+
+typedef struct dladm_aggr_port_attr_db {
+	char		lp_devname[MAXNAMELEN + 1];
+} dladm_aggr_port_attr_db_t;
+
+typedef struct dladm_aggr_port_attr {
+	char		lp_devname[MAXNAMELEN + 1];
+	uchar_t		lp_mac[ETHERADDRL];
+	aggr_port_state_t lp_state;
+	aggr_lacp_state_t lp_lacp_state;
+} dladm_aggr_port_attr_t;
+
+typedef struct dladm_aggr_grp_attr {
+	uint32_t	lg_key;
+	uint32_t	lg_nports;
+	dladm_aggr_port_attr_t *lg_ports;
+	uint32_t	lg_policy;
+	uchar_t		lg_mac[ETHERADDRL];
+	boolean_t	lg_mac_fixed;
+	aggr_lacp_mode_t lg_lacp_mode;
+	aggr_lacp_timer_t lg_lacp_timer;
+} dladm_aggr_grp_attr_t;
+
+extern dladm_status_t	dladm_aggr_create(uint32_t, uint32_t,
+			    dladm_aggr_port_attr_db_t *, uint32_t, boolean_t,
+			    uchar_t *, aggr_lacp_mode_t, aggr_lacp_timer_t,
+			    boolean_t, const char *);
+extern dladm_status_t	dladm_aggr_delete(uint32_t, boolean_t, const char *);
+extern dladm_status_t	dladm_aggr_add(uint32_t, uint32_t,
+			    dladm_aggr_port_attr_db_t *, boolean_t,
+			    const char *);
+extern dladm_status_t	dladm_aggr_remove(uint32_t, uint32_t,
+			    dladm_aggr_port_attr_db_t *, boolean_t,
+			    const char *);
+extern dladm_status_t	dladm_aggr_modify(uint32_t, uint32_t, uint32_t,
+			    boolean_t, uchar_t *, aggr_lacp_mode_t,
+			    aggr_lacp_timer_t, boolean_t, const char *);
+extern dladm_status_t	dladm_aggr_up(uint32_t, const char *);
+extern dladm_status_t	dladm_aggr_down(uint32_t);
+
+extern boolean_t	dladm_aggr_str2policy(const char *, uint32_t *);
+extern char		*dladm_aggr_policy2str(uint32_t, char *);
+extern boolean_t	dladm_aggr_str2macaddr(const char *, boolean_t *,
+			    uchar_t *);
+extern const char	*dladm_aggr_macaddr2str(unsigned char *, char *);
+
+extern boolean_t	dladm_aggr_str2lacpmode(const char *,
+			    aggr_lacp_mode_t *);
+extern const char	*dladm_aggr_lacpmode2str(aggr_lacp_mode_t, char *);
+extern boolean_t	dladm_aggr_str2lacptimer(const char *,
+			    aggr_lacp_timer_t *);
+extern const char	*dladm_aggr_lacptimer2str(aggr_lacp_timer_t, char *);
+
+extern const char	*dladm_aggr_portstate2str(aggr_port_state_t, char *);
+
+extern int		dladm_aggr_walk(int (*)(void *,
+			    dladm_aggr_grp_attr_t *), void *);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _LIBDLAGGR_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libdladm/common/libdllink.c	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,391 @@
+/*
+ * 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 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <strings.h>
+#include <sys/stat.h>
+#include <sys/dld.h>
+#include <libdlpi.h>
+#include <libdevinfo.h>
+#include <libdllink.h>
+#include <libdladm_impl.h>
+
+typedef struct dladm_dev {
+	char			dd_name[IFNAMSIZ];
+	struct dladm_dev	*dd_next;
+} dladm_dev_t;
+
+typedef struct dladm_walk {
+	dladm_dev_t		*dw_dev_list;
+} dladm_walk_t;
+
+/*
+ * Return the attributes of the specified datalink from the DLD driver.
+ */
+static int
+i_dladm_info(int fd, const char *name, dladm_attr_t *dap)
+{
+	dld_ioc_attr_t	dia;
+
+	if (strlen(name) >= IFNAMSIZ) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	(void) strlcpy(dia.dia_name, name, IFNAMSIZ);
+
+	if (i_dladm_ioctl(fd, DLDIOCATTR, &dia, sizeof (dia)) < 0)
+		return (-1);
+
+	(void) strlcpy(dap->da_dev, dia.dia_dev, MAXNAMELEN);
+	dap->da_max_sdu = dia.dia_max_sdu;
+	dap->da_vid = dia.dia_vid;
+
+	return (0);
+}
+
+/*
+ * Adds a datalink to the array corresponding to arg.
+ */
+static void
+i_dladm_nt_net_add(void *arg, char *name)
+{
+	dladm_walk_t	*dwp = arg;
+	dladm_dev_t	*ddp = dwp->dw_dev_list;
+	dladm_dev_t	**lastp = &dwp->dw_dev_list;
+
+	while (ddp) {
+		/*
+		 * Skip duplicates.
+		 */
+		if (strcmp(ddp->dd_name, name) == 0)
+			return;
+
+		lastp = &ddp->dd_next;
+		ddp = ddp->dd_next;
+	}
+
+	if ((ddp = malloc(sizeof (*ddp))) == NULL)
+		return;
+
+	(void) strlcpy(ddp->dd_name, name, IFNAMSIZ);
+	ddp->dd_next = NULL;
+	*lastp = ddp;
+}
+
+/*
+ * Walker callback invoked for each DDI_NT_NET node.
+ */
+static int
+i_dladm_nt_net_walk(di_node_t node, di_minor_t minor, void *arg)
+{
+	char		linkname[DLPI_LINKNAME_MAX];
+	dlpi_handle_t	dh;
+
+	if (dlpi_makelink(linkname, di_minor_name(minor),
+	    di_instance(node)) != DLPI_SUCCESS)
+		return (DI_WALK_CONTINUE);
+
+	if (dlpi_open(linkname, &dh, 0) == DLPI_SUCCESS) {
+		i_dladm_nt_net_add(arg, linkname);
+		dlpi_close(dh);
+	}
+	return (DI_WALK_CONTINUE);
+}
+
+/*
+ * Hold a data-link.
+ */
+static int
+i_dladm_hold_link(const char *name, zoneid_t zoneid, boolean_t docheck)
+{
+	int		fd;
+	dld_hold_vlan_t	dhv;
+
+	if (strlen(name) >= IFNAMSIZ) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
+		return (-1);
+
+	bzero(&dhv, sizeof (dld_hold_vlan_t));
+	(void) strlcpy(dhv.dhv_name, name, IFNAMSIZ);
+	dhv.dhv_zid = zoneid;
+	dhv.dhv_docheck = docheck;
+
+	if (i_dladm_ioctl(fd, DLDIOCHOLDVLAN, &dhv, sizeof (dhv)) < 0) {
+		int olderrno = errno;
+
+		(void) close(fd);
+		errno = olderrno;
+		return (-1);
+	}
+
+	(void) close(fd);
+	return (0);
+}
+
+/*
+ * Release a data-link.
+ */
+static int
+i_dladm_rele_link(const char *name, zoneid_t zoneid, boolean_t docheck)
+{
+	int		fd;
+	dld_hold_vlan_t	dhv;
+
+	if (strlen(name) >= IFNAMSIZ) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
+		return (-1);
+
+	bzero(&dhv, sizeof (dld_hold_vlan_t));
+	(void) strlcpy(dhv.dhv_name, name, IFNAMSIZ);
+	dhv.dhv_zid = zoneid;
+	dhv.dhv_docheck = docheck;
+
+	if (i_dladm_ioctl(fd, DLDIOCRELEVLAN, &dhv, sizeof (dhv)) < 0) {
+		int olderrno = errno;
+
+		(void) close(fd);
+		errno = olderrno;
+		return (-1);
+	}
+
+	(void) close(fd);
+	return (0);
+}
+
+/*
+ * Invoke the specified callback function for each active DDI_NT_NET
+ * node.
+ */
+int
+dladm_walk(void (*fn)(void *, const char *), void *arg)
+{
+	di_node_t	root;
+	dladm_walk_t	dw;
+	dladm_dev_t	*ddp, *last_ddp;
+
+	if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL) {
+		errno = EFAULT;
+		return (-1);
+	}
+	dw.dw_dev_list = NULL;
+
+	(void) di_walk_minor(root, DDI_NT_NET, DI_CHECK_ALIAS, &dw,
+	    i_dladm_nt_net_walk);
+
+	di_fini(root);
+
+	ddp = dw.dw_dev_list;
+	while (ddp) {
+		fn(arg, ddp->dd_name);
+		last_ddp = ddp;
+		ddp = ddp->dd_next;
+		free(last_ddp);
+	}
+
+	return (0);
+}
+
+/*
+ * MAC Administration Library.
+ *
+ * This library is used by administration tools such as dladm(1M) to
+ * iterate through the list of MAC interfaces
+ *
+ */
+
+typedef struct dladm_mac_dev {
+	char			dm_name[MAXNAMELEN];
+	struct dladm_mac_dev	*dm_next;
+} dladm_mac_dev_t;
+
+typedef struct macadm_walk {
+	dladm_mac_dev_t		*dmd_dev_list;
+} dladm_mac_walk_t;
+
+/*
+ * Local callback invoked for each DDI_NT_NET node.
+ */
+/* ARGSUSED */
+static int
+i_dladm_mac_walk(di_node_t node, di_minor_t minor, void *arg)
+{
+	dladm_mac_walk_t	*dmwp = arg;
+	dladm_mac_dev_t		*dmdp = dmwp->dmd_dev_list;
+	dladm_mac_dev_t		**last_dmdp = &dmwp->dmd_dev_list;
+	char			mac[MAXNAMELEN];
+
+	(void) snprintf(mac, MAXNAMELEN, "%s%d",
+	    di_driver_name(node), di_instance(node));
+
+	/*
+	 * Skip aggregations.
+	 */
+	if (strcmp("aggr", di_driver_name(node)) == 0)
+		return (DI_WALK_CONTINUE);
+
+	while (dmdp) {
+		/*
+		 * Skip duplicates.
+		 */
+		if (strcmp(dmdp->dm_name, mac) == 0)
+			return (DI_WALK_CONTINUE);
+
+		last_dmdp = &dmdp->dm_next;
+		dmdp = dmdp->dm_next;
+	}
+
+	if ((dmdp = malloc(sizeof (*dmdp))) == NULL)
+		return (DI_WALK_CONTINUE);
+
+	(void) strlcpy(dmdp->dm_name, mac, MAXNAMELEN);
+	dmdp->dm_next = NULL;
+	*last_dmdp = dmdp;
+
+	return (DI_WALK_CONTINUE);
+}
+
+/*
+ * Invoke the specified callback for each DDI_NT_MAC node.
+ */
+int
+dladm_mac_walk(void (*fn)(void *, const char *), void *arg)
+{
+	di_node_t		root;
+	dladm_mac_walk_t	dmw;
+	dladm_mac_dev_t		*dmdp, *next;
+
+	if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL)
+		return (-1);
+
+	dmw.dmd_dev_list = NULL;
+
+	(void) di_walk_minor(root, DDI_NT_NET, DI_CHECK_ALIAS, &dmw,
+	    i_dladm_mac_walk);
+
+	di_fini(root);
+
+	dmdp = dmw.dmd_dev_list;
+	for (dmdp = dmw.dmd_dev_list; dmdp != NULL; dmdp = next) {
+		next = dmdp->dm_next;
+		(*fn)(arg, dmdp->dm_name);
+		free(dmdp);
+	}
+
+	return (0);
+}
+
+/*
+ * Returns the current attributes of the specified datalink.
+ */
+int
+dladm_info(const char *name, dladm_attr_t *dap)
+{
+	int		fd;
+
+	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
+		return (-1);
+
+	if (i_dladm_info(fd, name, dap) < 0)
+		goto failed;
+
+	(void) close(fd);
+	return (0);
+
+failed:
+	(void) close(fd);
+	return (-1);
+}
+
+const char *
+dladm_linkstate2str(link_state_t state, char *buf)
+{
+	const char	*s;
+
+	switch (state) {
+	case LINK_STATE_UP:
+		s = "up";
+		break;
+	case LINK_STATE_DOWN:
+		s = "down";
+		break;
+	default:
+		s = "unknown";
+		break;
+	}
+	(void) snprintf(buf, DLADM_STRSIZE, "%s", s);
+	return (buf);
+}
+
+const char *
+dladm_linkduplex2str(link_duplex_t duplex, char *buf)
+{
+	const char	*s;
+
+	switch (duplex) {
+	case LINK_DUPLEX_FULL:
+		s = "full";
+		break;
+	case LINK_DUPLEX_HALF:
+		s = "half";
+		break;
+	default:
+		s = "unknown";
+		break;
+	}
+	(void) snprintf(buf, DLADM_STRSIZE, "%s", s);
+	return (buf);
+}
+
+/*
+ * Do a "hold" operation to a link.
+ */
+int
+dladm_hold_link(const char *name, zoneid_t zoneid, boolean_t docheck)
+{
+	return (i_dladm_hold_link(name, zoneid, docheck));
+}
+
+/*
+ * Do a "release" operation to a link.
+ */
+int
+dladm_rele_link(const char *name, zoneid_t zoneid, boolean_t docheck)
+{
+	return (i_dladm_rele_link(name, zoneid, docheck));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libdladm/common/libdllink.h	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,104 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _LIBDLLINK_H
+#define	_LIBDLLINK_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+/*
+ * This file includes strcutures, macros and routines used by general
+ * link administration, which applies not limited to one specific
+ * type of link.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mac.h>
+#include <libdladm.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef struct dladm_attr {
+	char		da_dev[MAXNAMELEN];
+	uint_t		da_max_sdu;
+	uint16_t	da_vid;
+} dladm_attr_t;
+
+/*
+ * Maximum size of secobj value. Note that it should not be greater than
+ * DLD_SECOBJ_VAL_MAX.
+ */
+#define	DLADM_SECOBJ_VAL_MAX	256
+
+/*
+ * Maximum size of secobj name. Note that it should not be greater than
+ * DLD_SECOBJ_NAME_MAX.
+ */
+#define	DLADM_SECOBJ_NAME_MAX	32
+
+#define	DLADM_PROP_VAL_MAX	25
+
+#define		DLADM_SECOBJ_CLASS_WEP	0
+typedef int	dladm_secobj_class_t;
+
+typedef void (dladm_walkcb_t)(void *, const char *);
+
+extern int	dladm_walk(dladm_walkcb_t *, void *);
+extern int	dladm_mac_walk(void (*fn)(void *, const char *), void *);
+extern int	dladm_info(const char *, dladm_attr_t *);
+extern int	dladm_hold_link(const char *, zoneid_t, boolean_t);
+extern int	dladm_rele_link(const char *, zoneid_t, boolean_t);
+
+extern dladm_status_t	dladm_set_prop(const char *, const char *,
+			    char **, uint_t, uint_t, char **);
+extern dladm_status_t	dladm_get_prop(const char *, dladm_prop_type_t,
+			    const char *, char **, uint_t *);
+extern dladm_status_t	dladm_walk_prop(const char *, void *,
+			    boolean_t (*)(void *, const char *));
+extern dladm_status_t	dladm_set_secobj(const char *, dladm_secobj_class_t,
+			    uint8_t *, uint_t, uint_t);
+extern dladm_status_t	dladm_get_secobj(const char *, dladm_secobj_class_t *,
+			    uint8_t *, uint_t *, uint_t);
+extern dladm_status_t	dladm_unset_secobj(const char *, uint_t);
+extern dladm_status_t	dladm_walk_secobj(void *,
+			    boolean_t (*)(void *, const char *), uint_t);
+
+extern const char	*dladm_linkstate2str(link_state_t, char *);
+extern const char	*dladm_linkduplex2str(link_duplex_t, char *);
+extern const char	*dladm_secobjclass2str(dladm_secobj_class_t, char *);
+extern dladm_status_t	dladm_str2secobjclass(const char *,
+			    dladm_secobj_class_t *);
+
+extern dladm_status_t	dladm_init_linkprop(void);
+extern dladm_status_t	dladm_init_secobj(void);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _LIBDLLINK_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libdladm/common/libdlwlan.c	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,1937 @@
+/*
+ * 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 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <libintl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stropts.h>
+#include <libdevinfo.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <libdlwlan.h>
+#include <libdlwlan_impl.h>
+#include <inet/wifi_ioctl.h>
+
+typedef struct val_desc {
+	char		*vd_name;
+	uint_t		vd_val;
+} val_desc_t;
+
+struct prop_desc;
+
+typedef dladm_status_t	wl_pd_getf_t(int, wldp_t *, char **, uint_t *);
+typedef dladm_status_t	wl_pd_setf_t(int, wldp_t *, val_desc_t *, uint_t);
+typedef dladm_status_t	wl_pd_checkf_t(int, wldp_t *, struct prop_desc *,
+			    char **, uint_t, val_desc_t **);
+typedef struct prop_desc {
+	char		*pd_name;
+	val_desc_t	pd_defval;
+	val_desc_t	*pd_modval;
+	uint_t		pd_nmodval;
+	wl_pd_setf_t	*pd_set;
+	wl_pd_getf_t	*pd_getmod;
+	wl_pd_getf_t	*pd_get;
+	wl_pd_checkf_t	*pd_check;
+} prop_desc_t;
+
+static int 	do_get_bsstype(int, wldp_t *);
+static int 	do_get_essid(int, wldp_t *);
+static int 	do_get_bssid(int, wldp_t *);
+static int 	do_get_signal(int, wldp_t *);
+static int 	do_get_encryption(int, wldp_t *);
+static int 	do_get_authmode(int, wldp_t *);
+static int 	do_get_linkstatus(int, wldp_t *);
+static int	do_get_esslist(int, wldp_t *);
+static int 	do_get_rate(int, wldp_t *);
+static int	do_get_phyconf(int, wldp_t *);
+static int	do_get_powermode(int, wldp_t *);
+static int	do_get_radio(int, wldp_t *);
+static int	do_get_mode(int, wldp_t *);
+
+static int	do_set_bsstype(int, wldp_t *, dladm_wlan_bsstype_t *);
+static int	do_set_authmode(int, wldp_t *, dladm_wlan_auth_t *);
+static int	do_set_encryption(int, wldp_t *, dladm_wlan_secmode_t *);
+static int	do_set_essid(int, wldp_t *, dladm_wlan_essid_t *);
+static int	do_set_createibss(int, wldp_t *, boolean_t *);
+static int	do_set_wepkey(int, wldp_t *, dladm_wlan_wepkey_t *, uint_t);
+static int	do_set_rate(int, wldp_t *, dladm_wlan_rates_t *);
+static int	do_set_powermode(int, wldp_t *, dladm_wlan_powermode_t *);
+static int	do_set_radio(int, wldp_t *, dladm_wlan_radio_t *);
+static int	do_set_channel(int, wldp_t *, dladm_wlan_channel_t *);
+
+static int	open_link(const char *);
+static int	do_scan(int, wldp_t *);
+static int	do_disconnect(int, wldp_t *);
+static boolean_t find_val_by_name(const char *, val_desc_t *, uint_t, uint_t *);
+static boolean_t find_name_by_val(uint_t, val_desc_t *, uint_t, char **);
+static void	generate_essid(dladm_wlan_essid_t *);
+
+static dladm_status_t	dladm_wlan_wlresult2status(wldp_t *);
+
+static wl_pd_getf_t	do_get_rate_mod, do_get_rate_prop, do_get_channel_prop,
+			do_get_powermode_prop, do_get_radio_prop;
+static wl_pd_setf_t 	do_set_rate_prop, do_set_powermode_prop,
+			do_set_radio_prop;
+static wl_pd_checkf_t	do_check_prop, do_check_rate;
+
+static val_desc_t	linkstatus_vals[] = {
+	{ "disconnected", 	DLADM_WLAN_LINKSTATUS_DISCONNECTED	},
+	{ "connected",		DLADM_WLAN_LINKSTATUS_CONNECTED	}
+};
+
+static val_desc_t 	secmode_vals[] = {
+	{ "none",	DLADM_WLAN_SECMODE_NONE		},
+	{ "wep",	DLADM_WLAN_SECMODE_WEP		}
+};
+
+static val_desc_t 	strength_vals[] = {
+	{ "very weak",	DLADM_WLAN_STRENGTH_VERY_WEAK 	},
+	{ "weak",	DLADM_WLAN_STRENGTH_WEAK		},
+	{ "good", 	DLADM_WLAN_STRENGTH_GOOD		},
+	{ "very good",	DLADM_WLAN_STRENGTH_VERY_GOOD	},
+	{ "excellent",	DLADM_WLAN_STRENGTH_EXCELLENT	}
+};
+
+static val_desc_t	mode_vals[] = {
+	{ "a",		DLADM_WLAN_MODE_80211A		},
+	{ "b",		DLADM_WLAN_MODE_80211B		},
+	{ "g",		DLADM_WLAN_MODE_80211G		},
+};
+
+static val_desc_t	auth_vals[] = {
+	{ "open",	DLADM_WLAN_AUTH_OPEN			},
+	{ "shared",	DLADM_WLAN_AUTH_SHARED		}
+};
+
+static val_desc_t	bsstype_vals[] = {
+	{ "bss",	DLADM_WLAN_BSSTYPE_BSS		},
+	{ "ibss",	DLADM_WLAN_BSSTYPE_IBSS		},
+	{ "any",	DLADM_WLAN_BSSTYPE_ANY		}
+};
+
+static val_desc_t	radio_vals[] = {
+	{ "on",		DLADM_WLAN_RADIO_ON			},
+	{ "off",	DLADM_WLAN_RADIO_OFF			}
+};
+
+static val_desc_t	powermode_vals[] = {
+	{ "off",	DLADM_WLAN_PM_OFF			},
+	{ "fast",	DLADM_WLAN_PM_FAST			},
+	{ "max",	DLADM_WLAN_PM_MAX			}
+};
+
+#define	VALCNT(vals)	(sizeof ((vals)) / sizeof (val_desc_t))
+static	prop_desc_t	prop_table[] = {
+
+	{ "channel",	{ NULL, 0 }, NULL, 0,
+	    NULL, NULL, do_get_channel_prop, do_check_prop},
+
+	{ "powermode",	{ "off", DLADM_WLAN_PM_OFF }, powermode_vals,
+	    VALCNT(powermode_vals),
+	    do_set_powermode_prop, NULL,
+	    do_get_powermode_prop, do_check_prop},
+
+	{ "radio", 	{ "on", DLADM_WLAN_RADIO_ON }, radio_vals,
+	    VALCNT(radio_vals),
+	    do_set_radio_prop, NULL,
+	    do_get_radio_prop, do_check_prop},
+
+	{ "speed",	{ "", 0 }, NULL, 0,
+	    do_set_rate_prop, do_get_rate_mod,
+	    do_get_rate_prop, do_check_rate}
+};
+/*
+ * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
+ * rates to be retrieved. However, we cannot increase it at this
+ * time because it will break binary comatibility with unbundled
+ * WiFi drivers and utilities. So for now we define an additional
+ * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
+ */
+#define	MAX_SUPPORT_RATES	64
+#define	DLADM_WLAN_MAX_PROPS	(sizeof (prop_table) / sizeof (prop_desc_t))
+#define	IS_CONNECTED(gbuf) \
+	((*(wl_linkstatus_t *)((gbuf)->wldp_buf) == WL_CONNECTED))
+
+static dladm_status_t
+dladm_wlan_wlresult2status(wldp_t *gbuf)
+{
+	switch (gbuf->wldp_result) {
+	case WL_SUCCESS:
+		return (DLADM_STATUS_OK);
+
+	case WL_NOTSUPPORTED:
+	case WL_LACK_FEATURE:
+		return (DLADM_STATUS_NOTSUP);
+
+	case WL_READONLY:
+		return (DLADM_STATUS_PROPRDONLY);
+
+	default:
+		break;
+	}
+
+	return (DLADM_STATUS_FAILED);
+}
+
+static int
+open_link(const char *link)
+{
+	char	linkname[MAXPATHLEN];
+	wldp_t	*gbuf;
+	int	fd;
+
+	if (link == NULL)
+		return (-1);
+
+	(void) snprintf(linkname, MAXPATHLEN, "/dev/%s", link);
+	if ((fd = open(linkname, O_RDWR)) < 0)
+		return (-1);
+
+	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
+		(void) close(fd);
+		return (-1);
+	}
+
+	/*
+	 * Check to see if the link is wireless.
+	 */
+	if (do_get_bsstype(fd, gbuf) < 0) {
+		free(gbuf);
+		(void) close(fd);
+		return (-1);
+	}
+
+	free(gbuf);
+	return (fd);
+}
+
+static dladm_wlan_mode_t
+do_convert_mode(wl_phy_conf_t *phyp)
+{
+	switch (phyp->wl_phy_fhss_conf.wl_fhss_subtype) {
+	case WL_ERP:
+		return (DLADM_WLAN_MODE_80211G);
+	case WL_OFDM:
+		return (DLADM_WLAN_MODE_80211A);
+	case WL_DSSS:
+	case WL_FHSS:
+		return (DLADM_WLAN_MODE_80211B);
+	default:
+		break;
+	}
+
+	return (DLADM_WLAN_MODE_NONE);
+}
+
+static boolean_t
+do_convert_chan(wl_phy_conf_t *phyp, uint32_t *channelp)
+{
+	wl_fhss_t *wlfp = &phyp->wl_phy_fhss_conf;
+	wl_ofdm_t *wlop = &phyp->wl_phy_ofdm_conf;
+
+	switch (wlfp->wl_fhss_subtype) {
+	case WL_FHSS:
+	case WL_DSSS:
+	case WL_IRBASE:
+	case WL_HRDS:
+	case WL_ERP:
+		*channelp = wlfp->wl_fhss_channel;
+		break;
+	case WL_OFDM:
+		*channelp = DLADM_WLAN_OFDM2CHAN(wlop->wl_ofdm_frequency);
+		break;
+	default:
+		return (B_FALSE);
+	}
+	return (B_TRUE);
+}
+
+#define	IEEE80211_RATE	0x7f
+static void
+fill_wlan_attr(wl_ess_conf_t *wlp, dladm_wlan_attr_t *attrp)
+{
+	int		i;
+
+	(void) memset(attrp, 0, sizeof (*attrp));
+
+	(void) snprintf(attrp->wa_essid.we_bytes, DLADM_WLAN_MAX_ESSID_LEN,
+	    "%s", wlp->wl_ess_conf_essid.wl_essid_essid);
+	attrp->wa_valid |= DLADM_WLAN_ATTR_ESSID;
+
+	(void) memcpy(attrp->wa_bssid.wb_bytes, wlp->wl_ess_conf_bssid,
+	    DLADM_WLAN_BSSID_LEN);
+	attrp->wa_valid |= DLADM_WLAN_ATTR_BSSID;
+
+	attrp->wa_secmode = (wlp->wl_ess_conf_wepenabled ==
+	    WL_ENC_WEP ? DLADM_WLAN_SECMODE_WEP : DLADM_WLAN_SECMODE_NONE);
+	attrp->wa_valid |= DLADM_WLAN_ATTR_SECMODE;
+
+	attrp->wa_bsstype = (wlp->wl_ess_conf_bsstype == WL_BSS_BSS ?
+	    DLADM_WLAN_BSSTYPE_BSS : DLADM_WLAN_BSSTYPE_IBSS);
+	attrp->wa_valid |= DLADM_WLAN_ATTR_BSSTYPE;
+
+	attrp->wa_auth = (wlp->wl_ess_conf_authmode == 0 ?
+	    DLADM_WLAN_AUTH_OPEN : DLADM_WLAN_AUTH_SHARED);
+	attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH;
+
+	attrp->wa_strength = DLADM_WLAN_SIGNAL2STRENGTH(wlp->wl_ess_conf_sl);
+	attrp->wa_valid |= DLADM_WLAN_ATTR_STRENGTH;
+
+	attrp->wa_mode = do_convert_mode((wl_phy_conf_t *)&wlp->wl_phy_conf);
+	attrp->wa_valid |= DLADM_WLAN_ATTR_MODE;
+
+	for (i = 0; i < MAX_SCAN_SUPPORT_RATES; i++) {
+		wlp->wl_supported_rates[i] &= IEEE80211_RATE;
+		if (wlp->wl_supported_rates[i] > attrp->wa_speed)
+			attrp->wa_speed = wlp->wl_supported_rates[i];
+	}
+	if (attrp->wa_speed > 0)
+		attrp->wa_valid |= DLADM_WLAN_ATTR_SPEED;
+
+	if (do_convert_chan((wl_phy_conf_t *)&wlp->wl_phy_conf,
+	    &attrp->wa_channel))
+		attrp->wa_valid |= DLADM_WLAN_ATTR_CHANNEL;
+}
+
+dladm_status_t
+dladm_wlan_scan(const char *link, void *arg,
+    boolean_t (*func)(void *, dladm_wlan_attr_t *))
+{
+	int			fd, i;
+	uint32_t		count;
+	wl_ess_conf_t		*wlp;
+	wldp_t 			*gbuf;
+	dladm_wlan_attr_t	wlattr;
+	dladm_status_t		status;
+	boolean_t		connected;
+
+	if ((fd = open_link(link)) < 0)
+		return (DLADM_STATUS_LINKINVAL);
+
+	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
+		status = DLADM_STATUS_NOMEM;
+		goto done;
+	}
+
+	if (do_get_linkstatus(fd, gbuf) < 0) {
+		status = DLADM_STATUS_FAILED;
+		goto done;
+	}
+	connected = IS_CONNECTED(gbuf);
+
+	if (do_scan(fd, gbuf) < 0) {
+		status = DLADM_STATUS_FAILED;
+		goto done;
+	}
+
+	if (do_get_esslist(fd, gbuf) < 0) {
+		status = DLADM_STATUS_FAILED;
+		goto done;
+	}
+
+	wlp = ((wl_ess_list_t *)gbuf->wldp_buf)->wl_ess_list_ess;
+	count = ((wl_ess_list_t *)(gbuf->wldp_buf))->wl_ess_list_num;
+
+	for (i = 0; i < count; i++, wlp++) {
+		fill_wlan_attr(wlp, &wlattr);
+		if (!func(arg, &wlattr))
+			break;
+	}
+
+	if (!connected) {
+		if (do_get_linkstatus(fd, gbuf) < 0) {
+			status = DLADM_STATUS_FAILED;
+			goto done;
+		}
+		if (IS_CONNECTED(gbuf))
+			(void) do_disconnect(fd, gbuf);
+	}
+
+	status = DLADM_STATUS_OK;
+done:
+	free(gbuf);
+	(void) close(fd);
+	return (status);
+}
+
+/*
+ * Structures used in building the list of eligible WLANs to connect to.
+ * Specifically, `connect_state' has the WLAN attributes that must be matched
+ * (in `cs_attr') and a growing list of WLANs that matched those attributes
+ * chained through `cs_list'.  Each element in the list is of type `attr_node'
+ * and has the matching WLAN's attributes and a pointer to the next element.
+ * For convenience, `cs_count' tracks the number of elements in the list.
+ */
+typedef struct attr_node {
+	dladm_wlan_attr_t	an_attr;
+	struct attr_node	*an_next;
+} attr_node_t;
+
+typedef struct connect_state {
+	dladm_wlan_attr_t	*cs_attr;
+	uint_t			cs_count;
+	attr_node_t		*cs_list;
+} connect_state_t;
+
+/*
+ * Compare two sets of WLAN attributes.  For now, we only consider strength
+ * and speed (in that order), which matches the documented default policy for
+ * dladm_wlan_connect().
+ */
+static int
+attr_compare(const void *p1, const void *p2)
+{
+	dladm_wlan_attr_t *attrp1, *attrp2;
+
+	attrp1 = (*(dladm_wlan_attr_t **)p1);
+	attrp2 = (*(dladm_wlan_attr_t **)p2);
+
+	if (attrp1->wa_strength < attrp2->wa_strength)
+		return (1);
+
+	if (attrp1->wa_strength > attrp2->wa_strength)
+		return (-1);
+
+	return (attrp2->wa_speed - attrp1->wa_speed);
+}
+
+/*
+ * Callback function used by dladm_wlan_connect() to filter out unwanted
+ * WLANs when scanning for available WLANs.  Always returns B_TRUE to
+ * continue the scan.
+ */
+static boolean_t
+connect_cb(void *arg, dladm_wlan_attr_t *attrp)
+{
+	attr_node_t		*nodep;
+	dladm_wlan_attr_t	*fattrp;
+	connect_state_t		*statep = (connect_state_t *)arg;
+
+	fattrp = statep->cs_attr;
+	if (fattrp == NULL)
+		goto append;
+
+	if ((fattrp->wa_valid & attrp->wa_valid) != fattrp->wa_valid)
+		return (B_TRUE);
+
+	if ((fattrp->wa_valid & DLADM_WLAN_ATTR_ESSID) != 0 &&
+	    strncmp(fattrp->wa_essid.we_bytes, attrp->wa_essid.we_bytes,
+	    DLADM_WLAN_MAX_ESSID_LEN) != 0)
+		return (B_TRUE);
+
+	if ((fattrp->wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0 &&
+	    fattrp->wa_secmode != attrp->wa_secmode)
+		return (B_TRUE);
+
+	if ((fattrp->wa_valid & DLADM_WLAN_ATTR_MODE) != 0 &&
+	    fattrp->wa_mode != attrp->wa_mode)
+		return (B_TRUE);
+
+	if ((fattrp->wa_valid & DLADM_WLAN_ATTR_STRENGTH) != 0 &&
+	    fattrp->wa_strength != attrp->wa_strength)
+		return (B_TRUE);
+
+	if ((fattrp->wa_valid & DLADM_WLAN_ATTR_SPEED) != 0 &&
+	    fattrp->wa_speed != attrp->wa_speed)
+		return (B_TRUE);
+
+	if ((fattrp->wa_valid & DLADM_WLAN_ATTR_AUTH) != 0) {
+		attrp->wa_auth = fattrp->wa_auth;
+		attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH;
+	}
+
+	if ((fattrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0 &&
+	    fattrp->wa_bsstype != attrp->wa_bsstype)
+		return (B_TRUE);
+
+	if ((fattrp->wa_valid & DLADM_WLAN_ATTR_BSSID) != 0 &&
+	    memcmp(fattrp->wa_bssid.wb_bytes, attrp->wa_bssid.wb_bytes,
+	    DLADM_WLAN_BSSID_LEN) != 0)
+		return (B_TRUE);
+append:
+	nodep = malloc(sizeof (attr_node_t));
+	if (nodep == NULL)
+		return (B_TRUE);
+
+	(void) memcpy(&nodep->an_attr, attrp, sizeof (dladm_wlan_attr_t));
+	nodep->an_next = statep->cs_list;
+	statep->cs_list = nodep;
+	statep->cs_count++;
+
+	return (B_TRUE);
+}
+
+static dladm_status_t
+do_connect(int fd, wldp_t *gbuf, dladm_wlan_attr_t *attrp,
+    boolean_t create_ibss, void *keys, uint_t key_count, int timeout)
+{
+	dladm_wlan_secmode_t		secmode;
+	dladm_wlan_auth_t		authmode;
+	dladm_wlan_bsstype_t		bsstype;
+	dladm_wlan_essid_t		essid;
+	boolean_t		essid_valid = B_FALSE;
+	dladm_wlan_channel_t		channel;
+	hrtime_t		start;
+
+	if ((attrp->wa_valid & DLADM_WLAN_ATTR_CHANNEL) != 0) {
+		channel = attrp->wa_channel;
+		if (do_set_channel(fd, gbuf, &channel) < 0)
+			goto fail;
+	}
+
+	secmode = ((attrp->wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0) ?
+	    attrp->wa_secmode : DLADM_WLAN_SECMODE_NONE;
+
+	if (do_set_encryption(fd, gbuf, &secmode) < 0)
+		goto fail;
+
+	authmode = ((attrp->wa_valid & DLADM_WLAN_ATTR_AUTH) != 0) ?
+	    attrp->wa_auth : DLADM_WLAN_AUTH_OPEN;
+
+	if (do_set_authmode(fd, gbuf, &authmode) < 0)
+		goto fail;
+
+	bsstype = ((attrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0) ?
+	    attrp->wa_bsstype : DLADM_WLAN_BSSTYPE_BSS;
+
+	if (do_set_bsstype(fd, gbuf, &bsstype) < 0)
+		goto fail;
+
+	if (secmode == DLADM_WLAN_SECMODE_WEP) {
+		if (keys == NULL || key_count == 0 || key_count > MAX_NWEPKEYS)
+			return (DLADM_STATUS_BADARG);
+		if (do_set_wepkey(fd, gbuf, keys, key_count) < 0)
+			goto fail;
+	}
+
+	if (create_ibss) {
+		if (do_set_channel(fd, gbuf, &channel) < 0)
+			goto fail;
+
+		if (do_set_createibss(fd, gbuf, &create_ibss) < 0)
+			goto fail;
+
+		if ((attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) == 0) {
+			generate_essid(&essid);
+			essid_valid = B_TRUE;
+		}
+	}
+
+	if ((attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) != 0) {
+		essid = attrp->wa_essid;
+		essid_valid = B_TRUE;
+	}
+
+	if (!essid_valid)
+		return (DLADM_STATUS_FAILED);
+	if (do_set_essid(fd, gbuf, &essid) < 0)
+		goto fail;
+
+	start = gethrtime();
+	for (;;) {
+		if (do_get_linkstatus(fd, gbuf) < 0)
+			goto fail;
+
+		if (IS_CONNECTED(gbuf))
+			break;
+
+		(void) poll(NULL, 0, DLADM_WLAN_CONNECT_POLLRATE);
+		if ((timeout >= 0) && (gethrtime() - start) /
+		    NANOSEC >= timeout)
+			return (DLADM_STATUS_TIMEDOUT);
+	}
+	return (DLADM_STATUS_OK);
+fail:
+	return (dladm_wlan_wlresult2status(gbuf));
+}
+
+dladm_status_t
+dladm_wlan_connect(const char *link, dladm_wlan_attr_t *attrp,
+    int timeout, void *keys, uint_t key_count, uint_t flags)
+{
+	int			fd, i;
+	wldp_t 			*gbuf = NULL;
+	connect_state_t		state = {0, NULL, NULL};
+	attr_node_t		*nodep = NULL;
+	boolean_t		create_ibss, set_authmode;
+	dladm_wlan_attr_t	**wl_list = NULL;
+	dladm_status_t		status = DLADM_STATUS_FAILED;
+
+	if ((fd = open_link(link)) < 0)
+		return (DLADM_STATUS_LINKINVAL);
+
+	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
+		status = DLADM_STATUS_NOMEM;
+		goto done;
+	}
+
+	if (do_get_linkstatus(fd, gbuf) < 0) {
+		status = DLADM_STATUS_FAILED;
+		goto done;
+	}
+
+	if (IS_CONNECTED(gbuf)) {
+		status = DLADM_STATUS_ISCONN;
+		goto done;
+	}
+
+	set_authmode = ((attrp != NULL) &&
+	    (attrp->wa_valid & DLADM_WLAN_ATTR_MODE) != 0);
+	create_ibss = ((flags & DLADM_WLAN_CONNECT_CREATEIBSS) != 0 &&
+	    attrp != NULL &&
+	    (attrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0 &&
+	    attrp->wa_bsstype == DLADM_WLAN_BSSTYPE_IBSS);
+
+	if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0 ||
+	    (create_ibss && attrp != NULL &&
+	    (attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) == 0)) {
+		status = do_connect(fd, gbuf, attrp,
+		    create_ibss, keys, key_count, timeout);
+		goto done;
+	}
+
+	state.cs_attr = attrp;
+	state.cs_list = NULL;
+	state.cs_count = 0;
+
+	status = dladm_wlan_scan(link, &state, connect_cb);
+	if (status != DLADM_STATUS_OK)
+		goto done;
+
+	if (state.cs_count == 0) {
+		if (!create_ibss) {
+			status = DLADM_STATUS_NOTFOUND;
+			goto done;
+		}
+		status = do_connect(fd, gbuf, attrp, create_ibss,
+		    keys, key_count, timeout);
+		goto done;
+	}
+
+	wl_list = malloc(state.cs_count * sizeof (dladm_wlan_attr_t *));
+	if (wl_list == NULL) {
+		status = DLADM_STATUS_NOMEM;
+		goto done;
+	}
+
+	nodep = state.cs_list;
+	for (i = 0; i < state.cs_count; i++) {
+		wl_list[i] = &nodep->an_attr;
+		nodep = nodep->an_next;
+	}
+	qsort(wl_list, state.cs_count, sizeof (dladm_wlan_attr_t *),
+	    attr_compare);
+
+	for (i = 0; i < state.cs_count; i++) {
+		dladm_wlan_attr_t	*ap = wl_list[i];
+
+		status = do_connect(fd, gbuf, ap, create_ibss, keys,
+		    key_count, timeout);
+		if (status == DLADM_STATUS_OK)
+			break;
+
+		if (!set_authmode) {
+			ap->wa_auth = DLADM_WLAN_AUTH_SHARED;
+			ap->wa_valid |= DLADM_WLAN_ATTR_AUTH;
+			status = do_connect(fd, gbuf, ap, create_ibss, keys,
+			    key_count, timeout);
+			if (status == DLADM_STATUS_OK)
+				break;
+		}
+	}
+done:
+	if ((status != DLADM_STATUS_OK) && (status != DLADM_STATUS_ISCONN))
+		(void) do_disconnect(fd, gbuf);
+
+	while (state.cs_list != NULL) {
+		nodep = state.cs_list;
+		state.cs_list = nodep->an_next;
+		free(nodep);
+	}
+	free(gbuf);
+	free(wl_list);
+	(void) close(fd);
+	return (status);
+}
+
+dladm_status_t
+dladm_wlan_disconnect(const char *link)
+{
+	int		fd;
+	wldp_t		*gbuf;
+	dladm_status_t	status;
+
+	if ((fd = open_link(link)) < 0)
+		return (DLADM_STATUS_BADARG);
+
+	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
+		status = DLADM_STATUS_NOMEM;
+		goto done;
+	}
+
+	if (do_get_linkstatus(fd, gbuf) < 0) {
+		status = DLADM_STATUS_FAILED;
+		goto done;
+	}
+
+	if (!IS_CONNECTED(gbuf)) {
+		status = DLADM_STATUS_NOTCONN;
+		goto done;
+	}
+
+	if (do_disconnect(fd, gbuf) < 0) {
+		status = DLADM_STATUS_FAILED;
+		goto done;
+	}
+
+	if (do_get_linkstatus(fd, gbuf) < 0) {
+		status = DLADM_STATUS_FAILED;
+		goto done;
+	}
+
+	if (IS_CONNECTED(gbuf)) {
+		status = DLADM_STATUS_FAILED;
+		goto done;
+	}
+
+	status = DLADM_STATUS_OK;
+done:
+	free(gbuf);
+	(void) close(fd);
+	return (status);
+}
+
+typedef struct dladm_wlan_linkname {
+	char			wl_name[MAXNAMELEN];
+	struct dladm_wlan_linkname	*wl_next;
+} dladm_wlan_linkname_t;
+
+typedef struct dladm_wlan_walk {
+	dladm_wlan_linkname_t	*ww_list;
+	dladm_status_t		ww_status;
+} dladm_wlan_walk_t;
+
+/* ARGSUSED */
+static int
+append_linkname(di_node_t node, di_minor_t minor, void *arg)
+{
+	dladm_wlan_walk_t		*statep = arg;
+	dladm_wlan_linkname_t	**lastp = &statep->ww_list;
+	dladm_wlan_linkname_t	*wlp = *lastp;
+	char			name[MAXNAMELEN];
+
+	(void) snprintf(name, MAXNAMELEN, "%s%d",
+	    di_driver_name(node), di_instance(node));
+
+	while (wlp != NULL) {
+		if (strcmp(wlp->wl_name, name) == 0)
+			return (DI_WALK_CONTINUE);
+
+		lastp = &wlp->wl_next;
+		wlp = wlp->wl_next;
+	}
+	if ((wlp = malloc(sizeof (*wlp))) == NULL) {
+		statep->ww_status = DLADM_STATUS_NOMEM;
+		return (DI_WALK_CONTINUE);
+	}
+
+	(void) strlcpy(wlp->wl_name, name, MAXNAMELEN);
+	wlp->wl_next = NULL;
+	*lastp = wlp;
+
+	return (DI_WALK_CONTINUE);
+}
+
+dladm_status_t
+dladm_wlan_walk(void *arg, boolean_t (*func)(void *, const char *))
+{
+	di_node_t		root;
+	dladm_wlan_walk_t		state;
+	dladm_wlan_linkname_t	*wlp, *wlp_next;
+	boolean_t		cont = B_TRUE;
+
+	if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL)
+		return (DLADM_STATUS_FAILED);
+
+	state.ww_list = NULL;
+	state.ww_status = DLADM_STATUS_OK;
+	(void) di_walk_minor(root, DDI_NT_NET_WIFI, DI_CHECK_ALIAS,
+	    &state, append_linkname);
+	di_fini(root);
+
+	for (wlp = state.ww_list; wlp != NULL; wlp = wlp_next) {
+		/*
+		 * NOTE: even if (*func)() returns B_FALSE, the loop continues
+		 * since all memory must be freed.
+		 */
+		if (cont)
+			cont = (*func)(arg, wlp->wl_name);
+		wlp_next = wlp->wl_next;
+		free(wlp);
+	}
+	return (state.ww_status);
+}
+
+dladm_status_t
+dladm_wlan_get_linkattr(const char *link, dladm_wlan_linkattr_t *attrp)
+{
+	int			fd;
+	wldp_t			*gbuf;
+	wl_rssi_t		signal;
+	wl_bss_type_t		bsstype;
+	wl_authmode_t		authmode;
+	wl_encryption_t		encryption;
+	wl_rates_t		*ratesp;
+	dladm_wlan_attr_t	*wl_attrp;
+	dladm_status_t		status = DLADM_STATUS_FAILED;
+
+	if (attrp == NULL)
+		return (DLADM_STATUS_BADARG);
+
+	if ((fd = open_link(link)) < 0)
+		return (DLADM_STATUS_LINKINVAL);
+
+	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
+		status = DLADM_STATUS_NOMEM;
+		goto done;
+	}
+
+	(void) memset(attrp, 0, sizeof (*attrp));
+	wl_attrp = &attrp->la_wlan_attr;
+
+	if (do_get_linkstatus(fd, gbuf) < 0)
+		goto done;
+
+	attrp->la_valid |= DLADM_WLAN_LINKATTR_STATUS;
+	if (!IS_CONNECTED(gbuf)) {
+		attrp->la_status = DLADM_WLAN_LINKSTATUS_DISCONNECTED;
+		status = DLADM_STATUS_OK;
+		goto done;
+	}
+	attrp->la_status = DLADM_WLAN_LINKSTATUS_CONNECTED;
+
+	if (do_get_essid(fd, gbuf) < 0)
+		goto done;
+
+	(void) strlcpy(wl_attrp->wa_essid.we_bytes,
+	    ((wl_essid_t *)(gbuf->wldp_buf))->wl_essid_essid,
+	    DLADM_WLAN_MAX_ESSID_LEN);
+
+	wl_attrp->wa_valid |= DLADM_WLAN_ATTR_ESSID;
+
+	if (do_get_bssid(fd, gbuf) < 0)
+		goto done;
+
+	(void) memcpy(wl_attrp->wa_bssid.wb_bytes, gbuf->wldp_buf,
+	    DLADM_WLAN_BSSID_LEN);
+
+	wl_attrp->wa_valid |= DLADM_WLAN_ATTR_BSSID;
+
+	if (do_get_encryption(fd, gbuf) < 0)
+		goto done;
+
+	encryption = *(wl_encryption_t *)(gbuf->wldp_buf);
+	wl_attrp->wa_valid |= DLADM_WLAN_ATTR_SECMODE;
+
+	switch (encryption) {
+	case WL_NOENCRYPTION:
+		wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_NONE;
+		break;
+	case WL_ENC_WEP:
+		wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_WEP;
+		break;
+	default:
+		wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_SECMODE;
+		break;
+	}
+
+	if (do_get_signal(fd, gbuf) < 0)
+		goto done;
+
+	signal = *(wl_rssi_t *)(gbuf->wldp_buf);
+	wl_attrp->wa_valid |= DLADM_WLAN_ATTR_STRENGTH;
+	wl_attrp->wa_strength = DLADM_WLAN_SIGNAL2STRENGTH(signal);
+
+	if (do_get_rate(fd, gbuf) < 0)
+		goto done;
+
+	ratesp = (wl_rates_t *)(gbuf->wldp_buf);
+	if (ratesp->wl_rates_num > 0) {
+		uint_t	i, r = 0;
+
+		for (i = 0; i < ratesp->wl_rates_num; i++) {
+			if (ratesp->wl_rates_rates[i] > r)
+				r = ratesp->wl_rates_rates[i];
+		}
+		wl_attrp->wa_speed = r;
+		wl_attrp->wa_valid |= DLADM_WLAN_ATTR_SPEED;
+	}
+
+	if (do_get_authmode(fd, gbuf) < 0)
+		goto done;
+
+	authmode = *(wl_authmode_t *)(gbuf->wldp_buf);
+	wl_attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH;
+
+	switch (authmode) {
+	case WL_OPENSYSTEM:
+		wl_attrp->wa_auth = DLADM_WLAN_AUTH_OPEN;
+		break;
+	case WL_SHAREDKEY:
+		wl_attrp->wa_auth = DLADM_WLAN_AUTH_SHARED;
+		break;
+	default:
+		wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_AUTH;
+		break;
+	}
+
+	if (do_get_bsstype(fd, gbuf) < 0)
+		goto done;
+
+	bsstype = *(wl_bss_type_t *)(gbuf->wldp_buf);
+	wl_attrp->wa_valid |= DLADM_WLAN_ATTR_BSSTYPE;
+
+	switch (bsstype) {
+	case WL_BSS_BSS:
+		wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_BSS;
+		break;
+	case WL_BSS_IBSS:
+		wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_IBSS;
+		break;
+	case WL_BSS_ANY:
+		wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_ANY;
+		break;
+	default:
+		wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_BSSTYPE;
+		break;
+	}
+
+	if (do_get_mode(fd, gbuf) < 0)
+		goto done;
+
+	wl_attrp->wa_mode = do_convert_mode((wl_phy_conf_t *)(gbuf->wldp_buf));
+	wl_attrp->wa_valid |= DLADM_WLAN_ATTR_MODE;
+	if (wl_attrp->wa_mode != DLADM_WLAN_MODE_NONE)
+		wl_attrp->wa_valid |= DLADM_WLAN_ATTR_MODE;
+
+	attrp->la_valid |= DLADM_WLAN_LINKATTR_WLAN;
+	status = DLADM_STATUS_OK;
+
+done:
+	free(gbuf);
+	(void) close(fd);
+	return (status);
+}
+
+boolean_t
+dladm_wlan_is_valid(const char *link)
+{
+	int fd = open_link(link);
+
+	if (fd < 0)
+		return (B_FALSE);
+
+	(void) close(fd);
+	return (B_TRUE);
+}
+
+/* ARGSUSED */
+static dladm_status_t
+do_check_prop(int fd, wldp_t *guf, prop_desc_t *pdp, char **prop_val,
+    uint_t val_cnt, val_desc_t **vdpp)
+{
+	int		i;
+	val_desc_t	*vdp;
+
+	if (pdp->pd_nmodval == 0)
+		return (DLADM_STATUS_PROPRDONLY);
+
+	if (val_cnt != 1)
+		return (DLADM_STATUS_BADVALCNT);
+
+	for (i = 0; i < pdp->pd_nmodval; i++)
+		if (strcasecmp(*prop_val, pdp->pd_modval[i].vd_name) == 0)
+			break;
+
+	if (i == pdp->pd_nmodval)
+		return (DLADM_STATUS_BADVAL);
+
+	vdp = malloc(sizeof (val_desc_t));
+	if (vdp == NULL)
+		return (DLADM_STATUS_NOMEM);
+
+	(void) memcpy(vdp, &pdp->pd_modval[i], sizeof (val_desc_t));
+	*vdpp = vdp;
+	return (DLADM_STATUS_OK);
+}
+
+static dladm_status_t
+do_set_prop(int fd, wldp_t *gbuf, prop_desc_t *pdp,
+    char **prop_val, uint_t val_cnt)
+{
+	dladm_status_t	status;
+	val_desc_t	*vdp = NULL;
+	uint_t		cnt;
+
+	if (pdp->pd_set == NULL)
+		return (DLADM_STATUS_PROPRDONLY);
+
+	if (prop_val != NULL) {
+		status = pdp->pd_check(fd, gbuf, pdp, prop_val,
+		    val_cnt, &vdp);
+
+		if (status != DLADM_STATUS_OK)
+			return (status);
+
+		cnt = val_cnt;
+	} else {
+		if (pdp->pd_defval.vd_name == NULL)
+			return (DLADM_STATUS_NOTSUP);
+
+		if ((vdp = malloc(sizeof (val_desc_t))) == NULL)
+			return (DLADM_STATUS_NOMEM);
+
+		*vdp = pdp->pd_defval;
+		cnt = 1;
+	}
+	status = pdp->pd_set(fd, gbuf, vdp, cnt);
+	if (status == DLADM_STATUS_OK) {
+		/*
+		 * Some ioctls return 0 but store error code in
+		 * wldp_result. Need to fix them.
+		 */
+		if (gbuf->wldp_result != WL_SUCCESS)
+			status = dladm_wlan_wlresult2status(gbuf);
+	}
+	free(vdp);
+	return (status);
+}
+
+dladm_status_t
+dladm_wlan_set_prop(const char *link, const char *prop_name,
+    char **prop_val, uint_t val_cnt, char **errprop)
+{
+	int		fd, i;
+	wldp_t		*gbuf = NULL;
+	boolean_t	found = B_FALSE;
+	dladm_status_t	status = DLADM_STATUS_OK;
+
+	if ((prop_name == NULL && prop_val != NULL) ||
+	    (prop_val != NULL && val_cnt == 0))
+		return (DLADM_STATUS_BADARG);
+
+	if ((fd = open_link(link)) < 0)
+		return (DLADM_STATUS_LINKINVAL);
+
+	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
+		status = DLADM_STATUS_NOMEM;
+		goto done;
+	}
+
+	for (i = 0; i < DLADM_WLAN_MAX_PROPS; i++) {
+		prop_desc_t	*pdp = &prop_table[i];
+		dladm_status_t	s;
+
+		if (prop_name != NULL &&
+		    (strcasecmp(prop_name, pdp->pd_name) != 0))
+			continue;
+
+		found = B_TRUE;
+		s = do_set_prop(fd, gbuf, pdp, prop_val, val_cnt);
+
+		if (prop_name != NULL) {
+			status = s;
+			break;
+		} else {
+			if (s != DLADM_STATUS_OK &&
+			    s != DLADM_STATUS_NOTSUP) {
+				if (errprop != NULL)
+					*errprop = pdp->pd_name;
+				status = s;
+				break;
+			}
+		}
+	}
+	if (!found)
+		status = DLADM_STATUS_NOTFOUND;
+done:
+	free(gbuf);
+	(void) close(fd);
+	return (status);
+}
+
+/* ARGSUSED */
+dladm_status_t
+dladm_wlan_walk_prop(const char *link, void *arg,
+    boolean_t (*func)(void *, const char *))
+{
+	int	i;
+
+	for (i = 0; i < DLADM_WLAN_MAX_PROPS; i++) {
+		if (!func(arg, prop_table[i].pd_name))
+			break;
+	}
+	return (DLADM_STATUS_OK);
+}
+
+dladm_status_t
+dladm_wlan_get_prop(const char *link, dladm_prop_type_t type,
+    const char *prop_name, char **prop_val, uint_t *val_cnt)
+{
+	int		fd;
+	int		i;
+	wldp_t		*gbuf;
+	dladm_status_t	status;
+	uint_t		cnt;
+	prop_desc_t	*pdp;
+
+	if (prop_val == NULL || val_cnt == NULL || *val_cnt == 0)
+		return (DLADM_STATUS_BADARG);
+
+	for (i = 0; i < DLADM_WLAN_MAX_PROPS; i++)
+		if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
+			break;
+
+	if (i == DLADM_WLAN_MAX_PROPS)
+		return (DLADM_STATUS_NOTFOUND);
+
+	if ((fd = open_link(link)) < 0)
+		return (DLADM_STATUS_LINKINVAL);
+
+	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
+		status = DLADM_STATUS_NOMEM;
+		goto done;
+	}
+	pdp = &prop_table[i];
+	status = DLADM_STATUS_OK;
+
+	switch (type) {
+	case DLADM_PROP_VAL_CURRENT:
+		status = pdp->pd_get(fd, gbuf, prop_val, val_cnt);
+		break;
+
+	case DLADM_PROP_VAL_DEFAULT:
+		if (pdp->pd_defval.vd_name == NULL) {
+			status = DLADM_STATUS_NOTSUP;
+			break;
+		}
+		(void) strcpy(*prop_val, pdp->pd_defval.vd_name);
+		*val_cnt = 1;
+		break;
+
+	case DLADM_PROP_VAL_MODIFIABLE:
+		if (pdp->pd_getmod != NULL) {
+			status = pdp->pd_getmod(fd, gbuf, prop_val, val_cnt);
+			break;
+		}
+		cnt = pdp->pd_nmodval;
+		if (cnt == 0) {
+			status = DLADM_STATUS_NOTSUP;
+		} else if (cnt > *val_cnt) {
+			status = DLADM_STATUS_TOOSMALL;
+		} else {
+			for (i = 0; i < cnt; i++) {
+				(void) strcpy(prop_val[i],
+				    pdp->pd_modval[i].vd_name);
+			}
+			*val_cnt = cnt;
+		}
+		break;
+	default:
+		status = DLADM_STATUS_BADARG;
+		break;
+	}
+done:
+	free(gbuf);
+	(void) close(fd);
+	return (status);
+}
+
+static boolean_t
+find_val_by_name(const char *str, val_desc_t *vdp, uint_t cnt, uint_t *valp)
+{
+	int	i;
+
+	for (i = 0; i < cnt; i++) {
+		if (strcasecmp(str, vdp[i].vd_name) == 0) {
+			*valp = vdp[i].vd_val;
+			return (B_TRUE);
+		}
+	}
+	return (B_FALSE);
+}
+
+static boolean_t
+find_name_by_val(uint_t val, val_desc_t *vdp, uint_t cnt, char **strp)
+{
+	int	i;
+
+	for (i = 0; i < cnt; i++) {
+		if (val == vdp[i].vd_val) {
+			*strp = vdp[i].vd_name;
+			return (B_TRUE);
+		}
+	}
+	return (B_FALSE);
+}
+
+const char *
+dladm_wlan_essid2str(dladm_wlan_essid_t *essid, char *buf)
+{
+	(void) snprintf(buf, DLADM_STRSIZE, "%s", essid->we_bytes);
+	return (buf);
+}
+
+const char *
+dladm_wlan_bssid2str(dladm_wlan_bssid_t *bssid, char *buf)
+{
+	return (_link_ntoa(bssid->wb_bytes, buf, DLADM_WLAN_BSSID_LEN,
+	    IFT_OTHER));
+}
+
+static const char *
+dladm_wlan_val2str(uint_t val, val_desc_t *vdp, uint_t cnt, char *buf)
+{
+	char	*s;
+
+	if (!find_name_by_val(val, vdp, cnt, &s))
+		s = "";
+
+	(void) snprintf(buf, DLADM_STRSIZE, "%s", s);
+	return (buf);
+}
+
+const char *
+dladm_wlan_secmode2str(dladm_wlan_secmode_t *secmode, char *buf)
+{
+	return (dladm_wlan_val2str((uint_t)*secmode, secmode_vals,
+	    VALCNT(secmode_vals), buf));
+}
+
+const char *
+dladm_wlan_strength2str(dladm_wlan_strength_t *strength, char *buf)
+{
+	return (dladm_wlan_val2str((uint_t)*strength, strength_vals,
+	    VALCNT(strength_vals), buf));
+}
+
+const char *
+dladm_wlan_mode2str(dladm_wlan_mode_t *mode, char *buf)
+{
+	return (dladm_wlan_val2str((uint_t)*mode, mode_vals,
+	    VALCNT(mode_vals), buf));
+}
+
+const char *
+dladm_wlan_speed2str(dladm_wlan_speed_t *speed, char *buf)
+{
+	(void) snprintf(buf, DLADM_STRSIZE, "%.*f", *speed % 2,
+	    (float)(*speed) / 2);
+	return (buf);
+}
+
+const char *
+dladm_wlan_auth2str(dladm_wlan_auth_t *auth, char *buf)
+{
+	return (dladm_wlan_val2str((uint_t)*auth, auth_vals,
+	    VALCNT(auth_vals), buf));
+}
+
+const char *
+dladm_wlan_bsstype2str(dladm_wlan_bsstype_t *bsstype, char *buf)
+{
+	return (dladm_wlan_val2str((uint_t)*bsstype, bsstype_vals,
+	    VALCNT(bsstype_vals), buf));
+}
+
+const char *
+dladm_wlan_linkstatus2str(dladm_wlan_linkstatus_t *linkstatus, char *buf)
+{
+	return (dladm_wlan_val2str((uint_t)*linkstatus, linkstatus_vals,
+	    VALCNT(linkstatus_vals), buf));
+}
+
+dladm_status_t
+dladm_wlan_str2essid(const char *str, dladm_wlan_essid_t *essid)
+{
+	if (str[0] == '\0')
+		return (DLADM_STATUS_BADARG);
+
+	(void) strlcpy(essid->we_bytes, str, DLADM_WLAN_MAX_ESSID_LEN);
+	return (DLADM_STATUS_OK);
+}
+
+dladm_status_t
+dladm_wlan_str2bssid(const char *str, dladm_wlan_bssid_t *bssid)
+{
+	int	len;
+	uchar_t	*buf;
+
+	buf = _link_aton(str, &len);
+	if (buf == NULL)
+		return (DLADM_STATUS_BADARG);
+
+	if (len != DLADM_WLAN_BSSID_LEN) {
+		free(buf);
+		return (DLADM_STATUS_BADARG);
+	}
+
+	(void) memcpy(bssid->wb_bytes, buf, len);
+	free(buf);
+	return (DLADM_STATUS_OK);
+}
+
+dladm_status_t
+dladm_wlan_str2secmode(const char *str, dladm_wlan_secmode_t *secmode)
+{
+	uint_t	val;
+
+	if (!find_val_by_name(str, secmode_vals, VALCNT(secmode_vals), &val))
+		return (DLADM_STATUS_BADARG);
+
+	*secmode = (dladm_wlan_secmode_t)val;
+	return (DLADM_STATUS_OK);
+}
+
+dladm_status_t
+dladm_wlan_str2strength(const char *str, dladm_wlan_strength_t *strength)
+{
+	uint_t	val;
+
+	if (!find_val_by_name(str, strength_vals, VALCNT(strength_vals), &val))
+		return (DLADM_STATUS_BADARG);
+
+	*strength = (dladm_wlan_strength_t)val;
+	return (DLADM_STATUS_OK);
+}
+
+dladm_status_t
+dladm_wlan_str2mode(const char *str, dladm_wlan_mode_t *mode)
+{
+	uint_t	val;
+
+	if (!find_val_by_name(str, mode_vals, VALCNT(mode_vals), &val))
+		return (DLADM_STATUS_BADARG);
+
+	*mode = (dladm_wlan_mode_t)val;
+	return (DLADM_STATUS_OK);
+}
+
+dladm_status_t
+dladm_wlan_str2speed(const char *str, dladm_wlan_speed_t *speed)
+{
+	*speed = (dladm_wlan_speed_t)(atof(str) * 2);
+	return (DLADM_STATUS_OK);
+}
+
+dladm_status_t
+dladm_wlan_str2auth(const char *str, dladm_wlan_auth_t *auth)
+{
+	uint_t	val;
+
+	if (!find_val_by_name(str, auth_vals, VALCNT(auth_vals), &val))
+		return (DLADM_STATUS_BADARG);
+
+	*auth = (dladm_wlan_auth_t)val;
+	return (DLADM_STATUS_OK);
+}
+
+dladm_status_t
+dladm_wlan_str2bsstype(const char *str, dladm_wlan_bsstype_t *bsstype)
+{
+	uint_t	val;
+
+	if (!find_val_by_name(str, bsstype_vals, VALCNT(bsstype_vals), &val))
+		return (DLADM_STATUS_BADARG);
+
+	*bsstype = (dladm_wlan_bsstype_t)val;
+	return (DLADM_STATUS_OK);
+}
+
+dladm_status_t
+dladm_wlan_str2linkstatus(const char *str, dladm_wlan_linkstatus_t *linkstatus)
+{
+	uint_t	val;
+
+	if (!find_val_by_name(str, linkstatus_vals, VALCNT(linkstatus_vals),
+	    &val))
+		return (DLADM_STATUS_BADARG);
+
+	*linkstatus = (dladm_wlan_linkstatus_t)val;
+	return (DLADM_STATUS_OK);
+}
+
+static int
+do_ioctl(int fd, wldp_t *gbuf, uint_t id, size_t len, uint_t cmd, size_t cmdlen)
+{
+	int			rc;
+	struct	strioctl	stri;
+
+	gbuf->wldp_type = NET_802_11;
+	gbuf->wldp_id	= id;
+	gbuf->wldp_length = len;
+
+	stri.ic_timout	= 0;
+	stri.ic_dp	= (char *)gbuf;
+	stri.ic_cmd	= cmd;
+	stri.ic_len	= cmdlen;
+
+	if ((rc = ioctl(fd, I_STR, &stri)) != 0) {
+		if (rc > 0)
+			errno = rc;
+		return (-1);
+	}
+	return (0);
+}
+
+static int
+do_get_ioctl(int fd, wldp_t *gbuf, uint_t id)
+{
+	(void) memset(gbuf, 0, MAX_BUF_LEN);
+	return (do_ioctl(fd, gbuf, id, MAX_BUF_LEN, WLAN_GET_PARAM,
+	    MAX_BUF_LEN));
+}
+
+static int
+do_set_ioctl(int fd, wldp_t *gbuf, uint_t id, void *buf, uint_t buflen)
+{
+	(void) memset(gbuf, 0, MAX_BUF_LEN);
+	(void) memcpy(gbuf->wldp_buf, buf, buflen);
+	buflen += WIFI_BUF_OFFSET;
+	return (do_ioctl(fd, gbuf, id, buflen, WLAN_SET_PARAM, buflen));
+}
+
+static int
+do_cmd_ioctl(int fd, wldp_t *gbuf, uint_t cmd)
+{
+	(void) memset(gbuf, 0, MAX_BUF_LEN);
+	return (do_ioctl(fd, gbuf, cmd, sizeof (wldp_t), WLAN_COMMAND,
+	    sizeof (wldp_t)));
+}
+
+static int
+do_scan(int fd, wldp_t *gbuf)
+{
+	return (do_cmd_ioctl(fd, gbuf, WL_SCAN));
+}
+
+static int
+do_disconnect(int fd, wldp_t *gbuf)
+{
+	return (do_cmd_ioctl(fd, gbuf, WL_DISASSOCIATE));
+}
+
+static int
+do_get_esslist(int fd, wldp_t *gbuf)
+{
+	(void) memset(gbuf, 0, MAX_BUF_LEN);
+	return (do_ioctl(fd, gbuf, WL_ESS_LIST, MAX_BUF_LEN,
+	    WLAN_GET_PARAM, sizeof (wldp_t)));
+}
+
+static int
+do_get_bssid(int fd, wldp_t *gbuf)
+{
+	return (do_get_ioctl(fd, gbuf, WL_BSSID));
+}
+
+static int
+do_get_essid(int fd, wldp_t *gbuf)
+{
+	return (do_get_ioctl(fd, gbuf, WL_ESSID));
+}
+
+static int
+do_get_bsstype(int fd, wldp_t *gbuf)
+{
+	return (do_get_ioctl(fd, gbuf, WL_BSS_TYPE));
+}
+
+static int
+do_get_linkstatus(int fd, wldp_t *gbuf)
+{
+	return (do_get_ioctl(fd, gbuf, WL_LINKSTATUS));
+}
+
+static int
+do_get_rate(int fd, wldp_t *gbuf)
+{
+	return (do_get_ioctl(fd, gbuf, WL_DESIRED_RATES));
+}
+
+static int
+do_get_phyconf(int fd, wldp_t *gbuf)
+{
+	return (do_get_ioctl(fd, gbuf, WL_PHY_CONFIG));
+}
+
+static int
+do_get_powermode(int fd, wldp_t *gbuf)
+{
+	return (do_get_ioctl(fd, gbuf, WL_POWER_MODE));
+}
+
+static int
+do_get_radio(int fd, wldp_t *gbuf)
+{
+	return (do_get_ioctl(fd, gbuf, WL_RADIO));
+}
+
+static int
+do_get_authmode(int fd, wldp_t *gbuf)
+{
+	return (do_get_ioctl(fd, gbuf, WL_AUTH_MODE));
+}
+
+static int
+do_get_encryption(int fd, wldp_t *gbuf)
+{
+	return (do_get_ioctl(fd, gbuf, WL_ENCRYPTION));
+}
+
+static int
+do_get_signal(int fd, wldp_t *gbuf)
+{
+	return (do_get_ioctl(fd, gbuf, WL_RSSI));
+}
+
+static int
+do_get_mode(int fd, wldp_t *gbuf)
+{
+	return (do_get_ioctl(fd, gbuf, WL_PHY_CONFIG));
+}
+
+static dladm_status_t
+do_get_rate_common(wldp_t *gbuf, char **prop_val, uint_t *val_cnt)
+{
+	wl_rates_t	*wrp = (wl_rates_t *)gbuf->wldp_buf;
+	uint_t		cnt = wrp->wl_rates_num;
+	uint_t		i;
+
+	if (cnt > *val_cnt)
+		return (DLADM_STATUS_TOOSMALL);
+	if (wrp->wl_rates_rates[0] == 0) {
+		prop_val[0][0] = '\0';
+		*val_cnt = 1;
+		return (DLADM_STATUS_OK);
+	}
+
+	for (i = 0; i < cnt; i++) {
+		(void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f",
+		    wrp->wl_rates_rates[i] % 2,
+		    (float)wrp->wl_rates_rates[i] / 2);
+	}
+	*val_cnt = cnt;
+	return (DLADM_STATUS_OK);
+}
+
+static dladm_status_t
+do_get_rate_prop(int fd, wldp_t *gbuf, char **prop_val, uint_t *val_cnt)
+{
+	if (do_get_rate(fd, gbuf) < 0)
+		return (dladm_wlan_wlresult2status(gbuf));
+
+	return (do_get_rate_common(gbuf, prop_val, val_cnt));
+}
+
+static dladm_status_t
+do_get_rate_mod(int fd, wldp_t *gbuf, char **prop_val, uint_t *val_cnt)
+{
+	if (do_get_ioctl(fd, gbuf, WL_SUPPORTED_RATES) < 0)
+		return (DLADM_STATUS_FAILED);
+
+	return (do_get_rate_common(gbuf, prop_val, val_cnt));
+}
+
+static dladm_status_t
+do_get_channel_prop(int fd, wldp_t *gbuf, char **prop_val, uint_t *val_cnt)
+{
+	uint32_t	channel;
+
+	if (do_get_phyconf(fd, gbuf) < 0)
+		return (dladm_wlan_wlresult2status(gbuf));
+
+	if (!do_convert_chan((wl_phy_conf_t *)gbuf->wldp_buf, &channel))
+		return (DLADM_STATUS_NOTFOUND);
+
+	(void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel);
+	*val_cnt = 1;
+
+	return (DLADM_STATUS_OK);
+}
+
+static dladm_status_t
+do_get_powermode_prop(int fd, wldp_t *gbuf, char **prop_val, uint_t *val_cnt)
+{
+	wl_ps_mode_t	*mode;
+	const char	*s;
+
+	if (do_get_powermode(fd, gbuf) < 0)
+		return (dladm_wlan_wlresult2status(gbuf));
+
+	mode = (wl_ps_mode_t *)(gbuf->wldp_buf);
+	switch (mode->wl_ps_mode) {
+	case WL_PM_AM:
+		s = "off";
+		break;
+	case WL_PM_MPS:
+		s = "max";
+		break;
+	case WL_PM_FAST:
+		s = "fast";
+		break;
+	default:
+		return (DLADM_STATUS_NOTFOUND);
+	}
+	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
+	*val_cnt = 1;
+
+	return (DLADM_STATUS_OK);
+}
+
+static dladm_status_t
+do_get_radio_prop(int fd, wldp_t *gbuf, char **prop_val, uint_t *val_cnt)
+{
+	wl_radio_t	radio;
+	const char	*s;
+
+	if (do_get_radio(fd, gbuf) < 0)
+		return (dladm_wlan_wlresult2status(gbuf));
+
+	radio = *(wl_radio_t *)(gbuf->wldp_buf);
+	switch (radio) {
+	case B_TRUE:
+		s = "on";
+		break;
+	case B_FALSE:
+		s = "off";
+		break;
+	default:
+		return (DLADM_STATUS_NOTFOUND);
+	}
+	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
+	*val_cnt = 1;
+
+	return (DLADM_STATUS_OK);
+}
+
+static int
+do_set_bsstype(int fd, wldp_t *gbuf, dladm_wlan_bsstype_t *bsstype)
+{
+	wl_bss_type_t	ibsstype;
+
+	switch (*bsstype) {
+	case DLADM_WLAN_BSSTYPE_BSS:
+		ibsstype = WL_BSS_BSS;
+		break;
+	case DLADM_WLAN_BSSTYPE_IBSS:
+		ibsstype = WL_BSS_IBSS;
+		break;
+	default:
+		ibsstype = WL_BSS_ANY;
+		break;
+	}
+	return (do_set_ioctl(fd, gbuf, WL_BSS_TYPE, &ibsstype,
+	    sizeof (ibsstype)));
+}
+
+static int
+do_set_authmode(int fd, wldp_t *gbuf, dladm_wlan_auth_t *auth)
+{
+	wl_authmode_t	auth_mode;
+
+	switch (*auth) {
+	case DLADM_WLAN_AUTH_OPEN:
+		auth_mode = WL_OPENSYSTEM;
+		break;
+	case DLADM_WLAN_AUTH_SHARED:
+		auth_mode = WL_SHAREDKEY;
+		break;
+	default:
+		return (-1);
+	}
+	return (do_set_ioctl(fd, gbuf, WL_AUTH_MODE, &auth_mode,
+	    sizeof (auth_mode)));
+}
+
+static int
+do_set_encryption(int fd, wldp_t *gbuf, dladm_wlan_secmode_t *secmode)
+{
+	wl_encryption_t	encryption;
+
+	switch (*secmode) {
+	case DLADM_WLAN_SECMODE_NONE:
+		encryption = WL_NOENCRYPTION;
+		break;
+	case DLADM_WLAN_SECMODE_WEP:
+		encryption = WL_ENC_WEP;
+		break;
+	default:
+		return (-1);
+	}
+	return (do_set_ioctl(fd, gbuf, WL_ENCRYPTION, &encryption,
+	    sizeof (encryption)));
+}
+
+static int
+do_set_wepkey(int fd, wldp_t *gbuf, dladm_wlan_wepkey_t *keys,
+    uint_t key_count)
+{
+	int			i;
+	wl_wep_key_t		*wkp;
+	wl_wep_key_tab_t	wepkey_tab;
+	dladm_wlan_wepkey_t	*kp;
+
+	if (key_count == 0 || key_count > MAX_NWEPKEYS || keys == NULL)
+		return (-1);
+
+	(void) memset(wepkey_tab, 0, sizeof (wepkey_tab));
+	for (i = 0; i < MAX_NWEPKEYS; i++)
+		wepkey_tab[i].wl_wep_operation = WL_NUL;
+
+	for (i = 0; i < key_count; i++) {
+		kp = &keys[i];
+		if (kp->wk_idx == 0 || kp->wk_idx > MAX_NWEPKEYS)
+			return (-1);
+		if (kp->wk_len != DLADM_WLAN_WEPKEY64_LEN &&
+		    kp->wk_len != DLADM_WLAN_WEPKEY128_LEN)
+			return (-1);
+
+		wkp = &wepkey_tab[kp->wk_idx - 1];
+		wkp->wl_wep_operation = WL_ADD;
+		wkp->wl_wep_length = kp->wk_len;
+		(void) memcpy(wkp->wl_wep_key, kp->wk_val, kp->wk_len);
+	}
+
+	return (do_set_ioctl(fd, gbuf, WL_WEP_KEY_TAB, &wepkey_tab,
+	    sizeof (wepkey_tab)));
+}
+
+static int
+do_set_essid(int fd, wldp_t *gbuf, dladm_wlan_essid_t *essid)
+{
+	wl_essid_t	iessid;
+
+	(void) memset(&iessid, 0, sizeof (essid));
+
+	if (essid != NULL && essid->we_bytes[0] != '\0') {
+		iessid.wl_essid_length = strlen(essid->we_bytes);
+		(void) strlcpy(iessid.wl_essid_essid, essid->we_bytes,
+		    sizeof (iessid.wl_essid_essid));
+	} else {
+		return (-1);
+	}
+	return (do_set_ioctl(fd, gbuf, WL_ESSID, &iessid, sizeof (iessid)));
+}
+
+/* ARGSUSED */
+static dladm_status_t
+do_check_rate(int fd, wldp_t *gbuf, prop_desc_t *pdp, char **prop_val,
+    uint_t val_cnt, val_desc_t **vdpp)
+{
+	int		i;
+	uint_t		modval_cnt = MAX_SUPPORT_RATES;
+	char		*buf, **modval;
+	dladm_status_t	status;
+	val_desc_t	*vdp = NULL;
+
+	if (val_cnt != 1)
+		return (DLADM_STATUS_BADVALCNT);
+
+	buf = malloc((sizeof (char *) + DLADM_STRSIZE) * MAX_SUPPORT_RATES);
+	if (buf == NULL)
+		goto done;
+
+	modval = (char **)(void *)buf;
+	for (i = 0; i < MAX_SUPPORT_RATES; i++) {
+		modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES +
+		    i * DLADM_STRSIZE;
+	}
+
+	status = do_get_rate_mod(fd, gbuf, modval, &modval_cnt);
+	if (status != DLADM_STATUS_OK)
+		goto done;
+
+	vdp = malloc(sizeof (val_desc_t));
+	if (vdp == NULL) {
+		status = DLADM_STATUS_NOMEM;
+		goto done;
+	}
+
+	for (i = 0; i < modval_cnt; i++) {
+		if (strcasecmp(*prop_val, modval[i]) == 0) {
+			vdp->vd_val = (uint_t)(atof(*prop_val) * 2);
+			status = DLADM_STATUS_OK;
+			*vdpp = vdp;
+			vdp = NULL;
+			break;
+		}
+	}
+	if (i == modval_cnt)
+		status = DLADM_STATUS_BADVAL;
+done:
+	free(buf);
+	free(vdp);
+	return (status);
+}
+
+static dladm_status_t
+do_set_rate_prop(int fd, wldp_t *gbuf, val_desc_t *vdp, uint_t val_cnt)
+{
+	dladm_wlan_rates_t	rates;
+
+	if (val_cnt != 1)
+		return (DLADM_STATUS_BADVALCNT);
+
+	rates.wr_cnt = 1;
+	rates.wr_rates[0] = vdp[0].vd_val;
+
+	if (do_set_rate(fd, gbuf, &rates) < 0)
+		return (dladm_wlan_wlresult2status(gbuf));
+
+	return (DLADM_STATUS_OK);
+}
+
+static int
+do_set_rate(int fd, wldp_t *gbuf, dladm_wlan_rates_t *rates)
+{
+	int		i;
+	uint_t		len;
+	wl_rates_t	*wrp = (wl_rates_t *)gbuf->wldp_buf;
+
+	(void) memset(gbuf, 0, MAX_BUF_LEN);
+
+	for (i = 0; i < rates->wr_cnt; i++)
+		wrp->wl_rates_rates[i] = rates->wr_rates[i];
+	wrp->wl_rates_num = rates->wr_cnt;
+
+	len = offsetof(wl_rates_t, wl_rates_rates) +
+	    (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET;
+	return (do_ioctl(fd, gbuf, WL_DESIRED_RATES, len, WLAN_SET_PARAM, len));
+}
+
+/* ARGSUSED */
+static dladm_status_t
+do_set_powermode_prop(int fd, wldp_t *gbuf, val_desc_t *vdp, uint_t val_cnt)
+{
+	dladm_wlan_powermode_t powermode = (dladm_wlan_powermode_t)vdp->vd_val;
+
+	if (do_set_powermode(fd, gbuf, &powermode) < 0)
+		return (dladm_wlan_wlresult2status(gbuf));
+
+	return (DLADM_STATUS_OK);
+}
+
+static int
+do_set_powermode(int fd, wldp_t *gbuf, dladm_wlan_powermode_t *pm)
+{
+	wl_ps_mode_t	ps_mode;
+
+	(void) memset(&ps_mode, 0xff, sizeof (ps_mode));
+
+	switch (*pm) {
+	case DLADM_WLAN_PM_OFF:
+		ps_mode.wl_ps_mode = WL_PM_AM;
+		break;
+	case DLADM_WLAN_PM_MAX:
+		ps_mode.wl_ps_mode = WL_PM_MPS;
+		break;
+	case DLADM_WLAN_PM_FAST:
+		ps_mode.wl_ps_mode = WL_PM_FAST;
+		break;
+	default:
+		return (-1);
+	}
+	return (do_set_ioctl(fd, gbuf, WL_POWER_MODE, &ps_mode,
+	    sizeof (ps_mode)));
+}
+
+/* ARGSUSED */
+static dladm_status_t
+do_set_radio_prop(int fd, wldp_t *gbuf, val_desc_t *vdp, uint_t val_cnt)
+{
+	dladm_wlan_radio_t	radio = (dladm_wlan_radio_t)vdp->vd_val;
+
+	if (do_set_radio(fd, gbuf, &radio) < 0)
+		return (dladm_wlan_wlresult2status(gbuf));
+
+	return (DLADM_STATUS_OK);
+}
+
+static int
+do_set_radio(int fd, wldp_t *gbuf, dladm_wlan_radio_t *radio)
+{
+	wl_radio_t r;
+
+	switch (*radio) {
+	case DLADM_WLAN_RADIO_ON:
+		r = B_TRUE;
+		break;
+	case DLADM_WLAN_RADIO_OFF:
+		r = B_FALSE;
+		break;
+	default:
+		return (-1);
+	}
+	return (do_set_ioctl(fd, gbuf, WL_RADIO, &r, sizeof (r)));
+}
+
+static int
+do_set_channel(int fd, wldp_t *gbuf, dladm_wlan_channel_t *channel)
+{
+	wl_phy_conf_t phy_conf;
+
+	if (*channel > MAX_CHANNEL_NUM)
+		return (-1);
+
+	(void) memset(&phy_conf, 0xff, sizeof (phy_conf));
+	phy_conf.wl_phy_dsss_conf.wl_dsss_channel = *channel;
+
+	return (do_set_ioctl(fd, gbuf, WL_PHY_CONFIG, &phy_conf,
+	    sizeof (phy_conf)));
+}
+
+static int
+do_set_createibss(int fd, wldp_t *gbuf, boolean_t *create_ibss)
+{
+	wl_create_ibss_t cr = (wl_create_ibss_t)(*create_ibss);
+
+	return (do_set_ioctl(fd, gbuf, WL_CREATE_IBSS, &cr, sizeof (cr)));
+}
+
+static void
+generate_essid(dladm_wlan_essid_t *essid)
+{
+	srandom(gethrtime());
+	(void) snprintf(essid->we_bytes, DLADM_WLAN_MAX_ESSID_LEN, "%d",
+	    random());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libdladm/common/libdlwlan.h	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,202 @@
+/*
+ * 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 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _LIBDLWLAN_H
+#define	_LIBDLWLAN_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+/*
+ * This file includes structures, macros and routines used by WLAN link
+ * administration.
+ */
+
+#include <sys/types.h>
+#include <libdladm.h>
+
+/*
+ * General libdlwlan definitions and functions.
+ *
+ * These interfaces are ON consolidation-private.
+ * For documentation, refer to PSARC/2006/623.
+ */
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#define	DLADM_WLAN_MAX_ESSID_LEN	32	/* per 802.11 spec */
+#define	DLADM_WLAN_BSSID_LEN		6	/* per 802.11 spec */
+
+#define	DLADM_WLAN_CONNECT_TIMEOUT_DEFAULT	10
+#define	DLADM_WLAN_CONNECT_CREATEIBSS		0x00000001
+#define	DLADM_WLAN_CONNECT_NOSCAN		0x00000002
+
+typedef struct dladm_wlan_essid {
+	char	we_bytes[DLADM_WLAN_MAX_ESSID_LEN];
+} dladm_wlan_essid_t;
+
+typedef struct dladm_wlan_bssid {
+	uint8_t	wb_bytes[DLADM_WLAN_BSSID_LEN];
+} dladm_wlan_bssid_t;
+
+typedef enum {
+	DLADM_WLAN_SECMODE_NONE = 1,
+	DLADM_WLAN_SECMODE_WEP
+} dladm_wlan_secmode_t;
+
+typedef enum {
+	DLADM_WLAN_STRENGTH_VERY_WEAK = 1,
+	DLADM_WLAN_STRENGTH_WEAK,
+	DLADM_WLAN_STRENGTH_GOOD,
+	DLADM_WLAN_STRENGTH_VERY_GOOD,
+	DLADM_WLAN_STRENGTH_EXCELLENT
+} dladm_wlan_strength_t;
+
+typedef enum {
+	DLADM_WLAN_MODE_NONE = 0,
+	DLADM_WLAN_MODE_80211A,
+	DLADM_WLAN_MODE_80211B,
+	DLADM_WLAN_MODE_80211G
+} dladm_wlan_mode_t;
+
+typedef enum {
+	DLADM_WLAN_AUTH_OPEN = 1,
+	DLADM_WLAN_AUTH_SHARED
+} dladm_wlan_auth_t;
+
+typedef enum {
+	DLADM_WLAN_BSSTYPE_BSS = 1,
+	DLADM_WLAN_BSSTYPE_IBSS,
+	DLADM_WLAN_BSSTYPE_ANY
+} dladm_wlan_bsstype_t;
+
+typedef enum {
+	DLADM_WLAN_LINKSTATUS_DISCONNECTED = 1,
+	DLADM_WLAN_LINKSTATUS_CONNECTED
+} dladm_wlan_linkstatus_t;
+
+typedef uint32_t dladm_wlan_speed_t;
+typedef	uint32_t dladm_wlan_channel_t;
+
+enum {
+	DLADM_WLAN_ATTR_ESSID	= 0x00000001,
+	DLADM_WLAN_ATTR_BSSID	= 0x00000002,
+	DLADM_WLAN_ATTR_SECMODE	= 0x00000004,
+	DLADM_WLAN_ATTR_STRENGTH = 0x00000008,
+	DLADM_WLAN_ATTR_MODE	= 0x00000010,
+	DLADM_WLAN_ATTR_SPEED	= 0x00000020,
+	DLADM_WLAN_ATTR_AUTH	= 0x00000040,
+	DLADM_WLAN_ATTR_BSSTYPE	= 0x00000080,
+	DLADM_WLAN_ATTR_CHANNEL	= 0x00000100
+};
+typedef struct dladm_wlan_attr {
+	uint_t			wa_valid;
+	dladm_wlan_essid_t	wa_essid;
+	dladm_wlan_bssid_t	wa_bssid;
+	dladm_wlan_secmode_t	wa_secmode;
+	dladm_wlan_strength_t	wa_strength;
+	dladm_wlan_mode_t	wa_mode;
+	dladm_wlan_speed_t	wa_speed;
+	dladm_wlan_auth_t	wa_auth;
+	dladm_wlan_bsstype_t	wa_bsstype;
+	dladm_wlan_channel_t	wa_channel;
+} dladm_wlan_attr_t;
+
+enum {
+	DLADM_WLAN_LINKATTR_STATUS	= 0x00000001,
+	DLADM_WLAN_LINKATTR_WLAN	= 0x00000002
+};
+typedef struct dladm_wlan_linkattr {
+	uint_t			la_valid;
+	dladm_wlan_linkstatus_t	la_status;
+	dladm_wlan_attr_t	la_wlan_attr;
+} dladm_wlan_linkattr_t;
+
+#define	DLADM_WLAN_WEPKEY64_LEN		5 	/* per WEP spec */
+#define	DLADM_WLAN_WEPKEY128_LEN	13 	/* per WEP spec */
+#define	DLADM_WLAN_MAX_WEPKEY_LEN	13	/* per WEP spec */
+#define	DLADM_WLAN_MAX_WEPKEYS		4 	/* MAX_NWEPKEYS */
+#define	DLADM_WLAN_MAX_WEPKEYNAME_LEN	64
+typedef struct dladm_wlan_wepkey {
+	uint_t		wk_idx;
+	uint_t		wk_len;
+	uint8_t		wk_val[DLADM_WLAN_MAX_WEPKEY_LEN];
+	char		wk_name[DLADM_WLAN_MAX_WEPKEYNAME_LEN];
+} dladm_wlan_wepkey_t;
+
+extern dladm_status_t	dladm_wlan_scan(const char *, void *,
+			    boolean_t (*)(void *, dladm_wlan_attr_t *));
+extern dladm_status_t	dladm_wlan_connect(const char *, dladm_wlan_attr_t *,
+			    int, void *, uint_t, uint_t);
+extern dladm_status_t	dladm_wlan_disconnect(const char *);
+extern dladm_status_t	dladm_wlan_get_linkattr(const char *,
+			    dladm_wlan_linkattr_t *);
+extern dladm_status_t	dladm_wlan_walk(void *,
+			    boolean_t (*)(void *, const char *));
+extern boolean_t	dladm_wlan_is_valid(const char *);
+extern dladm_status_t	dladm_wlan_set_prop(const char *, const char *,
+			    char **, uint_t, char **);
+extern dladm_status_t	dladm_wlan_walk_prop(const char *, void *,
+			    boolean_t (*)(void *, const char *));
+extern dladm_status_t	dladm_wlan_get_prop(const char *, dladm_prop_type_t,
+			    const char *, char **, uint_t *);
+
+extern const char	*dladm_wlan_essid2str(dladm_wlan_essid_t *, char *);
+extern const char	*dladm_wlan_bssid2str(dladm_wlan_bssid_t *, char *);
+extern const char	*dladm_wlan_secmode2str(dladm_wlan_secmode_t *, char *);
+extern const char	*dladm_wlan_strength2str(dladm_wlan_strength_t *,
+			    char *);
+extern const char	*dladm_wlan_mode2str(dladm_wlan_mode_t *, char *);
+extern const char	*dladm_wlan_speed2str(dladm_wlan_speed_t *, char *);
+extern const char	*dladm_wlan_auth2str(dladm_wlan_auth_t *, char *);
+extern const char	*dladm_wlan_bsstype2str(dladm_wlan_bsstype_t *, char *);
+extern const char	*dladm_wlan_linkstatus2str(dladm_wlan_linkstatus_t *,
+			    char *);
+
+extern dladm_status_t	dladm_wlan_str2essid(const char *,
+			    dladm_wlan_essid_t *);
+extern dladm_status_t	dladm_wlan_str2bssid(const char *,
+			    dladm_wlan_bssid_t *);
+extern dladm_status_t	dladm_wlan_str2secmode(const char *,
+			    dladm_wlan_secmode_t *);
+extern dladm_status_t	dladm_wlan_str2strength(const char *,
+			    dladm_wlan_strength_t *);
+extern dladm_status_t	dladm_wlan_str2mode(const char *,
+			    dladm_wlan_mode_t *);
+extern dladm_status_t	dladm_wlan_str2speed(const char *,
+			    dladm_wlan_speed_t *);
+extern dladm_status_t	dladm_wlan_str2auth(const char *,
+			    dladm_wlan_auth_t *);
+extern dladm_status_t	dladm_wlan_str2bsstype(const char *,
+			    dladm_wlan_bsstype_t *);
+extern dladm_status_t	dladm_wlan_str2linkstatus(const char *,
+			    dladm_wlan_linkstatus_t *);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _LIBDLWLAN_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libdladm/common/libdlwlan_impl.h	Wed Mar 21 09:48:58 2007 -0700
@@ -0,0 +1,83 @@
+/*
+ * 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 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _LIBDLWLAN_IMPL_H
+#define	_LIBDLWLAN_IMPL_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/types.h>
+#include <inet/wifi_ioctl.h>
+
+/*
+ * Implementation-private data structures, macros, and constants.
+ */
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * Map a signal value from 0-15 into an enumerated strength.  Since there are
+ * 5 strengths but 16 values, by convention the "middle" strength gets the
+ * extra value.  Thus, the buckets are 0-2, 3-5, 6-9, 10-12, and 13-15.
+ */
+#define	DLADM_WLAN_SIGNAL2STRENGTH(signal)			\
+	    (((signal) > 12 ? DLADM_WLAN_STRENGTH_EXCELLENT :	\
+	    ((signal) > 9 ? DLADM_WLAN_STRENGTH_VERY_GOOD : 	\
+	    ((signal) > 5 ? DLADM_WLAN_STRENGTH_GOOD :		\
+	    ((signal) > 2 ? DLADM_WLAN_STRENGTH_WEAK :		\
+	    DLADM_WLAN_STRENGTH_VERY_WEAK)))))
+
+/*
+ * Convert between an OFDM MHz and a channel number.
+ */
+#define	DLADM_WLAN_OFDM2CHAN(mhz)		(((mhz) - 5000) / 5)
+
+#define	DLADM_WLAN_CONNECT_POLLRATE		200 /* milliseconds */
+#define	DLADM_WLAN_CONNECT_DEFAULT_CHANNEL	1
+
+#define	DLADM_WLAN_MAX_RATES	4
+typedef	struct dladm_wlan_rates {
+	uint8_t		wr_rates[DLADM_WLAN_MAX_RATES];
+	int		wr_cnt;
+} dladm_wlan_rates_t;
+
+typedef enum {
+	DLADM_WLAN_RADIO_ON = 1,
+	DLADM_WLAN_RADIO_OFF
+} dladm_wlan_radio_t;
+
+typedef	enum {
+	DLADM_WLAN_PM_OFF = 1,
+	DLADM_WLAN_PM_MAX,
+	DLADM_WLAN_PM_FAST
+} dladm_wlan_powermode_t;
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _LIBDLWLAN_IMPL_H */
--- a/usr/src/lib/libdladm/common/linkprop.c	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/lib/libdladm/common/linkprop.c	Wed Mar 21 09:48:58 2007 -0700
@@ -37,9 +37,9 @@
 #include <unistd.h>
 #include <libdevinfo.h>
 #include <zone.h>
-#include <libwladm.h>
+#include <libdllink.h>
 #include <libdladm_impl.h>
-
+#include <libdlwlan.h>
 #include <dlfcn.h>
 #include <link.h>
 
@@ -90,45 +90,6 @@
 
 #define	MAX_PROPS	(sizeof (prop_table) / sizeof (prop_desc_t))
 
-/*
- * Convert a wladm_status_t to a dladm_status_t. This is used by wrappers
- * to libwladm routines (e.g. dladm_set_prop()). Note that the mapping is
- * not 1-1; whenever possible we try to look for an error code with a
- * similar meaning. Error codes with no suitable counterpart in libdladm
- * will be mapped to DLADM_STATUS_FAILED. Clients who require clearer error
- * reporting should use libwladm directly.
- */
-static dladm_status_t
-dladm_wladmstatus2status(wladm_status_t wstatus)
-{
-	switch (wstatus) {
-	case WLADM_STATUS_OK:
-		return (DLADM_STATUS_OK);
-	case WLADM_STATUS_FAILED:
-		return (DLADM_STATUS_FAILED);
-	case WLADM_STATUS_NOTSUP:
-		return (DLADM_STATUS_NOTSUP);
-	case WLADM_STATUS_BADARG:
-		return (DLADM_STATUS_BADARG);
-	case WLADM_STATUS_NOTFOUND:
-		return (DLADM_STATUS_NOTFOUND);
-	case WLADM_STATUS_BADVAL:
-		return (DLADM_STATUS_BADVAL);
-	case WLADM_STATUS_LINKINVAL:
-		return (DLADM_STATUS_LINKINVAL);
-	case WLADM_STATUS_NOMEM:
-		return (DLADM_STATUS_NOMEM);
-	case WLADM_STATUS_PROPRDONLY:
-		return (DLADM_STATUS_PROPRDONLY);
-	case WLADM_STATUS_TOOSMALL:
-		return (DLADM_STATUS_TOOSMALL);
-	case WLADM_STATUS_BADVALCNT:
-		return (DLADM_STATUS_BADVALCNT);
-	default:
-		return (DLADM_STATUS_FAILED);
-	}
-}
-
 dladm_status_t
 dladm_set_prop(const char *link, const char *prop_name, char **prop_val,
     uint_t val_cnt, uint_t flags, char **errprop)
@@ -148,10 +109,9 @@
 
 		if (status == DLADM_STATUS_NOTFOUND) {
 			status = DLADM_STATUS_BADARG;
-			if (wladm_is_valid(link)) {
-				status = dladm_wladmstatus2status(
-				    wladm_set_prop(link, prop_name,
-				    prop_val, val_cnt, errprop));
+			if (dladm_wlan_is_valid(link)) {
+				status = dladm_wlan_set_prop(link, prop_name,
+				    prop_val, val_cnt, errprop);
 			}
 		}
 		if (status != DLADM_STATUS_OK)
@@ -177,11 +137,10 @@
 		return (DLADM_STATUS_BADARG);
 
 	/* For wifi links, show wifi properties first */
-	if (wladm_is_valid(link)) {
+	if (dladm_wlan_is_valid(link)) {
 		dladm_status_t	status;
 
-		status = dladm_wladmstatus2status(
-		    wladm_walk_prop(link, arg, func));
+		status = dladm_wlan_walk_prop(link, arg, func);
 		if (status != DLADM_STATUS_OK)
 			return (status);
 	}
@@ -205,6 +164,8 @@
 		return (DLADM_STATUS_BADARG);
 
 	if (type == DLADM_PROP_VAL_PERSISTENT) {
+		if (i_dladm_is_prop_temponly(prop_name, NULL))
+			return (DLADM_STATUS_TEMPONLY);
 		return (i_dladm_get_prop_db(link, prop_name,
 		    prop_val, val_cntp));
 	}
@@ -214,26 +175,9 @@
 	if (status != DLADM_STATUS_NOTFOUND)
 		return (status);
 
-	if (wladm_is_valid(link)) {
-		wladm_prop_type_t	wtype;
-
-		switch (type) {
-		case DLADM_PROP_VAL_CURRENT:
-			wtype = WLADM_PROP_VAL_CURRENT;
-			break;
-		case DLADM_PROP_VAL_DEFAULT:
-			wtype = WLADM_PROP_VAL_DEFAULT;
-			break;
-		case DLADM_PROP_VAL_MODIFIABLE:
-			wtype = WLADM_PROP_VAL_MODIFIABLE;
-			break;
-		default:
-			return (DLADM_STATUS_BADARG);
-		}
-
-		return (dladm_wladmstatus2status(
-		    wladm_get_prop(link, wtype, prop_name,
-		    prop_val, val_cntp)));
+	if (dladm_wlan_is_valid(link)) {
+		return (dladm_wlan_get_prop(link, type, prop_name,
+		    prop_val, val_cntp));
 	}
 	return (DLADM_STATUS_BADARG);
 }
@@ -1195,9 +1139,3 @@
 
 	return (B_FALSE);
 }
-
-boolean_t
-dladm_is_prop_temponly(const char *prop_name, char **errprop)
-{
-	return (i_dladm_is_prop_temponly(prop_name, errprop));
-}
--- a/usr/src/lib/libdladm/common/llib-ldladm	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/lib/libdladm/common/llib-ldladm	Wed Mar 21 09:48:58 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -29,4 +28,6 @@
 /*LINTLIBRARY*/
 /*PROTOLIB1*/
 
-#include <libdladm.h>
+#include <libdllink.h>
+#include <libdlaggr.h>
+#include <libdlwlan.h>
--- a/usr/src/lib/libdladm/common/mapfile-vers	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/lib/libdladm/common/mapfile-vers	Wed Mar 21 09:48:58 2007 -0700
@@ -29,24 +29,69 @@
     global:
 	dladm_info;
 	dladm_walk;
-	dladm_walk_vlan;
+	dladm_hold_link;
+	dladm_rele_link;
+	dladm_status2str;
+	dladm_linkstate2str;
+	dladm_linkduplex2str;
+	dladm_set_rootdir;
+	dladm_mac_walk;
+	dladm_init_linkprop;
 	dladm_get_prop;
 	dladm_set_prop;
 	dladm_walk_prop;
-	dladm_is_prop_temponly;
+	dladm_init_secobj;
 	dladm_get_secobj;
 	dladm_set_secobj;
 	dladm_unset_secobj;
 	dladm_walk_secobj;
-	dladm_status2str;
 	dladm_secobjclass2str;
 	dladm_str2secobjclass;
-	dladm_init_linkprop;
-	dladm_init_secobj;
-	dladm_set_rootdir;
+	dladm_aggr_walk;
+	dladm_aggr_up;
+	dladm_aggr_down;
+	dladm_aggr_add;
+	dladm_aggr_create;
+	dladm_aggr_delete;
+	dladm_aggr_modify;
+	dladm_aggr_remove;
+	dladm_aggr_lacpmode2str;
+	dladm_aggr_lacptimer2str;
+	dladm_aggr_macaddr2str;
+	dladm_aggr_policy2str;
+	dladm_aggr_portstate2str;
+	dladm_aggr_str2lacpmode;
+	dladm_aggr_str2lacptimer;
+	dladm_aggr_str2macaddr;
+	dladm_aggr_str2policy;
+	dladm_wlan_walk;
+	dladm_wlan_scan;
+	dladm_wlan_connect;
+	dladm_wlan_disconnect;
+	dladm_wlan_get_linkattr;
+	dladm_wlan_is_valid;
+	dladm_wlan_set_prop;
+	dladm_wlan_walk_prop;
+	dladm_wlan_get_prop;
+	dladm_wlan_essid2str;
+	dladm_wlan_bssid2str;
+	dladm_wlan_secmode2str;
+	dladm_wlan_strength2str;
+	dladm_wlan_mode2str;
+	dladm_wlan_speed2str;
+	dladm_wlan_auth2str;
+	dladm_wlan_bsstype2str;
+	dladm_wlan_linkstatus2str;
+	dladm_wlan_str2essid;
+	dladm_wlan_str2bssid;
+	dladm_wlan_str2secmode;
+	dladm_wlan_str2strength;
+	dladm_wlan_str2mode;
+	dladm_wlan_str2speed;
+	dladm_wlan_str2auth;
+	dladm_wlan_str2bsstype;
+	dladm_wlan_str2linkstatus;
 
-	dladm_hold_link;
-	dladm_rele_link;
     local:
 	*;
 };
--- a/usr/src/lib/libdladm/common/secobj.c	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/lib/libdladm/common/secobj.c	Wed Mar 21 09:48:58 2007 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -34,6 +34,7 @@
 #include <sys/stat.h>
 #include <sys/dld.h>
 #include <libinetutil.h>
+#include <libdllink.h>
 #include <libdladm_impl.h>
 
 static dladm_status_t	i_dladm_set_secobj_db(const char *,
--- a/usr/src/lib/liblaadm/Makefile	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +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 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-include $(SRC)/lib/Makefile.lib
-
-HDRS =		liblaadm.h
-HDRDIR =	common
-
-SUBDIRS =		$(MACH)
-
-POFILE =	liblaadm.po
-MSGFILES =	common/liblaadm.c
-
-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/liblaadm/Makefile.com	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +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 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-LIBRARY = liblaadm.a
-VERS    = .1
-OBJECTS = liblaadm.o
-
-include ../../Makefile.lib
-
-# install this library in the root filesystem
-include ../../Makefile.rootfs
-
-LIBS =		$(DYNLIB) $(LINTLIB)
-
-LDLIBS +=	-lsocket -lc
-
-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/liblaadm/common/liblaadm.c	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1707 +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 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stropts.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <strings.h>
-#include <libintl.h>
-#include <net/if_types.h>
-#include <net/if_dl.h>
-#include <liblaadm.h>
-
-/*
- * Link Aggregation Administration Library.
- *
- * This library is used by administration tools such as dladm(1M) to
- * configure link aggregations.
- *
- * Link aggregation configuration information is saved in a text
- * file of the following format:
- *
- * <db-file>	::= <groups>*
- * <group>	::= <key> <sep> <policy> <sep> <nports> <sep> <ports> <sep>
- *		      <mac> <sep> <lacp-mode> <sep> <lacp-timer>
- * <sep>	::= ' ' | '\t'
- * <key>	::= <number>
- * <nports>	::= <number>
- * <ports>	::= <port> <m-port>*
- * <m-port>	::= ',' <port>
- * <port>	::= <devname>
- * <devname>	::= <string>
- * <port-num>	::= <number>
- * <policy>	::= <pol-level> <m-pol>*
- * <m-pol>	::= ',' <pol-level>
- * <pol-level>	::= 'L2' | 'L3' | 'L4'
- * <mac>	::= 'auto' | <mac-addr>
- * <mac-addr>	::= <hex> ':' <hex> ':' <hex> ':' <hex> ':' <hex> ':' <hex>
- * <lacp-mode>	::= 'off' | 'active' | 'passive'
- * <lacp-timer>	::= 'short' | 'long'
- */
-
-#define	LAADM_DEV	"/devices/pseudo/aggr@0:" AGGR_DEVNAME_CTL
-#define	LAADM_DB	"/etc/dladm/aggregation.conf"
-#define	LAADM_DB_TMP	"/etc/dladm/aggregation.conf.new"
-#define	LAADM_DB_LOCK	"/tmp/aggregation.conf.lock"
-
-#define	LAADM_DB_PERMS	S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
-#define	LAADM_DB_OWNER	15	/* "dladm" UID */
-#define	LAADM_DB_GROUP	3	/* "sys" GID */
-
-/*
- * The largest configurable aggregation key.  Because by default the key is
- * used as the DLPI device PPA and default VLAN PPA's are calculated as
- * ((1000 * vid) + PPA), the largest key can't be > 999.
- */
-#define	LAADM_MAX_KEY	999
-
-#define	BLANK_LINE(s)	((s[0] == '\0') || (s[0] == '#') || (s[0] == '\n'))
-
-#define	MAXLINELEN	1024
-
-/* Limits on buffer size for LAIOC_INFO request */
-#define	MIN_INFO_SIZE (4*1024)
-#define	MAX_INFO_SIZE (128*1024)
-
-#define	MAXPATHLEN	1024
-
-static uchar_t	zero_mac[] = {0, 0, 0, 0, 0, 0};
-
-/* configuration database entry */
-typedef struct laadm_grp_attr_db {
-	uint32_t	lt_key;
-	uint32_t	lt_policy;
-	uint32_t	lt_nports;
-	laadm_port_attr_db_t *lt_ports;
-	boolean_t	lt_mac_fixed;
-	uchar_t		lt_mac[ETHERADDRL];
-	aggr_lacp_mode_t lt_lacp_mode;
-	aggr_lacp_timer_t lt_lacp_timer;
-} laadm_grp_attr_db_t;
-
-typedef struct laadm_up {
-	uint32_t	lu_key;
-	boolean_t	lu_found;
-	int		lu_fd;
-} laadm_up_t;
-
-typedef struct laadm_down {
-	uint32_t	ld_key;
-	boolean_t	ld_found;
-} laadm_down_t;
-
-typedef struct laadm_modify_attr {
-	uint32_t	ld_policy;
-	boolean_t	ld_mac_fixed;
-	uchar_t		ld_mac[ETHERADDRL];
-	aggr_lacp_mode_t ld_lacp_mode;
-	aggr_lacp_timer_t ld_lacp_timer;
-} laadm_modify_attr_t;
-
-typedef struct policy_s {
-	char		*pol_name;
-	uint32_t	policy;
-} policy_t;
-
-static policy_t policies[] = {
-	{"L2",		AGGR_POLICY_L2},
-	{"L3",		AGGR_POLICY_L3},
-	{"L4",		AGGR_POLICY_L4}};
-
-#define	NPOLICIES	(sizeof (policies) / sizeof (policy_t))
-
-typedef struct laadm_lacp_mode_s {
-	char		*mode_str;
-	aggr_lacp_mode_t mode_id;
-} laadm_lacp_mode_t;
-
-static laadm_lacp_mode_t lacp_modes[] = {
-	{"off", AGGR_LACP_OFF},
-	{"active", AGGR_LACP_ACTIVE},
-	{"passive", AGGR_LACP_PASSIVE}};
-
-#define	NLACP_MODES	(sizeof (lacp_modes) / sizeof (laadm_lacp_mode_t))
-
-typedef struct laadm_lacp_timer_s {
-	char		*lt_str;
-	aggr_lacp_timer_t lt_id;
-} laadm_lacp_timer_t;
-
-static laadm_lacp_timer_t lacp_timers[] = {
-	{"short", AGGR_LACP_TIMER_SHORT},
-	{"long", AGGR_LACP_TIMER_LONG}};
-
-#define	NLACP_TIMERS	(sizeof (lacp_timers) / sizeof (laadm_lacp_timer_t))
-
-typedef struct delete_db_state {
-	uint32_t	ds_key;
-	boolean_t	ds_found;
-} delete_db_state_t;
-
-
-typedef struct modify_db_state {
-	uint32_t	us_key;
-	uint32_t		us_mask;
-	laadm_modify_attr_t *us_attr_new;
-	laadm_modify_attr_t *us_attr_old;
-	boolean_t	us_found;
-} modify_db_state_t;
-
-typedef struct add_db_state {
-	laadm_grp_attr_db_t *as_attr;
-	boolean_t	as_found;
-} add_db_state_t;
-
-static int i_laadm_fput_grp(FILE *, laadm_grp_attr_db_t *);
-
-static int
-i_laadm_strioctl(int fd, int cmd, void *ptr, int ilen)
-{
-	struct strioctl str;
-
-	str.ic_cmd = cmd;
-	str.ic_timout = 0;
-	str.ic_len = ilen;
-	str.ic_dp = ptr;
-
-	return (ioctl(fd, I_STR, &str));
-}
-
-/*
- * Open and lock the aggregation configuration file lock. The lock is
- * acquired as a reader (F_RDLCK) or writer (F_WRLCK).
- */
-static int
-i_laadm_lock_db(short type)
-{
-	int lock_fd;
-	struct flock lock;
-
-	if ((lock_fd = open(LAADM_DB_LOCK, O_RDWR | O_CREAT | O_TRUNC,
-	    LAADM_DB_PERMS)) < 0)
-		return (-1);
-
-	lock.l_type = type;
-	lock.l_whence = SEEK_SET;
-	lock.l_start = 0;
-	lock.l_len = 0;
-
-	if (fcntl(lock_fd, F_SETLKW, &lock) < 0) {
-		(void) close(lock_fd);
-		(void) unlink(LAADM_DB_LOCK);
-		return (-1);
-	}
-	return (lock_fd);
-}
-
-/*
- * Unlock and close the specified file.
- */
-static void
-i_laadm_unlock_db(int fd)
-{
-	struct flock lock;
-
-	if (fd < 0)
-		return;
-
-	lock.l_type = F_UNLCK;
-	lock.l_whence = SEEK_SET;
-	lock.l_start = 0;
-	lock.l_len = 0;
-
-	(void) fcntl(fd, F_SETLKW, &lock);
-	(void) close(fd);
-	(void) unlink(LAADM_DB_LOCK);
-}
-
-/*
- * Walk through the groups defined on the system and for each group <grp>,
- * invoke <fn>(<arg>, <grp>);
- * Terminate the walk if at any time <fn> returns non-NULL value
- */
-int
-laadm_walk_sys(int (*fn)(void *, laadm_grp_attr_sys_t *), void *arg)
-{
-	laioc_info_t *ioc;
-	laioc_info_group_t *grp;
-	laioc_info_port_t *port;
-	laadm_grp_attr_sys_t attr;
-	int rc, i, j, bufsize, fd;
-	char *where;
-
-	if ((fd = open(LAADM_DEV, O_RDWR)) == -1)
-		return (-1);
-
-	bufsize = MIN_INFO_SIZE;
-	ioc = (laioc_info_t *)calloc(1, bufsize);
-	if (ioc == NULL) {
-		(void) close(fd);
-		errno = ENOMEM;
-		return (-1);
-	}
-
-tryagain:
-	rc = i_laadm_strioctl(fd, LAIOC_INFO, ioc, bufsize);
-
-	if (rc != 0) {
-		if (errno == ENOSPC) {
-			/*
-			 * The LAIOC_INFO call failed due to a short
-			 * buffer. Reallocate the buffer and try again.
-			 */
-			bufsize *= 2;
-			if (bufsize <= MAX_INFO_SIZE) {
-				ioc = (laioc_info_t *)realloc(ioc, bufsize);
-				if (ioc != NULL) {
-					bzero(ioc, sizeof (bufsize));
-					goto tryagain;
-				}
-			}
-		}
-		goto bail;
-	}
-
-	/*
-	 * Go through each group returned by the aggregation driver.
-	 */
-	where = (char *)(ioc + 1);
-	for (i = 0; i < ioc->li_ngroups; i++) {
-		/* LINTED E_BAD_PTR_CAST_ALIGN */
-		grp = (laioc_info_group_t *)where;
-
-		attr.lg_key = grp->lg_key;
-		attr.lg_nports = grp->lg_nports;
-		attr.lg_policy = grp->lg_policy;
-		attr.lg_lacp_mode = grp->lg_lacp_mode;
-		attr.lg_lacp_timer = grp->lg_lacp_timer;
-
-		bcopy(grp->lg_mac, attr.lg_mac, ETHERADDRL);
-		attr.lg_mac_fixed = grp->lg_mac_fixed;
-
-		attr.lg_ports = malloc(grp->lg_nports *
-		    sizeof (laadm_port_attr_sys_t));
-		if (attr.lg_ports == NULL) {
-			errno = ENOMEM;
-			goto bail;
-		}
-
-		where = (char *)(grp + 1);
-
-		/*
-		 * Go through each port that is part of the group.
-		 */
-		for (j = 0; j < grp->lg_nports; j++) {
-			/* LINTED E_BAD_PTR_CAST_ALIGN */
-			port = (laioc_info_port_t *)where;
-
-			bcopy(port->lp_devname, attr.lg_ports[j].lp_devname,
-			    MAXNAMELEN + 1);
-			bcopy(port->lp_mac, attr.lg_ports[j].lp_mac,
-			    ETHERADDRL);
-			attr.lg_ports[j].lp_state = port->lp_state;
-			attr.lg_ports[j].lp_lacp_state = port->lp_lacp_state;
-
-			where = (char *)(port + 1);
-		}
-
-		rc = fn(arg, &attr);
-		free(attr.lg_ports);
-		if (rc != 0)
-			goto bail;
-	}
-
-bail:
-	free(ioc);
-	(void) close(fd);
-	return (rc);
-}
-
-/*
- * Parse one line of the link aggregation DB, and return the corresponding
- * group. Memory for the ports associated with the aggregation may be
- * allocated. It is the responsibility of the caller to free the lt_ports
- * aggregation group attribute.
- *
- * Returns -1 on parsing failure, or 0 on success.
- */
-static int
-i_laadm_parse_db(char *line, laadm_grp_attr_db_t *attr)
-{
-	char	*token;
-	int	i;
-	int	value;
-	char	*endp = NULL;
-	char	*lasts = NULL;
-
-	bzero(attr, sizeof (*attr));
-
-	/* key */
-	if ((token = strtok_r(line, " \t", &lasts)) == NULL)
-		goto failed;
-
-	errno = 0;
-	value = (int)strtol(token, &endp, 10);
-	if (errno != 0 || *endp != '\0')
-		goto failed;
-
-	attr->lt_key = value;
-
-	/* policy */
-	if ((token = strtok_r(NULL, " \t", &lasts)) == NULL ||
-	    !laadm_str_to_policy(token, &attr->lt_policy))
-		goto failed;
-
-	/* number of ports */
-	if ((token = strtok_r(NULL, " \t", &lasts)) == NULL)
-		return (-1);
-
-	errno = 0;
-	value = (int)strtol(token, &endp, 10);
-	if (errno != 0 || *endp != '\0')
-		goto failed;
-
-	attr->lt_nports = value;
-
-	/* ports */
-	if ((attr->lt_ports = malloc(attr->lt_nports *
-	    sizeof (laadm_port_attr_db_t))) == NULL)
-		goto failed;
-
-	for (i = 0; i < attr->lt_nports; i++) {
-		char *where, *devname;
-
-		/* port */
-		if ((token = strtok_r(NULL, ", \t\n", &lasts)) == NULL)
-			goto failed;
-
-		/*
-		 * device name: In a previous version of this file, a port
-		 * number could be specified using <devname>/<portnum>.
-		 * This syntax is unecessary and obsolete.
-		 */
-		if ((devname = strtok_r(token, "/", &where)) == NULL)
-			goto failed;
-		if (strlcpy(attr->lt_ports[i].lp_devname, devname,
-		    MAXNAMELEN) >= MAXNAMELEN)
-			goto failed;
-	}
-
-	/* unicast MAC address */
-	if ((token = strtok_r(NULL, " \t\n", &lasts)) == NULL ||
-	    !laadm_str_to_mac_addr(token, &attr->lt_mac_fixed,
-	    attr->lt_mac))
-		goto failed;
-
-	/* LACP mode */
-	if ((token = strtok_r(NULL, " \t\n", &lasts)) == NULL ||
-	    !laadm_str_to_lacp_mode(token, &attr->lt_lacp_mode))
-		attr->lt_lacp_mode = AGGR_LACP_OFF;
-
-	/* LACP timer */
-	if ((token = strtok_r(NULL, " \t\n", &lasts)) == NULL ||
-	    !laadm_str_to_lacp_timer(token, &attr->lt_lacp_timer))
-		attr->lt_lacp_timer = AGGR_LACP_TIMER_SHORT;
-
-	return (0);
-
-failed:
-	free(attr->lt_ports);
-	attr->lt_ports = NULL;
-	return (-1);
-}
-
-/*
- * Walk through the groups defined in the DB and for each group <grp>,
- * invoke <fn>(<arg>, <grp>);
- */
-static int
-i_laadm_walk_db(int (*fn)(void *, laadm_grp_attr_db_t *, laadm_diag_t *),
-    void *arg, const char *root, laadm_diag_t *diag)
-{
-	FILE *fp;
-	char line[MAXLINELEN];
-	laadm_grp_attr_db_t attr;
-	char *db_file;
-	char db_file_buf[MAXPATHLEN];
-	int lock_fd, retval = -1;
-
-	if (root == NULL) {
-		db_file = LAADM_DB;
-	} else {
-		(void) snprintf(db_file_buf, MAXPATHLEN, "%s%s", root,
-		    LAADM_DB);
-		db_file = db_file_buf;
-	}
-
-	lock_fd = i_laadm_lock_db(F_RDLCK);
-
-	if ((fp = fopen(db_file, "r")) == NULL) {
-		i_laadm_unlock_db(lock_fd);
-		*diag = LAADM_DIAG_REPOSITORY_OPENFAIL;
-		return (-1);
-	}
-
-	bzero(&attr, sizeof (attr));
-
-	while (fgets(line, MAXLINELEN, fp) != NULL) {
-		/* skip comments */
-		if (BLANK_LINE(line))
-			continue;
-
-		if (i_laadm_parse_db(line, &attr) != 0) {
-			errno = EFAULT;
-			*diag = LAADM_DIAG_REPOSITORY_PARSEFAIL;
-			goto failed;
-		}
-
-		if (fn(arg, &attr, diag) != 0)
-			goto failed;
-
-		free(attr.lt_ports);
-		attr.lt_ports = NULL;
-	}
-	retval = 0;
-
-failed:
-	free(attr.lt_ports);
-	(void) fclose(fp);
-	i_laadm_unlock_db(lock_fd);
-	return (retval);
-}
-
-/*
- * Send an add or remove command to the link aggregation driver.
- */
-static int
-i_laadm_add_rem_sys(laadm_grp_attr_db_t *attr, int cmd, laadm_diag_t *diag)
-{
-	int i, rc, fd, len;
-	laioc_add_rem_t *iocp;
-	laioc_port_t *ports;
-
-	len = sizeof (*iocp) + attr->lt_nports * sizeof (laioc_port_t);
-	iocp = malloc(len);
-	if (iocp == NULL)
-		goto failed;
-
-	iocp->la_key = attr->lt_key;
-	iocp->la_nports = attr->lt_nports;
-	ports = (laioc_port_t *)(iocp + 1);
-
-	for (i = 0; i < attr->lt_nports; i++) {
-		if (strlcpy(ports[i].lp_devname,
-		    attr->lt_ports[i].lp_devname,
-		    MAXNAMELEN) >= MAXNAMELEN)
-			goto failed;
-	}
-
-	if ((fd = open(LAADM_DEV, O_RDWR)) < 0) {
-		*diag = LAADM_DIAG_REPOSITORY_OPENFAIL;
-		goto failed;
-	}
-
-	rc = i_laadm_strioctl(fd, cmd, iocp, len);
-	if ((rc < 0) && (errno == EINVAL))
-		*diag = LAADM_DIAG_INVALID_INTFNAME;
-
-	(void) close(fd);
-
-	free(iocp);
-	return (rc);
-
-failed:
-	free(iocp);
-	return (-1);
-}
-
-/*
- * Send a modify command to the link aggregation driver.
- */
-static int
-i_laadm_modify_sys(uint32_t key, uint32_t mask, laadm_modify_attr_t *attr,
-    laadm_diag_t *diag)
-{
-	int rc, fd;
-	laioc_modify_t ioc;
-
-	ioc.lu_key = key;
-
-	ioc.lu_modify_mask = 0;
-	if (mask & LAADM_MODIFY_POLICY)
-		ioc.lu_modify_mask |= LAIOC_MODIFY_POLICY;
-	if (mask & LAADM_MODIFY_MAC)
-		ioc.lu_modify_mask |= LAIOC_MODIFY_MAC;
-	if (mask & LAADM_MODIFY_LACP_MODE)
-		ioc.lu_modify_mask |= LAIOC_MODIFY_LACP_MODE;
-	if (mask & LAADM_MODIFY_LACP_TIMER)
-		ioc.lu_modify_mask |= LAIOC_MODIFY_LACP_TIMER;
-
-	ioc.lu_policy = attr->ld_policy;
-	ioc.lu_mac_fixed = attr->ld_mac_fixed;
-	bcopy(attr->ld_mac, ioc.lu_mac, ETHERADDRL);
-	ioc.lu_lacp_mode = attr->ld_lacp_mode;
-	ioc.lu_lacp_timer = attr->ld_lacp_timer;
-
-	if ((fd = open(LAADM_DEV, O_RDWR)) < 0) {
-		*diag = LAADM_DIAG_REPOSITORY_OPENFAIL;
-		return (-1);
-	}
-
-	rc = i_laadm_strioctl(fd, LAIOC_MODIFY, &ioc, sizeof (ioc));
-	if ((rc < 0) && (errno == EINVAL))
-		*diag = LAADM_DIAG_INVALID_MACADDR;
-
-	(void) close(fd);
-
-	return (rc);
-}
-
-/*
- * Send a create command to the link aggregation driver.
- */
-static int
-i_laadm_create_sys(int fd, laadm_grp_attr_db_t *attr, laadm_diag_t *diag)
-{
-	int i, rc, len;
-	laioc_create_t *iocp;
-	laioc_port_t *ports;
-
-	len = sizeof (*iocp) + attr->lt_nports * sizeof (laioc_port_t);
-	iocp = malloc(len);
-	if (iocp == NULL)
-		return (-1);
-
-	iocp->lc_key = attr->lt_key;
-	iocp->lc_nports = attr->lt_nports;
-	iocp->lc_policy = attr->lt_policy;
-	iocp->lc_lacp_mode = attr->lt_lacp_mode;
-	iocp->lc_lacp_timer = attr->lt_lacp_timer;
-
-	ports = (laioc_port_t *)(iocp + 1);
-
-	for (i = 0; i < attr->lt_nports; i++) {
-		if (strlcpy(ports[i].lp_devname,
-		    attr->lt_ports[i].lp_devname,
-		    MAXNAMELEN) >= MAXNAMELEN) {
-			errno = EINVAL;
-			free(iocp);
-			return (-1);
-		}
-	}
-
-	if (attr->lt_mac_fixed &&
-	    ((bcmp(zero_mac, attr->lt_mac, ETHERADDRL) == 0) ||
-	    (attr->lt_mac[0] & 0x01))) {
-		errno = EINVAL;
-		*diag = LAADM_DIAG_INVALID_MACADDR;
-		free(iocp);
-		return (-1);
-	}
-
-	bcopy(attr->lt_mac, iocp->lc_mac, ETHERADDRL);
-	iocp->lc_mac_fixed = attr->lt_mac_fixed;
-
-	rc = i_laadm_strioctl(fd, LAIOC_CREATE, iocp, len);
-	if (rc < 0)
-		*diag = LAADM_DIAG_INVALID_INTFNAME;
-
-	free(iocp);
-	return (rc);
-}
-
-/*
- * Invoked to bring up a link aggregation group.
- */
-static int
-i_laadm_up(void *arg, laadm_grp_attr_db_t *attr, laadm_diag_t *diag)
-{
-	laadm_up_t *up = (laadm_up_t *)arg;
-
-	if (up->lu_key != 0 && up->lu_key != attr->lt_key)
-		return (0);
-
-	up->lu_found = B_TRUE;
-
-	if (i_laadm_create_sys(up->lu_fd, attr, diag) < 0 &&
-	    up->lu_key != 0) {
-		return (-1);
-	}
-
-	return (0);
-}
-
-/*
- * Bring up a link aggregation group or all of them if the key is zero.
- * If key is 0, walk may terminate early if any of the links fail
- */
-int
-laadm_up(uint32_t key, const char *root, laadm_diag_t *diag)
-{
-	laadm_up_t up;
-
-	if ((up.lu_fd = open(LAADM_DEV, O_RDWR)) < 0)
-		return (-1);
-
-	up.lu_key = key;
-	up.lu_found = B_FALSE;
-
-	if (i_laadm_walk_db(i_laadm_up, &up, root, diag) < 0) {
-		(void) close(up.lu_fd);
-		return (-1);
-	}
-	(void) close(up.lu_fd);
-
-	/*
-	 * only return error if user specified key and key was
-	 * not found
-	 */
-	if (!up.lu_found && key != 0) {
-		errno = ENOENT;
-		return (-1);
-	}
-
-	return (0);
-}
-/*
- * Send a delete command to the link aggregation driver.
- */
-static int
-i_laadm_delete_sys(int fd, laadm_grp_attr_sys_t *attr)
-{
-	laioc_delete_t ioc;
-
-	ioc.ld_key = attr->lg_key;
-
-	return (i_laadm_strioctl(fd, LAIOC_DELETE, &ioc, sizeof (ioc)));
-}
-
-/*
- * Invoked to bring down a link aggregation group.
- */
-static int
-i_laadm_down(void *arg, laadm_grp_attr_sys_t *attr)
-{
-	laadm_down_t *down = (laadm_down_t *)arg;
-	int fd;
-
-	if (down->ld_key != 0 && down->ld_key != attr->lg_key)
-		return (0);
-
-	down->ld_found = B_TRUE;
-
-	if ((fd = open(LAADM_DEV, O_RDWR)) < 0)
-		return (-1);
-
-	if (i_laadm_delete_sys(fd, attr) < 0 && down->ld_key != 0) {
-		(void) close(fd);
-		return (-1);
-	}
-
-	(void) close(fd);
-	return (0);
-}
-
-/*
- * Bring down a link aggregation group or all of them if the key is zero.
- * If key is 0, walk may terminate early if any of the links fail
- */
-int
-laadm_down(uint32_t key)
-{
-	laadm_down_t down;
-
-	down.ld_key = key;
-	down.ld_found = B_FALSE;
-
-	if (laadm_walk_sys(i_laadm_down, &down) < 0)
-		return (-1);
-
-	/*
-	 * only return error if user specified key and key was
-	 * not found
-	 */
-	if (!down.ld_found && key != 0) {
-		errno = ENOENT;
-		return (-1);
-	}
-
-	return (0);
-}
-
-/*
- * For each group <grp> found in the DB, invokes <fn>(<grp>, <arg>).
- *
- * The following values can be returned by <fn>():
- *
- * -1: an error occured. This will cause the walk to be terminated,
- *     and the original DB file to be preserved.
- *
- *  0: success and write. The walker will write the contents of
- *     the attribute passed as argument to <fn>(), and continue walking
- *     the entries found in the DB.
- *
- *  1: skip. The walker should not write the contents of the current
- *     group attributes to the new DB, but should continue walking
- *     the entries found in the DB.
- */
-static int
-i_laadm_walk_rw_db(int (*fn)(void *, laadm_grp_attr_db_t *),
-    void *arg,
-    const char *root,
-    laadm_diag_t *diag)
-{
-	FILE *fp, *nfp;
-	int nfd, fn_rc, lock_fd;
-	char line[MAXLINELEN];
-	laadm_grp_attr_db_t attr;
-	char *db_file, *tmp_db_file;
-	char db_file_buf[MAXPATHLEN];
-	char tmp_db_file_buf[MAXPATHLEN];
-
-	if (root == NULL) {
-		db_file = LAADM_DB;
-		tmp_db_file = LAADM_DB_TMP;
-	} else {
-		(void) snprintf(db_file_buf, MAXPATHLEN, "%s%s", root,
-		    LAADM_DB);
-		(void) snprintf(tmp_db_file_buf, MAXPATHLEN, "%s%s", root,
-		    LAADM_DB_TMP);
-		db_file = db_file_buf;
-		tmp_db_file = tmp_db_file_buf;
-	}
-
-	if ((lock_fd = i_laadm_lock_db(F_WRLCK)) < 0)
-		return (-1);
-
-	if ((fp = fopen(db_file, "r")) == NULL) {
-		i_laadm_unlock_db(lock_fd);
-		*diag = LAADM_DIAG_REPOSITORY_OPENFAIL;
-		return (-1);
-	}
-
-	if ((nfd = open(tmp_db_file, O_WRONLY|O_CREAT|O_TRUNC,
-	    LAADM_DB_PERMS)) == -1) {
-		(void) fclose(fp);
-		i_laadm_unlock_db(lock_fd);
-		return (-1);
-	}
-
-	if ((nfp = fdopen(nfd, "w")) == NULL) {
-		(void) close(nfd);
-		(void) fclose(fp);
-		(void) unlink(tmp_db_file);
-		i_laadm_unlock_db(lock_fd);
-		*diag = LAADM_DIAG_REPOSITORY_OPENFAIL;
-		return (-1);
-	}
-
-	attr.lt_ports = NULL;
-
-	while (fgets(line, MAXLINELEN, fp) != NULL) {
-
-		/* skip comments */
-		if (BLANK_LINE(line)) {
-			if (fputs(line, nfp) == EOF)
-				goto failed;
-			continue;
-		}
-
-		if (i_laadm_parse_db(line, &attr) != 0) {
-			errno = EFAULT;
-			*diag = LAADM_DIAG_REPOSITORY_PARSEFAIL;
-			goto failed;
-		}
-
-		fn_rc = fn(arg, &attr);
-
-		switch (fn_rc) {
-		case -1:
-			/* failure, stop walking */
-			goto failed;
-		case 0:
-			/*
-			 * Success, write group attributes, which could
-			 * have been modified by fn().
-			 */
-			if (i_laadm_fput_grp(nfp, &attr) != 0)
-				goto failed;
-			break;
-		case 1:
-			/* skip current group */
-			break;
-		}
-
-		free(attr.lt_ports);
-		attr.lt_ports = NULL;
-	}
-
-	if (getuid() == 0 || geteuid() == 0) {
-		if (fchmod(nfd, LAADM_DB_PERMS) == -1)
-			goto failed;
-
-		if (fchown(nfd, LAADM_DB_OWNER, LAADM_DB_GROUP) == -1)
-			goto failed;
-	}
-
-	if (fflush(nfp) == EOF)
-		goto failed;
-
-	(void) fclose(fp);
-	(void) fclose(nfp);
-
-	if (rename(tmp_db_file, db_file) == -1) {
-		(void) unlink(tmp_db_file);
-		i_laadm_unlock_db(lock_fd);
-		return (-1);
-	}
-
-	i_laadm_unlock_db(lock_fd);
-	return (0);
-
-failed:
-	free(attr.lt_ports);
-	(void) fclose(fp);
-	(void) fclose(nfp);
-	(void) unlink(tmp_db_file);
-	i_laadm_unlock_db(lock_fd);
-
-	return (-1);
-}
-
-/*
- * Remove an entry from the DB.
- */
-static int
-i_laadm_delete_db_fn(void *arg, laadm_grp_attr_db_t *grp)
-{
-	delete_db_state_t *state = arg;
-
-	if (grp->lt_key != state->ds_key)
-		return (0);
-
-	state->ds_found = B_TRUE;
-
-	/* don't save matching group */
-	return (1);
-}
-
-static int
-i_laadm_delete_db(laadm_grp_attr_db_t *attr, const char *root,
-    laadm_diag_t *diag)
-{
-	delete_db_state_t state;
-
-	state.ds_key = attr->lt_key;
-	state.ds_found = B_FALSE;
-
-	if (i_laadm_walk_rw_db(i_laadm_delete_db_fn, &state, root,
-	    diag) != 0)
-		return (-1);
-
-	if (!state.ds_found) {
-		errno = ENOENT;
-		return (-1);
-	}
-
-	return (0);
-}
-
-/*
- * Modify the properties of an existing group in the DB.
- */
-static int
-i_laadm_modify_db_fn(void *arg, laadm_grp_attr_db_t *grp)
-{
-	modify_db_state_t *state = arg;
-	laadm_modify_attr_t *new_attr = state->us_attr_new;
-	laadm_modify_attr_t *old_attr = state->us_attr_old;
-
-	if (grp->lt_key != state->us_key)
-		return (0);
-
-	state->us_found = B_TRUE;
-
-	if (state->us_mask & LAADM_MODIFY_POLICY) {
-		if (old_attr != NULL)
-			old_attr->ld_policy = grp->lt_policy;
-		grp->lt_policy = new_attr->ld_policy;
-	}
-
-	if (state->us_mask & LAADM_MODIFY_MAC) {
-		if (old_attr != NULL) {
-			old_attr->ld_mac_fixed = grp->lt_mac_fixed;
-			bcopy(grp->lt_mac, old_attr->ld_mac, ETHERADDRL);
-		}
-		grp->lt_mac_fixed = new_attr->ld_mac_fixed;
-		bcopy(new_attr->ld_mac, grp->lt_mac, ETHERADDRL);
-	}
-
-	if (state->us_mask & LAADM_MODIFY_LACP_MODE) {
-		if (old_attr != NULL)
-			old_attr->ld_lacp_mode = grp->lt_lacp_mode;
-		grp->lt_lacp_mode = new_attr->ld_lacp_mode;
-	}
-
-	if (state->us_mask & LAADM_MODIFY_LACP_TIMER) {
-		if (old_attr != NULL)
-			old_attr->ld_lacp_timer = grp->lt_lacp_timer;
-		grp->lt_lacp_timer = new_attr->ld_lacp_timer;
-	}
-
-	/* save modified group */
-	return (0);
-}
-
-static int
-i_laadm_modify_db(uint32_t key, uint32_t mask, laadm_modify_attr_t *new,
-    laadm_modify_attr_t *old, const char *root, laadm_diag_t *diag)
-{
-	modify_db_state_t state;
-
-	state.us_key = key;
-	state.us_mask = mask;
-	state.us_attr_new = new;
-	state.us_attr_old = old;
-	state.us_found = B_FALSE;
-
-	if (i_laadm_walk_rw_db(i_laadm_modify_db_fn, &state, root,
-	    diag) != 0)
-		return (-1);
-
-	if (!state.us_found) {
-		errno = ENOENT;
-		return (-1);
-	}
-
-	return (0);
-}
-
-/*
- * Add ports to an existing group in the DB.
- */
-static int
-i_laadm_add_db_fn(void *arg, laadm_grp_attr_db_t *grp)
-{
-	add_db_state_t *state = arg;
-	laadm_grp_attr_db_t *attr = state->as_attr;
-	void *ports;
-	int i, j;
-
-	if (grp->lt_key != attr->lt_key)
-		return (0);
-
-	state->as_found = B_TRUE;
-
-	/* are any of the ports to be added already members of the group? */
-	for (i = 0; i < grp->lt_nports; i++) {
-		for (j = 0; j < attr->lt_nports; j++) {
-			if (strcmp(grp->lt_ports[i].lp_devname,
-			    attr->lt_ports[j].lp_devname) == 0) {
-				errno = EEXIST;
-				return (-1);
-			}
-		}
-	}
-
-	/* add groups specified by attr to grp */
-	ports = realloc(grp->lt_ports, (grp->lt_nports +
-	    attr->lt_nports) * sizeof (laadm_port_attr_db_t));
-	if (ports == NULL)
-		return (-1);
-	grp->lt_ports = ports;
-
-	for (i = 0; i < attr->lt_nports; i++) {
-		if (strlcpy(grp->lt_ports[grp->lt_nports + i].lp_devname,
-		    attr->lt_ports[i].lp_devname, MAXNAMELEN + 1) >=
-		    MAXNAMELEN + 1)
-			return (-1);
-	}
-
-	grp->lt_nports += attr->lt_nports;
-
-	/* save modified group */
-	return (0);
-}
-
-static int
-i_laadm_add_db(laadm_grp_attr_db_t *attr, const char *root,
-    laadm_diag_t *diag)
-{
-	add_db_state_t state;
-
-	state.as_attr = attr;
-	state.as_found = B_FALSE;
-
-	if (i_laadm_walk_rw_db(i_laadm_add_db_fn, &state, root,
-	    diag) != 0)
-		return (-1);
-
-	if (!state.as_found) {
-		errno = ENOENT;
-		return (-1);
-	}
-
-	return (0);
-}
-
-/*
- * Remove ports from an existing group in the DB.
- */
-
-typedef struct remove_db_state {
-	laadm_grp_attr_db_t *rs_attr;
-	boolean_t	rs_found;
-} remove_db_state_t;
-
-static int
-i_laadm_remove_db_fn(void *arg, laadm_grp_attr_db_t *grp)
-{
-	remove_db_state_t *state = (remove_db_state_t *)arg;
-	laadm_grp_attr_db_t *attr = state->rs_attr;
-	int i, j, k, nremoved;
-	boolean_t match;
-
-	if (grp->lt_key != attr->lt_key)
-		return (0);
-
-	state->rs_found = B_TRUE;
-
-	/* remove the ports specified by attr from the group */
-	nremoved = 0;
-	k = 0;
-	for (i = 0; i < grp->lt_nports; i++) {
-		match = B_FALSE;
-		for (j = 0; j < attr->lt_nports && !match; j++) {
-			match = (strcmp(grp->lt_ports[i].lp_devname,
-			    attr->lt_ports[j].lp_devname) == 0);
-		}
-		if (match)
-			nremoved++;
-		else
-			grp->lt_ports[k++] = grp->lt_ports[i];
-	}
-
-	if (nremoved != attr->lt_nports) {
-		errno = ENOENT;
-		return (-1);
-	}
-
-	grp->lt_nports -= nremoved;
-
-	/* save modified group */
-	return (0);
-}
-
-static int
-i_laadm_remove_db(laadm_grp_attr_db_t *attr, const char *root,
-    laadm_diag_t *diag)
-{
-	remove_db_state_t state;
-
-	state.rs_attr = attr;
-	state.rs_found = B_FALSE;
-
-	if (i_laadm_walk_rw_db(i_laadm_remove_db_fn, &state, root,
-	    diag) != 0)
-		return (-1);
-
-	if (!state.rs_found) {
-		errno = ENOENT;
-		return (-1);
-	}
-
-	return (0);
-}
-
-/*
- * Given a policy string, return a policy mask. Returns B_TRUE on
- * success, or B_FALSE if an error occured during parsing.
- */
-boolean_t
-laadm_str_to_policy(const char *str, uint32_t *policy)
-{
-	int i;
-	policy_t *pol;
-	char *token = NULL;
-	char *lasts;
-
-	*policy = 0;
-
-	while ((token = strtok_r((token == NULL) ? (char *)str : NULL, ",",
-	    &lasts)) != NULL) {
-		for (i = 0; i < NPOLICIES; i++) {
-			pol = &policies[i];
-			if (strcasecmp(token, pol->pol_name) == 0) {
-				*policy |= pol->policy;
-				break;
-			}
-		}
-		if (i == NPOLICIES)
-			return (B_FALSE);
-	}
-
-	return (B_TRUE);
-}
-
-/*
- * Given a policy mask, returns a printable string, or NULL if the
- * policy mask is invalid. It is the responsibility of the caller to
- * free the returned string after use.
- */
-char *
-laadm_policy_to_str(uint32_t policy, char *str)
-{
-	int i, npolicies = 0;
-	policy_t *pol;
-
-	str[0] = '\0';
-
-	for (i = 0; i < NPOLICIES; i++) {
-		pol = &policies[i];
-		if ((policy & pol->policy) != 0) {
-			npolicies++;
-			if (npolicies > 1)
-				(void) strcat(str, ",");
-			(void) strcat(str, pol->pol_name);
-		}
-	}
-
-	return (str);
-}
-
-/*
- * Given a MAC address string, return the MAC address in the mac_addr
- * array. If the MAC address was not explicitly specified, i.e. is
- * equal to 'auto', zero out mac-addr and set mac_fixed to B_TRUE.
- * Return B_FALSE if a syntax error was encountered, B_FALSE otherwise.
- */
-boolean_t
-laadm_str_to_mac_addr(const char *str, boolean_t *mac_fixed, uchar_t *mac_addr)
-{
-	uchar_t *conv_str;
-	int mac_len;
-
-	*mac_fixed = (strcmp(str, "auto") != 0);
-	if (!*mac_fixed) {
-		bzero(mac_addr, ETHERADDRL);
-		return (B_TRUE);
-	}
-
-	conv_str = _link_aton(str, &mac_len);
-	if (conv_str == NULL)
-		return (B_FALSE);
-
-	if (mac_len != ETHERADDRL) {
-		free(conv_str);
-		return (B_FALSE);
-	}
-
-	if ((bcmp(zero_mac, conv_str, ETHERADDRL) == 0) ||
-	    (conv_str[0] & 0x01)) {
-		free(conv_str);
-		return (B_FALSE);
-	}
-
-	bcopy(conv_str, mac_addr, ETHERADDRL);
-	free(conv_str);
-
-	return (B_TRUE);
-}
-
-/*
- * Returns a string containing a printable representation of a MAC address.
- */
-const char *
-laadm_mac_addr_to_str(unsigned char *mac, char *buf)
-{
-	static char unknown_mac[] = {0, 0, 0, 0, 0, 0};
-
-	if (buf == NULL)
-		return (NULL);
-
-	if (bcmp(unknown_mac, mac, ETHERADDRL) == 0)
-		return (gettext("<unknown>"));
-	else
-		return (_link_ntoa(mac, buf, ETHERADDRL, IFT_OTHER));
-}
-
-/*
- * Given a LACP mode string, find the corresponding LACP mode number. Returns
- * B_TRUE if a match was found, B_FALSE otherwise.
- */
-boolean_t
-laadm_str_to_lacp_mode(const char *str, aggr_lacp_mode_t *lacp_mode)
-{
-	int i;
-	laadm_lacp_mode_t *mode;
-
-	for (i = 0; i < NLACP_MODES; i++) {
-		mode = &lacp_modes[i];
-		if (strncasecmp(str, mode->mode_str,
-		    strlen(mode->mode_str)) == 0) {
-			*lacp_mode = mode->mode_id;
-			return (B_TRUE);
-		}
-	}
-
-	return (B_FALSE);
-}
-
-/*
- * Given a LACP mode number, returns a printable string, or NULL if the
- * LACP mode number is invalid.
- */
-const char *
-laadm_lacp_mode_to_str(aggr_lacp_mode_t mode_id)
-{
-	int i;
-	laadm_lacp_mode_t *mode;
-
-	for (i = 0; i < NLACP_MODES; i++) {
-		mode = &lacp_modes[i];
-		if (mode->mode_id == mode_id)
-			return (mode->mode_str);
-	}
-
-	return (NULL);
-}
-
-/*
- * Given a LACP timer string, find the corresponding LACP timer number. Returns
- * B_TRUE if a match was found, B_FALSE otherwise.
- */
-boolean_t
-laadm_str_to_lacp_timer(const char *str, aggr_lacp_timer_t *lacp_timer)
-{
-	int i;
-	laadm_lacp_timer_t *timer;
-
-	for (i = 0; i < NLACP_TIMERS; i++) {
-		timer = &lacp_timers[i];
-		if (strncasecmp(str, timer->lt_str,
-		    strlen(timer->lt_str)) == 0) {
-			*lacp_timer = timer->lt_id;
-			return (B_TRUE);
-		}
-	}
-
-	return (B_FALSE);
-}
-
-/*
- * Given a LACP timer, returns a printable string, or NULL if the
- * LACP timer number is invalid.
- */
-const char *
-laadm_lacp_timer_to_str(aggr_lacp_timer_t timer_id)
-{
-	int i;
-	laadm_lacp_timer_t *timer;
-
-	for (i = 0; i < NLACP_TIMERS; i++) {
-		timer = &lacp_timers[i];
-		if (timer->lt_id == timer_id)
-			return (timer->lt_str);
-	}
-
-	return (NULL);
-}
-
-#define	FPRINTF_ERR(fcall) if ((fcall) < 0) return (-1);
-
-/*
- * Write the attribute of a group to the specified file. Returns 0 on
- * success, -1 on failure.
- */
-static int
-i_laadm_fput_grp(FILE *fp, laadm_grp_attr_db_t *attr)
-{
-	int i;
-	char addr_str[ETHERADDRL * 3];
-	char policy_str[LAADM_POLICY_STR_LEN];
-
-	/* key, policy */
-	FPRINTF_ERR(fprintf(fp, "%d\t%s\t", attr->lt_key,
-	    laadm_policy_to_str(attr->lt_policy, policy_str)));
-
-	/* number of ports, ports */
-	FPRINTF_ERR(fprintf(fp, "%d\t", attr->lt_nports));
-	for (i = 0; i < attr->lt_nports; i++) {
-		if (i > 0)
-			FPRINTF_ERR(fprintf(fp, ","));
-		FPRINTF_ERR(fprintf(fp, "%s", attr->lt_ports[i].lp_devname));
-	}
-	FPRINTF_ERR(fprintf(fp, "\t"));
-
-	/* MAC address */
-	if (!attr->lt_mac_fixed) {
-		FPRINTF_ERR(fprintf(fp, "auto"));
-	} else {
-		FPRINTF_ERR(fprintf(fp, "%s",
-		    laadm_mac_addr_to_str(attr->lt_mac, addr_str)));
-	}
-	FPRINTF_ERR(fprintf(fp, "\t"));
-
-	FPRINTF_ERR(fprintf(fp, "%s\t",
-	    laadm_lacp_mode_to_str(attr->lt_lacp_mode)));
-
-	FPRINTF_ERR(fprintf(fp, "%s\n",
-	    laadm_lacp_timer_to_str(attr->lt_lacp_timer)));
-
-	return (0);
-}
-
-static int
-i_laadm_create_db(laadm_grp_attr_db_t *attr, const char *root,
-    laadm_diag_t *diag)
-{
-	FILE *fp;
-	char line[MAXLINELEN];
-	uint32_t key;
-	int 		lock_fd, retval = -1;
-	char 		*db_file;
-	char 		db_file_buf[MAXPATHLEN];
-	char 		*endp = NULL;
-
-	if (root == NULL) {
-		db_file = LAADM_DB;
-	} else {
-		(void) snprintf(db_file_buf, MAXPATHLEN, "%s%s", root,
-		    LAADM_DB);
-		db_file = db_file_buf;
-	}
-
-	if ((lock_fd = i_laadm_lock_db(F_WRLCK)) < 0)
-		return (-1);
-
-	if ((fp = fopen(db_file, "r+")) == NULL &&
-	    (fp = fopen(db_file, "w")) == NULL) {
-		i_laadm_unlock_db(lock_fd);
-		*diag = LAADM_DIAG_REPOSITORY_OPENFAIL;
-		return (-1);
-	}
-
-	/* look for existing group with same key */
-	while (fgets(line, MAXLINELEN, fp) != NULL) {
-		char *holder, *lasts;
-
-		/* skip comments */
-		if (BLANK_LINE(line))
-			continue;
-
-		/* ignore corrupted lines */
-		holder = strtok_r(line, " \t", &lasts);
-		if (holder == NULL)
-			continue;
-
-		/* port number */
-		errno = 0;
-		key = (int)strtol(holder, &endp, 10);
-		if (errno != 0 || *endp != '\0') {
-			goto failed;
-		}
-
-		if (key == attr->lt_key) {
-			/* group with key already exists */
-			errno = EEXIST;
-			goto failed;
-		}
-	}
-
-	/*
-	 * If we get here, we've verified that no existing group with
-	 * the same key already exists. It's now time to add the
-	 * new group to the DB.
-	 */
-	if (i_laadm_fput_grp(fp, attr) != 0)
-		goto failed;
-
-	retval = 0;
-
-failed:
-	(void) fclose(fp);
-	i_laadm_unlock_db(lock_fd);
-	return (retval);
-}
-
-/*
- * Create a new link aggregation group. Update the configuration
- * file and bring it up.
- */
-int
-laadm_create(uint32_t key, uint32_t nports, laadm_port_attr_db_t *ports,
-    uint32_t policy, boolean_t mac_addr_fixed, uchar_t *mac_addr,
-    aggr_lacp_mode_t lacp_mode, aggr_lacp_timer_t lacp_timer, boolean_t tempop,
-    const char *root, laadm_diag_t *diag)
-{
-	laadm_grp_attr_db_t attr;
-	int errno_sav;
-
-	if (key == 0 || key > LAADM_MAX_KEY) {
-		errno = EINVAL;
-		*diag = LAADM_DIAG_INVALID_KEY;
-		return (-1);
-	}
-
-	attr.lt_key = key;
-	attr.lt_nports = nports;
-	attr.lt_ports = ports;
-	attr.lt_policy = policy;
-	attr.lt_mac_fixed = mac_addr_fixed;
-	if (attr.lt_mac_fixed)
-		bcopy(mac_addr, attr.lt_mac, ETHERADDRL);
-	else
-		bzero(attr.lt_mac, ETHERADDRL);
-	attr.lt_lacp_mode = lacp_mode;
-	attr.lt_lacp_timer = lacp_timer;
-
-	/* add the link aggregation group to the DB */
-	if (!tempop) {
-		if (i_laadm_create_db(&attr, root, diag) < 0)
-			return (-1);
-	} else {
-		laadm_up_t up;
-		int rc;
-
-		up.lu_key = key;
-		up.lu_found = B_FALSE;
-		up.lu_fd = open(LAADM_DEV, O_RDWR);
-		if (up.lu_fd < 0)
-			return (-1);
-
-		rc = i_laadm_up((void *)&up, &attr, diag);
-		(void) close(up.lu_fd);
-		return (rc);
-	}
-
-	/* bring up the link aggregation group */
-	if (laadm_up(key, root, diag) < 0) {
-		if (errno != EEXIST) {
-			errno_sav = errno;
-			if (!tempop) {
-				(void) i_laadm_delete_db(&attr, root,
-				    diag);
-			}
-			errno = errno_sav;
-		}
-		return (-1);
-	}
-
-	return (0);
-}
-
-/*
- * Modify the parameters of an existing link aggregation group. Update
- * the configuration file and pass the changes to the kernel.
- */
-int
-laadm_modify(uint32_t key, uint32_t modify_mask, uint32_t policy,
-    boolean_t mac_fixed, uchar_t *mac_addr, aggr_lacp_mode_t lacp_mode,
-    aggr_lacp_timer_t lacp_timer, boolean_t tempop, const char *root,
-    laadm_diag_t *diag)
-{
-	laadm_modify_attr_t new_attr, old_attr;
-	int errno_save;
-
-	if (key == 0) {
-		errno = EINVAL;
-		*diag = LAADM_DIAG_INVALID_KEY;
-		return (-1);
-	}
-
-	if (modify_mask & LAADM_MODIFY_POLICY)
-		new_attr.ld_policy = policy;
-
-	if (modify_mask & LAADM_MODIFY_MAC) {
-		new_attr.ld_mac_fixed = mac_fixed;
-		bcopy(mac_addr, new_attr.ld_mac, ETHERADDRL);
-	}
-
-	if (modify_mask & LAADM_MODIFY_LACP_MODE)
-		new_attr.ld_lacp_mode = lacp_mode;
-
-	if (modify_mask & LAADM_MODIFY_LACP_TIMER)
-		new_attr.ld_lacp_timer = lacp_timer;
-
-	/* update the DB */
-	if (!tempop) {
-		if (i_laadm_modify_db(key, modify_mask, &new_attr,
-		    &old_attr, root, diag) < 0)
-			return (-1);
-	}
-
-	if (i_laadm_modify_sys(key, modify_mask, &new_attr,
-	    diag) < 0) {
-		if (!tempop) {
-			errno_save = errno;
-			(void) i_laadm_modify_db(key, modify_mask,
-			    &old_attr, NULL, root, diag);
-			errno = errno_save;
-		}
-		return (-1);
-	}
-
-	return (0);
-}
-
-/*
- * Delete a previously created link aggregation group.
- */
-int
-laadm_delete(uint32_t key, boolean_t tempop, const char *root,
-    laadm_diag_t *diag)
-{
-	laadm_grp_attr_db_t db_attr;
-
-	if (key == 0) {
-		errno = EINVAL;
-		*diag = LAADM_DIAG_INVALID_KEY;
-		return (-1);
-	}
-
-	if (tempop) {
-		laadm_down_t down;
-		laadm_grp_attr_sys_t sys_attr;
-
-		down.ld_key = key;
-		down.ld_found = B_FALSE;
-		sys_attr.lg_key = key;
-		return (i_laadm_down((void *)&down, &sys_attr));
-	} else if ((laadm_down(key) < 0) && errno == EBUSY) {
-		return (-1);
-	}
-
-	db_attr.lt_key = key;
-
-	if (tempop)
-		return (0);
-
-	return (i_laadm_delete_db(&db_attr, root, diag));
-}
-
-/*
- * Add one or more ports to an existing link aggregation.
- */
-int
-laadm_add(uint32_t key, uint32_t nports, laadm_port_attr_db_t *ports,
-    boolean_t tempop, const char *root, laadm_diag_t *diag)
-{
-	laadm_grp_attr_db_t attr;
-	int errno_save;
-
-	if (key == 0) {
-		errno = EINVAL;
-		*diag = LAADM_DIAG_INVALID_KEY;
-		return (-1);
-	}
-
-	bzero(&attr, sizeof (attr));
-	attr.lt_key = key;
-	attr.lt_nports = nports;
-	attr.lt_ports = ports;
-
-	if (!tempop) {
-		if (i_laadm_add_db(&attr, root, diag) < 0)
-			return (-1);
-	}
-
-	if (i_laadm_add_rem_sys(&attr, LAIOC_ADD, diag) < 0) {
-		if (!tempop) {
-			errno_save = errno;
-			(void) i_laadm_remove_db(&attr, root, diag);
-			errno = errno_save;
-		}
-		return (-1);
-	}
-
-	return (0);
-}
-
-/*
- * Remove one or more ports from an existing link aggregation.
- */
-int
-laadm_remove(uint32_t key, uint32_t nports, laadm_port_attr_db_t *ports,
-    boolean_t tempop, const char *root, laadm_diag_t *diag)
-{
-	laadm_grp_attr_db_t attr;
-	int errno_save;
-
-	if (key == 0) {
-		errno = EINVAL;
-		*diag = LAADM_DIAG_INVALID_KEY;
-		return (-1);
-	}
-
-	bzero(&attr, sizeof (attr));
-	attr.lt_key = key;
-	attr.lt_nports = nports;
-	attr.lt_ports = ports;
-
-	if (!tempop) {
-		if (i_laadm_remove_db(&attr, root, diag) < 0)
-			return (-1);
-	}
-
-	if (i_laadm_add_rem_sys(&attr, LAIOC_REMOVE, diag) < 0) {
-		if (!tempop) {
-			errno_save = errno;
-			(void) i_laadm_add_db(&attr, root, diag);
-			errno = errno_save;
-		}
-		return (-1);
-	}
-
-	return (0);
-}
-
-const char *
-laadm_diag(laadm_diag_t diag) {
-	switch (diag) {
-	case LAADM_DIAG_REPOSITORY_OPENFAIL:
-		return (gettext("configuration repository open failed"));
-	case LAADM_DIAG_REPOSITORY_PARSEFAIL:
-		return (gettext("parsing of configuration repository failed"));
-	case LAADM_DIAG_REPOSITORY_CLOSEFAIL:
-		return (gettext("configuration repository close failed"));
-	case LAADM_DIAG_INVALID_INTFNAME:
-		return (gettext("invalid interface name"));
-	case LAADM_DIAG_INVALID_MACADDR:
-		return (gettext("invalid MAC address"));
-	case LAADM_DIAG_INVALID_KEY:
-		return (gettext("invalid key"));
-	default:
-		return (gettext("unknown diagnostic"));
-	}
-}
--- a/usr/src/lib/liblaadm/common/liblaadm.h	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +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 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _LIBLAADM_H
-#define	_LIBLAADM_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <sys/types.h>
-#include <sys/aggr.h>
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-/*
- * Modification flags sent with the LAIOC_MODIFY ioctl
- */
-#define	LAADM_MODIFY_POLICY		0x01
-#define	LAADM_MODIFY_MAC		0x02
-#define	LAADM_MODIFY_LACP_MODE		0x04
-#define	LAADM_MODIFY_LACP_TIMER		0x08
-
-#define	LAADM_POLICY_STR_LEN		8
-
-typedef struct laadm_port_attr_db {
-	char		lp_devname[MAXNAMELEN + 1];
-} laadm_port_attr_db_t;
-
-typedef struct laadm_port_attr_sys {
-	char		lp_devname[MAXNAMELEN + 1];
-	uchar_t		lp_mac[ETHERADDRL];
-	aggr_port_state_t lp_state;
-	aggr_lacp_state_t lp_lacp_state;
-} laadm_port_attr_sys_t;
-
-typedef struct laadm_grp_attr_sys {
-	uint32_t	lg_key;
-	uint32_t	lg_nports;
-	laadm_port_attr_sys_t *lg_ports;
-	uint32_t	lg_policy;
-	uchar_t		lg_mac[ETHERADDRL];
-	boolean_t	lg_mac_fixed;
-	aggr_lacp_mode_t lg_lacp_mode;
-	aggr_lacp_timer_t lg_lacp_timer;
-} laadm_grp_attr_sys_t;
-
-/*
- * Diagnostic codes.  These supplement error messages.
- */
-typedef enum {
-	LAADM_DIAG_REPOSITORY_OPENFAIL  = 1,
-	LAADM_DIAG_REPOSITORY_PARSEFAIL	= 2,
-	LAADM_DIAG_REPOSITORY_CLOSEFAIL	= 3,
-	LAADM_DIAG_INVALID_INTFNAME	= 4,
-	LAADM_DIAG_INVALID_MACADDR	= 5,
-	LAADM_DIAG_INVALID_KEY		= 6
-} laadm_diag_t;
-
-extern int laadm_create(uint32_t, uint32_t, laadm_port_attr_db_t *,
-    uint32_t, boolean_t, uchar_t *, aggr_lacp_mode_t, aggr_lacp_timer_t,
-    boolean_t, const char *, laadm_diag_t *);
-extern int laadm_delete(uint32_t, boolean_t, const char *,
-    laadm_diag_t *);
-extern int laadm_add(uint32_t, uint32_t, laadm_port_attr_db_t *,
-    boolean_t, const char *, laadm_diag_t *);
-extern int laadm_remove(uint32_t, uint32_t, laadm_port_attr_db_t *,
-    boolean_t, const char *, laadm_diag_t *);
-extern int laadm_modify(uint32_t, uint32_t, uint32_t, boolean_t,
-    uchar_t *, aggr_lacp_mode_t, aggr_lacp_timer_t, boolean_t, const char *,
-    laadm_diag_t *);
-extern int laadm_up(uint32_t, const char *, laadm_diag_t *);
-extern int laadm_down(uint32_t);
-
-extern boolean_t laadm_str_to_policy(const char *, uint32_t *);
-extern char *laadm_policy_to_str(uint32_t, char *buf);
-extern boolean_t laadm_str_to_mac_addr(const char *, boolean_t *, uchar_t *);
-extern const char *laadm_mac_addr_to_str(unsigned char *, char *);
-
-extern boolean_t laadm_str_to_lacp_mode(const char *, aggr_lacp_mode_t *);
-extern const char *laadm_lacp_mode_to_str(aggr_lacp_mode_t);
-extern boolean_t laadm_str_to_lacp_timer(const char *, aggr_lacp_timer_t *);
-extern const char *laadm_lacp_timer_to_str(aggr_lacp_timer_t);
-
-extern int laadm_walk_sys(int (*)(void *, laadm_grp_attr_sys_t *), void *);
-extern const char *laadm_diag(laadm_diag_t);
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _LIBLAADM_H */
--- a/usr/src/lib/liblaadm/common/llib-llaadm	Wed Mar 21 09:33:24 2007 -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 2005 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*LINTLIBRARY*/
-/*PROTOLIB1*/
-
-#include <liblaadm.h>
--- a/usr/src/lib/liblaadm/common/mapfile-vers	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +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 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-SUNWprivate_1.1 {
-    global:
-	laadm_add;
-	laadm_create;
-	laadm_delete;
-	laadm_diag;
-	laadm_down;
-	laadm_lacp_mode_to_str;
-	laadm_lacp_timer_to_str;
-	laadm_mac_addr_to_str;
-	laadm_modify;
-	laadm_policy_to_str;
-	laadm_remove;
-	laadm_str_to_lacp_mode;
-	laadm_str_to_lacp_timer;
-	laadm_str_to_mac_addr;
-	laadm_str_to_policy;
-	laadm_up;
-	laadm_walk_sys;
-    local:
-	*;
-};
--- a/usr/src/lib/liblaadm/i386/Makefile	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +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 2005 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-include ../Makefile.com
-
-install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- a/usr/src/lib/liblaadm/sparc/Makefile	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +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 2005 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-include ../Makefile.com
-
-install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- a/usr/src/lib/libmacadm/Makefile	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +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 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-include $(SRC)/lib/Makefile.lib
-
-HDRS =		libmacadm.h
-HDRDIR =	common
-
-SUBDIRS =		$(MACH)
-
-POFILE =	libmacadm.po
-MSGFILES =	common/libmacadm.c
-
-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/libmacadm/Makefile.com	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +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 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-LIBRARY = libmacadm.a
-VERS    = .1
-OBJECTS = libmacadm.o
-
-include ../../Makefile.lib
-
-# install this library in the root filesystem
-include ../../Makefile.rootfs
-
-LIBS =		$(DYNLIB) $(LINTLIB)
-
-LDLIBS +=	-ldevinfo -lc
-
-SRCDIR =	../common
-$(LINTLIB) :=	SRCS = $(SRCDIR)/$(LINTSRC)
-
-CFLAGS +=	$(CCVERBOSE)
-CPPFLAGS +=	-I$(SRCDIR) -D_REENTRANT
-
-.KEEP_STATE:
-
-all:		$(LIBS) fnamecheck
-
-lint:		lintcheck
-
-include $(SRC)/lib/Makefile.targ
--- a/usr/src/lib/libmacadm/common/libmacadm.c	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +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 2005 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stropts.h>
-#include <sys/dld.h>
-#include <libdevinfo.h>
-
-#define	_KERNEL
-#include <sys/sysmacros.h>
-#undef	_KERNEL
-
-/*
- * MAC Administration Library.
- *
- * This library is used by administration tools such as dladm(1M) to
- * iterate through the list of MAC interfaces
- *
- */
-
-typedef struct macadm_dev {
-	char			md_name[MAXNAMELEN];
-	struct macadm_dev	*md_next;
-} macadm_dev_t;
-
-typedef struct macadm_walk {
-	macadm_dev_t		*mw_dev_list;
-} macadm_walk_t;
-
-/*
- * Local callback invoked for each DDI_NT_NET node.
- */
-/* ARGSUSED */
-static int
-i_macadm_apply(di_node_t node, di_minor_t minor, void *arg)
-{
-	macadm_walk_t	*mwp = arg;
-	macadm_dev_t	*mdp = mwp->mw_dev_list;
-	macadm_dev_t	**lastp = &mwp->mw_dev_list;
-	char		dev[MAXNAMELEN];
-
-	(void) snprintf(dev, MAXNAMELEN, "%s%d",
-	    di_driver_name(node), di_instance(node));
-
-	/*
-	 * Skip aggregations.
-	 */
-	if (strcmp("aggr", di_driver_name(node)) == 0)
-		return (DI_WALK_CONTINUE);
-
-	while (mdp) {
-		/*
-		 * Skip duplicates.
-		 */
-		if (strcmp(mdp->md_name, dev) == 0)
-			return (DI_WALK_CONTINUE);
-
-		lastp = &mdp->md_next;
-		mdp = mdp->md_next;
-	}
-
-	if ((mdp = malloc(sizeof (*mdp))) == NULL)
-		return (DI_WALK_CONTINUE);
-
-	(void) strlcpy(mdp->md_name, dev, MAXNAMELEN);
-	mdp->md_next = NULL;
-	*lastp = mdp;
-
-	return (DI_WALK_CONTINUE);
-}
-
-/*
- * Invoke the specified callback for each DDI_NT_MAC node.
- */
-int
-macadm_walk(void (*fn)(void *, const char *), void *arg,
-    boolean_t use_cache)
-{
-	di_node_t	root;
-	macadm_walk_t	mw;
-	macadm_dev_t	*mdp;
-	uint_t		flags;
-
-	if (use_cache) {
-		flags = DINFOCACHE;
-	} else {
-		flags = DINFOSUBTREE | DINFOMINOR | DINFOPROP | DINFOFORCE;
-	}
-
-	if ((root = di_init("/", flags)) == DI_NODE_NIL) {
-		return (-1);
-	}
-	mw.mw_dev_list = NULL;
-
-	(void) di_walk_minor(root, DDI_NT_NET, DI_CHECK_ALIAS, &mw,
-	    i_macadm_apply);
-
-	di_fini(root);
-
-	mdp = mw.mw_dev_list;
-	while (mdp) {
-		(*fn)(arg, mdp->md_name);
-		mdp = mdp->md_next;
-	}
-
-	return (0);
-}
--- a/usr/src/lib/libmacadm/common/libmacadm.h	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +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 2005 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _LIBMACADM_H
-#define	_LIBMACADM_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <sys/types.h>
-#include <sys/mac.h>
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-extern int	macadm_walk(void (*)(void *, const char *),
-    void *, boolean_t);
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _LIBMACADM_H */
--- a/usr/src/lib/libmacadm/common/llib-lmacadm	Wed Mar 21 09:33:24 2007 -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 2005 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*LINTLIBRARY*/
-/*PROTOLIB1*/
-
-#include <libmacadm.h>
--- a/usr/src/lib/libmacadm/common/mapfile-vers	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +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 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-SUNWprivate_1.1 {
-    global:
-	macadm_walk;
-    local:
-	*;
-};
--- a/usr/src/lib/libmacadm/i386/Makefile	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +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 2005 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-include ../Makefile.com
-
-install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- a/usr/src/lib/libmacadm/sparc/Makefile	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +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 2005 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-include ../Makefile.com
-
-install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- a/usr/src/lib/libwladm/Makefile	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +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 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-include $(SRC)/lib/Makefile.lib
-
-HDRS =		libwladm.h libwladm_impl.h
-HDRDIR =	common
-
-SUBDIRS =	$(MACH)
-
-POFILE =	libwladm.po
-MSGFILES =	common/libwladm.c
-XGETFLAGS =	-a -x libwladm.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/libwladm/Makefile.com	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +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 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-LIBRARY = libwladm.a
-VERS    = .1
-OBJECTS = libwladm.o
-
-include ../../Makefile.lib
-# install this library in the root filesystem
-include ../../Makefile.rootfs
-
-LIBS =		$(DYNLIB) $(LINTLIB)
-LDLIBS +=	-ldevinfo -lsocket -lc
-
-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/libwladm/common/libwladm.c	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1962 +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 2007 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <libintl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stropts.h>
-#include <libdevinfo.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <net/if_types.h>
-#include <libwladm.h>
-#include <libwladm_impl.h>
-#include <inet/wifi_ioctl.h>
-
-typedef struct val_desc {
-	char		*vd_name;
-	uint_t		vd_val;
-} val_desc_t;
-
-struct prop_desc;
-
-typedef wladm_status_t pd_getf_t(int, wldp_t *, char **, uint_t *);
-typedef wladm_status_t pd_setf_t(int, wldp_t *, val_desc_t *, uint_t);
-typedef wladm_status_t pd_checkf_t(int, wldp_t *, struct prop_desc *, char **,
-			    uint_t, val_desc_t **);
-typedef struct prop_desc {
-	char		*pd_name;
-	val_desc_t	pd_defval;
-	val_desc_t	*pd_modval;
-	uint_t		pd_nmodval;
-	pd_setf_t	*pd_set;
-	pd_getf_t	*pd_getmod;
-	pd_getf_t	*pd_get;
-	pd_checkf_t	*pd_check;
-} prop_desc_t;
-
-static int 	do_get_bsstype(int, wldp_t *);
-static int 	do_get_essid(int, wldp_t *);
-static int 	do_get_bssid(int, wldp_t *);
-static int 	do_get_signal(int, wldp_t *);
-static int 	do_get_encryption(int, wldp_t *);
-static int 	do_get_authmode(int, wldp_t *);
-static int 	do_get_linkstatus(int, wldp_t *);
-static int	do_get_esslist(int, wldp_t *);
-static int 	do_get_rate(int, wldp_t *);
-static int	do_get_phyconf(int, wldp_t *);
-static int	do_get_powermode(int, wldp_t *);
-static int	do_get_radio(int, wldp_t *);
-static int	do_get_mode(int, wldp_t *);
-
-static int	do_set_bsstype(int, wldp_t *, wladm_bsstype_t *);
-static int	do_set_authmode(int, wldp_t *, wladm_auth_t *);
-static int	do_set_encryption(int, wldp_t *, wladm_secmode_t *);
-static int	do_set_essid(int, wldp_t *, wladm_essid_t *);
-static int	do_set_createibss(int, wldp_t *, boolean_t *);
-static int	do_set_wepkey(int, wldp_t *, wladm_wep_key_t *, uint_t);
-static int	do_set_rate(int, wldp_t *, wladm_rates_t *);
-static int	do_set_powermode(int, wldp_t *, wladm_powermode_t *);
-static int	do_set_radio(int, wldp_t *, wladm_radio_t *);
-static int	do_set_channel(int, wldp_t *, wladm_channel_t *);
-
-static int	open_link(const char *);
-static int	do_scan(int, wldp_t *);
-static int	do_disconnect(int, wldp_t *);
-static boolean_t find_val_by_name(const char *, val_desc_t *, uint_t, uint_t *);
-static boolean_t find_name_by_val(uint_t, val_desc_t *, uint_t, char **);
-static void	generate_essid(wladm_essid_t *);
-
-static wladm_status_t	wladm_wlresult2status(wldp_t *);
-
-static pd_getf_t	do_get_rate_mod, do_get_rate_prop, do_get_channel_prop,
-			do_get_powermode_prop, do_get_radio_prop;
-static pd_setf_t 	do_set_rate_prop, do_set_powermode_prop,
-			do_set_radio_prop;
-static pd_checkf_t	do_check_prop, do_check_rate;
-
-static val_desc_t status_vals[] = {
-	{ "ok",				WLADM_STATUS_OK			},
-	{ "invalid argument",		WLADM_STATUS_BADARG		},
-	{ "operation failed",		WLADM_STATUS_FAILED		},
-	{ "operation not supported", 	WLADM_STATUS_NOTSUP		},
-	{ "already connected",		WLADM_STATUS_ISCONN		},
-	{ "not connected",		WLADM_STATUS_NOTCONN		},
-	{ "not found",			WLADM_STATUS_NOTFOUND		},
-	{ "value not found",		WLADM_STATUS_BADVAL		},
-	{ "invalid link",		WLADM_STATUS_LINKINVAL		},
-	{ "insufficient memory",	WLADM_STATUS_NOMEM		},
-	{ "operation timed out",	WLADM_STATUS_TIMEDOUT		},
-	{ "read-only property",		WLADM_STATUS_PROPRDONLY		},
-	{ "not enough space",		WLADM_STATUS_TOOSMALL		},
-	{ "invalid number of values",	WLADM_STATUS_BADVALCNT 		}
-};
-
-static val_desc_t	linkstatus_vals[] = {
-	{ "disconnected", 		WLADM_LINK_STATUS_DISCONNECTED	},
-	{ "connected",			WLADM_LINK_STATUS_CONNECTED	}
-};
-
-static val_desc_t 	secmode_vals[] = {
-	{ "none",	WLADM_SECMODE_NONE		},
-	{ "wep",	WLADM_SECMODE_WEP		}
-};
-
-static val_desc_t 	strength_vals[] = {
-	{ "very weak",	WLADM_STRENGTH_VERY_WEAK 	},
-	{ "weak",	WLADM_STRENGTH_WEAK		},
-	{ "good", 	WLADM_STRENGTH_GOOD		},
-	{ "very good",	WLADM_STRENGTH_VERY_GOOD	},
-	{ "excellent",	WLADM_STRENGTH_EXCELLENT	}
-};
-
-static val_desc_t	mode_vals[] = {
-	{ "a",		WLADM_MODE_80211A		},
-	{ "b",		WLADM_MODE_80211B		},
-	{ "g",		WLADM_MODE_80211G		},
-};
-
-static val_desc_t	auth_vals[] = {
-	{ "open",	WLADM_AUTH_OPEN			},
-	{ "shared",	WLADM_AUTH_SHARED		}
-};
-
-static val_desc_t	bsstype_vals[] = {
-	{ "bss",	WLADM_BSSTYPE_BSS		},
-	{ "ibss",	WLADM_BSSTYPE_IBSS		},
-	{ "any",	WLADM_BSSTYPE_ANY		}
-};
-
-static val_desc_t	radio_vals[] = {
-	{ "on",		WLADM_RADIO_ON			},
-	{ "off",	WLADM_RADIO_OFF			}
-};
-
-static val_desc_t	powermode_vals[] = {
-	{ "off",	WLADM_PM_OFF			},
-	{ "fast",	WLADM_PM_FAST			},
-	{ "max",	WLADM_PM_MAX			}
-};
-
-#define	VALCNT(vals)	(sizeof ((vals)) / sizeof (val_desc_t))
-static	prop_desc_t	prop_table[] = {
-
-	{ "channel",	{ NULL, 0 }, NULL, 0,
-	    NULL, NULL, do_get_channel_prop, do_check_prop},
-
-	{ "powermode",	{ "off", WLADM_PM_OFF }, powermode_vals,
-	    VALCNT(powermode_vals),
-	    do_set_powermode_prop, NULL,
-	    do_get_powermode_prop, do_check_prop},
-
-	{ "radio", 	{ "on", WLADM_RADIO_ON }, radio_vals,
-	    VALCNT(radio_vals),
-	    do_set_radio_prop, NULL,
-	    do_get_radio_prop, do_check_prop},
-
-	{ "speed",	{ "", 0 }, NULL, 0,
-	    do_set_rate_prop, do_get_rate_mod,
-	    do_get_rate_prop, do_check_rate}
-};
-/*
- * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
- * rates to be retrieved. However, we cannot increase it at this
- * time because it will break binary comatibility with unbundled
- * WiFi drivers and utilities. So for now we define an additional
- * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
- */
-#define	MAX_SUPPORT_RATES	64
-#define	WLADM_MAX_PROPS		(sizeof (prop_table) / sizeof (prop_desc_t))
-#define	IS_CONNECTED(gbuf) \
-	((*(wl_linkstatus_t *)((gbuf)->wldp_buf) == WL_CONNECTED))
-
-static wladm_status_t
-wladm_wlresult2status(wldp_t *gbuf)
-{
-	switch (gbuf->wldp_result) {
-	case WL_SUCCESS:
-		return (WLADM_STATUS_OK);
-
-	case WL_NOTSUPPORTED:
-	case WL_LACK_FEATURE:
-		return (WLADM_STATUS_NOTSUP);
-
-	case WL_READONLY:
-		return (WLADM_STATUS_PROPRDONLY);
-
-	default:
-		break;
-	}
-
-	return (WLADM_STATUS_FAILED);
-}
-
-static int
-open_link(const char *link)
-{
-	char	linkname[MAXPATHLEN];
-	wldp_t	*gbuf;
-	int	fd;
-
-	if (link == NULL)
-		return (-1);
-
-	(void) snprintf(linkname, MAXPATHLEN, "/dev/%s", link);
-	if ((fd = open(linkname, O_RDWR)) < 0)
-		return (-1);
-
-	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
-		(void) close(fd);
-		return (-1);
-	}
-
-	/*
-	 * Check to see if the link is wireless.
-	 */
-	if (do_get_bsstype(fd, gbuf) < 0) {
-		free(gbuf);
-		(void) close(fd);
-		return (-1);
-	}
-
-	free(gbuf);
-	return (fd);
-}
-
-static wladm_mode_t
-do_convert_mode(wl_phy_conf_t *phyp)
-{
-	switch (phyp->wl_phy_fhss_conf.wl_fhss_subtype) {
-	case WL_ERP:
-		return (WLADM_MODE_80211G);
-	case WL_OFDM:
-		return (WLADM_MODE_80211A);
-	case WL_DSSS:
-	case WL_FHSS:
-		return (WLADM_MODE_80211B);
-	default:
-		break;
-	}
-
-	return (WLADM_MODE_NONE);
-}
-
-static boolean_t
-do_convert_chan(wl_phy_conf_t *phyp, uint32_t *channelp)
-{
-	wl_fhss_t *wlfp = &phyp->wl_phy_fhss_conf;
-	wl_ofdm_t *wlop = &phyp->wl_phy_ofdm_conf;
-
-	switch (wlfp->wl_fhss_subtype) {
-	case WL_FHSS:
-	case WL_DSSS:
-	case WL_IRBASE:
-	case WL_HRDS:
-	case WL_ERP:
-		*channelp = wlfp->wl_fhss_channel;
-		break;
-	case WL_OFDM:
-		*channelp = WLADM_OFDM2CHAN(wlop->wl_ofdm_frequency);
-		break;
-	default:
-		return (B_FALSE);
-	}
-	return (B_TRUE);
-}
-
-#define	IEEE80211_RATE	0x7f
-static void
-fill_wlan_attr(wl_ess_conf_t *wlp, wladm_wlan_attr_t *attrp)
-{
-	int		i;
-
-	(void) memset(attrp, 0, sizeof (*attrp));
-
-	(void) snprintf(attrp->wa_essid.we_bytes, WLADM_MAX_ESSID_LEN, "%s",
-	    wlp->wl_ess_conf_essid.wl_essid_essid);
-	attrp->wa_valid |= WLADM_WLAN_ATTR_ESSID;
-
-	(void) memcpy(attrp->wa_bssid.wb_bytes, wlp->wl_ess_conf_bssid,
-	    WLADM_BSSID_LEN);
-	attrp->wa_valid |= WLADM_WLAN_ATTR_BSSID;
-
-	attrp->wa_secmode = (wlp->wl_ess_conf_wepenabled ==
-	    WL_ENC_WEP ? WLADM_SECMODE_WEP : WLADM_SECMODE_NONE);
-	attrp->wa_valid |= WLADM_WLAN_ATTR_SECMODE;
-
-	attrp->wa_bsstype = (wlp->wl_ess_conf_bsstype == WL_BSS_BSS ?
-	    WLADM_BSSTYPE_BSS : WLADM_BSSTYPE_IBSS);
-	attrp->wa_valid |= WLADM_WLAN_ATTR_BSSTYPE;
-
-	attrp->wa_auth = (wlp->wl_ess_conf_authmode == 0 ?
-	    WLADM_AUTH_OPEN : WLADM_AUTH_SHARED);
-	attrp->wa_valid |= WLADM_WLAN_ATTR_AUTH;
-
-	attrp->wa_strength = WLADM_SIGNAL2STRENGTH(wlp->wl_ess_conf_sl);
-	attrp->wa_valid |= WLADM_WLAN_ATTR_STRENGTH;
-
-	attrp->wa_mode = do_convert_mode((wl_phy_conf_t *)&wlp->wl_phy_conf);
-	attrp->wa_valid |= WLADM_WLAN_ATTR_MODE;
-
-	for (i = 0; i < MAX_SCAN_SUPPORT_RATES; i++) {
-		wlp->wl_supported_rates[i] &= IEEE80211_RATE;
-		if (wlp->wl_supported_rates[i] > attrp->wa_speed)
-			attrp->wa_speed = wlp->wl_supported_rates[i];
-	}
-	if (attrp->wa_speed > 0)
-		attrp->wa_valid |= WLADM_WLAN_ATTR_SPEED;
-
-	if (do_convert_chan((wl_phy_conf_t *)&wlp->wl_phy_conf,
-	    &attrp->wa_channel))
-		attrp->wa_valid |= WLADM_WLAN_ATTR_CHANNEL;
-}
-
-wladm_status_t
-wladm_scan(const char *link, void *arg,
-    boolean_t (*func)(void *, wladm_wlan_attr_t *))
-{
-	int			fd, i;
-	uint32_t		count;
-	wl_ess_conf_t		*wlp;
-	wldp_t 			*gbuf;
-	wladm_wlan_attr_t	wlattr;
-	wladm_status_t		status;
-	boolean_t		connected;
-
-	if ((fd = open_link(link)) < 0)
-		return (WLADM_STATUS_LINKINVAL);
-
-	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
-		status = WLADM_STATUS_NOMEM;
-		goto done;
-	}
-
-	if (do_get_linkstatus(fd, gbuf) < 0) {
-		status = WLADM_STATUS_FAILED;
-		goto done;
-	}
-	connected = IS_CONNECTED(gbuf);
-
-	if (do_scan(fd, gbuf) < 0) {
-		status = WLADM_STATUS_FAILED;
-		goto done;
-	}
-
-	if (do_get_esslist(fd, gbuf) < 0) {
-		status = WLADM_STATUS_FAILED;
-		goto done;
-	}
-
-	wlp = ((wl_ess_list_t *)gbuf->wldp_buf)->wl_ess_list_ess;
-	count = ((wl_ess_list_t *)(gbuf->wldp_buf))->wl_ess_list_num;
-
-	for (i = 0; i < count; i++, wlp++) {
-		fill_wlan_attr(wlp, &wlattr);
-		if (!func(arg, &wlattr))
-			break;
-	}
-
-	if (!connected) {
-		if (do_get_linkstatus(fd, gbuf) < 0) {
-			status = WLADM_STATUS_FAILED;
-			goto done;
-		}
-		if (IS_CONNECTED(gbuf))
-			(void) do_disconnect(fd, gbuf);
-	}
-
-	status = WLADM_STATUS_OK;
-done:
-	free(gbuf);
-	(void) close(fd);
-	return (status);
-}
-
-/*
- * Structures used in building the list of eligible WLANs to connect to.
- * Specifically, `connect_state' has the WLAN attributes that must be matched
- * (in `cs_attr') and a growing list of WLANs that matched those attributes
- * chained through `cs_list'.  Each element in the list is of type `attr_node'
- * and has the matching WLAN's attributes and a pointer to the next element.
- * For convenience, `cs_count' tracks the number of elements in the list.
- */
-typedef struct attr_node {
-	wladm_wlan_attr_t	an_attr;
-	struct attr_node	*an_next;
-} attr_node_t;
-
-typedef struct connect_state {
-	wladm_wlan_attr_t	*cs_attr;
-	uint_t			cs_count;
-	attr_node_t		*cs_list;
-} connect_state_t;
-
-/*
- * Compare two sets of WLAN attributes.  For now, we only consider strength
- * and speed (in that order), which matches the documented default policy for
- * wladm_connect().
- */
-static int
-attr_compare(const void *p1, const void *p2)
-{
-	wladm_wlan_attr_t *attrp1, *attrp2;
-
-	attrp1 = (*(wladm_wlan_attr_t **)p1);
-	attrp2 = (*(wladm_wlan_attr_t **)p2);
-
-	if (attrp1->wa_strength < attrp2->wa_strength)
-		return (1);
-
-	if (attrp1->wa_strength > attrp2->wa_strength)
-		return (-1);
-
-	return (attrp2->wa_speed - attrp1->wa_speed);
-}
-
-/*
- * Callback function used by wladm_connect() to filter out unwanted WLANs when
- * scanning for available WLANs.  Always returns B_TRUE to continue the scan.
- */
-static boolean_t
-connect_cb(void *arg, wladm_wlan_attr_t *attrp)
-{
-	attr_node_t		*nodep;
-	wladm_wlan_attr_t	*fattrp;
-	connect_state_t		*statep = (connect_state_t *)arg;
-
-	fattrp = statep->cs_attr;
-	if (fattrp == NULL)
-		goto append;
-
-	if ((fattrp->wa_valid & attrp->wa_valid) != fattrp->wa_valid)
-		return (B_TRUE);
-
-	if ((fattrp->wa_valid & WLADM_WLAN_ATTR_ESSID) != 0 &&
-	    strncmp(fattrp->wa_essid.we_bytes, attrp->wa_essid.we_bytes,
-	    WLADM_MAX_ESSID_LEN) != 0)
-		return (B_TRUE);
-
-	if ((fattrp->wa_valid & WLADM_WLAN_ATTR_SECMODE) != 0 &&
-	    fattrp->wa_secmode != attrp->wa_secmode)
-		return (B_TRUE);
-
-	if ((fattrp->wa_valid & WLADM_WLAN_ATTR_MODE) != 0 &&
-	    fattrp->wa_mode != attrp->wa_mode)
-		return (B_TRUE);
-
-	if ((fattrp->wa_valid & WLADM_WLAN_ATTR_STRENGTH) != 0 &&
-	    fattrp->wa_strength != attrp->wa_strength)
-		return (B_TRUE);
-
-	if ((fattrp->wa_valid & WLADM_WLAN_ATTR_SPEED) != 0 &&
-	    fattrp->wa_speed != attrp->wa_speed)
-		return (B_TRUE);
-
-	if ((fattrp->wa_valid & WLADM_WLAN_ATTR_AUTH) != 0) {
-		attrp->wa_auth = fattrp->wa_auth;
-		attrp->wa_valid |= WLADM_WLAN_ATTR_AUTH;
-	}
-
-	if ((fattrp->wa_valid & WLADM_WLAN_ATTR_BSSTYPE) != 0 &&
-	    fattrp->wa_bsstype != attrp->wa_bsstype)
-		return (B_TRUE);
-
-	if ((fattrp->wa_valid & WLADM_WLAN_ATTR_BSSID) != 0 &&
-	    memcmp(fattrp->wa_bssid.wb_bytes, attrp->wa_bssid.wb_bytes,
-	    WLADM_BSSID_LEN) != 0)
-		return (B_TRUE);
-append:
-	nodep = malloc(sizeof (attr_node_t));
-	if (nodep == NULL)
-		return (B_TRUE);
-
-	(void) memcpy(&nodep->an_attr, attrp, sizeof (wladm_wlan_attr_t));
-	nodep->an_next = statep->cs_list;
-	statep->cs_list = nodep;
-	statep->cs_count++;
-
-	return (B_TRUE);
-}
-
-static wladm_status_t
-do_connect(int fd, wldp_t *gbuf, wladm_wlan_attr_t *attrp,
-    boolean_t create_ibss, void *keys, uint_t key_count, int timeout)
-{
-	wladm_secmode_t		secmode;
-	wladm_auth_t		authmode;
-	wladm_bsstype_t		bsstype;
-	wladm_essid_t		essid;
-	boolean_t		essid_valid = B_FALSE;
-	wladm_channel_t		channel;
-	hrtime_t		start;
-
-	if ((attrp->wa_valid & WLADM_WLAN_ATTR_CHANNEL) != 0) {
-		channel = attrp->wa_channel;
-		if (do_set_channel(fd, gbuf, &channel) < 0)
-			goto fail;
-	}
-
-	secmode = ((attrp->wa_valid & WLADM_WLAN_ATTR_SECMODE) != 0) ?
-	    attrp->wa_secmode : WLADM_SECMODE_NONE;
-
-	if (do_set_encryption(fd, gbuf, &secmode) < 0)
-		goto fail;
-
-	authmode = ((attrp->wa_valid & WLADM_WLAN_ATTR_AUTH) != 0) ?
-	    attrp->wa_auth : WLADM_AUTH_OPEN;
-
-	if (do_set_authmode(fd, gbuf, &authmode) < 0)
-		goto fail;
-
-	bsstype = ((attrp->wa_valid & WLADM_WLAN_ATTR_BSSTYPE) != 0) ?
-	    attrp->wa_bsstype : WLADM_BSSTYPE_BSS;
-
-	if (do_set_bsstype(fd, gbuf, &bsstype) < 0)
-		goto fail;
-
-	if (secmode == WLADM_SECMODE_WEP) {
-		if (keys == NULL || key_count == 0 || key_count > MAX_NWEPKEYS)
-			return (WLADM_STATUS_BADARG);
-		if (do_set_wepkey(fd, gbuf, keys, key_count) < 0)
-			goto fail;
-	}
-
-	if (create_ibss) {
-		if (do_set_channel(fd, gbuf, &channel) < 0)
-			goto fail;
-
-		if (do_set_createibss(fd, gbuf, &create_ibss) < 0)
-			goto fail;
-
-		if ((attrp->wa_valid & WLADM_WLAN_ATTR_ESSID) == 0) {
-			generate_essid(&essid);
-			essid_valid = B_TRUE;
-		}
-	}
-
-	if ((attrp->wa_valid & WLADM_WLAN_ATTR_ESSID) != 0) {
-		essid = attrp->wa_essid;
-		essid_valid = B_TRUE;
-	}
-
-	if (!essid_valid)
-		return (WLADM_STATUS_FAILED);
-	if (do_set_essid(fd, gbuf, &essid) < 0)
-		goto fail;
-
-	start = gethrtime();
-	for (;;) {
-		if (do_get_linkstatus(fd, gbuf) < 0)
-			goto fail;
-
-		if (IS_CONNECTED(gbuf))
-			break;
-
-		(void) poll(NULL, 0, WLADM_CONNECT_POLLRATE);
-		if ((timeout >= 0) && (gethrtime() - start) /
-		    NANOSEC >= timeout)
-			return (WLADM_STATUS_TIMEDOUT);
-	}
-	return (WLADM_STATUS_OK);
-fail:
-	return (wladm_wlresult2status(gbuf));
-}
-
-wladm_status_t
-wladm_connect(const char *link, wladm_wlan_attr_t *attrp,
-    int timeout, void *keys, uint_t key_count, uint_t flags)
-{
-	int			fd, i;
-	wldp_t 			*gbuf = NULL;
-	connect_state_t		state = {0, NULL, NULL};
-	attr_node_t		*nodep = NULL;
-	boolean_t		create_ibss, set_authmode;
-	wladm_wlan_attr_t	**wl_list = NULL;
-	wladm_status_t		status = WLADM_STATUS_FAILED;
-
-	if ((fd = open_link(link)) < 0)
-		return (WLADM_STATUS_LINKINVAL);
-
-	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
-		status = WLADM_STATUS_NOMEM;
-		goto done;
-	}
-
-	if (do_get_linkstatus(fd, gbuf) < 0) {
-		status = WLADM_STATUS_FAILED;
-		goto done;
-	}
-
-	if (IS_CONNECTED(gbuf)) {
-		status = WLADM_STATUS_ISCONN;
-		goto done;
-	}
-
-	set_authmode = ((attrp != NULL) &&
-	    (attrp->wa_valid & WLADM_WLAN_ATTR_MODE) != 0);
-	create_ibss = ((flags & WLADM_OPT_CREATEIBSS) != 0 &&
-	    attrp != NULL &&
-	    (attrp->wa_valid & WLADM_WLAN_ATTR_BSSTYPE) != 0 &&
-	    attrp->wa_bsstype == WLADM_BSSTYPE_IBSS);
-
-	if ((flags & WLADM_OPT_NOSCAN) != 0 ||
-	    (create_ibss && attrp != NULL &&
-	    (attrp->wa_valid & WLADM_WLAN_ATTR_ESSID) == 0)) {
-		status = do_connect(fd, gbuf, attrp,
-		    create_ibss, keys, key_count, timeout);
-		goto done;
-	}
-
-	state.cs_attr = attrp;
-	state.cs_list = NULL;
-	state.cs_count = 0;
-
-	status = wladm_scan(link, &state, connect_cb);
-	if (status != WLADM_STATUS_OK)
-		goto done;
-
-	if (state.cs_count == 0) {
-		if (!create_ibss) {
-			status = WLADM_STATUS_NOTFOUND;
-			goto done;
-		}
-		status = do_connect(fd, gbuf, attrp, create_ibss,
-		    keys, key_count, timeout);
-		goto done;
-	}
-
-	wl_list = malloc(state.cs_count * sizeof (wladm_wlan_attr_t *));
-	if (wl_list == NULL) {
-		status = WLADM_STATUS_NOMEM;
-		goto done;
-	}
-
-	nodep = state.cs_list;
-	for (i = 0; i < state.cs_count; i++) {
-		wl_list[i] = &nodep->an_attr;
-		nodep = nodep->an_next;
-	}
-	qsort(wl_list, state.cs_count, sizeof (wladm_wlan_attr_t *),
-	    attr_compare);
-
-	for (i = 0; i < state.cs_count; i++) {
-		wladm_wlan_attr_t	*ap = wl_list[i];
-
-		status = do_connect(fd, gbuf, ap, create_ibss, keys,
-		    key_count, timeout);
-		if (status == WLADM_STATUS_OK)
-			break;
-
-		if (!set_authmode) {
-			ap->wa_auth = WLADM_AUTH_SHARED;
-			ap->wa_valid |= WLADM_WLAN_ATTR_AUTH;
-			status = do_connect(fd, gbuf, ap, create_ibss, keys,
-			    key_count, timeout);
-			if (status == WLADM_STATUS_OK)
-				break;
-		}
-	}
-done:
-	if ((status != WLADM_STATUS_OK) && (status != WLADM_STATUS_ISCONN))
-		(void) do_disconnect(fd, gbuf);
-
-	while (state.cs_list != NULL) {
-		nodep = state.cs_list;
-		state.cs_list = nodep->an_next;
-		free(nodep);
-	}
-	free(gbuf);
-	free(wl_list);
-	(void) close(fd);
-	return (status);
-}
-
-wladm_status_t
-wladm_disconnect(const char *link)
-{
-	int		fd;
-	wldp_t		*gbuf;
-	wladm_status_t	status;
-
-	if ((fd = open_link(link)) < 0)
-		return (WLADM_STATUS_BADARG);
-
-	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
-		status = WLADM_STATUS_NOMEM;
-		goto done;
-	}
-
-	if (do_get_linkstatus(fd, gbuf) < 0) {
-		status = WLADM_STATUS_FAILED;
-		goto done;
-	}
-
-	if (!IS_CONNECTED(gbuf)) {
-		status = WLADM_STATUS_NOTCONN;
-		goto done;
-	}
-
-	if (do_disconnect(fd, gbuf) < 0) {
-		status = WLADM_STATUS_FAILED;
-		goto done;
-	}
-
-	if (do_get_linkstatus(fd, gbuf) < 0) {
-		status = WLADM_STATUS_FAILED;
-		goto done;
-	}
-
-	if (IS_CONNECTED(gbuf)) {
-		status = WLADM_STATUS_FAILED;
-		goto done;
-	}
-
-	status = WLADM_STATUS_OK;
-done:
-	free(gbuf);
-	(void) close(fd);
-	return (status);
-}
-
-typedef struct wladm_linkname {
-	char			wl_name[MAXNAMELEN];
-	struct wladm_linkname	*wl_next;
-} wladm_linkname_t;
-
-typedef struct wladm_walk {
-	wladm_linkname_t	*ww_list;
-	wladm_status_t		ww_status;
-} wladm_walk_t;
-
-/* ARGSUSED */
-static int
-append_linkname(di_node_t node, di_minor_t minor, void *arg)
-{
-	wladm_walk_t		*statep = arg;
-	wladm_linkname_t	**lastp = &statep->ww_list;
-	wladm_linkname_t	*wlp = *lastp;
-	char			name[MAXNAMELEN];
-
-	(void) snprintf(name, MAXNAMELEN, "%s%d",
-	    di_driver_name(node), di_instance(node));
-
-	while (wlp != NULL) {
-		if (strcmp(wlp->wl_name, name) == 0)
-			return (DI_WALK_CONTINUE);
-
-		lastp = &wlp->wl_next;
-		wlp = wlp->wl_next;
-	}
-	if ((wlp = malloc(sizeof (*wlp))) == NULL) {
-		statep->ww_status = WLADM_STATUS_NOMEM;
-		return (DI_WALK_CONTINUE);
-	}
-
-	(void) strlcpy(wlp->wl_name, name, MAXNAMELEN);
-	wlp->wl_next = NULL;
-	*lastp = wlp;
-
-	return (DI_WALK_CONTINUE);
-}
-
-wladm_status_t
-wladm_walk(void *arg, boolean_t (*func)(void *, const char *))
-{
-	di_node_t		root;
-	wladm_walk_t		state;
-	wladm_linkname_t	*wlp, *wlp_next;
-	boolean_t		cont = B_TRUE;
-
-	if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL)
-		return (WLADM_STATUS_FAILED);
-
-	state.ww_list = NULL;
-	state.ww_status = WLADM_STATUS_OK;
-	(void) di_walk_minor(root, DDI_NT_NET_WIFI, DI_CHECK_ALIAS,
-	    &state, append_linkname);
-	di_fini(root);
-
-	for (wlp = state.ww_list; wlp != NULL; wlp = wlp_next) {
-		/*
-		 * NOTE: even if (*func)() returns B_FALSE, the loop continues
-		 * since all memory must be freed.
-		 */
-		if (cont)
-			cont = (*func)(arg, wlp->wl_name);
-		wlp_next = wlp->wl_next;
-		free(wlp);
-	}
-	return (state.ww_status);
-}
-
-wladm_status_t
-wladm_get_link_attr(const char *link, wladm_link_attr_t *attrp)
-{
-	int			fd;
-	wldp_t			*gbuf;
-	wl_rssi_t		signal;
-	wl_bss_type_t		bsstype;
-	wl_authmode_t		authmode;
-	wl_encryption_t		encryption;
-	wl_rates_t		*ratesp;
-	wladm_wlan_attr_t	*wl_attrp;
-	wladm_status_t		status = WLADM_STATUS_FAILED;
-
-	if (attrp == NULL)
-		return (WLADM_STATUS_BADARG);
-
-	if ((fd = open_link(link)) < 0)
-		return (WLADM_STATUS_LINKINVAL);
-
-	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
-		status = WLADM_STATUS_NOMEM;
-		goto done;
-	}
-
-	(void) memset(attrp, 0, sizeof (*attrp));
-	wl_attrp = &attrp->la_wlan_attr;
-
-	if (do_get_linkstatus(fd, gbuf) < 0)
-		goto done;
-
-	attrp->la_valid |= WLADM_LINK_ATTR_STATUS;
-	if (!IS_CONNECTED(gbuf)) {
-		attrp->la_status = WLADM_LINK_STATUS_DISCONNECTED;
-		status = WLADM_STATUS_OK;
-		goto done;
-	}
-	attrp->la_status = WLADM_LINK_STATUS_CONNECTED;
-
-	if (do_get_essid(fd, gbuf) < 0)
-		goto done;
-
-	(void) strlcpy(wl_attrp->wa_essid.we_bytes,
-	    ((wl_essid_t *)(gbuf->wldp_buf))->wl_essid_essid,
-	    WLADM_MAX_ESSID_LEN);
-
-	wl_attrp->wa_valid |= WLADM_WLAN_ATTR_ESSID;
-
-	if (do_get_bssid(fd, gbuf) < 0)
-		goto done;
-
-	(void) memcpy(wl_attrp->wa_bssid.wb_bytes, gbuf->wldp_buf,
-	    WLADM_BSSID_LEN);
-
-	wl_attrp->wa_valid |= WLADM_WLAN_ATTR_BSSID;
-
-	if (do_get_encryption(fd, gbuf) < 0)
-		goto done;
-
-	encryption = *(wl_encryption_t *)(gbuf->wldp_buf);
-	wl_attrp->wa_valid |= WLADM_WLAN_ATTR_SECMODE;
-
-	switch (encryption) {
-	case WL_NOENCRYPTION:
-		wl_attrp->wa_secmode = WLADM_SECMODE_NONE;
-		break;
-	case WL_ENC_WEP:
-		wl_attrp->wa_secmode = WLADM_SECMODE_WEP;
-		break;
-	default:
-		wl_attrp->wa_valid &= ~WLADM_WLAN_ATTR_SECMODE;
-		break;
-	}
-
-	if (do_get_signal(fd, gbuf) < 0)
-		goto done;
-
-	signal = *(wl_rssi_t *)(gbuf->wldp_buf);
-	wl_attrp->wa_valid |= WLADM_WLAN_ATTR_STRENGTH;
-	wl_attrp->wa_strength = WLADM_SIGNAL2STRENGTH(signal);
-
-	if (do_get_rate(fd, gbuf) < 0)
-		goto done;
-
-	ratesp = (wl_rates_t *)(gbuf->wldp_buf);
-	if (ratesp->wl_rates_num > 0) {
-		uint_t	i, r = 0;
-
-		for (i = 0; i < ratesp->wl_rates_num; i++) {
-			if (ratesp->wl_rates_rates[i] > r)
-				r = ratesp->wl_rates_rates[i];
-		}
-		wl_attrp->wa_speed = r;
-		wl_attrp->wa_valid |= WLADM_WLAN_ATTR_SPEED;
-	}
-
-	if (do_get_authmode(fd, gbuf) < 0)
-		goto done;
-
-	authmode = *(wl_authmode_t *)(gbuf->wldp_buf);
-	wl_attrp->wa_valid |= WLADM_WLAN_ATTR_AUTH;
-
-	switch (authmode) {
-	case WL_OPENSYSTEM:
-		wl_attrp->wa_auth = WLADM_AUTH_OPEN;
-		break;
-	case WL_SHAREDKEY:
-		wl_attrp->wa_auth = WLADM_AUTH_SHARED;
-		break;
-	default:
-		wl_attrp->wa_valid &= ~WLADM_WLAN_ATTR_AUTH;
-		break;
-	}
-
-	if (do_get_bsstype(fd, gbuf) < 0)
-		goto done;
-
-	bsstype = *(wl_bss_type_t *)(gbuf->wldp_buf);
-	wl_attrp->wa_valid |= WLADM_WLAN_ATTR_BSSTYPE;
-
-	switch (bsstype) {
-	case WL_BSS_BSS:
-		wl_attrp->wa_bsstype = WLADM_BSSTYPE_BSS;
-		break;
-	case WL_BSS_IBSS:
-		wl_attrp->wa_bsstype = WLADM_BSSTYPE_IBSS;
-		break;
-	case WL_BSS_ANY:
-		wl_attrp->wa_bsstype = WLADM_BSSTYPE_ANY;
-		break;
-	default:
-		wl_attrp->wa_valid &= ~WLADM_WLAN_ATTR_BSSTYPE;
-		break;
-	}
-
-	if (do_get_mode(fd, gbuf) < 0)
-		goto done;
-
-	wl_attrp->wa_mode = do_convert_mode((wl_phy_conf_t *)(gbuf->wldp_buf));
-	wl_attrp->wa_valid |= WLADM_WLAN_ATTR_MODE;
-	if (wl_attrp->wa_mode != WLADM_MODE_NONE)
-		wl_attrp->wa_valid |= WLADM_WLAN_ATTR_MODE;
-
-	attrp->la_valid |= WLADM_LINK_ATTR_WLAN;
-	status = WLADM_STATUS_OK;
-
-done:
-	free(gbuf);
-	(void) close(fd);
-	return (status);
-}
-
-boolean_t
-wladm_is_valid(const char *link)
-{
-	int fd = open_link(link);
-
-	if (fd < 0)
-		return (B_FALSE);
-
-	(void) close(fd);
-	return (B_TRUE);
-}
-
-/* ARGSUSED */
-static wladm_status_t
-do_check_prop(int fd, wldp_t *guf, prop_desc_t *pdp, char **prop_val,
-    uint_t val_cnt, val_desc_t **vdpp)
-{
-	int		i;
-	val_desc_t	*vdp;
-
-	if (pdp->pd_nmodval == 0)
-		return (WLADM_STATUS_PROPRDONLY);
-
-	if (val_cnt != 1)
-		return (WLADM_STATUS_BADVALCNT);
-
-	for (i = 0; i < pdp->pd_nmodval; i++)
-		if (strcasecmp(*prop_val, pdp->pd_modval[i].vd_name) == 0)
-			break;
-
-	if (i == pdp->pd_nmodval)
-		return (WLADM_STATUS_BADVAL);
-
-	vdp = malloc(sizeof (val_desc_t));
-	if (vdp == NULL)
-		return (WLADM_STATUS_NOMEM);
-
-	(void) memcpy(vdp, &pdp->pd_modval[i], sizeof (val_desc_t));
-	*vdpp = vdp;
-	return (WLADM_STATUS_OK);
-}
-
-static wladm_status_t
-do_set_prop(int fd, wldp_t *gbuf, prop_desc_t *pdp,
-    char **prop_val, uint_t val_cnt)
-{
-	wladm_status_t	status;
-	val_desc_t	*vdp = NULL;
-	uint_t		cnt;
-
-	if (pdp->pd_set == NULL)
-		return (WLADM_STATUS_PROPRDONLY);
-
-	if (prop_val != NULL) {
-		status = pdp->pd_check(fd, gbuf, pdp, prop_val,
-		    val_cnt, &vdp);
-
-		if (status != WLADM_STATUS_OK)
-			return (status);
-
-		cnt = val_cnt;
-	} else {
-		if (pdp->pd_defval.vd_name == NULL)
-			return (WLADM_STATUS_NOTSUP);
-
-		if ((vdp = malloc(sizeof (val_desc_t))) == NULL)
-			return (WLADM_STATUS_NOMEM);
-
-		*vdp = pdp->pd_defval;
-		cnt = 1;
-	}
-	status = pdp->pd_set(fd, gbuf, vdp, cnt);
-	if (status == WLADM_STATUS_OK) {
-		/*
-		 * Some ioctls return 0 but store error code in
-		 * wldp_result. Need to fix them.
-		 */
-		if (gbuf->wldp_result != WL_SUCCESS)
-			status = wladm_wlresult2status(gbuf);
-	}
-	free(vdp);
-	return (status);
-}
-
-wladm_status_t
-wladm_set_prop(const char *link, const char *prop_name,
-    char **prop_val, uint_t val_cnt, char **errprop)
-{
-	int		fd, i;
-	wldp_t		*gbuf = NULL;
-	boolean_t	found = B_FALSE;
-	wladm_status_t	status = WLADM_STATUS_OK;
-
-	if ((prop_name == NULL && prop_val != NULL) ||
-	    (prop_val != NULL && val_cnt == 0))
-		return (WLADM_STATUS_BADARG);
-
-	if ((fd = open_link(link)) < 0)
-		return (WLADM_STATUS_LINKINVAL);
-
-	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
-		status = WLADM_STATUS_NOMEM;
-		goto done;
-	}
-
-	for (i = 0; i < WLADM_MAX_PROPS; i++) {
-		prop_desc_t	*pdp = &prop_table[i];
-		wladm_status_t	s;
-
-		if (prop_name != NULL &&
-		    (strcasecmp(prop_name, pdp->pd_name) != 0))
-			continue;
-
-		found = B_TRUE;
-		s = do_set_prop(fd, gbuf, pdp, prop_val, val_cnt);
-
-		if (prop_name != NULL) {
-			status = s;
-			break;
-		} else {
-			if (s != WLADM_STATUS_OK &&
-			    s != WLADM_STATUS_NOTSUP) {
-				if (errprop != NULL)
-					*errprop = pdp->pd_name;
-				status = s;
-				break;
-			}
-		}
-	}
-	if (!found)
-		status = WLADM_STATUS_NOTFOUND;
-done:
-	free(gbuf);
-	(void) close(fd);
-	return (status);
-}
-
-/* ARGSUSED */
-wladm_status_t
-wladm_walk_prop(const char *link, void *arg,
-    boolean_t (*func)(void *, const char *))
-{
-	int	i;
-
-	for (i = 0; i < WLADM_MAX_PROPS; i++) {
-		if (!func(arg, prop_table[i].pd_name))
-			break;
-	}
-	return (WLADM_STATUS_OK);
-}
-
-wladm_status_t
-wladm_get_prop(const char *link, wladm_prop_type_t type, const char *prop_name,
-    char **prop_val, uint_t *val_cnt)
-{
-	int		fd;
-	int		i;
-	wldp_t		*gbuf;
-	wladm_status_t	status;
-	uint_t		cnt;
-	prop_desc_t	*pdp;
-
-	if (prop_val == NULL || val_cnt == NULL || *val_cnt == 0)
-		return (WLADM_STATUS_BADARG);
-
-	for (i = 0; i < WLADM_MAX_PROPS; i++)
-		if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
-			break;
-
-	if (i == WLADM_MAX_PROPS)
-		return (WLADM_STATUS_NOTFOUND);
-
-	if ((fd = open_link(link)) < 0)
-		return (WLADM_STATUS_LINKINVAL);
-
-	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
-		status = WLADM_STATUS_NOMEM;
-		goto done;
-	}
-	pdp = &prop_table[i];
-	status = WLADM_STATUS_OK;
-
-	switch (type) {
-	case WLADM_PROP_VAL_CURRENT:
-		status = pdp->pd_get(fd, gbuf, prop_val, val_cnt);
-		break;
-
-	case WLADM_PROP_VAL_DEFAULT:
-		if (pdp->pd_defval.vd_name == NULL) {
-			status = WLADM_STATUS_NOTSUP;
-			break;
-		}
-		(void) strcpy(*prop_val, pdp->pd_defval.vd_name);
-		*val_cnt = 1;
-		break;
-
-	case WLADM_PROP_VAL_MODIFIABLE:
-		if (pdp->pd_getmod != NULL) {
-			status = pdp->pd_getmod(fd, gbuf, prop_val, val_cnt);
-			break;
-		}
-		cnt = pdp->pd_nmodval;
-		if (cnt == 0) {
-			status = WLADM_STATUS_NOTSUP;
-		} else if (cnt > *val_cnt) {
-			status = WLADM_STATUS_TOOSMALL;
-		} else {
-			for (i = 0; i < cnt; i++) {
-				(void) strcpy(prop_val[i],
-				    pdp->pd_modval[i].vd_name);
-			}
-			*val_cnt = cnt;
-		}
-		break;
-	default:
-		status = WLADM_STATUS_BADARG;
-		break;
-	}
-done:
-	free(gbuf);
-	(void) close(fd);
-	return (status);
-}
-
-static boolean_t
-find_val_by_name(const char *str, val_desc_t *vdp, uint_t cnt, uint_t *valp)
-{
-	int	i;
-
-	for (i = 0; i < cnt; i++) {
-		if (strcasecmp(str, vdp[i].vd_name) == 0) {
-			*valp = vdp[i].vd_val;
-			return (B_TRUE);
-		}
-	}
-	return (B_FALSE);
-}
-
-static boolean_t
-find_name_by_val(uint_t val, val_desc_t *vdp, uint_t cnt, char **strp)
-{
-	int	i;
-
-	for (i = 0; i < cnt; i++) {
-		if (val == vdp[i].vd_val) {
-			*strp = vdp[i].vd_name;
-			return (B_TRUE);
-		}
-	}
-	return (B_FALSE);
-}
-
-const char *
-wladm_essid2str(wladm_essid_t *essid, char *buf)
-{
-	(void) snprintf(buf, WLADM_STRSIZE, "%s", essid->we_bytes);
-	return (buf);
-}
-
-const char *
-wladm_bssid2str(wladm_bssid_t *bssid, char *buf)
-{
-	return (_link_ntoa(bssid->wb_bytes, buf, WLADM_BSSID_LEN, IFT_OTHER));
-}
-
-static const char *
-wladm_val2str(uint_t val, val_desc_t *vdp, uint_t cnt, char *buf)
-{
-	char	*s;
-
-	if (!find_name_by_val(val, vdp, cnt, &s))
-		s = "";
-
-	(void) snprintf(buf, WLADM_STRSIZE, "%s", s);
-	return (buf);
-}
-
-const char *
-wladm_secmode2str(wladm_secmode_t *secmode, char *buf)
-{
-	return (wladm_val2str((uint_t)*secmode, secmode_vals,
-	    VALCNT(secmode_vals), buf));
-}
-
-const char *
-wladm_strength2str(wladm_strength_t *strength, char *buf)
-{
-	return (wladm_val2str((uint_t)*strength, strength_vals,
-	    VALCNT(strength_vals), buf));
-}
-
-const char *
-wladm_mode2str(wladm_mode_t *mode, char *buf)
-{
-	return (wladm_val2str((uint_t)*mode, mode_vals,
-	    VALCNT(mode_vals), buf));
-}
-
-const char *
-wladm_speed2str(wladm_speed_t *speed, char *buf)
-{
-	(void) snprintf(buf, WLADM_STRSIZE, "%.*f", *speed % 2,
-	    (float)(*speed) / 2);
-	return (buf);
-}
-
-const char *
-wladm_auth2str(wladm_auth_t *auth, char *buf)
-{
-	return (wladm_val2str((uint_t)*auth, auth_vals,
-	    VALCNT(auth_vals), buf));
-}
-
-const char *
-wladm_bsstype2str(wladm_bsstype_t *bsstype, char *buf)
-{
-	return (wladm_val2str((uint_t)*bsstype, bsstype_vals,
-	    VALCNT(bsstype_vals), buf));
-}
-
-const char *
-wladm_linkstatus2str(wladm_linkstatus_t *linkstatus, char *buf)
-{
-	return (wladm_val2str((uint_t)*linkstatus, linkstatus_vals,
-	    VALCNT(linkstatus_vals), buf));
-}
-
-const char *
-wladm_status2str(wladm_status_t status, char *buf)
-{
-	const char *s;
-
-	s = wladm_val2str((uint_t)status, status_vals,
-	    VALCNT(status_vals), buf);
-	(void) snprintf(buf, WLADM_STRSIZE, "%s", dgettext(TEXT_DOMAIN, s));
-	return (buf);
-}
-
-wladm_status_t
-wladm_str2essid(const char *str, wladm_essid_t *essid)
-{
-	if (str[0] == '\0')
-		return (WLADM_STATUS_BADARG);
-
-	(void) strlcpy(essid->we_bytes, str, WLADM_MAX_ESSID_LEN);
-	return (WLADM_STATUS_OK);
-}
-
-wladm_status_t
-wladm_str2bssid(const char *str, wladm_bssid_t *bssid)
-{
-	int	len;
-	uchar_t	*buf;
-
-	buf = _link_aton(str, &len);
-	if (buf == NULL)
-		return (WLADM_STATUS_BADARG);
-
-	if (len != WLADM_BSSID_LEN) {
-		free(buf);
-		return (WLADM_STATUS_BADARG);
-	}
-
-	(void) memcpy(bssid->wb_bytes, buf, len);
-	free(buf);
-	return (WLADM_STATUS_OK);
-}
-
-wladm_status_t
-wladm_str2secmode(const char *str, wladm_secmode_t *secmode)
-{
-	uint_t	val;
-
-	if (!find_val_by_name(str, secmode_vals, VALCNT(secmode_vals), &val))
-		return (WLADM_STATUS_BADARG);
-
-	*secmode = (wladm_secmode_t)val;
-	return (WLADM_STATUS_OK);
-}
-
-wladm_status_t
-wladm_str2strength(const char *str, wladm_strength_t *strength)
-{
-	uint_t	val;
-
-	if (!find_val_by_name(str, strength_vals, VALCNT(strength_vals), &val))
-		return (WLADM_STATUS_BADARG);
-
-	*strength = (wladm_strength_t)val;
-	return (WLADM_STATUS_OK);
-}
-
-wladm_status_t
-wladm_str2mode(const char *str, wladm_mode_t *mode)
-{
-	uint_t	val;
-
-	if (!find_val_by_name(str, mode_vals, VALCNT(mode_vals), &val))
-		return (WLADM_STATUS_BADARG);
-
-	*mode = (wladm_mode_t)val;
-	return (WLADM_STATUS_OK);
-}
-
-wladm_status_t
-wladm_str2speed(const char *str, wladm_speed_t *speed)
-{
-	*speed = (wladm_speed_t)(atof(str) * 2);
-	return (WLADM_STATUS_OK);
-}
-
-wladm_status_t
-wladm_str2auth(const char *str, wladm_auth_t *auth)
-{
-	uint_t	val;
-
-	if (!find_val_by_name(str, auth_vals, VALCNT(auth_vals), &val))
-		return (WLADM_STATUS_BADARG);
-
-	*auth = (wladm_auth_t)val;
-	return (WLADM_STATUS_OK);
-}
-
-wladm_status_t
-wladm_str2bsstype(const char *str, wladm_bsstype_t *bsstype)
-{
-	uint_t	val;
-
-	if (!find_val_by_name(str, bsstype_vals, VALCNT(bsstype_vals), &val))
-		return (WLADM_STATUS_BADARG);
-
-	*bsstype = (wladm_bsstype_t)val;
-	return (WLADM_STATUS_OK);
-}
-
-wladm_status_t
-wladm_str2linkstatus(const char *str, wladm_linkstatus_t *linkstatus)
-{
-	uint_t	val;
-
-	if (!find_val_by_name(str, linkstatus_vals, VALCNT(linkstatus_vals),
-	    &val))
-		return (WLADM_STATUS_BADARG);
-
-	*linkstatus = (wladm_linkstatus_t)val;
-	return (WLADM_STATUS_OK);
-}
-
-static int
-do_ioctl(int fd, wldp_t *gbuf, uint_t id, size_t len, uint_t cmd, size_t cmdlen)
-{
-	int			rc;
-	struct	strioctl	stri;
-
-	gbuf->wldp_type = NET_802_11;
-	gbuf->wldp_id	= id;
-	gbuf->wldp_length = len;
-
-	stri.ic_timout	= 0;
-	stri.ic_dp	= (char *)gbuf;
-	stri.ic_cmd	= cmd;
-	stri.ic_len	= cmdlen;
-
-	if ((rc = ioctl(fd, I_STR, &stri)) != 0) {
-		if (rc > 0)
-			errno = rc;
-		return (-1);
-	}
-	return (0);
-}
-
-static int
-do_get_ioctl(int fd, wldp_t *gbuf, uint_t id)
-{
-	(void) memset(gbuf, 0, MAX_BUF_LEN);
-	return (do_ioctl(fd, gbuf, id, MAX_BUF_LEN, WLAN_GET_PARAM,
-	    MAX_BUF_LEN));
-}
-
-static int
-do_set_ioctl(int fd, wldp_t *gbuf, uint_t id, void *buf, uint_t buflen)
-{
-	(void) memset(gbuf, 0, MAX_BUF_LEN);
-	(void) memcpy(gbuf->wldp_buf, buf, buflen);
-	buflen += WIFI_BUF_OFFSET;
-	return (do_ioctl(fd, gbuf, id, buflen, WLAN_SET_PARAM, buflen));
-}
-
-static int
-do_cmd_ioctl(int fd, wldp_t *gbuf, uint_t cmd)
-{
-	(void) memset(gbuf, 0, MAX_BUF_LEN);
-	return (do_ioctl(fd, gbuf, cmd, sizeof (wldp_t), WLAN_COMMAND,
-	    sizeof (wldp_t)));
-}
-
-static int
-do_scan(int fd, wldp_t *gbuf)
-{
-	return (do_cmd_ioctl(fd, gbuf, WL_SCAN));
-}
-
-static int
-do_disconnect(int fd, wldp_t *gbuf)
-{
-	return (do_cmd_ioctl(fd, gbuf, WL_DISASSOCIATE));
-}
-
-static int
-do_get_esslist(int fd, wldp_t *gbuf)
-{
-	(void) memset(gbuf, 0, MAX_BUF_LEN);
-	return (do_ioctl(fd, gbuf, WL_ESS_LIST, MAX_BUF_LEN,
-	    WLAN_GET_PARAM, sizeof (wldp_t)));
-}
-
-static int
-do_get_bssid(int fd, wldp_t *gbuf)
-{
-	return (do_get_ioctl(fd, gbuf, WL_BSSID));
-}
-
-static int
-do_get_essid(int fd, wldp_t *gbuf)
-{
-	return (do_get_ioctl(fd, gbuf, WL_ESSID));
-}
-
-static int
-do_get_bsstype(int fd, wldp_t *gbuf)
-{
-	return (do_get_ioctl(fd, gbuf, WL_BSS_TYPE));
-}
-
-static int
-do_get_linkstatus(int fd, wldp_t *gbuf)
-{
-	return (do_get_ioctl(fd, gbuf, WL_LINKSTATUS));
-}
-
-static int
-do_get_rate(int fd, wldp_t *gbuf)
-{
-	return (do_get_ioctl(fd, gbuf, WL_DESIRED_RATES));
-}
-
-static int
-do_get_phyconf(int fd, wldp_t *gbuf)
-{
-	return (do_get_ioctl(fd, gbuf, WL_PHY_CONFIG));
-}
-
-static int
-do_get_powermode(int fd, wldp_t *gbuf)
-{
-	return (do_get_ioctl(fd, gbuf, WL_POWER_MODE));
-}
-
-static int
-do_get_radio(int fd, wldp_t *gbuf)
-{
-	return (do_get_ioctl(fd, gbuf, WL_RADIO));
-}
-
-static int
-do_get_authmode(int fd, wldp_t *gbuf)
-{
-	return (do_get_ioctl(fd, gbuf, WL_AUTH_MODE));
-}
-
-static int
-do_get_encryption(int fd, wldp_t *gbuf)
-{
-	return (do_get_ioctl(fd, gbuf, WL_ENCRYPTION));
-}
-
-static int
-do_get_signal(int fd, wldp_t *gbuf)
-{
-	return (do_get_ioctl(fd, gbuf, WL_RSSI));
-}
-
-static int
-do_get_mode(int fd, wldp_t *gbuf)
-{
-	return (do_get_ioctl(fd, gbuf, WL_PHY_CONFIG));
-}
-
-static wladm_status_t
-do_get_rate_common(wldp_t *gbuf, char **prop_val, uint_t *val_cnt)
-{
-	wl_rates_t	*wrp = (wl_rates_t *)gbuf->wldp_buf;
-	uint_t		cnt = wrp->wl_rates_num;
-	uint_t		i;
-
-	if (cnt > *val_cnt)
-		return (WLADM_STATUS_TOOSMALL);
-	if (wrp->wl_rates_rates[0] == 0) {
-		prop_val[0][0] = '\0';
-		*val_cnt = 1;
-		return (WLADM_STATUS_OK);
-	}
-
-	for (i = 0; i < cnt; i++) {
-		(void) snprintf(prop_val[i], WLADM_STRSIZE, "%.*f",
-		    wrp->wl_rates_rates[i] % 2,
-		    (float)wrp->wl_rates_rates[i] / 2);
-	}
-	*val_cnt = cnt;
-	return (WLADM_STATUS_OK);
-}
-
-static wladm_status_t
-do_get_rate_prop(int fd, wldp_t *gbuf, char **prop_val, uint_t *val_cnt)
-{
-	if (do_get_rate(fd, gbuf) < 0)
-		return (wladm_wlresult2status(gbuf));
-
-	return (do_get_rate_common(gbuf, prop_val, val_cnt));
-}
-
-static wladm_status_t
-do_get_rate_mod(int fd, wldp_t *gbuf, char **prop_val, uint_t *val_cnt)
-{
-	if (do_get_ioctl(fd, gbuf, WL_SUPPORTED_RATES) < 0)
-		return (WLADM_STATUS_FAILED);
-
-	return (do_get_rate_common(gbuf, prop_val, val_cnt));
-}
-
-static wladm_status_t
-do_get_channel_prop(int fd, wldp_t *gbuf, char **prop_val, uint_t *val_cnt)
-{
-	uint32_t	channel;
-
-	if (do_get_phyconf(fd, gbuf) < 0)
-		return (wladm_wlresult2status(gbuf));
-
-	if (!do_convert_chan((wl_phy_conf_t *)gbuf->wldp_buf, &channel))
-		return (WLADM_STATUS_NOTFOUND);
-
-	(void) snprintf(*prop_val, WLADM_STRSIZE, "%u", channel);
-	*val_cnt = 1;
-
-	return (WLADM_STATUS_OK);
-}
-
-static wladm_status_t
-do_get_powermode_prop(int fd, wldp_t *gbuf, char **prop_val, uint_t *val_cnt)
-{
-	wl_ps_mode_t	*mode;
-	const char	*s;
-
-	if (do_get_powermode(fd, gbuf) < 0)
-		return (wladm_wlresult2status(gbuf));
-
-	mode = (wl_ps_mode_t *)(gbuf->wldp_buf);
-	switch (mode->wl_ps_mode) {
-	case WL_PM_AM:
-		s = "off";
-		break;
-	case WL_PM_MPS:
-		s = "max";
-		break;
-	case WL_PM_FAST:
-		s = "fast";
-		break;
-	default:
-		return (WLADM_STATUS_NOTFOUND);
-	}
-	(void) snprintf(*prop_val, WLADM_STRSIZE, "%s", s);
-	*val_cnt = 1;
-
-	return (WLADM_STATUS_OK);
-}
-
-static wladm_status_t
-do_get_radio_prop(int fd, wldp_t *gbuf, char **prop_val, uint_t *val_cnt)
-{
-	wl_radio_t	radio;
-	const char	*s;
-
-	if (do_get_radio(fd, gbuf) < 0)
-		return (wladm_wlresult2status(gbuf));
-
-	radio = *(wl_radio_t *)(gbuf->wldp_buf);
-	switch (radio) {
-	case B_TRUE:
-		s = "on";
-		break;
-	case B_FALSE:
-		s = "off";
-		break;
-	default:
-		return (WLADM_STATUS_NOTFOUND);
-	}
-	(void) snprintf(*prop_val, WLADM_STRSIZE, "%s", s);
-	*val_cnt = 1;
-
-	return (WLADM_STATUS_OK);
-}
-
-static int
-do_set_bsstype(int fd, wldp_t *gbuf, wladm_bsstype_t *bsstype)
-{
-	wl_bss_type_t	ibsstype;
-
-	switch (*bsstype) {
-	case WLADM_BSSTYPE_BSS:
-		ibsstype = WL_BSS_BSS;
-		break;
-	case WLADM_BSSTYPE_IBSS:
-		ibsstype = WL_BSS_IBSS;
-		break;
-	default:
-		ibsstype = WL_BSS_ANY;
-		break;
-	}
-	return (do_set_ioctl(fd, gbuf, WL_BSS_TYPE, &ibsstype,
-	    sizeof (ibsstype)));
-}
-
-static int
-do_set_authmode(int fd, wldp_t *gbuf, wladm_auth_t *auth)
-{
-	wl_authmode_t	auth_mode;
-
-	switch (*auth) {
-	case WLADM_AUTH_OPEN:
-		auth_mode = WL_OPENSYSTEM;
-		break;
-	case WLADM_AUTH_SHARED:
-		auth_mode = WL_SHAREDKEY;
-		break;
-	default:
-		return (-1);
-	}
-	return (do_set_ioctl(fd, gbuf, WL_AUTH_MODE, &auth_mode,
-	    sizeof (auth_mode)));
-}
-
-static int
-do_set_encryption(int fd, wldp_t *gbuf, wladm_secmode_t *secmode)
-{
-	wl_encryption_t	encryption;
-
-	switch (*secmode) {
-	case WLADM_SECMODE_NONE:
-		encryption = WL_NOENCRYPTION;
-		break;
-	case WLADM_SECMODE_WEP:
-		encryption = WL_ENC_WEP;
-		break;
-	default:
-		return (-1);
-	}
-	return (do_set_ioctl(fd, gbuf, WL_ENCRYPTION, &encryption,
-	    sizeof (encryption)));
-}
-
-static int
-do_set_wepkey(int fd, wldp_t *gbuf, wladm_wep_key_t *keys, uint_t key_count)
-{
-	int			i;
-	wl_wep_key_t		*wkp;
-	wl_wep_key_tab_t	wepkey_tab;
-	wladm_wep_key_t		*kp;
-
-	if (key_count == 0 || key_count > MAX_NWEPKEYS || keys == NULL)
-		return (-1);
-
-	(void) memset(wepkey_tab, 0, sizeof (wepkey_tab));
-	for (i = 0; i < MAX_NWEPKEYS; i++)
-		wepkey_tab[i].wl_wep_operation = WL_NUL;
-
-	for (i = 0; i < key_count; i++) {
-		kp = &keys[i];
-		if (kp->wk_idx == 0 || kp->wk_idx > MAX_NWEPKEYS)
-			return (-1);
-		if (kp->wk_len != WLADM_WEPKEY64_LEN &&
-		    kp->wk_len != WLADM_WEPKEY128_LEN)
-			return (-1);
-
-		wkp = &wepkey_tab[kp->wk_idx - 1];
-		wkp->wl_wep_operation = WL_ADD;
-		wkp->wl_wep_length = kp->wk_len;
-		(void) memcpy(wkp->wl_wep_key, kp->wk_val, kp->wk_len);
-	}
-
-	return (do_set_ioctl(fd, gbuf, WL_WEP_KEY_TAB, &wepkey_tab,
-	    sizeof (wepkey_tab)));
-}
-
-static int
-do_set_essid(int fd, wldp_t *gbuf, wladm_essid_t *essid)
-{
-	wl_essid_t	iessid;
-
-	(void) memset(&iessid, 0, sizeof (essid));
-
-	if (essid != NULL && essid->we_bytes[0] != '\0') {
-		iessid.wl_essid_length = strlen(essid->we_bytes);
-		(void) strlcpy(iessid.wl_essid_essid, essid->we_bytes,
-		    sizeof (iessid.wl_essid_essid));
-	} else {
-		return (-1);
-	}
-	return (do_set_ioctl(fd, gbuf, WL_ESSID, &iessid, sizeof (iessid)));
-}
-
-/* ARGSUSED */
-static wladm_status_t
-do_check_rate(int fd, wldp_t *gbuf, prop_desc_t *pdp, char **prop_val,
-    uint_t val_cnt, val_desc_t **vdpp)
-{
-	int		i;
-	uint_t		modval_cnt = MAX_SUPPORT_RATES;
-	char		*buf, **modval;
-	wladm_status_t	status;
-	val_desc_t	*vdp = NULL;
-
-	if (val_cnt != 1)
-		return (WLADM_STATUS_BADVALCNT);
-
-	buf = malloc((sizeof (char *) + WLADM_STRSIZE) *
-	    MAX_SUPPORT_RATES);
-	if (buf == NULL)
-		goto done;
-
-	modval = (char **)(void *)buf;
-	for (i = 0; i < MAX_SUPPORT_RATES; i++) {
-		modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES +
-		    i * WLADM_STRSIZE;
-	}
-
-	status = do_get_rate_mod(fd, gbuf, modval, &modval_cnt);
-	if (status != WLADM_STATUS_OK)
-		goto done;
-
-	vdp = malloc(sizeof (val_desc_t));
-	if (vdp == NULL) {
-		status = WLADM_STATUS_NOMEM;
-		goto done;
-	}
-
-	for (i = 0; i < modval_cnt; i++) {
-		if (strcasecmp(*prop_val, modval[i]) == 0) {
-			vdp->vd_val = (uint_t)(atof(*prop_val) * 2);
-			status = WLADM_STATUS_OK;
-			*vdpp = vdp;
-			vdp = NULL;
-			break;
-		}
-	}
-	if (i == modval_cnt)
-		status = WLADM_STATUS_BADVAL;
-done:
-	free(buf);
-	free(vdp);
-	return (status);
-}
-
-static wladm_status_t
-do_set_rate_prop(int fd, wldp_t *gbuf, val_desc_t *vdp, uint_t val_cnt)
-{
-	wladm_rates_t	rates;
-
-	if (val_cnt != 1)
-		return (WLADM_STATUS_BADVALCNT);
-
-	rates.wr_cnt = 1;
-	rates.wr_rates[0] = vdp[0].vd_val;
-
-	if (do_set_rate(fd, gbuf, &rates) < 0)
-		return (wladm_wlresult2status(gbuf));
-
-	return (WLADM_STATUS_OK);
-}
-
-static int
-do_set_rate(int fd, wldp_t *gbuf, wladm_rates_t *rates)
-{
-	int		i;
-	uint_t		len;
-	wl_rates_t	*wrp = (wl_rates_t *)gbuf->wldp_buf;
-
-	(void) memset(gbuf, 0, MAX_BUF_LEN);
-
-	for (i = 0; i < rates->wr_cnt; i++)
-		wrp->wl_rates_rates[i] = rates->wr_rates[i];
-	wrp->wl_rates_num = rates->wr_cnt;
-
-	len = offsetof(wl_rates_t, wl_rates_rates) +
-	    (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET;
-	return (do_ioctl(fd, gbuf, WL_DESIRED_RATES, len, WLAN_SET_PARAM, len));
-}
-
-/* ARGSUSED */
-static wladm_status_t
-do_set_powermode_prop(int fd, wldp_t *gbuf, val_desc_t *vdp, uint_t val_cnt)
-{
-	wladm_powermode_t powermode = (wladm_powermode_t)vdp->vd_val;
-
-	if (do_set_powermode(fd, gbuf, &powermode) < 0)
-		return (wladm_wlresult2status(gbuf));
-
-	return (WLADM_STATUS_OK);
-}
-
-static int
-do_set_powermode(int fd, wldp_t *gbuf, wladm_powermode_t *pm)
-{
-	wl_ps_mode_t	ps_mode;
-
-	(void) memset(&ps_mode, 0xff, sizeof (ps_mode));
-
-	switch (*pm) {
-	case WLADM_PM_OFF:
-		ps_mode.wl_ps_mode = WL_PM_AM;
-		break;
-	case WLADM_PM_MAX:
-		ps_mode.wl_ps_mode = WL_PM_MPS;
-		break;
-	case WLADM_PM_FAST:
-		ps_mode.wl_ps_mode = WL_PM_FAST;
-		break;
-	default:
-		return (-1);
-	}
-	return (do_set_ioctl(fd, gbuf, WL_POWER_MODE, &ps_mode,
-	    sizeof (ps_mode)));
-}
-
-/* ARGSUSED */
-static wladm_status_t
-do_set_radio_prop(int fd, wldp_t *gbuf, val_desc_t *vdp, uint_t val_cnt)
-{
-	wladm_radio_t	radio = (wladm_radio_t)vdp->vd_val;
-
-	if (do_set_radio(fd, gbuf, &radio) < 0)
-		return (wladm_wlresult2status(gbuf));
-
-	return (WLADM_STATUS_OK);
-}
-
-static int
-do_set_radio(int fd, wldp_t *gbuf, wladm_radio_t *radio)
-{
-	wl_radio_t r;
-
-	switch (*radio) {
-	case WLADM_RADIO_ON:
-		r = B_TRUE;
-		break;
-	case WLADM_RADIO_OFF:
-		r = B_FALSE;
-		break;
-	default:
-		return (-1);
-	}
-	return (do_set_ioctl(fd, gbuf, WL_RADIO, &r, sizeof (r)));
-}
-
-static int
-do_set_channel(int fd, wldp_t *gbuf, wladm_channel_t *channel)
-{
-	wl_phy_conf_t phy_conf;
-
-	if (*channel > MAX_CHANNEL_NUM)
-		return (-1);
-
-	(void) memset(&phy_conf, 0xff, sizeof (phy_conf));
-	phy_conf.wl_phy_dsss_conf.wl_dsss_channel = *channel;
-
-	return (do_set_ioctl(fd, gbuf, WL_PHY_CONFIG, &phy_conf,
-	    sizeof (phy_conf)));
-}
-
-static int
-do_set_createibss(int fd, wldp_t *gbuf, boolean_t *create_ibss)
-{
-	wl_create_ibss_t cr = (wl_create_ibss_t)(*create_ibss);
-
-	return (do_set_ioctl(fd, gbuf, WL_CREATE_IBSS, &cr, sizeof (cr)));
-}
-
-static void
-generate_essid(wladm_essid_t *essid)
-{
-	srandom(gethrtime());
-	(void) snprintf(essid->we_bytes, WLADM_MAX_ESSID_LEN, "%d", random());
-}
--- a/usr/src/lib/libwladm/common/libwladm.h	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,209 +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 2007 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _LIBWLADM_H
-#define	_LIBWLADM_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <sys/types.h>
-
-/*
- * General libwladm definitions and functions.
- *
- * These interfaces are ON consolidation-private.
- * For documentation, refer to PSARC/2006/623.
- */
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-#define	WLADM_MAX_ESSID_LEN		32	/* per 802.11 spec */
-#define	WLADM_BSSID_LEN			6	/* per 802.11 spec */
-#define	WLADM_STRSIZE			256
-
-#define	WLADM_CONNECT_TIMEOUT_DEFAULT	10
-#define	WLADM_OPT_CREATEIBSS		0x00000001
-#define	WLADM_OPT_NOSCAN		0x00000002
-
-typedef struct wladm_essid {
-	char	we_bytes[WLADM_MAX_ESSID_LEN];
-} wladm_essid_t;
-
-typedef struct wladm_bssid {
-	uint8_t	wb_bytes[WLADM_BSSID_LEN];
-} wladm_bssid_t;
-
-typedef enum {
-	WLADM_SECMODE_NONE = 1,
-	WLADM_SECMODE_WEP
-} wladm_secmode_t;
-
-typedef enum {
-	WLADM_STRENGTH_VERY_WEAK = 1,
-	WLADM_STRENGTH_WEAK,
-	WLADM_STRENGTH_GOOD,
-	WLADM_STRENGTH_VERY_GOOD,
-	WLADM_STRENGTH_EXCELLENT
-} wladm_strength_t;
-
-typedef enum {
-	WLADM_MODE_NONE = 0,
-	WLADM_MODE_80211A,
-	WLADM_MODE_80211B,
-	WLADM_MODE_80211G
-} wladm_mode_t;
-
-typedef enum {
-	WLADM_AUTH_OPEN = 1,
-	WLADM_AUTH_SHARED
-} wladm_auth_t;
-
-typedef enum {
-	WLADM_BSSTYPE_BSS = 1,
-	WLADM_BSSTYPE_IBSS,
-	WLADM_BSSTYPE_ANY
-} wladm_bsstype_t;
-
-typedef enum {
-	WLADM_LINK_STATUS_DISCONNECTED = 1,
-	WLADM_LINK_STATUS_CONNECTED
-} wladm_linkstatus_t;
-
-typedef enum {
-	WLADM_STATUS_OK = 0,
-	WLADM_STATUS_BADARG,
-	WLADM_STATUS_FAILED,
-	WLADM_STATUS_NOTSUP,
-	WLADM_STATUS_ISCONN,
-	WLADM_STATUS_NOTCONN,
-	WLADM_STATUS_NOTFOUND,
-	WLADM_STATUS_BADVAL,
-	WLADM_STATUS_LINKINVAL,
-	WLADM_STATUS_NOMEM,
-	WLADM_STATUS_TIMEDOUT,
-	WLADM_STATUS_PROPRDONLY,
-	WLADM_STATUS_TOOSMALL,
-	WLADM_STATUS_BADVALCNT
-} wladm_status_t;
-
-typedef uint32_t wladm_speed_t;
-typedef	uint32_t wladm_channel_t;
-
-enum {
-	WLADM_WLAN_ATTR_ESSID	= 0x00000001,
-	WLADM_WLAN_ATTR_BSSID	= 0x00000002,
-	WLADM_WLAN_ATTR_SECMODE	= 0x00000004,
-	WLADM_WLAN_ATTR_STRENGTH = 0x00000008,
-	WLADM_WLAN_ATTR_MODE	= 0x00000010,
-	WLADM_WLAN_ATTR_SPEED	= 0x00000020,
-	WLADM_WLAN_ATTR_AUTH	= 0x00000040,
-	WLADM_WLAN_ATTR_BSSTYPE	= 0x00000080,
-	WLADM_WLAN_ATTR_CHANNEL	= 0x00000100
-};
-typedef struct wladm_wlan_attr {
-	uint_t			wa_valid;
-	wladm_essid_t		wa_essid;
-	wladm_bssid_t		wa_bssid;
-	wladm_secmode_t		wa_secmode;
-	wladm_strength_t	wa_strength;
-	wladm_mode_t		wa_mode;
-	wladm_speed_t		wa_speed;
-	wladm_auth_t		wa_auth;
-	wladm_bsstype_t		wa_bsstype;
-	wladm_channel_t		wa_channel;
-} wladm_wlan_attr_t;
-
-enum {
-	WLADM_LINK_ATTR_STATUS	= 0x00000001,
-	WLADM_LINK_ATTR_WLAN	= 0x00000002
-};
-typedef struct wladm_link_attr {
-	uint_t			la_valid;
-	wladm_linkstatus_t	la_status;
-	wladm_wlan_attr_t	la_wlan_attr;
-} wladm_link_attr_t;
-
-#define	WLADM_WEPKEY64_LEN		5 	/* per WEP spec */
-#define	WLADM_WEPKEY128_LEN		13 	/* per WEP spec */
-#define	WLADM_MAX_WEPKEY_LEN		13	/* per WEP spec */
-#define	WLADM_MAX_WEPKEYS		4 	/* MAX_NWEPKEYS */
-#define	WLADM_MAX_WEPKEYNAME_LEN	64
-typedef struct wladm_wep_key {
-	uint_t		wk_idx;
-	uint_t		wk_len;
-	uint8_t		wk_val[WLADM_MAX_WEPKEY_LEN];
-	char		wk_name[WLADM_MAX_WEPKEYNAME_LEN];
-} wladm_wep_key_t;
-
-typedef enum {
-	WLADM_PROP_VAL_CURRENT = 1,
-	WLADM_PROP_VAL_DEFAULT,
-	WLADM_PROP_VAL_MODIFIABLE
-} wladm_prop_type_t;
-
-extern wladm_status_t	wladm_scan(const char *, void *,
-			    boolean_t (*)(void *, wladm_wlan_attr_t *));
-extern wladm_status_t	wladm_connect(const char *, wladm_wlan_attr_t *,
-			    int, void *, uint_t, uint_t);
-extern wladm_status_t	wladm_disconnect(const char *);
-extern wladm_status_t	wladm_get_link_attr(const char *, wladm_link_attr_t *);
-extern wladm_status_t	wladm_walk(void *, boolean_t (*)(void *, const char *));
-extern boolean_t	wladm_is_valid(const char *);
-extern wladm_status_t	wladm_set_prop(const char *, const char *, char **,
-			    uint_t, char **);
-extern wladm_status_t	wladm_walk_prop(const char *, void *,
-			    boolean_t (*)(void *, const char *));
-extern wladm_status_t	wladm_get_prop(const char *, wladm_prop_type_t,
-			    const char *, char **, uint_t *);
-
-extern const char	*wladm_essid2str(wladm_essid_t *, char *);
-extern const char	*wladm_bssid2str(wladm_bssid_t *, char *);
-extern const char	*wladm_secmode2str(wladm_secmode_t *, char *);
-extern const char	*wladm_strength2str(wladm_strength_t *, char *);
-extern const char	*wladm_mode2str(wladm_mode_t *, char *);
-extern const char	*wladm_speed2str(wladm_speed_t *, char *);
-extern const char	*wladm_auth2str(wladm_auth_t *, char *);
-extern const char	*wladm_bsstype2str(wladm_bsstype_t *, char *);
-extern const char	*wladm_linkstatus2str(wladm_linkstatus_t *, char *);
-extern const char	*wladm_status2str(wladm_status_t, char *);
-
-extern wladm_status_t	wladm_str2essid(const char *, wladm_essid_t *);
-extern wladm_status_t	wladm_str2bssid(const char *, wladm_bssid_t *);
-extern wladm_status_t	wladm_str2secmode(const char *, wladm_secmode_t *);
-extern wladm_status_t	wladm_str2strength(const char *, wladm_strength_t *);
-extern wladm_status_t	wladm_str2mode(const char *, wladm_mode_t *);
-extern wladm_status_t	wladm_str2speed(const char *, wladm_speed_t *);
-extern wladm_status_t	wladm_str2auth(const char *, wladm_auth_t *);
-extern wladm_status_t	wladm_str2bsstype(const char *, wladm_bsstype_t *);
-extern wladm_status_t	wladm_str2linkstatus(const char *,
-			    wladm_linkstatus_t *);
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _LIBWLADM_H */
--- a/usr/src/lib/libwladm/common/libwladm_impl.h	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +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 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _LIBWLADM_IMPL_H
-#define	_LIBWLADM_IMPL_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <sys/types.h>
-#include <inet/wifi_ioctl.h>
-
-/*
- * Implementation-private data structures, macros, and constants.
- */
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-/*
- * Map a signal value from 0-15 into an enumerated strength.  Since there are
- * 5 strengths but 16 values, by convention the "middle" strength gets the
- * extra value.  Thus, the buckets are 0-2, 3-5, 6-9, 10-12, and 13-15.
- */
-#define	WLADM_SIGNAL2STRENGTH(signal)				\
-	    (((signal) > 12 ? WLADM_STRENGTH_EXCELLENT :	\
-	    ((signal) > 9 ? WLADM_STRENGTH_VERY_GOOD : 		\
-	    ((signal) > 5 ? WLADM_STRENGTH_GOOD :		\
-	    ((signal) > 2 ? WLADM_STRENGTH_WEAK : WLADM_STRENGTH_VERY_WEAK)))))
-
-/*
- * Convert between an OFDM MHz and a channel number.
- */
-#define	WLADM_OFDM2CHAN(mhz)		(((mhz) - 5000) / 5)
-
-#define	WLADM_CONNECT_POLLRATE		200 /* milliseconds */
-#define	WLADM_CONNECT_DEFAULT_CHANNEL	1
-
-#define	WLADM_MAX_RATES	4
-typedef	struct wladm_rates {
-	uint8_t		wr_rates[WLADM_MAX_RATES];
-	int		wr_cnt;
-} wladm_rates_t;
-
-typedef enum {
-	WLADM_RADIO_ON = 1,
-	WLADM_RADIO_OFF
-} wladm_radio_t;
-
-typedef	enum {
-	WLADM_PM_OFF = 1,
-	WLADM_PM_MAX,
-	WLADM_PM_FAST
-} wladm_powermode_t;
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _LIBWLADM_IMPL_H */
--- a/usr/src/lib/libwladm/common/llib-lwladm	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +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 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*LINTLIBRARY*/
-/*PROTOLIB1*/
-
-#include <libwladm.h>
--- a/usr/src/lib/libwladm/common/mapfile-vers	Wed Mar 21 09:33:24 2007 -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 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-SUNWprivate_1.1 {
-    global:
-	wladm_scan;
-	wladm_connect;
-	wladm_disconnect;
-	wladm_get_link_attr;
-	wladm_walk;
-	wladm_is_valid;
-	wladm_set_prop;
-	wladm_walk_prop;
-	wladm_get_prop;
-	wladm_essid2str;
-	wladm_bssid2str;
-	wladm_secmode2str;
-	wladm_strength2str;
-	wladm_mode2str;
-	wladm_speed2str;
-	wladm_auth2str;
-	wladm_bsstype2str;
-	wladm_linkstatus2str;
-	wladm_status2str;
-	wladm_str2essid;
-	wladm_str2bssid;
-	wladm_str2secmode;
-	wladm_str2strength;
-	wladm_str2mode;
-	wladm_str2speed;
-	wladm_str2auth;
-	wladm_str2bsstype;
-	wladm_str2linkstatus;
-    local:
-	*;
-};
--- a/usr/src/lib/libwladm/i386/Makefile	Wed Mar 21 09:33:24 2007 -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 (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 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-include ../Makefile.com
-
-install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- a/usr/src/lib/libwladm/libwladm.xcl	Wed Mar 21 09:33:24 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +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 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-msgid  "a"
-msgid  "b"
-msgid  "g"
-msgid  "channel"
-msgid  "powermode"
-msgid  "radio"
-msgid  "speed"
-msgid  ""
-msgid  "%.*f"
-msgid  "%d"
-msgid  "%s"
-msgid  "%s%d"
-msgid  "%u"
-msgid  "/"
-msgid  "/dev/%s"
-msgid  "open"
-msgid  "shared"
-msgid  "bss"
-msgid  "ibss"
-msgid  "any"
-msgid  "on"
-msgid  "off"
-msgid  "fast"
-msgid  "max"
-msgid  "wep"
-msgid  "none"
--- a/usr/src/lib/libwladm/sparc/Makefile	Wed Mar 21 09:33:24 2007 -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 (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 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-include ../Makefile.com
-
-install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- a/usr/src/pkgdefs/SUNWcslr/prototype_com	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/pkgdefs/SUNWcslr/prototype_com	Wed Mar 21 09:48:58 2007 -0700
@@ -92,10 +92,8 @@
 f none lib/libintl.so.1 755 root bin
 s none lib/libkstat.so=libkstat.so.1
 f none lib/libkstat.so.1 755 root bin
-f none lib/liblaadm.so.1 755 root bin
 f none lib/libld.so.4 755 root bin
 f none lib/liblddbg.so.4 755 root bin
-f none lib/libmacadm.so.1 755 root bin
 s none lib/libmd.so=libmd.so.1
 f none lib/libmd.so.1 755 root bin
 s none lib/libmd5.so=libmd5.so.1
@@ -151,7 +149,6 @@
 s none lib/libtsol.so=libtsol.so.2
 s none lib/libw.so=libw.so.1
 f none lib/libw.so.1 755 root bin
-f none lib/libwladm.so.1 755 root bin
 s none lib/libumem.so=libumem.so.1
 f none lib/libumem.so.1 0755 root bin
 s none lib/libuuid.so=libuuid.so.1
--- a/usr/src/pkgdefs/etc/exception_list_i386	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/pkgdefs/etc/exception_list_i386	Wed Mar 21 09:48:58 2007 -0700
@@ -93,22 +93,13 @@
 #
 usr/include/libdladm.h		i386
 usr/include/libdladm_impl.h	i386
-usr/include/liblaadm.h		i386
-usr/include/libmacadm.h		i386
-usr/include/libwladm.h		i386
-usr/include/libwladm_impl.h	i386
+usr/include/libdllink.h		i386
+usr/include/libdlaggr.h		i386
+usr/include/libdlwlan.h		i386
+usr/include/libdlwlan_impl.h	i386
 lib/libdladm.so			i386
-lib/liblaadm.so			i386
-lib/libmacadm.so		i386
-lib/libwladm.so			i386
 lib/llib-ldladm.ln		i386
 lib/llib-ldladm			i386
-lib/llib-llaadm.ln		i386
-lib/llib-llaadm			i386
-lib/llib-lmacadm.ln		i386
-lib/llib-lmacadm		i386
-lib/llib-lwladm.ln		i386
-lib/llib-lwladm			i386
 #
 # Installed in the proto area for building utilties dependent on
 # it, but is not shipped.
--- a/usr/src/pkgdefs/etc/exception_list_sparc	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/pkgdefs/etc/exception_list_sparc	Wed Mar 21 09:48:58 2007 -0700
@@ -82,22 +82,13 @@
 #
 usr/include/libdladm.h		sparc
 usr/include/libdladm_impl.h	sparc
-usr/include/liblaadm.h		sparc
-usr/include/libmacadm.h		sparc
-usr/include/libwladm.h		sparc
-usr/include/libwladm_impl.h	sparc
+usr/include/libdllink.h		sparc
+usr/include/libdlaggr.h		sparc
+usr/include/libdlwlan.h		sparc
+usr/include/libdlwlan_impl.h	sparc
 lib/libdladm.so			sparc
-lib/liblaadm.so			sparc
-lib/libmacadm.so		sparc
-lib/libwladm.so			sparc
 lib/llib-ldladm.ln		sparc
 lib/llib-ldladm			sparc
-lib/llib-llaadm.ln		sparc
-lib/llib-llaadm			sparc
-lib/llib-lmacadm.ln		sparc
-lib/llib-lmacadm		sparc
-lib/llib-lwladm.ln		sparc
-lib/llib-lwladm			sparc
 #
 # Installed in the proto area for building those things
 # that are dependent on it. No delivered as part of a pkg.
--- a/usr/src/tools/scripts/bfu.sh	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/tools/scripts/bfu.sh	Wed Mar 21 09:48:58 2007 -0700
@@ -6527,6 +6527,14 @@
 	rm -f $usr/kernel/fs/amd64/xmemfs
 	rm -rf $usr/lib/fs/xmemfs
 
+	#
+	# Remove obsolete libmacadm, liblaadm and libwladm. If this is
+	# a backwards BFU, they will be extracted by cpio.
+	#
+	rm -f $root/lib/libmacadm.so.1
+	rm -f $root/lib/liblaadm.so.1
+	rm -f $root/lib/libwladm.so.1
+
 	# End of pre-archive extraction hacks.
 
 	if [ $diskless = no -a $zone = global ]; then
--- a/usr/src/uts/common/io/dld/dld_drv.c	Wed Mar 21 09:33:24 2007 -0700
+++ b/usr/src/uts/common/io/dld/dld_drv.c	Wed Mar 21 09:48:58 2007 -0700
@@ -513,10 +513,12 @@
 	}
 
 	if ((err = dls_vlan_setzoneid(dhv->dhv_name, dhv->dhv_zid,
-	    dhv->dhv_docheck)) != 0)
+	    dhv->dhv_docheck)) != 0) {
+		dls_vlan_rele(dvp);
 		miocnak(q, mp, 0, err);
-	else
+	} else {
 		miocack(q, mp, 0, 0);
+	}
 }
 
 /*