PSARC/2002/762 Layered Trusted Solaris
PSARC/2005/060 TSNET: Trusted Networking with Security Labels
PSARC/2005/259 Layered Trusted Solaris Label Interfaces
PSARC/2005/573 Solaris Trusted Extensions for Printing
PSARC/2005/691 Trusted Extensions for Device Allocation
PSARC/2005/723 Solaris Trusted Extensions Filesystem Labeling
PSARC/2006/009 Labeled Auditing
PSARC/2006/155 Trusted Extensions RBAC Changes
PSARC/2006/191 is_system_labeled
6293271 Zone processes should use zone_kcred instead of kcred
6394554 integrate Solaris Trusted Extensions

--HG--
rename : usr/src/cmd/dminfo/Makefile => deleted_files/usr/src/cmd/dminfo/Makefile
rename : usr/src/cmd/dminfo/dminfo.c => usr/src/cmd/allocate/dminfo.c
diff --git a/usr/src/cmd/dminfo/Makefile b/deleted_files/usr/src/cmd/dminfo/Makefile
similarity index 100%
rename from usr/src/cmd/dminfo/Makefile
rename to deleted_files/usr/src/cmd/dminfo/Makefile
diff --git a/usr/src/Makefile.lint b/usr/src/Makefile.lint
index 96414c9..39dcec7 100644
--- a/usr/src/Makefile.lint
+++ b/usr/src/Makefile.lint
@@ -350,6 +350,8 @@
 	lib/libsmbios \
 	lib/libsmedia \
 	lib/libthread \
+	lib/libtsnet \
+	lib/libtsol \
 	lib/libumem \
 	lib/libuutil \
 	lib/libwanboot \
diff --git a/usr/src/Targetdirs b/usr/src/Targetdirs
index b55eb30..2747344 100644
--- a/usr/src/Targetdirs
+++ b/usr/src/Targetdirs
@@ -200,6 +200,7 @@
 	/usr/include/kerberosv5 \
 	/usr/include/libmilter \
 	/usr/include/sasl \
+	/usr/include/tsol \
 	/usr/lib \
 	/usr/lib/abi \
 	/usr/lib/class \
@@ -860,6 +861,10 @@
 $(ROOT)/usr/lib/libthread.so:=		REALPATH=../../lib/libthread.so.1
 $(ROOT)/usr/lib/libthread_db.so.1:=	REALPATH=../../lib/libc_db.so.1
 $(ROOT)/usr/lib/libthread_db.so:=	REALPATH=../../lib/libc_db.so.1
+$(ROOT)/usr/lib/libtsnet.so.1:=		REALPATH=../../lib/libtsnet.so.1
+$(ROOT)/usr/lib/libtsnet.so:=		REALPATH=../../lib/libtsnet.so.1
+$(ROOT)/usr/lib/libtsol.so.2:=		REALPATH=../../lib/libtsol.so.2
+$(ROOT)/usr/lib/libtsol.so:=		REALPATH=../../lib/libtsol.so.2
 $(ROOT)/usr/lib/libumem.so.1:=		REALPATH=../../lib/libumem.so.1
 $(ROOT)/usr/lib/libumem.so:=		REALPATH=../../lib/libumem.so.1
 $(ROOT)/usr/lib/libuuid.so.1:=		REALPATH=../../lib/libuuid.so.1
@@ -960,6 +965,10 @@
 $(ROOT)/usr/lib/llib-lthread:=		REALPATH=../../lib/llib-lthread
 $(ROOT)/usr/lib/llib-lthread_db.ln:=	REALPATH=../../lib/llib-lc_db.ln
 $(ROOT)/usr/lib/llib-lthread_db:=	REALPATH=../../lib/llib-lc_db
+$(ROOT)/usr/lib/llib-ltsnet.ln:=	REALPATH=../../lib/llib-ltsnet.ln
+$(ROOT)/usr/lib/llib-ltsnet:=		REALPATH=../../lib/llib-ltsnet
+$(ROOT)/usr/lib/llib-ltsol.ln:=		REALPATH=../../lib/llib-ltsol.ln
+$(ROOT)/usr/lib/llib-ltsol:=		REALPATH=../../lib/llib-ltsol
 $(ROOT)/usr/lib/llib-lumem.ln:=		REALPATH=../../lib/llib-lumem.ln
 $(ROOT)/usr/lib/llib-lumem:=		REALPATH=../../lib/llib-lumem
 $(ROOT)/usr/lib/llib-luuid.ln:=		REALPATH=../../lib/llib-luuid.ln
@@ -1165,6 +1174,14 @@
 	REALPATH=../../../lib/$(MACH64)/libc_db.so.1
 $(ROOT)/usr/lib/$(MACH64)/libthread_db.so:= \
 	REALPATH=../../../lib/$(MACH64)/libc_db.so.1
+$(ROOT)/usr/lib/$(MACH64)/libtsnet.so.1:= \
+	REALPATH=../../../lib/$(MACH64)/libtsnet.so.1
+$(ROOT)/usr/lib/$(MACH64)/libtsnet.so:= \
+	REALPATH=../../../lib/$(MACH64)/libtsnet.so.1
+$(ROOT)/usr/lib/$(MACH64)/libtsol.so.2:= \
+	REALPATH=../../../lib/$(MACH64)/libtsol.so.2
+$(ROOT)/usr/lib/$(MACH64)/libtsol.so:= \
+	REALPATH=../../../lib/$(MACH64)/libtsol.so.2
 $(ROOT)/usr/lib/$(MACH64)/libumem.so.1:= \
 	REALPATH=../../../lib/$(MACH64)/libumem.so.1
 $(ROOT)/usr/lib/$(MACH64)/libumem.so:= \
@@ -1275,6 +1292,10 @@
 	REALPATH=../../../lib/$(MACH64)/llib-lthread.ln
 $(ROOT)/usr/lib/$(MACH64)/llib-lthread_db.ln:= \
 	REALPATH=../../../lib/$(MACH64)/llib-lc_db.ln
+$(ROOT)/usr/lib/$(MACH64)/llib-ltsnet.ln:= \
+	REALPATH=../../../lib/$(MACH64)/llib-ltsnet.ln
+$(ROOT)/usr/lib/$(MACH64)/llib-ltsol.ln:= \
+	REALPATH=../../../lib/$(MACH64)/llib-ltsol.ln
 $(ROOT)/usr/lib/$(MACH64)/llib-lumem.ln:= \
 	REALPATH=../../../lib/$(MACH64)/llib-lumem.ln
 $(ROOT)/usr/lib/$(MACH64)/llib-luuid.ln:= \
@@ -1402,6 +1423,8 @@
 	/usr/lib/libsendfile.so.1 \
 	/usr/lib/libsocket.so \
 	/usr/lib/libsocket.so.1 \
+	/usr/lib/libsysevent.so \
+	/usr/lib/libsysevent.so.1 \
 	/usr/lib/libtermcap.so \
 	/usr/lib/libtermcap.so.1 \
 	/usr/lib/libtermlib.so \
@@ -1410,8 +1433,10 @@
 	/usr/lib/libthread.so.1 \
 	/usr/lib/libthread_db.so \
 	/usr/lib/libthread_db.so.1 \
-	/usr/lib/libsysevent.so \
-	/usr/lib/libsysevent.so.1 \
+	/usr/lib/libtsnet.so \
+	/usr/lib/libtsnet.so.1 \
+	/usr/lib/libtsol.so \
+	/usr/lib/libtsol.so.2 \
 	/usr/lib/libumem.so \
 	/usr/lib/libumem.so.1 \
 	/usr/lib/libuuid.so \
@@ -1512,6 +1537,10 @@
 	/usr/lib/llib-lthread.ln \
 	/usr/lib/llib-lthread_db \
 	/usr/lib/llib-lthread_db.ln \
+	/usr/lib/llib-ltsnet \
+	/usr/lib/llib-ltsnet.ln \
+	/usr/lib/llib-ltsol \
+	/usr/lib/llib-ltsol.ln \
 	/usr/lib/llib-lumem \
 	/usr/lib/llib-lumem.ln \
 	/usr/lib/llib-luuid \
@@ -1633,6 +1662,10 @@
 	/usr/lib/$(MACH64)/libthread.so.1 \
 	/usr/lib/$(MACH64)/libthread_db.so \
 	/usr/lib/$(MACH64)/libthread_db.so.1 \
+	/usr/lib/$(MACH64)/libtsnet.so \
+	/usr/lib/$(MACH64)/libtsnet.so.1 \
+	/usr/lib/$(MACH64)/libtsol.so \
+	/usr/lib/$(MACH64)/libtsol.so.2 \
 	/usr/lib/$(MACH64)/libumem.so \
 	/usr/lib/$(MACH64)/libumem.so.1 \
 	/usr/lib/$(MACH64)/libuuid.so \
@@ -1688,6 +1721,8 @@
 	/usr/lib/$(MACH64)/llib-ltermlib.ln \
 	/usr/lib/$(MACH64)/llib-lthread.ln \
 	/usr/lib/$(MACH64)/llib-lthread_db.ln \
+	/usr/lib/$(MACH64)/llib-ltsnet.ln \
+	/usr/lib/$(MACH64)/llib-ltsol.ln \
 	/usr/lib/$(MACH64)/llib-lumem.ln \
 	/usr/lib/$(MACH64)/llib-luuid.ln \
 	/usr/lib/$(MACH64)/llib-lxnet.ln \
diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile
index b72d2d2..645eb78 100644
--- a/usr/src/cmd/Makefile
+++ b/usr/src/cmd/Makefile
@@ -17,6 +17,8 @@
 # information: Portions Copyright [yyyy] [name of copyright owner]
 #
 # CDDL HEADER END
+
+
 #
 #
 # Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
@@ -720,7 +722,6 @@
 	auditd		\
 	auditreduce	\
 	auditstat	\
-	dminfo		\
 	praudit		\
 	bsmconv		\
 	bsmrecord	\
diff --git a/usr/src/cmd/allocate/Makefile b/usr/src/cmd/allocate/Makefile
index 6b3055b..53cf843 100644
--- a/usr/src/cmd/allocate/Makefile
+++ b/usr/src/cmd/allocate/Makefile
@@ -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.
@@ -19,8 +18,9 @@
 #
 # CDDL HEADER END
 #
+
 #
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -33,87 +33,123 @@
 ROOTSECLIB =	$(ROOTSEC)/lib
 ROOTDIRS =	$(ROOTSECDEV) $(ROOTSECLIB)
 
-PROG1 =		allocate
-PROG2 =		mkdevmaps mkdevalloc
-PROG3 =		audio_clean
-PROG =		$(PROG1) $(PROG2) $(PROG3)
-DEFILE =	deallocate
-LISTFILE =	list_devices
 RTLCKS =	audio fd0 sr0 st0 st1
-SCRIPTS =	st_clean fd_clean sr_clean
+SCRIPTS =	fd_clean  sr_clean  st_clean
 ALLSCRIPTS =	allscripts.sh
 
-POFILE=		allocate_all.po
-POFILES=	$(OBJS:%.o=%.po) $(ALLSCRIPTS:%.sh=%.po)
+PROGalloc =	allocate
+PROGmkdevalloc =	mkdevalloc
+PROGdminfo =	dminfo
+PROGaudio =	audio_clean
+PROG =		$(PROGalloc) $(PROGmkdevalloc) $(PROGdminfo) $(PROGaudio)
 
-# make DFLAGS=-DDEBUG
+LINKPROGalloc =	deallocate list_devices
+LINKPROGmkdevalloc = mkdevmaps
 
-DFLAGS=
+
+POFILE =	allocate_all.po
+POFILES =	$(OBJS:%.o=%.po) $(ALLSCRIPTS:%.sh=%.po)
+
+DFLAGS +=	-D_REENTRANT
 CPPFLAGS +=	$(DFLAGS)
 
-ROOTPROG =	$(PROG1:%=$(ROOTUSRSBIN)/%) $(PROG2:%=$(ROOTUSRSBIN)/%) \
-		$(PROG3:%=$(ROOTSECLIB)/%)
-ROOTLOCKS=	$(RTLCKS:%=$(ROOTSECDEV)/%)
-ROOTSCRIPTS=	$(SCRIPTS:%=$(ROOTSECLIB)/%)
+ROOTLOCKS =	$(RTLCKS:%=$(ROOTSECDEV)/%)
+ROOTSCRIPTS =	$(SCRIPTS:%=$(ROOTSECLIB)/%)
 
-CLOBBERFILES += $(SCRIPTS)
+ROOTPROG =	$(PROGallocate:%=$(ROOTUSRSBIN)/%) \
+		$(PROGmkdevalloc:%=$(ROOTUSRSBIN)/%) \
+		$(PROGdminfo:%=$(ROOTUSRSBIN)/%) \
+		$(PROGaudio:%=$(ROOTSECLIB)/%)
+ROOTLINKalloc =	$(LINKPROGalloc:%=$(ROOTUSRSBIN)/%)
+ROOTLINKmkdevalloc = $(LINKPROGmkdevalloc:%=$(ROOTUSRSBIN)/%)
+ROOTLINKS =	$(ROOTLINKalloc) $(ROOTLINKmkdevalloc)
 
-allocate :=	POBJS = allocate.o  allocate3.o
-mkdevmaps :=	POBJS = mkdevmaps.o
-mkdevalloc :=	POBJS = mkdevalloc.o
-audio_clean :=	POBJS = audio_clean.o
+PROGallocOBJS =		allocate.o allocate3.o
+PROGmkdevallocOBJS =	mkdevalloc.o
+PROGdminfoOBJS =	dminfo.o
+PROGaudioOBJS =		audio_clean.o
 
-OBJS =		allocate.o allocate3.o audio_clean.o mkdevmaps.o mkdevalloc.o
+OBJS =		$(PROGallocOBJS) \
+		$(PROGmkdevallocOBJS) \
+		$(PROGdminfoOBJS) \
+		$(PROGaudioOBJS)
+
 SRCS =		$(OBJS:%.o=%.c)
 
-FILEMODE=       0755
-DIRMODE=        0755
-OWNER=          root
-GROUP=          sys
-
+$(ROOTUSRSBIN)/% :=	FILEMODE = 555
+$(ROOTUSRSBIN)/allocate :=	FILEMODE = 4555
 $(ROOTUSRSBIN)/% :=     OWNER = root 
 $(ROOTUSRSBIN)/% :=     GROUP = bin 
+$(ROOTSECDEV)/% :=	FILEMODE = 0400
+$(ROOTSECDEV)/% :=	OWNER = root
+$(ROOTSECDEV)/% :=	GROUP = bin
+$(ROOTSECLIB)/% :=	FILEMODE = 0555
+$(ROOTSECLIB)/% :=	OWNER = root
+$(ROOTSECLIB)/% :=	GROUP = sys
 
-$(ROOTUSRSBIN)/allocate := 	FILEMODE = 04755
-$(ROOTUSRSBIN)/deallocate :=	FILEMODE = 04755
-$(ROOTUSRSBIN)/list_devices :=	FILEMODE = 04755
+LAZYLIBS =	$(ZLAZYLOAD) -ltsol -lgen $(ZNOLAZYLOAD)
+lint :=		LDLIBS += -lbsm -lsec -lsecdb -ltsol -lgen
+$(PROGalloc) :=		LDLIBS += -lbsm -lsec -lsecdb $(LAZYLIBS)
+$(PROGmkdevalloc) :=	LDLIBS += -lbsm
+$(PROGdminfo) :=	LDLIBS += -lbsm
+$(PROGaudio) :=		LDLIBS += -lbsm
 
-$(ROOTSECDEV)/% :=		FILEMODE = 0400
-$(ROOTSECDEV)/% :=              OWNER = root
-$(ROOTSECDEV)/% :=              GROUP = bin
-
-$(ROOTSECLIB)/% :=		FILEMODE = 0751
-
-allocate :=	LDLIBS += -lbsm -lsec -lsecdb
+CLOBBERFILES +=	$(SCRIPTS)
 
 .KEEP_STATE:
 
 all :		$(PROG) $(RTLCKS) $(SCRIPTS)
 
-install :	all $(ROOTDIRS) $(ROOTPROG) $(ROOTLOCKS) $(ROOTSCRIPTS)
-		$(RM) $(ROOTUSRSBIN)/$(DEFILE)
-		$(LN) $(ROOTUSRSBIN)/$(PROG1) $(ROOTUSRSBIN)/$(DEFILE)
-		$(RM) $(ROOTUSRSBIN)/$(LISTFILE)
-		$(LN) $(ROOTUSRSBIN)/$(PROG1) $(ROOTUSRSBIN)/$(LISTFILE)
-
-$(PROG) :	$$(POBJS)
-		$(LINK.c) $(POBJS) -o $@ $(LDLIBS)
-		$(POST_PROCESS)
+install :	$(PROG) $(ROOTDIRS) $(ROOTPROG) $(ROOTLOCKS) \
+		$(ROOTSCRIPTS) $(ROOTLINKS)
 
 $(RTLCKS):
 		$(TOUCH) $@
 
-$(ROOTDIRS):
+$(ROOTSECLIB)/%: %.sh
+		$(INS.rename)
+
+$(PROGalloc) :	$(PROGallocOBJS)
+		$(LINK.c) $(PROGallocOBJS) -o $@ $(LDLIBS)
+		$(POST_PROCESS)
+
+$(PROGmkdevalloc) :	$(PROGmkdevallocOBJS)
+			$(LINK.c) $(PROGmkdevallocOBJS) -o $@ $(LDLIBS)
+			$(POST_PROCESS)
+
+$(PROGdminfo) :	$(PROGdminfoOBJS)
+		$(LINK.c) $(PROGdminfoOBJS) -o $@ $(LDLIBS)
+		$(POST_PROCESS)
+
+$(PROGaudio) :	$(PROGaudioOBJS)
+		$(LINK.c) $(PROGaudioOBJS) -o $@ $(LDLIBS)
+		$(POST_PROCESS)
+
+$(ROOTDIRS) :
 		$(INS.dir)
 
 $(ROOTSECDEV)/%: %
 		$(INS.file)
 
 $(ROOTSECLIB)/%: %
+		$(RM) $@
 		$(INS.file)
 
+$(ROOTSECLIB)/audio_clean :	audio_clean
+				$(RM) $@
+				$(INS.file) $(@F)
+
+$(ROOTLINKalloc) :	$(PROGalloc:%=$(ROOTUSRSBIN)/%)
+			$(RM) $@
+			$(LN) $(PROGalloc:%=$(ROOTUSRSBIN)/%) $@
+
+$(ROOTLINKmkdevalloc) :	$(PROGmkdevalloc:%=$(ROOTUSRSBIN)/%)
+			$(RM) $@
+			$(LN) $(PROGmkdevalloc:%=$(ROOTUSRSBIN)/%) $@
+
 $(POFILE):      $(POFILES)
-		$(RM) $@; $(CAT) $(POFILES) > $@; $(RM)  $(POFILES)
+		$(RM) $@
+		$(CAT) $(POFILES) > $@
 
 #
 # Concatenate all the scripts into one before we build the catalogue.
@@ -124,7 +160,8 @@
 		$(CAT) $(SCRIPTS:%=%.sh) > $@
 
 clean :
-		$(RM) $(OBJS) $(RTLCKS) $(ALLSCRIPTS)
+		$(RM) $(PROG) $(RTLCKS) $(OBJS) \
+		$(SCRIPTS) $(ALLSCRIPTS) $(POFILE) $(POFILES)
 
 lint :		lint_SRCS
 
diff --git a/usr/src/cmd/allocate/allocate.c b/usr/src/cmd/allocate/allocate.c
index a2c1c96..36f0050 100644
--- a/usr/src/cmd/allocate/allocate.c
+++ b/usr/src/cmd/allocate/allocate.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,6 +18,7 @@
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
@@ -33,140 +33,207 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-
+#include <ctype.h>
+#include <nss_dbdefs.h>
 #include <sys/types.h>
-
+#include <sys/wait.h>
+#include <tsol/label.h>
+#include <zone.h>
+#include <bsm/devalloc.h>
 #include "allocate.h"
 
 #if !defined(TEXT_DOMAIN)
 #define	TEXT_DOMAIN "SUNW_OST_OSCMD"
 #endif
 
+#define	ALLOC	"allocate"
+#define	DEALLOC	"deallocate"
+#define	LIST	"list_devices"
+
 extern void audit_allocate_argv(int, int, char *[]);
 extern int audit_allocate_record(int);
 
+int system_labeled = 0;
+static int windowing = 0;
+static int wdwmsg(char *name, char *msg);
+
 static void
 usage(int func)
 {
-	char *use[7];
+	if (system_labeled) {
+		char *use[9];
 
-	use[0] = gettext("allocate [-s] [-U uname] [-F] device");
-	use[1] = gettext("allocate [-s] [-U uname] -g dev_type");
-	use[2] = gettext("deallocate [-s] [-F] device");
-	use[3] = gettext("deallocate [-s] -I");
-	use[4] = gettext("list_devices [-s] [-U uid] -l [device]");
-	use[5] = gettext("list_devices [-s] [-U uid] -n [device]");
-	use[6] = gettext("list_devices [-s] [-U uid] -u [device]");
+		use[0] = gettext("allocate [-s] [-w] [-U uname] [-z zonename] "
+		    "[-F] device");
+		use[1] = gettext("allocate [-s] [-w] [-U uname] [-z zonename] "
+		    "[-F] -g dev_type");
+		use[2] = gettext("deallocate [-s] [-w] [-z zonename] "
+		    "[-F] device");
+		use[3] = gettext("deallocate [-s] [-w] [-z zonename] "
+		    "[-F] -g dev_type");
+		use[4] = gettext("deallocate [-s] [-w] [-z zonename] -I");
+		use[5] = gettext("list_devices [-s] [-U uid] [-z zonename] "
+		    "[-a] -l [device]");
+		use[6] = gettext("list_devices [-s] [-U uid] [-z zonename] "
+		    "[-a] -n [device]");
+		use[7] = gettext("list_devices [-s] [-U uid] [-z zonename] "
+		    "[-a] -u [device]");
+		use[8] = gettext("list_devices [-s] -d dev_type");
 
-	switch (func) {
-		case 0:
-			(void) fprintf(stderr, "%s\n%s\n", use[0], use[1]);
-			break;
-		case 1:
-			(void) fprintf(stderr, "%s\n%s\n", use[2], use[3]);
-			break;
-		case 2:
-			(void) fprintf(stderr, "%s\n%s\n%s\n", use[4], use[5],
-			    use[6]);
-			break;
-		default:
-			(void) fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
-				use[0], use[1], use[2], use[3], use[4]);
+		switch (func) {
+			case 0:
+				(void) fprintf(stderr, "%s\n%s\n",
+				    use[0], use[1]);
+				break;
+			case 1:
+				(void) fprintf(stderr, "%s\n%s\n%s\n",
+				    use[2], use[3], use[4]);
+				break;
+			case 2:
+				(void) fprintf(stderr, "%s\n%s\n%s\n%s\n",
+				    use[5], use[6], use[7], use[8]);
+				break;
+			default:
+				(void) fprintf(stderr,
+				    "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
+				    use[0], use[1], use[2], use[3], use[4],
+				    use[5], use[6], use[7], use[8]);
+		}
+	} else {
+		char *use[7];
+
+		use[0] = gettext("allocate [-s] [-U uname] [-F] device");
+		use[1] = gettext("allocate [-s] [-U uname] -g dev_type");
+		use[2] = gettext("deallocate [-s] [-F] device");
+		use[3] = gettext("deallocate [-s] -I");
+		use[4] = gettext("list_devices [-s] [-U uid] -l [device]");
+		use[5] = gettext("list_devices [-s] [-U uid] -n [device]");
+		use[6] = gettext("list_devices [-s] [-U uid] -u [device]");
+
+		switch (func) {
+			case 0:
+				(void) fprintf(stderr, "%s\n%s\n",
+				    use[0], use[1]);
+				break;
+			case 1:
+				(void) fprintf(stderr, "%s\n%s\n",
+				    use[2], use[3]);
+				break;
+			case 2:
+				(void) fprintf(stderr, "%s\n%s\n%s\n",
+				    use[4], use[5], use[6]);
+				break;
+			default:
+				(void) fprintf(stderr,
+				    "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
+					use[0], use[1], use[2], use[3], use[4],
+					use[5], use[6]);
+		}
 	}
 	exit(1);
 }
 
-static void
+void
 print_error(int error, char *name)
 {
-	char *msg;
+	char	*msg;
+	char	msgbuf[200];
 
 	switch (error) {
-	case SYSERROR:
-		msg = gettext("Unknown System error.");
-		break;
-	case IMPORT_ERR:
-		msg = gettext(
-		    "User lacks authorization required for this operation.");
-		break;
-	case NODAENT:
-		msg = gettext(
-		    "No device allocate file entry for specified device.");
-		break;
-	case NODMAPENT:
-		msg = gettext(
-		    "No device maps file entry for specified device.");
-		break;
-	case DACLCK:
-		msg = gettext("Concurrent operations for specified device, "
-		    "try later.");
-		break;
-	case DACACC:
-		msg = gettext(
-		    "Can't access DAC file for the device specified.");
-		break;
-	case DEVLST:
-		msg = gettext(
-		    "Could not use device list for the device specified.");
-		break;
-	case NALLOCU:
+	case ALLOCUERR:
 		msg = gettext("Specified device is allocated to another user.");
 		break;
-	case NOTAUTH:
-		msg = gettext("Not authorized for specified operation.");
+	case CHOWNERR:
+		msg = gettext("Failed to chown.");
 		break;
-	case CNTFRC:
-		msg = gettext("Can't force deallocate specified device.");
+	case CLEANERR:
+		msg = gettext("Unable to clean up device.");
 		break;
-	case CNTDEXEC:
+	case CNTDEXECERR:
 		msg = gettext(
 		    "Can't exec device-clean program for specified device.");
 		break;
-	case NO_DEVICE:
-		msg = gettext(
-		    "Can't find a device of type requested to allocate.");
+	case CNTFRCERR:
+		msg = gettext("Can't force deallocate specified device.");
 		break;
-	case DSPMISS:
+	case DACACCERR:
+		msg = gettext(
+		    "Can't access DAC file for the device specified.");
+		break;
+	case DAOFFERR:
+		msg = gettext(
+		    "Device allocation feature is not activated "
+		    "on this system.");
+		break;
+	case DAUTHERR:
+		msg = gettext("Device not allocatable.");
+		break;
+	case DEFATTRSERR:
+		msg = gettext("No default attributes for specified "
+		    "device type.");
+		break;
+	case DEVLKERR:
+		msg = gettext("Concurrent operations for specified device, "
+		    "try later.");
+		break;
+	case DEVLONGERR:
+		msg = gettext("Device name is too long.");
+		break;
+	case DEVNALLOCERR:
+		msg = gettext("Device not allocated.");
+		break;
+	case DEVNAMEERR:
+		msg = gettext("Device name error.");
+		break;
+	case DEVSTATEERR:
+		msg = gettext("Device specified is in allocate error state.");
+		break;
+	case DEVZONEERR:
+		msg = gettext("Can't find name of the zone to which "
+		    "device is allocated.");
+		break;
+	case DSPMISSERR:
 		msg = gettext(
 		    "Device special file(s) missing for specified device.");
 		break;
-	case ALLOCERR:
-		msg = gettext("Device specified is in allocate error state.");
+	case LABELRNGERR:
+		msg = gettext(
+		    "Operation inconsistent with device's label range.");
 		break;
-	case CHOWN_PERR:
-		msg = gettext("Process lacks privilege required to chown().");
+	case LOGINDEVPERMERR:
+		msg = gettext("Device controlled by logindevperm(4)");
 		break;
-	case ALLOC:
+	case NODAERR:
+		msg = gettext("No entry for specified device.");
+		break;
+	case NODMAPERR:
+		msg = gettext("No entry for specified device.");
+		break;
+	case PREALLOCERR:
 		msg = gettext("Device already allocated.");
 		break;
-	case ALLOC_OTHER:
-		msg = gettext("Device allocated to another user.");
+	case SETACLERR:
+		msg = gettext("Failed to set ACL.");
 		break;
-	case NALLOC:
-		msg = gettext("Device not allocated.");
+	case UAUTHERR:
+		msg = gettext(
+		    "User lacks authorization required for this operation.");
 		break;
-	case AUTHERR:
-		msg = gettext("Device not allocatable.");
-		break;
-	case CLEAN_ERR:
-		msg = gettext("Unable to clean up the device.");
-		break;
-	case SETACL_PERR:
-		msg = gettext("Process lacks privilege required to set ACL.");
-		break;
-	case DEVNAME_ERR:
-		msg = gettext("Error forming device name.");
-		break;
-	case DEVNAME_TOOLONG:
-		msg = gettext("Device name is too long.");
+	case ZONEERR:
+		msg = gettext("Failed to configure device in zone.");
 		break;
 	default:
 		msg = gettext("Unknown error code.");
 		break;
 	}
 
-	(void) fprintf(stderr, "%s: %s\n", name, msg);
-	(void) fflush(stderr);
+	if (windowing) {
+		(void) snprintf(msgbuf, sizeof (msgbuf), "%s: %s\n", name, msg);
+		(void) wdwmsg(name, msgbuf);
+	} else {
+		(void) fprintf(stderr, "%s: %s\n", name, msg);
+		(void) fflush(stderr);
+	}
 }
 
 char *newenv[] = {"PATH=/usr/bin:/usr/sbin",
@@ -193,16 +260,21 @@
 int
 main(int argc, char *argv[], char *envp[])
 {
-	char	*name, *env;
-	int	func = -1, optflg = 0, error = 0, c;
-	uid_t	uid = getuid();
-	char	*uname = NULL, *device = NULL;
-	struct passwd *pw_ent;
-	int env_num = 1;	/* PATH= is 0 entry */
+	char		*name, *env;
+	int		func = -1, optflg = 0, error = 0, c;
+	zoneid_t	zoneid;
+	uid_t		uid;
+	char		*uname = NULL, *device = NULL, *zonename = NULL;
+	char		*zname;
+	char		pw_buf[NSS_BUFLEN_PASSWD];
+	struct passwd	pw_ent;
+	int 		env_num = 1;	/* PATH= is 0 entry */
 
 	(void) setlocale(LC_ALL, "");
 	(void) textdomain(TEXT_DOMAIN);
 
+	system_labeled = is_system_labeled();
+
 	/*
 	 * get all enviroment variables
 	 * which affect on internationalization.
@@ -234,43 +306,75 @@
 	else
 		name++;
 
-	if (strcmp(name, "allocate") == 0)
+	if (strcmp(name, ALLOC) == 0)
 		func = 0;
-	else if (strcmp(name, "deallocate") == 0)
+	else if (strcmp(name, DEALLOC) == 0)
 		func = 1;
-	else if (strcmp(name, "list_devices") == 0)
+	else if (strcmp(name, LIST) == 0)
 		func = 2;
-	else {
-		usage(ALL);
-	}
+	else
+		usage(-1);
 
 	audit_allocate_argv(func, argc, argv);
 
+	if (system_labeled) {
+		/*
+		 * allocate, deallocate, list_devices run in
+		 * global zone only.
+		 */
+		zoneid = getzoneid();
+		if (zoneid != GLOBAL_ZONEID)
+			exit(GLOBALERR);
+		zname = GLOBAL_ZONENAME;
+		/*
+		 * check if device allocation is activated.
+		 */
+		if (da_is_on() == 0) {
+			(void) fprintf(stderr, "%s%s",
+			    gettext("Turn device allocation on"),
+			    gettext(" to use this feature.\n"));
+			exit(DAOFFERR);
+		}
+	}
+
 	if (func == 0) {	/* allocate */
-		while ((c = getopt(argc, argv, "sU:Fg")) != -1) {
+		while ((c = getopt(argc, argv, "gswz:FU:")) != -1) {
 			switch (c) {
+			case 'g':
+				optflg |= TYPE;
+				break;
 			case 's':
 				optflg |= SILENT;
 				break;
+			case 'w':
+				if (system_labeled) {
+					optflg |= WINDOWING;
+					windowing = 1;
+				} else {
+					usage(func);
+				}
+				break;
+			case 'z':
+				if (system_labeled) {
+					optflg |= ZONENAME;
+					zonename = optarg;
+				} else {
+					usage(func);
+				}
+				break;
+			case 'F':
+				optflg |= FORCE;
+				break;
 			case 'U':
 				optflg |= USERNAME;
 				uname = optarg;
 				break;
-			case 'g':
-				optflg |= TYPE;
-				break;
-			case 'F':
-				optflg |= FORCE;
-				break;
 			case '?':
 			default :
 				usage(func);
 			}
 		}
 
-		if ((optflg & TYPE) && (optflg & FORCE))
-			usage(func);
-
 		/*
 		 * allocate(1) must be supplied with one device argument
 		 */
@@ -282,11 +386,33 @@
 	}
 
 	else if (func == 1) {	/* deallocate */
-		while ((c = getopt(argc, argv, "sFI")) != -1) {
+		while ((c = getopt(argc, argv, "gswz:FI")) != -1) {
 			switch (c) {
+			case 'g':
+				if (system_labeled)
+					optflg |= TYPE;
+				else
+					usage(func);
+				break;
 			case 's':
 				optflg |= SILENT;
 				break;
+			case 'w':
+				if (system_labeled) {
+					optflg |= WINDOWING;
+					windowing = 1;
+				} else {
+					usage(func);
+				}
+				break;
+			case 'z':
+				if (system_labeled) {
+					optflg |= ZONENAME;
+					zonename = optarg;
+				} else {
+					usage(func);
+				}
+				break;
 			case 'F':
 				optflg |= FORCE;
 				break;
@@ -302,6 +428,9 @@
 		if ((optflg & FORCE) && (optflg & FORCE_ALL))
 			usage(func);
 
+		if (system_labeled && ((optflg & FORCE_ALL) && (optflg & TYPE)))
+			usage(func);
+
 		/*
 		 * deallocate(1) must be supplied with one device
 		 * argument unless the '-I' argument is supplied
@@ -320,35 +449,86 @@
 	}
 
 	else if (func == 2) {	/* list_devices */
-		while ((c = getopt(argc, argv, "sU:lnu")) != -1) {
+		while ((c = getopt(argc, argv, "adlnsuwz:U:")) != -1) {
 			switch (c) {
+			case 'a':
+				if (system_labeled) {
+					/*
+					 * list auths, cleaning programs,
+					 * labels.
+					 */
+					optflg |= LISTATTRS;
+				} else {
+					usage(func);
+				}
+				break;
+			case 'd':
+				if (system_labeled) {
+					/*
+					 * list devalloc_defaults
+					 */
+					optflg |= LISTDEFS;
+				} else {
+					usage(func);
+				}
+				break;
+			case 'l':
+				optflg |= LISTALL;
+				break;
+			case 'n':
+				optflg |= LISTFREE;
+				break;
 			case 's':
 				optflg |= SILENT;
 				break;
+			case 'u':
+				optflg |= LISTALLOC;
+				break;
+			case 'w':
+				if (system_labeled) {
+					/*
+					 * Private interface for use by
+					 * list_devices GUI
+					 */
+					optflg |= WINDOWING;
+				} else {
+					usage(func);
+				}
+				break;
+			case 'z':
+				if (system_labeled) {
+					optflg |= ZONENAME;
+					zonename = optarg;
+				} else {
+					usage(func);
+				}
+				break;
 			case 'U':
 				optflg |= USERID;
 				uid = atoi(optarg);
 				break;
-			case 'l':
-				optflg |= LIST;
-				break;
-			case 'n':
-				optflg |= FREE;
-				break;
-			case 'u':
-				optflg |= CURRENT;
-				break;
 			case '?':
 			default :
 				usage(func);
 			}
 		}
 
-		if (((optflg & LIST) && (optflg & FREE)) ||
-		    ((optflg & LIST) && (optflg & CURRENT)) ||
-		    ((optflg & FREE) && (optflg & CURRENT)) ||
-		    (!(optflg & (LIST | FREE | CURRENT))))
+		if (system_labeled) {
+			if (((optflg & LISTALL) && (optflg & LISTFREE)) ||
+			    ((optflg & LISTALL) && (optflg & LISTALLOC)) ||
+			    ((optflg & LISTFREE) && (optflg & LISTALLOC)) ||
+			    ((optflg & LISTDEFS) &&
+			    (optflg & (LISTATTRS | LISTALL | LISTFREE |
+			    LISTALLOC | USERID | WINDOWING | ZONENAME))) ||
+			    (!(optflg & (LISTALL | LISTFREE | LISTALLOC |
+			    LISTDEFS | WINDOWING))))
+				usage(func);
+		} else if (((optflg & LISTALL) && (optflg & LISTFREE)) ||
+		    ((optflg & LISTALL) && (optflg & LISTALLOC)) ||
+		    ((optflg & LISTFREE) && (optflg & LISTALLOC)) ||
+		    (!(optflg & (LISTALL | LISTFREE | LISTALLOC)))) {
 			usage(func);
+		}
 
 		/*
 		 * list_devices(1) takes an optional device argument
@@ -363,31 +543,47 @@
 	}
 
 	if (optflg & USERNAME) {
-		if ((pw_ent = getpwnam(uname)) == NULL) {
-			(void) fprintf(stderr, gettext(
-			    "Invalid user name -- %s -- \n"), uname);
+		if (getpwnam_r(uname, &pw_ent, pw_buf, sizeof (pw_buf)) ==
+		    NULL) {
+			(void) fprintf(stderr,
+			    gettext("Invalid user name -- %s -- \n"), uname);
 			exit(1);
 		}
-		uid = pw_ent->pw_uid;
-	}
-
-	if (optflg & USERID) {
-		if ((pw_ent = getpwuid(uid)) == NULL) {
-			(void) fprintf(stderr, gettext(
-			    "Invalid user ID -- %d -- \n"), uid);
+		uid = pw_ent.pw_uid;
+	} else if (optflg & USERID) {
+		if (getpwuid_r(uid, &pw_ent, pw_buf, sizeof (pw_buf)) == NULL) {
+			(void) fprintf(stderr,
+			    gettext("Invalid user ID -- %d -- \n"), uid);
 			exit(1);
 		}
-		uid = pw_ent->pw_uid;
+		uid = pw_ent.pw_uid;
+	} else {
+		/*
+		 * caller's uid is the default if no user specified.
+		 */
+		uid = getuid();
 	}
 
-	if (func == 0) {
-		error = allocate(optflg, uid, device);
-	} else if (func == 1) {
-		error = deallocate(optflg, uid, device);
-	} else if (func == 2) {
-		error = list_devices(optflg, uid, device);
+	/*
+	 * global zone is the default if no zonename specified.
+	 */
+	if (zonename == NULL) {
+		zonename = zname;
+	} else {
+		if (zone_get_id(zonename, &zoneid) != 0) {
+			(void) fprintf(stderr,
+			    gettext("Invalid zone name -- %s -- \n"), zonename);
+			exit(1);
+		}
 	}
 
+	if (func == 0)
+		error = allocate(optflg, uid, device, zonename);
+	else if (func == 1)
+		error = deallocate(optflg, uid, device, zonename);
+	else if (func == 2)
+		error = list_devices(optflg, uid, device, zonename);
+
 	(void) audit_allocate_record(error);
 
 	if (error) {
@@ -398,3 +594,41 @@
 
 	return (0);
 }
+
+/*
+ * Display error message via /etc/security/lib/wdwmsg script
+ */
+static int
+wdwmsg(char *name, char *msg)
+{
+	pid_t child_pid;
+	pid_t wait_pid;
+	int child_status;
+
+	/* Fork a child */
+	switch (child_pid = fork()) {
+	case -1:	/* FAILURE */
+		return (-1);
+		break;
+
+	case 0:		/* CHILD */
+		(void) execl("/etc/security/lib/wdwmsg", "wdwmsg", msg,
+		    name, "OK", NULL);
+		/* If exec failed, send message to stderr */
+		(void) fprintf(stderr, "%s", msg);
+		return (-1);
+
+	default:	/* PARENT */
+		/* Wait for child to exit */
+		wait_pid = waitpid(child_pid, &child_status, 0);
+		if ((wait_pid < 0) && (errno == ECHILD))
+			return (0);
+		if ((wait_pid < 0) || (wait_pid != child_pid))
+			return (-1);
+		if (WIFEXITED(child_status))
+			return (WEXITSTATUS(child_status));
+		if (WIFSIGNALED(child_status))
+			return (WTERMSIG(child_status));
+		return (0);
+	}
+}
diff --git a/usr/src/cmd/allocate/allocate.h b/usr/src/cmd/allocate/allocate.h
index 29f222a..f6a7956 100644
--- a/usr/src/cmd/allocate/allocate.h
+++ b/usr/src/cmd/allocate/allocate.h
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,6 +18,7 @@
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
@@ -34,59 +34,58 @@
 #endif
 
 /* Option Flags */
-#define	SILENT		0001	/* -s */
-#define	USERID		0002	/* -U <uid> for list_devices(1) */
-#define	LIST		0004	/* -l */
-#define	FREE		0010	/* -n */
-#define	CURRENT 	0020	/* -u */
-#define	FORCE		0040	/* -F */
-#define	FORCE_ALL 	0100	/* -I */
-#define	TYPE		0200	/* -g */
-#define	USERNAME	0400	/* -U <username> for allocate(1) */
+#define	LISTATTRS	0x00000001	/* -a */
+#define	LISTDEFS	0x00000002	/* -d */
+#define	TYPE		0x00000004	/* -g */
+#define	LISTALL		0x00000008	/* -l */
+#define	LISTFREE	0x00000010	/* -n */
+#define	SILENT		0x00000020	/* -s */
+#define	LISTALLOC 	0x00000040	/* -u */
+#define	WINDOWING	0x00000080	/* -w */
+#define	ZONENAME	0x00000100	/* -z */
+#define	BOOT		0x00000200	/* -B */
+#define	FORCE		0x00000400	/* -F */
+#define	FORCE_ALL 	0x00000800	/* -I */
+#define	USERID		0x00001000	/* -U for list_devices */
+#define	USERNAME	0x00002000	/* -U for allocate */
 
 /* Misc. */
 
-#define	ALL	-1
+#define	CLEAN_MOUNT		11	/* Also defined in disk_clean.sh */
 
-/* Error returns start at 4 */
-#define	SYSERROR	4
-#define	DACLCK		5
-#define	DACACC		6
-#define	DEVLST		7
-#define	NALLOCU		8
-#define	NOTAUTH		9
-#define	CNTFRC		10
-#define	CNTDEXEC	11
-#define	NO_DEVICE	12
-#define	DSPMISS		13
-#define	ALLOCERR	14
-#define	IMPORT_ERR	15
-#define	NODAENT		16
-#define	NODMAPENT	17
-#define	SETACL_PERR	18
-#define	CHOWN_PERR	19
-#define	ALLOC		20
-#define	ALLOC_OTHER	21
-#define	NALLOC		22
-#define	AUTHERR		23
-#define	CLEAN_ERR	24
-#define	DEVNAME_ERR	25
-#define	DEVNAME_TOOLONG	26
+#define	ALLOCUERR		1
+#define	CHOWNERR		2
+#define	CLEANERR		3
+#define	CNTDEXECERR		4
+#define	CNTFRCERR		5
+#define	DACACCERR		6
+#define	DAOFFERR		7
+#define	DAUTHERR		8
+#define	DEFATTRSERR		9
+#define	DEVLKERR		10
+#define	DEVLONGERR		11
+#define	DEVNALLOCERR		12
+#define	DEVNAMEERR		13
+#define	DEVSTATEERR		14
+#define	DEVZONEERR		15
+#define	DSPMISSERR		16
+#define	GLOBALERR		17
+#define	LABELRNGERR		18
+#define	LOGINDEVPERMERR		19
+#define	NODAERR			20
+#define	NODMAPERR		21
+#define	PREALLOCERR		22
+#define	SETACLERR		23
+#define	UAUTHERR		24
+#define	ZONEERR			25
 
-/* Tunable Parameters */
-#define	DEV_DIR		"/dev"
-#define	DAC_DIR		"/etc/security/dev"
-#define	SECLIB		"/etc/security/lib"
-#define	ALLOC_MODE	0600
-#define	DEALLOC_MODE    0000
 #define	ALLOC_ERR_MODE  0100
-#define	ALLOC_UID	(uid_t)0	/* root */
-#define	ALLOC_GID	(gid_t)1	/* other */
+#define	ALLOC_INVALID	0700
 
 /* Functions */
-extern int allocate(int optflg, uid_t uid, char *device);
-extern int deallocate(int optflg, uid_t uid, char *device);
-extern int list_devices(int optflg, uid_t uid, char *device);
+extern int allocate(int optflg, uid_t uid, char *device, char *zonename);
+extern int deallocate(int optflg, uid_t uid, char *device, char *zonename);
+extern int list_devices(int optflg, uid_t uid, char *device, char *zonename);
 
 #ifdef	__cplusplus
 }
diff --git a/usr/src/cmd/allocate/allocate3.c b/usr/src/cmd/allocate/allocate3.c
index 1e24722..7b4ef26 100644
--- a/usr/src/cmd/allocate/allocate3.c
+++ b/usr/src/cmd/allocate/allocate3.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,6 +18,7 @@
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
@@ -38,11 +38,16 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <strings.h>
 #include <unistd.h>
-
 #include <bsm/devices.h>
-#include <bsm/audit_uevents.h>
-
+#include <sys/acl.h>
+#include <tsol/label.h>
+#include <syslog.h>
+#include <limits.h>
+#include <user_attr.h>
+#include <secdb.h>
+#include <sys/mkdev.h>
 #include <sys/acl.h>
 #include <sys/file.h>
 #include <sys/procfs.h>
@@ -52,198 +57,510 @@
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/wait.h>
-
+#include <utime.h>
+#include <libgen.h>
+#include <zone.h>
+#include <nss_dbdefs.h>
+#include <bsm/devalloc.h>
 #include "allocate.h"
 
-#ifdef	DEBUG
+extern void print_error(int, char *);
+
+#if	defined(DEBUG) || defined(lint)
 #define	dprintf(s, a) (void) fprintf(stderr, s, a)
 #define	dperror(s) perror(s)
 #else	/* !DEBUG */
-#define	dprintf(s, a)
-#define	dperror(s)
+#define	dprintf(s, a)	0
+#define	dperror(s)	0
 #endif	/* DEBUG */
 
-#define	EXIT(number) { \
-	if (optflg & FORCE) \
-		error = number; \
-	else \
-		return (number); \
-}
-
+#define	DEV_ERRORED(sbuf)	(((sbuf).st_mode & ~S_IFMT) == ALLOC_ERR_MODE)
+#define	DEV_INVALID(sbuf)	(((sbuf).st_mode & ~S_IFMT) == ALLOC_INVALID)
 #define	DEV_ALLOCATED(sbuf)	((sbuf).st_uid != ALLOC_UID || \
-				((sbuf).st_mode & ~S_IFMT) == ALLOC_MODE)
+			!(((sbuf).st_mode & ~S_IFMT) == DEALLOC_MODE || \
+			DEV_ERRORED(sbuf) || DEV_INVALID(sbuf)))
 
+#define	ALLOC_CLEAN		"-A"
+#define	DEALLOC_CLEAN		"-D"
+#define	DAC_DIR			"/etc/security/dev"
 #define	DEVICE_AUTH_SEPARATOR	","
-#define	PROCFS	"/proc/"
+#define	LOCALDEVICE		"/dev/console"
+#define	PROCFS			"/proc/"
+#define	SFF_NO_ERROR		0x1
+
+#define	ALLOC_BY_NONE		-1
+#define	CHECK_DRANGE		1
+#define	CHECK_URANGE		2
+#define	CHECK_ZLABEL		3
 
 extern void audit_allocate_list(char *);
 extern void audit_allocate_device(char *);
 
+extern int	system_labeled;
 extern char	*newenv[];
 
+struct state_file {
+	int	sf_flags;
+	char	sf_path[MAXPATHLEN];
+};
+
+struct file_info {
+	struct stat	fi_stat;
+	char		*fi_message;
+};
+
+struct zone_path {
+	int	count;
+	char	**path;
+};
+
+struct devnames {
+	char **dnames;
+};
+
+static int _dev_file_name(struct state_file *, devmap_t *);
+static int lock_dev(char *);
+static int _check_label(devalloc_t *, char *, uid_t, int);
+static int create_znode(char *, struct zone_path *, devmap_t *);
+static int remove_znode(char *, devmap_t *);
+static int update_device(char **, char *, int);
+
 /*
- * Checks if the specified user has any of the authorizations in the
- * list of authorizations
+ * checks if the invoking user is local to the device
  */
-
-static int
-is_authorized(char *auth_list, uid_t uid)
+/*ARGSUSED*/
+int
+_is_local(uid_t uid)
 {
-	char	*auth;
-	struct passwd *pw;
+	struct stat	statbuf;
 
-	pw = getpwuid(uid);
-	if (pw == NULL) {
-		dprintf("Can't get user info for uid=%d\n", (int)uid);
+	if (stat(LOCALDEVICE, &statbuf) == 0 &&
+	    statbuf.st_uid == uid)
+		return (1);
+
+	return (0);
+}
+
+/*
+ * Checks if the user with the specified uid has the specified authorization
+ */
+int
+_is_authorized(char *auths, uid_t uid)
+{
+	char		*dcp, *authlist, *lasts;
+	char		pw_buf[NSS_BUFLEN_PASSWD];
+	struct passwd	pw_ent;
+
+	/*
+	 * first, the easy cases
+	 */
+	if (strcmp(auths, "@") == 0)
+		return (1);
+	if (strcmp(auths, "*") == 0)
+		return (ALLOC_BY_NONE);
+	if (getpwuid_r(uid, &pw_ent, pw_buf, sizeof (pw_buf)) == NULL)
 		return (0);
+	if (strpbrk(auths, DEVICE_AUTH_SEPARATOR) == NULL)
+		return (chkauthattr(auths, pw_ent.pw_name));
+	authlist = strdup(auths);
+	if (authlist == NULL)
+		return (0);
+	for (dcp = authlist;
+	    (dcp = strtok_r(dcp, DEVICE_AUTH_SEPARATOR, &lasts)) != NULL;
+	    dcp = NULL) {
+		if (chkauthattr(dcp, pw_ent.pw_name))
+			break;
 	}
+	free(authlist);
 
-	auth = strtok(auth_list, DEVICE_AUTH_SEPARATOR);
-	while (auth != NULL) {
-		if (chkauthattr(auth, pw->pw_name))
-			return (1);
-		auth = strtok(NULL, DEVICE_AUTH_SEPARATOR);
-	}
-	return (0);
+	return (dcp != NULL);
 }
 
-static int
-check_devs(char *list)
+/*
+ * Checks if the specified user has authorization for the device
+ */
+int
+_is_dev_authorized(devalloc_t *da, uid_t uid)
 {
-	char	*file;
+	int	ares;
+	char	*auth_list, *dcp, *subauth = NULL;
 
-	file = strtok(list, " ");
-	while (file != NULL) {
+	auth_list = da->da_devauth;
+	if (auth_list == NULL)
+		return (0);
+	dcp = strpbrk(auth_list, KV_TOKEN_DELIMIT);
+	if (dcp == NULL)
+		return (_is_authorized(auth_list, uid));
+	if (_is_local(uid)) {
+		/* the local authorization is before the separator */
+		ares = dcp - auth_list;
+		subauth = malloc(ares + 1);
+		if (subauth == NULL)
+			return (0);
+		(void) strlcpy(subauth, auth_list, (ares + 1));
+		auth_list = subauth;
+	} else
+		auth_list = dcp + 1;
+	ares = _is_authorized(auth_list, uid);
+	if (subauth != NULL)
+		free(subauth);
 
-		if (access(file, F_OK) == -1) {
-			dprintf("Unable to access file %s\n", file);
-			return (-1);
+	return (ares);
+}
+
+int
+check_devs(devmap_t *dm)
+{
+	int	status = 0;
+	char	**file;
+
+	if (dm->dmap_devarray == NULL)
+		return (NODMAPERR);
+	for (file = dm->dmap_devarray; *file != NULL; file++) {
+		if ((status = access(*file, F_OK)) == -1) {
+			dprintf("Unable to access file %s\n", *file);
+			break;
 		}
-		file = strtok(NULL, " ");
 	}
+
+	return (status);
+}
+
+int
+print_da_defs(da_defs_t *da_defs)
+{
+	char	optbuf[BUFSIZ];
+	char	*p = NULL;
+
+	if (da_defs->devopts == NULL) {
+		dprintf("No default attributes for %s\n", da_defs->devtype);
+		return (DEFATTRSERR);
+	}
+	(void) printf("dev_type=%s\n", da_defs->devtype);
+	if (_kva2str(da_defs->devopts, optbuf, sizeof (optbuf), KV_ASSIGN,
+	    KV_TOKEN_DELIMIT) == 0) {
+		if (p = rindex(optbuf, ':'))
+			*p = '\0';
+		(void) printf("\t%s\n", optbuf);
+	}
+
 	return (0);
 }
 
-static void
-print_dev(devmap_t *dev_list)
+void
+print_dev_attrs(int optflag, devalloc_t *da, devmap_t *dm,
+    struct file_info *fip)
 {
-	char	*file;
+	char	*p = NULL;
+	char	optbuf[BUFSIZ];
 
-	(void) printf(gettext("device: %s "), dev_list->dmap_devname);
-	(void) printf(gettext("type: %s "), dev_list->dmap_devtype);
-	(void) printf(gettext("files: "));
+	(void) printf("device=%s%s", dm->dmap_devname, KV_DELIMITER);
+	(void) printf("type=%s%s", dm->dmap_devtype, KV_DELIMITER);
+	(void) printf("auths=%s%s",
+	    (da->da_devauth ? da->da_devauth : ""), KV_DELIMITER);
+	(void) printf("clean=%s%s",
+	    (da->da_devexec ? da->da_devexec : ""), KV_DELIMITER);
+	if (da->da_devopts != NULL) {
+		if (_kva2str(da->da_devopts, optbuf, sizeof (optbuf),
+		    KV_ASSIGN, KV_TOKEN_DELIMIT) == 0) {
+			if (p = rindex(optbuf, ':'))
+				*p = '\0';
+			(void) printf("%s", optbuf);
+		}
+	}
+	(void) printf("%s", KV_DELIMITER);
+	if (optflag & WINDOWING) {
+		if (DEV_INVALID(fip->fi_stat))
+			(void) printf("owner=/INVALID:%s%s", fip->fi_message,
+			    KV_DELIMITER);
+		else if (DEV_ERRORED(fip->fi_stat))
+			(void) printf("owner=/ERROR%s", KV_DELIMITER);
+		else if (!DEV_ALLOCATED(fip->fi_stat))
+			(void) printf("owner=/FREE%s", KV_DELIMITER);
+		else
+			(void) printf("owner=%ld%s", fip->fi_stat.st_uid,
+			    KV_DELIMITER);
+	}
+	(void) printf("files=%s", dm->dmap_devlist);
+	(void) printf("\n");
+}
 
-	file = strtok(dev_list->dmap_devlist, " ");
-	while (file != NULL) {
-		(void) printf("%s ", file);
-		file = strtok(NULL, " ");
+void
+print_dev(devmap_t *dm)
+{
+	char	**file;
+
+	(void) printf(gettext("device: %s "), dm->dmap_devname);
+	(void) printf(gettext("type: %s "), dm->dmap_devtype);
+	(void) printf(gettext("files:"));
+	file = dm->dmap_devarray;
+	if (file != NULL) {
+		for (; *file != NULL; file++)
+			(void) printf(" %s", *file);
 	}
 	(void) printf("\n");
 }
 
-static int
-list_device(int optflg, uid_t uid, char *device)
+/* ARGSUSED */
+int
+_list_device(int optflag, uid_t uid, devalloc_t *da, char *zonename)
 {
-	devalloc_t *dev_ent;
-	devmap_t *dev_list;
-	char	file_name[MAXPATHLEN];
-	struct	stat stat_buf;
-	char	*list;
-	int	bytes_formated;
+	int			bytes = 0;
+	int			error = 0;
+	int			is_authorized = 0;
+	char			*fname = NULL;
+	char			file_name[MAXPATHLEN];
+	devmap_t		*dm;
+	struct file_info	fi;
+	struct state_file	sf;
 
-	if ((dev_ent = getdanam(device)) == NULL) {
-		if ((dev_list = getdmapdev(device)) == NULL) {
-			dprintf("Unable to find %s in the allocate database\n",
-			    device);
-			return (NODMAPENT);
-		} else if ((dev_ent = getdanam(dev_list->dmap_devname)) ==
-		    NULL) {
-			dprintf("Unable to find %s in the allocate database\n",
-			    device);
-			return (NODAENT);
+	setdmapent();
+	if ((dm = getdmapnam(da->da_devname)) == NULL) {
+		enddmapent();
+		dprintf("Unable to find %s in the maps database\n",
+		    da->da_devname);
+		return (NODMAPERR);
+	}
+	enddmapent();
+	if (system_labeled) {
+		if ((error = _dev_file_name(&sf, dm)) != 0) {
+			freedmapent(dm);
+			dprintf("Unable to find %s device files\n",
+			    da->da_devname);
+			error = NODMAPERR;
+			goto out;
 		}
-	} else if ((dev_list = getdmapnam(device)) == NULL) {
-		dprintf("Unable to find %s in the allocate database\n", device);
-		return (NODMAPENT);
+		fname = sf.sf_path;
+	} else {
+		bytes = snprintf(file_name, MAXPATHLEN, "%s/%s", DAC_DIR,
+		    da->da_devname);
+		if (bytes <= 0) {
+			error = DEVNAMEERR;
+			goto out;
+		} else if (bytes >= MAXPATHLEN) {
+			dprintf("device name %s is too long.\n",
+			    da->da_devname);
+			error = DEVLONGERR;
+			goto out;
+		}
+		fname = file_name;
 	}
-
-	bytes_formated = snprintf(file_name, MAXPATHLEN, "%s/%s", DAC_DIR,
-	    dev_ent->da_devname);
-	if (bytes_formated <= 0) {
-		return (DEVNAME_ERR);
-	} else if (bytes_formated >= MAXPATHLEN) {
-		dprintf("device name %s is too long.\n", dev_ent->da_devname);
-		return (DEVNAME_TOOLONG);
-	}
-
-	if (stat(file_name, &stat_buf)) {
-		dprintf("Unable to stat %s\n", file_name);
+	if (stat(fname, &fi.fi_stat) != 0) {
+		dprintf("Unable to stat %s\n", fname);
 		dperror("Error:");
-		return (DACACC);
+		error = DACACCERR;
+		goto out;
 	}
-
-	if ((optflg & FREE) && DEV_ALLOCATED(stat_buf))
-		return (ALLOC);
-
-	if ((optflg & LIST) && DEV_ALLOCATED(stat_buf) &&
-	    (stat_buf.st_uid != uid))
-		return (ALLOC_OTHER);
-
-	if ((optflg & CURRENT) && (stat_buf.st_uid != uid))
-		return (NALLOC);
-
-	if ((stat_buf.st_mode & ~S_IFMT) == ALLOC_ERR_MODE)
-		return (ALLOCERR);
-
-	if ((list = strdup(dev_list->dmap_devlist)) == NULL)
-		return (SYSERROR);
-
-	if (check_devs(list) == -1) {
-		free(list);
-		return (DSPMISS);
+	if (optflag & USERID)
+		is_authorized = 1;
+	else
+		is_authorized = _is_dev_authorized(da, uid);
+	if (optflag & LISTFREE) {	/* list_devices -n */
+		/*
+		 * list all free devices
+		 */
+		if (DEV_ALLOCATED(fi.fi_stat)) {
+				error = PREALLOCERR;
+				goto out;
+		}
+		if (system_labeled) {
+			/*
+			 * for this free device, check if -
+			 * 1. user has authorization to allocate
+			 * 2. the zone label is within the label range of the
+			 *    device
+			 */
+			if (is_authorized == ALLOC_BY_NONE) {
+				error = DAUTHERR;
+				goto out;
+			} else if (is_authorized == 0) {
+				error = UAUTHERR;
+				goto out;
+			}
+			if (_check_label(da, zonename, uid,
+			    CHECK_DRANGE) != 0) {
+				error = LABELRNGERR;
+				goto out;
+			}
+		}
+	} else if (optflag & LISTALLOC) {	/*  list_devices -u */
+		/*
+		 * list all allocated devices
+		 */
+		if (!DEV_ALLOCATED(fi.fi_stat)) {
+			error = DEVNALLOCERR;
+			goto out;
+		}
+		if (fi.fi_stat.st_uid != uid) {
+			error = DEVSTATEERR;
+			goto out;
+		}
+		if (system_labeled) {
+			/*
+			 * check if the zone label equals the label at which
+			 * the device is allocated.
+			 */
+			if (_check_label(da, zonename, uid,
+			    CHECK_ZLABEL) != 0) {
+				error = LABELRNGERR;
+				goto out;
+			}
+		}
+	} else if (optflag & LISTALL) {		/* list_devices -l */
+		/*
+		 * list all devices - free and allocated - available
+		 */
+		if (DEV_ALLOCATED(fi.fi_stat)) {
+			if (optflag & WINDOWING &&
+			    (is_authorized == ALLOC_BY_NONE)) {
+				/*
+				 * don't complain if we're here for the GUI.
+				 */
+				error = 0;
+			} else if (fi.fi_stat.st_uid != uid) {
+				if (!(optflag & WINDOWING)) {
+					error = ALLOCUERR;
+					goto out;
+				}
+			}
+			if (system_labeled && !(optflag & WINDOWING)) {
+				/*
+				 * if we're not displaying in the GUI,
+				 * check if the zone label equals the label
+				 * at which the device is allocated.
+				 */
+				if (_check_label(da, zonename, uid,
+				    CHECK_ZLABEL) != 0) {
+					error = LABELRNGERR;
+					goto out;
+				}
+			}
+		} else if (system_labeled && !(optflag & WINDOWING)) {
+			/*
+			 * if we're not displaying in the GUI,
+			 * for this free device, check if -
+			 * 1. user has authorization to allocate
+			 * 2. the zone label is within the label range of the
+			 *    device
+			 */
+			if (is_authorized == ALLOC_BY_NONE) {
+				error = DAUTHERR;
+				goto out;
+			} else if (is_authorized == 0) {
+				error = UAUTHERR;
+				goto out;
+			}
+			if (_check_label(da, zonename, uid,
+			    CHECK_DRANGE) != 0) {
+				error = LABELRNGERR;
+				goto out;
+			}
+		}
 	}
+	if (system_labeled && DEV_ERRORED(fi.fi_stat) && !(optflag & LISTALL)) {
+		error = DEVSTATEERR;
+		goto out;
+	}
+	if (check_devs(dm) == -1) {
+		error = DSPMISSERR;
+		goto out;
+	}
+	if (optflag & LISTATTRS)
+		print_dev_attrs(optflag, da, dm, &fi);
+	else
+		print_dev(dm);
 
-	print_dev(dev_list);
+	error = 0;
 
-	free(list);
-	return (0);
+out:
+	freedmapent(dm);
+	return (error);
 }
 
+/* ARGSUSED */
 int
-list_devices(int optflg, uid_t uid, char *device)
+list_devices(int optflag, uid_t uid, char *device, char *zonename)
 {
-	DIR   * dev_dir;
-	struct dirent *dac_file;
-	int	error = 0, ret_code = 1;
+	int		error = 0;
+	da_defs_t	*da_defs;
+	devalloc_t	*da;
 
-	if (optflg & USERID) {
-		if (!is_authorized(DEVICE_REVOKE_AUTH, getuid()))
-			return (NOTAUTH);
+	if (system_labeled && optflag & WINDOWING && !(optflag & LISTATTRS)) {
+		/*
+		 * Private interface for GUI.
+		 */
+		(void) lock_dev(NULL);
+		(void) puts(DA_DB_LOCK);
+		return (0);
 	}
-	setdaent();
-
-	if (device) {
-		return (list_device(optflg, uid, device));
+	if (optflag & USERID) {
+		/*
+		 * we need device.revoke to list someone else's devices
+		 */
+		if (!_is_authorized(DEVICE_REVOKE_AUTH, getuid()))
+			return (UAUTHERR);
 	}
-
-	if ((dev_dir = opendir(DAC_DIR)) == NULL) {
-
-		dperror("Can't open DAC_DIR");
-		return (DACACC);
-	}
-
-	while ((dac_file = readdir(dev_dir)) != NULL) {
-		if ((strcmp(dac_file->d_name, ".") == 0) ||
-		    (strcmp(dac_file->d_name, "..") == 0)) {
-			continue;
-		} else {
-			error = list_device(optflg, uid, dac_file->d_name);
-			ret_code = ret_code ? error : ret_code;
+	if (system_labeled) {
+		if (!(optflag & USERID) &&
+		    !_is_authorized(DEFAULT_DEV_ALLOC_AUTH, uid))
+			/*
+			 * we need device.allocate to list our devices
+			 */
+			return (UAUTHERR);
+		if (optflag & LISTDEFS) {
+			/*
+			 * list default attrs from devalloc_defaults
+			 */
+			setdadefent();
+			if (device) {
+				/*
+				 * list default attrs for this device type
+				 */
+				da_defs = getdadeftype(device);
+				if (da_defs == NULL) {
+					enddadefent();
+					dprintf("No default attributes for "
+					    "%s\n", device);
+					return (DEFATTRSERR);
+				}
+				error = print_da_defs(da_defs);
+				freedadefent(da_defs);
+			} else {
+				/*
+				 * list everything in devalloc_defaults
+				 */
+				while ((da_defs = getdadefent()) != NULL) {
+					(void) print_da_defs(da_defs);
+					freedadefent(da_defs);
+				}
+			}
+			enddadefent();
+			return (error);
 		}
 	}
-	(void) closedir(dev_dir);
+	setdaent();
+	if (device) {
+		/*
+		 * list this device
+		 */
+		if ((da = getdanam(device)) == NULL) {
+			enddaent();
+			return (NODAERR);
+		}
+		error = _list_device(optflag, uid, da, zonename);
+		freedaent(da);
+	} else {
+		/*
+		 * list all devices
+		 */
+		while ((da = getdaent()) != NULL) {
+			(void) _list_device(optflag, uid, da, zonename);
+			freedaent(da);
+		}
+	}
 	enddaent();
-	return (ret_code);
+
+	return (error);
 }
 
 /*
@@ -251,24 +568,41 @@
  * This uses a fancy chmod() by setting a minimal ACL which sets the mode
  * and discards any existing ACL.
  */
-
-static int
-newdac(char *file, uid_t owner, gid_t group, o_mode_t mode)
+int
+_newdac(char *file, uid_t owner, gid_t group, o_mode_t mode)
 {
-	int		err = 0;
+	int	err = 0;
 
-	do {
+	if (mode == ALLOC_MODE) {
 		if (chown(file, owner, group) == -1) {
-			dperror("newdac, unable to chown");
-			err = CHOWN_PERR;
+			dperror("newdac: unable to chown");
+			err = CHOWNERR;
+		}
+	} else do {
+		if (chown(file, owner, group) == -1) {
+			dperror("newdac: unable to chown");
+			err = CHOWNERR;
 		}
 	} while (fdetach(file) == 0);
 
-	err = acl_strip(file, owner, group, (mode_t)mode);
+	if (err)
+		return (err);
+
+	if (strncmp(file, "/dev/", strlen("/dev/")) != 0) {
+		/*
+		 * This could be a SunRay device that is in /tmp.
+		 */
+		if (chmod(file, mode) == -1) {
+			dperror("newdac: unable to chmod");
+			err = SETACLERR;
+		}
+	} else {
+		err = acl_strip(file, owner, group, (mode_t)mode);
+	}
 
 	if (err != 0) {
-		dperror("newdac, unable to setacl");
-		err = SETACL_PERR;
+		dperror("newdac: unable to setacl");
+		err = SETACLERR;
 	}
 
 	return (err);
@@ -277,41 +611,60 @@
 static int
 lock_dev(char *file)
 {
-	int	fd;
+	int	lockfd = -1;
 
+	if ((file == NULL) || system_labeled)
+		file = DA_DEV_LOCK;
 	dprintf("locking %s\n", file);
-	if ((fd = open(file, O_RDWR)) == -1) {
-		dperror("lock_dev, cannot open DAC file");
-		return (DACACC);
+	if ((lockfd = open(file, O_RDWR | O_CREAT, 0600)) == -1) {
+		dperror("lock_dev: cannot open lock file");
+		return (DEVLKERR);
 	}
-
-	if (lockf(fd, F_TLOCK, 0) == -1) {
-		dperror("lock_dev, cannot set lock");
-		return (DACLCK);
+	if (lockf(lockfd, F_TLOCK, 0) == -1) {
+		dperror("lock_dev: cannot set lock");
+		return (DEVLKERR);
 	}
 
 	return (0);
 }
 
-static int
-mk_alloc(char *list, uid_t uid)
+int
+mk_alloc(devmap_t *list, uid_t uid, struct zone_path *zpath)
 {
-	char	*file;
-	int	err;
+	int	i;
+	int	error = 0;
+	char	**file;
+	gid_t	gid = getgid();
+	mode_t	mode = ALLOC_MODE;
 
-	file = strtok(list, " ");
-	while (file != NULL) {
-
-		dprintf("Allocating %s\n", file);
-		if ((err = newdac(file, uid, getgid(), ALLOC_MODE)) != 0) {
-			(void) newdac(file, ALLOC_UID, ALLOC_GID,
+	file = list->dmap_devarray;
+	if (file == NULL)
+		return (NODMAPERR);
+	for (; *file != NULL; file++) {
+		dprintf("Allocating %s\n", *file);
+		if ((error = _newdac(*file, uid, gid, mode)) != 0) {
+			(void) _newdac(*file, ALLOC_ERRID, ALLOC_GID,
 			    ALLOC_ERR_MODE);
-			return (err);
+			break;
 		}
-
-		file = strtok(NULL, " ");
 	}
-	return (0);
+	if (system_labeled && zpath->count && (error == 0)) {
+		/*
+		 * mark as allocated any new device nodes that we
+		 * created in local zone
+		 */
+		for (i = 0; i < zpath->count; i++) {
+			dprintf("Allocating %s\n", zpath->path[i]);
+			if ((error = _newdac(zpath->path[i], uid, gid,
+			    mode)) != 0) {
+				(void) _newdac(zpath->path[i], ALLOC_ERRID,
+				    ALLOC_GID, ALLOC_ERR_MODE);
+				break;
+			}
+		}
+	}
+
+	return (error);
 }
 
 /*
@@ -319,33 +672,32 @@
  * because "/usr/sbin/fuser -k file" kills all processes
  * working with the file, even "vold" (bug #4095152).
  */
-static int
-mk_revoke(int optflg, char *file)
+int
+mk_revoke(int optflag, char *file)
 {
-	char buf[MAXPATHLEN];
-	int r = 0, p[2], fp, lock;
-	FILE *ptr;
-	prpsinfo_t info;
-	pid_t pid, c_pid;
+	int		r = 0, p[2], fp, lock;
+	int		fuserpid;
+	char		buf[MAXPATHLEN];
+	FILE		*ptr;
+	pid_t		c_pid;
+	prpsinfo_t	info;
 
 	(void) strcpy(buf, PROCFS);
-
 	/*
-	 * vfork() and execle() just to make the same output
+	 * vfork() and execl() just to make the same output
 	 * as before fixing of bug #4095152.
 	 * The problem is that the "fuser" command prints
 	 * one part of output into stderr and another into stdout,
 	 * but user sees them mixed. Of course, better to change "fuser"
 	 * or to intercept and not to print its output.
 	 */
-	if (!(optflg & SILENT)) {
+	if (!(optflag & SILENT)) {
 		c_pid = vfork();
 		if (c_pid == -1)
 			return (-1);
 		if (c_pid == 0) {
 			dprintf("first exec fuser %s\n", file);
-			(void) execle("/usr/sbin/fuser", "fuser", file, NULL,
-			    newenv);
+			(void) execl("/usr/sbin/fuser", "fuser", file, NULL);
 			dperror("first exec fuser");
 			_exit(1);
 		}
@@ -355,21 +707,18 @@
 		if (WEXITSTATUS(lock) != 0)
 			return (-1);
 	}
-	dprintf("first continuing c_pid=%d\n", c_pid);
-
+	dprintf("first continuing c_pid=%d\n", (int)c_pid);
 	if (pipe(p)) {
 		dperror("pipe");
 		return (-1);
 	}
-
-	/* vfork() and execle() to catch output and to process it */
+	/* vfork() and execl() to catch output and to process it */
 	c_pid = vfork();
 	if (c_pid == -1) {
 		dperror("second vfork");
 		return (-1);
 	}
-	dprintf("second continuing c_pid=%d\n", c_pid);
-
+	dprintf("second continuing c_pid=%d\n", (int)c_pid);
 	if (c_pid == 0) {
 		(void) close(p[0]);
 		(void) close(1);
@@ -377,392 +726,1026 @@
 		(void) close(p[1]);
 		(void) close(2);
 		dprintf("second exec fuser %s\n", file);
-		(void) execle("/usr/sbin/fuser", "fuser", file, NULL, newenv);
+		(void) execl("/usr/sbin/fuser", "fuser", file, NULL);
 		dperror("second exec fuser");
 		_exit(1);
 	}
-
 	(void) close(p[1]);
 	if ((ptr = fdopen(p[0], "r")) != NULL) {
 		while (!feof(ptr)) {
-			if (fscanf(ptr, "%d", &pid) > 0) {
-				(void) sprintf(buf + strlen(PROCFS), "%d", pid);
+			if (fscanf(ptr, "%d", &fuserpid) > 0) {
+				(void) sprintf(buf + strlen(PROCFS), "%d",
+				    fuserpid);
 				if ((fp = open(buf, O_RDONLY)) == -1) {
 					dperror(buf);
 					continue;
 				}
-				if (ioctl(fp, PIOCPSINFO, (char *)&info)
-				    == -1) {
-					dprintf("%d psinfo failed", pid);
+				if (ioctl(fp, PIOCPSINFO,
+				    (char *)&info) == -1) {
+					dprintf("%d psinfo failed", fuserpid);
 					dperror("");
 					(void) close(fp);
 					continue;
 				}
 				(void) close(fp);
 				if (strcmp(info.pr_fname, "vold") == NULL) {
-					dprintf("%d matched vold name\n", pid);
+					dprintf("%d matched vold name\n",
+					    fuserpid);
 					continue;
 				}
 				dprintf("killing %s", info.pr_fname);
-				dprintf("(%d)\n", pid);
-				if ((r = kill(pid, SIGKILL)) == -1) {
-					dprintf("kill %d", pid);
+				dprintf("(%d)\n", fuserpid);
+				if ((r =
+				    kill((pid_t)fuserpid, SIGKILL)) == -1) {
+					dprintf("kill %d", fuserpid);
 					dperror("");
 					break;
 				}
 			}
 		}
-		dprintf("eof reached %x\n", ptr);
 	} else {
-		dperror("fdopen(p[0])");
+		dperror("fdopen(p[0], r)");
 		r = -1;
 	}
-
 	(void) fclose(ptr);
+
 	return (r);
 }
 
-static int
-mk_unalloc(int optflg, char *list)
+int
+mk_unalloc(int optflag, devmap_t *list)
 {
-	char	*file;
 	int	error = 0;
-	int child, status;
+	int	status;
+	char	**file;
 
-	audit_allocate_list(list);
+	audit_allocate_list(list->dmap_devlist);
+	file = list->dmap_devarray;
+	if (file == NULL)
+		return (NODMAPERR);
+	for (; *file != NULL; file++) {
+		dprintf("Deallocating %s\n", *file);
+		if (mk_revoke(optflag, *file) < 0) {
+			dprintf("mk_unalloc: unable to revoke %s\n", *file);
+			dperror("");
+			error = CNTFRCERR;
+		}
+		status = _newdac(*file, ALLOC_UID, ALLOC_GID, DEALLOC_MODE);
+		if (error == 0)
+			error = status;
 
-	child = vfork();
-	switch (child) {
-	case -1:
-		return (-1);
-	case 0:
-		(void) setuid(0);
-		file = strtok(list, " ");
-		while (file != NULL) {
-			dprintf("Deallocating %s\n", file);
-			if (mk_revoke(optflg, file) < 0) {
-				dprintf("mk_unalloc: unable to revoke %s\n",
-				    file);
-				dperror("");
-				error = CNTFRC;
-				break;
-			}
-			error = newdac(file, ALLOC_UID, ALLOC_GID,
-			    DEALLOC_MODE);
-			file = strtok(NULL, " ");
-		}
-		exit(error);
-	default:
-		while (wait(&status) != child);
-		if (WIFEXITED(status)) {
-			return (WEXITSTATUS(status));
-		}
-		return (-1);
 	}
+
+	return (error);
 }
 
-static int
-exec_clean(int optflg, char *name, char *path)
+int
+mk_error(devmap_t *list)
 {
-	char	*mode, *cmd;
-	int	status;
-	int	c;
+	int	status = 0;
+	char	**file;
 
-	if ((optflg & (FORCE_ALL | SILENT)) == (FORCE_ALL | SILENT))
+	audit_allocate_list(list->dmap_devlist);
+	file = list->dmap_devarray;
+	if (file == NULL)
+		return (NODMAPERR);
+	for (; *file != NULL; file++) {
+		dprintf("Putting %s in error state\n", *file);
+		status = _newdac(*file, ALLOC_ERRID, ALLOC_GID, ALLOC_ERR_MODE);
+	}
+
+	return (status);
+}
+
+int
+exec_clean(int optflag, char *devname, char *path, uid_t uid, char *zonename,
+    char *clean_arg)
+{
+	int		c;
+	int		status = 0, exit_status;
+	char		*mode, *cmd, *wdwcmd, *zoneroot;
+	char		*devzone = zonename;
+	char		wdwpath[PATH_MAX];
+	char		zonepath[MAXPATHLEN];
+	char		title[100];
+	char		pw_buf[NSS_BUFLEN_PASSWD];
+	struct passwd	pw_ent;
+
+	zonepath[0] = '\0';
+	if (system_labeled) {
+		if ((zoneroot = getzonerootbyname(zonename)) == NULL) {
+			if (strcmp(clean_arg, ALLOC_CLEAN) == 0) {
+				return (-1);
+			} else if (optflag & FORCE) {
+				(void) strcpy(zonepath, "/");
+				devzone = GLOBAL_ZONENAME;
+			} else {
+				dprintf("unable to get label for %s zone\n",
+				    zonename);
+				return (-1);
+			}
+		} else {
+			(void) strcpy(zonepath, zoneroot);
+			free(zoneroot);
+		}
+	}
+	if (getpwuid_r(uid, &pw_ent, pw_buf, sizeof (pw_buf)) == NULL)
+		return (-1);
+	if (optflag & FORCE_ALL)
 		mode = "-I";
-	else if (optflg & FORCE_ALL)
-		mode = "-i";
-	else if (optflg & FORCE)
+	else if (optflag & FORCE)
 		mode = "-f";
 	else
 		mode = "-s";
+	if (path == NULL)
+		return (0);
 	if ((cmd = strrchr(path, '/')) == NULL)
 		cmd = path;
 	else
 		cmd++;	/* skip leading '/' */
-
 	c = vfork();
 	switch (c) {
 	case -1:
 		return (-1);
 	case 0:
 		(void) setuid(0);
+		if (system_labeled && (optflag & WINDOWING)) {
+			/* First try .windowing version of script */
+			(void) strncpy(wdwpath, path, PATH_MAX);
+			(void) strncat(wdwpath, ".windowing", PATH_MAX);
+			if ((wdwcmd = strrchr(wdwpath, '/')) == NULL)
+				wdwcmd = wdwpath;
+			(void) execl(wdwpath, wdwcmd, mode, devname, clean_arg,
+			    pw_ent.pw_name, devzone, zonepath, NULL);
+			/* If that failed, run regular version via dtterm */
+			(void) snprintf(title, sizeof (title),
+			    "Device %s for %s",
+			    strcmp(clean_arg, ALLOC_CLEAN) == 0 ?
+			    "allocation" : "deallocation", devname);
+			(void) execl("/usr/dt/bin/dtterm", "dtterm",
+			    "-title", title, "-geometry", "x10+100+400",
+			    "-e", "/etc/security/lib/wdwwrapper",
+			    path, mode, devname, clean_arg, pw_ent.pw_name,
+			    devzone, zonepath, NULL);
+			/*
+			 * And if that failed, continue on to try
+			 * running regular version directly.
+			 */
+		}
 		dprintf("clean script: %s, ", path);
 		dprintf("cmd=%s, ", cmd);
 		dprintf("mode=%s, ", mode);
-		dprintf("name=%s\n", name);
-		(void) execle(path, cmd, mode, name, NULL, newenv);
+		if (system_labeled) {
+			dprintf("devname=%s ", devname);
+			dprintf("zonename=%s ", devzone);
+			dprintf("zonepath=%s ", zonepath);
+			dprintf("username=%s\n", pw_ent.pw_name);
+			(void) execl(path, cmd, mode, devname, clean_arg,
+			    pw_ent.pw_name, devzone, zonepath, NULL);
+		} else {
+			dprintf("devname=%s\n", devname);
+			(void) execle(path, cmd, mode, devname, NULL, newenv);
+		}
 		dprintf("Unable to execute clean up script %s\n", path);
 		dperror("");
-		exit(CNTDEXEC);
+		exit(CNTDEXECERR);
 	default:
-		while (wait(&status) != c);
-		if (WIFEXITED(status))
-			return (WEXITSTATUS(status));
-		dprintf("exit status %d\n", status);
+		(void) waitpid(c, &status, 0);
+		dprintf("Child %d", c);
+		if (WIFEXITED(status)) {
+			exit_status = WEXITSTATUS(status);
+			dprintf(" exited, status: %d\n", exit_status);
+			return (exit_status);
+		} else if (WIFSIGNALED(status)) {
+			dprintf(" killed, signal %d\n", WTERMSIG(status));
+		} else {
+			dprintf(": exit status %d\n", status);
+		}
 		return (-1);
 	}
 }
 
-static int
-deallocate_dev(int optflg, devalloc_t *dev_ent, uid_t uid)
+int
+_deallocate_dev(int optflag, devalloc_t *da, devmap_t *dm_in, uid_t uid,
+    char *zonename)
 {
-	devmap_t *dev_list;
-	char	file_name[MAXPATHLEN];
-	struct stat stat_buf;
-	char	*list;
-	int	error = 0, err;
-	int	bytes_formated;
+	int			bytes = 0;
+	int			error = 0;
+	int			is_authorized = 0;
+	uid_t			nuid;
+	char			*fname = NULL;
+	char			file_name[MAXPATHLEN];
+	char			*devzone = NULL;
+	devmap_t		*dm = NULL, *dm_new = NULL;
+	struct stat		stat_buf;
+	struct state_file	sf;
 
-	bytes_formated = snprintf(file_name, MAXPATHLEN, "%s/%s", DAC_DIR,
-	    dev_ent->da_devname);
-	if (bytes_formated <= 0) {
-		return (DEVNAME_ERR);
-	} else if (bytes_formated >= MAXPATHLEN) {
-		dprintf("device name %s is too long.\n", dev_ent->da_devname);
-		return (DEVNAME_TOOLONG);
-	}
-
-	audit_allocate_device(file_name);
-
-	if (stat(file_name, &stat_buf)) {
-		dprintf("Unable to stat %s\n", file_name);
-		dperror("Error:");
-		return (DACACC);
-	}
-
-	if (!(optflg & FORCE) && stat_buf.st_uid != uid &&
-	    DEV_ALLOCATED(stat_buf)) {
-		return (NALLOCU);
-	}
-
-	if (!(optflg & FORCE_ALL) && !DEV_ALLOCATED(stat_buf)) {
-		if ((stat_buf.st_mode & ~S_IFMT) == ALLOC_ERR_MODE) {
-			if (!(optflg & FORCE))
-				return (ALLOCERR);
-		} else
-			return (NALLOC);
-	}
-
-	/* All checks passed, time to lock and deallocate */
-	if ((error = lock_dev(file_name)) != 0)
-		return (error);
-
-	if ((err = newdac(file_name, ALLOC_UID, ALLOC_GID, DEALLOC_MODE))
-	    != 0) {
-		(void) newdac(file_name, ALLOC_UID, ALLOC_GID, ALLOC_ERR_MODE);
-		EXIT(err);
-	}
-
-	if ((dev_list = getdmapnam(dev_ent->da_devname)) == NULL) {
-		dprintf("Unable to find %s in the device map database\n",
-		    dev_ent->da_devname);
-		EXIT(NODMAPENT);
+	if (dm_in == NULL) {
+		setdmapent();
+		if ((dm_new = getdmapnam(da->da_devname)) == NULL) {
+			enddmapent();
+			dprintf("Unable to find %s in device map database\n",
+			    da->da_devname);
+			return (NODMAPERR);
+		}
+		enddmapent();
+		dm = dm_new;
 	} else {
-		if ((list = strdup(dev_list->dmap_devlist)) == NULL) {
-			EXIT(SYSERROR)
+		dm = dm_in;
+	}
+	if (system_labeled) {
+		if (_dev_file_name(&sf, dm) != 0) {
+			if (dm_new)
+				freedmapent(dm_new);
+			dprintf("Unable to find %s device files\n",
+			    da->da_devname);
+			error = NODMAPERR;
+			goto out;
+		}
+		fname = sf.sf_path;
+	} else {
+		bytes = snprintf(file_name,  MAXPATHLEN, "%s/%s", DAC_DIR,
+		    da->da_devname);
+		if (bytes <= 0) {
+			error = DEVNAMEERR;
+			goto out;
+		} else if (bytes >= MAXPATHLEN) {
+			dprintf("device name %s is too long.\n",
+			    da->da_devname);
+			error = DEVLONGERR;
+			goto out;
+		}
+		fname = file_name;
+	}
+
+	audit_allocate_device(fname);
+
+	if (stat(fname, &stat_buf) != 0) {
+		dprintf("Unable to stat %s\n", fname);
+		error = DACACCERR;
+		goto out;
+	}
+	is_authorized = _is_dev_authorized(da, uid);
+	if (!(optflag & (FORCE | FORCE_ALL)) && !is_authorized) {
+		dprintf("User %d is unauthorized to deallocate\n", (int)uid);
+		error = UAUTHERR;
+		goto out;
+	}
+	if (system_labeled) {
+		/*
+		 * unless we're here to deallocate by force, check if the
+		 * label at which the device is currently allocated is
+		 * within the user label range.
+		 */
+		if (!(optflag & FORCE) &&
+		    _check_label(da, zonename, uid, CHECK_URANGE) != 0) {
+			error = LABELRNGERR;
+			goto out;
+		}
+	}
+	if (!(optflag & FORCE) && stat_buf.st_uid != uid &&
+	    DEV_ALLOCATED(stat_buf)) {
+		error = ALLOCUERR;
+		goto out;
+	}
+	if (!DEV_ALLOCATED(stat_buf)) {
+		if (DEV_ERRORED(stat_buf)) {
+			if (!(optflag & FORCE)) {
+				error = DEVSTATEERR;
+				goto out;
+			}
 		} else {
-			if (mk_unalloc(optflg, list) != 0) {
-				(void) newdac(file_name, ALLOC_UID, ALLOC_GID,
-				    ALLOC_ERR_MODE);
-				free(list);
-				list = NULL;
-				EXIT(DEVLST);
+			error = DEVNALLOCERR;
+			goto out;
+		}
+	}
+	/* All checks passed, time to lock and deallocate */
+	if ((error = lock_dev(fname)) != 0)
+		goto out;
+	if (system_labeled) {
+		devzone = kva_match(da->da_devopts, DAOPT_ZONE);
+		if (devzone && (strcmp(devzone, GLOBAL_ZONENAME) != 0)) {
+			if ((remove_znode(devzone, dm) != 0) &&
+			    !(optflag & FORCE)) {
+				error = ZONEERR;
+				goto out;
+			}
+		}
+	}
+	if ((error = mk_unalloc(optflag, dm)) != 0) {
+		if (!(optflag & FORCE))
+			goto out;
+	}
+	if (system_labeled == 0) {
+		if ((error = _newdac(fname, ALLOC_UID, ALLOC_GID,
+		    DEALLOC_MODE)) != 0) {
+			(void) _newdac(file_name, ALLOC_UID, ALLOC_GID,
+			    ALLOC_ERR_MODE);
+			goto out;
+		}
+	}
+	/*
+	 * if we are deallocating device owned by someone else,
+	 * pass the owner's uid to the cleaning script.
+	 */
+	nuid = (stat_buf.st_uid == uid) ? uid : stat_buf.st_uid;
+	error = exec_clean(optflag, da->da_devname, da->da_devexec, nuid,
+	    devzone, DEALLOC_CLEAN);
+	if (error != 0) {
+		if (!(optflag & (FORCE | FORCE_ALL))) {
+			error = CLEANERR;
+			(void) mk_error(dm);
+		} else {
+			error = 0;
+		}
+	}
+
+out:
+	if (dm_new)
+		freedmapent(dm_new);
+	return (error);
+}
+
+int
+_allocate_dev(int optflag, uid_t uid, devalloc_t *da, char *zonename)
+{
+	int			i;
+	int			bytes = 0;
+	int			error = 0;
+	int			is_authorized = 0;
+	int			dealloc_optflag = 0;
+	char			*fname = NULL;
+	char			file_name[MAXPATHLEN];
+	devmap_t 		*dm;
+	struct stat 		stat_buf;
+	struct state_file	sf;
+	struct zone_path	zpath;
+
+	zpath.count = 0;
+	zpath.path = NULL;
+	setdmapent();
+	if ((dm = getdmapnam(da->da_devname)) == NULL) {
+		enddmapent();
+		dprintf("Unable to find %s in device map database\n",
+		    da->da_devname);
+		return (NODMAPERR);
+	}
+	enddmapent();
+	if (system_labeled) {
+		if (_dev_file_name(&sf, dm) != 0) {
+			freedmapent(dm);
+			dprintf("Unable to find %s device files\n",
+			    da->da_devname);
+			error = NODMAPERR;
+			goto out;
+		}
+		fname = sf.sf_path;
+	} else {
+		bytes = snprintf(file_name,  MAXPATHLEN, "%s/%s", DAC_DIR,
+		    da->da_devname);
+		if (bytes <= 0) {
+			error = DEVNAMEERR;
+			goto out;
+		} else if (bytes >= MAXPATHLEN) {
+			dprintf("device name %s is too long.\n",
+			    da->da_devname);
+			error = DEVLONGERR;
+			goto out;
+		}
+		fname = file_name;
+	}
+
+	(void) audit_allocate_device(fname);
+
+	if (stat(fname, &stat_buf) != 0) {
+		dprintf("Unable to stat %s\n", fname);
+		dperror("Error:");
+		error = DACACCERR;
+		goto out;
+	}
+	if (DEV_ERRORED(stat_buf)) {
+		error = DEVSTATEERR;
+		goto out;
+	}
+	is_authorized = _is_dev_authorized(da, uid);
+	if (is_authorized == ALLOC_BY_NONE) {
+		dprintf("Device %s is not allocatable\n", da->da_devname);
+		error = UAUTHERR;
+		goto out;
+	} else if (!is_authorized && !(optflag & USERNAME)) {
+		dprintf("User %d is unauthorized to allocate\n", (int)uid);
+		error = UAUTHERR;
+		goto out;
+	}
+	if (system_labeled) {
+		/*
+		 * check if label of the zone to which the device is being
+		 * allocated is within the device label range.
+		 */
+		if (_check_label(da, zonename, uid, CHECK_DRANGE) != 0) {
+			error = LABELRNGERR;
+			goto out;
+		}
+	}
+	if (check_devs(dm) == -1) {
+		error = DSPMISSERR;
+		goto out;
+	}
+	if (DEV_ALLOCATED(stat_buf)) {
+		if (optflag & FORCE) {
+			if (optflag & SILENT)
+				dealloc_optflag = FORCE|SILENT;
+			else
+				dealloc_optflag = FORCE;
+			if (_deallocate_dev(dealloc_optflag, da, dm, uid,
+			    zonename)) {
+				dprintf("Couldn't force deallocate device %s\n",
+				    da->da_devname);
+				error = CNTFRCERR;
+				goto out;
+			}
+		} else if (stat_buf.st_uid == uid) {
+			error = PREALLOCERR;
+			goto out;
+		} else {
+			error = ALLOCUERR;
+			goto out;
+		}
+	}
+	/* All checks passed, time to lock and allocate */
+	if ((error = lock_dev(fname)) != 0)
+		goto out;
+	if (system_labeled) {
+		/*
+		 * Run the cleaning program; it also mounts allocated
+		 * device if required.
+		 */
+		error = exec_clean(optflag, da->da_devname, da->da_devexec, uid,
+		    zonename, ALLOC_CLEAN);
+		if ((error != 0) && (error != CLEAN_MOUNT)) {
+			error = CLEANERR;
+			(void) mk_error(dm);
+			goto out;
+		}
+		/*
+		 * If not mounted, create zonelinks, if this is not the
+		 * global zone.
+		 */
+		if ((strcmp(zonename, GLOBAL_ZONENAME) != 0) &&
+		    (error != CLEAN_MOUNT)) {
+			if (create_znode(zonename, &zpath, dm) != 0) {
+				error = ZONEERR;
+				goto out;
 			}
 		}
 	}
 
-	if (list != NULL)
-		free(list);
-	if (exec_clean(optflg, dev_ent->da_devname, dev_ent->da_devexec))
-		EXIT(CLEAN_ERR);
+	(void) audit_allocate_list(dm->dmap_devlist);
+
+	if ((error = mk_alloc(dm, uid, &zpath)) != 0) {
+		(void) mk_unalloc(optflag, dm);
+		goto out;
+	}
+
+	if (system_labeled == 0) {
+		if ((error = _newdac(file_name, uid, getgid(),
+		    ALLOC_MODE)) != 0) {
+			(void) _newdac(file_name, ALLOC_UID, ALLOC_GID,
+			    ALLOC_ERR_MODE);
+			goto out;
+		}
+	}
+	error = 0;
+out:
+	if (zpath.count) {
+		for (i = 0; i < zpath.count; i++)
+			free(zpath.path[i]);
+		free(zpath.path);
+	}
+	freedmapent(dm);
+	return (error);
+}
+
+void
+_store_devnames(int *count, struct devnames *dnms, char *zonename,
+    devalloc_t *da, int flag)
+{
+	int i;
+
+	dnms->dnames = (char **)realloc(dnms->dnames,
+	    (*count + 1) * sizeof (char *));
+	if (da) {
+		dnms->dnames[*count] = strdup(da->da_devname);
+		(*count)++;
+	} else {
+		dnms->dnames[*count] = NULL;
+		if (flag == DA_ADD_ZONE)
+			(void) update_device(dnms->dnames, zonename,
+			    DA_ADD_ZONE);
+		else if (flag == DA_REMOVE_ZONE)
+			(void) update_device(dnms->dnames, NULL,
+			    DA_REMOVE_ZONE);
+		for (i = 0; i < *count; i++)
+			free(dnms->dnames[i]);
+		free(dnms->dnames);
+	}
+}
+
+int
+allocate(int optflag, uid_t uid, char *device, char *zonename)
+{
+	int		count = 0;
+	int		error = 0;
+	devalloc_t	*da;
+	struct devnames	dnms;
+
+	if (optflag & (FORCE | USERID | USERNAME)) {
+		if (!_is_authorized(DEVICE_REVOKE_AUTH, getuid()))
+			return (UAUTHERR);
+	}
+	dnms.dnames = NULL;
+	setdaent();
+	if (optflag & TYPE) {
+		/*
+		 * allocate devices of this type
+		 */
+		while ((da = getdatype(device)) != NULL) {
+			if (system_labeled &&
+			    da_check_logindevperm(da->da_devname)) {
+				freedaent(da);
+				continue;
+			}
+			dprintf("trying to allocate %s\n", da->da_devname);
+			error = _allocate_dev(optflag, uid, da, zonename);
+			if (system_labeled && (error == 0)) {
+				/*
+				 * we need to record in device_allocate the
+				 * label (zone name) at which this device is
+				 * being allocated. store this device entry.
+				 */
+				_store_devnames(&count, &dnms, zonename, da, 0);
+			}
+			freedaent(da);
+			error = 0;
+		}
+	} else {
+		/*
+		 * allocate this device
+		 */
+		if ((da = getdanam(device)) == NULL) {
+			enddaent();
+			return (NODAERR);
+		}
+		if (system_labeled && da_check_logindevperm(device)) {
+			freedaent(da);
+			return (LOGINDEVPERMERR);
+		}
+		dprintf("trying to allocate %s\n", da->da_devname);
+		error = _allocate_dev(optflag, uid, da, zonename);
+		/*
+		 * we need to record in device_allocate the label (zone name)
+		 * at which this device is being allocated. store this device
+		 * entry.
+		 */
+		if (system_labeled && (error == 0))
+			_store_devnames(&count, &dnms, zonename, da, 0);
+		freedaent(da);
+	}
+	enddaent();
+	/*
+	 * add to device_allocate labels (zone names) for the devices we
+	 * allocated.
+	 */
+	if (dnms.dnames)
+		_store_devnames(&count, &dnms, zonename, NULL, DA_ADD_ZONE);
+
+	return (error);
+}
+
+/* ARGSUSED */
+int
+deallocate(int optflag, uid_t uid, char *device, char *zonename)
+{
+	int		count = 0;
+	int		error = 0;
+	devalloc_t	*da;
+	struct devnames dnms;
+
+	if (optflag & (FORCE | FORCE_ALL)) {
+		if (!_is_authorized(DEVICE_REVOKE_AUTH, getuid()))
+		return (UAUTHERR);
+	}
+	if (optflag & FORCE_ALL)
+		optflag |= FORCE;
+	dnms.dnames = NULL;
+	setdaent();
+	if (optflag & FORCE_ALL) {
+		/*
+		 * deallocate all devices
+		 */
+		while ((da = getdaent()) != NULL) {
+			if (system_labeled &&
+			    da_check_logindevperm(da->da_devname)) {
+				freedaent(da);
+				continue;
+			}
+			dprintf("trying to deallocate %s\n", da->da_devname);
+			error = _deallocate_dev(optflag, da, NULL, uid,
+			    zonename);
+			if (system_labeled && (error == 0)) {
+				/*
+				 * we need to remove this device's allocation
+				 * label (zone name) from device_allocate.
+				 * store this device name.
+				 */
+				_store_devnames(&count, &dnms, zonename, da, 0);
+			}
+			freedaent(da);
+			error = 0;
+		}
+	} else if (system_labeled && optflag & TYPE) {
+		/*
+		 * deallocate all devices of this type
+		 */
+		while ((da = getdatype(device)) != NULL) {
+			if (da_check_logindevperm(da->da_devname)) {
+				freedaent(da);
+				continue;
+			}
+			dprintf("trying to deallocate %s\n", da->da_devname);
+			error = _deallocate_dev(optflag, da, NULL, uid,
+			    zonename);
+			if (error == 0) {
+				/*
+				 * we need to remove this device's allocation
+				 * label (zone name) from device_allocate.
+				 * store this device name.
+				 */
+				_store_devnames(&count, &dnms, zonename, da, 0);
+			}
+			freedaent(da);
+			error = 0;
+		}
+	} else if (!(optflag & TYPE)) {
+		/*
+		 * deallocate this device
+		 */
+		if ((da = getdanam(device)) == NULL) {
+			enddaent();
+			return (NODAERR);
+		}
+		if (system_labeled && da_check_logindevperm(da->da_devname)) {
+			freedaent(da);
+			return (LOGINDEVPERMERR);
+		}
+		dprintf("trying to deallocate %s\n", da->da_devname);
+		error = _deallocate_dev(optflag, da, NULL, uid, zonename);
+		if (system_labeled && (error == 0)) {
+			/*
+			 * we need to remove this device's allocation label
+			 * (zone name) from device_allocate. store this
+			 * device name.
+			 */
+			_store_devnames(&count, &dnms, zonename, da, 0);
+		}
+		freedaent(da);
+	}
+	enddaent();
+	/*
+	 * remove from device_allocate labels (zone names) for the devices we
+	 * deallocated.
+	 */
+	if (dnms.dnames)
+		_store_devnames(&count, &dnms, zonename, NULL, DA_REMOVE_ZONE);
+
 	return (error);
 }
 
 static int
-allocate_dev(int optflg, uid_t uid, devalloc_t *dev_ent)
+_dev_file_name(struct state_file *sfp, devmap_t *dm)
 {
-	devmap_t *dev_list;
-	char	file_name[MAXPATHLEN];
-	struct stat stat_buf;
-	char	*list;
-	int	error = 0;
-	int	bytes_formated;
-	int	deallocate_optflg = 0;
-
-	bytes_formated = snprintf(file_name, MAXPATHLEN, "%s/%s", DAC_DIR,
-	    dev_ent->da_devname);
-	if (bytes_formated <= 0) {
-		return (DEVNAME_ERR);
-	} else if (bytes_formated >= MAXPATHLEN) {
-		dprintf("device name %s is too long.\n", dev_ent->da_devname);
-		return (DEVNAME_TOOLONG);
+	sfp->sf_flags = 0;
+	/* if devlist is generated, never leave device in error state */
+	if (dm->dmap_devlist[0] == '`')
+		sfp->sf_flags |= SFF_NO_ERROR;
+	if (dm->dmap_devarray == NULL ||
+	    dm->dmap_devarray[0] == NULL)
+		return (NODMAPERR);
+	(void) strncpy(sfp->sf_path, dm->dmap_devarray[0],
+	    sizeof (sfp->sf_path));
+	sfp->sf_path[sizeof (sfp->sf_path) - 1] = '\0';
+	if (sfp->sf_path[0] == '\0') {
+		dprintf("dev_file_name: no device list for %s\n",
+		    dm->dmap_devname);
+		return (NODMAPERR);
 	}
 
-	audit_allocate_device(file_name);
+	return (0);
+}
 
-	if (stat(file_name, &stat_buf)) {
-		dprintf("Unable to stat %s\n", file_name);
-		dperror("Error:");
-		return (DACACC);
+/*
+ * _check_label -
+ *	checks the device label range against zone label, which is also
+ *	user's current label.
+ *	returns 0 if in range, -1 for all other conditions.
+ *
+ */
+
+static int
+_check_label(devalloc_t *da, char *zonename, uid_t uid, int flag)
+{
+	int		err;
+	int		in_range = 0;
+	char		*alloczone, *lstr;
+	char		pw_buf[NSS_BUFLEN_PASSWD];
+	blrange_t	*range;
+	m_label_t	*zlabel;
+	struct passwd	pw_ent;
+
+	if ((da == NULL) || (zonename == NULL))
+		return (-1);
+
+	if ((zlabel = getzonelabelbyname(zonename)) == NULL) {
+		dprintf("unable to get label for %s zone\n", zonename);
+		return (-1);
 	}
+	if (flag == CHECK_DRANGE) {
+		blrange_t	drange;
 
-	if (DEV_ALLOCATED(stat_buf)) {
-		if (optflg & FORCE) {
-			if (optflg & SILENT)
-				deallocate_optflg = FORCE|SILENT;
-			else
-				deallocate_optflg = FORCE;
+		drange.lower_bound = blabel_alloc();
+		lstr = kva_match(da->da_devopts, DAOPT_MINLABEL);
+		if (lstr == NULL) {
+			bsllow(drange.lower_bound);
+		} else if (stobsl(lstr, drange.lower_bound, NO_CORRECTION,
+		    &err) == 0) {
+			dprintf("bad min_label for device %s\n",
+			    da->da_devname);
+			free(zlabel);
+			blabel_free(drange.lower_bound);
+			return (-1);
+		}
+		drange.upper_bound = blabel_alloc();
+		lstr = kva_match(da->da_devopts, DAOPT_MAXLABEL);
+		if (lstr == NULL) {
+			bslhigh(drange.upper_bound);
+		} else if (stobsl(lstr, drange.upper_bound, NO_CORRECTION,
+		    &err) == 0) {
+			dprintf("bad max_label for device %s\n",
+			    da->da_devname);
+			free(zlabel);
+			blabel_free(drange.lower_bound);
+			blabel_free(drange.upper_bound);
+			return (-1);
+		}
+		if (blinrange(zlabel, &drange) == 0) {
+			char	*zlbl = NULL, *min = NULL, *max = NULL;
 
-			if (deallocate_dev(deallocate_optflg, dev_ent, uid)) {
-				dprintf("Couldn't force deallocate device %s\n",
-				    dev_ent->da_devname);
-				return (CNTFRC);
-			}
-		} else if (stat_buf.st_uid == uid) {
-			return (ALLOC);
-		} else
-			return (ALLOC_OTHER);
-	}
-	if ((stat_buf.st_mode & ~S_IFMT) == ALLOC_ERR_MODE)
-		return (ALLOCERR);
-
-	if (strcmp(dev_ent->da_devauth, "*") == 0) {
-		dprintf("Device %s is not allocatable\n", dev_ent->da_devname);
-		return (AUTHERR);
-	}
-
-	if (strcmp(dev_ent->da_devauth, "@")) {
-		if (!is_authorized(dev_ent->da_devauth, uid)) {
-			dprintf("User %d is unauthorized to allocate\n",
+			(void) bsltos(zlabel, &zlbl, 0, 0);
+			(void) bsltos(drange.lower_bound, &min, 0, 0);
+			(void) bsltos(drange.upper_bound, &max, 0, 0);
+			dprintf("%s zone label ", zonename);
+			dprintf("%s outside device label range: ", zlbl);
+			dprintf("min - %s, ", min);
+			dprintf("max - %s\n", max);
+			free(zlabel);
+			blabel_free(drange.lower_bound);
+			blabel_free(drange.upper_bound);
+			return (-1);
+		}
+	} else if (flag == CHECK_URANGE) {
+		if (getpwuid_r(uid, &pw_ent, pw_buf, sizeof (pw_buf)) == NULL) {
+			dprintf("Unable to get passwd entry for userid %d\n",
 			    (int)uid);
-			return (IMPORT_ERR);
+			free(zlabel);
+			return (-1);
+		}
+		if ((range = getuserrange(pw_ent.pw_name)) == NULL) {
+			dprintf("Unable to get label range for userid %d\n",
+			    (int)uid);
+			free(zlabel);
+			return (-1);
+		}
+		in_range = blinrange(zlabel, range);
+		free(zlabel);
+		blabel_free(range->lower_bound);
+		blabel_free(range->upper_bound);
+		free(range);
+		if (in_range == 0) {
+			dprintf("%s device label ", da->da_devname);
+			dprintf("out of user %d label range\n", (int)uid);
+			return (-1);
+		}
+	} else if (flag == CHECK_ZLABEL) {
+		alloczone = kva_match(da->da_devopts, DAOPT_ZONE);
+		if (alloczone == NULL) {
+			free(zlabel);
+			return (-1);
+		}
+		if (strcmp(zonename, alloczone) != 0) {
+			dprintf("%s zone is different than ", zonename);
+			dprintf("%s zone to which the device ", alloczone);
+			dprintf("%s is allocated\n", da->da_devname);
+			free(zlabel);
+			return (-1);
 		}
 	}
+	free(zlabel);
 
-	if ((dev_list = getdmapnam(dev_ent->da_devname)) == NULL) {
-		dprintf("Unable to find %s in device map database\n",
-		    dev_ent->da_devname);
-		return (NODMAPENT);
-	}
-
-	if ((list = strdup(dev_list->dmap_devlist)) == NULL)
-		return (SYSERROR);
-
-	if (check_devs(list) == -1) {
-		free(list);
-		return (DSPMISS);
-	}
-
-	/* All checks passed, time to lock and allocate */
-	if ((error = lock_dev(file_name)) != 0) {
-		free(list);
-		return (error);
-	}
-
-	if ((error = newdac(file_name, uid, getgid(), ALLOC_MODE)) != 0) {
-		(void) newdac(file_name, ALLOC_UID, ALLOC_GID, ALLOC_ERR_MODE);
-		free(list);
-		return (error);
-	}
-
-	/* refresh list from check_devs overwritting it */
-	(void) strcpy(list, dev_list->dmap_devlist);
-	audit_allocate_list(list);
-
-	if (mk_alloc(list, uid) != 0) {
-		/* refresh list from mk_alloc overwritting it */
-		(void) strcpy(list, dev_list->dmap_devlist);
-		(void) mk_unalloc(optflg, list);
-		free(list);
-		return (DEVLST);
-	}
-
-	free(list);
 	return (0);
 }
 
 int
-allocate(int optflg, uid_t uid, char *device)
+create_znode(char *zonename, struct zone_path *zpath, devmap_t *list)
 {
-	devalloc_t	*dev_ent;
-	devmap_t	*dev_list;
+	int		i;
+	int		size;
+	int		len = 0;
+	int		fcount = 0;
+	char		*p, *tmpfile, *zoneroot;
+	char		**file;
+	char		zonepath[MAXPATHLEN];
+	struct stat	statb;
 
-	if (((optflg & FORCE) || uid != getuid()) &&
-	    !is_authorized(DEVICE_REVOKE_AUTH, getuid()))
-		return (NOTAUTH);
-
-	setdaent();
-	setdmapent();
-
-	if (!(optflg & TYPE)) {
-		if ((dev_ent = getdanam(device)) == NULL) {
-			if ((dev_list = getdmapdev(device)) == NULL)
-				return (NODMAPENT);
-			else if ((dev_ent = getdanam(dev_list->dmap_devname))
-			    == NULL)
-				return (NODAENT);
+	file = list->dmap_devarray;
+	if (file == NULL)
+		return (NODMAPERR);
+	if ((zoneroot = getzonerootbyname(zonename)) == NULL) {
+		dprintf("unable to get label for %s zone\n", zonename);
+		return (1);
+	}
+	(void) strcpy(zonepath, zoneroot);
+	free(zoneroot);
+	if ((p = strstr(zonepath, "/root")) == NULL)
+		return (1);
+	*p = '\0';
+	len = strlen(zonepath);
+	size = sizeof (zonepath);
+	for (; *file != NULL; file++) {
+		if (stat(*file, &statb) == -1) {
+			dprintf("Couldn't stat the file %s\n", *file);
+			return (1);
 		}
-		return (allocate_dev(optflg, uid, dev_ent));
+		/*
+		 * First time initialization
+		 */
+		tmpfile = strdup(*file);
+
+		/*
+		 * Most devices have pathnames starting in /dev
+		 * but SunRay devices do not. In SRRS 3.1 they use /tmp.
+		 *
+		 * If the device pathname is not in /dev then create
+		 * a symbolic link to it and put the device in /dev
+		 */
+		if (strncmp(tmpfile, "/dev/", strlen("/dev/")) != 0) {
+			char	*linkdir;
+			char	srclinkdir[MAXPATHLEN];
+			char	dstlinkdir[MAXPATHLEN];
+
+			linkdir = strchr(tmpfile + 1, '/');
+			p = strchr(linkdir + 1, '/');
+			*p = '\0';
+			(void) strcpy(dstlinkdir, "/dev");
+			(void) strncat(dstlinkdir, linkdir, MAXPATHLEN);
+			(void) snprintf(srclinkdir, MAXPATHLEN, "%s/root%s",
+				zonepath, tmpfile);
+			(void) symlink(dstlinkdir, srclinkdir);
+			*p = '/';
+			(void) strncat(dstlinkdir, p, MAXPATHLEN);
+			free(tmpfile);
+			tmpfile = strdup(dstlinkdir);
+		}
+		if ((p = rindex(tmpfile, '/')) == NULL) {
+			dprintf("bad path in create_znode for %s\n",
+			    tmpfile);
+			return (1);
+		}
+		*p = '\0';
+		(void) strcat(zonepath, tmpfile);
+		*p = '/';
+		if ((mkdirp(zonepath, 0755) != 0) && (errno != EEXIST)) {
+			dprintf("Unable to create directory %s\n", zonepath);
+			return (1);
+		}
+		zonepath[len] = '\0';
+		if (strlcat(zonepath, tmpfile, size) >= size) {
+			dprintf("Buffer overflow in create_znode for %s\n",
+			    *file);
+			free(tmpfile);
+			return (1);
+		}
+		free(tmpfile);
+		fcount++;
+		if ((zpath->path = (char **)realloc(zpath->path,
+		    (fcount * sizeof (char *)))) == NULL)
+			return (1);
+		zpath->path[zpath->count] = strdup(zonepath);
+		zpath->count = fcount;
+		if (mknod(zonepath, statb.st_mode, statb.st_rdev) == -1) {
+			switch (errno) {
+			case EEXIST:
+				break;
+			default:
+				dprintf("mknod error: %s\n",
+				    strerror(errno));
+				for (i = 0; i <= fcount; i++)
+					free(zpath->path[i]);
+				free(zpath->path);
+				return (1);
+			}
+		}
+		zonepath[len] = '\0';
 	}
 
-	while ((dev_ent = getdatype(device)) != NULL) {
-		dprintf("trying to allocate %s\n", dev_ent->da_devname);
-		if (!allocate_dev(optflg, uid, dev_ent)) {
-			return (0);
-		}
-	}
-	enddaent();
-	return (NO_DEVICE);
+	return (0);
 }
 
 int
-deallocate(int optflg, uid_t uid, char *device)
+remove_znode(char *zonename, devmap_t *dm)
 {
-	DIR	*dev_dir;
-	struct dirent	*dac_file;
-	devalloc_t	*dev_ent;
-	devmap_t	*dev_list;
-	int	error = NODAENT;
+	int		len = 0;
+	char		*zoneroot;
+	char		**file;
+	char		zonepath[MAXPATHLEN];
 
-	if (optflg & (FORCE | FORCE_ALL) &&
-	    !is_authorized(DEVICE_REVOKE_AUTH, getuid()))
-		return (NOTAUTH);
-	if (optflg & FORCE_ALL)
-		optflg |= FORCE;
+	file = dm->dmap_devarray;
+	if (file == NULL)
+		return (NODMAPERR);
+	if ((zoneroot = getzonerootbyname(zonename)) == NULL) {
+		(void) snprintf(zonepath, MAXPATHLEN, "/zone/%s", zonename);
+	} else {
+		char *p;
 
-	setdaent();
-	setdmapent();
+		if ((p = strstr(zoneroot, "/root")) == NULL)
+			return (1);
+		*p = '\0';
+		(void)  strcpy(zonepath, zoneroot);
+		free(zoneroot);
+	}
+	/*
+	 * To support SunRay we will just deal with the
+	 * file in /dev, not the symlinks.
+	 */
+	(void) strncat(zonepath, "/dev", MAXPATHLEN);
+	len = strlen(zonepath);
+	for (; *file != NULL; file++) {
+		char *devrelpath;
 
-	if (!(optflg & FORCE_ALL)) {
-		if ((dev_ent = getdanam(device)) == NULL) {
-			if ((dev_list = getdmapdev(device)) == NULL)
-				return (NODMAPENT);
-			else if ((dev_ent = getdanam(dev_list->dmap_devname))
-			    == NULL)
-				return (NODAENT);
+		/*
+		 * remove device node from zone.
+		 *
+		 * SunRay devices don't start with /dev
+		 * so skip over first directory to make
+		 * sure it is /dev. SunRay devices in zones
+		 * will have a symlink into /dev but
+		 * we don't ever delete it.
+		 */
+		devrelpath = strchr(*file + 1, '/');
+
+		if (strlcat(zonepath, devrelpath, MAXPATHLEN) >= MAXPATHLEN) {
+			dprintf("Buffer overflow in remove_znode for %s\n",
+			    *file);
+			return (1);
 		}
-
-		return (deallocate_dev(optflg, dev_ent, uid));
-	}
-
-	if ((dev_dir = opendir(DAC_DIR)) == NULL) {
-		dperror("Can't open DAC_DIR");
-		return (DACACC);
-	}
-
-	while ((dac_file = readdir(dev_dir)) != NULL) {
-		if ((strcmp(dac_file->d_name, ".") == 0) ||
-		    (strcmp(dac_file->d_name, "..") == 0)) {
-			continue;
-		} else {
-			if ((dev_ent = getdanam(dac_file->d_name)) == NULL) {
-				continue;
-			}
-			error = deallocate_dev(optflg, dev_ent, uid);
+		errno = 0;
+		if ((unlink(zonepath) == -1) && (errno != ENOENT)) {
+			perror(zonepath);
+			return (1);
 		}
+		zonepath[len] = '\0';
 	}
-	(void) closedir(dev_dir);
-	enddaent();
-	return (error);
+
+	return (0);
+}
+
+int
+update_device(char **devnames, char *zonename, int flag)
+{
+	int		len, rc;
+	char		*optstr = NULL;
+	da_args		dargs;
+	devinfo_t	devinfo;
+
+	dargs.optflag = flag;
+	dargs.optflag |= DA_UPDATE|DA_ALLOC_ONLY;
+	dargs.rootdir = NULL;
+	dargs.devnames = devnames;
+	devinfo.devname = devinfo.devtype = devinfo.devauths = devinfo.devexec =
+	    devinfo.devlist = NULL;
+	if (dargs.optflag & DA_ADD_ZONE) {
+		len = strlen(DAOPT_ZONE) + strlen(zonename) + 3;
+		if ((optstr = (char *)malloc(len)) == NULL)
+			return (-1);
+		(void) snprintf(optstr, len, "%s%s%s", DAOPT_ZONE, KV_ASSIGN,
+		    zonename);
+		devinfo.devopts = optstr;
+	}
+	dargs.devinfo = &devinfo;
+
+	rc = da_update_device(&dargs);
+
+	if (optstr)
+		free(optstr);
+
+	return (rc);
 }
diff --git a/usr/src/cmd/allocate/audio_clean.c b/usr/src/cmd/allocate/audio_clean.c
index 4447fdf..24753b8 100644
--- a/usr/src/cmd/allocate/audio_clean.c
+++ b/usr/src/cmd/allocate/audio_clean.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -53,9 +53,10 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <strings.h>
 #include <stropts.h>
 #include <unistd.h>
-
+#include <bsm/devices.h>
 #include <sys/audioio.h>
 #include <sys/file.h>
 #include <sys/ioctl.h>
@@ -67,54 +68,32 @@
 #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
 #endif
 
-#define	BUF_SIZE 512
-#define	DMINFO	"dminfo -v -n"	/* Cmd to xlate name to device */
-#define	AUDIO	"/dev/audio"	/* Device name of audio device */
-
-static char *Audio_dev = AUDIO;
-
 #ifdef	DEBUG
 static void print_info(audio_info_t *);
 static void print_prinfo(audio_prinfo_t *);
 #endif	/* DEBUG */
 
 static void
-usage(char *prog, int verbose)
+usage(char *prog)
 {
-	if (verbose)
-		(void) fprintf(stderr,
-		    gettext("usage: %s [-I|-s|-f|-i] device\n"), prog);
-}
-
-/*
- * Return the first substring in string before the ':' in "item"
- */
-static void
-first_field(char *string, char *item)
-{
-	item = string;
-
-	while (*item != ':')
-		item++;
-	*item = 0;
+	(void) fprintf(stderr, "%s%s", prog,
+	    gettext(" : usage:[-I|-s|-f|-i] device\n"));
 }
 
 int
-main(int argc, char *argv[])
+main(int argc, char **argv)
 {
-	int	err = 0;
+	int		err = 0;
+	int		Audio_fd;
+	int		forced = 0;		/* Command line options */
+	int		initial = 0;
+	int		standard = 0;
+	int		verbose = 1;		/* default is to be verbose */
+	int		c;
+	char		*prog, *devname, *devpath;
+	devmap_t	*dm;
 	struct stat	st;
 	audio_info_t	info;
-	int	i;
-	char	cmd_str[BUF_SIZE];
-	char	map[BUF_SIZE];
-	char	*prog;
-	FILE	*fp;
-	int	Audio_fd;
-	int	forced = 0;		/* Command line options */
-	int	initial = 0;
-	int	standard = 0;
-	int	verbose = 1;		/* default is to be verbose */
 
 	(void) setlocale(LC_ALL, "");
 	(void) textdomain(TEXT_DOMAIN);
@@ -126,8 +105,8 @@
 	 * the same thing.
 	 */
 
-	while ((i = getopt(argc, argv, "Iifs")) != EOF) {
-		switch (i) {
+	while ((c = getopt(argc, argv, "Iifs")) != -1) {
+		switch (c) {
 		case 'I':
 			verbose = 0;
 			initial++;
@@ -152,54 +131,49 @@
 		case '?':
 			err++;
 			break;
+		default:
+			err++;
+			break;
 		}
 		if (err) {
-			usage(prog, verbose);
+			if (verbose)
+				usage(prog);
 			exit(1);
 		}
-		argc -= optind;
-		argv += optind;
 	}
 
-	if (argv[0] == NULL) {	/* no device name */
-		usage(prog, verbose);
-		exit(1);
-	}
-
-	if (strlen(argv[0]) > (BUF_SIZE - sizeof (DMINFO) - 2)) {
-		(void) fprintf(stderr, gettext("device name %s too long\n"),
-		    argv[0]);
-		exit(1);
-	}
-
-	(void) strcpy(cmd_str, DMINFO);
-	(void) strcat(cmd_str, " ");
-	(void) strcat(cmd_str, argv[0]);	/* device name */
-
-	if ((fp = popen(cmd_str, "r")) == NULL) {
+	if ((argc - optind) != 1) {
 		if (verbose)
-			(void) fprintf(stderr,
-			    gettext("%s couldn't execute \"%s\"\n"), prog,
-			    cmd_str);
+			usage(prog);
 		exit(1);
+	} else {
+		devname = argv[optind];
 	}
 
-	if (fread(map, 1, BUF_SIZE, fp) == 0) {
+	setdmapent();
+	if ((dm = getdmapnam(devname)) == NULL) {
+		enddmapent();
 		if (verbose)
-			(void) fprintf(stderr,
-			    gettext("%s no results from \"%s\"\n"), prog,
-			    cmd_str);
-		exit(1);
+			(void) fprintf(stderr, "%s%s",
+			    devname,
+			    gettext(" : No such allocatable device\n"));
+			exit(1);
 	}
-
-	(void) pclose(fp);
-
-	first_field(map, Audio_dev);  /* Put the 1st field in dev */
+	enddmapent();
+	if (dm->dmap_devarray == NULL || dm->dmap_devarray[0] == NULL) {
+		if (verbose)
+			(void) fprintf(stderr, "%s%s",
+			    devname,
+			    gettext(" : No such allocatable device\n"));
+			exit(1);
+	}
+	devpath = strdup(dm->dmap_devarray[0]);
+	freedmapent(dm);
 
 	/*
 	 * Validate and open the audio device
 	 */
-	err = stat(Audio_dev, &st);
+	err = stat(devpath, &st);
 
 	if (err < 0) {
 		if (verbose) {
@@ -213,7 +187,7 @@
 		if (verbose)
 			(void) fprintf(stderr,
 			    gettext("%s: %s is not an audio device\n"), prog,
-			    Audio_dev);
+			    devpath);
 		exit(1);
 	}
 
@@ -222,26 +196,18 @@
 	 * using it we check to see if we're going to hang before we
 	 * do anything.
 	 */
-	/* Try it quickly, first */
-	Audio_fd = open(Audio_dev, O_WRONLY | O_NDELAY);
+	Audio_fd = open(devpath, O_WRONLY | O_NDELAY);
 
 	if ((Audio_fd < 0) && (errno == EBUSY)) {
 		if (verbose)
 			(void) fprintf(stderr, gettext("%s: waiting for %s..."),
-			    prog, Audio_dev);
-
-		/* Now hang until it's open */
-		Audio_fd = open(Audio_dev, O_WRONLY);
-		if (Audio_fd < 0) {
-			if (verbose)
-				perror(Audio_dev);
-			exit(1);
-		}
+			    prog, devpath);
+		exit(0);
 	} else if (Audio_fd < 0) {
 		if (verbose) {
 			(void) fprintf(stderr, gettext("%s: error opening "),
 			    prog);
-			perror(Audio_dev);
+			perror(devpath);
 		}
 		exit(1);
 	}
@@ -253,6 +219,7 @@
 
 	if (ioctl(Audio_fd, AUDIO_GETINFO, &info) != 0)  {
 		perror("Ioctl AUDIO_GETINFO error");
+		(void) close(Audio_fd);
 		exit(1);
 	}
 
@@ -265,12 +232,14 @@
 	if (ioctl(Audio_fd, AUDIO_SETINFO, &info) != 0) {
 		if (verbose)
 			perror(gettext("Ioctl AUDIO_SETINFO error"));
+		(void) close(Audio_fd);
 		exit(1);
 	}
 
 #ifdef	DEBUG
 	if (ioctl(Audio_fd, AUDIO_GETINFO, &info) != 0)  {
 		perror("Ioctl AUDIO_GETINFO-2 error");
+		(void) close(Audio_fd);
 		exit(1);
 	}
 
diff --git a/usr/src/cmd/dminfo/dminfo.c b/usr/src/cmd/allocate/dminfo.c
similarity index 90%
rename from usr/src/cmd/dminfo/dminfo.c
rename to usr/src/cmd/allocate/dminfo.c
index b1dc7ea..1a2d035 100644
--- a/usr/src/cmd/dminfo/dminfo.c
+++ b/usr/src/cmd/allocate/dminfo.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,19 +18,15 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
-#if !defined(lint) && defined(SCCSIDS)
-static char	*bsm_sccsid =
-		    "@(#)dminfo.c	1.8	05/06/15 SMI; SunOS BSM";
-#endif
-
 #include <locale.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <string.h>
 #include <unistd.h>
@@ -70,7 +65,7 @@
 {
 	(void) printf("%s:", dmapp->dmap_devname);
 	(void) printf("%s:", dmapp->dmap_devtype);
-	(void) printf("%s:", dmapp->dmap_devlist);
+	(void) printf("%s", dmapp->dmap_devlist);
 	(void) printf("\n");
 }
 
@@ -82,9 +77,7 @@
  *
  */
 static void
-dmapi_err(exit_code, err_msg)
-int	exit_code;
-char	*err_msg;
+dmapi_err(int exit_code, char *err_msg)
 {
 	if (err_msg != NULL) {
 		(void) fprintf(stderr, "dmapinfo:%s\n", err_msg);
@@ -107,12 +100,12 @@
 			prog_name,
 			"[-u Entry]");
 	}
+
 	exit(exit_code);
 }
 
-
 int
-main(int argc, char *argv[])
+main(int argc, char **argv)
 {
 	devmap_t *dmapp;
 	devmap_t dmap;
@@ -227,12 +220,12 @@
 			dmapi_err(EINVOKE,
 				gettext("Bad dmap_devname in entry argument"));
 		}
-		if ((dmap.dmap_devtype = getdmapfield((char *)NULL)) ==
+		if ((dmap.dmap_devtype = getdmapfield(NULL)) ==
 			NULL) {
 			dmapi_err(EINVOKE,
 				gettext("Bad dmap_devtype in entry Argument"));
 		}
-		if ((dmap.dmap_devlist = getdmapfield((char *)NULL)) ==
+		if ((dmap.dmap_devlist = getdmapfield(NULL)) ==
 			NULL) {
 			dmapi_err(EINVOKE,
 				gettext("Bad dmap_devlist in entry argument"));
@@ -319,21 +312,27 @@
 		nptr = getdmapdfield(nptr);
 		while (nptr) {
 			if (verbose) {
-(void) fprintf(stderr, gettext("dmapinfo: Check %s for device (%s).\n"),
-				filename, nptr);
+				(void) fprintf(stderr,
+				    gettext("dmapinfo: "
+					"Check %s for device (%s).\n"),
+				    filename, nptr);
 			}
 			if (getdmapdev(nptr) != NULL) {
 				if (verbose) {
-(void) fprintf(stderr, gettext("dmapinfo: Device (%s) found in %s.\n"),
-					nptr, filename);
+					(void) fprintf(stderr,
+					    gettext("dmapinfo: "
+						"Device (%s) found in %s.\n"),
+					    nptr, filename);
 				}
 				exit(1);
 			}
 			if (verbose) {
-(void) fprintf(stderr, gettext("dmapinfo: Device (%s) not found in %s.\n"),
-					nptr, filename);
+				(void) fprintf(stderr,
+				    gettext("dmapinfo: "
+					"Device (%s) not found in %s.\n"),
+				    nptr, filename);
 			}
-			nptr = getdmapdfield((char *)NULL);
+			nptr = getdmapdfield(NULL);
 		}
 		/*
 		 * Good the entry is uniq. So lets find out how long it is
@@ -390,17 +389,21 @@
 	 * of 1.
 	 */
 	if (device) {
+		setdmapent();
 		while (argc >= 1) {
 			if ((dmapp = getdmapdev(*argv)) != NULL) {
 				if (verbose) {
 					printdmapent(dmapp);
 				}
 				cntr++;
-			} else if (any == 0)
+			} else if (any == 0) {
+				enddmapent();
 				exit(1);
+			}
 			argc--;
 			argv++;
 		}
+		enddmapent();
 		if (cntr != 0)
 			exit(0);
 		exit(1);
@@ -413,6 +416,7 @@
 	 * of 1.
 	 */
 	if (name) {
+		setdmapent();
 		while (argc >= 1) {
 			if ((dmapp = getdmapnam(*argv)) != NULL) {
 				if (verbose) {
@@ -424,6 +428,7 @@
 			argc--;
 			argv++;
 		}
+		enddmapent();
 		if (cntr != 0)
 			exit(0);
 		exit(1);
@@ -438,20 +443,22 @@
 	 */
 	if (tp) {
 		cntr = 0;
+		setdmapent();
 		while (argc >= 1) {
-			setdmapent();
 			while ((dmapp = getdmaptype(*argv)) != 0) {
 				cntr++;
 				if (verbose) {
 					printdmapent(dmapp);
 				}
 			}
-			enddmapent();
-			if ((any == 0) && (cntr == 0))
+			if ((any == 0) && (cntr == 0)) {
+				enddmapent();
 				exit(1);
+			}
 			argc--;
 			argv++;
 		}
+		enddmapent();
 		if (cntr == 0)
 			exit(1);
 		exit(0);
diff --git a/usr/src/cmd/allocate/mkdevalloc.c b/usr/src/cmd/allocate/mkdevalloc.c
index 50c58af..e423e37 100644
--- a/usr/src/cmd/allocate/mkdevalloc.c
+++ b/usr/src/cmd/allocate/mkdevalloc.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -49,27 +49,40 @@
  *		/dev/nsr*
  *		/dev/dsk/c?t?d0s?
  *		/dev/rdsk/c?t?d0s?
+ *
  */
 
+#include <errno.h>
+#include <fcntl.h>
 #include <sys/types.h>	/* for stat(2), etc. */
 #include <sys/stat.h>
 #include <dirent.h>	/* for readdir(3), etc. */
 #include <unistd.h>	/* for readlink(2) */
+#include <stropts.h>
 #include <string.h>	/* for strcpy(3), etc. */
 #include <strings.h>	/* for bcopy(3C), etc. */
 #include <stdio.h>	/* for perror(3) */
 #include <stdlib.h>	/* for atoi(3) */
+#include <sys/dkio.h>
 #include <locale.h>
 #include <libintl.h>
+#include <libdevinfo.h>
+#include <secdb.h>
 #include <auth_attr.h>
 #include <auth_list.h>
-#include "allocate.h"   /* for SECLIB */
+#include <bsm/devices.h>
+#include <bsm/devalloc.h>
+#include <tsol/label.h>
 
 #ifndef TEXT_DOMAIN
 #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
 #endif
 
+#define	MKDEVALLOC	"mkdevalloc"
+#define	MKDEVMAPS	"mkdevmaps"
+
 #define	DELTA	5	/* array size delta when full */
+#define	SECLIB	"/etc/security/lib"
 
 /* "/dev/rst...", "/dev/nrst...", "/dev/rmt/..." */
 struct tape {
@@ -82,6 +95,7 @@
 #define	SIZE_OF_NRST 4		/* |nrmt| */
 #define	SIZE_OF_TMP  4		/* |/tmp| */
 #define	SIZE_OF_RMT  8		/* |/dev/rmt| */
+#define	TAPE_CLEAN    SECLIB"/st_clean"
 
 /* "/dev/audio", "/dev/audioctl", "/dev/sound/..." */
 struct audio {
@@ -91,6 +105,7 @@
 } *audio;
 #define	DFLT_NAUDIO   10	/* size of initial array */
 #define	SIZE_OF_SOUND 10	/* |/dev/sound| */
+#define	AUDIO_CLEAN   SECLIB"/audio_clean"
 
 /* "/dev/sr", "/dev/nsr", "/dev/dsk/c?t?d0s?", "/dev/rdsk/c?t?d0s?" */
 struct cd {
@@ -105,7 +120,17 @@
 #define	SIZE_OF_RSR  3		/* |rsr| */
 #define	SIZE_OF_DSK  8		/* |/dev/dsk| */
 #define	SIZE_OF_RDSK 9		/* |/dev/rdsk| */
+#define	CD_CLEAN    SECLIB"/sr_clean"
 
+/* "/dev/sr", "/dev/nsr", "/dev/dsk/c?t?d0s?", "/dev/rdsk/c?t?d0s?" */
+struct rmdisk {
+	char	*name;
+	char	*device;
+	int	id;
+	int	controller;
+	int	number;
+} *rmdisk, *rmdisk_r;
+#define	DFLT_RMDISK	10	/* size of initial array */
 
 /* "/dev/fd0*", "/dev/rfd0*", "/dev/fd1*", "/dev/rfd1*" */
 struct fp {
@@ -116,30 +141,72 @@
 #define	DFLT_NFP    10		/* size of initial array */
 #define	SIZE_OF_FD0  3		/* |fd0| */
 #define	SIZE_OF_RFD0 4		/* |rfd0| */
+#define	FLOPPY_CLEAN SECLIB"/fd_clean"
 
 static void dotape();
 static void doaudio();
 static void dofloppy();
-static void docd();
+static int docd();
+static void dormdisk(int);
 static void initmem();
 static int  expandmem(int, void **, int);
 static void no_memory(void);
 
+int		system_labeled = 0;
+int		do_devalloc = 0;
+int		do_devmaps = 0;
+int		do_files = 0;
+devlist_t	devlist;
+
 int
-main(void)
+main(int argc, char **argv)
 {
+	int		cd_count = 0;
+	char		*progname;
+	struct stat	tx_stat;
+
 	(void) setlocale(LC_ALL, "");
 	(void) textdomain(TEXT_DOMAIN);
 
+	if ((progname = strrchr(argv[0], '/')) == NULL)
+		progname = argv[0];
+	else
+		progname++;
+	if (strcmp(progname, MKDEVALLOC) == 0)
+		do_devalloc = 1;
+	else if (strcmp(progname, MKDEVMAPS) == 0)
+		do_devmaps = 1;
+	else
+		exit(1);
+
+	system_labeled = is_system_labeled();
+	if (system_labeled == 0) {
+		/*
+		 * is_system_labeled() will return false in case we are
+		 * starting before the first reboot after Trusted Extensions
+		 * is installed. we check for a well known TX binary to
+		 * to see if TX is installed.
+		 */
+		if (stat(DA_LABEL_CHECK, &tx_stat) == 0)
+			system_labeled = 1;
+	}
+
+	if (system_labeled && do_devalloc && (argc == 2) &&
+	    (strcmp(argv[1], DA_IS_LABELED) == 0)) {
+		/*
+		 * write device entries to device_allocate and device_maps.
+		 * default is to print them on stdout.
+		 */
+		do_files = 1;
+	}
+
 	initmem();		/* initialize memory */
-
-	dotape();		/* do tape */
-
-	doaudio();		/* do audio */
-
-	dofloppy();		/* do floppy */
-
-	docd();			/* do cd */
+	dotape();
+	doaudio();
+	dofloppy();
+	cd_count = docd();
+	if (system_labeled)
+		dormdisk(cd_count);
 
 	return (0);
 }
@@ -149,13 +216,18 @@
 {
 	DIR *dirp;
 	struct dirent *dep;	/* directory entry pointer */
-	int	i, j, n;
+	int	i, j;
 	char	*nm;		/* name/device of special device */
 	char	linkvalue[2048];	/* symlink value */
 	struct stat stat;	/* determine if it's a symlink */
 	int	sz;		/* size of symlink value */
 	char	*cp;		/* pointer into string */
 	int	ntape;		/* max array size */
+	int	tape_count;
+	int	first = 0;
+	char	*dname, *dtype, *dclean;
+	da_args	dargs;
+	deventry_t *entry;
 
 	ntape = DFLT_NTAPE;
 
@@ -260,30 +332,92 @@
 
 		i++;
 	}
-	n = i;
+	tape_count = i;
 
 	(void) closedir(dirp);
 
 	/* remove duplicate entries */
-	for (i = 0; i < n - 1; i++) {
-		for (j = i + 1; j < n; j++) {
+	for (i = 0; i < tape_count - 1; i++) {
+		for (j = i + 1; j < tape_count; j++) {
 			if (strcmp(tape[i].device, tape[j].device))
 				continue;
 			tape[j].number = -1;
 		}
 	}
 
-	/* print out device_allocate entries for tape devices */
+	if (system_labeled) {
+		dname = DA_TAPE_NAME;
+		dtype = DA_TAPE_TYPE;
+		dclean = DA_DEFAULT_TAPE_CLEAN;
+	} else {
+		dname = "st";
+		dtype = "st";
+		dclean = TAPE_CLEAN;
+	}
 	for (i = 0; i < 8; i++) {
-		for (j = 0; j < n; j++) {
-			if (tape[j].number == i) {
-				(void) printf(
-					"st%d;st;reserved;reserved;%s;",
-					i, DEFAULT_DEV_ALLOC_AUTH);
-				(void) printf("%s%s\n", SECLIB, "/st_clean");
+		for (j = 0; j < tape_count; j++) {
+			if (tape[j].number != i)
+				continue;
+			if (do_files) {
+				(void) da_add_list(&devlist, tape[j].name, i,
+				    DA_TAPE);
+			} else if (do_devalloc) {
+				/* print device_allocate for tape devices */
+				if (system_labeled) {
+					(void) printf("%s%d%s\\\n",
+					    dname, i, KV_DELIMITER);
+					(void) printf("\t%s%s\\\n",
+					    DA_TAPE_TYPE, KV_DELIMITER);
+					(void) printf("\t%s%s\\\n",
+					    DA_RESERVED, KV_DELIMITER);
+					(void) printf("\t%s%s\\\n",
+					    DA_RESERVED, KV_DELIMITER);
+					(void) printf("\t%s%s\\\n",
+					    DEFAULT_DEV_ALLOC_AUTH,
+					    KV_DELIMITER);
+					(void) printf("\t%s\n\n", dclean);
+				} else {
+					(void) printf(
+					    "st%d;st;reserved;reserved;%s;",
+					    i, DEFAULT_DEV_ALLOC_AUTH);
+					(void) printf("%s%s\n", SECLIB,
+					    "/st_clean");
+				}
 				break;
+			} else if (do_devmaps) {
+				/* print device_maps for tape devices */
+				if (first) {
+					(void) printf(" ");
+				} else {
+					if (system_labeled) {
+						(void) printf("%s%d%s\\\n",
+						    dname, i, KV_TOKEN_DELIMIT);
+						(void) printf("\t%s%s\\\n",
+						    dtype, KV_TOKEN_DELIMIT);
+						(void) printf("\t");
+					} else {
+						(void) printf("st%d:\\\n", i);
+						(void) printf("\trmt:\\\n");
+						(void) printf("\t");
+					}
+						first++;
+				}
+				(void) printf("%s", tape[j].name);
 			}
 		}
+		if (do_devmaps && first) {
+			(void) printf("\n\n");
+			first = 0;
+		}
+	}
+	if (do_files && tape_count) {
+		dargs.rootdir = NULL;
+		dargs.devnames = NULL;
+		dargs.optflag = DA_ADD;
+		for (entry = devlist.tape; entry != NULL; entry = entry->next) {
+			dargs.devinfo = &(entry->devinfo);
+			(void) da_update_device(&dargs);
+		}
 	}
 }
 
@@ -292,13 +426,20 @@
 {
 	DIR *dirp;
 	struct dirent *dep;	/* directory entry pointer */
-	int	i, j, n;
+	int	i, j;
 	char	*nm;		/* name/device of special device */
 	char	linkvalue[2048];	/* symlink value */
 	struct stat stat;	/* determine if it's a symlink */
 	int	sz;		/* size of symlink value */
 	char	*cp;		/* pointer into string */
 	int	naudio;		/* max array size */
+	int	audio_count = 0;
+	int	len, slen;
+	int	first = 0;
+	char	dname[128];
+	char	*dclean;
+	da_args	dargs;
+	deventry_t *entry;
 
 	naudio = DFLT_NAUDIO;
 
@@ -397,28 +538,90 @@
 	(void) closedir(dirp);
 
 skip:
-	n = i;
+	audio_count = i;
 
 	/* remove duplicate entries */
-	for (i = 0; i < n - 1; i++) {
-		for (j = i + 1; j < n; j++) {
+	for (i = 0; i < audio_count - 1; i++) {
+		for (j = i + 1; j < audio_count; j++) {
 			if (strcmp(audio[i].device, audio[j].device))
 				continue;
 			audio[j].number = -1;
 		}
 	}
 
-	/* print out device_allocate entries for tape devices */
+	/* print out device_allocate entries for audio devices */
+	(void) strcpy(dname, DA_AUDIO_NAME);
+	slen = strlen(DA_AUDIO_NAME);
+	len = sizeof (dname) - slen;
+	dclean = system_labeled ? DA_DEFAULT_AUDIO_CLEAN : AUDIO_CLEAN;
 	for (i = 0; i < 8; i++) {
-		for (j = 0; j < n; j++) {
-			if (audio[j].number == i) {
-				(void) printf("audio;audio;");
-				(void) printf("reserved;reserved;%s;",
-				    DEFAULT_DEV_ALLOC_AUTH);
-				(void) printf("%s%s\n", SECLIB, "/audio_clean");
+		for (j = 0; j < audio_count; j++) {
+			if (audio[j].number != i)
+				continue;
+			if (system_labeled)
+				(void) snprintf(dname+slen, len, "%d", i);
+			if (do_files) {
+				(void) da_add_list(&devlist, audio[j].name,
+				    i, DA_AUDIO);
+			} else if (do_devalloc) {
+				/* print device_allocate for audio devices */
+				if (system_labeled) {
+					(void) printf("%s%s\\\n",
+					    dname, KV_DELIMITER);
+					(void) printf("\t%s%s\\\n",
+					    DA_AUDIO_TYPE, KV_DELIMITER);
+					(void) printf("\t%s%s\\\n",
+					    DA_RESERVED, KV_DELIMITER);
+					(void) printf("\t%s%s\\\n",
+					    DA_RESERVED, KV_DELIMITER);
+					(void) printf("\t%s%s\\\n",
+					    DEFAULT_DEV_ALLOC_AUTH,
+					    KV_DELIMITER);
+					(void) printf("\t%s\n\n", dclean);
+				} else {
+					(void) printf("audio;audio;");
+					(void) printf("reserved;reserved;%s;",
+					    DEFAULT_DEV_ALLOC_AUTH);
+					(void) printf("%s%s\n", SECLIB,
+					    "/audio_clean");
+				}
 				break;
+			} else if (do_devmaps) {
+				/* print device_maps for audio devices */
+				if (first) {
+					(void) printf(" ");
+				} else {
+					if (system_labeled) {
+						(void) printf("%s%s\\\n",
+						    dname, KV_TOKEN_DELIMIT);
+						(void) printf("\t%s%s\\\n",
+						    DA_AUDIO_TYPE,
+						    KV_TOKEN_DELIMIT);
+						(void) printf("\t");
+					} else {
+						(void) printf("audio:\\\n");
+						(void) printf("\taudio:\\\n");
+						(void) printf("\t");
+					}
+					first++;
+				}
+				(void) printf("%s", audio[j].name);
 			}
 		}
+		if (do_devmaps && first) {
+			(void) printf("\n\n");
+			first = 0;
+		}
+	}
+	if (do_files && audio_count) {
+		dargs.rootdir = NULL;
+		dargs.devnames = NULL;
+		dargs.optflag = DA_ADD;
+		for (entry = devlist.audio; entry != NULL;
+		    entry = entry->next) {
+			dargs.devinfo = &(entry->devinfo);
+			(void) da_update_device(&dargs);
+		}
 	}
 }
 
@@ -427,13 +630,18 @@
 {
 	DIR *dirp;
 	struct dirent *dep;	/* directory entry pointer */
-	int i, j, n;
+	int i, j;
 	char *nm;		/* name/device of special device */
 	char linkvalue[2048];	/* symlink value */
 	struct stat stat;	/* determine if it's a symlink */
 	int sz;			/* size of symlink value */
 	char *cp;		/* pointer into string */
 	int nfp;		/* max array size */
+	int floppy_count = 0;
+	int first = 0;
+	char *dname, *dclean;
+	da_args dargs;
+	deventry_t *entry;
 
 	nfp = DFLT_NFP;
 
@@ -500,27 +708,96 @@
 
 	(void) closedir(dirp);
 
-	n = i;
+	floppy_count = i;
 
-	/* print out device_allocate entries for tape devices */
+	/* print out device_allocate entries for floppy devices */
+	if (system_labeled) {
+		dname = DA_FLOPPY_NAME;
+		dclean = DA_DEFAULT_DISK_CLEAN;
+	} else {
+		dname = "fd";
+		dclean = FLOPPY_CLEAN;
+	}
 	for (i = 0; i < 8; i++) {
-	    for (j = 0; j < n; j++) {
-		if (fp[j].number == i) {
-		    (void) printf("fd%d;fd;reserved;reserved;%s;",
-			i, DEFAULT_DEV_ALLOC_AUTH);
-		    (void) printf("/etc/security/lib/fd_clean\n");
-		    break;
+		for (j = 0; j < floppy_count; j++) {
+			if (fp[j].number != i)
+				continue;
+			if (do_files) {
+				(void) da_add_list(&devlist, fp[j].name, i,
+				    DA_FLOPPY);
+			} else if (do_devalloc) {
+				/* print device_allocate for floppy devices */
+				if (system_labeled) {
+					(void) printf("%s%d%s\\\n",
+					    dname, i, KV_DELIMITER);
+					(void) printf("\t%s%s\\\n",
+					    DA_FLOPPY_TYPE, KV_DELIMITER);
+					(void) printf("\t%s%s\\\n",
+					    DA_RESERVED, KV_DELIMITER);
+					(void) printf("\t%s%s\\\n",
+					    DA_RESERVED, KV_DELIMITER);
+					(void) printf("\t%s%s\\\n",
+					    DEFAULT_DEV_ALLOC_AUTH,
+					    KV_DELIMITER);
+					(void) printf("\t%s\n\n", dclean);
+				} else {
+					(void) printf(
+					    "fd%d;fd;reserved;reserved;%s;",
+					    i, DEFAULT_DEV_ALLOC_AUTH);
+					(void) printf("%s%s\n", SECLIB,
+					    "/fd_clean");
+				}
+				break;
+			} else if (do_devmaps) {
+				/* print device_maps for floppy devices */
+				if (first) {
+					(void) printf(" ");
+				} else {
+					if (system_labeled) {
+						(void) printf("%s%d%s\\\n",
+						    dname, i, KV_TOKEN_DELIMIT);
+						(void) printf("\t%s%s\\\n",
+						    DA_FLOPPY_TYPE,
+						    KV_TOKEN_DELIMIT);
+						(void) printf("\t");
+					} else {
+						(void) printf("fd%d:\\\n", i);
+						(void) printf("\tfd:\\\n");
+						(void) printf("\t");
+					}
+					if (i == 0) {
+						(void) printf("/dev/diskette ");
+						(void) printf(
+						    "/dev/rdiskette ");
+					}
+					first++;
+				}
+				(void) printf("%s", fp[j].name);
+			}
 		}
-	    }
+		if (do_devmaps && first) {
+			(void) printf("\n\n");
+			first = 0;
+		}
+	}
+	if (do_files && floppy_count) {
+		dargs.rootdir = NULL;
+		dargs.devnames = NULL;
+		dargs.optflag = DA_ADD;
+		for (entry = devlist.floppy; entry != NULL;
+		    entry = entry->next) {
+			dargs.devinfo = &(entry->devinfo);
+			(void) da_update_device(&dargs);
+		}
 	}
 }
 
-static void
+static int
 docd()
 {
 	DIR *dirp;
 	struct dirent *dep;	/* directory entry pointer */
-	int	i, j, n;
+	int	i, j;
 	char	*nm;		/* name/device of special device */
 	char	linkvalue[2048];	/* symlink value */
 	struct stat stat;	/* determine if it's a symlink */
@@ -529,6 +806,11 @@
 	int	id;		/* disk id */
 	int	ctrl;		/* disk controller */
 	int	ncd;		/* max array size */
+	int	cd_count = 0;
+	int	first = 0;
+	char	*dname, *dclean;
+	da_args	dargs;
+	deventry_t *entry;
 
 	ncd = DFLT_NCD;
 
@@ -580,6 +862,7 @@
 		if ((sz = readlink(cd[i].name, linkvalue, sizeof (linkvalue))) <
 		    0)
 			continue;
+
 		nm = (char *)malloc(sz + 1);
 		if (nm == NULL)
 			no_memory();
@@ -593,7 +876,7 @@
 
 		i++;
 	}
-	n = i;
+	cd_count = i;
 
 	(void) closedir(dirp);
 
@@ -616,7 +899,7 @@
 			continue;
 
 		/* see if this is one of the cd special devices */
-		for (j = 0; j < n; j++) {
+		for (j = 0; j < cd_count; j++) {
 			if (cd[j].number == id && cd[j].controller == ctrl)
 				goto found;
 		}
@@ -667,7 +950,7 @@
 			continue;
 
 		/* see if this is one of the cd special devices */
-		for (j = 0; j < n; j++) {
+		for (j = 0; j < cd_count; j++) {
 			if (cd[j].number == id && cd[j].controller == ctrl)
 				goto found1;
 		}
@@ -701,18 +984,255 @@
 
 	(void) closedir(dirp);
 
-	n = i;
+	cd_count = i;
 
-	/* print out device_maps entries for tape devices */
+	if (system_labeled) {
+		dname = DA_CD_NAME;
+		dclean = DA_DEFAULT_DISK_CLEAN;
+	} else {
+		dname = "sr";
+		dclean = CD_CLEAN;
+	}
 	for (i = 0; i < 8; i++) {
-		for (j = 0; j < n; j++) {
-			if (cd[j].id == i) {
-				(void) printf(
-					"sr%d;sr;reserved;reserved;%s;",
-					i, DEFAULT_DEV_ALLOC_AUTH);
-				(void) printf("%s%s\n", SECLIB, "/sr_clean");
+		for (j = 0; j < cd_count; j++) {
+			if (cd[j].id != i)
+				continue;
+			if (do_files) {
+				(void) da_add_list(&devlist, cd[j].name, i,
+				    DA_CD);
+			} else if (do_devalloc) {
+				/* print device_allocate for cd devices */
+				if (system_labeled) {
+					(void) printf("%s%d%s\\\n",
+					    dname, i, KV_DELIMITER);
+					(void) printf("\t%s%s\\\n",
+					    DA_CD_TYPE, KV_DELIMITER);
+					(void) printf("\t%s%s\\\n",
+					    DA_RESERVED, KV_DELIMITER);
+					(void) printf("\t%s%s\\\n",
+					    DA_RESERVED, KV_DELIMITER);
+					(void) printf("\t%s%s\\\n",
+					    DEFAULT_DEV_ALLOC_AUTH,
+					    KV_DELIMITER);
+					(void) printf("\t%s\n\n", dclean);
+				} else {
+					(void) printf(
+					    "sr%d;sr;reserved;reserved;%s;",
+					    i, DEFAULT_DEV_ALLOC_AUTH);
+					(void) printf("%s%s\n", SECLIB,
+					    "/sr_clean");
+				}
+				break;
+			} else if (do_devmaps) {
+				/* print device_maps for cd devices */
+				if (first) {
+					(void) printf(" ");
+				} else {
+					if (system_labeled) {
+						(void) printf("%s%d%s\\\n",
+						    dname, i, KV_TOKEN_DELIMIT);
+						(void) printf("\t%s%s\\\n",
+						    DA_CD_TYPE,
+						    KV_TOKEN_DELIMIT);
+						(void) printf("\t");
+					} else {
+						(void) printf("sr%d:\\\n", i);
+						(void) printf("\tsr:\\\n");
+						(void) printf("\t");
+					}
+					first++;
+				}
+				(void) printf("%s", cd[j].name);
+			}
+		}
+		if (do_devmaps && first) {
+			(void) printf("\n\n");
+			first = 0;
+		}
+	}
+	if (do_files && cd_count) {
+		dargs.rootdir = NULL;
+		dargs.devnames = NULL;
+		dargs.optflag = DA_ADD;
+		for (entry = devlist.cd; entry != NULL; entry = entry->next) {
+			dargs.devinfo = &(entry->devinfo);
+			(void) da_update_device(&dargs);
+		}
+	}
+
+	return (cd_count);
+}
+
+static void
+dormdisk(int cd_count)
+{
+	DIR *dirp;
+	struct dirent *dep;	/* directory entry pointer */
+	int	i, j;
+	char	*nm;		/* name/device of special device */
+	int	id;		/* disk id */
+	int	ctrl;		/* disk controller */
+	int	nrmdisk;	/* max array size */
+	int	fd = -1;
+	int	rmdisk_count;
+	int	first = 0;
+	int	is_cd;
+	int	checked;
+	int	removable;
+	char	path[MAXPATHLEN];
+	da_args	dargs;
+	deventry_t *entry;
+
+	nrmdisk = DFLT_RMDISK;
+	i = rmdisk_count = 0;
+
+	/*
+	 * scan /dev/dsk for rmdisk devices
+	 */
+	if ((dirp = opendir("/dev/dsk")) == NULL) {
+		perror("gettext(open /dev/dsk failure)");
+		exit(1);
+	}
+
+	while (dep = readdir(dirp)) {
+		is_cd = 0;
+		checked = 0;
+		removable = 0;
+		/* skip . .. etc... */
+		if (strncmp(dep->d_name, ".", 1) == NULL)
+			continue;
+
+		/* get device # (disk #) */
+		if (sscanf(dep->d_name, "c%dt%d", &ctrl, &id) <= 0)
+			continue;
+
+		/* see if we've already examined this device */
+		for (j = 0; j < i; j++) {
+			if (id == rmdisk[j].id &&
+			    ctrl == rmdisk[j].controller &&
+			    (strcmp(dep->d_name, rmdisk[j].name) == 0)) {
+				checked = 1;
 				break;
 			}
+			if (id == rmdisk[j].id && ctrl != rmdisk[j].controller)
+				/*
+				 * c2t0d0s0 is a different rmdisk than c3t0d0s0.
+				 */
+				id = rmdisk[j].id + 1;
+		}
+		if (checked)
+			continue;
+
+		/* ignore if this is a cd */
+		for (j = 0; j < cd_count; j++) {
+			if (id == cd[j].number && ctrl == cd[j].controller) {
+				is_cd = 1;
+				break;
+			}
+		}
+		if (is_cd)
+			continue;
+
+		/* see if device is removable */
+		(void) snprintf(path, sizeof (path), "%s%s", "/dev/rdsk/",
+		    dep->d_name);
+		if ((fd = open(path, O_RDONLY | O_NONBLOCK)) < 0)
+			continue;
+		(void) ioctl(fd, DKIOCREMOVABLE, &removable);
+		(void) close(fd);
+		if (removable == 0)
+			continue;
+
+		/*
+		 * add new entry to table (/dev/dsk + / + d_name + \0)
+		 * if array full, then expand it
+		 */
+		if (i == nrmdisk) {
+			/* will exit(1) if insufficient memory */
+			nrmdisk = expandmem(i, (void **)&rmdisk,
+			    sizeof (struct rmdisk));
+		}
+		nm = (char *)malloc(SIZE_OF_DSK + 1 + strlen(dep->d_name) + 1);
+		if (nm == NULL)
+			no_memory();
+		(void) strcpy(nm, "/dev/dsk/");
+		(void) strcat(nm, dep->d_name);
+		rmdisk[i].name = nm;
+		rmdisk[i].id = id;
+		rmdisk[i].controller = ctrl;
+		rmdisk[i].device = "";
+		rmdisk[i].number = id;
+		rmdisk_r[i].name = strdup(path);
+		i++;
+	}
+
+	rmdisk_count = i;
+	(void) closedir(dirp);
+
+	for (i = 0, j = rmdisk_count; i < rmdisk_count; i++, j++) {
+		if (j == nrmdisk) {
+			/* will exit(1) if insufficient memory */
+			nrmdisk = expandmem(j, (void **)&rmdisk,
+			    sizeof (struct rmdisk));
+		}
+		rmdisk[j].name = rmdisk_r[i].name;
+		rmdisk[j].id = rmdisk[i].id;
+		rmdisk[j].controller = rmdisk[i].controller;
+		rmdisk[j].device = rmdisk[i].device;
+		rmdisk[j].number = rmdisk[i].number;
+	}
+	rmdisk_count = j;
+
+	for (i = 0; i < 8; i++) {
+		for (j = 0; j < rmdisk_count; j++) {
+			if (rmdisk[j].id != i)
+				continue;
+			if (do_files) {
+				(void) da_add_list(&devlist, rmdisk[j].name, i,
+				    DA_RMDISK);
+			} else if (do_devalloc) {
+				/* print device_allocate for rmdisk devices */
+				(void) printf("%s%d%s\\\n",
+				    DA_RMDISK_NAME, i, KV_DELIMITER);
+				(void) printf("\t%s%s\\\n",
+				    DA_RMDISK_TYPE, KV_DELIMITER);
+				(void) printf("\t%s%s\\\n",
+				    DA_RESERVED, KV_DELIMITER);
+				(void) printf("\t%s%s\\\n",
+				    DA_RESERVED, KV_DELIMITER);
+				(void) printf("\t%s%s\\\n",
+				    DEFAULT_DEV_ALLOC_AUTH, KV_DELIMITER);
+				(void) printf("\t%s\n", DA_DEFAULT_DISK_CLEAN);
+				break;
+			} else if (do_devmaps) {
+				/* print device_maps for rmdisk devices */
+				if (first) {
+					(void) printf(" ");
+				} else {
+					(void) printf("%s%d%s\\\n",
+					    DA_RMDISK_NAME, i,
+					    KV_TOKEN_DELIMIT);
+					(void) printf("\t%s%s\\\n",
+					    DA_RMDISK_TYPE, KV_TOKEN_DELIMIT);
+					(void) printf("\t");
+					first++;
+				}
+				(void) printf("%s", rmdisk[j].name);
+			}
+		}
+		if (do_devmaps && first) {
+			(void) printf("\n\n");
+			first = 0;
+		}
+	}
+	if (do_files && rmdisk_count) {
+		dargs.rootdir = NULL;
+		dargs.devnames = NULL;
+		dargs.optflag = DA_ADD;
+		for (entry = devlist.rmdisk; entry != NULL;
+		    entry = entry->next) {
+			dargs.devinfo = &(entry->devinfo);
+			(void) da_update_device(&dargs);
 		}
 	}
 }
@@ -725,9 +1245,22 @@
 	audio = (struct audio *)calloc(DFLT_NAUDIO, sizeof (struct audio));
 	cd    = (struct cd *)calloc(DFLT_NCD, sizeof (struct cd));
 	fp    = (struct fp *)calloc(DFLT_NFP, sizeof (struct fp));
+	if (system_labeled) {
+		rmdisk = (struct rmdisk *)calloc(DFLT_RMDISK,
+		    sizeof (struct rmdisk));
+		if (rmdisk == NULL)
+			no_memory();
+		rmdisk_r = (struct rmdisk *)calloc(DFLT_RMDISK,
+		    sizeof (struct rmdisk));
+		if (rmdisk_r == NULL)
+			no_memory();
+	}
 
 	if (tape == NULL || audio == NULL || cd == NULL || fp == NULL)
 		no_memory();
+
+	devlist.audio = devlist.cd = devlist.floppy = devlist.rmdisk =
+	    devlist.tape = NULL;
 }
 
 /* note n will be # elments in array (and could be 0) */
diff --git a/usr/src/cmd/auditconfig/auditconfig.c b/usr/src/cmd/auditconfig/auditconfig.c
index 46d42cd..57c6f7d 100644
--- a/usr/src/cmd/auditconfig/auditconfig.c
+++ b/usr/src/cmd/auditconfig/auditconfig.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -52,6 +51,7 @@
 #include <pwd.h>
 #include <libintl.h>
 #include <zone.h>
+#include <tsol/label.h>
 
 #include <bsm/audit.h>
 #include <bsm/audit_record.h>
@@ -117,6 +117,10 @@
 #define	AC_KERN_EVENT 		0
 #define	AC_USER_EVENT 		1
 
+/* defines for policy entry flags: */
+
+#define	AC_TSOL 		1	/* policy is TSOL-only */
+
 #define	NONE(s) (!strlen(s) ? gettext("none") : s)
 
 #define	ALL_POLICIES   (AUDIT_AHLT|\
@@ -131,7 +135,9 @@
 			AUDIT_PATH|\
 			AUDIT_PUBLIC|\
 			AUDIT_ZONENAME|\
-			AUDIT_PERZONE)
+			AUDIT_PERZONE|\
+			AUDIT_WINDATA_DOWN|\
+			AUDIT_WINDATA_UP)
 
 #define	NO_POLICIES  (0)
 
@@ -153,6 +159,7 @@
 struct policy_entry {
 	char *policy_str;
 	uint_t policy_mask;
+	uint_t policy_flags;
 	char *policy_desc;
 };
 
@@ -236,27 +243,40 @@
 #define	ARG2_TBL_SZ (sizeof (arg2_table) / sizeof (struct arg_entry))
 
 static struct policy_entry policy_table[] = {
-	{"ahlt",  AUDIT_AHLT,   "halt machine if it can not record an "
-	    "async event"},
-	{"arge",  AUDIT_ARGE,   "include exec environment args in audit recs"},
-	{"argv",  AUDIT_ARGV,   "include exec command line args in audit recs"},
-	{"cnt",   AUDIT_CNT,    "when no more space, drop recs and keep a cnt"},
-	{"group", AUDIT_GROUP,  "include supplementary groups in audit recs"},
-	{"seq",   AUDIT_SEQ,    "include a sequence number in audit recs"},
-	{"trail", AUDIT_TRAIL,  "include trailer token in audit recs"},
-	{"path",  AUDIT_PATH,   "allow multiple paths per event"},
-	{"public",  AUDIT_PUBLIC,   "audit public files"},
-	{"zonename", AUDIT_ZONENAME,    "generate zonename token"},
-	{"perzone", AUDIT_PERZONE,	"use a separate queue and auditd per "
-	    "zone"},
-	{"all",   ALL_POLICIES, "all policies"},
-	{"none",  NO_POLICIES,  "no policies"}
+	{"ahlt",	AUDIT_AHLT,	NULL,
+	    "halt machine if it can not record an async event"},
+	{"arge",	AUDIT_ARGE,	NULL,
+	    "include exec environment args in audit recs"},
+	{"argv",	AUDIT_ARGV,	NULL,
+	    "include exec command line args in audit recs"},
+	{"cnt",		AUDIT_CNT,	NULL,
+	    "when no more space, drop recs and keep a cnt"},
+	{"group",	AUDIT_GROUP,	NULL,
+	    "include supplementary groups in audit recs"},
+	{"path",	AUDIT_PATH,	NULL,
+	    "allow multiple paths per event"},
+	{"public",	AUDIT_PUBLIC,	NULL,	"audit public files"},
+	{"seq",		AUDIT_SEQ,	NULL,
+	    "include a sequence number in audit recs"},
+	{"trail",	AUDIT_TRAIL,	NULL,
+	    "include trailer token in audit recs"},
+	{"windata_down",	AUDIT_WINDATA_DOWN,	AC_TSOL,
+		"include downgraded information in audit recs"},
+	{"windata_up",		AUDIT_WINDATA_UP,	AC_TSOL,
+		"include upgraded information in audit recs"},
+	{"zonename",	AUDIT_ZONENAME,	NULL,	"generate zonename token"},
+	{"perzone",	AUDIT_PERZONE,	NULL,
+	    "use a separate queue and auditd per zone"},
+	{"all",		ALL_POLICIES,	NULL,	"all policies"},
+	{"none",	NO_POLICIES,	NULL,	"no policies"}
 	};
 
 #define	POLICY_TBL_SZ (sizeof (policy_table) / sizeof (struct policy_entry))
 
 static char *progname;
 
+int	tsol_on;			/* is TSOL installed? */
+
 static au_event_ent_t *egetauevnam();
 static au_event_ent_t *egetauevnum();
 static char *strtolower();
@@ -368,6 +388,8 @@
 		strcmp(argv[1], "-?") == 0))
 		exit_usage(0);
 
+	tsol_on = is_system_labeled();
+
 	parse_args(argv);
 
 	do_args(argv);
@@ -1246,6 +1268,15 @@
 				"Could not allocate subject token\n"));
 		if (au_write(rd, tokp) == -1)
 exit_error(gettext("Could not construct subject token of audit record\n"));
+
+		if (tsol_on) {
+			if ((tokp = au_to_mylabel()) == (token_t *)NULL)
+				exit_error(gettext(
+				    "Could not allocate slabel token\n"));
+			if (au_write(rd, tokp) == -1)
+exit_error(gettext("Could not construct slabel token of audit record\n"));
+		}
+
 		if ((tokp = au_to_text(audit_str)) == (token_t *)NULL)
 			exit_error(gettext("Could not allocate text token\n"));
 		if (au_write(rd, tokp) == -1)
@@ -1634,10 +1665,12 @@
 	 *	Print a properly aligned header.
 	 */
 	(void) printf(gettext("policy string    description:\n"));
-	for (i = 0; i < POLICY_TBL_SZ; i++)
-		(void) printf("%-17s%s\n",
-			policy_table[i].policy_str,
-			gettext(policy_table[i].policy_desc));
+	for (i = 0; i < POLICY_TBL_SZ; i++) {
+		if ((policy_table[i].policy_flags & AC_TSOL) && !tsol_on)
+			continue;	/* skip this entry */
+		(void) printf("%-17s%s\n", policy_table[i].policy_str,
+		    gettext(policy_table[i].policy_desc));
+	}
 }
 
 static void
@@ -2295,10 +2328,12 @@
 {
 	int i;
 
-	for (i = 0; i < POLICY_TBL_SZ; i++)
-		if (strcmp(strtolower(policy),
-			policy_table[i].policy_str) == 0)
+	for (i = 0; i < POLICY_TBL_SZ; i++) {
+		if ((policy_table[i].policy_flags & AC_TSOL) && !tsol_on)
+			continue;	/* skip this entry */
+		if (strcmp(strtolower(policy), policy_table[i].policy_str) == 0)
 			return (&policy_table[i]);
+	}
 
 	return ((struct policy_entry *)NULL);
 }
@@ -2389,7 +2424,9 @@
 
 	*policy_str = '\0';
 
-	for (i = 0, j = 0; i < POLICY_TBL_SZ; i++)
+	for (i = 0, j = 0; i < POLICY_TBL_SZ; i++) {
+		if ((policy_table[i].policy_flags & AC_TSOL) && !tsol_on)
+			continue;	/* skip this entry */
 		if (policy & policy_table[i].policy_mask &&
 		    policy_table[i].policy_mask != ALL_POLICIES) {
 			if (j++)
@@ -2397,6 +2434,7 @@
 			(void) strlcat(policy_str,
 			    policy_table[i].policy_str, len);
 		}
+	}
 
 	if (*policy_str)
 		return (0);
diff --git a/usr/src/cmd/auditreduce/Makefile b/usr/src/cmd/auditreduce/Makefile
index 7d10fd2..b63b6c9 100644
--- a/usr/src/cmd/auditreduce/Makefile
+++ b/usr/src/cmd/auditreduce/Makefile
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -18,9 +17,11 @@
 # information: Portions Copyright [yyyy] [name of copyright owner]
 #
 # CDDL HEADER END
+
+
 #
 #
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -39,7 +40,9 @@
 POFILES=main.po option.po proc.po time.po token.po
 
 CPPFLAGS += -I$(TABLEDIR) -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
-LDLIBS += -lnsl -lbsm
+LAZYLIBS = $(ZLAZYLOAD) -ltsol $(ZNOLAZYLOAD)
+lint := LAZYLIBS = -ltsol
+LDLIBS += -lnsl -lbsm  $(LAZYLIBS)
 
 .KEEP_STATE:
 
diff --git a/usr/src/cmd/auditreduce/auditr.h b/usr/src/cmd/auditreduce/auditr.h
index 6146203..de5e26b 100644
--- a/usr/src/cmd/auditreduce/auditr.h
+++ b/usr/src/cmd/auditreduce/auditr.h
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
  * CDDL HEADER END
  */
 /*
- * Copyright (c) 1987 - 2000 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
  */
 
 #ifndef _AUDITR_H
@@ -62,6 +61,9 @@
 #include <bsm/audit_record.h>
 #include <bsm/libbsm.h>
 
+#include <tsol/label.h>
+#include <sys/tsol/label_macro.h>
+
 #include "auditrt.h"
 
 /*
diff --git a/usr/src/cmd/auditreduce/auditrd.h b/usr/src/cmd/auditreduce/auditrd.h
index 22f65b7..bcd498c 100644
--- a/usr/src/cmd/auditreduce/auditrd.h
+++ b/usr/src/cmd/auditreduce/auditrd.h
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -51,9 +50,7 @@
 time_t	m_before;		/* 'b' before a time */
 audit_state_t mask;		/* used with m_class */
 char	*zonename;		/* 'z' zonename */
-#ifdef	TSOL
-brange_t m_label;		/* 'l' mandatory label range */
-#endif	/* TSOL */
+m_range_t *m_label;		/* 'l' mandatory label range */
 int	flags;
 int	checkflags;
 int	socket_flag;
diff --git a/usr/src/cmd/auditreduce/auditrt.h b/usr/src/cmd/auditreduce/auditrt.h
index d929030..f013cbf 100644
--- a/usr/src/cmd/auditreduce/auditrt.h
+++ b/usr/src/cmd/auditreduce/auditrt.h
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -175,9 +174,7 @@
 extern audit_state_t mask;	/* used with m_class */
 extern char	*zonename;	/* 'z' zonename */
 
-#ifdef	TSOL
-extern brange_t m_label;	/* 'l' mandatory label range */
-#endif	/* TSOL */
+extern m_range_t *m_label;	/* 'l' mandatory label range */
 extern int	flags;
 extern int	checkflags;
 extern int	socket_flag;
diff --git a/usr/src/cmd/auditreduce/option.c b/usr/src/cmd/auditreduce/option.c
index 181a383..f4aaa9d 100644
--- a/usr/src/cmd/auditreduce/option.c
+++ b/usr/src/cmd/auditreduce/option.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -34,11 +33,6 @@
 
 #include <locale.h>
 #include <sys/zone.h>	/* for max zonename length */
-
-#ifdef	TSOL
-#include <tsol/label.h>
-#endif	/* TSOL */
-
 #include "auditr.h"
 
 /*
@@ -95,9 +89,7 @@
 static int	proc_id(char *, int);
 static int	proc_object(char *);
 static void	proc_pcb(audit_pcb_t *, char *, int);
-#ifdef	TSOL
 static int	proc_slabel(char *);
-#endif	/* TSOL */
 static int	proc_subject(char *);
 static int	proc_sid(char *);
 static int	proc_type(char *);
@@ -203,12 +195,16 @@
 			if (proc_id(optarg, opt))
 				error = TRUE;
 			break;
-#ifdef	TSOL
 		case 'l':		/* label range -- reserved for TX */
+			if (!is_system_labeled()) {
+				(void) fprintf(stderr,
+				    gettext("%s option 'l' requires "
+				    "Trusted Extensions.\n"), ar);
+				return (-1);
+			}
 			if (proc_slabel(optarg))
 				error = TRUE;
 			break;
-#endif	/* TSOL */
 		case 's':		/* session ID */
 			if (proc_sid(optarg))
 				error = TRUE;
@@ -1137,7 +1133,6 @@
 }
 
 
-#ifdef	TSOL
 /*
  * .func	proc_slabel - process sensitivity label range argument.
  * .desc	Parse sensitivity label range sl:sl
@@ -1157,67 +1152,101 @@
 		error_str = gettext("'l' option specified multiple times");
 		return (-1);
 	}
-
 	flags |= M_LABEL;
-	p = strchr(optstr, ':');
+
+	if ((m_label = malloc(sizeof (m_range_t))) == NULL) {
+		return (-1);
+	}
+	m_label->lower_bound = NULL;
+	m_label->upper_bound = NULL;
+
+	p = strchr(optstr, ';');
 	if (p == NULL) {
 		/* exact label match, lower and upper range bounds the same */
-		if (stobsl(optstr, &m_slabel.lower_bound, NO_CORRECTION,
-		    &error) == 0) {
+		if (str_to_label(optstr, &m_label->lower_bound, MAC_LABEL,
+		    L_NO_CORRECTION, &error) == -1) {
 			(void) sprintf(errbuf,
 			    gettext("invalid sensitivity label (%s) err %d"),
 			    optstr, error);
 			error_str = errbuf;
-			return (-1);
+			goto errout;
 		}
-		m_slabel.upper_bound = m_slabel.lower_bound;
+		m_label->upper_bound = m_label->lower_bound;
 		return (0);
 	}
 	if (p == optstr) {
 		/* lower bound is not specified .. default is admin_low */
-		bsllow(&m_slabel.lower_bound);
-		if (stobsl(p + 1, &m_slabel.upper_bound, NO_CORRECTION,
-		    &error) == 0) {
-			(void) sprintf(errbuf,
-			    gettext("invalid sensitivity label (%s) err %d"),
-			    p + 1, error);
-			error_str = errbuf;
+		if (str_to_label(ADMIN_LOW, &m_label->lower_bound, MAC_LABEL,
+		    L_NO_CORRECTION, &error) == -1) {
+			free(m_label);
 			return (-1);
 		}
+
+		p++;
+		if (*p == '\0') {
+			/* upper bound not specified .. default is admin_high */
+			if (str_to_label(ADMIN_HIGH, &m_label->upper_bound,
+			    MAC_LABEL, L_NO_CORRECTION, &error) == -1) {
+				m_label_free(m_label->lower_bound);
+				free(m_label);
+				return (-1);
+			}
+		} else {
+			if (str_to_label(p, &m_label->upper_bound, MAC_LABEL,
+			    L_NO_CORRECTION, &error) == -1) {
+				(void) sprintf(errbuf, gettext(
+				    "invalid sensitivity label (%s) err %d"),
+				    p, error);
+				error_str = errbuf;
+				goto errout;
+			}
+		}
 		return (0);
 	}
 	*p++ = '\0';
-	if (stobsl(optstr, &m_slabel.lower_bound, NO_CORRECTION, &error) == 0) {
+	if (str_to_label(optstr, &m_label->lower_bound, MAC_LABEL,
+	    L_NO_CORRECTION, &error) == -1) {
 		(void) sprintf(errbuf,
 		    gettext("invalid sensitivity label (%s) err %d"), optstr,
 		    error);
 		error_str = errbuf;
-		return (-1);
+		goto errout;
 	}
-	if (*p == '\0')
+	if (*p == '\0') {
 		/* upper bound is not specified .. default is admin_high */
-		bslhigh(&m_slabel.upper_bound);
-	else {
-		if (stobsl(p, &m_slabel.upper_bound, NO_CORRECTION, &error) ==
-		    0) {
+		if (str_to_label(ADMIN_HIGH, &m_label->upper_bound,
+		    MAC_LABEL, L_NO_CORRECTION, &error) == -1) {
+			m_label_free(m_label->lower_bound);
+			free(m_label);
+			return (-1);
+		}
+	} else {
+		if (str_to_label(p, &m_label->upper_bound, MAC_LABEL,
+		    L_NO_CORRECTION, &error) == -1) {
 			(void) sprintf(errbuf,
 			    gettext("invalid sensitivity label (%s) err %d"),
 			    p, error);
 			error_str = errbuf;
-			return (-1);
+			goto errout;
 		}
 	}
 	/* make sure that upper bound dominates the lower bound */
-	if (!bldominates(&m_slabel.upper_bound, &m_slabel.lower_bound)) {
-		*--p = ':';
+	if (!bldominates(m_label->upper_bound, m_label->lower_bound)) {
+		*--p = ';';
 		(void) sprintf(errbuf,
 		    gettext("invalid sensitivity label range (%s)"), optstr);
 		error_str = errbuf;
-		return (-1);
+		goto errout;
 	}
 	return (0);
+
+errout:
+	m_label_free(m_label->upper_bound);
+	m_label_free(m_label->lower_bound);
+	free(m_label);
+
+	return (-1);
 }
-#endif	/* !TSOL */
 
 /*
  * proc_zonename - pick up zone name.
diff --git a/usr/src/cmd/auditreduce/token.c b/usr/src/cmd/auditreduce/token.c
index 7b3c75e..f47c1e4 100644
--- a/usr/src/cmd/auditreduce/token.c
+++ b/usr/src/cmd/auditreduce/token.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1868,48 +1867,6 @@
 }
 
 /*
- * Format of clearance token:
- *	clearance		adr_char*(sizeof (bclear_t))
- */
-#ifndef	TSOL
-/* ARGSUSED */
-#endif	/* !TSOL */
-int
-clearance_token(adr_t *adr)
-{
-#ifdef	TSOL
-	bclear_t clearance;
-
-	adrm_char(adr, (char *)&clearance, sizeof (bclear_t));
-	return (-1);
-#else	/* !TSOL */
-	return (-2);
-#endif	/* TSOL */
-}
-
-
-/*
- * Format of ilabel token:
- *	ilabel			adr_char*(sizeof (bilabel_t))
- */
-#ifndef	TSOL
-/* ARGSUSED */
-#endif	/* !TSOL */
-int
-ilabel_token(adr_t *adr)
-{
-#ifdef	TSOL
-	bilabel_t ilabel;
-
-	adrm_char(adr, (char *)&ilabel, sizeof (ilabel));
-
-	return (-1);
-#else	/* !TSOL */
-	return (-2);
-#endif	/* TSOL */
-}
-
-/*
  * Format of privilege set token:
  *	priv_set type		string
  *	priv_set		string
@@ -1927,26 +1884,19 @@
  * Format of slabel token:
  *	slabel			adr_char*(sizeof (bslabel_t))
  */
-#ifndef	TSOL
-/* ARGSUSED */
-#endif	/* !TSOL */
 int
 slabel_token(adr_t *adr)
 {
-#ifdef	TSOL
 	bslabel_t slabel;
 
 	adrm_char(adr, (char *)&slabel, sizeof (slabel));
 
-	if (flags & M_SLABEL) {
-		if (blinrange(&slabel, &m_slabel))
-			checkflags = checkflags | M_SLABEL;
+	if (flags & M_LABEL) {
+		if (blinrange(&slabel, m_label))
+			checkflags = checkflags | M_LABEL;
 	}
 
 	return (-1);
-#else	/* !TSOL */
-	return (-2);
-#endif	/* TSOL */
 }
 
 
diff --git a/usr/src/cmd/bsmconv/bsmconv.sh b/usr/src/cmd/bsmconv/bsmconv.sh
index ca0856d..db037c5 100644
--- a/usr/src/cmd/bsmconv/bsmconv.sh
+++ b/usr/src/cmd/bsmconv/bsmconv.sh
@@ -1,11 +1,11 @@
 #! /bin/sh
 #
+#
 # 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,8 +20,7 @@
 #
 # CDDL HEADER END
 #
-#
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -143,18 +142,25 @@
     printf "${form}\n" $PROG
 fi
 
-# Initial device allocation files
+# Initialize device allocation
 
-form=`gettext "%s: INFO: initializing device allocation files."`
+form=`gettext "%s: INFO: initializing device allocation."`
 printf "${form}\n" $PROG
-if [ ! -f ${ROOT}/$DEVALLOC ]
+if [ -x /usr/bin/plabel ]
 then
-	mkdevalloc > ${ROOT}/$DEVALLOC
+	# Trusted Extensions is installed.
+	/usr/sbin/devfsadm -e
+else
+	if [ ! -f ${ROOT}/${DEVALLOC} ]
+	then
+		mkdevalloc > ${ROOT}/$DEVALLOC
+	fi
+	if [ ! -f ${ROOT}/${DEVMAPS} ]
+	then
+		mkdevmaps > ${ROOT}/$DEVMAPS
+	fi
 fi
-if [ ! -f $DEVMAPS ]
-then
-	mkdevmaps > ${ROOT}/$DEVMAPS
-fi
+
 
 # enable auditd.  Since we're running as single user, auditd won't
 # actually start until reboot.
diff --git a/usr/src/cmd/bsmunconv/bsmunconv.sh b/usr/src/cmd/bsmunconv/bsmunconv.sh
index 0e06c46..85661b6 100644
--- a/usr/src/cmd/bsmunconv/bsmunconv.sh
+++ b/usr/src/cmd/bsmunconv/bsmunconv.sh
@@ -1,11 +1,12 @@
 #! /bin/sh
 #
+#
+#
 # 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,8 +21,7 @@
 #
 # CDDL HEADER END
 #
-#
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -84,8 +84,7 @@
 bsmunconvert()
 {
 
-# deallocate user allocatable devices and turn off device allocation
-/usr/sbin/deallocate -Is
+# turn off device allocation
 /usr/sbin/devfsadm -d
 
 # disable auditd service
diff --git a/usr/src/cmd/cmd-inet/usr.bin/netstat/Makefile b/usr/src/cmd/cmd-inet/usr.bin/netstat/Makefile
index e4fdbd8..5e52d8c 100644
--- a/usr/src/cmd/cmd-inet/usr.bin/netstat/Makefile
+++ b/usr/src/cmd/cmd-inet/usr.bin/netstat/Makefile
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -18,11 +17,13 @@
 # information: Portions Copyright [yyyy] [name of copyright owner]
 #
 # CDDL HEADER END
+
+
 #
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
 #
-# Copyright 1996-2003 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # Copyright (c) 1990 Mentat Inc.
@@ -43,8 +44,9 @@
 SRCS=		$(LOCALSRCS) $(COMMONSRCS)
 
 CPPFLAGS += -DNDEBUG -I$(CMDINETCOMMONDIR)
-LDLIBS += -ldhcpagent -lcmd -lsocket -lnsl -lkstat
-LINTFLAGS += -m
+LAZYLIBS = $(ZLAZYLOAD) -ltsol $(ZNOLAZYLOAD)
+lint := LAZYLIBS = -ltsol
+LDLIBS += -ldhcpagent -lcmd -lsocket -lnsl -lkstat -ltsnet $(LAZYLIBS)
 
 .KEEP_STATE:
 
diff --git a/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c b/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c
index f978ae4..8218eac 100644
--- a/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c
+++ b/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -66,7 +65,6 @@
 #include <sys/stream.h>
 #include <stropts.h>
 #include <sys/strstat.h>
-#include <sys/sysmacros.h>
 #include <sys/tihdr.h>
 
 #include <sys/socket.h>
@@ -94,9 +92,10 @@
 #include <dhcpagent_util.h>
 #include <compat.h>
 
+#include <libtsnet.h>
+#include <tsol/label.h>
+
 extern void	unixpr(kstat_ctl_t *kc);
-extern void	setifdhcp(const char *caller, const char *ifname,
-		    int argc, char *argv[]);
 
 #define	STR_EXPAND	4
 
@@ -141,7 +140,7 @@
 static void		mib_item_destroy(mib_item_t **item);
 
 static boolean_t	octetstrmatch(const Octet_t *a, const Octet_t *b);
-static char		*octetstr(Octet_t *op, int code,
+static char		*octetstr(const Octet_t *op, int code,
 			    char *dst, uint_t dstlen);
 static char		*pr_addr(uint_t addr,
 			    char *dst, uint_t dstlen);
@@ -150,8 +149,8 @@
 			    char *dst, uint_t dstlen);
 static char		*pr_mask(uint_t addr,
 			    char *dst, uint_t dstlen);
-static char		*pr_prefix6(struct in6_addr *addr, uint_t prefixlen,
-			    char *dst, uint_t dstlen);
+static char		*pr_prefix6(const struct in6_addr *addr,
+			    uint_t prefixlen, char *dst, uint_t dstlen);
 static char		*pr_ap(uint_t addr, uint_t port,
 			    char *proto, char *dst, uint_t dstlen);
 static char		*pr_ap6(const in6_addr_t *addr, uint_t port,
@@ -166,7 +165,10 @@
 static char		*portname(uint_t port, char *proto,
 			    char *dst, uint_t dstlen);
 
-static	char		*mitcp_state(int code);
+static const char	*mitcp_state(int code,
+			    const mib2_transportMLPEntry_t *attr);
+static const char	*miudp_state(int code,
+			    const mib2_transportMLPEntry_t *attr);
 
 static void		stat_report(mib_item_t *item);
 static void		mrt_stat_report(mib_item_t *item);
@@ -183,9 +185,9 @@
 static void		if_report_ip6(mib2_ipv6AddrEntry_t *ap6,
 			    char ifname[], char logintname[],
 			    struct ifstat *statptr, boolean_t ksp_not_null);
-static void		ire_report(mib_item_t *item);
-static void		tcp_report(mib_item_t *item);
-static void		udp_report(mib_item_t *item);
+static void		ire_report(const mib_item_t *item);
+static void		tcp_report(const mib_item_t *item);
+static void		udp_report(const mib_item_t *item);
 static void		group_report(mib_item_t *item);
 static void		print_ip_stats(mib2_ip_t *ip);
 static void		print_icmp_stats(mib2_icmp_t *icmp);
@@ -197,7 +199,7 @@
 static void		print_rawip_stats(mib2_rawip_t *rawip);
 static void		print_igmp_stats(struct igmpstat *igps);
 static void		print_mrt_stats(struct mrtstat *mrts);
-static void		sctp_report(mib_item_t *item);
+static void		sctp_report(const mib_item_t *item);
 static void		sum_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6,
 			    mib2_ipv6IfStatsEntry_t *sum6);
 static void		sum_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6,
@@ -232,6 +234,7 @@
 static	boolean_t	Mflag = B_FALSE;	/* STREAMS Memory Statistics */
 static	boolean_t	Nflag = B_FALSE;	/* Numeric Network Addresses */
 static	boolean_t	Rflag = B_FALSE;	/* Routing Tables */
+static	boolean_t	RSECflag = B_FALSE;	/* Security attributes */
 static	boolean_t	Sflag = B_FALSE;	/* Per-protocol Statistics */
 static	boolean_t	Vflag = B_FALSE;	/* Verbose */
 static	boolean_t	Pflag = B_FALSE;	/* Net to Media Tables */
@@ -254,6 +257,7 @@
 static int ipNetToMediaEntrySize;
 static int ipMemberEntrySize;
 static int ipGroupSourceEntrySize;
+static int ipRouteAttributeSize;
 static int vifctlSize;
 static int mfcctlSize;
 
@@ -265,6 +269,7 @@
 static int ipv6MemberEntrySize;
 static int ipv6GroupSourceEntrySize;
 
+static int transportMLPSize;
 static int tcpConnEntrySize;
 static int tcp6ConnEntrySize;
 static int udpEntrySize;
@@ -362,7 +367,7 @@
 		    default_ip_str, DEFAULT_IP, INET_DEFAULT_FILE);
 	free(default_ip_str);
 
-	while ((c = getopt(argc, argv, "adimnrspMgvf:P:I:D")) != -1) {
+	while ((c = getopt(argc, argv, "adimnrspMgvf:P:I:DR")) != -1) {
 		switch ((char)c) {
 		case 'a':		/* all connections */
 			Aflag = B_TRUE;
@@ -391,6 +396,11 @@
 			IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
 			break;
 
+		case 'R':		/* security attributes */
+			RSECflag = B_TRUE;
+			IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
+			break;
+
 		case 's':		/* per-protocol statistics */
 			Sflag = B_TRUE;
 			IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
@@ -467,6 +477,14 @@
 	}
 
 	/*
+	 * Make sure -R option is set only on a labeled system.
+	 */
+	if (RSECflag && !is_system_labeled()) {
+		(void) fprintf(stderr, "-R set but labeling is not enabled\n");
+		usage(name);
+	}
+
+	/*
 	 * Handle other arguments: find interval, count; the
 	 * flags that accept 'interval' and 'count' are OR'd
 	 * in the outermost 'if'; more flags may be added as
@@ -1460,7 +1478,7 @@
 
 /* If octetstr() changes make an appropriate change to STR_EXPAND */
 static char *
-octetstr(Octet_t *op, int code, char *dst, uint_t dstlen)
+octetstr(const Octet_t *op, int code, char *dst, uint_t dstlen)
 {
 	int	i;
 	char	*cp;
@@ -1504,11 +1522,11 @@
 	return (dst);
 }
 
-static char *
-mitcp_state(int state)
+static const char *
+mitcp_state(int state, const mib2_transportMLPEntry_t *attr)
 {
-static	char	tcpsbuf[50];
-	char	*cp;
+	static char tcpsbuf[50];
+	const char *cp;
 
 	switch (state) {
 	case TCPS_CLOSED:
@@ -1556,6 +1574,55 @@
 		cp = tcpsbuf;
 		break;
 	}
+
+	if (RSECflag && attr != NULL && attr->tme_flags != 0) {
+		if (cp != tcpsbuf) {
+			(void) strlcpy(tcpsbuf, cp, sizeof (tcpsbuf));
+			cp = tcpsbuf;
+		}
+		if (attr->tme_flags & MIB2_TMEF_PRIVATE)
+			(void) strlcat(tcpsbuf, " P", sizeof (tcpsbuf));
+		if (attr->tme_flags & MIB2_TMEF_SHARED)
+			(void) strlcat(tcpsbuf, " S", sizeof (tcpsbuf));
+	}
+
+	return (cp);
+}
+
+static const char *
+miudp_state(int state, const mib2_transportMLPEntry_t *attr)
+{
+	static char udpsbuf[50];
+	const char *cp;
+
+	switch (state) {
+	case MIB2_UDP_unbound:
+		cp = "Unbound";
+		break;
+	case MIB2_UDP_idle:
+		cp = "Idle";
+		break;
+	case MIB2_UDP_connected:
+		cp = "Connected";
+		break;
+	default:
+		(void) snprintf(udpsbuf, sizeof (udpsbuf),
+		    "Unknown State(%d)", state);
+		cp = udpsbuf;
+		break;
+	}
+
+	if (RSECflag && attr != NULL && attr->tme_flags != 0) {
+		if (cp != udpsbuf) {
+			(void) strlcpy(udpsbuf, cp, sizeof (udpsbuf));
+			cp = udpsbuf;
+		}
+		if (attr->tme_flags & MIB2_TMEF_PRIVATE)
+			(void) strlcat(udpsbuf, " P", sizeof (udpsbuf));
+		if (attr->tme_flags & MIB2_TMEF_SHARED)
+			(void) strlcat(udpsbuf, " S", sizeof (udpsbuf));
+	}
+
 	return (cp);
 }
 
@@ -1637,6 +1704,8 @@
 			ipNetToMediaEntrySize = ip->ipNetToMediaEntrySize;
 			ipMemberEntrySize = ip->ipMemberEntrySize;
 			ipGroupSourceEntrySize = ip->ipGroupSourceEntrySize;
+			ipRouteAttributeSize = ip->ipRouteAttributeSize;
+			transportMLPSize = ip->transportMLPSize;
 			assert(IS_P2ALIGNED(ipAddrEntrySize,
 			    sizeof (mib2_ipAddrEntry_t *)) &&
 			    IS_P2ALIGNED(ipRouteEntrySize,
@@ -1646,7 +1715,11 @@
 			    IS_P2ALIGNED(ipMemberEntrySize,
 				sizeof (ip_member_t *)) &&
 			    IS_P2ALIGNED(ipGroupSourceEntrySize,
-				sizeof (ip_grpsrc_t *)));
+				sizeof (ip_grpsrc_t *)) &&
+			    IS_P2ALIGNED(ipRouteAttributeSize,
+				sizeof (mib2_ipAttributeEntry_t *)) &&
+			    IS_P2ALIGNED(transportMLPSize,
+				sizeof (mib2_transportMLPEntry_t *)));
 			break;
 		}
 		case EXPER_DVMRP: {
@@ -1737,6 +1810,8 @@
 		(void) printf("\tipNetToMediaEntrySize %d\n",
 		    ipNetToMediaEntrySize);
 		(void) printf("\tipMemberEntrySize %d\n", ipMemberEntrySize);
+		(void) printf("\tipRouteAttributeSize %d\n",
+		    ipRouteAttributeSize);
 		(void) printf("\tvifctlSize %d\n", vifctlSize);
 		(void) printf("\tmfcctlSize %d\n", mfcctlSize);
 
@@ -1748,6 +1823,7 @@
 		    ipv6MemberEntrySize);
 		(void) printf("\tipv6IfIcmpEntrySize %d\n",
 		    ipv6IfIcmpEntrySize);
+		(void) printf("\ttransportMLPSize %d\n", transportMLPSize);
 		(void) printf("\ttcpConnEntrySize %d\n", tcpConnEntrySize);
 		(void) printf("\ttcp6ConnEntrySize %d\n", tcp6ConnEntrySize);
 		(void) printf("\tudpEntrySize %d\n", udpEntrySize);
@@ -3656,23 +3732,102 @@
 
 /* ------------------------- ire_report (netstat -r) ------------------------ */
 
-static boolean_t ire_report_item_v4(mib2_ipRouteEntry_t *rp, boolean_t first);
-static boolean_t ire_report_item_v4src(mib2_ipRouteEntry_t *rp,
-    boolean_t first);
-static boolean_t ire_report_item_v6(mib2_ipv6RouteEntry_t *rp6,
-    boolean_t first);
+typedef struct sec_attr_list_s {
+	struct sec_attr_list_s *sal_next;
+	const mib2_ipAttributeEntry_t *sal_attr;
+} sec_attr_list_t;
+
+static boolean_t ire_report_item_v4(const mib2_ipRouteEntry_t *, boolean_t,
+    const sec_attr_list_t *);
+static boolean_t ire_report_item_v4src(const mib2_ipRouteEntry_t *, boolean_t,
+    const sec_attr_list_t *);
+static boolean_t ire_report_item_v6(const mib2_ipv6RouteEntry_t *, boolean_t,
+    const sec_attr_list_t *);
+static const char *pr_secattr(const sec_attr_list_t *);
 
 static void
-ire_report(mib_item_t *item)
+ire_report(const mib_item_t *item)
 {
 	int			jtemp = 0;
 	boolean_t		print_hdr_once_v4 = B_TRUE;
 	boolean_t		print_hdr_once_v6 = B_TRUE;
 	mib2_ipRouteEntry_t	*rp;
 	mib2_ipv6RouteEntry_t	*rp6;
+	sec_attr_list_t		**v4_attrs, **v4a;
+	sec_attr_list_t		**v6_attrs, **v6a;
+	sec_attr_list_t		*all_attrs, *aptr;
+	const mib_item_t	*iptr;
+	int			ipv4_route_count, ipv6_route_count;
+	int			route_attrs_count;
+
+	/*
+	 * Preparation pass: the kernel returns separate entries for IP routing
+	 * table entries and security attributes.  We loop through the
+	 * attributes first and link them into lists.
+	 */
+	ipv4_route_count = ipv6_route_count = route_attrs_count = 0;
+	for (iptr = item; iptr != NULL; iptr = iptr->next_item) {
+		if (iptr->group == MIB2_IP6 && iptr->mib_id == MIB2_IP6_ROUTE)
+			ipv6_route_count += iptr->length / ipv6RouteEntrySize;
+		if (iptr->group == MIB2_IP && iptr->mib_id == MIB2_IP_ROUTE)
+			ipv4_route_count += iptr->length / ipRouteEntrySize;
+		if ((iptr->group == MIB2_IP || iptr->group == MIB2_IP6) &&
+		    iptr->mib_id == EXPER_IP_RTATTR)
+			route_attrs_count += iptr->length /
+			    ipRouteAttributeSize;
+	}
+	v4_attrs = v6_attrs = NULL;
+	all_attrs = NULL;
+	if (family_selected(AF_INET) && ipv4_route_count > 0) {
+		v4_attrs = calloc(ipv4_route_count, sizeof (*v4_attrs));
+		if (v4_attrs == NULL) {
+			perror("ire_report calloc v4_attrs failed");
+			return;
+		}
+	}
+	if (family_selected(AF_INET6) && ipv6_route_count > 0) {
+		v6_attrs = calloc(ipv6_route_count, sizeof (*v6_attrs));
+		if (v6_attrs == NULL) {
+			perror("ire_report calloc v6_attrs failed");
+			goto ire_report_done;
+		}
+	}
+	if (route_attrs_count > 0) {
+		all_attrs = malloc(route_attrs_count * sizeof (*all_attrs));
+		if (all_attrs == NULL) {
+			perror("ire_report malloc all_attrs failed");
+			goto ire_report_done;
+		}
+	}
+	aptr = all_attrs;
+	for (iptr = item; iptr != NULL; iptr = iptr->next_item) {
+		mib2_ipAttributeEntry_t *iae;
+		sec_attr_list_t **alp;
+
+		if (v4_attrs != NULL && iptr->group == MIB2_IP &&
+		    iptr->mib_id == EXPER_IP_RTATTR) {
+			alp = v4_attrs;
+		} else if (v6_attrs != NULL && iptr->group == MIB2_IP6 &&
+		    iptr->mib_id == EXPER_IP_RTATTR) {
+			alp = v6_attrs;
+		} else {
+			continue;
+		}
+		for (iae = iptr->valp;
+		    (char *)iae < (char *)iptr->valp + iptr->length;
+		    /* LINTED: (note 1) */
+		    iae = (mib2_ipAttributeEntry_t *)((char *)iae +
+		    ipRouteAttributeSize)) {
+			aptr->sal_next = alp[iae->iae_routeidx];
+			aptr->sal_attr = iae;
+			alp[iae->iae_routeidx] = aptr++;
+		}
+	}
 
 	/* 'for' loop 1: */
-	for (; item; item = item->next_item) {
+	v4a = v4_attrs;
+	v6a = v6_attrs;
+	for (; item != NULL; item = item->next_item) {
 		if (Dflag) {
 			(void) printf("\n--- Entry %d ---\n", ++jtemp);
 			(void) printf("Group = %d, mib_id = %d, "
@@ -3710,17 +3865,21 @@
 			    /* LINTED: (note 1) */
 			    rp = (mib2_ipRouteEntry_t *)((char *)rp +
 			    ipRouteEntrySize)) {
+				aptr = v4a == NULL ? NULL : *v4a++;
 				print_hdr_once_v4 = ire_report_item_v4(rp,
-				    print_hdr_once_v4);
+				    print_hdr_once_v4, aptr);
 			}
+			if (v4a != NULL)
+				v4a -= item->length / ipRouteEntrySize;
 			print_hdr_once_v4 = B_TRUE;
 			for (rp = (mib2_ipRouteEntry_t *)item->valp;
 			    (char *)rp < (char *)item->valp + item->length;
 			    /* LINTED: (note 1) */
 			    rp = (mib2_ipRouteEntry_t *)((char *)rp +
 			    ipRouteEntrySize)) {
+				aptr = v4a == NULL ? NULL : *v4a++;
 				print_hdr_once_v4 = ire_report_item_v4src(rp,
-				    print_hdr_once_v4);
+				    print_hdr_once_v4, aptr);
 			}
 		} else {
 			for (rp6 = (mib2_ipv6RouteEntry_t *)item->valp;
@@ -3728,12 +3887,20 @@
 			    /* LINTED: (note 1) */
 			    rp6 = (mib2_ipv6RouteEntry_t *)((char *)rp6 +
 			    ipv6RouteEntrySize)) {
+				aptr = v6a == NULL ? NULL : *v6a++;
 				print_hdr_once_v6 = ire_report_item_v6(rp6,
-				    print_hdr_once_v6);
+				    print_hdr_once_v6, aptr);
 			}
 		}
 	} /* 'for' loop 1 ends */
 	(void) fflush(stdout);
+ire_report_done:
+	if (v4_attrs != NULL)
+		free(v4_attrs);
+	if (v6_attrs != NULL)
+		free(v6_attrs);
+	if (all_attrs != NULL)
+		free(all_attrs);
 }
 
 /*
@@ -3809,7 +3976,7 @@
  * of each type matches, then display the route.
  */
 static boolean_t
-ire_filter_match_v4(mib2_ipRouteEntry_t *rp, uint_t flag_b)
+ire_filter_match_v4(const mib2_ipRouteEntry_t *rp, uint_t flag_b)
 {
 	filter_t *fp;
 	int idx;
@@ -3865,7 +4032,7 @@
  * route.
  */
 static uint_t
-form_v4_route_flags(mib2_ipRouteEntry_t *rp, char *flags)
+form_v4_route_flags(const mib2_ipRouteEntry_t *rp, char *flags)
 {
 	uint_t flag_b;
 
@@ -3910,8 +4077,23 @@
 	return (flag_b);
 }
 
+static const char ire_hdr_v4[] =
+"\n%s Table: IPv4\n";
+static const char ire_hdr_v4_compat[] =
+"\n%s Table:\n";
+static const char ire_hdr_v4_verbose[] =
+"  Destination             Mask           Gateway          Device Mxfrg "
+"Rtt   Ref Flg  Out  In/Fwd %s\n"
+"-------------------- --------------- -------------------- ------ ----- "
+"----- --- --- ----- ------ %s\n";
+
+static const char ire_hdr_v4_normal[] =
+"  Destination           Gateway           Flags  Ref   Use   Interface %s\n"
+"-------------------- -------------------- ----- ----- ------ --------- %s\n";
+
 static boolean_t
-ire_report_item_v4(mib2_ipRouteEntry_t *rp, boolean_t first)
+ire_report_item_v4(const mib2_ipRouteEntry_t *rp, boolean_t first,
+    const sec_attr_list_t *attrs)
 {
 	char			dstbuf[MAXHOSTNAMELEN + 1];
 	char			maskbuf[MAXHOSTNAMELEN + 1];
@@ -3934,29 +4116,11 @@
 		return (first);
 
 	if (first) {
-		if (Vflag) {
-			(void) puts(v4compat ?
-			    "\nIRE Table:" :
-			    "\nIRE Table: IPv4");
-			(void) puts("  Destination             Mask       "
-			    "    Gateway          "
-			    "Device Mxfrg  Rtt  Ref Flg  Out  "
-			    "In/Fwd");
-			(void) puts("-------------------- --------------- "
-			    "-------------------- "
-			    "------ ----- ----- --- --- ----- "
-			    "------");
-		} else {
-			(void) puts(v4compat ?
-			    "\nRouting Table:" :
-			    "\nRouting Table: IPv4");
-			(void) puts("  Destination        "
-			    "   Gateway           Flags  Ref   Use   "
-			    "Interface");
-			(void) puts("-------------------- "
-			    "-------------------- ----- ----- ------ "
-			    "---------");
-		}
+		(void) printf(v4compat ? ire_hdr_v4_compat : ire_hdr_v4,
+		    Vflag ? "IRE" : "Routing");
+		(void) printf(Vflag ? ire_hdr_v4_verbose : ire_hdr_v4_normal,
+		    RSECflag ? "  Gateway security attributes  " : "",
+		    RSECflag ? "-------------------------------" : "");
 		first = B_FALSE;
 	}
 
@@ -3968,7 +4132,7 @@
 	}
 	if (Vflag) {
 		(void) printf("%-20s %-15s %-20s %-6s %5u%c %4u %3u "
-		    "%-4s%6u%6u\n",
+		    "%-4s%6u%6u %s\n",
 		    dstbuf,
 		    pr_mask(rp->ipRouteMask, maskbuf, sizeof (maskbuf)),
 		    pr_addrnz(rp->ipRouteNextHop, gwbuf, sizeof (gwbuf)),
@@ -3979,25 +4143,43 @@
 		    rp->ipRouteInfo.re_ref,
 		    flags,
 		    rp->ipRouteInfo.re_obpkt,
-		    rp->ipRouteInfo.re_ibpkt);
+		    rp->ipRouteInfo.re_ibpkt,
+		    pr_secattr(attrs));
 	} else {
-		(void) printf("%-20s %-20s %-5s  %4u%7u  %s\n",
+		(void) printf("%-20s %-20s %-5s  %4u%7u %-9s %s\n",
 		    dstbuf,
 		    pr_addrnz(rp->ipRouteNextHop, gwbuf, sizeof (gwbuf)),
 		    flags,
 		    rp->ipRouteInfo.re_ref,
 		    rp->ipRouteInfo.re_obpkt + rp->ipRouteInfo.re_ibpkt,
 		    octetstr(&rp->ipRouteIfIndex, 'a',
-			ifname, sizeof (ifname)));
+		    ifname, sizeof (ifname)),
+		    pr_secattr(attrs));
 	}
 	return (first);
 }
 
+static const char ire_hdr_src_v4[] =
+"\n%s Table: IPv4 Source-Specific\n";
+static const char ire_hdr_src_v4_compat[] =
+"\n%s Table: Source-Specific\n";
+static const char ire_hdr_src_v4_verbose[] =
+"  Destination        In If       Source            Gateway         "
+"  Out If    Mxfrg  Rtt  Ref Flg  Out  In/Fwd %s\n"
+"------------------ ----------- ----------------- ----------------- "
+"----------- ----- ----- --- --- ----- ------ %s\n";
+static const char ire_hdr_src_v4_normal[] =
+"  Destination    In If     Source          Gateway       Flags  Use   "
+" Out If  %s\n"
+"--------------- -------- --------------- --------------- ----- ------ "
+"-------- %s\n";
+
 /*
  * Report a source-specific route.
  */
 static boolean_t
-ire_report_item_v4src(mib2_ipRouteEntry_t *rp, boolean_t first)
+ire_report_item_v4src(const mib2_ipRouteEntry_t *rp, boolean_t first,
+    const sec_attr_list_t *attrs)
 {
 	char	dstbuf[MAXHOSTNAMELEN + 1];
 	char	srcbuf[MAXHOSTNAMELEN + 1];
@@ -4025,25 +4207,12 @@
 		return (first);
 
 	if (first) {
-		if (Vflag) {
-			(void) printf("\nIRE Table: %sSource-Specific\n",
-			    v4compat ? "" : "IPv4 ");
-			(void) puts("  Destination        In If     "
-			    "  Source            Gateway         "
-			    "  Out If    Mxfrg  Rtt  Ref Flg  Out  In/Fwd");
-			(void) puts("------------------ ----------- "
-			    "----------------- ----------------- "
-			    "----------- ----- ----- --- --- ----- ------");
-		} else {
-			(void) printf("\nRouting Table: %sSource-Specific\n",
-			    v4compat ? "" : "IPv4 ");
-			(void) puts("  Destination    In If   "
-			    "  Source          Gateway       Flags  Use   "
-			    " Out If");
-			(void) puts("--------------- -------- "
-			    "--------------- --------------- ----- ------ "
-			    "--------");
-		}
+		(void) printf(v4compat ? ire_hdr_src_v4_compat :
+		    ire_hdr_src_v4, Vflag ? "IRE" : "Routing");
+		(void) printf(Vflag ? ire_hdr_src_v4_verbose :
+		    ire_hdr_src_v4_normal,
+		    RSECflag ? "  Gateway security attributes  " : "",
+		    RSECflag ? "-------------------------------" : "");
 		first = B_FALSE;
 	}
 
@@ -4065,17 +4234,18 @@
 	(void) pr_addrnz(rp->ipRouteNextHop, gwbuf, sizeof (gwbuf));
 	if (Vflag) {
 		(void) printf("%-18s %-11s %-17s %-17s %-11s %4u%c %5u %3u "
-		    "%-3s %5u %6u\n",
+		    "%-3s %5u %6u %s\n",
 		    dstbuf, inif, srcbuf, gwbuf,  outif,
 		    rp->ipRouteInfo.re_max_frag,
 		    rp->ipRouteInfo.re_frag_flag ? '*' : ' ',
 		    rp->ipRouteInfo.re_rtt, rp->ipRouteInfo.re_ref, flags,
-		    rp->ipRouteInfo.re_obpkt, rp->ipRouteInfo.re_ibpkt);
+		    rp->ipRouteInfo.re_obpkt, rp->ipRouteInfo.re_ibpkt,
+		    pr_secattr(attrs));
 	} else {
-		(void) printf("%-15s %-8s %-15s %-15s %-5s %6u %-8s\n", dstbuf,
-		    inif, srcbuf, gwbuf, flags,
-		    rp->ipRouteInfo.re_obpkt + rp->ipRouteInfo.re_ibpkt,
-		    outif);
+		(void) printf("%-15s %-8s %-15s %-15s %-5s %6u %-8s %s\n",
+		    dstbuf, inif, srcbuf, gwbuf, flags,
+		    rp->ipRouteInfo.re_obpkt + rp->ipRouteInfo.re_ibpkt, outif,
+		    pr_secattr(attrs));
 	}
 	return (first);
 }
@@ -4145,7 +4315,7 @@
  * types, then the route is selected and displayed.
  */
 static boolean_t
-ire_filter_match_v6(mib2_ipv6RouteEntry_t *rp6, uint_t flag_b)
+ire_filter_match_v6(const mib2_ipv6RouteEntry_t *rp6, uint_t flag_b)
 {
 	filter_t *fp;
 	int idx;
@@ -4201,8 +4371,22 @@
 	return (B_TRUE);
 }
 
+static const char ire_hdr_v6[] =
+"\n%s Table: IPv6\n";
+static const char ire_hdr_v6_verbose[] =
+"  Destination/Mask            Gateway                    If    PMTU   Rtt  "
+"Ref Flags  Out   In/Fwd %s\n"
+"--------------------------- --------------------------- ----- ------ ----- "
+"--- ----- ------ ------ %s\n";
+static const char ire_hdr_v6_normal[] =
+"  Destination/Mask            Gateway                   Flags Ref   Use  "
+" If   %s\n"
+"--------------------------- --------------------------- ----- --- ------ "
+"----- %s\n";
+
 static boolean_t
-ire_report_item_v6(mib2_ipv6RouteEntry_t *rp6, boolean_t first)
+ire_report_item_v6(const mib2_ipv6RouteEntry_t *rp6, boolean_t first,
+    const sec_attr_list_t *attrs)
 {
 	char			dstbuf[MAXHOSTNAMELEN + 1];
 	char			gwbuf[MAXHOSTNAMELEN + 1];
@@ -4256,29 +4440,16 @@
 		return (first);
 
 	if (first) {
-		if (Vflag) {
-			(void) puts("\nIRE Table: IPv6");
-			(void) puts("  Destination/Mask          "
-			    "  Gateway                   "
-			    " If    PMTU   Rtt  Ref Flags  Out   In/Fwd");
-			(void) puts("--------------------------- "
-			    "--------------------------- "
-			    "----- ------ ----- --- ----- ------ ------");
-		} else {
-			(void) puts("\nRouting Table: IPv6");
-			(void) puts("  Destination/Mask          "
-			    "  Gateway                   Flags Ref   Use  "
-			    " If  ");
-			(void) puts("--------------------------- "
-			    "--------------------------- ----- --- ------ "
-			    "-----");
-		}
+		(void) printf(ire_hdr_v6, Vflag ? "IRE" : "Routing");
+		(void) printf(Vflag ? ire_hdr_v6_verbose : ire_hdr_v6_normal,
+		    RSECflag ? "  Gateway security attributes  " : "",
+		    RSECflag ? "-------------------------------" : "");
 		first = B_FALSE;
 	}
 
 	if (Vflag) {
 		(void) printf("%-27s %-27s %-5s %5u%c %5u %3u "
-		    "%-5s %6u %6u\n",
+		    "%-5s %6u %6u %s\n",
 		    pr_prefix6(&rp6->ipv6RouteDest,
 			rp6->ipv6RoutePfxLength, dstbuf, sizeof (dstbuf)),
 		    IN6_IS_ADDR_UNSPECIFIED(&rp6->ipv6RouteNextHop) ?
@@ -4292,9 +4463,10 @@
 		    rp6->ipv6RouteInfo.re_ref,
 		    flags,
 		    rp6->ipv6RouteInfo.re_obpkt,
-		    rp6->ipv6RouteInfo.re_ibpkt);
+		    rp6->ipv6RouteInfo.re_ibpkt,
+		    pr_secattr(attrs));
 	} else {
-		(void) printf("%-27s %-27s %-5s %3u %6u %-5s\n",
+		(void) printf("%-27s %-27s %-5s %3u %6u %-5s %s\n",
 		    pr_prefix6(&rp6->ipv6RouteDest,
 			rp6->ipv6RoutePfxLength, dstbuf, sizeof (dstbuf)),
 		    IN6_IS_ADDR_UNSPECIFIED(&rp6->ipv6RouteNextHop) ?
@@ -4304,11 +4476,59 @@
 		    rp6->ipv6RouteInfo.re_ref,
 		    rp6->ipv6RouteInfo.re_obpkt + rp6->ipv6RouteInfo.re_ibpkt,
 		    octetstr(&rp6->ipv6RouteIfIndex, 'a',
-		    ifname, sizeof (ifname)));
+		    ifname, sizeof (ifname)),
+		    pr_secattr(attrs));
 	}
 	return (first);
 }
 
+/*
+ * Common attribute-gathering routine for all transports.
+ */
+static mib2_transportMLPEntry_t **
+gather_attrs(const mib_item_t *item, int group, int mib_id, int esize)
+{
+	int transport_count = 0;
+	const mib_item_t *iptr;
+	mib2_transportMLPEntry_t **attrs, *tme;
+
+	for (iptr = item; iptr != NULL; iptr = iptr->next_item) {
+		if (iptr->group == group && iptr->mib_id == mib_id)
+			transport_count += iptr->length / esize;
+	}
+	if (transport_count <= 0)
+		return (NULL);
+	attrs = calloc(transport_count, sizeof (*attrs));
+	if (attrs == NULL) {
+		perror("gather_attrs calloc failed");
+		return (NULL);
+	}
+	for (iptr = item; iptr != NULL; iptr = iptr->next_item) {
+		if (iptr->group == group && iptr->mib_id == EXPER_XPORT_MLP) {
+			for (tme = iptr->valp;
+			    (char *)tme < (char *)iptr->valp + iptr->length;
+			    /* LINTED: (note 1) */
+			    tme = (mib2_transportMLPEntry_t *)((char *)tme +
+			    transportMLPSize)) {
+				attrs[tme->tme_connidx] = tme;
+			}
+		}
+	}
+	return (attrs);
+}
+
+static void
+print_transport_label(const mib2_transportMLPEntry_t *attr)
+{
+	if (!RSECflag || attr == NULL)
+		return;
+
+	if (bisinvalid(&attr->tme_label))
+		(void) printf("   INVALID\n");
+	else
+		(void) printf("   %s\n", sl_to_str(&attr->tme_label));
+}
+
 /* ------------------------------ TCP_REPORT------------------------------- */
 
 static const char tcp_hdr_v4[] =
@@ -4317,43 +4537,65 @@
 "\nTCP\n";
 static const char tcp_hdr_v4_verbose[] =
 "Local/Remote Address Swind  Snext     Suna   Rwind  Rnext     Rack   "
-" Rto   Mss  State\n"
+" Rto   Mss     State\n"
 "-------------------- ----- -------- -------- ----- -------- -------- "
-"----- ----- -----\n";
+"----- ----- -----------\n";
 static const char tcp_hdr_v4_normal[] =
-"   Local Address        Remote Address    Swind Send-Q Rwind Recv-Q  State\n"
-"-------------------- -------------------- ----- ------ ----- ------ -------\n";
+"   Local Address        Remote Address    Swind Send-Q Rwind Recv-Q "
+"   State\n"
+"-------------------- -------------------- ----- ------ ----- ------ "
+"-----------\n";
 
 static const char tcp_hdr_v6[] =
 "\nTCP: IPv6\n";
 static const char tcp_hdr_v6_verbose[] =
 "Local/Remote Address              Swind  Snext     Suna   Rwind  Rnext   "
-"  Rack    Rto   Mss    State      If  \n"
+"  Rack    Rto   Mss    State      If\n"
 "--------------------------------- ----- -------- -------- ----- -------- "
 "-------- ----- ----- ----------- -----\n";
 static const char tcp_hdr_v6_normal[] =
 "   Local Address                     Remote Address                 "
-"Swind Send-Q Rwind Recv-Q   State      If \n"
+"Swind Send-Q Rwind Recv-Q   State      If\n"
 "--------------------------------- --------------------------------- "
 "----- ------ ----- ------ ----------- -----\n";
 
-static boolean_t tcp_report_item_v4(mib2_tcpConnEntry_t *tp, boolean_t first);
-static boolean_t tcp_report_item_v6(mib2_tcp6ConnEntry_t *tp6, boolean_t first);
+static boolean_t tcp_report_item_v4(const mib2_tcpConnEntry_t *,
+    boolean_t first, const mib2_transportMLPEntry_t *);
+static boolean_t tcp_report_item_v6(const mib2_tcp6ConnEntry_t *,
+    boolean_t first, const mib2_transportMLPEntry_t *);
 
 static void
-tcp_report(mib_item_t *item)
+tcp_report(const mib_item_t *item)
 {
 	int			jtemp = 0;
 	boolean_t		print_hdr_once_v4 = B_TRUE;
 	boolean_t		print_hdr_once_v6 = B_TRUE;
 	mib2_tcpConnEntry_t	*tp;
 	mib2_tcp6ConnEntry_t	*tp6;
+	mib2_transportMLPEntry_t **v4_attrs, **v6_attrs;
+	mib2_transportMLPEntry_t **v4a, **v6a;
+	mib2_transportMLPEntry_t *aptr;
 
 	if (!protocol_selected(IPPROTO_TCP))
 		return;
 
+	/*
+	 * Preparation pass: the kernel returns separate entries for TCP
+	 * connection table entries and Multilevel Port attributes.  We loop
+	 * through the attributes first and set up an array for each address
+	 * family.
+	 */
+	v4_attrs = family_selected(AF_INET) && RSECflag ?
+	    gather_attrs(item, MIB2_TCP, MIB2_TCP_CONN, tcpConnEntrySize) :
+	    NULL;
+	v6_attrs = family_selected(AF_INET6) && RSECflag ?
+	    gather_attrs(item, MIB2_TCP6, MIB2_TCP6_CONN, tcp6ConnEntrySize) :
+	    NULL;
+
 	/* 'for' loop 1: */
-	for (; item; item = item->next_item) {
+	v4a = v4_attrs;
+	v6a = v6_attrs;
+	for (; item != NULL; item = item->next_item) {
 		if (Dflag) {
 			(void) printf("\n--- Entry %d ---\n", ++jtemp);
 			(void) printf("Group = %d, mib_id = %d, "
@@ -4379,8 +4621,9 @@
 			    /* LINTED: (note 1) */
 			    tp = (mib2_tcpConnEntry_t *)((char *)tp +
 			    tcpConnEntrySize)) {
+				aptr = v4a == NULL ? NULL : *v4a++;
 				print_hdr_once_v4 = tcp_report_item_v4(tp,
-				    print_hdr_once_v4);
+				    print_hdr_once_v4, aptr);
 			}
 		} else {
 			for (tp6 = (mib2_tcp6ConnEntry_t *)item->valp;
@@ -4388,16 +4631,23 @@
 			    /* LINTED: (note 1) */
 			    tp6 = (mib2_tcp6ConnEntry_t *)((char *)tp6 +
 			    tcp6ConnEntrySize)) {
+				aptr = v6a == NULL ? NULL : *v6a++;
 				print_hdr_once_v6 = tcp_report_item_v6(tp6,
-				    print_hdr_once_v6);
+				    print_hdr_once_v6, aptr);
 			}
 		}
 	} /* 'for' loop 1 ends */
 	(void) fflush(stdout);
+
+	if (v4_attrs != NULL)
+		free(v4_attrs);
+	if (v6_attrs != NULL)
+		free(v6_attrs);
 }
 
 static boolean_t
-tcp_report_item_v4(mib2_tcpConnEntry_t *tp, boolean_t first)
+tcp_report_item_v4(const mib2_tcpConnEntry_t *tp, boolean_t first,
+    const mib2_transportMLPEntry_t *attr)
 {
 	/*
 	 * lname and fname below are for the hostname as well as the portname
@@ -4411,10 +4661,8 @@
 		return (first); /* Nothing to print */
 
 	if (first) {
-		(void) fputs(v4compat ? tcp_hdr_v4_compat : tcp_hdr_v4, stdout);
-		(void) fputs(Vflag ? tcp_hdr_v4_verbose : tcp_hdr_v4_normal,
-		    stdout);
-		first = B_FALSE;
+		(void) printf(v4compat ? tcp_hdr_v4_compat : tcp_hdr_v4);
+		(void) printf(Vflag ? tcp_hdr_v4_verbose : tcp_hdr_v4_normal);
 	}
 
 	if (Vflag) {
@@ -4432,7 +4680,7 @@
 		    tp->tcpConnEntryInfo.ce_rack,
 		    tp->tcpConnEntryInfo.ce_rto,
 		    tp->tcpConnEntryInfo.ce_mss,
-		    mitcp_state(tp->tcpConnEntryInfo.ce_state));
+		    mitcp_state(tp->tcpConnEntryInfo.ce_state, attr));
 	} else {
 		int sq = (int)tp->tcpConnEntryInfo.ce_snxt -
 		    (int)tp->tcpConnEntryInfo.ce_suna - 1;
@@ -4448,13 +4696,17 @@
 		    (sq >= 0) ? sq : 0,
 		    tp->tcpConnEntryInfo.ce_rwnd,
 		    (rq >= 0) ? rq : 0,
-		    mitcp_state(tp->tcpConnEntryInfo.ce_state));
+		    mitcp_state(tp->tcpConnEntryInfo.ce_state, attr));
 	}
-	return (first);
+
+	print_transport_label(attr);
+
+	return (B_FALSE);
 }
 
 static boolean_t
-tcp_report_item_v6(mib2_tcp6ConnEntry_t *tp6, boolean_t first)
+tcp_report_item_v6(const mib2_tcp6ConnEntry_t *tp6, boolean_t first,
+    const mib2_transportMLPEntry_t *attr)
 {
 	/*
 	 * lname and fname below are for the hostname as well as the portname
@@ -4470,18 +4722,18 @@
 		return (first); /* Nothing to print */
 
 	if (first) {
-		(void) fputs(tcp_hdr_v6, stdout);
-		(void) fputs(Vflag ? tcp_hdr_v6_verbose : tcp_hdr_v6_normal,
-		    stdout);
-		first = B_FALSE;
+		(void) printf(tcp_hdr_v6);
+		(void) printf(Vflag ? tcp_hdr_v6_verbose : tcp_hdr_v6_normal);
 	}
 
 	ifnamep = (tp6->tcp6ConnIfIndex != 0) ?
 	    if_indextoname(tp6->tcp6ConnIfIndex, ifname) : NULL;
+	if (ifnamep == NULL)
+		ifnamep = "";
 
 	if (Vflag) {
 		(void) printf("%-33s\n%-33s %5u %08x %08x %5u %08x %08x "
-		    "%5u %5u %-11s %-5s\n",
+		    "%5u %5u %-11s %s\n",
 		    pr_ap6(&tp6->tcp6ConnLocalAddress,
 			tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
 		    pr_ap6(&tp6->tcp6ConnRemAddress,
@@ -4494,15 +4746,15 @@
 		    tp6->tcp6ConnEntryInfo.ce_rack,
 		    tp6->tcp6ConnEntryInfo.ce_rto,
 		    tp6->tcp6ConnEntryInfo.ce_mss,
-		    mitcp_state(tp6->tcp6ConnEntryInfo.ce_state),
-		    (ifnamep == NULL) ? "" : ifnamep);
+		    mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
+		    ifnamep);
 	} else {
 		int sq = (int)tp6->tcp6ConnEntryInfo.ce_snxt -
 		    (int)tp6->tcp6ConnEntryInfo.ce_suna - 1;
 		int rq = (int)tp6->tcp6ConnEntryInfo.ce_rnxt -
 		    (int)tp6->tcp6ConnEntryInfo.ce_rack;
 
-		(void) printf("%-33s %-33s %5u %6d %5u %6d %-11s %-5s\n",
+		(void) printf("%-33s %-33s %5u %6d %5u %6d %-11s %s\n",
 		    pr_ap6(&tp6->tcp6ConnLocalAddress,
 			tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
 		    pr_ap6(&tp6->tcp6ConnRemAddress,
@@ -4511,35 +4763,61 @@
 		    (sq >= 0) ? sq : 0,
 		    tp6->tcp6ConnEntryInfo.ce_rwnd,
 		    (rq >= 0) ? rq : 0,
-		    mitcp_state(tp6->tcp6ConnEntryInfo.ce_state),
-		    (ifnamep == NULL) ? "" : ifnamep);
+		    mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
+		    ifnamep);
 	}
-	return (first);
+
+	print_transport_label(attr);
+
+	return (B_FALSE);
 }
 
 /* ------------------------------- UDP_REPORT------------------------------- */
 
-static boolean_t udp_report_item_v4(mib2_udpEntry_t *ude, boolean_t first);
-static boolean_t udp_report_item_v6(mib2_udp6Entry_t *ude6, boolean_t first);
+static boolean_t udp_report_item_v4(const mib2_udpEntry_t *ude,
+    boolean_t first, const mib2_transportMLPEntry_t *attr);
+static boolean_t udp_report_item_v6(const mib2_udp6Entry_t *ude6,
+    boolean_t first, const mib2_transportMLPEntry_t *attr);
 
-static char *udp_hdr_v6 =
+static const char udp_hdr_v4[] =
+"   Local Address        Remote Address      State\n"
+"-------------------- -------------------- ----------\n";
+
+static const char udp_hdr_v6[] =
 "   Local Address                     Remote Address                 "
-"  State      If  \n"
+"  State      If\n"
 "--------------------------------- --------------------------------- "
 "---------- -----\n";
 
 static void
-udp_report(mib_item_t *item)
+udp_report(const mib_item_t *item)
 {
 	int			jtemp = 0;
 	boolean_t		print_hdr_once_v4 = B_TRUE;
 	boolean_t		print_hdr_once_v6 = B_TRUE;
 	mib2_udpEntry_t		*ude;
 	mib2_udp6Entry_t	*ude6;
+	mib2_transportMLPEntry_t **v4_attrs, **v6_attrs;
+	mib2_transportMLPEntry_t **v4a, **v6a;
+	mib2_transportMLPEntry_t *aptr;
 
 	if (!protocol_selected(IPPROTO_UDP))
 		return;
 
+	/*
+	 * Preparation pass: the kernel returns separate entries for UDP
+	 * connection table entries and Multilevel Port attributes.  We loop
+	 * through the attributes first and set up an array for each address
+	 * family.
+	 */
+	v4_attrs = family_selected(AF_INET) && RSECflag ?
+	    gather_attrs(item, MIB2_UDP, MIB2_UDP_ENTRY, udpEntrySize) : NULL;
+	v6_attrs = family_selected(AF_INET6) && RSECflag ?
+	    gather_attrs(item, MIB2_UDP6, MIB2_UDP6_ENTRY, udp6EntrySize) :
+	    NULL;
+
+	v4a = v4_attrs;
+	v6a = v6_attrs;
 	/* 'for' loop 1: */
 	for (; item; item = item->next_item) {
 		if (Dflag) {
@@ -4567,8 +4845,9 @@
 			    /* LINTED: (note 1) */
 			    ude = (mib2_udpEntry_t *)((char *)ude +
 			    udpEntrySize)) {
+				aptr = v4a == NULL ? NULL : *v4a++;
 				print_hdr_once_v4 = udp_report_item_v4(ude,
-				    print_hdr_once_v4);
+				    print_hdr_once_v4, aptr);
 			}
 		} else {
 			for (ude6 = (mib2_udp6Entry_t *)item->valp;
@@ -4576,109 +4855,91 @@
 			    /* LINTED: (note 1) */
 			    ude6 = (mib2_udp6Entry_t *)((char *)ude6 +
 			    udp6EntrySize)) {
+				aptr = v6a == NULL ? NULL : *v6a++;
 				print_hdr_once_v6 = udp_report_item_v6(ude6,
-				    print_hdr_once_v6);
+				    print_hdr_once_v6, aptr);
 			}
 		}
 	} /* 'for' loop 1 ends */
 	(void) fflush(stdout);
+
+	if (v4_attrs != NULL)
+		free(v4_attrs);
+	if (v6_attrs != NULL)
+		free(v6_attrs);
 }
 
 static boolean_t
-udp_report_item_v4(mib2_udpEntry_t *ude, boolean_t first)
+udp_report_item_v4(const mib2_udpEntry_t *ude, boolean_t first,
+    const mib2_transportMLPEntry_t *attr)
 {
 	char	lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
 			/* hostname + portname */
-	char	*cp;
 
 	if (!(Aflag || ude->udpEntryInfo.ue_state >= MIB2_UDP_connected))
 		return (first); /* Nothing to print */
 
 	if (first) {
-		(void) puts(v4compat ? "\nUDP" : "\nUDP: IPv4");
-		(void) puts(
-		    "   Local Address         Remote Address     State");
-		(void) puts(
-		    "-------------------- -------------------- -------");
+		(void) printf(v4compat ? "\nUDP\n" : "\nUDP: IPv4\n");
+		(void) printf(udp_hdr_v4);
 		first = B_FALSE;
 	}
 
-	switch (ude->udpEntryInfo.ue_state) {
-	case MIB2_UDP_unbound:
-		cp = "Unbound";
-		break;
-	case MIB2_UDP_idle:
-		cp = "Idle";
-		break;
-	case MIB2_UDP_connected:
-		cp = "Connected";
-		break;
-	default:
-		cp = "Unknown";
-		break;
-	}
 	(void) printf("%-20s ",
 	    pr_ap(ude->udpLocalAddress, ude->udpLocalPort, "udp",
 	    lname, sizeof (lname)));
-	if (ude->udpEntryInfo.ue_state == MIB2_UDP_connected) {
-		(void) printf("%-20s ",
-		    pr_ap(ude->udpEntryInfo.ue_RemoteAddress,
-		    ude->udpEntryInfo.ue_RemotePort, "udp",
-		    lname, sizeof (lname)));
-	} else {
-		(void) printf("%-20s ", "");
-	}
-	(void) printf("  %s\n", cp);
+	(void) printf("%-20s %s\n",
+	    ude->udpEntryInfo.ue_state == MIB2_UDP_connected ?
+	    pr_ap(ude->udpEntryInfo.ue_RemoteAddress,
+	    ude->udpEntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) :
+	    "",
+	    miudp_state(ude->udpEntryInfo.ue_state, attr));
+
+	/*
+	 * UDP sockets don't have remote attributes, so there's no need to
+	 * print them here.
+	 */
+
 	return (first);
 }
 
 static boolean_t
-udp_report_item_v6(mib2_udp6Entry_t *ude6, boolean_t first)
+udp_report_item_v6(const mib2_udp6Entry_t *ude6, boolean_t first,
+    const mib2_transportMLPEntry_t *attr)
 {
 	char	lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
 			/* hostname + portname */
-	char	*cp;
 	char	ifname[LIFNAMSIZ + 1];
+	const char *ifnamep;
 
 	if (!(Aflag || ude6->udp6EntryInfo.ue_state >= MIB2_UDP_connected))
 		return (first); /* Nothing to print */
 
 	if (first) {
-		(void) printf("\nUDP: IPv6\n%s", udp_hdr_v6);
+		(void) printf("\nUDP: IPv6\n");
+		(void) printf(udp_hdr_v6);
 		first = B_FALSE;
 	}
 
-	switch (ude6->udp6EntryInfo.ue_state) {
-	case MIB2_UDP_unbound:
-		cp = "Unbound";
-		break;
-	case MIB2_UDP_idle:
-		cp = "Idle";
-		break;
-	case MIB2_UDP_connected:
-		cp = "Connected";
-		break;
-	default:
-		cp = "Unknown";
-		break;
-	}
+	ifnamep = (ude6->udp6IfIndex != 0) ?
+	    if_indextoname(ude6->udp6IfIndex, ifname) : NULL;
+
 	(void) printf("%-33s ",
 	    pr_ap6(&ude6->udp6LocalAddress,
 	    ude6->udp6LocalPort, "udp", lname, sizeof (lname)));
-	if (ude6->udp6EntryInfo.ue_state == MIB2_UDP_connected) {
-		(void) printf("%-33s ",
-		    pr_ap6(&ude6->udp6EntryInfo.ue_RemoteAddress,
-		    ude6->udp6EntryInfo.ue_RemotePort, "udp",
-		    lname, sizeof (lname)));
-	} else {
-		(void) printf("%-33s ", "");
-	}
-	if (ude6->udp6IfIndex != 0 &&
-	    (if_indextoname(ude6->udp6IfIndex, ifname) != NULL)) {
-		(void) printf("%-10s %-5s\n", cp, ifname);
-	} else {
-		(void) printf("%-10s\n", cp);
-	}
+	(void) printf("%-33s %-10s %s\n",
+	    ude6->udp6EntryInfo.ue_state == MIB2_UDP_connected ?
+	    pr_ap6(&ude6->udp6EntryInfo.ue_RemoteAddress,
+	    ude6->udp6EntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) :
+	    "",
+	    miudp_state(ude6->udp6EntryInfo.ue_state, attr),
+	    ifnamep == NULL ? "" : ifnamep);
+
+	/*
+	 * UDP sockets don't have remote attributes, so there's no need to
+	 * print them here.
+	 */
+
 	return (first);
 }
 
@@ -4693,38 +4954,66 @@
 "------ ------ ------ ------ ------- -----------";
 
 static const char *
-nssctp_state(int state)
+nssctp_state(int state, const mib2_transportMLPEntry_t *attr)
 {
+	static char sctpsbuf[50];
+	const char *cp;
+
 	switch (state) {
 	case MIB2_SCTP_closed:
-		return ("CLOSED");
+		cp = "CLOSED";
+		break;
 	case MIB2_SCTP_cookieWait:
-		return ("COOKIE_WAIT");
+		cp = "COOKIE_WAIT";
+		break;
 	case MIB2_SCTP_cookieEchoed:
-		return ("COOKIE_ECHOED");
+		cp = "COOKIE_ECHOED";
+		break;
 	case MIB2_SCTP_established:
-		return ("ESTABLISHED");
+		cp = "ESTABLISHED";
+		break;
 	case MIB2_SCTP_shutdownPending:
-		return ("SHUTDOWN_PENDING");
+		cp = "SHUTDOWN_PENDING";
+		break;
 	case MIB2_SCTP_shutdownSent:
-		return ("SHUTDOWN_SENT");
+		cp = "SHUTDOWN_SENT";
+		break;
 	case MIB2_SCTP_shutdownReceived:
-		return ("SHUTDOWN_RECEIVED");
+		cp = "SHUTDOWN_RECEIVED";
+		break;
 	case MIB2_SCTP_shutdownAckSent:
-		return ("SHUTDOWN_ACK_SENT");
+		cp = "SHUTDOWN_ACK_SENT";
+		break;
 	case MIB2_SCTP_listen:
-		return ("LISTEN");
+		cp = "LISTEN";
+		break;
 	default:
-		return ("UNKNOWN STATE");
+		(void) snprintf(sctpsbuf, sizeof (sctpsbuf),
+		    "UNKNOWN STATE(%d)", state);
+		cp = sctpsbuf;
+		break;
 	}
+
+	if (RSECflag && attr != NULL && attr->tme_flags != 0) {
+		if (cp != sctpsbuf) {
+			(void) strlcpy(sctpsbuf, cp, sizeof (sctpsbuf));
+			cp = sctpsbuf;
+		}
+		if (attr->tme_flags & MIB2_TMEF_PRIVATE)
+			(void) strlcat(sctpsbuf, " P", sizeof (sctpsbuf));
+		if (attr->tme_flags & MIB2_TMEF_SHARED)
+			(void) strlcat(sctpsbuf, " S", sizeof (sctpsbuf));
+	}
+
+	return (cp);
 }
 
-static mib2_sctpConnRemoteEntry_t *
-sctp_getnext_rem(mib_item_t **itemp, mib2_sctpConnRemoteEntry_t *current,
-    uint32_t associd)
+static const mib2_sctpConnRemoteEntry_t *
+sctp_getnext_rem(const mib_item_t **itemp,
+    const mib2_sctpConnRemoteEntry_t *current, uint32_t associd)
 {
-	mib_item_t *item = *itemp;
-	mib2_sctpConnRemoteEntry_t	*sre;
+	const mib_item_t *item = *itemp;
+	const mib2_sctpConnRemoteEntry_t	*sre;
 
 	for (; item != NULL; item = item->next_item, current = NULL) {
 		if (!(item->group == MIB2_SCTP &&
@@ -4734,15 +5023,15 @@
 
 		if (current != NULL) {
 			/* LINTED: (note 1) */
-			sre = (mib2_sctpConnRemoteEntry_t *)((char *)current +
-			    sctpRemoteEntrySize);
+			sre = (const mib2_sctpConnRemoteEntry_t *)
+			    ((const char *)current + sctpRemoteEntrySize);
 		} else {
 			sre = item->valp;
 		}
 		for (; (char *)sre < (char *)item->valp + item->length;
-			/* LINTED: (note 1) */
-			sre = (mib2_sctpConnRemoteEntry_t *)((char *)sre +
-			    sctpRemoteEntrySize)) {
+		    /* LINTED: (note 1) */
+		    sre = (const mib2_sctpConnRemoteEntry_t *)
+		    ((const char *)sre + sctpRemoteEntrySize)) {
 			if (sre->sctpAssocId != associd) {
 				continue;
 			}
@@ -4754,12 +5043,12 @@
 	return (NULL);
 }
 
-static mib2_sctpConnLocalEntry_t *
-sctp_getnext_local(mib_item_t **itemp, mib2_sctpConnLocalEntry_t *current,
-    uint32_t associd)
+static const mib2_sctpConnLocalEntry_t *
+sctp_getnext_local(const mib_item_t **itemp,
+    const mib2_sctpConnLocalEntry_t *current, uint32_t associd)
 {
-	mib_item_t *item = *itemp;
-	mib2_sctpConnLocalEntry_t	*sle;
+	const mib_item_t *item = *itemp;
+	const mib2_sctpConnLocalEntry_t	*sle;
 
 	for (; item != NULL; item = item->next_item, current = NULL) {
 		if (!(item->group == MIB2_SCTP &&
@@ -4769,15 +5058,15 @@
 
 		if (current != NULL) {
 			/* LINTED: (note 1) */
-			sle = (mib2_sctpConnLocalEntry_t *)((char *)current +
-			    sctpLocalEntrySize);
+			sle = (const mib2_sctpConnLocalEntry_t *)
+			    ((const char *)current + sctpLocalEntrySize);
 		} else {
 			sle = item->valp;
 		}
 		for (; (char *)sle < (char *)item->valp + item->length;
-			/* LINTED: (note 1) */
-			sle = (mib2_sctpConnLocalEntry_t *)((char *)sle +
-			    sctpLocalEntrySize)) {
+		    /* LINTED: (note 1) */
+		    sle = (const mib2_sctpConnLocalEntry_t *)
+		    ((const char *)sle + sctpLocalEntrySize)) {
 			if (sle->sctpAssocId != associd) {
 				continue;
 			}
@@ -4830,14 +5119,15 @@
 }
 
 static void
-sctp_conn_report_item(mib_item_t *head, mib2_sctpConnEntry_t *sp)
+sctp_conn_report_item(const mib_item_t *head, const mib2_sctpConnEntry_t *sp,
+    const mib2_transportMLPEntry_t *attr)
 {
 	char		lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
 	char		fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
-	mib2_sctpConnRemoteEntry_t	*sre = NULL;
-	mib2_sctpConnLocalEntry_t	*sle = NULL;
-	mib_item_t	*local = head;
-	mib_item_t	*remote = head;
+	const mib2_sctpConnRemoteEntry_t	*sre = NULL;
+	const mib2_sctpConnLocalEntry_t	*sle = NULL;
+	const mib_item_t *local = head;
+	const mib_item_t *remote = head;
 	uint32_t	id = sp->sctpAssocId;
 	boolean_t	printfirst = B_TRUE;
 
@@ -4853,7 +5143,9 @@
 	    sp->sctpConnEntryInfo.ce_rwnd,
 	    sp->sctpConnEntryInfo.ce_recvq,
 	    sp->sctpAssocInStreams, sp->sctpAssocOutStreams,
-	    nssctp_state(sp->sctpAssocState));
+	    nssctp_state(sp->sctpAssocState, attr));
+
+	print_transport_label(attr);
 
 	if (!Vflag) {
 		return;
@@ -4902,12 +5194,25 @@
 }
 
 static void
-sctp_report(mib_item_t *item)
+sctp_report(const mib_item_t *item)
 {
-	mib_item_t		*head;
-	mib2_sctpConnEntry_t	*sp;
+	const mib_item_t		*head;
+	const mib2_sctpConnEntry_t	*sp;
 	boolean_t		first = B_TRUE;
+	mib2_transportMLPEntry_t **attrs, **aptr;
+	mib2_transportMLPEntry_t *attr;
 
+	/*
+	 * Preparation pass: the kernel returns separate entries for SCTP
+	 * connection table entries and Multilevel Port attributes.  We loop
+	 * through the attributes first and set up an array for each address
+	 * family.
+	 */
+	attrs = RSECflag ?
+	    gather_attrs(item, MIB2_SCTP, MIB2_SCTP_CONN, sctpEntrySize) :
+	    NULL;
+
+	aptr = attrs;
 	head = item;
 	for (; item != NULL; item = item->next_item) {
 
@@ -4916,11 +5221,10 @@
 			continue;
 
 		for (sp = item->valp;
-			(char *)sp < (char *)item->valp + item->length;
-			/* LINTED: (note 1) */
-			sp = (mib2_sctpConnEntry_t *)((char *)sp +
-			    sctpEntrySize)) {
-
+		    (char *)sp < (char *)item->valp + item->length;
+		    /* LINTED: (note 1) */
+		    sp = (mib2_sctpConnEntry_t *)((char *)sp + sctpEntrySize)) {
+			attr = aptr == NULL ? NULL : *aptr++;
 			if (Aflag ||
 			    sp->sctpAssocState >= MIB2_SCTP_established) {
 				if (first == B_TRUE) {
@@ -4928,10 +5232,12 @@
 					(void) puts(sctp_hdr_normal);
 					first = B_FALSE;
 				}
-				sctp_conn_report_item(head, sp);
+				sctp_conn_report_item(head, sp, attr);
 			}
 		}
 	}
+	if (attrs != NULL)
+		free(attrs);
 }
 
 static char *
@@ -5330,7 +5636,8 @@
  * Does not print /128 to save space in printout. H flag carries this notion.
  */
 static char *
-pr_prefix6(struct in6_addr *addr, uint_t prefixlen, char *dst, uint_t dstlen)
+pr_prefix6(const struct in6_addr *addr, uint_t prefixlen, char *dst,
+    uint_t dstlen)
 {
 	char *cp;
 
@@ -5634,6 +5941,53 @@
 	}
 }
 
+#define	MAX_STRING_SIZE	256
+
+static const char *
+pr_secattr(const sec_attr_list_t *attrs)
+{
+	int i;
+	char buf[MAX_STRING_SIZE + 1], *cp;
+	static char *sbuf;
+	static size_t sbuf_len;
+	struct rtsa_s rtsa;
+	const sec_attr_list_t *aptr;
+
+	if (!RSECflag || attrs == NULL)
+		return ("");
+
+	for (aptr = attrs, i = 1; aptr != NULL; aptr = aptr->sal_next)
+		i += MAX_STRING_SIZE;
+	if (i > sbuf_len) {
+		cp = realloc(sbuf, i);
+		if (cp == NULL) {
+			perror("realloc security attribute buffer");
+			return ("");
+		}
+		sbuf_len = i;
+		sbuf = cp;
+	}
+
+	cp = sbuf;
+	while (attrs != NULL) {
+		const mib2_ipAttributeEntry_t *iae = attrs->sal_attr;
+
+		/* note: effectively hard-coded in rtsa_keyword */
+		rtsa.rtsa_mask = RTSA_CIPSO | RTSA_SLRANGE | RTSA_DOI;
+		rtsa.rtsa_slrange = iae->iae_slrange;
+		rtsa.rtsa_doi = iae->iae_doi;
+
+		(void) snprintf(cp, MAX_STRING_SIZE,
+		    "<%s>%s ", rtsa_to_str(&rtsa, buf, sizeof (buf)),
+		    attrs->sal_next == NULL ? "" : ",");
+		cp += strlen(cp);
+		attrs = attrs->sal_next;
+	}
+	*cp = '\0';
+
+	return (sbuf);
+}
+
 /*
  * Pretty print a port number. If the Nflag was
  * specified, use numbers instead of names.
@@ -5936,7 +6290,8 @@
  */
 /*PRINTFLIKE2*/
 static void
-fatal(int errcode, char *format, ...) {
+fatal(int errcode, char *format, ...)
+{
 	va_list argp;
 
 	if (format == NULL)
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/Makefile b/usr/src/cmd/cmd-inet/usr.sbin/Makefile
index af9d3a9..efb96c7 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/Makefile
+++ b/usr/src/cmd/cmd-inet/usr.sbin/Makefile
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -18,9 +17,11 @@
 # information: Portions Copyright [yyyy] [name of copyright owner]
 #
 # CDDL HEADER END
+
+
 #
 #
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -58,6 +59,7 @@
 CMDPROG=	in.telnetd
 IPSECUTILPROG=	ikeadm ipsecalgs ipsecconf ipseckey
 K5PROGS=	in.telnetd in.rlogind in.rshd
+TSNETPROG=	route
 DEFAULTFILES=	telnetd.dfl
 
 PROGSRCS=	$(PROG:%=%.c)
@@ -148,6 +150,7 @@
 				-I$(SRC)/lib/pam_modules/krb5
 LDLIBS +=	$(K5LIBS)
 $(IPSECUTILPROG)	:=	LDLIBS += -lipsecutil
+$(TSNETPROG)		:=	LDLIBS += -ltsnet
 
 in.rarpd		:=	LDLIBS += -linetutil
 route			:=	CPPFLAGS += -DNDEBUG
@@ -246,7 +249,7 @@
 	$(LINT.c) ipsecconf.c $(LDLIBS) -lsocket -lnsl -lipsecutil
 	$(LINT.c) ipseckey.c $(LDLIBS) -lsocket -lnsl -lipsecutil
 	$(LINT.c) ikeadm.c $(LDLIBS) -lnsl -lipsecutil
-	$(LINT.c) route.c $(LDLIBS) -lsocket -lnsl
+	$(LINT.c) route.c $(LDLIBS) -lsocket -lnsl -ltsnet
 	$(LINT.c) routeadm.c $(LDLIBS) -lsocket
 	$(LINT.c) syncinit.c $(LDLIBS) -ldlpi
 	$(LINT.c) syncloop.c $(LDLIBS) -ldlpi
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c b/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c
index ee57766..162a64a 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 /*
@@ -162,6 +162,7 @@
 static int	clr_tun_encap_limit(char *arg, int64_t param);
 static int	set_tun_hop_limit(char *arg, int64_t param);
 static int	setzone(char *arg, int64_t param);
+static int	setallzones(char *arg, int64_t param);
 static int	setifsrc(char *arg, int64_t param);
 
 #ifdef DEBUG
@@ -307,6 +308,7 @@
 	{ "destination", NEXTARG,	setifdstaddr,	0,	AF_ANY },
 	{ "zone",	NEXTARG,	setzone,	0,	AF_ANY },
 	{ "-zone",	0,		setzone,	0,	AF_ANY },
+	{ "all-zones",	0,		setallzones,	0,	AF_ANY },
 	{ "ether",	OPTARG,		setifether,	0,	AF_ANY },
 	{ "usesrc",	NEXTARG,	setifsrc,	0,	AF_ANY },
 	{ 0,		0,		setifaddr,	0,	AF_ANY },
@@ -2858,6 +2860,18 @@
 	return (0);
 }
 
+/* Put interface into all zones */
+/* ARGSUSED */
+static int
+setallzones(char *arg, int64_t param)
+{
+	(void) strlcpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
+	lifr.lifr_zoneid = ALL_ZONES;
+	if (ioctl(s, SIOCSLIFZONE, (caddr_t)&lifr) == -1)
+		Perror0_exit("SIOCSLIFZONE");
+	return (0);
+}
+
 /* Set source address to use */
 /* ARGSUSED */
 static int
@@ -2958,7 +2972,9 @@
 		    lifr.lifr_zoneid != getzoneid()) {
 			char zone_name[ZONENAME_MAX];
 
-			if (getzonenamebyid(lifr.lifr_zoneid, zone_name,
+			if (lifr.lifr_zoneid == ALL_ZONES) {
+				(void) printf("\n\tall-zones");
+			} else if (getzonenamebyid(lifr.lifr_zoneid, zone_name,
 			    sizeof (zone_name)) < 0) {
 				(void) printf("\n\tzone %d", lifr.lifr_zoneid);
 			} else {
@@ -4765,7 +4781,8 @@
 	    "\t[ standby | -standby ]\n"
 	    "\t[ failover | -failover ]\n"
 	    "\t[ zone <zonename> | -zone ]\n"
-	    "\t[ usesrc <interface> ]\n");
+	    "\t[ usesrc <interface> ]\n"
+	    "\t[ all-zones ]\n");
 
 	(void) fprintf(stderr, "or\n");
 	(void) fprintf(stderr,
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/in.routed/table.c b/usr/src/cmd/cmd-inet/usr.sbin/in.routed/table.c
index 1c81d64..d23133c 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/in.routed/table.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/in.routed/table.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  *
  * Copyright (c) 1983, 1988, 1993
@@ -1692,6 +1692,8 @@
  * ss is a pointer to the beginning of the data following the
  * rt_msghdr contained in the routing socket message, which consists
  * of a string of concatenated sockaddr structure of different types.
+ *
+ * Extended attributes can be appended at the end of the list.
  */
 static int
 rt_xaddrs(struct rt_addrinfo *info,
@@ -1766,11 +1768,35 @@
 			goto xaddr_done;
 		}
 	}
+
+	while (((char *)ss + sizeof (rtm_ext_t)) <= lim) {
+		rtm_ext_t *tp;
+		char *nxt;
+
+		/* LINTED: alignment */
+		tp = (rtm_ext_t *)ss;
+		nxt = (char *)(tp + 1) + tp->rtmex_len;
+
+		if (!IS_P2ALIGNED(tp->rtmex_len, sizeof (uint32_t)) ||
+		    nxt > lim) {
+			break;
+		}
+
+		/* LINTED: alignment */
+		ss = (struct sockaddr_storage *)nxt;
+	}
+
 	if ((char *)ss != lim) {
-		if (!(prev_complaints & XBAD_LONG))
+		if ((char *)ss > lim) {
+			if (!(prev_complaints & XBAD_SHORT))
+				msglog("routing message too short by %d bytes",
+				    (char *)ss - lim);
+			complaints |= XBAD_SHORT;
+		} else if (!(prev_complaints & XBAD_LONG)) {
 			msglog("%d bytes of routing message left over",
 			    lim - (char *)ss);
-		complaints |= XBAD_LONG;
+			complaints |= XBAD_LONG;
+		}
 		retv = -1;
 	}
 xaddr_done:
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/route.c b/usr/src/cmd/cmd-inet/usr.sbin/route.c
index 18044d9..431d92d 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/route.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/route.c
@@ -74,11 +74,16 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <stddef.h>
 #include <string.h>
 #include <stropts.h>
 #include <fcntl.h>
 #include <stdarg.h>
 #include <assert.h>
+#include <strings.h>
+
+#include <libtsnet.h>
+#include <tsol/label.h>
 
 static struct keytab {
 	char	*kt_cp;
@@ -168,6 +173,8 @@
 	{"setsrc",	K_SETSRC},
 #define	K_SHOW		43
 	{"show",	K_SHOW},
+#define	K_SECATTR	43
+	{"secattr",	K_SECATTR},
 	{0, 0}
 };
 
@@ -206,14 +213,16 @@
 	su_t ri_ifa;
 	su_t ri_ifp;
 	char *ri_ifp_str;
+	int ri_rtsa_cnt;	/* number of gateway security attributes */
+	struct rtsa_s ri_rtsa;	/* enough space for one attribute */
 } rtcmd_irep_t;
 
 typedef struct	mib_item_s {
-	struct mib_item_s	*next_item;
-	long			group;
-	long			mib_id;
-	long			length;
-	intmax_t		*valp;
+	struct mib_item_s *next_item;
+	long group;
+	long mib_id;
+	long length;
+	intmax_t *valp;
 } mib_item_t;
 
 typedef enum {
@@ -257,18 +266,18 @@
 static char		*netname(struct sockaddr *sa);
 static int		newroute(char **argv);
 static rtcmd_irep_t	*new_rtcmd_irep(void);
-static void		pmsg_addrs(char *cp, int addrs);
-static void		pmsg_common(struct rt_msghdr *rtm);
+static void		pmsg_addrs(const char *cp, size_t len, uint_t addrs);
+static void		pmsg_common(const struct rt_msghdr *rtm, size_t len);
 static void		print_getmsg(rtcmd_irep_t *req_rt,
     struct rt_msghdr *rtm, int msglen);
 static void		print_rtcmd_short(FILE *to, rtcmd_irep_t *rcip,
     boolean_t gw_good, boolean_t to_saved);
 static void		print_rtmsg(struct rt_msghdr *rtm, int msglen);
 static void		quit(char *s, int err) __NORETURN;
-static char		*routename(struct sockaddr *sa);
+static char		*routename(const struct sockaddr *sa);
 static void		rtmonitor(int argc, char *argv[]);
 static int		rtmsg(rtcmd_irep_t *rcip);
-static int		salen(struct sockaddr *sa);
+static int		salen(const struct sockaddr *sa);
 static void		save_route(int argc, char **argv, int do_flush);
 static void		save_string(char **dst, char *src);
 static int		search_rtfile(FILE *fp, FILE *temp_fp, rtcmd_irep_t *rt,
@@ -283,6 +292,7 @@
 static void		syntax_error(char *err, ...);
 static void		usage(char *cp);
 static void		write_to_rtfile(FILE *fp, int argc, char **argv);
+static void		pmsg_secattr(const char *, size_t, const char *);
 
 static pid_t		pid;
 static int		s;
@@ -315,7 +325,7 @@
 
 static struct {
 	struct	rt_msghdr m_rtm;
-	char	m_space[512];
+	char	m_space[BUF_SIZE];
 } m_rtmsg;
 
 /*
@@ -337,7 +347,6 @@
 #define	BAD_ADDR	-1	/* prefix is invalid */
 #define	NO_PREFIX	-2	/* no prefix was found */
 
-
 void
 usage(char *cp)
 {
@@ -408,7 +417,7 @@
 	(void) textdomain(TEXT_DOMAIN);
 
 	if (argc < 2)
-		usage((char *)NULL);
+		usage(NULL);
 
 	while ((ch = getopt(argc, argv, "R:nqdtvfp")) != EOF) {
 		switch (ch) {
@@ -438,7 +447,7 @@
 			break;
 		case '?':
 		default:
-			usage((char *)NULL);
+			usage(NULL);
 			/* NOTREACHED */
 		}
 	}
@@ -815,7 +824,7 @@
  * Return the name of the host whose address is given.
  */
 char *
-routename(struct sockaddr *sa)
+routename(const struct sockaddr *sa)
 {
 	char *cp;
 	static char line[MAXHOSTNAMELEN + 1];
@@ -1362,6 +1371,31 @@
 			}
 			rcip->ri_flags |= RTF_SETSRC;
 			break;
+		case K_SECATTR:
+			if (!NEXTTOKEN) {
+				syntax_arg_missing(keyword_str);
+				return (B_FALSE);
+			}
+			if ((rcip->ri_cmd == RTM_ADD ||
+			    rcip->ri_cmd == RTM_CHANGE) &&
+			    rcip->ri_rtsa_cnt++ < 1 && is_system_labeled()) {
+				int err;
+
+				if (!rtsa_keyword(tok, &rcip->ri_rtsa, &err,
+				    NULL)) {
+					(void) fprintf(stderr, gettext("route: "
+					    "bad security attribute: %s\n"),
+					    tsol_strerror(err, errno));
+					return (B_FALSE);
+				}
+			}
+			if (rcip->ri_rtsa_cnt > 1) {
+				(void) fprintf(stderr,
+				    gettext("route: can't specify more "
+				    "than one security attribute\n"));
+				return (B_FALSE);
+			}
+			break;
 		default:
 			if (dash_keyword) {
 				syntax_bad_keyword(tok + 1);
@@ -2428,7 +2462,25 @@
 	 */
 	NEXTADDR(RTA_SRC, newrt->ri_src);
 #undef	NEXTADDR
+
+	if (newrt->ri_rtsa_cnt > 0) {
+		/* LINTED: aligned */
+		rtm_ext_t *rtm_ext = (rtm_ext_t *)cp;
+		tsol_rtsecattr_t *rtsecattr;
+
+		rtm_ext->rtmex_type = RTMEX_GATEWAY_SECATTR;
+		rtm_ext->rtmex_len = TSOL_RTSECATTR_SIZE(1);
+
+		rtsecattr = (tsol_rtsecattr_t *)(rtm_ext + 1);
+		rtsecattr->rtsa_cnt = 1;
+
+		bcopy(&newrt->ri_rtsa, rtsecattr->rtsa_attr,
+		    sizeof (newrt->ri_rtsa));
+		cp = (char *)(rtsecattr->rtsa_attr + 1);
+	}
+
 	rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
+
 	if (verbose)
 		print_rtmsg(&rtm, l);
 	if (debugonly)
@@ -2522,10 +2574,12 @@
 		    rtm->rtm_version);
 		return;
 	}
-	if (rtm->rtm_msglen > (ushort_t)msglen) {
+	if (rtm->rtm_msglen != msglen) {
 		(void) printf("message length mismatch, in packet %d, "
 		    "returned %d\n",
 		    rtm->rtm_msglen, msglen);
+		if (msglen > rtm->rtm_msglen)
+			msglen = rtm->rtm_msglen;
 	}
 	/*
 	 * Since rtm->rtm_type is unsigned, we'll just check the case of zero
@@ -2536,26 +2590,29 @@
 		    rtm->rtm_type);
 		return;
 	}
-	(void) printf("%s: len %d, ", msgtypes[rtm->rtm_type], rtm->rtm_msglen);
+	(void) printf("%s: len %d, ", msgtypes[rtm->rtm_type], msglen);
 	switch (rtm->rtm_type) {
 	case RTM_IFINFO:
 		ifm = (struct if_msghdr *)rtm;
 		(void) printf("if# %d, flags:", ifm->ifm_index);
 		bprintf(stdout, ifm->ifm_flags, ifnetflags);
-		pmsg_addrs((char *)(ifm + 1), ifm->ifm_addrs);
+		pmsg_addrs((const char *)(ifm + 1), msglen - sizeof (*ifm),
+		    ifm->ifm_addrs);
 		break;
 	case RTM_NEWADDR:
 	case RTM_DELADDR:
 		ifam = (struct ifa_msghdr *)rtm;
 		(void) printf("metric %d, flags:", ifam->ifam_metric);
 		bprintf(stdout, ifam->ifam_flags, routeflags);
-		pmsg_addrs((char *)(ifam + 1), ifam->ifam_addrs);
+		pmsg_addrs((const char *)(ifam + 1), msglen - sizeof (*ifam),
+		    ifam->ifam_addrs);
 		break;
 	default:
 		(void) printf("pid: %ld, seq %d, errno %d, flags:",
 			rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno);
 		bprintf(stdout, rtm->rtm_flags, routeflags);
-		pmsg_common(rtm);
+		pmsg_common(rtm, msglen);
+		break;
 	}
 }
 
@@ -2665,50 +2722,76 @@
 	(void) printf("%8d%c ", rtm->rtm_rmx.rmx_mtu, lock(MTU));
 	if (rtm->rtm_rmx.rmx_expire)
 		rtm->rtm_rmx.rmx_expire -= time(0);
-	(void) printf("%8d%c\n", rtm->rtm_rmx.rmx_expire, lock(EXPIRE));
+	(void) printf("%8d%c", rtm->rtm_rmx.rmx_expire, lock(EXPIRE));
 #undef lock
 #undef msec
 #define	RTA_IGN	\
 	(RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_IFP|RTA_IFA|RTA_BRD|RTA_SRC)
 	if (verbose) {
-		pmsg_common(rtm);
-	} else if (rtm->rtm_addrs &~ RTA_IGN) {
-		(void) printf("sockaddrs: ");
-		bprintf(stdout, rtm->rtm_addrs, addrnames);
+		pmsg_common(rtm, msglen);
+	} else {
+		const char *sptr, *endptr;
+		const struct sockaddr *sa;
+		uint_t addrs;
+
+		/* Not verbose; just print out the exceptional cases */
+		if (rtm->rtm_addrs &~ RTA_IGN) {
+			(void) printf("\nsockaddrs: ");
+			bprintf(stdout, rtm->rtm_addrs, addrnames);
+		}
+		sptr = (const char *)(rtm + 1);
+		endptr = (const char *)rtm + msglen;
+		addrs = rtm->rtm_addrs;
+		while (addrs != 0 && sptr + sizeof (*sa) <= endptr) {
+			addrs &= addrs - 1;
+			/* LINTED */
+			sa = (const struct sockaddr *)sptr;
+			ADVANCE(sptr, sa);
+		}
+		if (addrs == 0)
+			pmsg_secattr(sptr, endptr - sptr, "    secattr: ");
 		(void) putchar('\n');
 	}
 #undef	RTA_IGN
 }
 
-void
-pmsg_common(struct rt_msghdr *rtm)
+static void
+pmsg_common(const struct rt_msghdr *rtm, size_t msglen)
 {
 	(void) printf("\nlocks: ");
 	bprintf(stdout, (int)rtm->rtm_rmx.rmx_locks, metricnames);
 	(void) printf(" inits: ");
 	bprintf(stdout, (int)rtm->rtm_inits, metricnames);
-	pmsg_addrs(((char *)(rtm + 1)), rtm->rtm_addrs);
+	pmsg_addrs((const char *)(rtm + 1), msglen - sizeof (*rtm),
+	    rtm->rtm_addrs);
 }
 
-void
-pmsg_addrs(char *cp, int addrs)
+static void
+pmsg_addrs(const char *cp, size_t msglen, uint_t addrs)
 {
-	struct sockaddr *sa;
+	const struct sockaddr *sa;
+	const char *maxptr;
 	int i;
 
-	if (addrs == 0)
-		return;
-	(void) printf("\nsockaddrs: ");
-	bprintf(stdout, addrs, addrnames);
-	(void) putchar('\n');
-	for (i = 1; i != 0; i <<= 1) {
-		if (i & addrs) {
-			/* LINTED */
-			sa = (struct sockaddr *)cp;
-			(void) printf(" %s", routename(sa));
-			ADVANCE(cp, sa);
+	if (addrs != 0) {
+		(void) printf("\nsockaddrs: ");
+		bprintf(stdout, addrs, addrnames);
+		(void) putchar('\n');
+		maxptr = cp + msglen;
+		for (i = 1; i != 0 && cp + sizeof (*sa) <= maxptr; i <<= 1) {
+			if (i & addrs) {
+				/* LINTED */
+				sa = (const struct sockaddr *)cp;
+				(void) printf(" %s", routename(sa));
+				ADVANCE(cp, sa);
+			}
 		}
+		if (i != 0)
+			msglen = 0;
+		else
+			msglen = maxptr - cp;
 	}
+	pmsg_secattr(cp, msglen, "secattr: ");
 	(void) putchar('\n');
 	(void) fflush(stdout);
 }
@@ -2834,7 +2917,7 @@
 }
 
 int
-salen(struct sockaddr *sa)
+salen(const struct sockaddr *sa)
 {
 	switch (sa->sa_family) {
 	case AF_INET:
@@ -3094,3 +3177,57 @@
 	}
 	return (NULL);
 }
+
+/*
+ * print label security attributes for gateways.
+ */
+static void
+pmsg_secattr(const char *sptr, size_t msglen, const char *labelstr)
+{
+	rtm_ext_t rtm_ext;
+	tsol_rtsecattr_t sp;
+	struct rtsa_s *rtsa = &sp.rtsa_attr[0];
+	const char *endptr;
+	char buf[256];
+	int i;
+
+	if (!is_system_labeled())
+		return;
+
+	endptr = sptr + msglen;
+
+	for (;;) {
+		if (sptr + sizeof (rtm_ext_t) + sizeof (sp) > endptr)
+			return;
+
+		bcopy(sptr, &rtm_ext, sizeof (rtm_ext));
+		sptr += sizeof (rtm_ext);
+		if (rtm_ext.rtmex_type == RTMEX_GATEWAY_SECATTR)
+			break;
+		sptr += rtm_ext.rtmex_len;
+	}
+
+	/* bail if this entry is corrupt or overruns buffer length */
+	if (rtm_ext.rtmex_len < sizeof (sp) ||
+	    sptr + rtm_ext.rtmex_len > endptr)
+		return;
+
+	/* run up just to the end of this extension */
+	endptr = sptr + rtm_ext.rtmex_len;
+
+	bcopy(sptr, &sp, sizeof (sp));
+	sptr += sizeof (sp);
+
+	if (sptr + (sp.rtsa_cnt - 1) * sizeof (*rtsa) != endptr)
+		return;
+
+	for (i = 0; i < sp.rtsa_cnt; i++) {
+		if (i > 0) {
+			/* first element is part of sp initalized above */
+			bcopy(sptr, rtsa, sizeof (*rtsa));
+			sptr += sizeof (*rtsa);
+		}
+		(void) printf("\n%s%s", labelstr, rtsa_to_str(rtsa, buf,
+		    sizeof (buf)));
+	}
+}
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile b/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile
index e9dc9a3..d853d7f 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -18,9 +17,11 @@
 # information: Portions Copyright [yyyy] [name of copyright owner]
 #
 # CDDL HEADER END
+
+
 #
 #
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -46,7 +47,8 @@
 include	../../../Makefile.cmd
 
 CPPFLAGS += -I. -I$(SRC)/common/net/dhcp
-LDLIBS += -ldhcputil -ldlpi -lsocket -lnsl
+LDLIBS += -ldhcputil -ldlpi -lsocket -lnsl \
+	-z lazyload -ltsol -z nolazyload
 
 .KEEP_STATE:
 
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.c b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.c
index 3b5e49b..386fcbc 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.c
@@ -53,7 +53,7 @@
 
 #include "snoop.h"
 
-int snaplen;
+static int snaplen;
 char *device = NULL;
 
 /* Global error recovery variables */
@@ -61,12 +61,9 @@
 int snoop_nrecover;			/* number of recoveries on curr pkt */
 int quitting;				/* user termination flag */
 
-extern int encap_levels;		/* variables needing reset on error */
-extern unsigned int total_encap_levels;
-
-struct snoop_handler *snoop_hp;		/* global alarm handler head */
-struct snoop_handler *snoop_tp;		/* global alarm handler tail */
-time_t snoop_nalarm;			/* time of next alarm */
+static struct snoop_handler *snoop_hp;		/* global alarm handler head */
+static struct snoop_handler *snoop_tp;		/* global alarm handler tail */
+static time_t snoop_nalarm;			/* time of next alarm */
 
 /* protected interpreter output areas */
 #define	MAXSUM		8
@@ -76,10 +73,10 @@
 static char *line;
 static char *encap;
 
-int audio;
+static int audio;
 int maxcount;	/* maximum no of packets to capture */
 int count;	/* count of packets captured */
-int sumcount;
+static int sumcount;
 int x_offset = -1;
 int x_length = 0x7fffffff;
 FILE *namefile;
@@ -91,17 +88,15 @@
 #endif
 struct Pf_ext_packetfilt pf;
 
-void usage();
+static void usage(void);
 void show_count();
-void snoop_sigrecover(int sig, siginfo_t *info, void *p);
+static void snoop_sigrecover(int sig, siginfo_t *info, void *p);
 static char *protmalloc(size_t);
 static void resetperm(void);
 
 int
 main(int argc, char **argv)
 {
-	extern char *optarg;
-	extern int optind;
 	int c;
 	int filter = 0;
 	int flags = F_SUM;
@@ -120,8 +115,6 @@
 	char self[MAXHOSTNAMELEN + 1];
 	char *argstr = NULL;
 	void (*proc)();
-	extern void cap_write();
-	extern void process_pkt();
 	char *audiodev;
 	int ret;
 	struct sigaction sigact;
@@ -170,7 +163,7 @@
 	/* Initialize a master signal handler */
 	sigact.sa_handler = NULL;
 	sigact.sa_sigaction = snoop_sigrecover;
-	sigemptyset(&sigact.sa_mask);
+	(void) sigemptyset(&sigact.sa_mask);
 	sigact.sa_flags = SA_ONSTACK|SA_SIGINFO;
 
 	/* Register master signal handler */
@@ -231,7 +224,7 @@
 	if (sigsetjmp(jmp_env, 1)) {
 		exit(1);
 	}
-	setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
+	(void) setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
 
 	while ((c = getopt(argc, argv, "at:CPDSi:o:Nn:s:d:vVp:f:c:x:?rqz"))
 				!= EOF) {
@@ -491,7 +484,7 @@
 		net_read(chunksize, filter, proc, flags);
 
 		if (!(flags & F_NOW))
-			printf("\n");
+			(void) printf("\n");
 	}
 
 	if (ocapfile)
@@ -500,7 +493,7 @@
 	return (0);
 }
 
-int tone[] = {
+static int tone[] = {
 0x076113, 0x153333, 0x147317, 0x144311, 0x147315, 0x050353, 0x037103, 0x051106,
 0x157155, 0x142723, 0x133273, 0x134664, 0x051712, 0x024465, 0x026447, 0x072473,
 0x136715, 0x126257, 0x135256, 0x047344, 0x034476, 0x027464, 0x036062, 0x133334,
@@ -524,7 +517,7 @@
 	len = len ? len : 4;
 
 	if (audio) {
-		write(audio, tone, len);
+		(void) write(audio, tone, len);
 	}
 }
 
@@ -561,16 +554,16 @@
 	int i, start;
 
 	if (flags & F_NUM) {
-		sprintf(lp, "%3d ", num);
+		(void) sprintf(lp, "%3d ", num);
 		lp += strlen(lp);
 	}
 	tm = localtime(&tvp->tv_sec);
 
 	if (flags & F_TIME) {
 		if (flags & F_ATIME) {
-			sprintf(lp, "%d:%02d:%d.%05d ",
+			(void) sprintf(lp, "%d:%02d:%d.%05d ",
 				tm->tm_hour, tm->tm_min, tm->tm_sec,
-				tvp->tv_usec / 10);
+				(int)tvp->tv_usec / 10);
 			lp += strlen(lp);
 		} else {
 			if (flags & F_RTIME) {
@@ -586,44 +579,44 @@
 				usec += 1000000;
 				sec  -= 1;
 			}
-			sprintf(lp, "%3d.%05d ", sec, usec / 10);
+			(void) sprintf(lp, "%3d.%05d ", sec, usec / 10);
 			lp += strlen(lp);
 		}
 	}
 
 	if (flags & F_WHO) {
-		sprintf(lp, "%12s -> %-12s ", src, dst);
+		(void) sprintf(lp, "%12s -> %-12s ", src, dst);
 		lp += strlen(lp);
 	}
 
 	if (flags & F_DROPS) {
-		sprintf(lp, "drops: %d ", drops);
+		(void) sprintf(lp, "drops: %d ", drops);
 		lp += strlen(lp);
 	}
 
 	if (flags & F_LEN) {
-		sprintf(lp, "length: %4d  ", len);
+		(void) sprintf(lp, "length: %4d  ", len);
 		lp += strlen(lp);
 	}
 
 	if (flags & F_SUM) {
 		if (flags & F_ALLSUM)
-			printf("________________________________\n");
+			(void) printf("________________________________\n");
 
 		start = flags & F_ALLSUM ? 0 : sumcount - 1;
-		sprintf(encap, "  (%d encap)", total_encap_levels - 1);
-		printf("%s%s%s\n", line, sumline[start],
+		(void) sprintf(encap, "  (%d encap)", total_encap_levels - 1);
+		(void) printf("%s%s%s\n", line, sumline[start],
 		    ((flags & F_ALLSUM) || (total_encap_levels == 1)) ? "" :
 			encap);
 
 		for (i = start + 1; i < sumcount; i++)
-			printf("%s%s\n", line, sumline[i]);
+			(void) printf("%s%s\n", line, sumline[i]);
 
 		sumcount = 0;
 	}
 
 	if (flags & F_DTAIL) {
-		printf("%s\n\n", detail_line);
+		(void) printf("%s\n\n", detail_line);
 		detail_line[0] = '\0';
 	}
 }
@@ -658,7 +651,7 @@
 	int off, len;
 {
 	if (detail_line[0]) {
-		printf("%s\n", detail_line);
+		(void) printf("%s\n", detail_line);
 		detail_line[0] = '\0';
 	}
 	return (detail_line);
@@ -667,27 +660,32 @@
 /*
  * Print an error.
  * Works like printf (fmt string and variable args)
- * except that it will subsititute an error message
+ * except that it will substitute an error message
  * for a "%m" string (like syslog) and it calls
  * long_jump - it doesn't return to where it was
  * called from - it goes to the last setjmp().
  */
+/* VARARGS1 */
 void
-pr_err(char *fmt, ...)
+pr_err(const char *fmt, ...)
 {
 	va_list ap;
-	char buf[BUFSIZ], *p2;
-	char *p1;
+	char buf[1024], *p2;
+	const char *p1;
 
-	strcpy(buf, "snoop: ");
+	(void) strcpy(buf, "snoop: ");
 	p2 = buf + strlen(buf);
 
-	for (p1 = fmt; *p1; p1++) {
+	/*
+	 * Note that we terminate the buffer with '\n' and '\0'.
+	 */
+	for (p1 = fmt; *p1 != '\0' && p2 < buf + sizeof (buf) - 2; p1++) {
 		if (*p1 == '%' && *(p1+1) == 'm') {
-			char *errstr;
+			const char *errstr;
 
-			if ((errstr = strerror(errno)) != (char *)NULL) {
-				(void) strcpy(p2, errstr);
+			if ((errstr = strerror(errno)) != NULL) {
+				*p2 = '\0';
+				(void) strlcat(buf, errstr, sizeof (buf));
 				p2 += strlen(p2);
 			}
 			p1++;
@@ -700,6 +698,7 @@
 	*p2 = '\0';
 
 	va_start(ap, fmt);
+	/* LINTED: E_SEC_PRINTF_VAR_FMT */
 	(void) vfprintf(stderr, buf, ap);
 	va_end(ap);
 	snoop_sigrecover(-1, NULL, NULL);	/* global error recovery */
@@ -710,8 +709,8 @@
  * PLEASE keep this up to date!
  * Naive users *love* this stuff.
  */
-void
-usage()
+static void
+usage(void)
 {
 	(void) fprintf(stderr, "\nUsage:  snoop\n");
 	(void) fprintf(stderr,
@@ -793,8 +792,8 @@
 	volatile sigset_t s_mask;
 	volatile int ret = -1;
 
-	sigemptyset((sigset_t *)&s_mask);
-	sigaddset((sigset_t *)&s_mask, SIGALRM);
+	(void) sigemptyset((sigset_t *)&s_mask);
+	(void) sigaddset((sigset_t *)&s_mask, SIGALRM);
 	if (s_sec < 0)
 		return (-1);
 
@@ -812,7 +811,7 @@
 			snoop_hp = snoop_tp = (struct snoop_handler *)sh;
 
 			snoop_nalarm = sh->s_time;
-			alarm(sh->s_time - now);
+			(void) alarm(sh->s_time - now);
 		} else {
 			snoop_tp->s_next = (struct snoop_handler *)sh;
 			snoop_tp = (struct snoop_handler *)sh;
@@ -905,7 +904,7 @@
  * out the signal blocking.
  */
 /*ARGSUSED*/
-void
+static void
 snoop_sigrecover(int sig, siginfo_t *info, void *p)
 {
 	volatile time_t now;
@@ -934,7 +933,7 @@
 		/* Setup next alarm */
 		if (nalarm) {
 			snoop_nalarm = nalarm;
-			alarm(nalarm - now);
+			(void) alarm(nalarm - now);
 		} else {
 			snoop_nalarm = 0;
 		}
@@ -979,7 +978,7 @@
 			return;
 		}
 		if (snoop_nrecover >= SNOOP_MAXRECOVER) {
-			fprintf(stderr,
+			(void) fprintf(stderr,
 				"snoop: WARNING: skipping from packet %d\n",
 				count);
 			snoop_nrecover = 0;
@@ -988,13 +987,13 @@
 			return;
 		}
 	} else if (snoop_nrecover >= SNOOP_MAXRECOVER) {
-		fprintf(stderr,
+		(void) fprintf(stderr,
 			"snoop: ERROR: cannot recover from packet %d\n", count);
 		exit(1);
 	}
 
 #ifdef DEBUG
-	fprintf(stderr, "snoop_sigrecover(%d, %p, %p)\n", sig, info, p);
+	(void) fprintf(stderr, "snoop_sigrecover(%d, %p, %p)\n", sig, info, p);
 #endif /* DEBUG */
 
 	/*
@@ -1006,7 +1005,8 @@
 		return;
 	} else if (sig != -1 && sig != SIGALRM) {
 		/* Inform user that snoop has taken a fault */
-		fprintf(stderr, "WARNING: received signal %d from packet %d\n",
+		(void) fprintf(stderr,
+		    "WARNING: received signal %d from packet %d\n",
 				sig, count);
 	}
 
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.h b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.h
index c78f3c9..fe9bf31 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.h
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.h
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -35,6 +34,7 @@
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/bufmod.h>
 #include <net/if.h>
 #include <netinet/in.h>
 #include <netinet/if_ether.h>
@@ -127,6 +127,7 @@
 extern char *get_sum_line(void);
 extern char *get_detail_line(int, int);
 extern struct timeval prev_time;
+extern void process_pkt(struct sb_hdr *, char *, int, int);
 extern char *getflag(int, int, char *, char *);
 extern void show_header(char *, char *, int);
 extern void xdr_init(char *, int);
@@ -173,6 +174,7 @@
 extern int pf_compile(char *, int);
 extern void compile(char *, int);
 extern void load_names(char *);
+extern void cap_write(struct sb_hdr *, char *, int, int);
 extern void cap_open_read(char *);
 extern void cap_open_write(char *);
 extern void cap_read(int, int, int, void (*)(), int);
@@ -187,9 +189,9 @@
 extern void show_line(char *);
 extern char *getxdr_time(void);
 extern char *showxdr_time(char *);
-extern char *addrtoname(int, void *);
+extern char *addrtoname(int, const void *);
 extern char *show_string(const char *, int, int);
-extern void pr_err(char *, ...);
+extern void pr_err(const char *, ...);
 extern void check_retransmit(char *, ulong_t);
 extern char *nameof_prog(int);
 extern char *getproto(int);
@@ -219,14 +221,40 @@
 extern void interpret_ldap(int, char *, int, int, int);
 extern void interpret_icmp(int, struct icmp *, int, int);
 extern void interpret_icmpv6(int, icmp6_t *, int, int);
-extern int interpret_ip(int, struct ip *, int);
-extern int interpret_ipv6(int, ip6_t *, int);
+extern int interpret_ip(int, const struct ip *, int);
+extern int interpret_ipv6(int, const ip6_t *, int);
 extern int interpret_ppp(int, uchar_t *, int);
 extern int interpret_pppoe(int, poep_t *, int);
+struct tcphdr;
+extern int interpret_tcp(int, struct tcphdr *, int, int);
+struct udphdr;
+extern int interpret_udp(int, struct udphdr *, int, int);
+extern int interpret_esp(int, uint8_t *, int, int);
+extern int interpret_ah(int, uint8_t *, int, int);
+struct sctp_hdr;
+extern void interpret_sctp(int, struct sctp_hdr *, int, int);
+extern void interpret_mip_cntrlmsg(int, uchar_t *, int);
+struct dhcp;
+extern int interpret_dhcp(int, struct dhcp *, int);
+struct tftphdr;
+extern int interpret_tftp(int, struct tftphdr *, int);
+extern int interpret_http(int, char *, int);
+struct ntpdata;
+extern int interpret_ntp(int, struct ntpdata *, int);
+extern void interpret_netbios_ns(int, uchar_t *, int);
+extern void interpret_netbios_datagram(int, uchar_t *, int);
+extern void interpret_netbios_ses(int, uchar_t *, int);
+extern void interpret_slp(int, char *, int);
+struct rip;
+extern int interpret_rip(int, struct rip *, int);
+struct rip6;
+extern int interpret_rip6(int, struct rip6 *, int);
+extern int interpret_socks_call(int, char *, int);
+extern int interpret_socks_reply(int, char *, int);
 extern void init_ldap(void);
 extern boolean_t arp_for_ether(char *, struct ether_addr *);
 extern char *ether_ouiname(uint32_t);
-char *tohex(char *p, int len);
+extern char *tohex(char *p, int len);
 extern char *printether(struct ether_addr *);
 extern char *print_ethertype(int);
 
@@ -257,6 +285,17 @@
 
 extern char *dlc_header;
 
+extern char *src_name, *dst_name;
+
+extern char *prot_prefix;
+extern char *prot_nest_prefix;
+extern char *prot_title;
+
+/* Keep track of how many nested IP headers we have. */
+extern unsigned int encap_levels, total_encap_levels;
+
+extern int quitting;
+
 /*
  * Global error recovery routine: used to reset snoop variables after
  * catastrophic failure.
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_capture.c b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_capture.c
index 2270229..e3e7bd7 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_capture.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_capture.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -57,27 +56,37 @@
 
 #include "snoop.h"
 
-void scan();
+/*
+ * Old header format.
+ * Actually two concatenated structs:  nit_bufhdr + nit_head
+ */
+struct ohdr {
+	/* nit_bufhdr */
+	int	o_msglen;
+	int	o_totlen;
+	/* nit_head */
+	struct timeval o_time;
+	int	o_drops;
+	int	o_len;
+};
+
+static void scan(char *, int, int, int, int, void (*)(), int, int, int);
 void convert_to_network();
 void convert_from_network();
-void convert_old();
-extern int quitting;
+static void convert_old(struct ohdr *);
 extern sigjmp_buf jmp_env, ojmp_env;
-int netfd;
-union DL_primitives netdl;			/* info_ack for interface */
-char *bufp;	/* pointer to read buffer */
+static int netfd;
+static union DL_primitives netdl;		/* info_ack for interface */
+static char *bufp;	/* pointer to read buffer */
 
-extern unsigned int encap_levels;
-
-static int strioctl(int, int, int, int, char *);
+static int strioctl(int, int, int, int, void *);
 
 /*
  * Convert a device id to a ppa value
  * e.g. "le0" -> 0
  */
-int
-device_ppa(device)
-	char *device;
+static int
+device_ppa(char *device)
 {
 	char *p;
 	char *tp;
@@ -97,9 +106,8 @@
  * Level 1 devices: "le0" -> "/dev/le0".
  * Level 2 devices: "le0" -> "/dev/le".
  */
-char *
-device_path(device)
-	char *device;
+static char *
+device_path(char *device)
 {
 	static char buff[IF_NAMESIZE + 1];
 	struct stat st;
@@ -223,8 +231,9 @@
 
 	/* allow limited functionality even is interface isn't known */
 	if (interface->mac_type == -1) {
-		fprintf(stderr, "snoop: WARNING: Mac Type = %x not supported\n",
-			netdl.info_ack.dl_mac_type);
+		fprintf(stderr,
+		    "snoop: WARNING: Mac Type = %lx not supported\n",
+		    netdl.info_ack.dl_mac_type);
 	}
 
 	/* for backward compatibility, allow known interface mtu_sizes */
@@ -244,6 +253,7 @@
  * push the streams buffer module and packet filter module, set various buffer
  * parameters.
  */
+/* ARGSUSED */
 void
 initdevice(device, snaplen, chunksize, timeout, fp, ppa)
 	char *device;
@@ -252,7 +262,6 @@
 	struct Pf_ext_packetfilt *fp;
 	int ppa;
 {
-	union DL_primitives dl;
 	extern int Pflg;
 
 	/*
@@ -281,7 +290,7 @@
 	dlpromiscon(netfd, DL_PROMISC_SAP);
 
 	if (ioctl(netfd, DLIOCRAW, 0) < 0) {
-		close(netfd);
+		(void) close(netfd);
 		pr_err("ioctl: DLIOCRAW: %s: %m", device_path(device));
 	}
 
@@ -290,38 +299,38 @@
 		 * push and configure the packet filtering module
 		 */
 		if (ioctl(netfd, I_PUSH, "pfmod") < 0) {
-			close(netfd);
+			(void) close(netfd);
 			pr_err("ioctl: I_PUSH pfmod: %s: %m",
 			    device_path(device));
 		}
 
 		if (strioctl(netfd, PFIOCSETF, -1, sizeof (*fp),
 		    (char *)fp) < 0) {
-			close(netfd);
+			(void) close(netfd);
 			pr_err("PFIOCSETF: %s: %m", device_path(device));
 		}
 	}
 
 	if (ioctl(netfd, I_PUSH, "bufmod") < 0) {
-		close(netfd);
+		(void) close(netfd);
 		pr_err("push bufmod: %s: %m", device_path(device));
 	}
 
 	if (strioctl(netfd, SBIOCSTIME, -1, sizeof (struct timeval),
 	    (char *)timeout) < 0) {
-		close(netfd);
+		(void) close(netfd);
 		pr_err("SBIOCSTIME: %s: %m", device_path(device));
 	}
 
 	if (strioctl(netfd, SBIOCSCHUNK, -1, sizeof (uint_t),
 	    (char *)&chunksize) < 0) {
-		close(netfd);
+		(void) close(netfd);
 		pr_err("SBIOCGCHUNK: %s: %m", device_path(device));
 	}
 
 	if (strioctl(netfd, SBIOCSSNAP, -1, sizeof (uint_t),
 	    (char *)&snaplen) < 0) {
-		close(netfd);
+		(void) close(netfd);
 		pr_err("SBIOCSSNAP: %s: %m", device_path(device));
 	}
 
@@ -330,7 +339,7 @@
 	 * accumulated before the device reached its final configuration.
 	 */
 	if (ioctl(netfd, I_FLUSH, FLUSHR) < 0) {
-		close(netfd);
+		(void) close(netfd);
 		pr_err("I_FLUSH: %s: %m", device_path(device));
 	}
 }
@@ -383,7 +392,7 @@
 	}
 
 	free(bufp);
-	close(netfd);
+	(void) close(netfd);
 
 	if (!quitting) {
 		if (r < 0)
@@ -422,13 +431,9 @@
 }
 #endif /* DEBUG */
 
-void
-scan(buf, len, filter, cap, old, proc, first, last, flags)
-	char *buf;
-	int len, filter, cap, old;
-	void (*proc)();
-	int first, last;
-	int flags;
+static void
+scan(char *buf, int len, int filter, int cap, int old, void (*proc)(),
+    int first, int last, int flags)
 {
 	volatile char *bp, *bufstop;
 	volatile struct sb_hdr *hdrp;
@@ -481,7 +486,7 @@
 			 * capture file, convert the header.
 			 */
 			if (old) {
-				convert_old(hdrp);
+				convert_old((struct ohdr *)hdrp);
 			}
 
 			nhdrp = &nhdr;
@@ -685,34 +690,33 @@
  * |	 word 0	   |	 word 1	   |	 word 2	   |	 word 3
  *
  */
-const char *snoop_id = "snoop\0\0\0";
-const int snoop_idlen = 8;
-const int snoop_version = 2;
+static const char *snoop_id = "snoop\0\0\0";
+static const int snoop_idlen = 8;
+static const int snoop_version = 2;
 
 void
 cap_open_write(name)
 	char *name;
 {
 	int vers;
-	int rc;
 
 	capfile_out = open(name, O_CREAT | O_TRUNC | O_RDWR, 0666);
 	if (capfile_out < 0)
 		pr_err("%s: %m", name);
 
 	vers = htonl(snoop_version);
-	if ((rc = nwrite(capfile_out, snoop_id, snoop_idlen)) == -1)
+	if (nwrite(capfile_out, snoop_id, snoop_idlen) == -1)
 		cap_write_error("snoop_id");
 
-	if ((rc = nwrite(capfile_out, &vers, sizeof (int))) == -1)
+	if (nwrite(capfile_out, &vers, sizeof (int)) == -1)
 		cap_write_error("version");
 }
 
 
 void
-cap_close()
+cap_close(void)
 {
-	close(capfile_out);
+	(void) close(capfile_out);
 }
 
 static char *cap_buffp = NULL;
@@ -737,7 +741,7 @@
 	cap_len = st.st_size;
 
 	cap_buffp = mmap(0, cap_len, PROT_READ, MAP_PRIVATE, capfile_in, 0);
-	close(capfile_in);
+	(void) close(capfile_in);
 	if ((int)cap_buffp == -1)
 		pr_err("couldn't mmap %s: %m", name);
 
@@ -810,9 +814,10 @@
 
 	scan(cap_buffp, cap_len, filter, 1, !cap_new, proc, first, last, flags);
 
-	munmap(cap_buffp, cap_len);
+	(void) munmap(cap_buffp, cap_len);
 }
 
+/* ARGSUSED */
 void
 cap_write(hdrp, pktp, num, flags)
 	struct sb_hdr *hdrp;
@@ -823,7 +828,6 @@
 	static int first = 1;
 	struct sb_hdr nhdr;
 	extern boolean_t qflg;
-	int rc;
 
 	if (hdrp == NULL)
 		return;
@@ -831,7 +835,7 @@
 	if (first) {
 		first = 0;
 		mac = htonl(interface->mac_type);
-		if ((rc = nwrite(capfile_out, &mac, sizeof (int))) == -1)
+		if (nwrite(capfile_out, &mac, sizeof (int)) == -1)
 			cap_write_error("mac_type");
 	}
 
@@ -847,10 +851,10 @@
 	nhdr.sbh_timestamp.tv_sec = htonl(hdrp->sbh_timestamp.tv_sec);
 	nhdr.sbh_timestamp.tv_usec = htonl(hdrp->sbh_timestamp.tv_usec);
 
-	if ((rc = nwrite(capfile_out, &nhdr, sizeof (nhdr))) == -1)
+	if (nwrite(capfile_out, &nhdr, sizeof (nhdr)) == -1)
 		cap_write_error("packet header");
 
-	if ((rc = nwrite(capfile_out, pktp, pktlen)) == -1)
+	if (nwrite(capfile_out, pktp, pktlen) == -1)
 		cap_write_error("packet");
 
 	if (! qflg)
@@ -858,26 +862,11 @@
 }
 
 /*
- * Old header format.
- * Actually two concatenated structs:  nit_bufhdr + nit_head
- */
-struct ohdr {
-	/* nit_bufhdr */
-	int	o_msglen;
-	int	o_totlen;
-	/* nit_head */
-	struct timeval o_time;
-	int	o_drops;
-	int	o_len;
-};
-
-/*
  * Convert a packet header from
  * old to new format.
  */
-void
-convert_old(ohdrp)
-	struct ohdr *ohdrp;
+static void
+convert_old(struct ohdr *ohdrp)
 {
 	struct sb_hdr nhdr;
 
@@ -891,7 +880,7 @@
 }
 
 static int
-strioctl(int fd, int cmd, int timout, int len, char *dp)
+strioctl(int fd, int cmd, int timout, int len, void *dp)
 {
 	struct	strioctl	sioc;
 	int	rc;
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_dhcp.c b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_dhcp.c
index 3ca7d44..f188a24 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_dhcp.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_dhcp.c
@@ -135,7 +135,7 @@
 #define	OPTIONS_ARRAY_SIZE	78
 
 int
-interpret_dhcp(int flags, PKT *dp, int len)
+interpret_dhcp(int flags, struct dhcp *dp, int len)
 {
 	if (flags & F_SUM) {
 		if ((memcmp(dp->cookie, bootmagic, sizeof (bootmagic)) == 0) &&
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ip.c b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ip.c
index 8421ecc..be6440a 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ip.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ip.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -28,7 +27,6 @@
 
 
 #include <stdio.h>
-#include <ctype.h>
 #include <string.h>
 #include <fcntl.h>
 #include <string.h>
@@ -37,7 +35,6 @@
 
 #include <sys/stropts.h>
 #include <sys/socket.h>
-#include <sys/sockio.h>
 #include <net/if.h>
 #include <netinet/in_systm.h>
 #include <netinet/in.h>
@@ -46,10 +43,14 @@
 #include <netinet/ip_icmp.h>
 #include <netinet/icmp6.h>
 #include <netinet/if_ether.h>
+#include <inet/ip.h>
 #include <inet/ip6.h>
-#include <inet/ipsecah.h>
 #include <arpa/inet.h>
 #include <netdb.h>
+#include <tsol/label.h>
+#include <sys/tsol/tndb.h>
+#include <sys/tsol/label_macro.h>
+
 #include "snoop.h"
 
 
@@ -67,34 +68,29 @@
 #define	SNOOP_ESP	0x20U
 #define	SNOOP_IPV6	0x40U
 
-extern char *dlc_header;
-
-static void prt_routing_hdr();
-static void prt_fragment_hdr();
-static void prt_hbh_options();
-static void prt_dest_options();
-static void print_route();
-static void print_ipoptions();
-char *getproto();
+static void prt_routing_hdr(int, const struct ip6_rthdr *);
+static void prt_fragment_hdr(int, const struct ip6_frag *);
+static void prt_hbh_options(int, const struct ip6_hbh *);
+static void prt_dest_options(int, const struct ip6_dest *);
+static void print_route(const uchar_t *);
+static void print_ipoptions(const uchar_t *, int);
+static void print_ripso(const uchar_t *);
+static void print_cipso(const uchar_t *);
 
 /* Keep track of how many nested IP headers we have. */
 unsigned int encap_levels;
 unsigned int total_encap_levels = 1;
 
 int
-interpret_ip(flags, ip, fraglen)
-	int flags;
-	struct ip *ip;
-	int fraglen;
+interpret_ip(int flags, const struct ip *ip, int fraglen)
 {
-	char *data;
+	uchar_t *data;
 	char buff[24];
 	boolean_t isfrag = B_FALSE;
 	boolean_t morefrag;
 	uint16_t fragoffset;
 	int hdrlen;
 	uint16_t iplen, uitmp;
-	extern char *src_name, *dst_name;
 
 	if (ip->ip_v == IPV6_VERSION) {
 		iplen = interpret_ipv6(flags, (ip6_t *)ip, fraglen);
@@ -108,7 +104,7 @@
 	total_encap_levels++;
 
 	hdrlen = ip->ip_hl * 4;
-	data = ((char *)ip) + hdrlen;
+	data = ((uchar_t *)ip) + hdrlen;
 	iplen = ntohs(ip->ip_len) - hdrlen;
 	fraglen -= hdrlen;
 	if (fraglen > iplen)
@@ -163,80 +159,74 @@
 	if (flags & F_DTAIL) {
 		show_header("IP:   ", "IP Header", iplen);
 		show_space();
-		(void) snprintf(get_line((char *)ip - dlc_header, 1),
-		    get_line_remain(), "Version = %d", ip->ip_v);
-		(void) snprintf(get_line((char *)ip - dlc_header, 1),
-		    get_line_remain(), "Header length = %d bytes", hdrlen);
-		(void) snprintf(get_line((char *)&ip->ip_tos - dlc_header, 1),
-		    get_line_remain(), "Type of service = 0x%02x", ip->ip_tos);
-		(void) snprintf(get_line((char *)&ip->ip_tos - dlc_header, 1),
-		    get_line_remain(), "      xxx. .... = %d (precedence)",
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Version = %d", ip->ip_v);
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Header length = %d bytes", hdrlen);
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Type of service = 0x%02x", ip->ip_tos);
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "      xxx. .... = %d (precedence)",
 		    ip->ip_tos >> 5);
-		(void) snprintf(get_line((char *)&ip->ip_tos - dlc_header, 1),
-		    get_line_remain(), "      %s",
-		    getflag(ip->ip_tos, IPTOS_LOWDELAY,
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "      %s", getflag(ip->ip_tos, IPTOS_LOWDELAY,
 		    "low delay", "normal delay"));
-		(void) snprintf(get_line((char *)&ip->ip_tos - dlc_header, 1),
-		    get_line_remain(), "      %s",
+		(void) snprintf(get_line(0, 0), get_line_remain(), "      %s",
 		    getflag(ip->ip_tos, IPTOS_THROUGHPUT,
 		    "high throughput", "normal throughput"));
-		(void) snprintf(get_line((char *)&ip->ip_tos - dlc_header, 1),
-		    get_line_remain(), "      %s",
+		(void) snprintf(get_line(0, 0), get_line_remain(), "      %s",
 		    getflag(ip->ip_tos, IPTOS_RELIABILITY,
 		    "high reliability", "normal reliability"));
-		(void) snprintf(get_line((char *)&ip->ip_tos - dlc_header, 1),
-		    get_line_remain(), "      %s",
+		(void) snprintf(get_line(0, 0), get_line_remain(), "      %s",
 		    getflag(ip->ip_tos, IPTOS_ECT,
 		    "ECN capable transport", "not ECN capable transport"));
-		(void) snprintf(get_line((char *)&ip->ip_tos - dlc_header, 1),
-		    get_line_remain(), "      %s",
+		(void) snprintf(get_line(0, 0), get_line_remain(), "      %s",
 		    getflag(ip->ip_tos, IPTOS_CE,
 		    "ECN congestion experienced",
 		    "no ECN congestion experienced"));
 		/* warning: ip_len is signed in netinet/ip.h */
 		uitmp = ntohs(ip->ip_len);
-		(void) snprintf(get_line((char *)&ip->ip_len - dlc_header, 2),
-		    get_line_remain(), "Total length = %u bytes%s", uitmp,
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Total length = %u bytes%s", uitmp,
 		    iplen > fraglen ? " -- truncated" : "");
-		(void) snprintf(get_line((char *)&ip->ip_id - dlc_header, 2),
-		    get_line_remain(), "Identification = %d", ntohs(ip->ip_id));
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Identification = %d", ntohs(ip->ip_id));
 		/* warning: ip_off is signed in netinet/ip.h */
 		uitmp = ntohs(ip->ip_off);
-		(void) snprintf(get_line((char *)&ip->ip_off - dlc_header, 1),
-		    get_line_remain(), "Flags = 0x%x", uitmp >> 12);
-		(void) snprintf(get_line((char *)&ip->ip_off - dlc_header, 1),
-		    get_line_remain(), "      %s",
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Flags = 0x%x", uitmp >> 12);
+		(void) snprintf(get_line(0, 0), get_line_remain(), "      %s",
 		    getflag(uitmp >> 8, IP_DF >> 8,
 		    "do not fragment", "may fragment"));
-		(void) snprintf(get_line((char *)&ip->ip_off - dlc_header, 1),
-		    get_line_remain(), "      %s",
+		(void) snprintf(get_line(0, 0), get_line_remain(), "      %s",
 		    getflag(uitmp >> 8, IP_MF >> 8,
 		    "more fragments", "last fragment"));
-		(void) snprintf(get_line((char *)&ip->ip_off - dlc_header, 2),
-		    get_line_remain(), "Fragment offset = %u bytes",
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Fragment offset = %u bytes",
 		    fragoffset);
-		(void) snprintf(get_line((char *)&ip->ip_ttl - dlc_header, 1),
-		    get_line_remain(), "Time to live = %d seconds/hops",
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Time to live = %d seconds/hops",
 		    ip->ip_ttl);
-		(void) snprintf(get_line((char *)&ip->ip_p - dlc_header, 1),
-		    get_line_remain(), "Protocol = %d (%s)", ip->ip_p,
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Protocol = %d (%s)", ip->ip_p,
 		    getproto(ip->ip_p));
 		/*
 		 * XXX need to compute checksum and print whether it's correct
 		 */
-		(void) snprintf(get_line((char *)&ip->ip_sum - dlc_header, 1),
-		    get_line_remain(), "Header checksum = %04x",
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Header checksum = %04x",
 		    ntohs(ip->ip_sum));
-		(void) snprintf(get_line((char *)&ip->ip_src - dlc_header, 1),
-		    get_line_remain(), "Source address = %s, %s",
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Source address = %s, %s",
 		    inet_ntoa(ip->ip_src), addrtoname(AF_INET, &ip->ip_src));
-		(void) snprintf(get_line((char *)&ip->ip_dst - dlc_header, 1),
-		    get_line_remain(), "Destination address = %s, %s",
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Destination address = %s, %s",
 		    inet_ntoa(ip->ip_dst), addrtoname(AF_INET, &ip->ip_dst));
 
 		/* Print IP options - if any */
 
-		print_ipoptions(ip + 1, hdrlen - sizeof (struct ip));
+		print_ipoptions((const uchar_t *)(ip + 1),
+		    hdrlen - sizeof (struct ip));
 		show_space();
 	}
 
@@ -248,8 +238,7 @@
 	 * of a fragmented packet.
 	 */
 	if (flags & F_DTAIL && fragoffset != 0) {
-		(void) snprintf(get_detail_line(data - dlc_header, iplen),
-		    MAXLINE,
+		(void) snprintf(get_detail_line(0, 0), MAXLINE,
 		    "%s:  [%d byte(s) of data, continuation of IP ident=%d]",
 		    getproto(ip->ip_p),
 		    iplen,
@@ -262,12 +251,14 @@
 			case IPPROTO_IP:
 				break;
 			case IPPROTO_ENCAP:
-				(void) interpret_ip(flags, (struct ip *)data,
-				    fraglen);
+				(void) interpret_ip(flags,
+				    /* LINTED: alignment */
+				    (const struct ip *)data, fraglen);
 				break;
 			case IPPROTO_ICMP:
-				interpret_icmp(flags, (struct icmp *)data,
-				    iplen, fraglen);
+				(void) interpret_icmp(flags,
+				    /* LINTED: alignment */
+				    (struct icmp *)data, iplen, fraglen);
 				break;
 			case IPPROTO_IGMP:
 				interpret_igmp(flags, data, iplen, fraglen);
@@ -275,14 +266,17 @@
 			case IPPROTO_GGP:
 				break;
 			case IPPROTO_TCP:
-				interpret_tcp(flags, data, iplen, fraglen);
+				(void) interpret_tcp(flags,
+				    (struct tcphdr *)data, iplen, fraglen);
 				break;
 
 			case IPPROTO_ESP:
-				interpret_esp(flags, data, iplen, fraglen);
+				(void) interpret_esp(flags, data, iplen,
+				    fraglen);
 				break;
 			case IPPROTO_AH:
-				interpret_ah(flags, data, iplen, fraglen);
+				(void) interpret_ah(flags, data, iplen,
+				    fraglen);
 				break;
 
 			case IPPROTO_OSPF:
@@ -293,7 +287,8 @@
 			case IPPROTO_PUP:
 				break;
 			case IPPROTO_UDP:
-				interpret_udp(flags, data, iplen, fraglen);
+				(void) interpret_udp(flags,
+				    (struct udphdr *)data, iplen, fraglen);
 				break;
 
 			case IPPROTO_IDP:
@@ -302,11 +297,13 @@
 			case IPPROTO_RAW:
 				break;
 			case IPPROTO_IPV6:	/* IPV6 encap */
+				/* LINTED: alignment */
 				(void) interpret_ipv6(flags, (ip6_t *)data,
 				    iplen);
 				break;
 			case IPPROTO_SCTP:
-				interpret_sctp(flags, data, iplen, fraglen);
+				(void) interpret_sctp(flags,
+				    (struct sctp_hdr *)data, iplen, fraglen);
 				break;
 			}
 		}
@@ -317,14 +314,10 @@
 }
 
 int
-interpret_ipv6(flags, ip6h, fraglen)
-	int flags;
-	ip6_t *ip6h;
-	int fraglen;
+interpret_ipv6(int flags, const ip6_t *ip6h, int fraglen)
 {
 	uint8_t *data;
 	int hdrlen, iplen;
-	extern char *src_name, *dst_name;
 	int version, flow, class;
 	uchar_t proto;
 	boolean_t isfrag = B_FALSE;
@@ -365,8 +358,8 @@
 	 * will not affect the detailed printing of the packet.
 	 */
 	if (flags & F_SUM) {
-		(void) sprintf(get_sum_line(), "IPv6  S=%s D=%s LEN=%d "
-		    "HOPS=%d CLASS=0x%x FLOW=0x%x",
+		(void) snprintf(get_sum_line(), MAXLINE,
+		    "IPv6  S=%s D=%s LEN=%d HOPS=%d CLASS=0x%x FLOW=0x%x",
 		    src_name, dst_name, iplen, ip6h->ip6_hops, class, flow);
 	} else if (flags & F_DTAIL) {
 
@@ -392,22 +385,22 @@
 		show_header("IPv6:   ", "IPv6 Header", iplen);
 		show_space();
 
-		(void) sprintf(get_line((char *)ip6h - dlc_header, 1),
+		(void) snprintf(get_line(0, 0), get_line_remain(),
 		    "Version = %d", version);
-		(void) sprintf(get_line((char *)ip6h - dlc_header, 1),
+		(void) snprintf(get_line(0, 0), get_line_remain(),
 		    "Traffic Class = %d", class);
-		(void) sprintf(get_line((char *)&ip6h->ip6_vcf - dlc_header, 4),
+		(void) snprintf(get_line(0, 0), get_line_remain(),
 		    "Flow label = 0x%x", flow);
-		(void) sprintf(get_line((char *)&ip6h->ip6_plen -
-		    dlc_header, 2), "Payload length = %d", iplen);
-		(void) sprintf(get_line((char *)&ip6h->ip6_nxt -
-		    dlc_header, 1), "Next Header = %d (%s)", proto,
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Payload length = %d", iplen);
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Next Header = %d (%s)", proto,
 		    getproto(proto));
-		(void) sprintf(get_line((char *)&ip6h->ip6_hops -
-		    dlc_header, 1), "Hop Limit = %d", ip6h->ip6_hops);
-		(void) sprintf(get_line((char *)&ip6h->ip6_src - dlc_header, 1),
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Hop Limit = %d", ip6h->ip6_hops);
+		(void) snprintf(get_line(0, 0), get_line_remain(),
 		    "Source address = %s%s", src_addrstr, print_srcname);
-		(void) sprintf(get_line((char *)&ip6h->ip6_dst - dlc_header, 1),
+		(void) snprintf(get_line(0, 0), get_line_remain(),
 		    "Destination address = %s%s", dst_addrstr, print_dstname);
 
 		show_space();
@@ -440,10 +433,13 @@
 		case IPPROTO_IP:
 			break;
 		case IPPROTO_ENCAP:
-			(void) interpret_ip(flags, (struct ip *)data, fraglen);
+			/* LINTED: alignment */
+			(void) interpret_ip(flags, (const struct ip *)data,
+			    fraglen);
 			break;
 		case IPPROTO_ICMPV6:
-			interpret_icmpv6(flags, (icmp6_t *)data, iplen,
+			/* LINTED: alignment */
+			(void) interpret_icmpv6(flags, (icmp6_t *)data, iplen,
 			    fraglen);
 			break;
 		case IPPROTO_IGMP:
@@ -452,19 +448,21 @@
 		case IPPROTO_GGP:
 			break;
 		case IPPROTO_TCP:
-			interpret_tcp(flags, data, iplen, fraglen);
+			(void) interpret_tcp(flags, (struct tcphdr *)data,
+			    iplen, fraglen);
 			break;
 		case IPPROTO_ESP:
-			interpret_esp(flags, data, iplen, fraglen);
+			(void) interpret_esp(flags, data, iplen, fraglen);
 			break;
 		case IPPROTO_AH:
-			interpret_ah(flags, data, iplen, fraglen);
+			(void) interpret_ah(flags, data, iplen, fraglen);
 			break;
 		case IPPROTO_EGP:
 		case IPPROTO_PUP:
 			break;
 		case IPPROTO_UDP:
-			interpret_udp(flags, data, iplen, fraglen);
+			(void) interpret_udp(flags, (struct udphdr *)data,
+			    iplen, fraglen);
 			break;
 		case IPPROTO_IDP:
 		case IPPROTO_HELLO:
@@ -472,10 +470,13 @@
 		case IPPROTO_RAW:
 			break;
 		case IPPROTO_IPV6:
-			(void) interpret_ipv6(flags, (ip6_t *)data, iplen);
+			/* LINTED: alignment */
+			(void) interpret_ipv6(flags, (const ip6_t *)data,
+			    iplen);
 			break;
 		case IPPROTO_SCTP:
-			interpret_sctp(flags, data, iplen, fraglen);
+			(void) interpret_sctp(flags, (struct sctp_hdr *)data,
+			    iplen, fraglen);
 			break;
 		case IPPROTO_OSPF:
 			interpret_ospf6(flags, data, iplen, fraglen);
@@ -518,7 +519,6 @@
 		 * header.
 		 */
 		if (*fraglen < 2) {
-			proto = IPPROTO_NONE;
 			return (extmask);
 		}
 
@@ -527,7 +527,6 @@
 			ipv6ext_hbh = (struct ip6_hbh *)data_ptr;
 			exthdrlen = 8 + ipv6ext_hbh->ip6h_len * 8;
 			if (*fraglen <= exthdrlen) {
-				proto = IPPROTO_NONE;
 				return (extmask);
 			}
 			prt_hbh_options(flags, ipv6ext_hbh);
@@ -538,7 +537,6 @@
 			ipv6ext_dest = (struct ip6_dest *)data_ptr;
 			exthdrlen = 8 + ipv6ext_dest->ip6d_len * 8;
 			if (*fraglen <= exthdrlen) {
-				proto = IPPROTO_NONE;
 				return (extmask);
 			}
 			prt_dest_options(flags, ipv6ext_dest);
@@ -549,7 +547,6 @@
 			ipv6ext_rthdr = (struct ip6_rthdr *)data_ptr;
 			exthdrlen = 8 + ipv6ext_rthdr->ip6r_len * 8;
 			if (*fraglen <= exthdrlen) {
-				proto = IPPROTO_NONE;
 				return (extmask);
 			}
 			prt_routing_hdr(flags, ipv6ext_rthdr);
@@ -557,10 +554,10 @@
 			proto = ipv6ext_rthdr->ip6r_nxt;
 			break;
 		case IPPROTO_FRAGMENT:
+			/* LINTED: alignment */
 			ipv6ext_frag = (struct ip6_frag *)data_ptr;
 			exthdrlen = sizeof (struct ip6_frag);
 			if (*fraglen <= exthdrlen) {
-				proto = IPPROTO_NONE;
 				return (extmask);
 			}
 			prt_fragment_hdr(flags, ipv6ext_frag);
@@ -593,66 +590,81 @@
 }
 
 static void
-print_ipoptions(opt, optlen)
-	uchar_t *opt;
-	int optlen;
+print_ipoptions(const uchar_t *opt, int optlen)
 {
 	int len;
+	int remain;
 	char *line;
+	const char *truncstr;
 
 	if (optlen <= 0) {
-		(void) sprintf(get_line((char *)&opt - dlc_header, 1),
+		(void) snprintf(get_line(0, 0), get_line_remain(),
 		    "No options");
 		return;
 	}
 
-	(void) sprintf(get_line((char *)&opt - dlc_header, 1),
+	(void) snprintf(get_line(0, 0), get_line_remain(),
 	    "Options: (%d bytes)", optlen);
 
 	while (optlen > 0) {
-		line = get_line((char *)&opt - dlc_header, 1);
+		line = get_line(0, 0);
+		remain = get_line_remain();
 		len = opt[1];
+		truncstr = len > optlen ? "?" : "";
 		switch (opt[0]) {
 		case IPOPT_EOL:
-			(void) strcpy(line, "  - End of option list");
+			(void) strlcpy(line, "  - End of option list", remain);
 			return;
 		case IPOPT_NOP:
-			(void) strcpy(line, "  - No op");
+			(void) strlcpy(line, "  - No op", remain);
 			len = 1;
 			break;
 		case IPOPT_RR:
-			(void) sprintf(line, "  - Record route (%d bytes)",
-			    len);
+			(void) snprintf(line, remain,
+			    "  - Record route (%d bytes%s)", len, truncstr);
 			print_route(opt);
 			break;
 		case IPOPT_TS:
-			(void) sprintf(line, "  - Time stamp (%d bytes)", len);
+			(void) snprintf(line, remain,
+			    "  - Time stamp (%d bytes%s)", len, truncstr);
 			break;
 		case IPOPT_SECURITY:
-			(void) sprintf(line, "  - Security (%d bytes)", len);
+			(void) snprintf(line, remain, "  - RIPSO (%d bytes%s)",
+			    len, truncstr);
+			print_ripso(opt);
+			break;
+		case IPOPT_COMSEC:
+			(void) snprintf(line, remain, "  - CIPSO (%d bytes%s)",
+			    len, truncstr);
+			print_cipso(opt);
 			break;
 		case IPOPT_LSRR:
-			(void) sprintf(line,
-			    "  - Loose source route (%d bytes)", len);
+			(void) snprintf(line, remain,
+			    "  - Loose source route (%d bytes%s)", len,
+			    truncstr);
 			print_route(opt);
 			break;
 		case IPOPT_SATID:
-			(void) sprintf(line, "  - SATNET Stream id (%d bytes)",
-			    len);
+			(void) snprintf(line, remain,
+			    "  - SATNET Stream id (%d bytes%s)",
+			    len, truncstr);
 			break;
 		case IPOPT_SSRR:
-			(void) sprintf(line,
-			    "  - Strict source route, (%d bytes)", len);
+			(void) snprintf(line, remain,
+			    "  - Strict source route, (%d bytes%s)", len,
+			    truncstr);
 			print_route(opt);
 			break;
 		default:
-			sprintf(line, "  - Option %d (unknown - %d bytes) %s",
-			    opt[0], len, tohex((char *)&opt[2], len - 2));
+			(void) snprintf(line, remain,
+			    "  - Option %d (unknown - %d bytes%s) %s",
+			    opt[0], len, truncstr,
+			    tohex((char *)&opt[2], len - 2));
 			break;
 		}
 		if (len <= 0) {
-			(void) sprintf(line, "  - Incomplete option len %d",
-				len);
+			(void) snprintf(line, remain,
+			    "  - Incomplete option len %d", len);
 			break;
 		}
 		opt += len;
@@ -661,17 +673,16 @@
 }
 
 static void
-print_route(opt)
-	uchar_t *opt;
+print_route(const uchar_t *opt)
 {
-	int len, pointer;
+	int len, pointer, remain;
 	struct in_addr addr;
 	char *line;
 
 	len = opt[1];
 	pointer = opt[2];
 
-	(void) sprintf(get_line((char *)(&opt + 2) - dlc_header, 1),
+	(void) snprintf(get_line(0, 0), get_line_remain(),
 	    "    Pointer = %d", pointer);
 
 	pointer -= IPOPT_MINOFF;
@@ -679,15 +690,16 @@
 	len -= (IPOPT_OFFSET + 1);
 
 	while (len > 0) {
-		line = get_line((char *)&(opt) - dlc_header, 4);
+		line = get_line(0, 0);
+		remain = get_line_remain();
 		memcpy((char *)&addr, opt, sizeof (addr));
 		if (addr.s_addr == INADDR_ANY)
-			(void) strcpy(line, "      -");
+			(void) strlcpy(line, "      -", remain);
 		else
-			(void) sprintf(line, "      %s",
+			(void) snprintf(line, remain, "      %s",
 			    addrtoname(AF_INET, &addr));
 		if (pointer == 0)
-			(void) strcat(line, "  <-- (current)");
+			(void) strlcat(line, "  <-- (current)", remain);
 
 		opt += sizeof (addr);
 		len -= sizeof (addr);
@@ -696,8 +708,7 @@
 }
 
 char *
-getproto(p)
-	int p;
+getproto(int p)
 {
 	switch (p) {
 	case IPPROTO_HOPOPTS:	return ("IPv6-HopOpts");
@@ -728,9 +739,7 @@
 }
 
 static void
-prt_routing_hdr(flags, ipv6ext_rthdr)
-	int flags;
-	struct ip6_rthdr *ipv6ext_rthdr;
+prt_routing_hdr(int flags, const struct ip6_rthdr *ipv6ext_rthdr)
 {
 	uint8_t nxt_hdr;
 	uint8_t type;
@@ -755,13 +764,13 @@
 	show_header("IPv6-Route:  ", "IPv6 Routing Header", 0);
 	show_space();
 
-	(void) sprintf(get_line((char *)ipv6ext_rthdr - dlc_header, 1),
+	(void) snprintf(get_line(0, 0), get_line_remain(),
 	    "Next header = %d (%s)", nxt_hdr, getproto(nxt_hdr));
-	(void) sprintf(get_line((char *)ipv6ext_rthdr - dlc_header, 1),
+	(void) snprintf(get_line(0, 0), get_line_remain(),
 	    "Header length = %d", len);
-	(void) sprintf(get_line((char *)ipv6ext_rthdr - dlc_header, 1),
+	(void) snprintf(get_line(0, 0), get_line_remain(),
 	    "Routing type = %d", type);
-	(void) sprintf(get_line((char *)ipv6ext_rthdr - dlc_header, 1),
+	(void) snprintf(get_line(0, 0), get_line_remain(),
 	    "Segments left = %d", segleft);
 
 	if (type == IPV6_RTHDR_TYPE_0) {
@@ -774,14 +783,14 @@
 		 * XXX to differentiate between the hops yet to do
 		 * XXX and the hops already taken.
 		 */
+		/* LINTED: alignment */
 		ipv6ext_rthdr0 = (struct ip6_rthdr0 *)ipv6ext_rthdr;
 		numaddrs = ipv6ext_rthdr0->ip6r0_len / 2;
 		addrs = (struct in6_addr *)(ipv6ext_rthdr0 + 1);
 		for (i = 0; i < numaddrs; i++) {
 			(void) inet_ntop(AF_INET6, &addrs[i], addr,
 			    INET6_ADDRSTRLEN);
-			(void) sprintf(get_line((char *)ipv6ext_rthdr -
-			    dlc_header, 1),
+			(void) snprintf(get_line(0, 0), get_line_remain(),
 			    "address[%d]=%s", i, addr);
 		}
 	}
@@ -790,9 +799,7 @@
 }
 
 static void
-prt_fragment_hdr(flags, ipv6ext_frag)
-	int flags;
-	struct ip6_frag *ipv6ext_frag;
+prt_fragment_hdr(int flags, const struct ip6_frag *ipv6ext_frag)
 {
 	boolean_t morefrag;
 	uint16_t fragoffset;
@@ -807,7 +814,7 @@
 	fragident = ntohl(ipv6ext_frag->ip6f_ident);
 
 	if (flags & F_SUM) {
-		(void) sprintf(get_sum_line(),
+		(void) snprintf(get_sum_line(), MAXLINE,
 		    "IPv6 fragment ID=%d Offset=%-4d MF=%d",
 		    fragident,
 		    fragoffset,
@@ -816,13 +823,13 @@
 		show_header("IPv6-Frag:  ", "IPv6 Fragment Header", 0);
 		show_space();
 
-		(void) sprintf(get_line((char *)ipv6ext_frag - dlc_header, 1),
+		(void) snprintf(get_line(0, 0), get_line_remain(),
 		    "Next Header = %d (%s)", nxt_hdr, getproto(nxt_hdr));
-		(void) sprintf(get_line((char *)ipv6ext_frag - dlc_header, 1),
+		(void) snprintf(get_line(0, 0), get_line_remain(),
 		    "Fragment Offset = %d", fragoffset);
-		(void) sprintf(get_line((char *)ipv6ext_frag - dlc_header, 1),
+		(void) snprintf(get_line(0, 0), get_line_remain(),
 		    "More Fragments Flag = %s", morefrag ? "true" : "false");
-		(void) sprintf(get_line((char *)ipv6ext_frag - dlc_header, 1),
+		(void) snprintf(get_line(0, 0), get_line_remain(),
 		    "Identification = %d", fragident);
 
 		show_space();
@@ -830,12 +837,131 @@
 }
 
 static void
-prt_hbh_options(flags, ipv6ext_hbh)
-	int flags;
-	struct ip6_hbh *ipv6ext_hbh;
+print_ip6opt_ls(const uchar_t *data, unsigned int op_len)
 {
-	uint8_t *data;
-	uint32_t len, olen;
+	uint32_t doi;
+	uint8_t sotype, solen;
+	uint16_t value, value2;
+	char *cp;
+	int remlen;
+	boolean_t printed;
+
+	(void) snprintf(get_line(0, 0), get_line_remain(),
+	    "Labeled Security Option len = %u bytes%s", op_len,
+	    op_len < sizeof (uint32_t) || (op_len & 1) != 0 ? "?" : "");
+	if (op_len < sizeof (uint32_t))
+		return;
+	GETINT32(doi, data);
+	(void) snprintf(get_line(0, 0), get_line_remain(),
+	    "    DOI = %d (%s)", doi, doi == IP6LS_DOI_V4 ? "IPv4" : "???");
+	op_len -= sizeof (uint32_t);
+	while (op_len > 0) {
+		GETINT8(sotype, data);
+		if (op_len < 2) {
+			(void) snprintf(get_line(0, 0), get_line_remain(),
+			    "    truncated %u suboption (no len)", sotype);
+			break;
+		}
+		GETINT8(solen, data);
+		if (solen < 2 || solen > op_len) {
+			(void) snprintf(get_line(0, 0), get_line_remain(),
+			    "    bad %u suboption (len 2 <= %u <= %u)",
+			    sotype, solen, op_len);
+			if (solen < 2)
+				solen = 2;
+			if (solen > op_len)
+				solen = op_len;
+		}
+		op_len -= solen;
+		solen -= 2;
+		cp = get_line(0, 0);
+		remlen = get_line_remain();
+		(void) strlcpy(cp, "    ", remlen);
+		cp += 4;
+		remlen -= 4;
+		printed = B_TRUE;
+		switch (sotype) {
+		case IP6LS_TT_LEVEL:
+			if (solen != 2) {
+				printed = B_FALSE;
+				break;
+			}
+			GETINT16(value, data);
+			(void) snprintf(cp, remlen, "Level %u", value);
+			solen = 0;
+			break;
+		case IP6LS_TT_VECTOR:
+			(void) strlcpy(cp, "Bit-Vector: ", remlen);
+			remlen -= strlen(cp);
+			cp += strlen(cp);
+			while (solen > 1) {
+				GETINT16(value, data);
+				solen -= 2;
+				(void) snprintf(cp, remlen, "%04x", value);
+				remlen -= strlen(cp);
+				cp += strlen(cp);
+			}
+			break;
+		case IP6LS_TT_ENUM:
+			(void) strlcpy(cp, "Enumeration:", remlen);
+			remlen -= strlen(cp);
+			cp += strlen(cp);
+			while (solen > 1) {
+				GETINT16(value, data);
+				solen -= 2;
+				(void) snprintf(cp, remlen, " %u", value);
+				remlen -= strlen(cp);
+				cp += strlen(cp);
+			}
+			break;
+		case IP6LS_TT_RANGES:
+			(void) strlcpy(cp, "Ranges:", remlen);
+			remlen -= strlen(cp);
+			cp += strlen(cp);
+			while (solen > 3) {
+				GETINT16(value, data);
+				GETINT16(value2, data);
+				solen -= 4;
+				(void) snprintf(cp, remlen, " %u-%u", value,
+				    value2);
+				remlen -= strlen(cp);
+				cp += strlen(cp);
+			}
+			break;
+		case IP6LS_TT_V4:
+			(void) strlcpy(cp, "IPv4 Option", remlen);
+			print_ipoptions(data, solen);
+			solen = 0;
+			break;
+		case IP6LS_TT_DEST:
+			(void) snprintf(cp, remlen,
+			    "Destination-Only Data length %u", solen);
+			solen = 0;
+			break;
+		default:
+			(void) snprintf(cp, remlen,
+			    "    unknown %u suboption (len %u)", sotype, solen);
+			solen = 0;
+			break;
+		}
+		if (solen != 0) {
+			if (printed) {
+				cp = get_line(0, 0);
+				remlen = get_line_remain();
+			}
+			(void) snprintf(cp, remlen,
+			    "    malformed %u suboption (remaining %u)",
+			    sotype, solen);
+			data += solen;
+		}
+	}
+}
+
+static void
+prt_hbh_options(int flags, const struct ip6_hbh *ipv6ext_hbh)
+{
+	const uint8_t *data, *ndata;
+	uint32_t len;
 	uint8_t op_type;
 	uint8_t op_len;
 	uint8_t nxt_hdr;
@@ -854,85 +980,84 @@
 	 */
 	len = ipv6ext_hbh->ip6h_len * 8 + 8;
 
-	data = (uint8_t *)ipv6ext_hbh + 2;
+	ndata = (const uint8_t *)ipv6ext_hbh + 2;
 	len -= 2;
 
 	nxt_hdr = ipv6ext_hbh->ip6h_nxt;
-	(void) sprintf(get_line((char *)ipv6ext_hbh - dlc_header, 1),
+	(void) snprintf(get_line(0, 0), get_line_remain(),
 	    "Next Header = %u (%s)", nxt_hdr, getproto(nxt_hdr));
 
 	while (len > 0) {
+		data = ndata;
 		GETINT8(op_type, data);
-		olen = len;
-		switch (op_type) {
-		case IP6OPT_PAD1:
-			(void) sprintf(get_line((char *)ipv6ext_hbh -
-			    dlc_header, 1),
+		/* This is the only one-octet IPv6 option */
+		if (op_type == IP6OPT_PAD1) {
+			(void) snprintf(get_line(0, 0), get_line_remain(),
 			    "pad1 option ");
 			len--;
-			break;
+			ndata = data;
+			continue;
+		}
+		GETINT8(op_len, data);
+		if (len < 2 || op_len + 2 > len) {
+			(void) snprintf(get_line(0, 0), get_line_remain(),
+			    "Error: option %u truncated (%u + 2 > %u)",
+			    op_type, op_len, len);
+			op_len = len - 2;
+			/*
+			 * Continue processing the malformed option so that we
+			 * can display as much as possible.
+			 */
+		}
+
+		/* advance pointers to the next option */
+		len -= op_len + 2;
+		ndata = data + op_len;
+
+		/* process this option */
+		switch (op_type) {
 		case IP6OPT_PADN:
-			GETINT8(op_len, data);
-			(void) sprintf(get_line((char *)ipv6ext_hbh -
-			    dlc_header, 1),
+			(void) snprintf(get_line(0, 0), get_line_remain(),
 			    "padN option len = %u", op_len);
-			data += op_len;	/* skip pads */
-			len -= (op_len + 2);
 			break;
 		case IP6OPT_JUMBO: {
 			uint32_t payload_len;
 
-			GETINT8(op_len, data);
-			(void) sprintf(get_line((char *)ipv6ext_hbh -
-			    dlc_header, 1),
-			    "Jumbo Payload Option len = %u bytes", op_len);
+			(void) snprintf(get_line(0, 0), get_line_remain(),
+			    "Jumbo Payload Option len = %u bytes%s", op_len,
+			    op_len == sizeof (uint32_t) ? "" : "?");
 			if (op_len == sizeof (uint32_t)) {
 				GETINT32(payload_len, data);
-				(void) sprintf(get_line((char *)ipv6ext_hbh -
-				    dlc_header, 1),
+				(void) snprintf(get_line(0, 0),
+				    get_line_remain(),
 				    "Jumbo Payload Length = %u bytes",
 				    payload_len);
-			} else {
-				data += op_len;
 			}
-			len -= (op_len + 2);
 			break;
 		}
 		case IP6OPT_ROUTER_ALERT: {
 			uint16_t value;
 			const char *label[] = {"MLD", "RSVP", "AN"};
 
-			GETINT8(op_len, data);
-			(void) snprintf(get_line((char *)ipv6ext_hbh -
-			    dlc_header, 1), get_line_remain(),
-			    "Router Alert Option len = %u bytes", op_len);
+			(void) snprintf(get_line(0, 0), get_line_remain(),
+			    "Router Alert Option len = %u bytes%s", op_len,
+			    op_len == sizeof (uint16_t) ? "" : "?");
 			if (op_len == sizeof (uint16_t)) {
 				GETINT16(value, data);
-				(void) snprintf(get_line((char *)ipv6ext_hbh -
-				    dlc_header, 1), get_line_remain(),
+				(void) snprintf(get_line(0, 0),
+				    get_line_remain(),
 				    "Alert Type = %d (%s)", value,
 				    value < sizeof (label) / sizeof (label[0]) ?
 				    label[value] : "???");
-			} else {
-				data += op_len;
 			}
-			len -= (op_len + 2);
 			break;
 		}
+		case IP6OPT_LS:
+			print_ip6opt_ls(data, op_len);
+			break;
 		default:
-			GETINT8(op_len, data);
-			(void) sprintf(get_line((char *)ipv6ext_hbh -
-			    dlc_header, 1),
+			(void) snprintf(get_line(0, 0), get_line_remain(),
 			    "Option type = %u, len = %u", op_type, op_len);
-			data += op_len;
-			len -= (op_len + 2);
-		}
-		/* check for corrupt length */
-		if (olen <= len) {
-			(void) sprintf(get_line((char *)ipv6ext_hbh -
-			    dlc_header, 1),
-			    "Incomplete option len = %u, len = %u", op_type,
-			    len);
 			break;
 		}
 	}
@@ -941,12 +1066,10 @@
 }
 
 static void
-prt_dest_options(flags, ipv6ext_dest)
-	int flags;
-	struct ip6_dest *ipv6ext_dest;
+prt_dest_options(int flags, const struct ip6_dest *ipv6ext_dest)
 {
-	uint8_t *data;
-	uint32_t len, olen;
+	const uint8_t *data, *ndata;
+	uint32_t len;
 	uint8_t op_type;
 	uint32_t op_len;
 	uint8_t nxt_hdr;
@@ -966,57 +1089,405 @@
 	 */
 	len = ipv6ext_dest->ip6d_len * 8 + 8;
 
-	data = (uint8_t *)ipv6ext_dest + 2; /* skip hdr/len */
+	ndata = (const uint8_t *)ipv6ext_dest + 2; /* skip hdr/len */
 	len -= 2;
 
 	nxt_hdr = ipv6ext_dest->ip6d_nxt;
-	(void) sprintf(get_line((char *)ipv6ext_dest - dlc_header, 1),
+	(void) snprintf(get_line(0, 0), get_line_remain(),
 	    "Next Header = %u (%s)", nxt_hdr, getproto(nxt_hdr));
 
 	while (len > 0) {
+		data = ndata;
 		GETINT8(op_type, data);
-		olen = len;
-		switch (op_type) {
-		case IP6OPT_PAD1:
-			(void) sprintf(get_line((char *)ipv6ext_dest -
-			    dlc_header, 1),
+		if (op_type == IP6OPT_PAD1) {
+			(void) snprintf(get_line(0, 0), get_line_remain(),
 			    "pad1 option ");
 			len--;
-			break;
+			ndata = data;
+			continue;
+		}
+		GETINT8(op_len, data);
+		if (len < 2 || op_len + 2 > len) {
+			(void) snprintf(get_line(0, 0), get_line_remain(),
+			    "Error: option %u truncated (%u + 2 > %u)",
+			    op_type, op_len, len);
+			op_len = len - 2;
+			/*
+			 * Continue processing the malformed option so that we
+			 * can display as much as possible.
+			 */
+		}
+
+		/* advance pointers to the next option */
+		len -= op_len + 2;
+		ndata = data + op_len;
+
+		/* process this option */
+		switch (op_type) {
 		case IP6OPT_PADN:
-			GETINT8(op_len, data);
-			(void) sprintf(get_line((char *)ipv6ext_dest -
-			    dlc_header, 1),
+			(void) snprintf(get_line(0, 0), get_line_remain(),
 			    "padN option len = %u", op_len);
-			data += op_len;
-			len -= (op_len + 2);
 			break;
 		case IP6OPT_TUNNEL_LIMIT:
-			GETINT8(op_len, data);
 			GETINT8(value, data);
-			(void) sprintf(get_line((char *)ipv6ext_dest -
-			    dlc_header, 1),
+			(void) snprintf(get_line(0, 0), get_line_remain(),
 			    "tunnel encapsulation limit len = %d, value = %d",
 			    op_len, value);
-			len -= (op_len + 2);
+			break;
+		case IP6OPT_LS:
+			print_ip6opt_ls(data, op_len);
 			break;
 		default:
-			GETINT8(op_len, data);
-			(void) sprintf(get_line((char *)ipv6ext_dest -
-			    dlc_header, 1),
+			(void) snprintf(get_line(0, 0), get_line_remain(),
 			    "Option type = %u, len = %u", op_type, op_len);
-			data += op_len;
-			len -= (op_len + 2);
-		}
-		/* check for corrupt length */
-		if (olen <= len) {
-			(void) sprintf(get_line((char *)ipv6ext_dest -
-			    dlc_header, 1),
-			    "Incomplete option len = %u, len = %u", op_type,
-			    len);
 			break;
 		}
 	}
 
 	show_space();
 }
+
+#define	ALABEL_MAXLEN	256
+
+static char ascii_label[ALABEL_MAXLEN];
+static char *plabel = ascii_label;
+
+struct snoop_pair {
+	int val;
+	const char *name;
+};
+
+static struct snoop_pair ripso_class_tbl[] = {
+	TSOL_CL_TOP_SECRET,	"TOP SECRET",
+	TSOL_CL_SECRET,		"SECRET",
+	TSOL_CL_CONFIDENTIAL,	"CONFIDENTIAL",
+	TSOL_CL_UNCLASSIFIED,	"UNCLASSIFIED",
+	-1,			NULL
+};
+
+static struct snoop_pair ripso_prot_tbl[] = {
+	TSOL_PA_GENSER,		"GENSER",
+	TSOL_PA_SIOP_ESI,	"SIOP-ESI",
+	TSOL_PA_SCI,		"SCI",
+	TSOL_PA_NSA,		"NSA",
+	TSOL_PA_DOE,		"DOE",
+	0x04,			"UNASSIGNED",
+	0x02,			"UNASSIGNED",
+	-1,			NULL
+};
+
+static struct snoop_pair *
+get_pair_byval(struct snoop_pair pairlist[], int val)
+{
+	int i;
+
+	for (i = 0; pairlist[i].name != NULL; i++)
+		if (pairlist[i].val == val)
+			return (&pairlist[i]);
+	return (NULL);
+}
+
+static void
+print_ripso(const uchar_t *opt)
+{
+	struct snoop_pair *ripso_class;
+	int i, index, prot_len;
+	boolean_t first_prot;
+	char line[100], *ptr;
+
+	prot_len = opt[1] - 3;
+	if (prot_len < 0)
+		return;
+
+	show_header("RIPSO:  ", "Revised IP Security Option", 0);
+	show_space();
+
+	(void) snprintf(get_line(0, 0), get_line_remain(),
+	    "Type = Basic Security Option (%d), Length = %d", opt[0], opt[1]);
+
+	/*
+	 * Display Classification Level
+	 */
+	ripso_class = get_pair_byval(ripso_class_tbl, (int)opt[2]);
+	if (ripso_class != NULL)
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Classification = Unknown (0x%02x)", opt[2]);
+	else
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Classification = %s (0x%02x)",
+		    ripso_class->name, ripso_class->val);
+
+	/*
+	 * Display Protection Authority Flags
+	 */
+	(void) snprintf(line, sizeof (line), "Protection Authority = ");
+	ptr = line;
+	first_prot = B_TRUE;
+	for (i = 0; i < prot_len; i++) {
+		index = 0;
+		while (ripso_prot_tbl[index].name != NULL) {
+			if (opt[3 + i] & ripso_prot_tbl[index].val) {
+				ptr = strchr(ptr, 0);
+				if (!first_prot) {
+					(void) strlcpy(ptr, ", ",
+					    sizeof (line) - (ptr - line));
+					ptr = strchr(ptr, 0);
+				}
+				(void) snprintf(ptr,
+				    sizeof (line) - (ptr - line),
+				    "%s (0x%02x)",
+				    ripso_prot_tbl[index].name,
+				    ripso_prot_tbl[index].val);
+			}
+			index++;
+		}
+		if ((opt[3 + i] & 1) == 0)
+			break;
+	}
+	if (!first_prot)
+		(void) snprintf(get_line(0, 0), get_line_remain(), "%s", line);
+	else
+		(void) snprintf(get_line(0, 0), get_line_remain(), "%sNone",
+		    line);
+}
+
+#define	CIPSO_GENERIC_ARRAY_LEN	200
+
+/*
+ * Return 1 if CIPSO SL and Categories are all 1's; 0 otherwise.
+ *
+ * Note: opt starts with "Tag Type":
+ *
+ * |tag_type(1)|tag_length(1)|align(1)|sl(1)|categories(variable)|
+ *
+ */
+static boolean_t
+cipso_high(const uchar_t *opt)
+{
+	int i;
+
+	if (((int)opt[1] + 6) < IP_MAX_OPT_LENGTH)
+		return (B_FALSE);
+	for (i = 0; i < ((int)opt[1] - 3); i++)
+		if (opt[3 + i] != 0xff)
+			return (B_FALSE);
+	return (B_TRUE);
+}
+
+/*
+ * Converts CIPSO label to SL.
+ *
+ * Note: opt starts with "Tag Type":
+ *
+ * |tag_type(1)|tag_length(1)|align(1)|sl(1)|categories(variable)|
+ *
+ */
+static void
+cipso2sl(const uchar_t *opt, bslabel_t *sl, int *high)
+{
+	int i, taglen;
+	uchar_t *q = (uchar_t *)&((_bslabel_impl_t *)sl)->compartments;
+
+	*high = 0;
+	taglen = opt[1];
+	memset((caddr_t)sl, 0, sizeof (bslabel_t));
+
+	if (cipso_high(opt)) {
+		BSLHIGH(sl);
+		*high = 1;
+	} else {
+		LCLASS_SET((_bslabel_impl_t *)sl, opt[3]);
+		for (i = 0; i < taglen - TSOL_TT1_MIN_LENGTH; i++)
+			q[i] = opt[TSOL_TT1_MIN_LENGTH + i];
+	}
+	SETBLTYPE(sl, SUN_SL_ID);
+}
+
+static int
+interpret_cipso_tagtype1(const uchar_t *opt)
+{
+	int i, taglen, ishigh;
+	bslabel_t sl;
+	char line[CIPSO_GENERIC_ARRAY_LEN], *ptr;
+
+	taglen = opt[1];
+	if (taglen < TSOL_TT1_MIN_LENGTH ||
+	    taglen > TSOL_TT1_MAX_LENGTH)
+		return (taglen);
+
+	(void) snprintf(get_line(0, 0), get_line_remain(),
+	    "Tag Type = %d, Tag Length = %d", opt[0], opt[1]);
+	(void) snprintf(get_line(0, 0), get_line_remain(),
+	    "Sensitivity Level = 0x%02x", opt[3]);
+	ptr = line;
+	for (i = 0; i < taglen - TSOL_TT1_MIN_LENGTH; i++) {
+		(void) snprintf(ptr, sizeof (line) - (ptr - line), "%02x",
+		    opt[TSOL_TT1_MIN_LENGTH + i]);
+		ptr = strchr(ptr, 0);
+	}
+	if (i != 0) {
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Categories = ");
+		(void) snprintf(get_line(0, 0), get_line_remain(), "\t%s",
+		    line);
+	} else {
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Categories = None");
+	}
+	cipso2sl(opt, &sl, &ishigh);
+	if (is_system_labeled) {
+		if (bsltos(&sl, &plabel, ALABEL_MAXLEN,
+		    LONG_CLASSIFICATION|LONG_WORDS|VIEW_INTERNAL) < 0) {
+			(void) snprintf(get_line(0, 0), get_line_remain(),
+			    "The Sensitivity Level and Categories can't be "
+			    "mapped to a valid SL");
+		} else {
+			(void) snprintf(get_line(0, 0), get_line_remain(),
+			    "The Sensitivity Level and Categories are mapped "
+			    "to the SL:");
+			(void) snprintf(get_line(0, 0), get_line_remain(),
+			    "\t%s", ascii_label);
+		}
+	}
+	return (taglen);
+}
+
+/*
+ * The following struct definition #define's are copied from TS1.x. They are
+ * not used here (except TTYPE_3_MAX_TOKENS), but included as a reference for
+ * the tag type 3 packet format.
+ */
+#define	TTYPE_3_MAX_TOKENS	7
+
+/*
+ * Display CIPSO tag type 3 which is defined by MAXSIX.
+ */
+static int
+interpret_cipso_tagtype3(const uchar_t *opt)
+{
+	uchar_t tagtype;
+	int index, numtokens, taglen;
+	uint16_t mask;
+	uint32_t token;
+	static const char *name[] = {
+		"SL",
+		"NCAV",
+		"INTEG",
+		"SID",
+		"undefined",
+		"undefined",
+		"IL",
+		"PRIVS",
+		"LUID",
+		"PID",
+		"IDS",
+		"ACL"
+	};
+
+	tagtype = *opt++;
+	(void) memcpy(&mask, opt + 3, sizeof (mask));
+	(void) snprintf(get_line(0, 0), get_line_remain(),
+	    "Tag Type = %d (MAXSIX)", tagtype);
+	(void) snprintf(get_line(0, 0), get_line_remain(),
+	    "Generation = 0x%02x%02x%02x, Mask = 0x%04x", opt[0], opt[1],
+	    opt[2], mask);
+	opt += 3 + sizeof (mask);
+
+	/*
+	 * Display tokens
+	 */
+	numtokens = 0;
+	index = 0;
+	while (mask != 0 && numtokens < TTYPE_3_MAX_TOKENS) {
+		if (mask & 0x0001) {
+			(void) memcpy(&token, opt, sizeof (token));
+			opt += sizeof (token);
+			(void) snprintf(get_line(0, 0), get_line_remain(),
+			    "Attribute = %s, Token = 0x%08x",
+			    index < sizeof (name) / sizeof (*name) ?
+			    name[index] : "unknown", token);
+			numtokens++;
+		}
+		mask = mask >> 1;
+		index++;
+	}
+
+	taglen = 6 + numtokens * 4;
+	return (taglen);
+}
+
+static void
+print_cipso(const uchar_t *opt)
+{
+	int optlen, taglen, tagnum;
+	uint32_t doi;
+	char line[CIPSO_GENERIC_ARRAY_LEN];
+	char *oldnest;
+
+	optlen = opt[1];
+	if (optlen < TSOL_CIPSO_MIN_LENGTH || optlen > TSOL_CIPSO_MAX_LENGTH)
+		return;
+
+	oldnest = prot_nest_prefix;
+	prot_nest_prefix = prot_prefix;
+	show_header("CIPSO:  ", "Common IP Security Option", 0);
+	show_space();
+
+	/*
+	 * Display CIPSO Header
+	 */
+	(void) snprintf(get_line(0, 0), get_line_remain(),
+	    "Type = CIPSO (%d), Length = %d", opt[0], opt[1]);
+	(void) memcpy(&doi, opt + 2, sizeof (doi));
+	(void) snprintf(get_line(0, 0), get_line_remain(),
+	    "Domain of Interpretation = %u", (unsigned)ntohl(doi));
+
+	if (opt[1] == TSOL_CIPSO_MIN_LENGTH) {	/* no tags */
+		show_space();
+		prot_prefix = prot_nest_prefix;
+		prot_nest_prefix = oldnest;
+		return;
+	}
+	optlen -= TSOL_CIPSO_MIN_LENGTH;
+	opt += TSOL_CIPSO_MIN_LENGTH;
+
+	/*
+	 * Display Each Tag
+	 */
+	tagnum = 1;
+	while (optlen >= TSOL_TT1_MIN_LENGTH) {
+		(void) snprintf(line, sizeof (line), "Tag# %d", tagnum);
+		show_header("CIPSO:  ", line, 0);
+		/*
+		 * We handle tag type 1 and 3 only. Note, tag type 3
+		 * is MAXSIX defined.
+		 */
+		switch (opt[0]) {
+		case 1:
+			taglen = interpret_cipso_tagtype1(opt);
+			break;
+		case 3:
+			taglen = interpret_cipso_tagtype3(opt);
+			break;
+		default:
+			(void) snprintf(get_line(0, 0), get_line_remain(),
+			    "Unknown Tag Type %d", opt[0]);
+			show_space();
+			prot_prefix = prot_nest_prefix;
+			prot_nest_prefix = oldnest;
+			return;
+		}
+
+		/*
+		 * Move to the next tag
+		 */
+		if (taglen <= 0)
+			break;
+		optlen -= taglen;
+		opt += taglen;
+		tagnum++;
+	}
+	show_space();
+	prot_prefix = prot_nest_prefix;
+	prot_nest_prefix = oldnest;
+}
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ipaddr.c b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ipaddr.c
index 45061e5..1f7a743 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ipaddr.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ipaddr.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,13 +19,14 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SunOS */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <ctype.h>
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -40,8 +40,10 @@
 #include <string.h>
 #include <signal.h>
 #include <setjmp.h>
+#include <arpa/inet.h>
+#include "snoop.h"
 
-sigjmp_buf nisjmp;
+static sigjmp_buf nisjmp;
 
 #define	MAXHASH 1024  /* must be a power of 2 */
 
@@ -70,16 +72,16 @@
 	struct in6_addr	h6_addr;
 };
 
-static struct hostdata *addhost(int, void *, char *, char **);
+static struct hostdata *addhost(int, const void *, const char *, char **);
 
-struct hostdata4 *h_table4[MAXHASH];
-struct hostdata6 *h_table6[MAXHASH];
+static struct hostdata4 *h_table4[MAXHASH];
+static struct hostdata6 *h_table6[MAXHASH];
 
 #define	iphash(e)  ((e) & (MAXHASH-1))
 
+/* ARGSUSED */
 static void
-wakeup(n)
-	int n;
+wakeup(int n)
 {
 	siglongjmp(nisjmp, 1);
 }
@@ -135,7 +137,7 @@
 }
 
 static struct hostdata *
-ip6lookup(struct in6_addr *ip6addr)
+ip6lookup(const struct in6_addr *ip6addr)
 {
 	struct hostdata6 *h;
 	struct hostent *hp = NULL;
@@ -182,9 +184,9 @@
 }
 
 static struct hostdata *
-addhost(int family, void *ipaddr, char *name, char **aliases)
+addhost(int family, const void *ipaddr, const char *name, char **aliases)
 {
-	register struct hostdata **hp, *n = NULL;
+	struct hostdata **hp, *n = NULL;
 	extern FILE *namefile;
 	int hashval;
 	static char aname[128];
@@ -203,7 +205,8 @@
 		if (n->h_hostname == NULL)
 			goto alloc_failed;
 
-		((struct hostdata4 *)n)->h4_addr = *(struct in_addr *)ipaddr;
+		((struct hostdata4 *)n)->h4_addr =
+		    *(const struct in_addr *)ipaddr;
 		hashval = ((struct in_addr *)ipaddr)->s_addr;
 		hp = (struct hostdata **)&h_table4[iphash(hashval)];
 		break;
@@ -219,7 +222,7 @@
 
 		memcpy(&((struct hostdata6 *)n)->h6_addr, ipaddr,
 		    sizeof (struct in6_addr));
-		hashval = ((int *)ipaddr)[3];
+		hashval = ((const int *)ipaddr)[3];
 		hp = (struct hostdata **)&h_table6[iphash(hashval)];
 		break;
 	default:
@@ -233,7 +236,7 @@
 
 	if (namefile != NULL) {
 		if (family == AF_INET) {
-			np = inet_ntoa(*(struct in_addr *)ipaddr);
+			np = inet_ntoa(*(const struct in_addr *)ipaddr);
 			if (np) {
 				(void) fprintf(namefile, "%s\t%s", np, name);
 				if (aliases) {
@@ -280,22 +283,18 @@
 }
 
 char *
-addrtoname(family, ipaddr)
-	int family;
-	void *ipaddr;
+addrtoname(int family, const void *ipaddr)
 {
 	switch (family) {
 	case AF_INET:
-		return (iplookup(*(struct in_addr *)ipaddr)->h_hostname);
+		return (iplookup(*(const struct in_addr *)ipaddr)->h_hostname);
 	case AF_INET6:
-		return (ip6lookup((struct in6_addr *)ipaddr)->h_hostname);
-	default:
-		fprintf(stderr, "snoop: ERROR: unknown address family: %d\n",
-		    family);
-		exit(1);
+		return (ip6lookup((const struct in6_addr *)ipaddr)->h_hostname);
 	}
-	/* Never reached... */
-	return (NULL);
+	(void) fprintf(stderr, "snoop: ERROR: unknown address family: %d\n",
+	    family);
+	exit(1);
+	/* NOTREACHED */
 }
 
 void
@@ -324,14 +323,15 @@
 		if (inet_pton(AF_INET6, addr, (void *)&addrv6) == 1) {
 			family = AF_INET6;
 			naddr = (void *)&addrv6;
-		} else if ((addrv4 = inet_addr(addr)) != -1) {
+		} else if ((addrv4 = inet_addr(addr)) != (ulong_t)-1) {
 			family = AF_INET;
 			naddr = (void *)&addrv4;
 		}
 		name = strtok(NULL, SEPARATORS);
 		if (name == NULL)
 			continue;
-		while ((alias = strtok(NULL, SEPARATORS)) && (*alias != '#')) {
+		while ((alias = strtok(NULL, SEPARATORS)) != NULL &&
+		    (*alias != '#')) {
 			(void) addhost(family, naddr, alias, NULL);
 		}
 		(void) addhost(family, naddr, name, NULL);
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ipsec.c b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ipsec.c
index a8c248c..76ec01f 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ipsec.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ipsec.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -32,6 +31,7 @@
 #include <string.h>
 #include <fcntl.h>
 #include <string.h>
+#include <strings.h>
 #include <sys/types.h>
 #include <sys/sysmacros.h>
 #include <sys/time.h>
@@ -49,11 +49,11 @@
 #include <inet/ipsecah.h>
 #include "snoop.h"
 
-extern char *dlc_header;
-
+/* ARGSUSED */
 int
 interpret_esp(int flags, uint8_t *hdr, int iplen, int fraglen)
 {
+	/* LINTED: alignment */
 	esph_t *esph = (esph_t *)hdr;
 	esph_t *aligned_esph;
 	esph_t storage;	/* In case hdr isn't aligned. */
@@ -104,6 +104,7 @@
 int
 interpret_ah(int flags, uint8_t *hdr, int iplen, int fraglen)
 {
+	/* LINTED: alignment */
 	ah_t *ah = (ah_t *)hdr;
 	ah_t *aligned_ah;
 	ah_t storage;	/* In case hdr isn't aligned. */
@@ -118,7 +119,7 @@
 
 	if (!IS_P2ALIGNED(hdr, 4)) {
 		aligned_ah = (ah_t *)&storage;
-		bcopy(hdr, storage, sizeof (ah_t));
+		bcopy(hdr, &storage, sizeof (ah_t));
 	} else {
 		aligned_ah = ah;
 	}
@@ -197,6 +198,7 @@
 	if (fraglen > 0)
 		switch (proto) {
 			case IPPROTO_ENCAP:
+				/* LINTED: alignment */
 				(void) interpret_ip(flags, (struct ip *)data,
 				    new_iplen);
 				break;
@@ -205,27 +207,33 @@
 				    new_iplen);
 				break;
 			case IPPROTO_ICMP:
-				interpret_icmp(flags, (struct icmp *)data,
-				    new_iplen, fraglen);
+				(void) interpret_icmp(flags,
+				    /* LINTED: alignment */
+				    (struct icmp *)data, new_iplen, fraglen);
 				break;
 			case IPPROTO_ICMPV6:
-				interpret_icmpv6(flags, (icmp6_t *)data,
+				/* LINTED: alignment */
+				(void) interpret_icmpv6(flags, (icmp6_t *)data,
 				    new_iplen, fraglen);
 				break;
 			case IPPROTO_TCP:
-				interpret_tcp(flags, data, new_iplen, fraglen);
+				(void) interpret_tcp(flags,
+				    (struct tcphdr *)data, new_iplen, fraglen);
 				break;
 
 			case IPPROTO_ESP:
-				interpret_esp(flags, data, new_iplen, fraglen);
-				break;
-			case IPPROTO_AH:
-				interpret_ah(flags, data, new_iplen, fraglen);
+				(void) interpret_esp(flags, data, new_iplen,
+				    fraglen);
 				break;
 
+			case IPPROTO_AH:
+				(void) interpret_ah(flags, data, new_iplen,
+				    fraglen);
+				break;
 
 			case IPPROTO_UDP:
-				interpret_udp(flags, data, new_iplen, fraglen);
+				(void) interpret_udp(flags,
+				    (struct udphdr *)data, new_iplen, fraglen);
 				break;
 			/* default case is to not print anything else */
 		}
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rip.c b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rip.c
index 91ff5be..c8a897c 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rip.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rip.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -38,7 +37,10 @@
 #include <protocols/routed.h>
 #include "snoop.h"
 
-static char *show_cmd(int);
+static const char *show_cmd(int);
+static int get_numtokens(unsigned int);
+static const struct rip_sec_entry *rip_next_sec_entry(
+    const struct rip_sec_entry *, int);
 
 int
 interpret_rip(int flags, struct rip *rip, int fraglen)
@@ -46,6 +48,9 @@
 	const struct netinfo *nip;
 	const struct entryinfo *ep;
 	const struct netauth *nap;
+	const struct rip_sec_entry *rsep, *rsn;
+	const struct rip_emetric *rep;
+	const uint32_t *tokp;
 	int len, count;
 	const char *cmdstr, *auth;
 	struct in_addr dst;
@@ -68,6 +73,8 @@
 		case RIPCMD_TRACEOFF:	cmdstr = "Traceoff";	break;
 		case RIPCMD_POLL:	cmdstr = "Poll";	break;
 		case RIPCMD_POLLENTRY:	cmdstr = "Poll entry";	break;
+		case RIPCMD_SEC_RESPONSE: cmdstr = "R - SEC";	break;
+		case RIPCMD_SEC_T_RESPONSE: cmdstr = "R - SEC_T"; break;
 		default: cmdstr = "?"; break;
 		}
 
@@ -108,6 +115,26 @@
 			len = 0;
 			break;
 
+		case RIPCMD_SEC_RESPONSE:
+		case RIPCMD_SEC_T_RESPONSE:
+			if (len < sizeof (rip->rip_tsol.rip_generation))
+				break;
+			len -= sizeof (rip->rip_tsol.rip_generation);
+			count = 0;
+			rsep = rip->rip_tsol.rip_sec_entry;
+			while (len > 0) {
+				rsn = rip_next_sec_entry(rsep, len);
+				if (rsn == NULL)
+					break;
+				len -= (const char *)rsn - (const char *)rsep;
+				rsep = rsn;
+				count++;
+			}
+			(void) snprintf(get_sum_line(), MAXLINE,
+			    "%s %s (%d destinations%s)", ripvers, cmdstr,
+			    count, (len != 0 ? "?" : ""));
+			break;
+
 		default:
 			(void) snprintf(get_sum_line(), MAXLINE,
 			    "%s %d (%s)", ripvers, rip->rip_cmd, cmdstr);
@@ -121,12 +148,11 @@
 		len = fraglen - 4;
 		show_header("RIP:  ", "Routing Information Protocol", fraglen);
 		show_space();
-		(void) snprintf(get_line((char *)(uintptr_t)rip->rip_cmd -
-		    dlc_header, 1), get_line_remain(), "Opcode = %d (%s)",
-		    rip->rip_cmd, show_cmd(rip->rip_cmd));
-		(void) snprintf(get_line((char *)(uintptr_t)rip->rip_vers -
-		    dlc_header, 1), get_line_remain(), "Version = %d",
-		    rip->rip_vers);
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Opcode = %d (%s)", rip->rip_cmd,
+		    show_cmd(rip->rip_cmd));
+		(void) snprintf(get_line(0, 0), get_line_remain(),
+		    "Version = %d", rip->rip_vers);
 
 		switch (rip->rip_cmd) {
 		case RIPCMD_REQUEST:
@@ -156,9 +182,7 @@
 						    nap->au.au_pw);
 					} else if (nap->a_type ==
 					    RIP_AUTH_MD5) {
-						(void) snprintf(get_line
-						    ((char *)nip - dlc_header,
-							sizeof (*nip)),
+						(void) snprintf(get_line(0, 0),
 						    get_line_remain(),
 						    " *** Auth MD5 pkt len %d, "
 						    "keyid %d, sequence %08lX, "
@@ -166,7 +190,7 @@
 						    ntohs(nap->au.a_md5.
 							md5_pkt_len),
 						    nap->au.a_md5.md5_keyid,
-						    ntohl(nap->au.a_md5.
+						    (long)ntohl(nap->au.a_md5.
 							md5_seqno),
 						    ntohs(nap->au.a_md5.
 							md5_auth_len));
@@ -189,15 +213,13 @@
 				}
 				if (nip->n_family == RIP_AF_UNSPEC &&
 				    rip->rip_cmd == RIPCMD_REQUEST) {
-					(void) snprintf(get_line((char *)nip -
-					    dlc_header, sizeof (*nip)),
+					(void) snprintf(get_line(0, 0),
 					    get_line_remain(),
 					    " *** All routes");
 					continue;
 				}
 				if (nip->n_family != RIP_AF_INET) {
-					(void) snprintf(get_line((char *)nip -
-					    dlc_header, sizeof (*nip)),
+					(void) snprintf(get_line(0, 0),
 					    get_line_remain(),
 					    " *** Address Family %d?",
 					    ntohs(nip->n_family));
@@ -231,8 +253,7 @@
 				}
 				dst.s_addr = nip->n_nhop;
 				mval = ntohl(nip->n_metric);
-				(void) snprintf(get_line((char *)nip -
-				    dlc_header, sizeof (*nip)),
+				(void) snprintf(get_line(0, 0),
 				    get_line_remain(),
 				    "%-31s %-15s %-6d %d%s",
 				    addrstr,
@@ -252,44 +273,105 @@
 			ep = (const struct entryinfo *)rip->rip_nets;
 			/* LINTED */
 			sin = (const struct sockaddr_in *)&ep->rtu_dst;
-			(void) snprintf(get_line((char *)sin - dlc_header,
-			    sizeof (struct sockaddr)), get_line_remain(),
+			(void) snprintf(get_line(0, 0), get_line_remain(),
 			    "Destination = %s %s",
 			    inet_ntoa(sin->sin_addr),
 			    addrtoname(AF_INET, (void *)&sin->sin_addr));
 			/* LINTED */
 			sin = (const struct sockaddr_in *)&ep->rtu_router;
-			(void) snprintf(get_line((char *)sin - dlc_header,
-			    sizeof (struct sockaddr)), get_line_remain(),
+			(void) snprintf(get_line(0, 0), get_line_remain(),
 			    "Router      = %s %s",
 			    inet_ntoa(sin->sin_addr),
 			    addrtoname(AF_INET, (void *)&sin->sin_addr));
-			(void) snprintf(get_line((char *)&ep->rtu_flags -
-			    dlc_header, 2), get_line_remain(),
+			(void) snprintf(get_line(0, 0), get_line_remain(),
 			    "Flags = %4x", (unsigned)ep->rtu_flags);
-			(void) snprintf(get_line((char *)&ep->rtu_state -
-			    dlc_header, 2), get_line_remain(),
+			(void) snprintf(get_line(0, 0), get_line_remain(),
 			    "State = %d", ep->rtu_state);
-			(void) snprintf(get_line((char *)&ep->rtu_timer -
-			    dlc_header, 4), get_line_remain(),
+			(void) snprintf(get_line(0, 0), get_line_remain(),
 			    "Timer = %d", ep->rtu_timer);
-			(void) snprintf(get_line((char *)&ep->rtu_metric -
-			    dlc_header, 4), get_line_remain(),
+			(void) snprintf(get_line(0, 0), get_line_remain(),
 			    "Metric = %d", ep->rtu_metric);
-			(void) snprintf(get_line((char *)&ep->int_flags -
-			    dlc_header, 4), get_line_remain(),
+			(void) snprintf(get_line(0, 0), get_line_remain(),
 			    "Int flags = %8x", ep->int_flags);
-			(void) snprintf(get_line((char *)ep->int_name -
-			    dlc_header, sizeof (ep->int_name)),
-			    get_line_remain(),
+			(void) snprintf(get_line(0, 0), get_line_remain(),
 			    "Int name = \"%.*s\"", sizeof (ep->int_name),
 			    ep->int_name);
 			break;
 
+		case RIPCMD_SEC_RESPONSE:
+		case RIPCMD_SEC_T_RESPONSE:
+			if (len < sizeof (rip->rip_tsol.rip_generation))
+				break;
+			len -= sizeof (rip->rip_tsol.rip_generation);
+			show_space();
+			(void) snprintf(get_line(0, 0), get_line_remain(),
+			    "Generation = %u",
+			    (unsigned)ntohl(rip->rip_tsol.rip_generation));
+			rsep = rip->rip_tsol.rip_sec_entry;
+			(void) snprintf(get_line(0, 0), get_line_remain(),
+			    "Address         E-METRIC");
+			rsep = rip->rip_tsol.rip_sec_entry;
+			while (len > 0) {
+				char *cp;
+				int blen, num;
+
+				rsn = rip_next_sec_entry(rsep, len);
+				if (rsn == NULL)
+					break;
+				dst.s_addr = rsep->rip_dst;
+				cp = get_line(0, 0);
+				blen = get_line_remain();
+				(void) snprintf(cp, blen, "%-16s ",
+				    inet_ntoa(dst));
+				cp += 17;
+				blen -= 17;
+				rep = rsep->rip_emetric;
+				for (count = ntohl(rsep->rip_count); count > 0;
+				    count--) {
+					(void) snprintf(cp, blen, "metric=%d",
+					    ntohs(rep->rip_metric));
+					blen -= strlen(cp);
+					cp += strlen(cp);
+					tokp = rep->rip_token;
+					num = get_numtokens(
+					    ntohs(rep->rip_mask));
+					/* advance to the next emetric */
+					rep = (const struct rip_emetric *)
+					    &rep->rip_token[num];
+					if (num > 0) {
+						(void) snprintf(cp, blen,
+						    ",tokens=%lx",
+						    (long)ntohl(*tokp));
+						tokp++;
+						num--;
+					} else {
+						(void) strlcpy(cp, ",no tokens",
+						    blen);
+					}
+					while (num > 0) {
+						blen -= strlen(cp);
+						cp += strlen(cp);
+						(void) snprintf(cp, blen,
+						    ",%lx",
+						    (long)ntohl(*tokp));
+						tokp++;
+						num--;
+					}
+					blen -= strlen(cp);
+					cp += strlen(cp);
+				}
+				if (rsep->rip_count == 0) {
+					(void) strlcpy(cp,
+					    "NULL (not reachable)", blen);
+				}
+				len -= (const char *)rsn - (const char *)rsep;
+				rsep = rsn;
+			}
+			break;
+
 		case RIPCMD_TRACEON:
 		case RIPCMD_TRACEOFF:
-			(void) snprintf(get_line((char *)rip->rip_tracefile -
-			    dlc_header, 2), get_line_remain(),
+			(void) snprintf(get_line(0, 0), get_line_remain(),
 			    "Trace file = %.*s", len, rip->rip_tracefile);
 			len = 0;
 			break;
@@ -299,7 +381,7 @@
 	return (fraglen - len);
 }
 
-static char *
+static const char *
 show_cmd(int c)
 {
 	switch (c) {
@@ -315,6 +397,44 @@
 		return ("route poll");
 	case RIPCMD_POLLENTRY:
 		return ("route poll entry");
+	case RIPCMD_SEC_RESPONSE:
+		return ("route sec response");
+	case RIPCMD_SEC_T_RESPONSE:
+		return ("route sec_t response");
 	}
 	return ("?");
 }
+
+static int
+get_numtokens(unsigned int mask)
+{
+	int num = 0;
+
+	while (mask != 0) {
+		num++;
+		mask &= mask - 1;
+	}
+	return (num);
+}
+
+static const struct rip_sec_entry *
+rip_next_sec_entry(const struct rip_sec_entry *rsep, int len)
+{
+	const struct rip_emetric *rep;
+	const char *limit = (const char *)rsep + len;
+	long count;
+
+	if ((const char *)(rep = rsep->rip_emetric) > limit)
+		return (NULL);
+	count = ntohl(rsep->rip_count);
+	while (count > 0) {
+		if ((const char *)rep->rip_token > limit)
+			return (NULL);
+		rep = (struct rip_emetric *)
+		    &rep->rip_token[get_numtokens(ntohs(rep->rip_mask))];
+		if ((const char *)rep > limit)
+			return (NULL);
+		count--;
+	}
+	return ((const struct rip_sec_entry *)rep);
+}
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rport.c b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rport.c
index 8a65afd..9722ee2 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rport.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rport.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,14 +19,17 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SunOS */
 
+#include <stdio.h>
+#include <stdlib.h>
 #include <ctype.h>
+#include <strings.h>
 #include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <sys/errno.h>
@@ -40,114 +42,106 @@
 #include <netinet/if_ether.h>
 #include "snoop.h"
 
-#define	NULL 0
-
-extern void interpret_mip_cntrlmsg(int, uchar_t *, int);
-
 struct porttable {
 	int	pt_num;
 	char	*pt_short;
-	char	*pt_long;
 };
 
-struct porttable pt_udp[] = {
-	7,	"ECHO",		"Echo",
-	9,	"DISCARD",	"Discard",
-	13,	"DAYTIME",	"Daytime",
-	19,	"CHARGEN",	"Character generator",
-	37,	"TIME",		"Time",
-	42,	"NAME",		"Host name server",
-	53,	"DNS",		"Domain Name Server",
-	67,	"BOOTPS",	"Bootstrap Protocol Server",
-	68,	"BOOTPC",	"Boostrap Protocol Client",
-	69,	"TFTP",		"Trivial File Transfer Protocol",
-	79,	"FINGER",	"Finger",
-/*	111,	"PORTMAP",	"Portmapper", Just Sun RPC */
-	123,	"NTP",		"Network Time Protocol",
-	137,	"NBNS",		"Netbios name service",
-	138,	"NBDG",		"Netbios datagram service",
-	389,	"LDAP",		"Lightweight Directory Access Protocol",
-	427,	"SLP",		"Service Location Protocol",
+static const struct porttable pt_udp[] = {
+	{ IPPORT_ECHO,		"ECHO" },
+	{ IPPORT_DISCARD,	"DISCARD" },
+	{ IPPORT_DAYTIME,	"DAYTIME" },
+	{ 19,			"CHARGEN" },
+	{ IPPORT_TIMESERVER,	"TIME" },
+	{ IPPORT_NAMESERVER,	"NAME" },
+	{ 53,			"DNS" },
+	{ IPPORT_BOOTPS,	"BOOTPS" },
+	{ IPPORT_BOOTPC,	"BOOTPC" },
+	{ IPPORT_TFTP,		"TFTP" },
+	{ IPPORT_FINGER,	"FINGER" },
+/*	{ 111,			"PORTMAP" }, Just Sun RPC */
+	{ 123,			"NTP" },
+	{ 137,			"NBNS" },
+	{ 138,			"NBDG" },
+	{ 389,			"LDAP" },
+	{ 427,			"SLP" },
 /* Mobile IP defines a set of new control messages sent over UDP port 434 */
-	434,	"Mobile IP",	"Mobile IP Control Messages",
-	512,	"BIFF",		"BIFF",
-	513,	"WHO",		"WHO",
-	514,	"SYSLOG",	"SYSLOG",
-	517,	"TALK",		"TALK",
-	520,	"RIP",		"Routing Information Protocol",
-	550,	"NEW-RWHO",	"NEW-RWHO",
-	560,	"RMONITOR",	"RMONITOR",
-	561,	"MONITOR",	"MONITOR",
-	521,	"RIPng",	"Routing Information Protocol for IPv6",
-	1080,	"SOCKS",	"SOCKS Gateway",
-	0,	NULL,		"",
+	{ 434,			"Mobile IP" },
+	{ IPPORT_BIFFUDP,	"BIFF" },
+	{ IPPORT_WHOSERVER,	"WHO" },
+	{ 514,			"SYSLOG" },
+	{ 517,			"TALK" },
+	{ IPPORT_ROUTESERVER,	"RIP" },
+	{ 521,			"RIPng" },
+	{ 550,			"NEW-RWHO" },
+	{ 560,			"RMONITOR" },
+	{ 561,			"MONITOR" },
+	{ 1080,			"SOCKS" },
+	{ 0,			NULL }
 };
 
-struct porttable pt_tcp[] = {
-	1,	"TCPMUX",	"TCPMUX",
-	7,	"ECHO",		"Echo",
-	9,	"DISCARD",	"Discard",
-	11,	"SYSTAT",	"Active users",
-	13,	"DAYTIME",	"Daytime",
-	15,	"NETSTAT",	"Who is up",
-	19,	"CHARGEN",	"Character generator",
-	20,	"FTP-DATA",	"File Transfer Protocol (data)",
-	21,	"FTP",		"File Transfer Protocol",
-	23,	"TELNET",	"Terminal connection",
-	25,	"SMTP",		"Simple Mail Transport Protocol",
-	37,	"TIME",		"Time",
-	39,	"RLP",		"Resource Location Protocol",
-	42,	"NAMESERVER",	"Host Name Server",
-	43,	"NICNAME",	"Who is",
-	53,	"DNS",		"Domain Name Server",
-	67,	"BOOTPS",	"Bootstrap Protocol Server",
-	68,	"BOOTPC",	"Bootstrap Protocol Client",
-	69,	"TFTP",		"Trivial File Transfer Protocol",
-	70,	"GOPHER",	"Internet Gopher Protocol",
-	77,	"RJE",		"RJE service (private)",
-	79,	"FINGER",	"Finger",
-	80,	"HTTP",		"HyperText Transfer Protocol",
-	87,	"LINK",		"Link",
-	95,	"SUPDUP",	"SUPDUP Protocol",
-	101,	"HOSTNAME",	"NIC Host Name Server",
-	102,	"ISO-TSAP",	"ISO-TSAP",
-	103,	"X400",		"X400 Mail service",
-	104,	"X400-SND",	"X400 Mail service",
-	105,	"CSNET-NS",	"CSNET-NS",
-	109,	"POP-2",	"POP-2",
-/*	111,	"PORTMAP",	"Portmapper", Just Sun RPC */
-	113,	"AUTH",		"Authentication Service",
-	117,	"UUCP-PATH",	"UUCP Path Service",
-	119,	"NNTP",		"Network News Transfer Protocol",
-	123,	"NTP",		"Network Time Protocol",
-	139,	"NBT",		"Netbios over TCP",
-	143,	"IMAP",		"Internet Message Access Protocol",
-	144,	"NeWS",		"Network extensible Window System",
-	389,	"LDAP",		"Lightweight Directory Access Protocol",
-	427,	"SLP",		"Service Location Protocol",
-	443,	"HTTPS",	"HTTP over SSL",
-	445,    "SMB",          "Direct Hosted Server Message Block",
-	512,	"EXEC",		"EXEC",
-	513,	"RLOGIN",	"RLOGIN",
-	514,	"RSHELL",	"RSHELL",
-	515,	"PRINTER",	"PRINTER",
-	530,	"COURIER",	"COURIER",
-	540,	"UUCP",		"UUCP",
-	600,	"PCSERVER",	"PCSERVER",
-	1524,	"INGRESLOCK",	"INGRESLOCK",
-	1080,	"SOCKS",	"SOCKS Gateway",
-	2904,	"M2UA",		"SS7 MTP2 User Adaption Layer",
-	2905,	"M3UA",		"SS7 MTP3 User Adaption Layer",
-	6000,	"XWIN",		"X Window System",
-	8080,	"HTTP (proxy)",	"HyperText Transfer Protocol (proxy)",
-	9900,	"IUA",		"ISDN Q.921 User Adaption Layer",
-	0,	NULL,		"",
+static struct porttable pt_tcp[] = {
+	{ 1,			"TCPMUX" },
+	{ IPPORT_ECHO,		"ECHO" },
+	{ IPPORT_DISCARD,	"DISCARD" },
+	{ IPPORT_SYSTAT,	"SYSTAT" },
+	{ IPPORT_DAYTIME,	"DAYTIME" },
+	{ IPPORT_NETSTAT,	"NETSTAT" },
+	{ 19,			"CHARGEN" },
+	{ 20,			"FTP-DATA" },
+	{ IPPORT_FTP,		"FTP" },
+	{ IPPORT_TELNET,	"TELNET" },
+	{ IPPORT_SMTP,		"SMTP" },
+	{ IPPORT_TIMESERVER,	"TIME" },
+	{ 39,			"RLP" },
+	{ IPPORT_NAMESERVER,	"NAMESERVER" },
+	{ IPPORT_WHOIS,		"NICNAME" },
+	{ 53,			"DNS" },
+	{ 70,			"GOPHER" },
+	{ IPPORT_RJE,		"RJE" },
+	{ IPPORT_FINGER,	"FINGER" },
+	{ 80,			"HTTP" },
+	{ IPPORT_TTYLINK,	"LINK" },
+	{ IPPORT_SUPDUP,	"SUPDUP" },
+	{ 101,			"HOSTNAME" },
+	{ 102,			"ISO-TSAP" },
+	{ 103,			"X400" },
+	{ 104,			"X400-SND" },
+	{ 105,			"CSNET-NS" },
+	{ 109,			"POP-2" },
+/*	{ 111,			"PORTMAP" }, Just Sun RPC */
+	{ 113,			"AUTH" },
+	{ 117,			"UUCP-PATH" },
+	{ 119,			"NNTP" },
+	{ 123,			"NTP" },
+	{ 139,			"NBT" },
+	{ 143,			"IMAP" },
+	{ 144,			"NeWS" },
+	{ 389,			"LDAP" },
+	{ 427,			"SLP" },
+	{ 443,			"HTTPS" },
+	{ 445,			"SMB" },
+	{ IPPORT_EXECSERVER,	"EXEC" },
+	{ IPPORT_LOGINSERVER,	"RLOGIN" },
+	{ IPPORT_CMDSERVER,	"RSHELL" },
+	{ 515,			"PRINTER" },
+	{ 530,			"COURIER" },
+	{ 540,			"UUCP" },
+	{ 600,			"PCSERVER" },
+	{ 1080,			"SOCKS" },
+	{ 1524,			"INGRESLOCK" },
+	{ 2904,			"M2UA" },
+	{ 2905,			"M3UA" },
+	{ 6000,			"XWIN" },
+	{ 8080,			"HTTP (proxy)" },
+	{ 9900,			"IUA" },
+	{ 0,			NULL },
 };
 
 char *
 getportname(int proto, in_port_t port)
 {
-	struct porttable *p, *pt;
+	const struct porttable *p, *pt;
 
 	switch (proto) {
 	case IPPROTO_SCTP: /* fallthru */
@@ -166,7 +160,7 @@
 int
 reservedport(int proto, int port)
 {
-	struct porttable *p, *pt;
+	const struct porttable *p, *pt;
 
 	switch (proto) {
 	case IPPROTO_TCP: pt = pt_tcp; break;
@@ -186,13 +180,13 @@
  * See TFTP interpreter.
  */
 #define	MAXTRANS 64
-struct ttable {
+static struct ttable {
 	int t_port;
-	int (*t_proc)();
+	int (*t_proc)(int, char *, int);
 } transients [MAXTRANS];
 
 int
-add_transient(int port, int (*proc)())
+add_transient(int port, int (*proc)(int, char *, int))
 {
 	static struct ttable *next = transients;
 
@@ -266,7 +260,7 @@
 			data++;
 			datalen--;
 
-			strlcpy(buffer, data, sizeof (buffer));
+			(void) strlcpy(buffer, data, sizeof (buffer));
 			composit = strtoul(buffer, &end, 0);
 			data += end - buffer;
 			if (*data == '>') {
@@ -306,11 +300,11 @@
 		static char syslog[] = "SYSLOG:  ";
 		show_header(syslog, syslog, dlen);
 		show_space();
-		(void) sprintf(get_detail_line(0, 80),
+		(void) snprintf(get_detail_line(0, 0), MAXLINE,
 		    "%s%sPriority: %.*s%s(%s.%s)", prot_nest_prefix, syslog,
 		    priostrlen, syslogstr, bogus ? "" : " ",
 		    facilstr, pristr);
-		(void) sprintf(get_line(0, 0),
+		(void) snprintf(get_line(0, 0), get_line_remain(),
 			"\"%s\"",
 			show_string(syslogstr, dlen, 60));
 		show_trailer();
@@ -323,7 +317,7 @@
 interpret_reserved(int flags, int proto, in_port_t src, in_port_t dst,
     char *data, int dlen)
 {
-	char *pn;
+	const char *pn;
 	int dir, port, which;
 	char pbuff[16], hbuff[32];
 	struct ttable *ttabp;
@@ -373,25 +367,29 @@
 
 	if (dlen > 0) {
 		switch (which) {
-		case  67:
-		case  68:
-			interpret_dhcp(flags, data, dlen);
+		case  IPPORT_BOOTPS:
+		case  IPPORT_BOOTPC:
+			(void) interpret_dhcp(flags, (struct dhcp *)data,
+			    dlen);
 			return (1);
-		case  69:
-			interpret_tftp(flags, data, dlen);
+		case  IPPORT_TFTP:
+			(void) interpret_tftp(flags, (struct tftphdr *)data,
+			    dlen);
 			return (1);
 		case  80:
 		case  8080:
-			interpret_http(flags, data, dlen);
+			(void) interpret_http(flags, data, dlen);
 			return (1);
 		case 123:
-			interpret_ntp(flags, data, dlen);
+			(void) interpret_ntp(flags, (struct ntpdata *)data,
+			    dlen);
 			return (1);
 		case 137:
-			interpret_netbios_ns(flags, data, dlen);
+			interpret_netbios_ns(flags, (uchar_t *)data, dlen);
 			return (1);
 		case 138:
-			interpret_netbios_datagram(flags, data, dlen);
+			interpret_netbios_datagram(flags, (uchar_t *)data,
+			    dlen);
 			return (1);
 		case 139:
 		case 445:
@@ -400,7 +398,7 @@
 			 * on port 139.  The same interpreter can be used
 			 * for both.
 			 */
-			interpret_netbios_ses(flags, data, dlen);
+			interpret_netbios_ses(flags, (uchar_t *)data, dlen);
 			return (1);
 		case 389:
 			interpret_ldap(flags, data, dlen, src, dst);
@@ -411,34 +409,36 @@
 		case 434:
 			interpret_mip_cntrlmsg(flags, (uchar_t *)data, dlen);
 			return (1);
-		case 520:
-			interpret_rip(flags, data, dlen);
+		case IPPORT_ROUTESERVER:
+			(void) interpret_rip(flags, (struct rip *)data, dlen);
 			return (1);
 		case 521:
-			interpret_rip6(flags, data, dlen);
+			(void) interpret_rip6(flags, (struct rip6 *)data,
+			    dlen);
 			return (1);
 		case 1080:
 			if (dir == 'C')
-				interpret_socks_call(flags, data, dlen);
+				(void) interpret_socks_call(flags, data, dlen);
 			else
-				interpret_socks_reply(flags, data, dlen);
+				(void) interpret_socks_reply(flags, data,
+				    dlen);
 			return (1);
 		}
 	}
 
 	if (flags & F_SUM) {
-		(void) sprintf(get_sum_line(),
+		(void) snprintf(get_sum_line(), MAXLINE,
 			"%s %c port=%d %s",
 			pn, dir, port,
 			show_string(data, dlen, 20));
 	}
 
 	if (flags & F_DTAIL) {
-		(void) sprintf(pbuff, "%s:  ", pn);
-		(void) sprintf(hbuff, "%s:  ", pn);
+		(void) snprintf(pbuff, sizeof (pbuff), "%s:  ", pn);
+		(void) snprintf(hbuff, sizeof (hbuff), "%s:  ", pn);
 		show_header(pbuff, hbuff, dlen);
 		show_space();
-		(void) sprintf(get_line(0, 0),
+		(void) snprintf(get_line(0, 0), get_line_remain(),
 			"\"%s\"",
 			show_string(data, dlen, 60));
 		show_trailer();
@@ -479,7 +479,7 @@
 				*pp++ = c;
 				printable++;
 			} else {
-				(void) sprintf(pp,
+				(void) snprintf(pp, TBSIZE - (pp - tbuff),
 					isdigit(*(p + 1)) ?
 					"\\%03o" : "\\%o", c);
 				pp += strlen(pp);
diff --git a/usr/src/cmd/devfsadm/Makefile.com b/usr/src/cmd/devfsadm/Makefile.com
index a07e703..247e1cb 100644
--- a/usr/src/cmd/devfsadm/Makefile.com
+++ b/usr/src/cmd/devfsadm/Makefile.com
@@ -32,12 +32,15 @@
 
 DEVFSADM_MOD = devfsadm
 
+DEVALLOCSRC =	devalloc.c
+
 PLCYSRC = devpolicy.c plcysubr.c
 
 MODLOADDIR = $(COMMON)/../modload
 
-DEVFSADM_SRC = $(COMMON)/$(DEVFSADM_MOD:%=%.c) $(PLCYSRC:%=$(COMMON)/%)
-DEVFSADM_OBJ = $(DEVFSADM_MOD:%=%.o) $(PLCYSRC:%.c=%.o)
+DEVFSADM_SRC = $(COMMON)/$(DEVFSADM_MOD:%=%.c) \
+		$(DEVALLOCSRC:%=$(COMMON)/%) $(PLCYSRC:%=$(COMMON)/%)
+DEVFSADM_OBJ = $(DEVFSADM_MOD:%=%.o) $(DEVALLOCSRC:%.c=%.o) $(PLCYSRC:%.c=%.o)
 
 DEVFSADM_DAEMON = devfsadmd
 
@@ -118,9 +121,9 @@
 LINTFLAGS += -erroff=E_NAME_DEF_NOT_USED2
 LINTFLAGS += -erroff=E_NAME_MULTIPLY_DEF2
 
-LAZYLIBS = -z lazyload -lzonecfg -z nolazyload
-lint := LAZYLIBS = -lzonecfg
-LDLIBS += -ldevinfo -lgen -lsysevent -lnvpair -lcmd $(LAZYLIBS)
+LAZYLIBS =	$(ZLAZYLOAD) -lzonecfg -lbsm $(ZNOLAZYLOAD)
+lint := LAZYLIBS = -lzonecfg -lbsm
+LDLIBS += -ldevinfo -lgen -lsysevent -lnvpair -lcmd -ldoor $(LAZYLIBS) -lnsl
 
 SRCS = $(DEVFSADM_SRC) $(LINK_SRCS)
 OBJS = $(DEVFSADM_OBJ) $(LINK_OBJS)
diff --git a/usr/src/cmd/devfsadm/audio_link.c b/usr/src/cmd/devfsadm/audio_link.c
index 2f898e3..75568ff 100644
--- a/usr/src/cmd/devfsadm/audio_link.c
+++ b/usr/src/cmd/devfsadm/audio_link.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -32,10 +31,13 @@
 #include <stdlib.h>
 #include <limits.h>
 #include <stdio.h>
+#include <bsm/devalloc.h>
 
 #define	MAX_AUDIO_LINK 100
 #define	RE_SIZE 64
 
+extern int system_labeled;
+
 static void check_audio_link(char *secondary_link,
 				const char *primary_link_format);
 static int audio_process(di_minor_t minor, di_node_t node);
@@ -117,6 +119,7 @@
 static int
 audio_process(di_minor_t minor, di_node_t node)
 {
+	int flags = 0;
 	char path[PATH_MAX + 1];
 	char *buf;
 	char *mn;
@@ -209,7 +212,10 @@
 		return (DEVFSADM_CONTINUE);
 	}
 
-	(void) devfsadm_mklink(path, node, minor, 0);
+	if (system_labeled)
+		flags = DA_ADD|DA_AUDIO;
+
+	(void) devfsadm_mklink(path, node, minor, flags);
 	return (DEVFSADM_CONTINUE);
 }
 
@@ -219,17 +225,21 @@
 {
 	char primary_link[PATH_MAX + 1];
 	int i;
+	int flags = 0;
 
 	/* if link is present, return */
 	if (devfsadm_link_valid(secondary_link) == DEVFSADM_TRUE) {
 		return;
 	}
 
+	if (system_labeled)
+		flags = DA_ADD|DA_AUDIO;
+
 	for (i = 0; i < MAX_AUDIO_LINK; i++) {
 		(void) sprintf(primary_link, primary_link_format, i);
 		if (devfsadm_link_valid(primary_link) == DEVFSADM_TRUE) {
 			(void) devfsadm_secondary_link(secondary_link,
-						primary_link, 0);
+						primary_link, flags);
 			break;
 		}
 	}
diff --git a/usr/src/cmd/devfsadm/devalloc.c b/usr/src/cmd/devfsadm/devalloc.c
new file mode 100644
index 0000000..413d617
--- /dev/null
+++ b/usr/src/cmd/devfsadm/devalloc.c
@@ -0,0 +1,253 @@
+/*
+ * 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"
+
+/*
+ * Device allocation related work.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/dkio.h>
+#include <sys/wait.h>
+#include <bsm/devalloc.h>
+
+#define	DEALLOCATE	 "/usr/sbin/deallocate"
+#define	MKDEVALLOC	"/usr/sbin/mkdevalloc"
+
+static void _update_dev(deventry_t *, int, char *);
+static int _make_db();
+
+
+/*
+ * _da_check_for_usb
+ *	returns 1 if device pointed by 'link' is a removable hotplugged
+ *	else returns 0.
+ */
+int
+_da_check_for_usb(char *link, char *root_dir)
+{
+	int		fd = -1;
+	int		len, dstsize;
+	int		removable = 0;
+	char		*p = NULL;
+	char		path[MAXPATHLEN];
+
+	dstsize = sizeof (path);
+	if (strcmp(root_dir, "") != 0) {
+		if (strlcat(path, root_dir, dstsize) >= dstsize)
+			return (0);
+		len = strlen(path);
+	} else {
+		len = 0;
+	}
+	if (strstr(link, "rdsk")) {
+		(void) snprintf(path, dstsize - len, "%s", link);
+	} else if (strstr(link, "dsk")) {
+		p = rindex(link, '/');
+		if (p == NULL)
+			return (0);
+		p++;
+		(void) snprintf(path, dstsize - len, "%s%s", "/dev/rdsk/", p);
+	} else {
+		return (0);
+	}
+
+	if ((fd = open(path, O_RDONLY | O_NONBLOCK)) < 0)
+		return (0);
+	(void) ioctl(fd, DKIOCREMOVABLE, &removable);
+	(void) close(fd);
+
+	return (removable);
+}
+
+/*
+ * _reset_devalloc
+ *	If device allocation is being turned on, creates device_allocate
+ *	device_maps if they do not exist.
+ *	Puts DEVICE_ALLOCATION=ON/OFF in device_allocate to indicate if
+ *	device allocation is on/off.
+ */
+void
+_reset_devalloc(int action)
+{
+	da_args	dargs;
+
+	if (action == DA_ON)
+		(void) _make_db();
+	else if ((action == DA_OFF) && (open(DEVALLOC, O_RDONLY) == -1))
+		return;
+
+	if (action == DA_ON)
+		dargs.optflag = DA_ON;
+	else if (action == DA_OFF)
+		dargs.optflag = DA_OFF | DA_ALLOC_ONLY;
+
+	dargs.rootdir = NULL;
+	dargs.devnames = NULL;
+	dargs.devinfo = NULL;
+
+	(void) da_update_device(&dargs);
+}
+
+/*
+ * _make_db
+ *	execs /usr/sbin/mkdevalloc to create device_allocate and
+ *	device_maps.
+ */
+static int
+_make_db()
+{
+	int	status;
+	pid_t	pid, wpid;
+
+	pid = vfork();
+	switch (pid) {
+	case -1:
+		return (1);
+	case 0:
+		if (execl(MKDEVALLOC, MKDEVALLOC, DA_IS_LABELED, NULL) == -1)
+			exit((errno == ENOENT) ? 0 : 1);
+	default:
+		for (;;) {
+			wpid = waitpid(pid, &status, 0);
+			if (wpid == (pid_t)-1) {
+				if (errno == EINTR)
+					continue;
+				else
+					return (1);
+			} else {
+				break;
+			}
+		}
+		break;
+	}
+
+	return ((WIFEXITED(status) == 0) ? 1 : WEXITSTATUS(status));
+}
+
+
+/*
+ * _update_devalloc_db
+ * 	Forms allocatable device entries to be written to device_allocate and
+ *	device_maps.
+ */
+/* ARGSUSED */
+void
+_update_devalloc_db(devlist_t *devlist, int devflag, int action, char *devname,
+    char *root_dir)
+{
+	int		i;
+	deventry_t	*entry = NULL, *dentry = NULL;
+
+	if (action == DA_ADD) {
+		for (i = 0; i < DA_COUNT; i++) {
+			switch (i) {
+			case 0:
+				dentry = devlist->audio;
+				break;
+			case 1:
+				dentry = devlist->cd;
+				break;
+			case 2:
+				dentry = devlist->floppy;
+				break;
+			case 3:
+				dentry = devlist->tape;
+				break;
+			case 4:
+				dentry = devlist->rmdisk;
+				break;
+			default:
+				return;
+			}
+			if (dentry)
+				_update_dev(dentry, action, NULL);
+		}
+	} else if (action == DA_REMOVE) {
+		if (devflag & DA_AUDIO)
+			dentry = devlist->audio;
+		else if (devflag & DA_CD)
+			dentry = devlist->cd;
+		else if (devflag & DA_FLOPPY)
+			dentry = devlist->floppy;
+		else if (devflag & DA_TAPE)
+			dentry = devlist->tape;
+		else if (devflag & DA_RMDISK)
+			dentry = devlist->rmdisk;
+		else
+			return;
+
+		for (entry = dentry; entry != NULL; entry = entry->next) {
+			if (strcmp(entry->devinfo.devname, devname) == 0)
+				break;
+		}
+		_update_dev(entry, action, devname);
+	}
+}
+
+static void
+_update_dev(deventry_t *dentry, int action, char *devname)
+{
+	da_args		dargs;
+	deventry_t	newentry, *entry;
+
+	dargs.rootdir = NULL;
+	dargs.devnames = NULL;
+
+	if (action == DA_ADD) {
+		dargs.optflag = DA_ADD | DA_FORCE;
+		for (entry = dentry; entry != NULL; entry = entry->next) {
+			dargs.devinfo = &(entry->devinfo);
+			(void) da_update_device(&dargs);
+		}
+	} else if (action == DA_REMOVE) {
+		dargs.optflag = DA_REMOVE;
+		if (dentry) {
+			entry = dentry;
+		} else {
+			newentry.devinfo.devname = strdup(devname);
+			newentry.devinfo.devtype =
+			newentry.devinfo.devauths =
+			newentry.devinfo.devexec =
+			newentry.devinfo.devopts =
+			newentry.devinfo.devlist = NULL;
+			newentry.devinfo.instance = 0;
+			newentry.next = NULL;
+			entry = &newentry;
+		}
+		dargs.devinfo = &(entry->devinfo);
+		(void) da_update_device(&dargs);
+	}
+}
diff --git a/usr/src/cmd/devfsadm/devfsadm.c b/usr/src/cmd/devfsadm/devfsadm.c
index 75ed42f..c390479 100644
--- a/usr/src/cmd/devfsadm/devfsadm.c
+++ b/usr/src/cmd/devfsadm/devfsadm.c
@@ -36,10 +36,18 @@
  * reconfiguration for hotplugging support.
  */
 
-#include "devfsadm_impl.h"
+#include <string.h>
+#include <tsol/label.h>
+#include <bsm/devices.h>
+#include <bsm/devalloc.h>
 #include <utime.h>
+#include "devfsadm_impl.h"
 
-/* globals */
+/* externs from devalloc.c */
+
+extern void  _reset_devalloc(int);
+extern void _update_devalloc_db(devlist_t *, int, int, char *, char *);
+extern int _da_check_for_usb(char *, char *);
 
 /* create or remove nodes or links. unset with -n */
 static int file_mods = TRUE;
@@ -50,12 +58,26 @@
 /* devlinks -d compatibility */
 static int devlinks_debug = FALSE;
 
-/* turn off device allocation with devfsadm -d */
-static int devalloc_off = FALSE;
+/* flag to check if system is labeled */
+int system_labeled = FALSE;
 
-/* devices to be deallocated with -d */
-static char *devalloc[5] =
-	{DDI_NT_AUDIO, DDI_NT_CD, DDI_NT_FD, DDI_NT_TAPE, NULL};
+/* flag to enable/disable device allocation with -e/-d */
+static int devalloc_flag = 0;
+
+/* flag to update device allocation database for this device type */
+static int update_devdb = 0;
+
+/*
+ * devices to be deallocated with -d :
+ *	audio, floppy, cd, floppy, tape, rmdisk.
+ */
+static char *devalloc_list[10] = {DDI_NT_AUDIO, DDI_NT_CD, DDI_NT_CD_CHAN,
+				    DDI_NT_FD, DDI_NT_TAPE, DDI_NT_BLOCK_CHAN,
+				    DDI_NT_UGEN, DDI_NT_USB_ATTACHMENT_POINT,
+				    DDI_NT_SCSI_NEXUS, NULL};
+
+/* list of allocatable devices */
+static devlist_t devlist;
 
 /* load a single driver only.  set with -i */
 static int single_drv = FALSE;
@@ -210,6 +232,7 @@
 int
 main(int argc, char *argv[])
 {
+	struct stat tx_stat;
 	struct passwd *pw;
 	struct group *gp;
 	pid_t pid;
@@ -251,10 +274,26 @@
 
 	(void) umask(0);
 
+	system_labeled = is_system_labeled();
+	if (system_labeled == FALSE) {
+		/*
+		 * is_system_labeled() will return false in case we are
+		 * starting before the first reboot after Trusted Extensions
+		 * is installed. we check for a well known TX binary to
+		 * to see if TX is installed.
+		 */
+		if (stat(DA_LABEL_CHECK, &tx_stat) == 0)
+			system_labeled = TRUE;
+	}
+
 	parse_args(argc, argv);
 
 	(void) sema_init(&dev_sema, 1, USYNC_THREAD, NULL);
 
+	/* Initialize device allocation list */
+	devlist.audio = devlist.cd = devlist.floppy = devlist.tape =
+	devlist.rmdisk = NULL;
+
 	if (daemon_mode == TRUE) {
 		/*
 		 * Build /dev and /devices before daemonizing if
@@ -311,7 +350,6 @@
 				(void) rcm_init();
 				login_dev_enable = TRUE;
 			}
-
 			daemon_update();
 		} else {
 			err_print(DAEMON_RUNNING, pid);
@@ -322,6 +360,9 @@
 	} else {
 		/* not a daemon, so just build /dev and /devices */
 		process_devinfo_tree();
+		if (devalloc_flag != 0)
+			/* Enable/disable device allocation */
+			_reset_devalloc(devalloc_flag);
 	}
 	return (0);
 }
@@ -607,7 +648,7 @@
 		devlinktab_file = DEVLINKTAB_FILE;
 
 		while ((opt = getopt(argc, argv,
-		    "Cc:dIi:l:np:PR:r:st:vV:x:z:Z:")) != EOF) {
+		    "Cc:deIi:l:np:PR:r:st:vV:x:z:Z:")) != EOF) {
 			if (opt == 'I' || opt == 'P') {
 				if (public_mode)
 					usage();
@@ -626,9 +667,21 @@
 						    sizeof (char *));
 				classes[num_classes - 1] = optarg;
 				break;
-			case  'd':
+			case 'd':
 				if (daemon_mode == FALSE) {
-					devalloc_off = TRUE;
+					/*
+					 * Device allocation to be disabled.
+					 */
+					devalloc_flag = DA_OFF;
+					build_dev = FALSE;
+				}
+				break;
+			case 'e':
+				if (daemon_mode == FALSE) {
+					/*
+					 * Device allocation to be enabled.
+					 */
+					devalloc_flag = DA_ON;
 					build_dev = FALSE;
 				}
 				break;
@@ -909,6 +962,12 @@
 	if ((dcip->dci_flags & DCA_NOTIFY_RCM) && rcm_hdl)
 		(void) notify_rcm(node, dcip->dci_minor);
 
+	/* Add new device to device allocation database */
+	if (system_labeled && update_devdb) {
+		_update_devalloc_db(&devlist, 0, DA_ADD, NULL, root_dir);
+		update_devdb = 0;
+	}
+
 	di_fini(node);
 }
 
@@ -986,7 +1045,7 @@
 
 	} else if (load_attach_drv == TRUE) {
 		/*
-		 * load and attach all drivers, then walk the entire tree.
+		 * Load and attach all drivers, then walk the entire tree.
 		 * If the cache flag is set, use DINFOCACHE to get cached
 		 * data.
 		 */
@@ -2825,11 +2884,33 @@
 	    == DEVFSADM_SUCCESS) {
 		linknew = TRUE;
 		add_link_to_cache(link, acontents);
+		if (system_labeled && (flags & DA_ADD)) {
+			/*
+			 * Add this device to the list of allocatable devices.
+			 */
+			int	instance = di_instance(node);
+
+			(void) da_add_list(&devlist, devlink, instance, flags);
+			update_devdb = flags;
+		}
 	} else {
 		linknew = FALSE;
 	}
 
 	if (link_exists == TRUE) {
+		if (system_labeled && (flags & DA_CD)) {
+			/*
+			 * if this is a removable disk, add it
+			 * as that to device allocation database.
+			 */
+			if (_da_check_for_usb(devlink, root_dir) == 1) {
+				int instance = di_instance(node);
+
+				(void) da_add_list(&devlist, devlink, instance,
+				    DA_ADD|DA_RMDISK);
+				update_devdb = DA_RMDISK;
+			}
+		}
 		/* Link exists or was just created */
 		(void) di_devlink_add_link(devlink_cache, link, rcontents,
 		    DI_PRIMARY_LINK);
@@ -2935,6 +3016,19 @@
 		 */
 		add_link_to_cache(link, lphy_path);
 		linknew = TRUE;
+		if (system_labeled &&
+		    ((flags & DA_AUDIO) && (flags & DA_ADD))) {
+			/*
+			 * Add this device to the list of allocatable devices.
+			 */
+			int	instance = 0;
+
+			op = strrchr(contents, '/');
+			op++;
+			(void) sscanf(op, "%d", &instance);
+			(void) da_add_list(&devlist, devlink, instance, flags);
+			update_devdb = flags;
+		}
 	} else {
 		linknew = FALSE;
 	}
@@ -3228,6 +3322,7 @@
 static void
 reset_node_permissions(di_node_t node, di_minor_t minor)
 {
+	int devalloc_is_on = 0;
 	int spectype;
 	char phy_path[PATH_MAX + 1];
 	mode_t mode;
@@ -3281,32 +3376,52 @@
 	}
 
 	/*
-	 * If we are here for deactivating device allocation, set
-	 * default permissions. Otherwise, set default permissions
-	 * only if this is a new device because we want to preserve
-	 * modified user permissions.
-	 * Devfs indicates a new device by faking an access time
-	 * of zero.
+	 * If we are here for a new device
+	 *	If device allocation is on
+	 *	then
+	 *		set ownership to root:other and permissions to 0000
+	 *	else
+	 *		set ownership and permissions as specified in minor_perm
+	 * If we are here for an existing device
+	 *	If device allocation is to be turned on
+	 *	then
+	 *		reset ownership to root:other and permissions to 0000
+	 *	else if device allocation is to be turned off
+	 *		reset ownership and permissions to those specified in
+	 *		minor_perm
+	 *	else
+	 *		preserve exsisting/user-modified ownership and
+	 *		permissions
+	 *
+	 * devfs indicates a new device by faking access time to be zero.
 	 */
+	devalloc_is_on = da_is_on();
 	if (sb.st_atime != 0) {
 		int  i;
 		char *nt;
 
-		if (devalloc_off == FALSE)
+		if ((devalloc_flag == 0) && (devalloc_is_on != 1))
+			/*
+			 * Leave existing devices as they are if we are not
+			 * turning device allocation on/off.
+			 */
 			return;
 
 		nt = di_minor_nodetype(minor);
+
 		if (nt == NULL)
 			return;
-		for (i = 0; devalloc[i]; i++) {
-			if (strcmp(nt, devalloc[i]) == 0)
+
+		for (i = 0; devalloc_list[i]; i++) {
+			if (strcmp(nt, devalloc_list[i]) == 0)
+				/*
+				 * One of the types recognized by devalloc,
+				 * reset attrs.
+				 */
 				break;
 		}
-
-		if (devalloc[i] == NULL)
+		if (devalloc_list[i] == NULL)
 			return;
-
-		/* One of the types recognized by devalloc, reset perms */
 	}
 
 	if (file_mods == FALSE) {
@@ -3315,12 +3430,24 @@
 		return;
 	}
 
-	if (sb.st_mode != mode) {
+	if ((devalloc_flag == DA_ON) || (devalloc_is_on == 1)) {
+		/*
+		 * we are here either to turn device allocation on
+		 * or to add a new device while device allocation in on
+		 */
+		mode = DEALLOC_MODE;
+		uid = DA_UID;
+		gid = DA_GID;
+	}
+
+	if ((devalloc_is_on == 1) || (devalloc_flag == DA_ON) ||
+	    (sb.st_mode != mode)) {
 		if (chmod(phy_path, mode) == -1)
 			vprint(VERBOSE_MID, CHMOD_FAILED,
 			    phy_path, strerror(errno));
 	}
-	if (sb.st_uid != uid || sb.st_gid != gid) {
+	if ((devalloc_is_on == 1) || (devalloc_flag == DA_ON) ||
+	    (sb.st_uid != uid || sb.st_gid != gid)) {
 		if (chown(phy_path, uid, gid) == -1)
 			vprint(VERBOSE_MID, CHOWN_FAILED,
 			    phy_path, strerror(errno));
@@ -4483,6 +4610,27 @@
 		}
 	}
 
+	/* update device allocation database */
+	if (system_labeled) {
+		int	ret = 0;
+		int	devtype = 0;
+		char	devname[MAXNAMELEN];
+
+		devname[0] = '\0';
+		if (strstr(node_path, DA_SOUND_NAME))
+			devtype = DA_AUDIO;
+		else if (strstr(node_path, "disk"))
+			devtype = DA_RMDISK;
+		else
+			goto out;
+		ret = da_remove_list(&devlist, NULL, devtype, devname,
+		    sizeof (devname));
+		if (ret != -1)
+			(void) _update_devalloc_db(&devlist, devtype, DA_REMOVE,
+			    devname, root_dir);
+	}
+
+out:
 	/* now log an event */
 	if (nvl) {
 		log_event(EC_DEV_REMOVE, ev_subclass, nvl);
@@ -4610,8 +4758,9 @@
 devfsadm_link_valid(char *link)
 {
 	struct stat sb;
-	char devlink[PATH_MAX + 1], *contents;
+	char devlink[PATH_MAX + 1], *contents = NULL;
 	int rv, type;
+	int instance = 0;
 
 	/* prepend link with dev_dir contents */
 	(void) strcpy(devlink, dev_dir);
@@ -4634,6 +4783,13 @@
 	 * The link exists. Add it to the database
 	 */
 	(void) di_devlink_add_link(devlink_cache, link, contents, type);
+	if (system_labeled && (rv == DEVFSADM_TRUE) &&
+	    strstr(devlink, DA_AUDIO_NAME) && contents) {
+		(void) sscanf(contents, "%*[a-z]%d", &instance);
+		(void) da_add_list(&devlist, devlink, instance,
+		    DA_ADD|DA_AUDIO);
+		_update_devalloc_db(&devlist, 0, DA_ADD, NULL, root_dir);
+	}
 	free(contents);
 
 	return (rv);
diff --git a/usr/src/cmd/devfsadm/disk_link.c b/usr/src/cmd/devfsadm/disk_link.c
index 57805e6..f12f9cf 100644
--- a/usr/src/cmd/devfsadm/disk_link.c
+++ b/usr/src/cmd/devfsadm/disk_link.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -32,6 +31,7 @@
 #include <stdlib.h>
 #include <limits.h>
 #include <sys/stat.h>
+#include <bsm/devalloc.h>
 
 #define	DISK_SUBPATH_MAX 100
 #define	RM_STALE 0x01
@@ -46,6 +46,8 @@
 #define	MN_EFI		"wd"
 #define	ASCIIWWNSIZE	255
 
+extern int system_labeled;
+
 static int disk_callback_chan(di_minor_t minor, di_node_t node);
 static int disk_callback_nchan(di_minor_t minor, di_node_t node);
 static int disk_callback_wwn(di_minor_t minor, di_node_t node);
@@ -209,6 +211,8 @@
 	char slice[4];
 	char *mn;
 	char *ctrl;
+	char *nt = NULL;
+	int  nflags = 0;
 
 	if (strstr(mn = di_minor_name(minor), ",raw")) {
 		dir = "rdsk";
@@ -255,7 +259,17 @@
 	}
 	(void) strcat(l_path, slice);
 
-	(void) devfsadm_mklink(l_path, node, minor, 0);
+	if (system_labeled) {
+		nt = di_minor_nodetype(minor);
+		if ((nt != NULL) &&
+		    ((strcmp(nt, DDI_NT_CD) == 0) ||
+		    (strcmp(nt, DDI_NT_CD_CHAN) == 0) ||
+		    (strcmp(nt, DDI_NT_BLOCK_CHAN) == 0))) {
+			nflags = DA_ADD|DA_CD;
+		}
+	}
+
+	(void) devfsadm_mklink(l_path, node, minor, nflags);
 
 	if ((flags & RM_STALE) == RM_STALE) {
 		(void) strcpy(stale_re, "^");
diff --git a/usr/src/cmd/devfsadm/i386/misc_link_i386.c b/usr/src/cmd/devfsadm/i386/misc_link_i386.c
index 484214d..1e40053 100644
--- a/usr/src/cmd/devfsadm/i386/misc_link_i386.c
+++ b/usr/src/cmd/devfsadm/i386/misc_link_i386.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -34,6 +33,9 @@
 #include <limits.h>
 #include <ctype.h>
 #include <sys/mc.h>
+#include <bsm/devalloc.h>
+
+extern int system_labeled;
 
 static int lp(di_minor_t minor, di_node_t node);
 static int serial_dialout(di_minor_t minor, di_node_t node);
@@ -151,16 +153,20 @@
 static int
 diskette(di_minor_t minor, di_node_t node)
 {
+	int flags = 0;
 	char *a2;
 	char link[PATH_MAX];
 	char *addr = di_bus_addr(node);
 	char *mn = di_minor_name(minor);
 
+	if (system_labeled)
+		flags = DA_ADD|DA_FLOPPY;
+
 	if (strcmp(addr, "0,0") == 0) {
 		if (strcmp(mn, "c") == 0) {
-			(void) devfsadm_mklink("diskette", node, minor, 0);
+			(void) devfsadm_mklink("diskette", node, minor, flags);
 		} else if (strcmp(mn, "c,raw") == 0) {
-			(void) devfsadm_mklink("rdiskette", node, minor, 0);
+			(void) devfsadm_mklink("rdiskette", node, minor, flags);
 		}
 
 	}
@@ -171,11 +177,13 @@
 			if (strcmp(mn, "c") == 0) {
 				(void) strcpy(link, "diskette");
 				(void) strcat(link, a2);
-				(void) devfsadm_mklink(link, node, minor, 0);
+				(void) devfsadm_mklink(link, node, minor,
+				    flags);
 			} else if (strcmp(mn, "c,raw") == 0) {
 				(void) strcpy(link, "rdiskette");
 				(void) strcat(link, a2);
-				(void) devfsadm_mklink(link, node, minor, 0);
+				(void) devfsadm_mklink(link, node, minor,
+				    flags);
 			}
 		}
 	}
diff --git a/usr/src/cmd/devfsadm/sparc/misc_link_sparc.c b/usr/src/cmd/devfsadm/sparc/misc_link_sparc.c
index ee2c059..0d0aa69 100644
--- a/usr/src/cmd/devfsadm/sparc/misc_link_sparc.c
+++ b/usr/src/cmd/devfsadm/sparc/misc_link_sparc.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -33,6 +32,9 @@
 #include <stdlib.h>
 #include <limits.h>
 #include <sys/mkdev.h>
+#include <bsm/devalloc.h>
+
+extern int system_labeled;
 
 static int node_name(di_minor_t minor, di_node_t node);
 
@@ -123,14 +125,19 @@
 static int
 diskette(di_minor_t minor, di_node_t node)
 {
-	char *mn = di_minor_name(minor);
+	int	flags = 0;
+	char	*mn = di_minor_name(minor);
+
+	if (system_labeled)
+		flags = DA_ADD|DA_FLOPPY;
+
 	if (strcmp(mn, "c") == 0) {
-		(void) devfsadm_mklink("diskette", node, minor, 0);
-		(void) devfsadm_mklink("diskette0", node, minor, 0);
+		(void) devfsadm_mklink("diskette", node, minor, flags);
+		(void) devfsadm_mklink("diskette0", node, minor, flags);
 
 	} else if (strcmp(mn, "c,raw") == 0) {
-		(void) devfsadm_mklink("rdiskette", node, minor, 0);
-		(void) devfsadm_mklink("rdiskette0", node, minor, 0);
+		(void) devfsadm_mklink("rdiskette", node, minor, flags);
+		(void) devfsadm_mklink("rdiskette0", node, minor, flags);
 
 	}
 	return (DEVFSADM_CONTINUE);
diff --git a/usr/src/cmd/devfsadm/tape_link.c b/usr/src/cmd/devfsadm/tape_link.c
index 2aae4a4..cd532d2 100644
--- a/usr/src/cmd/devfsadm/tape_link.c
+++ b/usr/src/cmd/devfsadm/tape_link.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -30,7 +29,9 @@
 #include <strings.h>
 #include <stdlib.h>
 #include <limits.h>
+#include <bsm/devalloc.h>
 
+extern int system_labeled;
 
 static int tape_process(di_minor_t minor, di_node_t node);
 
@@ -60,6 +61,7 @@
 static int
 tape_process(di_minor_t minor, di_node_t node)
 {
+	int flags = 0;
 	char l_path[PATH_MAX + 1];
 	char *buf;
 	char *mn;
@@ -98,7 +100,10 @@
 	(void) strcat(l_path, mn);
 	free(buf);
 
-	(void) devfsadm_mklink(l_path, node, minor, 0);
+	if (system_labeled)
+		flags = DA_ADD|DA_TAPE;
+
+	(void) devfsadm_mklink(l_path, node, minor, flags);
 
 	return (DEVFSADM_CONTINUE);
 }
diff --git a/usr/src/cmd/devfsadm/usb_link.c b/usr/src/cmd/devfsadm/usb_link.c
index 53f0380..5012d8a 100644
--- a/usr/src/cmd/devfsadm/usb_link.c
+++ b/usr/src/cmd/devfsadm/usb_link.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,7 +18,7 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -210,6 +209,7 @@
 	char *l_path, *p_path, *buf, *devfspath;
 	char *minor_nm, *drvr_nm, *name = (char *)NULL;
 	int i, index;
+	int flags = 0;
 	int create_secondary_link = 0;
 
 	minor_nm = di_minor_name(minor);
@@ -345,7 +345,7 @@
 
 	devfsadm_print(debug_mid, "mklink %s -> %s\n", l_path, p_path);
 
-	(void) devfsadm_mklink(l_path, node, minor, 0);
+	(void) devfsadm_mklink(l_path, node, minor, flags);
 
 	if (create_secondary_link) {
 		/*
@@ -376,6 +376,7 @@
 	char ugen_RE[128];
 	devfsadm_enumerate_t ugen_rules[1];
 	char l_path[PATH_MAX];
+	int flags = 0;
 
 	devfsadm_print(debug_mid, "ugen_create_link: p_path=%s name=%s\n",
 	    p_path, node_name);
@@ -418,7 +419,7 @@
 
 	devfsadm_print(debug_mid, "mklink %s -> %s\n", l_path, p_path);
 
-	(void) devfsadm_mklink(l_path, node, minor, 0);
+	(void) devfsadm_mklink(l_path, node, minor, flags);
 
 	free(buf);
 }
diff --git a/usr/src/cmd/fs.d/autofs/auto_subr.c b/usr/src/cmd/fs.d/autofs/auto_subr.c
index 28f8cf5..c92eef6 100644
--- a/usr/src/cmd/fs.d/autofs/auto_subr.c
+++ b/usr/src/cmd/fs.d/autofs/auto_subr.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
  * CDDL HEADER END
  */
 /*
- * Copyright (c) 1988-1999 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
  */
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -54,6 +53,9 @@
 #include <rpcsvc/nfs_prot.h>
 #include <assert.h>
 #include "automount.h"
+#include <zone.h>
+#include <priv.h>
+#include <fcntl.h>
 
 static char *check_hier(char *);
 static int natisa(char *, size_t);
@@ -62,9 +64,111 @@
 
 static bool_t nodirect_map = FALSE;
 
+/*
+ * If the system is labeled then we need to
+ * have a uniquely-named auto_home map for each zone.
+ * The maps are made unique by appending the zonename.
+ * The home directory is made unique by prepending /zone/<zonename>
+ * for each zone that is dominated by the current zone.
+ * The current zone's home directory mount point is not changed.
+ *
+ * For each auto_home_<zonename> a default template map is created
+ * only if it doesn't exist yet. The default entry is used to declare
+ * local home directories created within each zone. For example:
+ *
+ *	+auto_home_public
+ *      * -fstype=lofs :/zone/public/export/home/&
+ */
+static void
+loadzone_maps(char *mntpnt, char *map, char *opts, char **stack, char ***stkptr)
+{
+	zoneid_t *zids = NULL;
+	zoneid_t my_zoneid;
+	uint_t nzents_saved;
+	uint_t nzents;
+	int i;
+
+	if (!priv_ineffect(PRIV_SYS_MOUNT))
+		return;
+
+	if (zone_list(NULL, &nzents) != 0) {
+		return;
+	}
+	my_zoneid = getzoneid();
+again:
+	if (nzents == 0)
+		return;
+
+	zids = malloc(nzents * sizeof (zoneid_t));
+	nzents_saved = nzents;
+
+	if (zone_list(zids, &nzents) != 0) {
+		free(zids);
+		return;
+	}
+	if (nzents != nzents_saved) {
+		/* list changed, try again */
+		free(zids);
+		goto again;
+	}
+
+	for (i = 0; i < nzents; i++) {
+		char zonename[ZONENAME_MAX];
+		char zoneroot[MAXPATHLEN];
+
+		if (getzonenamebyid(zids[i], zonename, ZONENAME_MAX) != -1) {
+			char appended_map[MAXPATHLEN];
+			char prepended_mntpnt[MAXPATHLEN];
+			char map_path[MAXPATHLEN];
+			int fd;
+
+			(void) snprintf(appended_map, sizeof (appended_map),
+			    "%s_%s", map, zonename);
+
+			/* for current zone, leave mntpnt alone */
+			if (zids[i] != my_zoneid) {
+				(void) snprintf(prepended_mntpnt,
+				    sizeof (prepended_mntpnt),
+				    "/zone/%s%s", zonename, mntpnt);
+				if (zone_getattr(zids[i], ZONE_ATTR_ROOT,
+				    zoneroot, sizeof (zoneroot)) == -1)
+					continue;
+			} else {
+				(void) strcpy(prepended_mntpnt, mntpnt);
+				zoneroot[0] = '\0';
+			}
+
+			dirinit(prepended_mntpnt, appended_map, opts, 0, stack,
+			    stkptr);
+			/*
+			 * Next create auto_home_<zone> maps for each zone
+			 */
+
+			(void) snprintf(map_path, sizeof (map_path),
+			    "/etc/%s", appended_map);
+			/*
+			 * If the map file doesn't exist create a template
+			 */
+			if ((fd = open(map_path, O_RDWR | O_CREAT | O_EXCL,
+			    S_IRUSR | S_IWUSR | S_IRGRP| S_IROTH)) != -1) {
+				int len;
+				char map_rec[MAXPATHLEN];
+
+				len = snprintf(map_rec, sizeof (map_rec),
+				    "+%s\n*\t-fstype=lofs\t:%s/export/home/&\n",
+				    appended_map, zoneroot);
+				if (len <= sizeof (map_rec))
+					(void) write(fd, map_rec, len);
+				(void) close(fd);
+			}
+		}
+	}
+	free(zids);
+}
+
 void
 dirinit(char *mntpnt, char *map, char *opts, int direct, char **stack,
-	char ***stkptr)
+    char ***stkptr)
 {
 	struct autodir *dir;
 	char *p;
@@ -97,6 +201,16 @@
 		return;
 	}
 
+	/*
+	 * Home directories are polyinstantiated on
+	 * labeled systems.
+	 */
+	if (is_system_labeled() &&
+	    (strcmp(mntpnt, "/home") == 0) &&
+	    (strcmp(map, "auto_home") == 0)) {
+		(void) loadzone_maps(mntpnt, map, opts, stack, stkptr);
+		return;
+	}
 enter:
 	dir = (struct autodir *)malloc(sizeof (*dir));
 	if (dir == NULL)
diff --git a/usr/src/cmd/fs.d/autofs/autod_lookup.c b/usr/src/cmd/fs.d/autofs/autod_lookup.c
index a4abbbe..a70541b 100644
--- a/usr/src/cmd/fs.d/autofs/autod_lookup.c
+++ b/usr/src/cmd/fs.d/autofs/autod_lookup.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -22,7 +21,7 @@
 /*
  *	autod_lookup.c
  *
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -61,10 +60,6 @@
 	char *stack[STACKSIZ];
 	char **stkptr = stack;
 
-#ifdef lint
-	path = path;
-#endif /* lint */
-
 	/*
 	 * Default action is for no work to be done by kernel AUTOFS.
 	 */
diff --git a/usr/src/cmd/fs.d/autofs/autod_main.c b/usr/src/cmd/fs.d/autofs/autod_main.c
index 7bcf02d..ce57a1f 100644
--- a/usr/src/cmd/fs.d/autofs/autod_main.c
+++ b/usr/src/cmd/fs.d/autofs/autod_main.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -56,7 +55,8 @@
 #include <rpcsvc/daemon_utils.h>
 #include <deflt.h>
 #include <strings.h>
-
+#include <priv.h>
+#include <tsol/label.h>
 
 static void autofs_prog(struct svc_req *, SVCXPRT *);
 static void autofs_mount_1_r(struct autofs_lookupargs *,
@@ -322,6 +322,14 @@
 	/* other initializations */
 	(void) rwlock_init(&portmap_cache_lock, USYNC_THREAD, NULL);
 
+	/* on a labeled system, the automounter implements read-down policy */
+	if (is_system_labeled()) {
+		if ((setpflags(NET_MAC_AWARE, 1) == -1) ||
+		    (setpflags(NET_MAC_AWARE_INHERIT, 1) == -1))
+			syslog(LOG_ERR, "ignored failure to set MAC-aware "
+			    "mode: %m");
+	}
+
 	if (!rpc_control(RPC_SVC_MTMODE_SET, &rpc_svc_mode)) {
 		syslog(LOG_ERR, "unable to set automatic MT mode");
 		exit(1);
diff --git a/usr/src/cmd/fs.d/autofs/autod_nfs.c b/usr/src/cmd/fs.d/autofs/autod_nfs.c
index dc5cf60..741eba3 100644
--- a/usr/src/cmd/fs.d/autofs/autod_nfs.c
+++ b/usr/src/cmd/fs.d/autofs/autod_nfs.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -81,6 +80,10 @@
 #include <net/if.h>
 #include <assert.h>
 #include <rpcsvc/daemon_utils.h>
+#include <pwd.h>
+#include <strings.h>
+#include <tsol/label.h>
+#include <zone.h>
 
 extern char *nfs_get_qop_name();
 extern AUTH *nfs_create_ah();
@@ -145,6 +148,8 @@
 	struct netconfig **, char *, ushort_t, struct t_info *, caddr_t *,
 	bool_t, char *);
 
+static int create_homedir(const char *, const char *);
+
 enum type_of_stuff {
 	SERVER_ADDR = 0,
 	SERVER_PING = 1,
@@ -416,7 +421,6 @@
 	struct mapfs **mfs_tail)
 {
 	struct mapfs *tmp, *new;
-	void bcopy();
 
 	for (tmp = *mfs_head; tmp; tmp = tmp->mfs_next)
 		if ((strcmp(tmp->mfs_host, mfs->mfs_host) == 0 &&
@@ -1990,7 +1994,19 @@
 		    } /* syncaddr */
 		} /* AUTH_DH */
 
-		nfs_sec.sc_uid = cred->aup_uid;
+		/*
+		 * TSOL notes: automountd in tsol extension
+		 * has "read down" capability, i.e. we allow
+		 * a user to trigger an nfs mount into a lower
+		 * labeled zone. We achieve this by always having
+		 * root issue the mount request so that the
+		 * lookup ops can go past /zone/<zone_name>
+		 * on the server side.
+		 */
+		if (is_system_labeled())
+			nfs_sec.sc_uid = (uid_t)0;
+		else
+			nfs_sec.sc_uid = cred->aup_uid;
 		/*
 		 * If AUTH_DH is a chosen flavor now, its data will be stored
 		 * in the sec_data structure via nfs_clnt_secdata().
@@ -2253,7 +2269,7 @@
 		else
 			sl = service_list;
 
-		_check_services(sl);
+		(void) _check_services(sl);
 	}
 
 	/*
@@ -3598,6 +3614,13 @@
 			"  loopbackmount: fsname=%s, dir=%s, flags=%d\n",
 			fsname, dir, flags);
 
+	if (is_system_labeled()) {
+		if (create_homedir((const char *)fsname,
+		    (const char *)dir) == 0) {
+			return (NFSERR_NOENT);
+		}
+	}
+
 	if (mount(fsname, dir, flags | MS_DATA | MS_OPTIONSTR, fstype,
 	    NULL, 0, optbuf, sizeof (optbuf)) < 0) {
 		syslog(LOG_ERR, "Mount of %s on %s: %m", fsname, dir);
@@ -4214,3 +4237,78 @@
 
 	return (FALSE);
 }
+
+static int
+create_homedir(const char *src, const char *dst) {
+
+	struct stat stbuf;
+	char *dst_username;
+	struct passwd *pwd, pwds;
+	char buf_pwd[NSS_BUFLEN_PASSWD];
+	int homedir_len;
+	int dst_dir_len;
+	int src_dir_len;
+
+	if (trace > 1)
+		trace_prt(1, "entered create_homedir\n");
+
+	if (stat(src, &stbuf) == 0) {
+		if (trace > 1)
+			trace_prt(1, "src exists\n");
+		return (1);
+	}
+
+	dst_username = strrchr(dst, '/');
+	if (dst_username) {
+		dst_username++; /* Skip over slash */
+		pwd = getpwnam_r(dst_username, &pwds, buf_pwd,
+		    sizeof (buf_pwd));
+		if (pwd == NULL) {
+			return (0);
+		}
+	} else {
+		return (0);
+	}
+
+	homedir_len = strlen(pwd->pw_dir);
+	dst_dir_len = strlen(dst) - homedir_len;
+	src_dir_len = strlen(src) - homedir_len;
+
+	/* Check that the paths are in the same zone */
+	if (src_dir_len < dst_dir_len ||
+	    (strncmp(dst, src, dst_dir_len) != 0)) {
+		if (trace > 1)
+			trace_prt(1, "	paths don't match\n");
+		return (0);
+	}
+	/* Check that mountpoint is an auto_home entry */
+	if (dst_dir_len < 0 ||
+	    (strcmp(pwd->pw_dir, dst + dst_dir_len) != 0)) {
+		return (0);
+	}
+
+	/* Check that source is an home directory entry */
+	if (src_dir_len < 0 ||
+	    (strcmp(pwd->pw_dir, src + src_dir_len) != 0)) {
+		if (trace > 1)
+			trace_prt(1, "	homedir (2) doesn't match %s\n",
+		src+src_dir_len);
+		return (0);
+	}
+
+	if (mkdir(src,
+	    S_IRUSR | S_IWUSR | S_IXUSR | S_IXGRP | S_IXOTH) == -1) {
+		if (trace > 1) {
+			trace_prt(1, "	Couldn't mkdir %s\n", src);
+		}
+		return (0);
+	}
+
+	if (chown(src, pwd->pw_uid, pwd->pw_gid) == -1) {
+		unlink(src);
+		return (0);
+	}
+
+	/* Created new home directory for the user */
+	return (1);
+}
diff --git a/usr/src/cmd/fs.d/nfs/lib/nfs_tbind.c b/usr/src/cmd/fs.d/nfs/lib/nfs_tbind.c
index 358b4f5..b761e47 100644
--- a/usr/src/cmd/fs.d/nfs/lib/nfs_tbind.c
+++ b/usr/src/cmd/fs.d/nfs/lib/nfs_tbind.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -51,6 +50,9 @@
 #include <nfs/nfs_acl.h>
 #include <nfs/nfssys.h>
 #include <nfs/nfs4.h>
+#include <zone.h>
+#include <sys/socket.h>
+#include <tsol/label.h>
 
 /*
  * Determine valid semantics for most applications.
@@ -93,6 +95,8 @@
  */
 static	int	nofile_increase(int);
 static	int	reuseaddr(int);
+static	int	recvucred(int);
+static  int	anonmlp(int);
 static	void	add_to_poll_list(int, struct netconfig *);
 static	char	*serv_name_to_port_name(char *);
 static	int	bind_to_proto(char *, char *, struct netbuf **,
@@ -234,6 +238,7 @@
 	struct opthdr *opt;
 	char reqbuf[128];
 	bool_t use_any = FALSE;
+	bool_t gzone = TRUE;
 
 	if ((fd = nfslib_transport_open(nconf)) == -1) {
 		syslog(LOG_ERR, "cannot establish transport service over %s",
@@ -250,7 +255,7 @@
 		tb.addr.len = 0;
 		tb.addr.buf = 0;
 		use_any = TRUE;
-
+		gzone = (getzoneid() == GLOBAL_ZONEID);
 	} else if (netdir_getbyname(nconf, hs, &addrlist) != 0) {
 
 		syslog(LOG_ERR,
@@ -273,6 +278,31 @@
 			syslog(LOG_WARNING,
 			"couldn't set SO_REUSEADDR option on transport");
 		}
+	} else if (strcmp(nconf->nc_proto, "udp") == 0) {
+		/*
+		 * In order to run MLP on UDP, we need to handle creds.
+		 */
+		if (recvucred(fd) == -1) {
+			syslog(LOG_WARNING,
+			    "couldn't set SO_RECVUCRED option on transport");
+		}
+	}
+
+	/*
+	 * Make non global zone nfs4_callback port MLP
+	 */
+	if (use_any && is_system_labeled() && !gzone) {
+		if (anonmlp(fd) == -1) {
+			/*
+			 * failing to set this option means nfs4_callback
+			 * could fail silently later. So fail it with
+			 * with an error message now.
+			 */
+			syslog(LOG_ERR,
+			    "couldn't set SO_ANON_MLP option on transport");
+			(void) t_close(fd);
+			return (-1);
+		}
 	}
 
 	if (nconf->nc_semantics == NC_TPI_CLTS)
@@ -364,29 +394,26 @@
 }
 
 static int
-reuseaddr(int fd)
+setopt(int fd, int level, int name, int value)
 {
 	struct t_optmgmt req, resp;
-	struct opthdr *opt;
-	char reqbuf[128];
-	int *ip;
+	struct {
+		struct opthdr opt;
+		int value;
+	} reqbuf;
 
-	/* LINTED pointer alignment */
-	opt = (struct opthdr *)reqbuf;
-	opt->level = SOL_SOCKET;
-	opt->name = SO_REUSEADDR;
-	opt->len = sizeof (int);
+	reqbuf.opt.level = level;
+	reqbuf.opt.name = name;
+	reqbuf.opt.len = sizeof (int);
 
-	/* LINTED pointer alignment */
-	ip = (int *)&reqbuf[sizeof (struct opthdr)];
-	*ip = 1;
+	reqbuf.value = value;
 
 	req.flags = T_NEGOTIATE;
-	req.opt.len = sizeof (struct opthdr) + opt->len;
-	req.opt.buf = (char *)opt;
+	req.opt.len = sizeof (reqbuf);
+	req.opt.buf = (char *)&reqbuf;
 
 	resp.flags = 0;
-	resp.opt.buf = reqbuf;
+	resp.opt.buf = (char *)&reqbuf;
 	resp.opt.maxlen = sizeof (reqbuf);
 
 	if (t_optmgmt(fd, &req, &resp) < 0 || resp.flags != T_SUCCESS) {
@@ -396,6 +423,24 @@
 	return (0);
 }
 
+static int
+reuseaddr(int fd)
+{
+	return (setopt(fd, SOL_SOCKET, SO_REUSEADDR, 1));
+}
+
+static int
+recvucred(int fd)
+{
+	return (setopt(fd, SOL_SOCKET, SO_RECVUCRED, 1));
+}
+
+static int
+anonmlp(int fd)
+{
+	return (setopt(fd, SOL_SOCKET, SO_ANON_MLP, 1));
+}
+
 void
 nfslib_log_tli_error(char *tli_name, int fd, struct netconfig *nconf)
 {
diff --git a/usr/src/cmd/fs.d/nfs/mountd/mountd.c b/usr/src/cmd/fs.d/nfs/mountd/mountd.c
index dda4b78..2ae1d1e 100644
--- a/usr/src/cmd/fs.d/nfs/mountd/mountd.c
+++ b/usr/src/cmd/fs.d/nfs/mountd/mountd.c
@@ -112,6 +112,7 @@
 	int maxthreads;
 	int maxrecsz = RPC_MAXDATASIZE;
 	bool_t exclbind = TRUE;
+	bool_t can_do_mlp;
 
 	/*
 	 * Mountd requires uid 0 for:
@@ -123,10 +124,13 @@
 	 *		auditing
 	 *		nfs syscall
 	 *		file dac search (so it can stat all files)
+	 *	Optional privileges:
+	 *		MLP
 	 */
+	can_do_mlp = priv_ineffect(PRIV_NET_BINDMLP);
 	if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, -1, -1,
-		    PRIV_SYS_NFS, PRIV_PROC_AUDIT, PRIV_FILE_DAC_SEARCH,
-		    (char *)NULL) == -1) {
+	    PRIV_SYS_NFS, PRIV_PROC_AUDIT, PRIV_FILE_DAC_SEARCH,
+	    can_do_mlp ? PRIV_NET_BINDMLP : NULL, NULL) == -1) {
 		(void) fprintf(stderr,
 			"%s must be run as with sufficient privileges\n",
 			argv[0]);
@@ -788,6 +792,19 @@
 	}
 
 	/*
+	 * Trusted Extension doesn't support older versions of nfs(v2, v3).
+	 * To prevent circumventing TX label policy via using an older
+	 * version of nfs client, reject the mount request and log an
+	 * error.
+	 */
+	if (is_system_labeled()) {
+		syslog(LOG_ERR,
+		    "mount rejected: Solaris TX only supports nfs4 clients");
+		error = EACCES;
+		goto reply;
+	}
+
+	/*
 	 * Get the real path (no symbolic links in it)
 	 */
 	if (realpath(path, rpath) == NULL) {
diff --git a/usr/src/cmd/fs.d/nfs/nfsd/nfsd.c b/usr/src/cmd/fs.d/nfs/nfsd/nfsd.c
index 791fad6..818552f 100644
--- a/usr/src/cmd/fs.d/nfs/nfsd/nfsd.c
+++ b/usr/src/cmd/fs.d/nfs/nfsd/nfsd.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -137,6 +136,7 @@
 	NETSELDECL(df_proto) = NULL;
 	NETSELPDECL(providerp);
 	char *defval;
+	boolean_t can_do_mlp;
 
 	MyName = *av;
 
@@ -146,8 +146,10 @@
 	(void) _create_daemon_lock(NFSD, DAEMON_UID, DAEMON_GID);
 	svcsetprio();
 
+	can_do_mlp = priv_ineffect(PRIV_NET_BINDMLP);
 	if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET,
-	    DAEMON_UID, DAEMON_GID, PRIV_SYS_NFS, (char *)NULL) == -1) {
+	    DAEMON_UID, DAEMON_GID, PRIV_SYS_NFS,
+	    can_do_mlp ? PRIV_NET_BINDMLP : NULL, NULL) == -1) {
 		(void) fprintf(stderr, "%s should be run with"
 			" sufficient privileges\n", av[0]);
 		exit(1);
diff --git a/usr/src/cmd/fs.d/nfs/statd/sm_svc.c b/usr/src/cmd/fs.d/nfs/statd/sm_svc.c
index f90ec07..a3dca0c 100644
--- a/usr/src/cmd/fs.d/nfs/statd/sm_svc.c
+++ b/usr/src/cmd/fs.d/nfs/statd/sm_svc.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -671,9 +670,10 @@
  */
 
 static void
-set_statmon_owner()
+set_statmon_owner(void)
 {
 	int i;
+	boolean_t can_do_mlp;
 
 	/*
 	 * Recursively chown/chgrp /var/statmon and the alternate paths,
@@ -687,8 +687,10 @@
 		one_statmon_owner(alt_path);
 	}
 
+	can_do_mlp = priv_ineffect(PRIV_NET_BINDMLP);
 	if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET,
-	    DAEMON_UID, DAEMON_GID, (char *)NULL) == -1) {
+	    DAEMON_UID, DAEMON_GID, can_do_mlp ? PRIV_NET_BINDMLP : NULL,
+	    NULL) == -1) {
 		syslog(LOG_ERR, "can't run unprivileged: %m");
 		exit(1);
 	}
diff --git a/usr/src/cmd/ldap/Makefile.com b/usr/src/cmd/ldap/Makefile.com
index 824788f..d65d341 100644
--- a/usr/src/cmd/ldap/Makefile.com
+++ b/usr/src/cmd/ldap/Makefile.com
@@ -1,4 +1,24 @@
 #
+# 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.
 #
@@ -33,7 +53,7 @@
 
 # ldapaddent command
 LDAPADDENTPROG=	ldapaddent
-LDAPADDENTSRCS=	ldapaddent.c ldapaddrbac.c
+LDAPADDENTSRCS=	ldapaddent.c ldapaddrbac.c ldapaddtsol.c
 LDAPADDENTOBJS=	$(LDAPADDENTSRCS:%.c=%.o)
 
 # ldapclient command
@@ -74,7 +94,7 @@
 lint:=          TARGET= lint
 
 # C Pre-Processor flags used by C, CC & lint
-CPPFLAGS +=	-DSUN -DSVR4 -D_SYS_STREAM_H -DSOLARIS_LDAP_CMD \
+CPPFLAGS +=	-DSUN -DSVR4 -DSOLARIS_LDAP_CMD \
 		-I ../../../lib/libldap5/include/ldap \
 		-I ../../../lib/libsldap/common \
 		-I ../../../lib/libnsl/include/rpcsvc \
@@ -87,7 +107,7 @@
 ldapdelete :=	LDLIBS += -lldap
 ldapmodify :=	LDLIBS += -lldap
 ldaplist :=	LDLIBS += -lsldap
-ldapaddent :=	LDLIBS += -lsldap -lnsl
+ldapaddent :=	LDLIBS += -lsldap -lnsl -lsecdb
 ldapclient :=	LDLIBS += -lsldap -lscf
 
 lint :=		LDLIBS += -lldap
diff --git a/usr/src/cmd/ldap/ns_ldap/idsconfig.sh b/usr/src/cmd/ldap/ns_ldap/idsconfig.sh
index 645dfb7..485c5f9 100644
--- a/usr/src/cmd/ldap/ns_ldap/idsconfig.sh
+++ b/usr/src/cmd/ldap/ns_ldap/idsconfig.sh
@@ -1,11 +1,12 @@
 #!/bin/sh
 #
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -21,11 +22,9 @@
 # CDDL HEADER END
 #
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 # idsconfig -- script to setup iDS 5.x for Native LDAP II.
 #
-# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
@@ -3146,6 +3145,8 @@
 attributetypes:( 1.3.6.1.4.1.42.2.27.5.1.63 NAME 'sun-printer-bsdaddr' DESC 'Sets the server, print queue destination name and whether the client generates protocol extensions. "Solaris" specifies a Solaris print server extension. The value is represented by the following value: server "," destination ", Solaris".' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
 attributetypes:( 1.3.6.1.4.1.42.2.27.5.1.64 NAME 'sun-printer-kvp' DESC 'This attribute contains a set of key value pairs which may have meaning to the print subsystem or may be user defined. Each value is represented by the following: key "=" value.' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )
 attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.57 NAME 'nisplusTimeZone' DESC 'tzone column from NIS+ timezone table' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributetypes:( 1.3.6.1.4.1.42.2.27.5.1.67 NAME 'ipTnetTemplateName' DESC 'Trusted Solaris network template template_name' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributetypes:( 1.3.6.1.4.1.42.2.27.5.1.68 NAME 'ipTnetNumber' DESC 'Trusted Solaris network template ip_address' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
 EOF
 ) > ${TMPDIR}/schema_attr
 
@@ -3291,6 +3292,16 @@
 changetype: modify
 add: objectclasses
 objectclasses:	( 1.3.6.1.4.1.42.2.27.5.2.12 NAME 'nisplusTimeZoneData' DESC 'NIS+ timezone table data' SUP top STRUCTURAL MUST ( cn ) MAY ( nisplusTimeZone $ description ) )
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectclasses:  ( 1.3.6.1.4.1.42.2.27.5.2.8 NAME 'ipTnetTemplate' DESC 'Object class for TSOL network templates' SUP 'top' MUST ( objectclass $ ipTnetTemplateName ) MAY ( SolarisAttrKeyValue ) )
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectclasses:	( 1.3.6.1.4.1.42.2.27.5.2.9 NAME 'ipTnetHost' DESC 'Associates an IP address or wildcard with a TSOL template_name' SUP 'top' AUXILIARY MUST ( objectclass $ ipTnetNumber ) )
 EOF
 ) > ${TMPDIR}/schema_obj
 
@@ -3612,7 +3623,7 @@
 
     for ou in people group rpc protocols networks netgroup \
 	aliases hosts services ethers profile printers \
-	SolarisAuthAttr SolarisProfAttr Timezone ; do
+	SolarisAuthAttr SolarisProfAttr Timezone ipTnet ; do
 
 	# Check if nismaps already exist.
 	eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"ou=${ou},${LDAP_BASEDN}\" -s base \"objectclass=*\" ${VERB}"
diff --git a/usr/src/cmd/ldap/ns_ldap/ldapaddent.c b/usr/src/cmd/ldap/ns_ldap/ldapaddent.c
index a5d420e..7b30890 100644
--- a/usr/src/cmd/ldap/ns_ldap/ldapaddent.c
+++ b/usr/src/cmd/ldap/ns_ldap/ldapaddent.c
@@ -3572,6 +3572,10 @@
 		filedbmline_comment, "SolarisAuthAttr" },
 	{ NS_LDAP_TYPE_AUUSER, genent_audit_user, dump_audit_user,
 		filedbmline_comment, "SolarisAuditUser" },
+	{ NS_LDAP_TYPE_TNRHDB, genent_tnrhdb, dump_tnrhdb,
+		filedbmline_comment, "ipTnetHost" },
+	{ NS_LDAP_TYPE_TNRHTP, genent_tnrhtp, dump_tnrhtp,
+		filedbmline_comment, "ipTnetTemplate" },
 	{ 0, 0, 0, 0, 0 }
 };
 
@@ -3641,9 +3645,17 @@
 		(void) snprintf(filter, sizeof (filter),
 		    "(&(objectclass=%s)(!(objectclass=SolarisExecAttr)))",
 		    tt->objclass);
-	} else
+	} else if (strcmp(tt->ttype, NS_LDAP_TYPE_TNRHDB) == 0) {
+		/*
+		 * tnrhtp entries are ipTnet entries with SolarisAttrKeyValue
+		 */
+		(void) snprintf(filter, sizeof (filter),
+		    "(&(objectclass=%s)(SolarisAttrKeyValue=*)))",
+		    tt->objclass);
+	} else {
 		(void) snprintf(filter, sizeof (filter),
 		    "(objectclass=%s)", tt->objclass);
+	}
 
 	if (flags & F_VERBOSE)
 		(void) fprintf(stdout, gettext("FILTER = %s\n"), filter);
diff --git a/usr/src/cmd/ldap/ns_ldap/ldapaddent.h b/usr/src/cmd/ldap/ns_ldap/ldapaddent.h
index 6da82f1..42973d2 100644
--- a/usr/src/cmd/ldap/ns_ldap/ldapaddent.h
+++ b/usr/src/cmd/ldap/ns_ldap/ldapaddent.h
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -76,11 +75,16 @@
 extern int genent_exec_attr(char *line, int (*cback)());
 extern int genent_auth_attr(char *line, int (*cback)());
 extern int genent_audit_user(char *line, int (*cback)());
+extern int genent_tnrhdb(char *line, int (*cback)());
+extern int genent_tnrhtp(char *line, int (*cback)());
+
 extern void dump_user_attr(ns_ldap_result_t *res);
 extern void dump_prof_attr(ns_ldap_result_t *res);
 extern void dump_exec_attr(ns_ldap_result_t *res);
 extern void dump_auth_attr(ns_ldap_result_t *res);
 extern void dump_audit_user(ns_ldap_result_t *res);
+extern void dump_tnrhdb(ns_ldap_result_t *res);
+extern void dump_tnrhtp(ns_ldap_result_t *res);
 
 #ifdef	__cplusplus
 }
diff --git a/usr/src/cmd/ldap/ns_ldap/ldapaddrbac.c b/usr/src/cmd/ldap/ns_ldap/ldapaddrbac.c
index 04da2f7..63c065e 100644
--- a/usr/src/cmd/ldap/ns_ldap/ldapaddrbac.c
+++ b/usr/src/cmd/ldap/ns_ldap/ldapaddrbac.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -66,7 +65,7 @@
  * genent_attr:
  *   Generic function for generating entries for all of the *_attr databases.
  */
-static int
+int
 genent_attr(
 	char	*line,		/* entry to parse */
 	int	ncol,		/* number of columns in the database */
diff --git a/usr/src/cmd/ldap/ns_ldap/ldapaddtsol.c b/usr/src/cmd/ldap/ns_ldap/ldapaddtsol.c
new file mode 100644
index 0000000..985a859
--- /dev/null
+++ b/usr/src/cmd/ldap/ns_ldap/ldapaddtsol.c
@@ -0,0 +1,142 @@
+/*
+ * 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"
+
+/*
+ * ldapaddtsol.c
+ *
+ * Routines to add tnrhdb and tnrhtp from /etc/security/tsol into LDAP.
+ * Can also be used to dump entries from a ldap container in /etc format.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <libintl.h>
+#include <string.h>
+#include <nss.h>
+#include <secdb.h>
+#include <sys/tsol/tndb.h>
+#include "ldapaddent.h"
+
+extern  int	genent_attr(char *, int, entry_col **);
+
+int
+genent_tnrhdb(char *line, int (*cback)())
+{
+	entry_col	*ecol;
+	tsol_rhstr_t	data;
+	int		res, retval;
+
+	/*
+	 * parse entry into columns
+	 */
+	res = genent_attr(line, TNRHDB_NCOL, &ecol);
+	if (res != GENENT_OK)
+		return (res);
+
+	data.address = _do_unescape(ecol[0].ec_value.ec_value_val);
+	data.template = ecol[1].ec_value.ec_value_val;
+	if (strchr(data.address, ':') == NULL)
+		data.family = AF_INET;
+	else
+		data.family = AF_INET6;
+
+	if (flags & F_VERBOSE)
+		(void) printf(gettext("Adding entry : %s\n"), data.address);
+
+	retval = (*cback)(&data, 1);
+	if (retval)
+		res = GENENT_CBERR;
+
+	free(ecol);
+
+	return (res);
+}
+
+void
+dump_tnrhdb(ns_ldap_result_t *res)
+{
+	char	**value = NULL;
+
+	value = __ns_ldap_getAttr(res->entry, "ipTnetNumber");
+	if (value && value[0])
+		(void) printf("%s", value[0]);
+	else
+		return;
+
+	(void) putchar(':');
+	value = __ns_ldap_getAttr(res->entry, "ipTnetTemplateName");
+	if (value && value[0])
+		(void) printf("%s", value[0]);
+	(void) putchar('\n');
+}
+
+int
+genent_tnrhtp(char *line, int (*cback)())
+{
+	entry_col	*ecol;
+	tsol_tpstr_t	data;
+	int		res, retval;
+
+	/*
+	 * parse entry into columns
+	 */
+	res = genent_attr(line, TNRHTP_NCOL, &ecol);
+	if (res != GENENT_OK)
+		return (res);
+
+	data.template = ecol[0].ec_value.ec_value_val;
+	data.attrs = ecol[1].ec_value.ec_value_val;
+
+	if (flags & F_VERBOSE)
+		(void) printf(gettext("Adding entry : %s\n"), data.template);
+
+	retval = (*cback)(&data, 1);
+	if (retval)
+		res = GENENT_CBERR;
+
+	free(ecol);
+
+	return (res);
+}
+
+void
+dump_tnrhtp(ns_ldap_result_t *res)
+{
+	char	**value = NULL;
+
+	value = __ns_ldap_getAttr(res->entry, "ipTnetTemplateName");
+	if (value && value[0])
+		(void) printf("%s", value[0]);
+	else
+		return;
+
+	(void) putchar(':');
+	value = __ns_ldap_getAttr(res->entry, "SolarisAttrKeyValue");
+	if (value && value[0])
+		(void) printf("%s", value[0]);
+	(void) putchar('\n');
+}
diff --git a/usr/src/cmd/ldap/ns_ldap/mapping.c b/usr/src/cmd/ldap/ns_ldap/mapping.c
index 57827c6..470ca20 100644
--- a/usr/src/cmd/ldap/ns_ldap/mapping.c
+++ b/usr/src/cmd/ldap/ns_ldap/mapping.c
@@ -18,6 +18,7 @@
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
@@ -29,6 +30,7 @@
 #include <libintl.h>
 #include <strings.h>
 #include <stdio.h>
+#include <tsol/label.h>
 #include "../../../lib/libsldap/common/ns_sldap.h"
 
 
@@ -67,6 +69,8 @@
 	{"exec_attr", "cn", "SolarisExecAttr", NULL},
 	{"user_attr", "uid", "SolarisUserAttr", NULL},
 	{"audit_user", "uid", "SolarisAuditUser", NULL},
+	{"tnrhtp", "ipTnetTemplateName", "ipTnetTemplate", NULL},
+	{"tnrhdb", "ipTnetNumber", "ipTnetHost", NULL},
 	{NULL, NULL, NULL, NULL}
 };
 
@@ -112,10 +116,20 @@
 		"automountMapName",
 		"automountMap");
 	for (i = 0; maplist[i].database != NULL; i++) {
-	/* skip printing shadow */
-	if (strcasecmp(maplist[i].database, "shadow") != 0)
+		/* skip printing shadow */
+		if (strcasecmp(maplist[i].database, "shadow") == 0)
+			continue;
+		if (!is_system_labeled()) {
+			/*
+			 * do not print tnrhdb and tnrhtp if system is
+			 * not configured with Trusted Extensions
+			 */
+			if ((strcasecmp(maplist[i].database, "tnrhdb") == 0) ||
+			    (strcasecmp(maplist[i].database, "tnrhtp") == 0))
+				continue;
+		}
 		(void) fprintf(stdout, "%-15s%-20s%s\n", maplist[i].database,
-			maplist[i].def_type, maplist[i].objectclass);
+		    maplist[i].def_type, maplist[i].objectclass);
 	}
 }
 
diff --git a/usr/src/cmd/lp/cmd/Makefile b/usr/src/cmd/lp/cmd/Makefile
index 9bffdde..2a50a58 100644
--- a/usr/src/cmd/lp/cmd/Makefile
+++ b/usr/src/cmd/lp/cmd/Makefile
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -18,11 +17,13 @@
 # information: Portions Copyright [yyyy] [name of copyright owner]
 #
 # CDDL HEADER END
+
+
 #
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
 #
-# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # cmd/lp/cmd/Makefile
@@ -69,12 +70,14 @@
 cancel:=	LDLIBS += $(LIBREQ) $(LIBMSG) $(LIBOAM) $(LIBLP)
 lp:=		LDLIBS += $(LIBPRT) $(LIBREQ) $(LIBMSG) $(LIBOAM) $(LIBLP)
 lpfilter:=	LDLIBS += $(LIBFLT) $(LIBMSG) $(LIBACC) $(LIBOAM) $(LIBLP) \
-			-lgen
+			-lgen -z lazyload -lsecdb -z nolazyload
 lpforms:=	LDLIBS += $(LIBFRM) $(LIBMSG) $(LIBREQ) $(LIBOAM) \
-		$(LIBACC) $(LIBLP)
+			$(LIBACC) $(LIBLP) \
+			-z lazyload -lsecdb -z nolazyload
 lpmove:=	LDLIBS += $(LIBMSG) $(LIBACC) $(LIBOAM) $(LIBLP)
 lpshut:=	LDLIBS += $(LIBMSG) $(LIBOAM) $(LIBLP)
-lpsystem:=	LDLIBS += $(LIBSYS) $(LIBMSG) $(LIBOAM) $(LIBLP) -lnsl
+lpsystem:=	LDLIBS += $(LIBSYS) $(LIBMSG) $(LIBACC) $(LIBOAM) $(LIBLP) \
+			-lnsl -z lazyload -lsecdb -z nolazyload
 lpusers:=	LDLIBS += $(LIBMSG) $(LIBACC) $(LIBOAM) $(LIBUSR) $(LIBLP)
 
 .KEEP_STATE:
diff --git a/usr/src/cmd/lp/cmd/adaptor/Makefile b/usr/src/cmd/lp/cmd/adaptor/Makefile
index 5fc1aad..f7d7d75 100644
--- a/usr/src/cmd/lp/cmd/adaptor/Makefile
+++ b/usr/src/cmd/lp/cmd/adaptor/Makefile
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -18,9 +17,11 @@
 # information: Portions Copyright [yyyy] [name of copyright owner]
 #
 # CDDL HEADER END
+
+
 #
 #
-# Copyright 1996-2003 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -38,7 +39,7 @@
 
 CPPFLAGS +=	-I$(LPINC)
 CPPFLAGS +=	-I$(SRC)/lib
-LDLIBS +=	-lprint -lc
+LDLIBS +=	-lprint -z lazyload -ltsol -z nolazyload -lc
 LDLIBS	+=	-L$(SRC)/cmd/lp/lib/msgs -llpmsg
 LDLIBS	+=	-L$(SRC)/cmd/lp/lib/class -llpcls
 LDLIBS	+=	-L$(SRC)/cmd/lp/lib/lp -llp
diff --git a/usr/src/cmd/lp/cmd/adaptor/cancel_job.c b/usr/src/cmd/lp/cmd/adaptor/cancel_job.c
index 6ee2368..7ffa9af 100644
--- a/usr/src/cmd/lp/cmd/adaptor/cancel_job.c
+++ b/usr/src/cmd/lp/cmd/adaptor/cancel_job.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -83,7 +82,6 @@
 	return (buf);
 }
 
-
 /*
  * lpsched_cancel_job() attempts to cancel an lpsched requests that match the
  * passed in criteria.  a message is written for each cancelation or
@@ -123,12 +121,12 @@
 		size_t	size;
 		time_t	date;
 		short	outcome;
-		char *dest, *form, *pwheel, *file, *owner, *reqid;
+		char *dest, *slabel, *form, *pwheel, *file, *owner, *reqid;
 		const char **list_ptr = list;
 		char buf[BUFSIZ];
 
-		if (rcv_msg(R_INQUIRE_REQUEST, &status, &reqid, &owner, &size,
-				&date, &outcome, &dest, &form, &pwheel,
+		if (rcv_msg(R_INQUIRE_REQUEST, &status, &reqid, &owner, &slabel,
+				&size, &date, &outcome, &dest, &form, &pwheel,
 				&file) < 0) {
 			fprintf(ofp,
 			gettext("Failure to communicate with lpsched\n"));
diff --git a/usr/src/cmd/lp/cmd/adaptor/misc.c b/usr/src/cmd/lp/cmd/adaptor/misc.c
index 75bec08..e4959df 100644
--- a/usr/src/cmd/lp/cmd/adaptor/misc.c
+++ b/usr/src/cmd/lp/cmd/adaptor/misc.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -39,6 +38,8 @@
 
 #include <syslog.h>
 
+#include <tsol/label.h>
+
 #include "misc.h"
 
 /* lpsched include files */
@@ -48,7 +49,6 @@
 
 static char Msg[MSGMAX];
 
-
 /*
  * Format and send message to lpsched
  * (die if any errors occur)
@@ -216,15 +216,32 @@
  * has access to communicate with the scheduler.  In Solaris this currently
  * has no meaning.  The host is automatically allowed access.
  */
+char *slabel = NULL;
+
 int
-lpsched_client_access(const char *printer, const char *host)
+lpsched_client_access(const char *printer, const char *host, int peerfd)
 {
-	syslog(LOG_DEBUG, "lpsched_client_access(%s, %s)",
-		(printer ? printer : "NULL"), (host ? host : "NULL"));
+	syslog(LOG_DEBUG, "lpsched_client_access(%s, %s, %d)",
+		(printer ? printer : "NULL"), (host ? host : "NULL"),
+		peerfd);
 
 	if ((printer == NULL) || (host == NULL))
 		return (-1);
 
+	if (is_system_labeled) {
+		short status = MOK;
+		extern MESG *lp_Md;	/* liblpmsg supplies this */
+
+		if ((snd_msg(S_PASS_PEER_CONNECTION) < 0) ||
+		    (ioctl(lp_Md->writefd, I_SENDFD, peerfd) < 0) ||
+		    (rcv_msg(R_PASS_PEER_CONNECTION, &status) < 0))
+			status = MTRANSMITERR;
+		if (status != MOK)
+			return (-1);
+
+		get_peer_label(peerfd, &slabel);
+	}
+
 	return (0);
 }
 
diff --git a/usr/src/cmd/lp/cmd/adaptor/misc.h b/usr/src/cmd/lp/cmd/adaptor/misc.h
index 24b8d7f..f475468 100644
--- a/usr/src/cmd/lp/cmd/adaptor/misc.h
+++ b/usr/src/cmd/lp/cmd/adaptor/misc.h
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
  * CDDL HEADER END
  */
 /*
- * Copyright (c) 1996, by Sun Microsystems, Inc.
- * All Rights Reserved
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
  */
 
 #ident	"%Z%%M%	%I%	%E% SMI"
@@ -34,5 +33,6 @@
 extern int id_no(const char *);
 extern char *user_name(const char *);
 extern char *user_host(const char *);
+extern char *slabel;
 
 #endif /* _MISC_H */
diff --git a/usr/src/cmd/lp/cmd/adaptor/show_queue.c b/usr/src/cmd/lp/cmd/adaptor/show_queue.c
index 04867c6..4ed83ba 100644
--- a/usr/src/cmd/lp/cmd/adaptor/show_queue.c
+++ b/usr/src/cmd/lp/cmd/adaptor/show_queue.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 1995-2002 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -160,8 +159,8 @@
 #define	HEADER gettext("Rank\tOwner\tJob\tFile(s)\t\t\t\tTotal Size\n")
 
 static int
-job_list(const char *printer, FILE *ofp, const int type, const char **list,
-		const char *status_message, int *rank)
+job_list(const char *printer, FILE *ofp, const int type,
+    const char **list, const char *status_message, int *rank)
 {
 	int count = 0;
 	short status, outcome;
@@ -173,10 +172,11 @@
 		size_t size;
 		time_t date;
 		int id;
-		char *user, *reqid, *owner, *dest, *form, *pwheel, *file, *host;
+		char *user, *slabel, *reqid, *owner, *dest, *form, *pwheel,
+			*file, *host;
 
-		if (rcv_msg(R_INQUIRE_REQUEST, &status, &reqid, &owner, &size,
-				&date, &outcome, &dest, &form, &pwheel,
+		if (rcv_msg(R_INQUIRE_REQUEST, &status, &reqid, &owner, &slabel,
+				&size, &date, &outcome, &dest, &form, &pwheel,
 				&file) < 0)
 			return (count);
 
@@ -215,6 +215,7 @@
 	return (count);
 }
 
+
 /*
  * lpsched_show_queue() attempts to display the queue of "pending" jobs.  The
  * "type" is used to determine if this should be a short or long format
diff --git a/usr/src/cmd/lp/cmd/adaptor/submit_job.c b/usr/src/cmd/lp/cmd/adaptor/submit_job.c
index d3bf04d..ac6ad66 100644
--- a/usr/src/cmd/lp/cmd/adaptor/submit_job.c
+++ b/usr/src/cmd/lp/cmd/adaptor/submit_job.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
  * CDDL HEADER END
  */
 /*
- * Copyright (c) 1995-1999,2001 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
  */
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -31,15 +30,21 @@
 #include <unistd.h>
 #include <ctype.h>
 #include <sys/types.h>
+#include <sys/zone.h>
 #include <string.h>
 #include <libintl.h>
 
 #include <syslog.h>
 #include <stdarg.h>
 
+#include <tsol/label.h>
+
 #include "misc.h"
 
 /* lpsched include files */
+#if defined PS_FAULTED
+#undef  PS_FAULTED
+#endif /* PS_FAULTED */
 #include "lp.h"
 #include "msgs.h"
 #include "printers.h"
@@ -85,11 +90,11 @@
 	}
 }
 
-
 /*
  * mail() will send a mail message to the requesting user in the event of an
  * error during job submission.
  */
+
 static void
 mail(REQUEST *request, char *req_file, char *fmt, ...)
 {
@@ -97,6 +102,7 @@
 	char buf[BUFSIZ];
 	char *uname;
 	va_list ap;
+	char	*mail_zonename = NULL;
 
 	/*
 	 * Clean-up user name so we don't pass flags to /bin/mail, or
@@ -110,27 +116,59 @@
 	if (*uname == '\0')
 		return;		/* No username found */
 
-	snprintf(buf, sizeof (buf), "/bin/mail %s", uname);
+	/*
+	 * If in the global zone and the system is labeled, mail is
+	 * handled via a local labeled zone that is the same label as the
+	 * request.
+	 */
+	if ((getzoneid() == GLOBAL_ZONEID) && is_system_labeled() &&
+	    slabel != NULL) {
+		if ((mail_zonename = get_labeled_zonename(slabel)) ==
+		    (char *)-1) {
+			/* error during get_labeled_zonename, just return */
+			return;
+		}
+	}
+
+	/*
+	 * If mail_zonename is not NULL, use zlogin to execute /bin/mail
+	 * in the labeled zone 'mail_zonename'.
+	 */
+
+	if (mail_zonename != NULL) {
+		syslog(LOG_DEBUG,
+		    "lpsched: using '/usr/sbin/zlogin %s /bin/mail %s' to mail",
+		    mail_zonename, uname);
+		snprintf(buf, sizeof (buf),
+		    "/usr/sbin/zlogin %s /bin/mail %s",
+		    mail_zonename, uname);
+		Free(mail_zonename);
+	} else {
+		syslog(LOG_DEBUG,
+		    "lpsched: using '/bin/mail %s' to mail",
+		    uname);
+		snprintf(buf, sizeof (buf), "/bin/mail %s", uname);
+	}
 	clean_string(buf);
 	if ((pp = popen(buf, "w+")) == NULL)
 		return;
 	fprintf(pp, gettext("Subject: print request for %s failed\n\n"),
-		request->destination);
+	    request->destination);
 
 	fprintf(pp, gettext("\n\tRequest File: %s"), req_file);
 	fprintf(pp, gettext("\n\tDocument Type: %s"),
-		(request->input_type ? request->input_type :
-			gettext("(unknown)")));
+	    (request->input_type ? request->input_type :
+	    gettext("(unknown)")));
 	fprintf(pp, gettext("\n\tTitle:\t%s"),
-		(request->title ? request->title : gettext("(none)")));
+	    (request->title ? request->title : gettext("(none)")));
 	fprintf(pp, gettext("\n\tCopies:\t%d"), request->copies);
 	fprintf(pp, gettext("\n\tPriority:\t%d"), request->priority);
 	fprintf(pp, gettext("\n\tForm:\t%s"),
-		(request->form ? request->form : gettext("(none)")));
+	    (request->form ? request->form : gettext("(none)")));
 	fprintf(pp, gettext("\n\tOptions:\t%s"),
-		(request->options ? request->options : gettext("(none)")));
+	    (request->options ? request->options : gettext("(none)")));
 	fprintf(pp, gettext("\n\tModes:\t%s"),
-		(request->modes ? request->modes : gettext("(none)")));
+	    (request->modes ? request->modes : gettext("(none)")));
 
 	fprintf(pp, gettext("\n\tReason for Failure:\n\n\t\t"));
 	va_start(ap, fmt);
@@ -505,7 +543,7 @@
 	char	buf[MAXPATHLEN];
 	int	file_no = 0;
 	int	rc = -1;
-	char 	*tmp_dir = (char *)lpsched_temp_dir(printer, host);
+	char 	*tmp_dir;
 	char  *tmp;
 	short status;
 	long  bits;
@@ -515,6 +553,8 @@
 	syslog(LOG_DEBUG, "lpsched_submit_job(%s, %s, 0x%x)",
 		(printer ? printer : "NULL"), (cf ? cf : "NULL"), df_list);
 
+	tmp_dir = (char *)lpsched_temp_dir(printer, host);
+
 	if ((printer == NULL) || (host == NULL) || (cf == NULL) ||
 	    (df_list == NULL))
 		return (-1);
@@ -558,18 +598,21 @@
 	secure.req_id = strdup(buf);
 	secure.uid = LP_UID;
 	secure.gid = 0;
+	secure.slabel = NULL;
 
 	/* save the request file */
 	snprintf(buf, sizeof (buf), "%s/%d-0", host, request_id);
 	if (putrequest(buf, request) < 0) {
-		mail(request, buf, gettext("Can't save print request"));
+		mail(request, buf,
+		    gettext("Can't save print request"));
 		unlink_files(request->file_list);
 		return (-1);
 	}
 
 	/* save the secure file */
 	if (putsecure(buf, &secure) < 0) {
-		mail(request, buf, gettext("Can't save print secure file"));
+		mail(request, buf,
+		    gettext("Can't save print secure file"));
 		snprintf(buf, sizeof (buf), "%s/%s/%d-0", Lp_Tmp, host,
 		    request_id);
 		unlink(buf);
@@ -624,7 +667,8 @@
 				gettext("failure to communicate with lpsched"));
 			break;
 		default:
-			mail(request, buf, gettext("Unknown error: %d"),
+			mail(request, buf,
+			    gettext("Unknown error: %d"),
 				status);
 			break;
 		}
diff --git a/usr/src/cmd/lp/cmd/lpadmin/Makefile b/usr/src/cmd/lp/cmd/lpadmin/Makefile
index c756879..bb3c282 100644
--- a/usr/src/cmd/lp/cmd/lpadmin/Makefile
+++ b/usr/src/cmd/lp/cmd/lpadmin/Makefile
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -18,13 +17,15 @@
 # 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"
 #
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
 # cmd/lp/cmd/lpadmin/Makefile
 #
 
@@ -65,7 +66,8 @@
 
 SYSLIBS=	-lcurses
 
-LDLIBS +=	$(LPLIBS) $(SYSLIBS) $(I18N)
+LDLIBS +=	-z lazyload -lsecdb -z nolazyload $(LPLIBS) \
+			$(SYSLIBS) $(I18N)
 
 PROG=		lpadmin
 
diff --git a/usr/src/cmd/lp/cmd/lpadmin/do_printer.c b/usr/src/cmd/lp/cmd/lpadmin/do_printer.c
index f6a502f..66ab3f2 100644
--- a/usr/src/cmd/lp/cmd/lpadmin/do_printer.c
+++ b/usr/src/cmd/lp/cmd/lpadmin/do_printer.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -24,7 +23,7 @@
 
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -35,11 +34,16 @@
 #include <errno.h>
 #include <limits.h>
 #include <sys/types.h>
+#include <sys/zone.h>
 #include <stdlib.h>
 #include <libintl.h>
-
+#include <sys/tsol/label_macro.h>
+#include <bsm/devices.h>
 #include "lp.h"
 #include "class.h"
+#if defined PS_FAULTED
+#undef	PS_FAULTED
+#endif
 #include "printers.h"
 #include "msgs.h"
 
@@ -59,9 +63,11 @@
 #endif
 
 extern char		*label;
+
 static void		configure_printer();
 static char		*fullpath();
 char			*nameit();
+static void		pack_white(char *ptr);
 
 /**
  ** do_printer() - CREATE OR CHANGE PRINTER
@@ -630,6 +636,11 @@
 				);
 			done(1);
 		}
+
+		if ((getzoneid() == GLOBAL_ZONEID) && system_labeled &&
+		    (prbufp->device != NULL))
+			update_dev_dbs(p, prbufp->device, "ADD");
+
 	END_CRITICAL
 
 	return;
@@ -683,3 +694,88 @@
 	(void) strcat (copy, nm);
 	return (copy);
 }
+
+/*
+ * update_dev_dbs - ADD/REMOVE ENTRIES FOR THE PRINTER IN DEVICE
+ * 			ALLOCATION FILES
+ *
+ * We intentionally ignore errors, since we don't want the printer
+ * installation to be viewed as failing just because we didn't add
+ * the device_allocate entry.
+ *
+ *	Input:
+ *		prtname - printer name
+ *		devname - device associated w/ this printer
+ *		func - [ADD|REMOVE] entries in /etc/security/device_allocate
+ *			and /etc/security/device_maps
+ *
+ *	Return:
+ *		Always 'quiet' return.  Failures are ignored.
+ */
+void
+update_dev_dbs(char *prtname, char *devname, char *func)
+{
+	int		fd, status;
+	pid_t		pid;
+
+	pid = fork();
+	switch (pid) {
+	case -1:
+		/* fork failed, just return quietly */
+		return;
+	case 0:
+		/* child */
+		/* redirect to /dev/null */
+		(void) close(1);
+		(void) close(2);
+		fd = open("/dev/null", O_WRONLY);
+		fd = dup(fd);
+
+		if (strcmp(func, "ADD") == 0) {
+			execl("/usr/sbin/add_allocatable", "add_allocatable",
+			    "-n", prtname, "-t", "lp", "-l", devname,
+			    "-o", "minlabel=admin_low:maxlabel=admin_high",
+			    "-a", "*", "-c", "/bin/true", NULL);
+		} else {
+			if (strcmp(func, "REMOVE") == 0) {
+				execl("/usr/sbin/remove_allocatable",
+				    "remove_allocatable", "-n", prtname, NULL);
+			}
+		}
+		_exit(1);
+		/* NOT REACHED */
+	default:
+		waitpid(pid, &status, 0);
+		return;
+	}
+}
+
+/*
+ * pack_white(ptr) trims off multiple occurances of white space from a NULL
+ * terminated string pointed to by "ptr".
+ */
+static void
+pack_white(char *ptr)
+{
+	char	*tptr;
+	char	*mptr;
+	int	cnt;
+
+	if (ptr == NULL)
+		return;
+	cnt = strlen(ptr);
+	if (cnt == 0)
+		return;
+	mptr = (char *)calloc((unsigned)cnt+1, sizeof (char));
+	if (mptr == NULL)
+		return;
+	tptr = strtok(ptr, " \t");
+	while (tptr != NULL) {
+		(void) strcat(mptr, tptr);
+		(void) strcat(mptr, " ");
+		tptr = strtok(NULL, " \t");
+	}
+	cnt = strlen(mptr);
+	(void) strcpy(ptr, mptr);
+	free(mptr);
+}
diff --git a/usr/src/cmd/lp/cmd/lpadmin/lpadmin.c b/usr/src/cmd/lp/cmd/lpadmin/lpadmin.c
index cfe77a7..83560a6 100644
--- a/usr/src/cmd/lp/cmd/lpadmin/lpadmin.c
+++ b/usr/src/cmd/lp/cmd/lpadmin/lpadmin.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -28,6 +27,11 @@
 /*	  All Rights Reserved  	*/
 
 
+/*
+ * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include "stdio.h"
@@ -55,6 +59,8 @@
 			chkopts3(),
 			exit();
 
+int			system_labeled = 0;
+
 int			scheduler_active = 0;
 
 char			*label = 0;
@@ -88,6 +94,8 @@
 		/*NOTREACHED*/
 	}
 
+	system_labeled = is_system_labeled();
+
 	uname(&un);
 	Local_System = strdup(un.nodename);
     
diff --git a/usr/src/cmd/lp/cmd/lpadmin/lpadmin.h b/usr/src/cmd/lp/cmd/lpadmin/lpadmin.h
index 7c22f4e..3e58a3b 100644
--- a/usr/src/cmd/lp/cmd/lpadmin/lpadmin.h
+++ b/usr/src/cmd/lp/cmd/lpadmin/lpadmin.h
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -24,7 +23,7 @@
 
 
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -126,6 +125,10 @@
 			startup(),
 			usage();
 
+/* Routines/variables needed for labeled systems */
+extern void		update_dev_dbs(char *, char *, char *);
+extern int		system_labeled;
+
 
 #if	defined(__STDC__)
 void			send_message( int , ... );
diff --git a/usr/src/cmd/lp/cmd/lpadmin/rmdest.c b/usr/src/cmd/lp/cmd/lpadmin/rmdest.c
index b13555e..35ff27d 100644
--- a/usr/src/cmd/lp/cmd/lpadmin/rmdest.c
+++ b/usr/src/cmd/lp/cmd/lpadmin/rmdest.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -23,7 +22,12 @@
 /*	  All Rights Reserved  	*/
 
 
-#ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.1	*/
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
 
 #include "stdio.h"
 #include "ctype.h"
@@ -103,6 +107,9 @@
 		if (STREQU(getdflt(), dest))
 			newdflt (NAME_NONE);
 
+		if (system_labeled) {
+			update_dev_dbs(dest, NULL, "REMOVE");
+		}
 		break;
 
 	case MBUSY:
diff --git a/usr/src/cmd/lp/cmd/lpc/process.c b/usr/src/cmd/lp/cmd/lpc/process.c
index f7abe95..ddeda2c 100644
--- a/usr/src/cmd/lp/cmd/lpc/process.c
+++ b/usr/src/cmd/lp/cmd/lpc/process.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -319,6 +318,7 @@
 		*reject_reason,
 		*request_id,
 		*form,
+		*slabel,
 		*file,
 		*char_set,
 		*disable_reason;
@@ -366,6 +366,7 @@
 		rcv_msg(R_INQUIRE_REQUEST_RANK, &status,
 					   &request_id,
 					   &user,
+					   &slabel,
 					   &size,
 					   &date,
 					   &state,
diff --git a/usr/src/cmd/lp/cmd/lpc/topq.c b/usr/src/cmd/lp/cmd/lpc/topq.c
index 23ce029..4a5b0fc 100644
--- a/usr/src/cmd/lp/cmd/lpc/topq.c
+++ b/usr/src/cmd/lp/cmd/lpc/topq.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -171,7 +170,7 @@
 char	*machine;
 #endif
 {
-	char	 *request_id, *form, *character_set;
+	char	 *request_id, *form, *slabel, *character_set;
 	char	  buf[50];
 	char	**rqlist = NULL, **pp;
 	short	  state, status;
@@ -188,6 +187,7 @@
 		rcv_msg(R_INQUIRE_REQUEST, &status,
 					   &request_id,
 					   &user,
+					   &slabel,
 					   &size,
 					   &date,
 					   &state,
diff --git a/usr/src/cmd/lp/cmd/lpsched/Makefile b/usr/src/cmd/lp/cmd/lpsched/Makefile
index 3012533..3d03c42 100644
--- a/usr/src/cmd/lp/cmd/lpsched/Makefile
+++ b/usr/src/cmd/lp/cmd/lpsched/Makefile
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -18,11 +17,13 @@
 # information: Portions Copyright [yyyy] [name of copyright owner]
 #
 # CDDL HEADER END
+
+
 #
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
 #
-# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # cmd/lp/cmd/lpsched/lpsched/Makefile
@@ -102,7 +103,8 @@
 		$(LIBLP)	\
 		$(LIBSEC)
 
-SYSLIBS=	-lcurses -lgen -lcurses -lnsl
+SYSLIBS=	-lcurses -lgen -lcurses -lnsl -z lazyload \
+		-ltsol -lsecdb -lcmd -lbsm -z nolazyload
 
 LDLIBS +=	$(LPLIBS) $(SYSLIBS)
 
diff --git a/usr/src/cmd/lp/cmd/lpsched/disp1.c b/usr/src/cmd/lp/cmd/lpsched/disp1.c
index 7473af6..a551b7e 100644
--- a/usr/src/cmd/lp/cmd/lpsched/disp1.c
+++ b/usr/src/cmd/lp/cmd/lpsched/disp1.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -145,6 +144,8 @@
 		rp->secure->req_id = Strdup(s->req_id);
 		rp->secure->user = Strdup(s->user);
 		rp->secure->system = Strdup(s->system);
+		if (md->slabel != NULL)
+			rp->secure->slabel = Strdup(md->slabel);
 		freesecure(s);
 		/*
 		**  There are some anomallies associated w/
@@ -160,6 +161,8 @@
 		rp->request->outcome = 0;
 		rp->secure->uid = md->uid;
 		rp->secure->gid = md->gid;
+		if (md->slabel != NULL)
+			rp->secure->slabel = Strdup(md->slabel);
     
 		pw = getpwuid(md->uid);
 		endpwent();
@@ -365,6 +368,10 @@
     
     if (!(rp = request_by_id(req_id)))
 	status = MUNKNOWN;
+    else if ((md->admin == 0) && (is_system_labeled()) &&
+	    (md->slabel != NULL) && (rp->secure->slabel != NULL) &&
+	    (!STREQU(md->slabel, rp->secure->slabel)))
+	status = MUNKNOWN;
     else if (rp->request->outcome & RS_DONE)
 	status = M2LATE;
     else if (!md->admin && md->uid != rp->secure->uid)
@@ -438,6 +445,10 @@
 
     if (!(rp = request_by_id(req_id)))
 	status = MUNKNOWN;
+    else if ((md->admin == 0) && (is_system_labeled()) &&
+	    (md->slabel != NULL) && (rp->secure->slabel != NULL) &&
+	    (!STREQU(md->slabel, rp->secure->slabel)))
+	status = MUNKNOWN;
     else if (!(rp->request->outcome & RS_CHANGING))
 	status = MNOSTART;
     else {
@@ -618,6 +629,15 @@
 	    return(Strdup(crp->secure->req_id));
 	}
 
+	/*
+	 * For Trusted Extensions, we need to check the sensitivity label of the
+	 * connection and job before we try to cancel it.
+	 */
+	if ((md->admin == 0) && (is_system_labeled()) &&
+	    (md->slabel != NULL) && (crp->secure->slabel != NULL) &&
+	    (!STREQU(md->slabel, crp->secure->slabel)))
+	    continue;
+
 	crp->reason = MOK;
 	creq_id = Strdup(crp->secure->req_id);
 
@@ -737,14 +757,23 @@
 
 	if (*pwheel && !SAME(pwheel, rp->pwheel_name))
 	    continue;
+
+	/*
+	 * For Trusted Extensions, we need to check the sensitivity label of the
+	 * connection and job before we return it to the client.
+	 */
+	if ((md->admin <= 0) && (is_system_labeled()) &&
+	    (md->slabel != NULL) && (rp->secure->slabel != NULL) &&
+	    (!STREQU(md->slabel, rp->secure->slabel)))
+	    continue;
 	
 	if (found) {
 	    GetRequestFiles(found->request, files, sizeof(files));
 	    mputm(md, R_INQUIRE_REQUEST,
 		 MOKMORE,
 		 found->secure->req_id,
-		 found->request->user,
-			/* bgolden 091996, bug 1257405 */
+		 found->request->user, /* bgolden 091996, bug 1257405 */
+		 found->secure->slabel,
 		 found->secure->size,
 		 found->secure->date,
 		 found->request->outcome,
@@ -763,6 +792,7 @@
 	     MOK,
 	     found->secure->req_id,
 	     found->request->user, /* bgolden 091996, bug 1257405 */
+	     found->secure->slabel,
 	     found->secure->size,
 	     found->secure->date,
 	     found->request->outcome,
@@ -772,7 +802,7 @@
 	     files
 	);
     } else
-	mputm(md, R_INQUIRE_REQUEST, MNOINFO, "", "", 0L, 0L, 0, "", "", "",
+	mputm(md, R_INQUIRE_REQUEST, MNOINFO, "", "", "", 0L, 0L, 0, "", "", "",
 	      "");
 
     return;
@@ -829,6 +859,15 @@
 
 		if (*pwheel && !SAME(pwheel, rp->pwheel_name))
 			continue;
+		/*
+		 * For Trusted Extensions, we need to check the sensitivity
+		 * label of the connection and job before we return it to the
+		 * client.
+		 */
+		if ((md->admin <= 0) && (is_system_labeled()) &&
+		    (md->slabel != NULL) && (rp->secure->slabel != NULL) &&
+		    (!STREQU(md->slabel, rp->secure->slabel)))
+			continue;
 
 		if (found) {
 			GetRequestFiles(found->request, files, sizeof(files));
@@ -837,6 +876,7 @@
 				found->secure->req_id,
 				found->request->user,
 					/* bgolden 091996, bug 1257405 */
+				found->secure->slabel,
 				found->secure->size,
 				found->secure->date,
 				found->request->outcome,
@@ -858,6 +898,7 @@
 			MOK,
 			found->secure->req_id,
 			found->request->user, /* bgolden 091996, bug 1257405 */
+			found->secure->slabel,
 			found->secure->size,
 			found->secure->date,
 			found->request->outcome,
@@ -868,8 +909,8 @@
 			files
 		);
 	} else
-		mputm(md, R_INQUIRE_REQUEST_RANK, MNOINFO, "", "", 0L, 0L, 0,
-			"", "", "", 0, "");
+		mputm(md, R_INQUIRE_REQUEST_RANK, MNOINFO, "", "", "", 0L, 0L,
+			0, "", "", "", 0, "");
 }
 
 static int
@@ -1133,3 +1174,33 @@
 
     return(path);
 }
+
+/*
+ * The client is sending a peer connection to retreive label information
+ * from.  This is used in the event that the client is an intermediary for
+ * the actual requestor in a Trusted environment.
+ */
+void s_pass_peer_connection(char *m, MESG *md)
+{
+	short	status = MTRANSMITERR;
+	char	*dest;
+	struct strrecvfd recv_fd;
+
+	(void) getmessage(m, S_PASS_PEER_CONNECTION);
+	syslog(LOG_DEBUG, "s_pass_peer_connection()");
+
+	memset(&recv_fd, NULL, sizeof (recv_fd));
+	if (ioctl(md->readfd, I_RECVFD, &recv_fd) == 0) {
+		int fd = recv_fd.fd;
+
+		if (get_peer_label(fd, &md->slabel) == 0) {
+			if (md->admin == 1)
+				md->admin = -1; /* turn off query privilege */
+			status = MOK;
+		}
+
+		close(fd);
+	}
+
+	mputm(md, R_PASS_PEER_CONNECTION, status);
+}
diff --git a/usr/src/cmd/lp/cmd/lpsched/dispatch.h b/usr/src/cmd/lp/cmd/lpsched/dispatch.h
index cd4c55d..d4d6e50 100644
--- a/usr/src/cmd/lp/cmd/lpsched/dispatch.h
+++ b/usr/src/cmd/lp/cmd/lpsched/dispatch.h
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -82,6 +81,7 @@
 void		s_unmount_tray ( char *, MESG *);
 void		s_paper_changed ( char *, MESG *);
 void		s_paper_allowed ( char *, MESG *);
+void		s_pass_peer_connection ( char * , MESG * );
 	
 /**
  ** dispatch_table[]
diff --git a/usr/src/cmd/lp/cmd/lpsched/disptab.c b/usr/src/cmd/lp/cmd/lpsched/disptab.c
index a9452d5..46366a8 100644
--- a/usr/src/cmd/lp/cmd/lpsched/disptab.c
+++ b/usr/src/cmd/lp/cmd/lpsched/disptab.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 1996 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -139,6 +138,8 @@
 /* R_PAPER_CHANGED          */  0,			D_BADMSG,
 /* S_PAPER_ALLOWED          */  s_paper_allowed,	0,
 /* R_PAPER_ALLOWED          */  0,			D_BADMSG,
+/* S_PASS_PEER_CONNECTION   */  s_pass_peer_connection,	0,
+/* R_PASS_PEER_CONNECTION   */  0,			D_BADMSG,
 };
 
 static char *			dispatch_names[] = {
@@ -244,6 +245,8 @@
 "R_PAPER_CHANGED",
 "S_PAPER_ALLOWED",
 "R_PAPER_ALLOWED",
+"S_PASS_PEER_CONNECTION",
+"R_PASS_PEER_CONNECTION",
 };
 
 /* see include/msgs.h */
diff --git a/usr/src/cmd/lp/cmd/lpsched/exec.c b/usr/src/cmd/lp/cmd/lpsched/exec.c
index 579cada..4dd2b8a 100644
--- a/usr/src/cmd/lp/cmd/lpsched/exec.c
+++ b/usr/src/cmd/lp/cmd/lpsched/exec.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -29,6 +28,11 @@
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
+#include <pwd.h>
+#include <zone.h>
+#if defined PS_FAULTED
+#undef  PS_FAULTED
+#endif /* PS_FAULTED */
 #include <dial.h>
 
 #include <stdlib.h>
@@ -38,7 +42,7 @@
 #include "dial.h"
 #include "lpsched.h"
 #include <syslog.h>
-#include <pwd.h>
+#include "tsol/label.h"
 
 #define Done(EC,ERRNO)	done(((EC) << 8),ERRNO)
 
@@ -256,6 +260,7 @@
 }
 
 static char time_buf[50];
+
 /**
  ** exec() - FORK AND EXEC CHILD PROCESS
  **/
@@ -304,6 +309,8 @@
 	char *av[ARG_MAX];
 	char **envp = NULL;
 	int ac = 0;
+	char	*mail_zonename = NULL;
+	char	*slabel = NULL;
 
 	syslog(LOG_DEBUG, "exec(%s)", _exec_name(type));
 
@@ -440,7 +447,6 @@
 	for (i = 0; i < OpenMax; i++)
 		if (i != ChildMd->writefd)
 			Close (i);
-
 	setpgrp();
 
 	/* Set a default path */
@@ -717,6 +723,14 @@
 				request->request->user);
 		}
 		/*
+		 * Add the sensitivity label to the environment for
+		 * banner page and header/footer processing
+		 */
+
+		if (is_system_labeled() && request->secure->slabel != NULL)
+			addenv(&envp, "SLABEL", request->secure->slabel);
+
+		/*
 		 * Add the system name to the user name (ala system!user)
 		 * unless it is already there. RFS users may have trouble
 		 * here, sorry!
@@ -1016,9 +1030,8 @@
 					request->request->alert);
 		} else {
 			char *user = strdup(request->secure->user);
-			procuid = Lp_Uid;
-			procgid = Lp_Gid;
 			clean_string(user);
+			slabel = request->secure->slabel;
 
 			if ((request->request->actions & ACT_WRITE) &&
 			    (!request->secure->system ||
@@ -1032,9 +1045,41 @@
 				av[ac++] = arg_string(TRUSTED, "/bin/sh");
 				av[ac++] = arg_string(TRUSTED, "-c");
 				av[ac++] = arg_string(TRUSTED, "%s", argbuf);
-			} else {
+			} else if ((getzoneid() == GLOBAL_ZONEID) &&
+				   is_system_labeled() && (slabel != NULL)) {
+				/*
+				 * If in the global zone and the system is
+				 * labeled, mail is handled via a local
+				 * labeled zone that is the same label as
+				 * the request.
+				 */
+				if ((mail_zonename =
+				    get_labeled_zonename(slabel)) ==
+				    (char *)-1) {
+					/*
+					 * Cannot find labeled zone, just
+					 * return 0.
+					 */
+					return(0);
+				}
+			}
+			if (mail_zonename == NULL) {
+				procuid = Lp_Uid;
+				procgid = Lp_Gid;
 				av[ac++] = arg_string(TRUSTED, "%s", BINMAIL);
 				av[ac++] = arg_string(UNTRUSTED, "%s", user);
+			} else {
+				procuid = getuid();
+				procgid = getgid();
+				av[ac++] = arg_string(TRUSTED, "%s",
+				    "/usr/sbin/zlogin");
+				av[ac++] = arg_string(TRUSTED, "%s",
+				    mail_zonename);
+				av[ac++] = arg_string(TRUSTED, "%s",
+				    BINMAIL);
+				av[ac++] = arg_string(UNTRUSTED, "%s",
+				    user);
+				Free(mail_zonename);
 			}
 
 			free(user);
@@ -1070,7 +1115,7 @@
 
 	for (i = 0; av[i] != NULL; i++)
 		syslog(LOG_DEBUG, "exec: av[%d] = %s", i, av[i]);
-	for (i = 0; av[i] != NULL; i++)
+	for (i = 0; envp[i] != NULL; i++)
 		syslog(LOG_DEBUG, "exec: envp[%d] = %s", i, envp[i]);
 
 	execvpe(av[0], av, envp);
diff --git a/usr/src/cmd/lp/cmd/lpsched/validate.c b/usr/src/cmd/lp/cmd/lpsched/validate.c
index 017dad7..2791428 100644
--- a/usr/src/cmd/lp/cmd/lpsched/validate.c
+++ b/usr/src/cmd/lp/cmd/lpsched/validate.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2001 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -28,15 +27,23 @@
 /*	  All Rights Reserved  	*/
 
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.11.1.10	*/
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/* SVr4.0 1.11.1.10	*/
 /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
 
 #include "lpsched.h"
 
 #include "validate.h"
 
+#include <syslog.h>
+#include <errno.h>
+#include <deflt.h>
+#include <tsol/label.h>
+#include <auth_list.h>
+
 #define register auto
 
+
 int		pickfilter ( RSTATUS * , CANDIDATE * , FSTATUS * );
 
 unsigned long		chkprinter_result	= 0;
@@ -46,10 +53,14 @@
 char *			o_length	= 0;
 
 static int		wants_nobanner	= 0;
+static int		wants_nolabels	= 0;
 static int		lp_or_root	= 0;
 
 static int		_chkopts ( RSTATUS *, CANDIDATE * , FSTATUS * );
 static void		free_candidate ( CANDIDATE * );
+static int		tsol_check_printer_label_range(char *, const char *);
+static int		tsol_lpauth(char *, char *);
+static int		secpolicy_chkpolicy(char *policyp);
 
 /**
  ** _validate() - FIND A PRINTER TO HANDLE A REQUEST
@@ -79,6 +90,23 @@
 	wants_nobanner = 0;
 	memset (&single, 0, sizeof(single));
 
+	wants_nolabels = 0;
+	/*
+	 * If the system is labeled, the printing of postscript files
+	 * is restricted.  All users can print postscript files if the
+	 * file /etc/default/print contains "PRINT_POSTSCRIPT=1".
+	 * (this is checked by secpolicy_chkpolicy).  Otherwise the
+	 * user must have PRINT_POSTSCRIPT_AUTH to print postscript files.
+	 */
+	if ((is_system_labeled() &&
+	    strcmp(prs->request->input_type, "postscript") == 0) &&
+	    (secpolicy_chkpolicy("PRINT_POSTSCRIPT=") == 0)) {
+		if (tsol_lpauth(PRINT_POSTSCRIPT_AUTH, prs->secure->user)
+		    == 0) {
+			ret = MDENYDEST;
+			goto Return;
+		}
+	}
 	lp_or_root = 0;
 
 	if (STREQU(prs->secure->system, Local_System))
@@ -166,6 +194,8 @@
 					o_length = Strdup(*pl + 7);
 				else if (STREQU(*pl, "nobanner"))
 					wants_nobanner = 1;
+				else if (STREQU(*pl, "nolabels"))
+					wants_nolabels = 1;
 			freelist (list);
 		}
 	}
@@ -296,6 +326,16 @@
 			goto Return;
 		}
 
+		/* Check printer label range */
+		if (is_system_labeled() && prs->secure->slabel != NULL) {
+			if (tsol_check_printer_label_range(
+			    prs->secure->slabel,
+			    pps->printer->name) == 0) {
+				ret = MDENYDEST;
+				goto Return;
+			}
+		}
+
 		/* Does the printer allow the form? */
 		if (pfs && !CHKF(pfs, pps)) {
 			ret = MNOMOUNT;
@@ -563,6 +603,30 @@
 		ret = MOK;
 		goto Return;
 	}
+	/*
+	 * Clean out local printers
+	 * where the request is outside the printer label range.
+	 */
+	{
+		register CANDIDATE	*pcend2;
+
+		if (is_system_labeled()) {
+			for (pcend2 = pc = arena; pc < pcend; pc++) {
+				if (tsol_check_printer_label_range(
+				    prs->secure->slabel,
+				    pps->printer->name) == 1)
+					*pcend2++ = *pc;
+				else
+					free_candidate(pc);
+			}
+		}
+
+		if (pcend2 == arena) {
+			ret = MDENYDEST;
+			goto Return;
+		}
+		pcend = pcend2;
+	}
 
 #if	defined(OTHER_FACTORS)
 	/*
@@ -790,6 +854,7 @@
 	char *			paper = NULL;
 
 	char **			pt;
+	int			nobanner_not_allowed = 0;
 
 
 	/*
@@ -844,11 +909,47 @@
 	if (!pc->printer_types)
 		ret |= chk;
 
-	if (pc->pps->printer->banner == BAN_ALWAYS) {
-		if ((wants_nobanner == 1) && (lp_or_root != 1)) {
-			/* delete "nobanner" */
-			char **list;
+	/*
+	 * If the sytem is labeled, then user who wants 'nolabels' must
+	 * have PRINT_UNLABELED_AUTH authorizations to allow it.
+	 */
+	if (is_system_labeled() && (wants_nolabels == 1)) {
+		if (!tsol_lpauth(PRINT_UNLABELED_AUTH, prs->secure->user)) {
+			/* if not authorized, remove "nolabels" from options */
+			register char		**list;
+			if (prs->request->options &&
+			    (list = dashos(prs->request->options))) {
+				dellist(&list, "nolabels");
+				free(prs->request->options);
+				prs->request->options = sprintlist(list);
+			}
+		}
+	}
 
+
+	if (pc->pps->printer->banner == BAN_ALWAYS) {
+		/* delete "nobanner" */
+		char **list;
+
+		/*
+		 * If the system is labeled, users must have
+		 * PRINT_NOBANNER_AUTH authorization to print
+		 * without a banner.
+		 */
+		if (is_system_labeled()) {
+			if (wants_nobanner == 1) {
+				if (tsol_lpauth(PRINT_NOBANNER_AUTH,
+					prs->secure->user) == 0) {
+					nobanner_not_allowed = 1;
+				}
+			}
+
+		}
+		else if ((wants_nobanner == 1) && (lp_or_root != 1)) {
+			nobanner_not_allowed = 1;
+		}
+		if (nobanner_not_allowed == 1) {
+			/* Take out 'nobanner' from request options. */
 			if (prs->request->options &&
 			    (list = dashos(prs->request->options))) {
 				dellist(&list, "nobanner");
@@ -897,3 +998,85 @@
 		unload_str (&(pc->output_type));
 	return;
 }
+
+static int
+tsol_check_printer_label_range(char *slabel, const char *printer)
+{
+	int			in_range = 0;
+	int			err = 0;
+	m_range_t		*range;
+	m_label_t	*sl = NULL;
+
+	if (slabel == NULL)
+		return (0);
+
+	if ((err =
+	    (str_to_label(slabel, &sl, USER_CLEAR, L_NO_CORRECTION, &in_range)))
+	    == -1) {
+		/* stobsl error on printer max label */
+		return (0);
+	}
+	if ((range = getdevicerange(printer)) == NULL) {
+		m_label_free(sl);
+		return (0);
+	}
+
+	/* blinrange returns true (1) if in range, false (0) if not */
+	in_range = blinrange(sl, range);
+
+	m_label_free(sl);
+	m_label_free(range->lower_bound);
+	m_label_free(range->upper_bound);
+	free(range);
+
+	return (in_range);
+}
+
+/*
+ * Given a character string with a "username" or "system!username"
+ * this function returns a pointer to "username"
+ */
+static int
+tsol_lpauth(char *auth, char *in_name)
+{
+	char *cp;
+	int res;
+
+	if ((cp = strchr(in_name, '@')) != NULL) {
+		/* user@system */
+		*cp = '\0';
+		res = chkauthattr(auth, in_name);
+		*cp = '@';
+	} else if ((cp = strchr(in_name, '!')) != NULL)
+		/* system!user */
+		res = chkauthattr(auth, cp+1);
+	else
+		/* user */
+		res = chkauthattr(auth, in_name);
+
+	return (res);
+}
+
+#define	POLICY_FILE	"/etc/default/print"
+
+int
+secpolicy_chkpolicy(char *policyp)
+{
+	char *option;
+	int opt_val;
+
+	if (policyp == NULL)
+		return (0);
+	opt_val = 0;
+	if (defopen(POLICY_FILE) == 0) {
+
+		defcntl(DC_SETFLAGS, DC_STD & ~DC_CASE); /* ignore case */
+
+		if ((option = defread(policyp)) != NULL)
+			opt_val = atoi(option);
+	}
+	(void) defopen((char *)NULL);
+	syslog(LOG_DEBUG, "--- Policy %s, opt_val==%d",
+	    policyp ? policyp : "NULL", opt_val);
+	return (opt_val);
+}
diff --git a/usr/src/cmd/lp/cmd/lpstat/Makefile b/usr/src/cmd/lp/cmd/lpstat/Makefile
index 2623a14..9e9b661 100644
--- a/usr/src/cmd/lp/cmd/lpstat/Makefile
+++ b/usr/src/cmd/lp/cmd/lpstat/Makefile
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -18,11 +17,13 @@
 # information: Portions Copyright [yyyy] [name of copyright owner]
 #
 # CDDL HEADER END
+
+
 #
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
 #
-# Copyright 1989-2002 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # cmd/lp/cmd/lpstat/Makefile
@@ -61,7 +62,7 @@
 
 SYSLIBS=	-lcurses
 
-LDLIBS +=	$(LPLIBS) $(SYSLIBS) $(I18N)
+LDLIBS +=	$(LPLIBS) $(SYSLIBS) $(I18N) -z lazyload -lsecdb -z nolazyload
 
 POFILE=		lp_cmd_lpstat.po
 
diff --git a/usr/src/cmd/lp/cmd/lpstat/lpstat.h b/usr/src/cmd/lp/cmd/lpstat/lpstat.h
index a01ef97..b1d9a6d 100644
--- a/usr/src/cmd/lp/cmd/lpstat/lpstat.h
+++ b/usr/src/cmd/lp/cmd/lpstat/lpstat.h
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,9 +18,11 @@
  *
  * CDDL HEADER END
  */
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
-/*	Copyright (c) 2001 by Sun Microsystems, Inc. */
-/*	  All Rights Reserved  	*/
 
 
 #ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.7	*/
@@ -69,8 +70,8 @@
 void		do_user ( char ** );
 void		done ( int );
 void		parse ( int , char ** );
-void		putoline(char *, char *, long, time_t, int, char *, char *,
-			char *, int);
+void		putoline(char *, char *, char *, long, time_t, int, char *,
+			char *, char *, int);
 void		putpline(char *, int, char *, time_t, char *, char *, char *);
 void		putqline(char *, int, time_t, char *);
 void		putppline ( char * ,  char *);
diff --git a/usr/src/cmd/lp/cmd/lpstat/output.c b/usr/src/cmd/lp/cmd/lpstat/output.c
index f03a7ec..1cf2051 100644
--- a/usr/src/cmd/lp/cmd/lpstat/output.c
+++ b/usr/src/cmd/lp/cmd/lpstat/output.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -56,6 +55,7 @@
 
 	char			*class,
 				*user,
+				*slabel,
 				*reject_reason,
 				*request_id,
 				*printer,
@@ -131,6 +131,7 @@
 				&status,
 				&request_id,
 				&user,
+				&slabel,
 				&size,
 				&date,
 				&state,
@@ -147,8 +148,9 @@
 
 			case MOK:
 			case MOKMORE:
-				putoline(request_id, user, size, date, state,
-					printer, form, character_set, ++rank);
+				putoline(request_id, user, slabel, size, date,
+					state, printer, form, character_set,
+					++rank);
 				break;
 
 			}
@@ -161,6 +163,7 @@
 				&status,
 				&request_id,
 				&user,
+				&slabel,
 				&size,
 				&date,
 				&state,
@@ -178,8 +181,9 @@
 
 			case MOK:
 			case MOKMORE:
-				putoline(request_id, user, size, date, state,
-					printer, form, character_set, rank);
+				putoline(request_id, user, slabel, size, date,
+					state, printer, form, character_set,
+					rank);
 				break;
 
 			}
diff --git a/usr/src/cmd/lp/cmd/lpstat/request.c b/usr/src/cmd/lp/cmd/lpstat/request.c
index 85bd2a6..6ced71d 100644
--- a/usr/src/cmd/lp/cmd/lpstat/request.c
+++ b/usr/src/cmd/lp/cmd/lpstat/request.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -22,9 +21,8 @@
 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
 /*	  All Rights Reserved  	*/
 
-
 /*
- * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -36,6 +34,7 @@
 #include "sys/types.h"
 
 #include "lp.h"
+#include "strings.h"
 #include "msgs.h"
 #include "requests.h"
 
@@ -178,17 +177,24 @@
 	user_name = NULL;
 }
 
+
 /*
  * putoline()
  */
 
 void
-putoline(char *request_id, char *user, long size, time_t clock, int state,
-	char *printer, char *form, char *character_set, int rank)
+putoline(char *request_id, char *user, char *slabel, long size, time_t clock,
+	int state, char *printer, char *form, char *character_set, int rank)
 {
 	int showRank;
+	char user_buf[LOGMAX];
 	char date[SZ_DATE_BUFF];
 
+	if ((slabel != NULL) && (slabel[0] != '\0'))
+		snprintf(user_buf, sizeof (user_buf), "%s:%s", user, slabel);
+	else
+		snprintf(user_buf, sizeof (user_buf), "%s", user);
+
 	/*
 	 * This is the basic time format used in the output. It represents
 	 * all times of the form "Dec 11 11:04" seen in the output.
@@ -215,13 +221,12 @@
 		((showRank) ? IDSIZE - 2 : IDSIZE),
 		request_id,
 		LOGMAX-1,
-		user,
+		user_buf,
 		OSIZE,
 		size,
 		((showRank) ? "" : "  "),
 		date);
 
-
 	if (!(verbosity & (V_LONG|V_BITS))) {
 
 		/*
diff --git a/usr/src/cmd/lp/cmd/lpsystem.c b/usr/src/cmd/lp/cmd/lpsystem.c
index b919330..6819f06 100644
--- a/usr/src/cmd/lp/cmd/lpsystem.c
+++ b/usr/src/cmd/lp/cmd/lpsystem.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,14 +19,17 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 1997 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
 /*	  All Rights Reserved  	*/
 
-
+/*
+ * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.8	*/
 
@@ -45,6 +47,8 @@
 #include	"systems.h"
 #include	"msgs.h"
 #include	"boolean.h"
+#include	"access.h"
+#include	"tsol/label.h"
 
 #define WHO_AM_I	I_AM_LPSYSTEM
 #include "oam.h"
@@ -283,11 +287,22 @@
 SecurityCheck ()
 #endif
 {
-	if (geteuid () != 0)
-	{
-		(void)	fprintf (stderr,
-			gettext("ERROR:  You must be root.\n"));
-		(void)	exit (1);
+	/* On labeled systems check that user has print admin authorization */
+	if (is_system_labeled()) {
+		if (is_user_admin() == 0) {
+			(void) fprintf(stderr,
+			    gettext(
+			    "You are not authorized to administer printing.\n"\
+			    ));
+			(void) exit (1);
+		}
+	} else {
+		if (geteuid () != 0)
+		{
+			(void)	fprintf (stderr,
+				gettext("ERROR:  You must be root.\n"));
+			(void)	exit (1);
+		}
 	}
 }
 /*==================================================================*/
diff --git a/usr/src/cmd/lp/include/lp.h b/usr/src/cmd/lp/include/lp.h
index 4a7beb3..9cc5c01 100644
--- a/usr/src/cmd/lp/include/lp.h
+++ b/usr/src/cmd/lp/include/lp.h
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -599,6 +598,14 @@
 
 char *		next_x  ( char * , long * , unsigned int );
 
+/*
+ * Stuff needed for Trusted Extensions
+ */
+
+extern	char	*get_labeled_zonename(char *);
+extern int	get_peer_label(int fd, char **slabel);
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/usr/src/cmd/lp/include/msgs.h b/usr/src/cmd/lp/include/msgs.h
index f9aa711..7fa7046 100644
--- a/usr/src/cmd/lp/include/msgs.h
+++ b/usr/src/cmd/lp/include/msgs.h
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -152,10 +151,12 @@
 # define	R_PAPER_CHANGED			99
 # define	S_PAPER_ALLOWED			100
 # define	R_PAPER_ALLOWED			101
+# define	S_PASS_PEER_CONNECTION		102
+# define	R_PASS_PEER_CONNECTION		103
 /*
 **	Last available message
 */
-# define	LAST_MESSAGE			102
+# define	LAST_MESSAGE			104
 
 /*
 **      These are the possible status codes returned by the scheduler
@@ -322,6 +323,7 @@
     MQUE *	mque;			/* backlogged message ptr */
     uid_t	uid;			/* Clients UID */
     gid_t	gid;			/* Clients GID */
+    char *	slabel;			/* Clients SLABEL */
     void	(**on_discon)();	/* Clean up functions */
 } MESG;
 
diff --git a/usr/src/cmd/lp/include/secure.h b/usr/src/cmd/lp/include/secure.h
index b9b6323..ee95ff8 100644
--- a/usr/src/cmd/lp/include/secure.h
+++ b/usr/src/cmd/lp/include/secure.h
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -40,9 +39,9 @@
  **/
 
 /*
- * There are 7 fields in the secure request file.
+ * There are 8 fields in the secure request file.
  */
-#define	SC_MAX  7
+#define	SC_MAX  8
 # define SC_REQID	0	/* Original request id */
 # define SC_UID		1	/* Originator's user ID */
 # define SC_USER	2	/* Originator's real login name */
@@ -50,6 +49,7 @@
 # define SC_SIZE	4	/* Total size of the request data */
 # define SC_DATE	5	/* Date submitted (in seconds) */
 # define SC_SYSTEM	6	/* Originating system */
+# define SC_SLABEL	7	/* Sensitivity Label */
 
 /**
  ** The internal copy of a request as seen by the rest of the world:
@@ -63,6 +63,7 @@
     char	*system;
     char	*user;
     char	*req_id;
+    char	*slabel;
 }			SECURE;
 
 /**
diff --git a/usr/src/cmd/lp/lib/access/allowed.c b/usr/src/cmd/lp/lib/access/allowed.c
index a0a5eb7..c8f6844 100644
--- a/usr/src/cmd/lp/lib/access/allowed.c
+++ b/usr/src/cmd/lp/lib/access/allowed.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -23,7 +22,13 @@
 /*	  All Rights Reserved  	*/
 
 
-#ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.7	*/
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
 /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
 
 #include "string.h"
@@ -31,6 +36,10 @@
 
 #include "lp.h"
 #include "access.h"
+#include <pwd.h>
+#include <auth_attr.h>
+#include <auth_list.h>
+#include <tsol/label.h>
 
 /**
  ** is_user_admin() - CHECK IF CURRENT USER IS AN ADMINISTRATOR
@@ -45,7 +54,15 @@
 is_user_admin ()
 #endif
 {
-	return (Access(Lp_A, W_OK) == -1? 0 : 1);
+	/* For a labeled system, tsol_check_admin_auth is called
+	 * instead of using Access.
+	 */
+	if (is_system_labeled()) {
+		/* Check that user has print admin authorization */
+		return (tsol_check_admin_auth(getuid()));
+	} else {
+		return (Access(Lp_A, W_OK) == -1? 0 : 1);
+	}
 }
 
 /**
@@ -181,3 +198,22 @@
 
 	return (0);
 }
+
+/*
+ * Check to see if the specified user has the administer the printing
+ * system authorization.
+ */
+int
+tsol_check_admin_auth(uid_t uid)
+{
+	struct passwd *p;
+	char *name;
+
+	p = getpwuid(uid);
+	if (p != NULL && p->pw_name != NULL)
+		name = p->pw_name;
+	else
+		name = "";
+
+	return (chkauthattr(PRINT_ADMIN_AUTH, name));
+}
diff --git a/usr/src/cmd/lp/lib/lp/Makefile b/usr/src/cmd/lp/lib/lp/Makefile
index 440d800..3d14c21 100644
--- a/usr/src/cmd/lp/lib/lp/Makefile
+++ b/usr/src/cmd/lp/lib/lp/Makefile
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -18,9 +17,11 @@
 # information: Portions Copyright [yyyy] [name of copyright owner]
 #
 # CDDL HEADER END
+
+
 #
 #
-# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -69,6 +70,7 @@
 		syntax.o	\
 		tidbit.o	\
 		tinames.o	\
+		tx.o		\
 		wherelist.o	\
 		which.o
 
diff --git a/usr/src/cmd/lp/lib/lp/tx.c b/usr/src/cmd/lp/lib/lp/tx.c
new file mode 100644
index 0000000..5ab2944
--- /dev/null
+++ b/usr/src/cmd/lp/lib/lp/tx.c
@@ -0,0 +1,137 @@
+/*
+ * 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 <sys/types.h>
+#include <sys/zone.h>
+#include <syslog.h>
+#include <strings.h>
+
+#include <ucred.h>
+#include "tsol/label.h"
+/* lpsched include files */
+#if defined PS_FAULTED
+#undef  PS_FAULTED
+#endif /* PS_FAULTED */
+#include "lp.h"
+
+/*
+ * get_labeled_zonename - gets the the zonename with the same label.
+ *
+ *	Input:
+ *		slabel - USER_CLEAR label to match
+ *
+ *	Output:
+ *		-1 - zonename with that label could not be found
+ *			or no memory for zonename
+ *		 0 - label was GLOBAL_ZONENAME
+ *		 addr - zonename of zone matching USER_CLEAR label
+ *			must be retuened by calling Free(addr)
+ *
+ */
+
+char *
+get_labeled_zonename(char *slabel)
+{
+	m_label_t	*bsl = NULL;
+	int	err = 0;
+	ssize_t	zonename_size = -1;
+	zoneid_t	zid = -1;
+	char *zname = NULL;
+
+	syslog(LOG_DEBUG, "lpsched: get_labeled_zonename %s", slabel);
+	/*
+	 * convert the label to binary.
+	 */
+	if (str_to_label(slabel, &bsl, USER_CLEAR,
+	    L_NO_CORRECTION, &err) == -1) {
+		/* label could not be converted, error */
+		syslog(LOG_WARNING,
+		    "lpsched: %s: label not recognized (error==%d)",
+		    slabel, err);
+		return ((char *)-1);
+	}
+	if ((zid = getzoneidbylabel(bsl)) < 0) {
+		/* no zone with that label, cannot send mail */
+		syslog(LOG_WARNING,
+		    "lpsched: cannot send mail, no zone with %s label",
+		    slabel);
+		m_label_free(bsl);
+		return ((char *)-1);
+	}
+	zname = Malloc(ZONENAME_MAX + 1);
+	if ((zonename_size = getzonenamebyid(zid, zname, ZONENAME_MAX + 1))
+	    == -1) {
+		/* cannot get zone name, cannot send mail */
+		syslog(LOG_WARNING,
+		    "lpsched: cannot send mail, no zone name for %s",
+		    slabel);
+		m_label_free(bsl);
+		Free(zname);
+		return ((char *)-1);
+	} else {
+		m_label_free(bsl);
+		if (strcmp(zname, GLOBAL_ZONENAME) == 0) {
+			Free(zname);
+			zname = NULL;
+		}
+	}
+	return (zname);
+}
+
+int
+get_peer_label(int fd, char **slabel)
+{
+	if (is_system_labeled()) {
+		ucred_t *uc = NULL;
+		m_label_t *sl;
+		char *pslabel = NULL; /* peer's slabel */
+
+		if ((fd < 0) || (slabel == NULL)) {
+			errno = EINVAL;
+			return (-1);
+		}
+
+		if (getpeerucred(fd, &uc) == -1)
+			return (-1);
+
+		sl = ucred_getlabel(uc);
+		if (label_to_str(sl, &pslabel, M_INTERNAL, DEF_NAMES) != 0)
+			syslog(LOG_WARNING, "label_to_str(): %m");
+		ucred_free(uc);
+
+		if (pslabel != NULL) {
+			syslog(LOG_DEBUG, "get_peer_label(%d, %s): becomes %s",
+				fd, (*slabel ? *slabel : "NULL"), pslabel);
+			if (*slabel != NULL)
+				free(*slabel);
+			*slabel = strdup(pslabel);
+		}
+	}
+
+	return (0);
+}
diff --git a/usr/src/cmd/lp/lib/msgs/mlisten.c b/usr/src/cmd/lp/lib/msgs/mlisten.c
index f6f9c3d..b792801 100644
--- a/usr/src/cmd/lp/lib/msgs/mlisten.c
+++ b/usr/src/cmd/lp/lib/msgs/mlisten.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 1997 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -37,6 +36,9 @@
 # include	<fcntl.h>
 # include	<errno.h>
 #include	<syslog.h>
+#include <user_attr.h>
+#include <secdb.h>
+#include <pwd.h>
 
 # include	"lp.h"
 # include	"msgs.h"
@@ -328,7 +330,21 @@
 		md->type = MD_UNKNOWN;
 		md->uid = recbuf.uid;
 
+		/*
+		 * Determine if a print administrator is contacting lpsched.
+		 * currently, root, lp and users with the "solaris.print.admin"
+		 * privilege are print administrators
+		 */
 		md->admin = (md->uid == 0 || md->uid == Lp_Uid);
+		if (md->admin == 0) { 
+			struct passwd *pw = NULL;
+
+			if ((pw = getpwuid(md->uid)) != NULL)
+				md->admin = chkauthattr("solaris.print.admin",
+							pw->pw_name);
+		}
+	
+		get_peer_label(md->readfd, &md->slabel);
 
 		if (mlistenadd(md, POLLIN) != 0)
 		    return(NULL);
diff --git a/usr/src/cmd/lp/lib/msgs/msgfmts.c b/usr/src/cmd/lp/lib/msgs/msgfmts.c
index 0596079..efe7bfc 100644
--- a/usr/src/cmd/lp/lib/msgs/msgfmts.c
+++ b/usr/src/cmd/lp/lib/msgs/msgfmts.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -47,7 +46,7 @@
     "S",          	/* 11 - S_CANCEL_REQUEST */
     "H",          	/* 12 - R_CANCEL_REQUEST */
     "SSSSS",       	/* 13 - S_INQUIRE_REQUEST */
-    "HSSLLHSSSS",      	/* 14 - R_INQUIRE_REQUEST */
+    "HSSSLLHSSSS",     	/* 14 - R_INQUIRE_REQUEST */
     "S",          	/* 15 - S_LOAD_PRINTER */
     "H",          	/* 16 - R_LOAD_PRINTER */
     "S",          	/* 17 - S_UNLOAD_PRINTER */
@@ -108,7 +107,7 @@
     "SSHH",		/* 72 - S_GET_STATUS */
     "HSHH",		/* 73 - R_GET_STATUS */
     "HSSSSS",		/* 74 - S_INQUIRE_REQUEST_RANK */
-    "HSSLLHSSSHS",	/* 75 - R_INQUIRE_REQUEST_RANK */
+    "HSSSLLHSSSHS",	/* 75 - R_INQUIRE_REQUEST_RANK */
     "SSS",		/* 76 - S_CANCEL */
     "HLS",		/* 77 - R_CANCEL */
     "S",		/* 78 - S_NEW_CHILD */
@@ -136,5 +135,7 @@
     "H",          	/* 99 - R_PAPER_CHANGED */
     "S",          	/* 100 - S_PAPER_ALLOWED */
     "HSS",          	/* 101 - R_PAPER_ALLOWED */
+    "",          	/* 102 - S_PASS_PEER_CONNECTION */
+    "H",          	/* 103 - R_PASS_PEER_CONNECTION */
     0,
 };
diff --git a/usr/src/cmd/lp/lib/papi/Makefile b/usr/src/cmd/lp/lib/papi/Makefile
index b7afa69..72c7ff6 100644
--- a/usr/src/cmd/lp/lib/papi/Makefile
+++ b/usr/src/cmd/lp/lib/papi/Makefile
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -18,9 +17,11 @@
 # information: Portions Copyright [yyyy] [name of copyright owner]
 #
 # CDDL HEADER END
+
+
 #
 #
-# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -45,6 +46,8 @@
 CPPFLAGS +=	-I$(LPINC)
 CPPFLAGS +=	-I$(SRC)/lib
 CPPFLAGS +=	-D_REENTRANT
+CPPFLAGS +=	$(ENVCPPFLAGS1)
+CPPFLAGS +=	$(ENVCPPFLAGS2)
 LDLIBS +=	-lc
 LDLIBS	+=	-L$(SRC)/cmd/lp/lib/msgs -llpmsg
 LDLIBS	+=	-L$(SRC)/cmd/lp/lib/printers -llpprt
diff --git a/usr/src/cmd/lp/lib/papi/job.c b/usr/src/cmd/lp/lib/papi/job.c
index c2c8843..ff8aea7 100644
--- a/usr/src/cmd/lp/lib/papi/job.c
+++ b/usr/src/cmd/lp/lib/papi/job.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -783,6 +782,7 @@
 		*request_id = NULL,
 		*charset = NULL,
 		*user = NULL,
+		*slabel = NULL,
 		*file = NULL;
 	time_t date = 0;
 	size_t size = 0;
@@ -801,7 +801,7 @@
 		return (PAPI_SERVICE_UNAVAILABLE);
 
 	if (rcv_msg(svc, R_INQUIRE_REQUEST_RANK, &rc, &request_id,
-			&user, &size, &date, &state, &dest, &form,
+			&user, &slabel, &size, &date, &state, &dest, &form,
 			&charset, &rank, &file) < 0) {
 		detailed_error(svc,
 			gettext("failed to read response from scheduler"));
@@ -814,7 +814,7 @@
 	if ((*job = j = calloc(1, sizeof (*j))) == NULL)
 		return (PAPI_TEMPORARY_ERROR);
 
-	job_status_to_attributes(j, request_id, user, size, date, state,
+	job_status_to_attributes(j, request_id, user, slabel, size, date, state,
 				dest, form, charset, rank, file);
 
 	snprintf(req_id, sizeof (req_id), "%d-0", job_id);
diff --git a/usr/src/cmd/lp/lib/papi/lpsched-jobs.c b/usr/src/cmd/lp/lib/papi/lpsched-jobs.c
index 190aa9a..225cc08 100644
--- a/usr/src/cmd/lp/lib/papi/lpsched-jobs.c
+++ b/usr/src/cmd/lp/lib/papi/lpsched-jobs.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -470,9 +469,9 @@
  * Convert R_REQUEST_* results to the equivalent PAPI attribute representation.
  */
 void
-job_status_to_attributes(job_t *job, char *req_id, char *user, size_t size,
-		time_t date, short state, char *destination, char *form,
-		char *charset, short rank, char *file)
+job_status_to_attributes(job_t *job, char *req_id, char *user, char *slabel,
+		size_t size, time_t date, short state, char *destination,
+		char *form, char *charset, short rank, char *file)
 {
 	char buf[BUFSIZ];
 	char *p;
@@ -517,6 +516,8 @@
 				"lpsched-file", file);
 	addLPString(&job->attributes, PAPI_ATTR_EXCL,
 				"job-name", file);
+	addLPString(&job->attributes, PAPI_ATTR_EXCL,
+				"tsol-sensitivity-label", slabel);
 }
 
 void
diff --git a/usr/src/cmd/lp/lib/papi/mapfile-vers b/usr/src/cmd/lp/lib/papi/mapfile-vers
index 0aaa691..2bddef2 100644
--- a/usr/src/cmd/lp/lib/papi/mapfile-vers
+++ b/usr/src/cmd/lp/lib/papi/mapfile-vers
@@ -1,13 +1,14 @@
 #
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
 # 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.
@@ -22,7 +23,6 @@
 #
 # CDDL HEADER END
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
 #
 # Generic interface definition for usr/src/cmd/lp/lib/papi
 #
@@ -65,6 +65,7 @@
 
 		papiServiceCreate;
 		papiServiceDestroy;
+		papiServiceSetPeer;	# used by to pass peer connection
 		papiServiceSetUserName;
 		papiServiceSetPassword;
 		papiServiceSetEncryption;
diff --git a/usr/src/cmd/lp/lib/papi/papi_impl.h b/usr/src/cmd/lp/lib/papi/papi_impl.h
index 8dfdb2a..d2359f4 100644
--- a/usr/src/cmd/lp/lib/papi/papi_impl.h
+++ b/usr/src/cmd/lp/lib/papi/papi_impl.h
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -82,9 +81,9 @@
 extern void lpsched_request_to_job(REQUEST *r, job_t *j);
 
 extern void job_status_to_attributes(job_t *job, char *req_id, char *user,
-				size_t size, time_t date, short state,
-				char *destination, char *form, char *charset,
-				short rank, char *file);
+				char *slabel, size_t size, time_t date,
+				short state, char *destination, char *form,
+				char *charset, short rank, char *file);
 extern papi_status_t addLPString(papi_attribute_t ***list,
 					int flags, char *name, char *value);
 extern papi_status_t addLPStrings(papi_attribute_t ***list,
diff --git a/usr/src/cmd/lp/lib/papi/printer.c b/usr/src/cmd/lp/lib/papi/printer.c
index 8a3bd8c..2bfc1ea 100644
--- a/usr/src/cmd/lp/lib/papi/printer.c
+++ b/usr/src/cmd/lp/lib/papi/printer.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -328,14 +327,15 @@
 			*req_id = NULL,
 			*charset = NULL,
 			*owner = NULL,
+			*slabel = NULL,
 			*file = NULL;
 		time_t date = 0;
 		size_t size = 0;
 		short  rank = 0, state = 0;
 
 		if (rcv_msg(svc, R_INQUIRE_REQUEST_RANK, &rc, &req_id,
-				&owner, &size, &date, &state, &dest, &form,
-				&charset, &rank, &file) < 0)
+				&owner, &slabel, &size, &date, &state, &dest,
+				&form, &charset, &rank, &file) < 0)
 			return (PAPI_SERVICE_UNAVAILABLE);
 
 		if ((rc != MOK) && (rc != MOKMORE))
@@ -352,8 +352,8 @@
 		if ((job = calloc(1, sizeof (*job))) == NULL)
 			continue;
 
-		job_status_to_attributes(job, req_id, owner, size, date, state,
-				dest, form, charset, rank, file);
+		job_status_to_attributes(job, req_id, owner, slabel, size,
+				date, state, dest, form, charset, rank, file);
 
 		if ((ptr = strrchr(file, '-')) != NULL) {
 			*++ptr = '0';
diff --git a/usr/src/cmd/lp/lib/papi/service.c b/usr/src/cmd/lp/lib/papi/service.c
index 6444bdf..d451263 100644
--- a/usr/src/cmd/lp/lib/papi/service.c
+++ b/usr/src/cmd/lp/lib/papi/service.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -36,6 +35,8 @@
 #include <libintl.h>
 #include <papi_impl.h>
 
+#include <tsol/label.h>
+
 papi_status_t
 papiServiceCreate(papi_service_t *handle, const char *service_name,
 		const char *user_name, const char *password,
@@ -91,6 +92,38 @@
 	}
 }
 
+/*
+ * interface for passing a peer's connection to gather sensitivity labeling
+ * from for Trusted Solaris.
+ */
+papi_status_t
+papiServiceSetPeer(papi_service_t handle, int peerfd)
+{
+	papi_status_t result = PAPI_OK;
+	service_t *svc = handle;
+
+	if (svc == NULL)
+		return (PAPI_BAD_ARGUMENT);
+
+	if (is_system_labeled) {
+		short status;
+
+		if ((snd_msg(svc, S_PASS_PEER_CONNECTION) < 0) ||
+		    (ioctl(svc->md->writefd, I_SENDFD, peerfd) < 0) ||
+		    (rcv_msg(svc, R_PASS_PEER_CONNECTION, &status) < 0))
+			status = MTRANSMITERR;
+
+		if (status != MOK) {
+			detailed_error(svc,
+				gettext("failed to send peer connection: %s"),
+				lpsched_status_string(status));
+			result = lpsched_status_to_papi_status(status);
+		}
+	}
+
+	return (result);
+}
+
 papi_status_t
 papiServiceSetUserName(papi_service_t handle, const char *user_name)
 {
diff --git a/usr/src/cmd/lp/lib/secure/secure.c b/usr/src/cmd/lp/lib/secure/secure.c
index 4bc257f..09796de 100644
--- a/usr/src/cmd/lp/lib/secure/secure.c
+++ b/usr/src/cmd/lp/lib/secure/secure.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 1997 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -37,6 +36,7 @@
 
 #include "lp.h"
 #include "secure.h"
+#include <tsol/label.h>
 
 /**
  ** getsecure() - EXTRACT SECURE REQUEST STRUCTURE FROM DISK FILE
@@ -105,6 +105,10 @@
 		case SC_SYSTEM:
 			secbuf.system = Strdup(buf);
 			break;
+
+		case SC_SLABEL:
+			secbuf.slabel = Strdup(buf);
+			break;
 		}
 	}
 	if (errno != 0 || fld != SC_MAX) {
@@ -199,8 +203,31 @@
 		case SC_SYSTEM:
 			(void)fdprintf(fd, "%s\n", secbufp->system);
 			break;
-		}
 
+		case SC_SLABEL:
+			if (secbufp->slabel == NULL) {
+				if (is_system_labeled()) {
+					m_label_t *sl;
+
+					sl = m_label_alloc(MAC_LABEL);
+					(void) getplabel(sl);
+					if (label_to_str(sl, &(secbufp->slabel),
+					    M_INTERNAL, DEF_NAMES) != 0) {
+						perror("label_to_str");
+						secbufp->slabel =
+						    strdup("bad_label");
+					}
+					m_label_free(sl);
+					(void) fdprintf(fd, "%s\n",
+					    secbufp->slabel);
+				} else {
+					(void) fdprintf(fd, "none\n");
+				}
+			} else {
+				(void) fdprintf(fd, "%s\n", secbufp->slabel);
+			}
+			break;
+		}
 	close(fd);
 
 	return (0);
diff --git a/usr/src/cmd/mdb/common/modules/genunix/genunix.c b/usr/src/cmd/mdb/common/modules/genunix/genunix.c
index 4d72a12..ab0b15c 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/genunix.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/genunix.c
@@ -93,6 +93,7 @@
 #include "sobj.h"
 #include "sysevent.h"
 #include "rctl.h"
+#include "tsol.h"
 #include "typegraph.h"
 #include "ldi.h"
 #include "vfs.h"
@@ -3388,7 +3389,7 @@
 	/* from net.c */
 	{ "mi", ":[-p] [-d | -m]", "filter and display MI object or payload",
 		mi },
-	{ "netstat", "[-av] [-f inet | inet6 | unix] [-P tcp | udp]",
+	{ "netstat", "[-arv] [-f inet | inet6 | unix] [-P tcp | udp]",
 		"show network statistics", netstat },
 	{ "sonode", "?[-f inet | inet6 | unix | #] "
 		"[-t stream | dgram | raw | #] [-p #]",
@@ -3763,6 +3764,12 @@
 	{ "tsd", "walk list of thread-specific data",
 		tsd_walk_init, tsd_walk_step, tsd_walk_fini },
 
+	/* from tsol.c */
+	{ "tnrh", "walk remote host cache structures",
+	    tnrh_walk_init, tnrh_walk_step, tnrh_walk_fini },
+	{ "tnrhtp", "walk remote host template structures",
+	    tnrhtp_walk_init, tnrhtp_walk_step, tnrhtp_walk_fini },
+
 	/*
 	 * typegraph does not work under kmdb, as it requires too much memory
 	 * for its internal data structures.
diff --git a/usr/src/cmd/mdb/common/modules/genunix/net.c b/usr/src/cmd/mdb/common/modules/genunix/net.c
index 209b207..0195489 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/net.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/net.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -57,8 +56,14 @@
 #define	ADDR_V6_WIDTH	23
 #define	ADDR_V4_WIDTH	15
 
-#define	NETSTAT_ALL	0x1
-#define	NETSTAT_VERBOSE	0x2
+#define	NETSTAT_ALL	0x01
+#define	NETSTAT_VERBOSE	0x02
+#define	NETSTAT_ROUTE	0x04
+#define	NETSTAT_V4	0x08
+#define	NETSTAT_V6	0x10
+#define	NETSTAT_UNIX	0x20
+
+#define	NETSTAT_FIRST	0x80000000u
 
 /*
  * Print an IPv4 address and port number in a compact and easy to read format
@@ -790,6 +795,305 @@
 	    "Swind", "Snext", "Suna", "Rwind", "Rack", "Rnext", "Rto", "Mss");
 }
 
+static void
+get_ifname(const ire_t *ire, char *intf)
+{
+	ill_t ill;
+
+	*intf = '\0';
+	if (ire->ire_type == IRE_CACHE) {
+		queue_t stq;
+
+		if (mdb_vread(&stq, sizeof (stq), (uintptr_t)ire->ire_stq) ==
+		    -1)
+			return;
+		if (mdb_vread(&ill, sizeof (ill), (uintptr_t)stq.q_ptr) == -1)
+			return;
+		(void) mdb_readstr(intf, MIN(LIFNAMSIZ, ill.ill_name_length),
+		    (uintptr_t)ill.ill_name);
+	} else if (ire->ire_ipif != NULL) {
+		ipif_t ipif;
+		char *cp;
+
+		if (mdb_vread(&ipif, sizeof (ipif),
+		    (uintptr_t)ire->ire_ipif) == -1)
+			return;
+		if (mdb_vread(&ill, sizeof (ill), (uintptr_t)ipif.ipif_ill) ==
+		    -1)
+			return;
+		(void) mdb_readstr(intf, MIN(LIFNAMSIZ, ill.ill_name_length),
+		    (uintptr_t)ill.ill_name);
+		if (ipif.ipif_id != 0) {
+			cp = intf + strlen(intf);
+			(void) mdb_snprintf(cp, LIFNAMSIZ + 1 - (cp - intf),
+			    ":%u", ipif.ipif_id);
+		}
+	}
+}
+
+static void
+get_v4flags(const ire_t *ire, char *flags)
+{
+	(void) strcpy(flags, "U");
+	if (ire->ire_type == IRE_DEFAULT || ire->ire_type == IRE_PREFIX ||
+	    ire->ire_type == IRE_HOST || ire->ire_type == IRE_HOST_REDIRECT)
+		(void) strcat(flags, "G");
+	if (ire->ire_mask == IP_HOST_MASK)
+		(void) strcat(flags, "H");
+	if (ire->ire_type == IRE_HOST_REDIRECT)
+		(void) strcat(flags, "D");
+	if (ire->ire_type == IRE_CACHE)
+		(void) strcat(flags, "A");
+	if (ire->ire_type == IRE_BROADCAST)
+		(void) strcat(flags, "B");
+	if (ire->ire_type == IRE_LOCAL)
+		(void) strcat(flags, "L");
+	if (ire->ire_flags & RTF_MULTIRT)
+		(void) strcat(flags, "M");
+	if (ire->ire_flags & RTF_SETSRC)
+		(void) strcat(flags, "S");
+}
+
+static int
+ip_mask_to_plen(ipaddr_t mask)
+{
+	int i;
+
+	if (mask == 0)
+		return (0);
+	for (i = 32; i > 0; i--, mask >>= 1)
+		if (mask & 1)
+			break;
+	return (i);
+}
+
+static int
+netstat_irev4_cb(uintptr_t kaddr, const void *walk_data, void *cb_data)
+{
+	const ire_t *ire = walk_data;
+	uint_t *opts = cb_data;
+	ipaddr_t gate;
+	char flags[10], intf[LIFNAMSIZ + 1];
+
+	if (ire->ire_ipversion != IPV4_VERSION || ire->ire_in_src_addr != 0 ||
+	    ire->ire_in_ill != NULL)
+		return (WALK_NEXT);
+
+	if (!(*opts & NETSTAT_ALL) && (ire->ire_type == IRE_CACHE ||