PSARC 2007/140 libdladm restructure
authoryz147064
Wed, 21 Mar 2007 09:48:58 -0700
changeset 3871 5a1dfce6c5cc
parent 3870 b083fcb4e287
child 3872 a16817aded85
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
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
--- /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);
+	}
 }
 
 /*