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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/cmd/dminfo/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,55 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 1989, 2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+PROG= dminfo
+
+OBJS= dminfo.o
+SRCS= $(OBJS:%.o=%.c)
+
+include ../Makefile.cmd
+
+TEXT_DOMAIN=SUNW_BSM_DMINFO
+POS=dminfo.po
+include ../Makefile.cmd.bsm
+
+FILEMODE= 755
+
+LDLIBS += -lbsm
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+install: all $(ROOTUSRSBINPROG)
+
+clean:
+ rm -rf $(OBJS) $(POS)
+
+lint: lint_PROG
+
+include ../Makefile.targ
--- a/usr/src/Makefile.lint Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/Makefile.lint Fri Mar 24 12:29:20 2006 -0800
@@ -350,6 +350,8 @@
lib/libsmbios \
lib/libsmedia \
lib/libthread \
+ lib/libtsnet \
+ lib/libtsol \
lib/libumem \
lib/libuutil \
lib/libwanboot \
--- a/usr/src/Targetdirs Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/Targetdirs Fri Mar 24 12:29:20 2006 -0800
@@ -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 \
--- a/usr/src/cmd/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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 \
--- a/usr/src/cmd/allocate/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/allocate/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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
-
-$(ROOTUSRSBIN)/allocate := FILEMODE = 04755
-$(ROOTUSRSBIN)/deallocate := FILEMODE = 04755
-$(ROOTUSRSBIN)/list_devices := FILEMODE = 04755
+$(ROOTSECDEV)/% := FILEMODE = 0400
+$(ROOTSECDEV)/% := OWNER = root
+$(ROOTSECDEV)/% := GROUP = bin
+$(ROOTSECLIB)/% := FILEMODE = 0555
+$(ROOTSECLIB)/% := OWNER = root
+$(ROOTSECLIB)/% := GROUP = sys
-$(ROOTSECDEV)/% := FILEMODE = 0400
-$(ROOTSECDEV)/% := OWNER = root
-$(ROOTSECDEV)/% := GROUP = bin
+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
-$(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
--- a/usr/src/cmd/allocate/allocate.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/allocate/allocate.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.");
+ case ALLOCUERR:
+ msg = gettext("Specified device is allocated to another user.");
break;
- case IMPORT_ERR:
- msg = gettext(
- "User lacks authorization required for this operation.");
+ case CHOWNERR:
+ msg = gettext("Failed to chown.");
break;
- case NODAENT:
+ case CLEANERR:
+ msg = gettext("Unable to clean up device.");
+ break;
+ case CNTDEXECERR:
msg = gettext(
- "No device allocate file entry for specified device.");
- break;
- case NODMAPENT:
- msg = gettext(
- "No device maps file entry for specified device.");
+ "Can't exec device-clean program for specified device.");
break;
- case DACLCK:
- msg = gettext("Concurrent operations for specified device, "
- "try later.");
+ case CNTFRCERR:
+ msg = gettext("Can't force deallocate specified device.");
break;
- case DACACC:
+ case DACACCERR:
msg = gettext(
"Can't access DAC file for the device specified.");
break;
- case DEVLST:
+ case DAOFFERR:
msg = gettext(
- "Could not use device list for the device specified.");
+ "Device allocation feature is not activated "
+ "on this system.");
+ break;
+ case DAUTHERR:
+ msg = gettext("Device not allocatable.");
break;
- case NALLOCU:
- msg = gettext("Specified device is allocated to another user.");
+ case DEFATTRSERR:
+ msg = gettext("No default attributes for specified "
+ "device type.");
break;
- case NOTAUTH:
- msg = gettext("Not authorized for specified operation.");
+ case DEVLKERR:
+ msg = gettext("Concurrent operations for specified device, "
+ "try later.");
break;
- case CNTFRC:
- msg = gettext("Can't force deallocate specified device.");
+ 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 CNTDEXEC:
- msg = gettext(
- "Can't exec device-clean program for specified device.");
+ case DEVSTATEERR:
+ msg = gettext("Device specified is in allocate error state.");
break;
- case NO_DEVICE:
- msg = gettext(
- "Can't find a device of type requested to allocate.");
+ case DEVZONEERR:
+ msg = gettext("Can't find name of the zone to which "
+ "device is allocated.");
break;
- case DSPMISS:
+ 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 LOGINDEVPERMERR:
+ msg = gettext("Device controlled by logindevperm(4)");
break;
- case CHOWN_PERR:
- msg = gettext("Process lacks privilege required to chown().");
+ case NODAERR:
+ msg = gettext("No entry for specified device.");
break;
- case ALLOC:
+ 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.");
- break;
- case NALLOC:
- msg = gettext("Device not allocated.");
- break;
- case AUTHERR:
- msg = gettext("Device not allocatable.");
+ case SETACLERR:
+ msg = gettext("Failed to set ACL.");
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.");
+ case UAUTHERR:
+ msg = gettext(
+ "User lacks authorization required for this operation.");
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,30 +543,46 @@
}
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;
+ 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;
+ } else {
+ /*
+ * caller's uid is the default if no user specified.
+ */
+ uid = getuid();
}
- if (optflg & USERID) {
- if ((pw_ent = getpwuid(uid)) == NULL) {
- (void) fprintf(stderr, gettext(
- "Invalid user ID -- %d -- \n"), uid);
+ /*
+ * 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);
}
- uid = pw_ent->pw_uid;
}
- 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);
- }
+ 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);
@@ -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);
+ }
+}
--- a/usr/src/cmd/allocate/allocate.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/allocate/allocate.h Fri Mar 24 12:29:20 2006 -0800
@@ -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
}
--- a/usr/src/cmd/allocate/allocate3.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/allocate/allocate3.c Fri Mar 24 12:29:20 2006 -0800
@@ -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) == DEALLOC_MODE || \
+ DEV_ERRORED(sbuf) || DEV_INVALID(sbuf)))
-#define DEV_ALLOCATED(sbuf) ((sbuf).st_uid != ALLOC_UID || \
- ((sbuf).st_mode & ~S_IFMT) == ALLOC_MODE)
+#define ALLOC_CLEAN "-A"
+#define DEALLOC_CLEAN "-D"
+#define DAC_DIR "/etc/security/dev"
+#define DEVICE_AUTH_SEPARATOR ","
+#define LOCALDEVICE "/dev/console"
+#define PROCFS "/proc/"
+#define SFF_NO_ERROR 0x1
-#define DEVICE_AUTH_SEPARATOR ","
-#define PROCFS "/proc/"
+#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);
- return (0);
- }
+ if (stat(LOCALDEVICE, &statbuf) == 0 &&
+ statbuf.st_uid == uid)
+ return (1);
- 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);
}
-static int
-check_devs(char *list)
+/*
+ * Checks if the user with the specified uid has the specified authorization
+ */
+int
+_is_authorized(char *auths, uid_t uid)
{
- char *file;
+ 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);
+
+ return (dcp != NULL);
+}
+
+/*
+ * Checks if the specified user has authorization for the device
+ */
+int
+_is_dev_authorized(devalloc_t *da, uid_t uid)
+{
+ 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);
+
+ return (ares);
+}
+
+int
+check_devs(devmap_t *dm)
+{
+ int status = 0;
+ char **file;
- if (access(file, F_OK) == -1) {
- dprintf("Unable to access file %s\n", file);
- return (-1);
+ 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;
-
- 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);
- }
- } else if ((dev_list = getdmapnam(device)) == NULL) {
- dprintf("Unable to find %s in the allocate database\n", device);
- return (NODMAPENT);
- }
+ 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;
- 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);
+ 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;
+ }
+ 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;
+ }
+ if (stat(fname, &fi.fi_stat) != 0) {
+ dprintf("Unable to stat %s\n", fname);
+ dperror("Error:");
+ error = DACACCERR;
+ goto out;
}
-
- if (stat(file_name, &stat_buf)) {
- dprintf("Unable to stat %s\n", file_name);
- dperror("Error:");
- return (DACACC);
+ 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 ((optflg & FREE) && DEV_ALLOCATED(stat_buf))
- return (ALLOC);
+ 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);
- 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);
+ error = 0;
- if ((list = strdup(dev_list->dmap_devlist)) == NULL)
- return (SYSERROR);
-
- if (check_devs(list) == -1) {
- free(list);
- return (DSPMISS);
- }
-
- print_dev(dev_list);
-
- 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);
+ }
+ if (optflag & USERID) {
+ /*
+ * we need device.revoke to list someone else's devices
+ */
+ if (!_is_authorized(DEVICE_REVOKE_AUTH, getuid()))
+ return (UAUTHERR);
+ }
+ 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);
+ }
}
setdaent();
-
if (device) {
- return (list_device(optflg, uid, device));
- }
-
- 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;
+ /*
+ * 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);
}
}
- (void) closedir(dev_dir);
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;
-
- file = strtok(list, " ");
- while (file != NULL) {
+ int i;
+ int error = 0;
+ char **file;
+ gid_t gid = getgid();
+ mode_t mode = ALLOC_MODE;
- 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;
}
+ }
+ 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;
+ }
+ }
+ }
- file = strtok(NULL, " ");
- }
- return (0);
+ 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);
- (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;
-
- audit_allocate_list(list);
+ int status;
+ char **file;
- 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, " ");
+ 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;
}
- exit(error);
- default:
- while (wait(&status) != child);
- if (WIFEXITED(status)) {
- return (WEXITSTATUS(status));
- }
- return (-1);
+ status = _newdac(*file, ALLOC_UID, ALLOC_GID, DEALLOC_MODE);
+ if (error == 0)
+ error = status;
+
}
+
+ return (error);
}
-static int
-exec_clean(int optflg, char *name, char *path)
+int
+mk_error(devmap_t *list)
+{
+ int status = 0;
+ char **file;
+
+ 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)
{
- char *mode, *cmd;
- int status;
- int c;
+ 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;
- if ((optflg & (FORCE_ALL | SILENT)) == (FORCE_ALL | SILENT))
+ 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);
+ 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 {
+ 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(file_name);
+ audit_allocate_device(fname);
- if (stat(file_name, &stat_buf)) {
- dprintf("Unable to stat %s\n", file_name);
- dperror("Error:");
- return (DACACC);
+ 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 {
+ error = DEVNALLOCERR;
+ goto out;
+ }
}
-
- if (!(optflg & FORCE) && stat_buf.st_uid != uid &&
- DEV_ALLOCATED(stat_buf)) {
- return (NALLOCU);
+ /* 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;
+ }
}
- 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);
+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;
}
- /* 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);
- }
+ (void) audit_allocate_device(fname);
- 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);
- } else {
- if ((list = strdup(dev_list->dmap_devlist)) == NULL) {
- EXIT(SYSERROR)
+ 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 {
- if (mk_unalloc(optflg, list) != 0) {
- (void) newdac(file_name, ALLOC_UID, ALLOC_GID,
- ALLOC_ERR_MODE);
- free(list);
- list = NULL;
- EXIT(DEVLST);
+ 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);
- }
-
- audit_allocate_device(file_name);
-
- if (stat(file_name, &stat_buf)) {
- dprintf("Unable to stat %s\n", file_name);
- dperror("Error:");
- return (DACACC);
+ 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);
}
- if (DEV_ALLOCATED(stat_buf)) {
- if (optflg & FORCE) {
- if (optflg & SILENT)
- deallocate_optflg = FORCE|SILENT;
- else
- deallocate_optflg = FORCE;
+ return (0);
+}
+
+/*
+ * _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 (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);
+ 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 (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);
+ free(zlabel);
+ return (-1);
+ }
+ if ((range = getuserrange(pw_ent.pw_name)) == NULL) {
+ dprintf("Unable to get label range for userid %d\n",
(int)uid);
- return (IMPORT_ERR);
+ 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);
}
}
-
- 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);
- }
+ free(zlabel);
- /* 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);
+ 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);
+ }
+ /*
+ * 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];
- 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);
+ 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);
}
- return (allocate_dev(optflg, uid, dev_ent));
+ 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));
+ errno = 0;
+ if ((unlink(zonepath) == -1) && (errno != ENOENT)) {
+ perror(zonepath);
+ return (1);
+ }
+ zonepath[len] = '\0';
}
- if ((dev_dir = opendir(DAC_DIR)) == NULL) {
- dperror("Can't open DAC_DIR");
- return (DACACC);
- }
+ return (0);
+}
+
+int
+update_device(char **devnames, char *zonename, int flag)
+{
+ int len, rc;
+ char *optstr = NULL;
+ da_args dargs;
+ devinfo_t devinfo;
- 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);
- }
+ 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;
}
- (void) closedir(dev_dir);
- enddaent();
- return (error);
+ dargs.devinfo = &devinfo;
+
+ rc = da_update_device(&dargs);
+
+ if (optstr)
+ free(optstr);
+
+ return (rc);
}
--- a/usr/src/cmd/allocate/audio_clean.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/allocate/audio_clean.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
+ if ((argc - optind) != 1) {
+ if (verbose)
+ usage(prog);
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);
+ } else {
+ devname = argv[optind];
}
- (void) strcpy(cmd_str, DMINFO);
- (void) strcat(cmd_str, " ");
- (void) strcat(cmd_str, argv[0]); /* device name */
-
- if ((fp = popen(cmd_str, "r")) == NULL) {
+ setdmapent();
+ if ((dm = getdmapnam(devname)) == NULL) {
+ enddmapent();
if (verbose)
- (void) fprintf(stderr,
- gettext("%s couldn't execute \"%s\"\n"), prog,
- cmd_str);
- exit(1);
+ (void) fprintf(stderr, "%s%s",
+ devname,
+ gettext(" : No such allocatable device\n"));
+ exit(1);
}
-
- if (fread(map, 1, BUF_SIZE, fp) == 0) {
+ enddmapent();
+ if (dm->dmap_devarray == NULL || dm->dmap_devarray[0] == NULL) {
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 */
+ 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);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/allocate/dminfo.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,486 @@
+/*
+ * 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 <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <memory.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <bsm/devices.h>
+#define DMPFILE "/etc/security/device_maps"
+#define RETRY_SLEEP 6
+#define RETRY_COUNT 10
+#define EINVOKE 2
+#define EFAIL 1
+
+#if !defined(TEXT_DOMAIN)
+#define TEXT_DOMAIN "SUNW_BSM_DMINFO"
+#endif
+
+extern off_t lseek();
+
+char *getdmapfield();
+char *getdmapdfield();
+static void printdmapent();
+static void dmapi_err();
+
+static char *prog_name;
+
+/*
+ * printdmapent(dmapp) prints a devmap_t structure pointed to by dmapp.
+ */
+static void
+printdmapent(dmapp)
+ devmap_t *dmapp;
+{
+ (void) printf("%s:", dmapp->dmap_devname);
+ (void) printf("%s:", dmapp->dmap_devtype);
+ (void) printf("%s", dmapp->dmap_devlist);
+ (void) printf("\n");
+}
+
+
+/*
+ * dmapi_err(exit_code,err_msg) prints message pointed to by err_msg to
+ * stderr. Then prints usage message to stderr. Then exits program with
+ * exit_code.
+ *
+ */
+static void
+dmapi_err(int exit_code, char *err_msg)
+{
+ if (err_msg != NULL) {
+ (void) fprintf(stderr, "dmapinfo:%s\n", err_msg);
+ }
+ if (exit_code == EINVOKE) {
+ (void) fprintf(stderr,
+ "Usage: %s [-v] [-a] [-f filename] %s\n",
+ prog_name,
+ "[-d device ...]");
+ (void) fprintf(stderr,
+ " %s [-v] [-a] [-f filename] %s\n",
+ prog_name,
+ "[-n name ...]");
+ (void) fprintf(stderr,
+ " %s [-v] [-a] [-f filename] %s\n",
+ prog_name,
+ "[-t type ...]");
+ (void) fprintf(stderr,
+ " %s [-v] [-a] [-f filename] %s\n",
+ prog_name,
+ "[-u Entry]");
+ }
+
+ exit(exit_code);
+}
+
+int
+main(int argc, char **argv)
+{
+ devmap_t *dmapp;
+ devmap_t dmap;
+ char *mptr;
+ char *tptr;
+ char *nptr;
+ char *filename = DMPFILE;
+ int name = 0;
+ int device = 0;
+ int file = 0;
+ int verbose = 0;
+ int cntr = 0;
+ int any = 0;
+ int update = 0;
+ int tp = 0;
+ int des;
+ int status;
+
+ /* Internationalization */
+ (void) setlocale(LC_ALL, "");
+ (void) textdomain(TEXT_DOMAIN);
+
+ /*
+ * point prog_name to invocation name
+ */
+ if ((tptr = strrchr(*argv, '/')) != NULL)
+ prog_name = ++tptr;
+ else
+ prog_name = *argv;
+ argc--;
+ argv++;
+ /*
+ * parse arguments
+ */
+ while ((argc >= 1) && (argv[0][0] == '-')) {
+ switch (argv[0][1]) {
+ case 'a':
+ any++;
+ break;
+ case 'd':
+ if ((name) || (device) || (update) || (tp)) {
+ dmapi_err(EINVOKE,
+ gettext("option conflict"));
+ }
+ device++;
+ break;
+ case 'f':
+ argc--;
+ argv++;
+ if (argc <= 0)
+ dmapi_err(EINVOKE,
+ gettext("missing file name"));
+ filename = *argv;
+ file++;
+ break;
+ case 'n':
+ if ((name) || (device) || (update) || (tp)) {
+ dmapi_err(EINVOKE,
+ gettext("option conflict"));
+ }
+ name++;
+ break;
+ case 't':
+ if ((name) || (device) || (update) || (tp)) {
+ dmapi_err(EINVOKE,
+ gettext("option conflict"));
+ }
+ tp++;
+ break;
+ case 'u':
+ if ((name) || (device) || (update) || (tp)) {
+ dmapi_err(EINVOKE,
+ gettext("option conflict"));
+ }
+ update++;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ default:
+ dmapi_err(EINVOKE,
+ gettext("bad option"));
+ break;
+ }
+ argc--;
+ argv++;
+ }
+ /*
+ * -d(device) -n(name) and -u(update) switches require at least one
+ * argument.
+ */
+ if (file)
+ setdmapfile(filename);
+ if ((device) || (name) || (update) || (tp)) {
+ if (argc < 1) {
+ dmapi_err(EINVOKE,
+ gettext("insufficient args for this option"));
+ }
+ }
+ if (update) {
+ /*
+ * -u(update) switch requires only one argument
+ */
+ if (argc != 1) {
+ dmapi_err(EINVOKE,
+ gettext("too many args for this option"));
+ }
+ /*
+ * read entry argument from stdin into a devmap_t known as dmap
+ */
+ if ((dmap.dmap_devname = getdmapfield(*argv)) == NULL) {
+ dmapi_err(EINVOKE,
+ gettext("Bad dmap_devname in entry argument"));
+ }
+ if ((dmap.dmap_devtype = getdmapfield(NULL)) ==
+ NULL) {
+ dmapi_err(EINVOKE,
+ gettext("Bad dmap_devtype in entry Argument"));
+ }
+ if ((dmap.dmap_devlist = getdmapfield(NULL)) ==
+ NULL) {
+ dmapi_err(EINVOKE,
+ gettext("Bad dmap_devlist in entry argument"));
+ }
+ /*
+ * Find out how long device list is and create a buffer to
+ * hold it. Then copy it there. This is done since we do not
+ * want to corrupt the existing string.
+ */
+ cntr = strlen(dmap.dmap_devlist) + 1;
+ mptr = calloc((unsigned)cntr, sizeof (char));
+ if (mptr == NULL) {
+ if (verbose) {
+ (void) fprintf(stderr,
+ gettext(
+ "dmapinfo: Cannot calloc memory\n"));
+ }
+ exit(1);
+ }
+ (void) strcpy(mptr, dmap.dmap_devlist);
+ /*
+ * open the device maps file for read/ write. We are not
+ * sure we want to write to it yet but we may and this is a
+ * easy way to get the file descriptor. We want the file
+ * descriptor so we can lock the file.
+ */
+ if ((des = open(filename, O_RDWR)) < 0) {
+ if (verbose) {
+ (void) fprintf(stderr,
+ gettext("dmapinfo: Cannot open %s\n"),
+ filename);
+ }
+ exit(1);
+ }
+ cntr = 0;
+#ifdef CMW
+ while ((status = flock(des, LOCK_EX | LOCK_NB) == -1) &&
+ (cntr++ < RETRY_COUNT)) {
+ (void) sleep(RETRY_SLEEP);
+ }
+#else
+ while (((status = lockf(des, F_TLOCK, 0)) == -1) &&
+ (cntr++ < RETRY_COUNT)) {
+ (void) sleep(RETRY_SLEEP);
+ }
+#endif
+ if (status == -1) {
+ if (verbose) {
+ (void) fprintf(stderr,
+ gettext("dmapinfo: Cannot lock %s\n"), filename);
+ }
+ exit(1);
+ }
+ /*
+ * Now that we have the device_maps file then lets check
+ * for previous entrys with the same name. If it already
+ * exists then we will exit with status of 1.
+ */
+ if (verbose) {
+ (void) fprintf(stderr,
+ gettext("dmapinfo: Checking %s for name (%s).\n"),
+ filename, dmap.dmap_devname);
+ }
+ if (getdmapnam(dmap.dmap_devname) != NULL) {
+ if (verbose) {
+ (void) fprintf(stderr,
+ gettext("dmapinfo: Device name (%s) found in %s.\n"),
+ dmap.dmap_devname, filename);
+ }
+ exit(1);
+ }
+ if (verbose) {
+ (void) fprintf(stderr,
+ gettext("dmapinfo: Device name (%s) not found in %s.\n"),
+ dmap.dmap_devname, filename);
+ }
+ /*
+ * We now Know name does not exist and now we need to check
+ * to see if any of the devices in the device list are in the
+ * device maps file. If the already exist then we will exit
+ * with a status of 1.
+ */
+ nptr = mptr;
+ nptr = getdmapdfield(nptr);
+ while (nptr) {
+ if (verbose) {
+ (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);
+ }
+ exit(1);
+ }
+ if (verbose) {
+ (void) fprintf(stderr,
+ gettext("dmapinfo: "
+ "Device (%s) not found in %s.\n"),
+ nptr, filename);
+ }
+ nptr = getdmapdfield(NULL);
+ }
+ /*
+ * Good the entry is uniq. So lets find out how long it is
+ * and add it to the end of device maps file in a pretty
+ * way.
+ */
+ if (verbose) {
+ (void) fprintf(stderr, "dmapinfo: Adding entry to %s\n",
+ filename);
+ printdmapent(&dmap);
+ }
+ cntr = strlen(dmap.dmap_devname);
+ cntr += strlen(dmap.dmap_devtype);
+ cntr += strlen(dmap.dmap_devlist);
+ cntr += 15;
+ tptr = calloc((unsigned)cntr, sizeof (char));
+ if (tptr == NULL) {
+ exit(1);
+ }
+ (void) strcat(tptr, dmap.dmap_devname);
+ (void) strcat(tptr, ":\\\n\t");
+ (void) strcat(tptr, dmap.dmap_devtype);
+ (void) strcat(tptr, ":\\\n\t");
+ (void) strcat(tptr, dmap.dmap_devlist);
+ (void) strcat(tptr, ":\\\n\t");
+ (void) strcat(tptr, "\n");
+ cntr = strlen(tptr);
+#ifdef CMW
+ if (lseek(des, 0L, L_XTND) == -1L) {
+ exit(1);
+ }
+#else
+ if (lseek(des, 0L, SEEK_END) == -1L) {
+ exit(1);
+ }
+#endif
+ if (write(des, tptr, cntr) == -1) {
+ exit(1);
+ }
+ if (close(des) == -1) {
+ exit(1);
+ }
+ if (verbose) {
+ (void) fprintf(stderr, "dmapinfo: Entry added to %s\n",
+ filename);
+ }
+ exit(0);
+ }
+ /*
+ * Look for devices in device_maps file. If verbose switch is set
+ * then print entry(s) found. If "any" switch is set then, if any
+ * device is found will result in a exit status of 0. If "any" switch
+ * is not set then, if any device is not will result in a exit status
+ * of 1.
+ */
+ if (device) {
+ setdmapent();
+ while (argc >= 1) {
+ if ((dmapp = getdmapdev(*argv)) != NULL) {
+ if (verbose) {
+ printdmapent(dmapp);
+ }
+ cntr++;
+ } else if (any == 0) {
+ enddmapent();
+ exit(1);
+ }
+ argc--;
+ argv++;
+ }
+ enddmapent();
+ if (cntr != 0)
+ exit(0);
+ exit(1);
+ }
+ /*
+ * Look for names in device_maps file. If verbose switch is set
+ * then print entry(s) found. If "any" switch is set then, if any
+ * name is found will result in a exit status of 0. If "any" switch
+ * is not set then, if any name is not will result in a exit status
+ * of 1.
+ */
+ if (name) {
+ setdmapent();
+ while (argc >= 1) {
+ if ((dmapp = getdmapnam(*argv)) != NULL) {
+ if (verbose) {
+ printdmapent(dmapp);
+ }
+ cntr++;
+ } else if (any == 0)
+ exit(1);
+ argc--;
+ argv++;
+ }
+ enddmapent();
+ if (cntr != 0)
+ exit(0);
+ exit(1);
+ }
+ /*
+ * Read all entrys from device maps file. If verbose flag is set
+ * then all the device maps files are printed. This is useful for
+ * piping to grep. Also this option used without the verbose option
+ * is useful to check for device maps file and for at least one
+ * entry. If the device maps file is found and there is one entry
+ * the return status is 0.
+ */
+ if (tp) {
+ cntr = 0;
+ setdmapent();
+ while (argc >= 1) {
+ while ((dmapp = getdmaptype(*argv)) != 0) {
+ cntr++;
+ if (verbose) {
+ printdmapent(dmapp);
+ }
+ }
+ if ((any == 0) && (cntr == 0)) {
+ enddmapent();
+ exit(1);
+ }
+ argc--;
+ argv++;
+ }
+ enddmapent();
+ if (cntr == 0)
+ exit(1);
+ exit(0);
+ }
+ /*
+ * Read all entrys from device maps file. If verbose flag is set
+ * then all the device maps files are printed. This is useful for
+ * piping to grep. Also this option used without the verbose option
+ * is useful to check for device maps file and for atleast one
+ * entry. If the device maps file is found and there is one entry
+ * the return status is 0.
+ */
+ cntr = 0;
+ setdmapent();
+ while ((dmapp = getdmapent()) != 0) {
+ cntr++;
+ if (verbose) {
+ printdmapent(dmapp);
+ }
+ }
+ enddmapent();
+ if (cntr == 0)
+ exit(1);
+ return (0);
+}
--- a/usr/src/cmd/allocate/mkdevalloc.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/allocate/mkdevalloc.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
- initmem(); /* initialize memory */
-
- dotape(); /* do tape */
+ 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);
- doaudio(); /* do audio */
+ 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;
+ }
- dofloppy(); /* do floppy */
+ 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;
+ }
- docd(); /* do cd */
+ initmem(); /* initialize memory */
+ 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) */
--- a/usr/src/cmd/auditconfig/auditconfig.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/auditconfig/auditconfig.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
--- a/usr/src/cmd/auditreduce/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/auditreduce/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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:
--- a/usr/src/cmd/auditreduce/auditr.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/auditreduce/auditr.h Fri Mar 24 12:29:20 2006 -0800
@@ -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"
/*
--- a/usr/src/cmd/auditreduce/auditrd.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/auditreduce/auditrd.h Fri Mar 24 12:29:20 2006 -0800
@@ -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;
--- a/usr/src/cmd/auditreduce/auditrt.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/auditreduce/auditrt.h Fri Mar 24 12:29:20 2006 -0800
@@ -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;
--- a/usr/src/cmd/auditreduce/option.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/auditreduce/option.c Fri Mar 24 12:29:20 2006 -0800
@@ -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;
- 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.
--- a/usr/src/cmd/auditreduce/token.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/auditreduce/token.c Fri Mar 24 12:29:20 2006 -0800
@@ -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 */
}
--- a/usr/src/cmd/bsmconv/bsmconv.sh Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/bsmconv/bsmconv.sh Fri Mar 24 12:29:20 2006 -0800
@@ -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.
--- a/usr/src/cmd/bsmunconv/bsmunconv.sh Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/bsmunconv/bsmunconv.sh Fri Mar 24 12:29:20 2006 -0800
@@ -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
--- a/usr/src/cmd/cmd-inet/usr.bin/netstat/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/cmd-inet/usr.bin/netstat/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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:
--- a/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c Fri Mar 24 12:29:20 2006 -0800
@@ -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 char *udp_hdr_v6 =
+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 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)
--- a/usr/src/cmd/cmd-inet/usr.sbin/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/cmd-inet/usr.sbin/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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
--- a/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c Fri Mar 24 12:29:20 2006 -0800
@@ -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,
--- a/usr/src/cmd/cmd-inet/usr.sbin/in.routed/table.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/cmd-inet/usr.sbin/in.routed/table.c Fri Mar 24 12:29:20 2006 -0800
@@ -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:
--- a/usr/src/cmd/cmd-inet/usr.sbin/route.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/cmd-inet/usr.sbin/route.c Fri Mar 24 12:29:20 2006 -0800
@@ -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)));
+ }
+}
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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:
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
}
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_capture.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_capture.c Fri Mar 24 12:29:20 2006 -0800
@@ -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;
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_dhcp.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_dhcp.c Fri Mar 24 12:29:20 2006 -0800
@@ -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) &&
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ip.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ip.c Fri Mar 24 12:29:20 2006 -0800
@@ -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;
+}
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ipaddr.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ipaddr.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ipsec.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ipsec.c Fri Mar 24 12:29:20 2006 -0800
@@ -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 */
}
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rip.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rip.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
+}
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rport.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rport.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
--- a/usr/src/cmd/devfsadm/Makefile.com Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/devfsadm/Makefile.com Fri Mar 24 12:29:20 2006 -0800
@@ -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)
--- a/usr/src/cmd/devfsadm/audio_link.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/devfsadm/audio_link.c Fri Mar 24 12:29:20 2006 -0800
@@ -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;
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/devfsadm/devalloc.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
+ }
+}
--- a/usr/src/cmd/devfsadm/devfsadm.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/devfsadm/devfsadm.c Fri Mar 24 12:29:20 2006 -0800
@@ -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>
-
-/* globals */
+#include "devfsadm_impl.h"
+
+/* 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;
-
-/* 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 check if system is labeled */
+int system_labeled = FALSE;
+
+/* 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);
--- a/usr/src/cmd/devfsadm/disk_link.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/devfsadm/disk_link.c Fri Mar 24 12:29:20 2006 -0800
@@ -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, "^");
--- a/usr/src/cmd/devfsadm/i386/misc_link_i386.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/devfsadm/i386/misc_link_i386.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
}
}
}
--- a/usr/src/cmd/devfsadm/sparc/misc_link_sparc.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/devfsadm/sparc/misc_link_sparc.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
--- a/usr/src/cmd/devfsadm/tape_link.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/devfsadm/tape_link.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
}
--- a/usr/src/cmd/devfsadm/usb_link.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/devfsadm/usb_link.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
}
--- a/usr/src/cmd/dminfo/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 1989, 2002 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
-#
-
-PROG= dminfo
-
-OBJS= dminfo.o
-SRCS= $(OBJS:%.o=%.c)
-
-include ../Makefile.cmd
-
-TEXT_DOMAIN=SUNW_BSM_DMINFO
-POS=dminfo.po
-include ../Makefile.cmd.bsm
-
-FILEMODE= 755
-
-LDLIBS += -lbsm
-
-.KEEP_STATE:
-
-all: $(PROG)
-
-install: all $(ROOTUSRSBINPROG)
-
-clean:
- rm -rf $(OBJS) $(POS)
-
-lint: lint_PROG
-
-include ../Makefile.targ
--- a/usr/src/cmd/dminfo/dminfo.c Thu Mar 23 19:49:27 2006 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,479 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#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 <string.h>
-#include <string.h>
-#include <unistd.h>
-#include <malloc.h>
-#include <memory.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/file.h>
-#include <fcntl.h>
-#include <bsm/devices.h>
-#define DMPFILE "/etc/security/device_maps"
-#define RETRY_SLEEP 6
-#define RETRY_COUNT 10
-#define EINVOKE 2
-#define EFAIL 1
-
-#if !defined(TEXT_DOMAIN)
-#define TEXT_DOMAIN "SUNW_BSM_DMINFO"
-#endif
-
-extern off_t lseek();
-
-char *getdmapfield();
-char *getdmapdfield();
-static void printdmapent();
-static void dmapi_err();
-
-static char *prog_name;
-
-/*
- * printdmapent(dmapp) prints a devmap_t structure pointed to by dmapp.
- */
-static void
-printdmapent(dmapp)
- devmap_t *dmapp;
-{
- (void) printf("%s:", dmapp->dmap_devname);
- (void) printf("%s:", dmapp->dmap_devtype);
- (void) printf("%s:", dmapp->dmap_devlist);
- (void) printf("\n");
-}
-
-
-/*
- * dmapi_err(exit_code,err_msg) prints message pointed to by err_msg to
- * stderr. Then prints usage message to stderr. Then exits program with
- * exit_code.
- *
- */
-static void
-dmapi_err(exit_code, err_msg)
-int exit_code;
-char *err_msg;
-{
- if (err_msg != NULL) {
- (void) fprintf(stderr, "dmapinfo:%s\n", err_msg);
- }
- if (exit_code == EINVOKE) {
- (void) fprintf(stderr,
- "Usage: %s [-v] [-a] [-f filename] %s\n",
- prog_name,
- "[-d device ...]");
- (void) fprintf(stderr,
- " %s [-v] [-a] [-f filename] %s\n",
- prog_name,
- "[-n name ...]");
- (void) fprintf(stderr,
- " %s [-v] [-a] [-f filename] %s\n",
- prog_name,
- "[-t type ...]");
- (void) fprintf(stderr,
- " %s [-v] [-a] [-f filename] %s\n",
- prog_name,
- "[-u Entry]");
- }
- exit(exit_code);
-}
-
-
-int
-main(int argc, char *argv[])
-{
- devmap_t *dmapp;
- devmap_t dmap;
- char *mptr;
- char *tptr;
- char *nptr;
- char *filename = DMPFILE;
- int name = 0;
- int device = 0;
- int file = 0;
- int verbose = 0;
- int cntr = 0;
- int any = 0;
- int update = 0;
- int tp = 0;
- int des;
- int status;
-
- /* Internationalization */
- (void) setlocale(LC_ALL, "");
- (void) textdomain(TEXT_DOMAIN);
-
- /*
- * point prog_name to invocation name
- */
- if ((tptr = strrchr(*argv, '/')) != NULL)
- prog_name = ++tptr;
- else
- prog_name = *argv;
- argc--;
- argv++;
- /*
- * parse arguments
- */
- while ((argc >= 1) && (argv[0][0] == '-')) {
- switch (argv[0][1]) {
- case 'a':
- any++;
- break;
- case 'd':
- if ((name) || (device) || (update) || (tp)) {
- dmapi_err(EINVOKE,
- gettext("option conflict"));
- }
- device++;
- break;
- case 'f':
- argc--;
- argv++;
- if (argc <= 0)
- dmapi_err(EINVOKE,
- gettext("missing file name"));
- filename = *argv;
- file++;
- break;
- case 'n':
- if ((name) || (device) || (update) || (tp)) {
- dmapi_err(EINVOKE,
- gettext("option conflict"));
- }
- name++;
- break;
- case 't':
- if ((name) || (device) || (update) || (tp)) {
- dmapi_err(EINVOKE,
- gettext("option conflict"));
- }
- tp++;
- break;
- case 'u':
- if ((name) || (device) || (update) || (tp)) {
- dmapi_err(EINVOKE,
- gettext("option conflict"));
- }
- update++;
- break;
- case 'v':
- verbose++;
- break;
- default:
- dmapi_err(EINVOKE,
- gettext("bad option"));
- break;
- }
- argc--;
- argv++;
- }
- /*
- * -d(device) -n(name) and -u(update) switches require at least one
- * argument.
- */
- if (file)
- setdmapfile(filename);
- if ((device) || (name) || (update) || (tp)) {
- if (argc < 1) {
- dmapi_err(EINVOKE,
- gettext("insufficient args for this option"));
- }
- }
- if (update) {
- /*
- * -u(update) switch requires only one argument
- */
- if (argc != 1) {
- dmapi_err(EINVOKE,
- gettext("too many args for this option"));
- }
- /*
- * read entry argument from stdin into a devmap_t known as dmap
- */
- if ((dmap.dmap_devname = getdmapfield(*argv)) == NULL) {
- dmapi_err(EINVOKE,
- gettext("Bad dmap_devname in entry argument"));
- }
- if ((dmap.dmap_devtype = getdmapfield((char *)NULL)) ==
- NULL) {
- dmapi_err(EINVOKE,
- gettext("Bad dmap_devtype in entry Argument"));
- }
- if ((dmap.dmap_devlist = getdmapfield((char *)NULL)) ==
- NULL) {
- dmapi_err(EINVOKE,
- gettext("Bad dmap_devlist in entry argument"));
- }
- /*
- * Find out how long device list is and create a buffer to
- * hold it. Then copy it there. This is done since we do not
- * want to corrupt the existing string.
- */
- cntr = strlen(dmap.dmap_devlist) + 1;
- mptr = calloc((unsigned)cntr, sizeof (char));
- if (mptr == NULL) {
- if (verbose) {
- (void) fprintf(stderr,
- gettext(
- "dmapinfo: Cannot calloc memory\n"));
- }
- exit(1);
- }
- (void) strcpy(mptr, dmap.dmap_devlist);
- /*
- * open the device maps file for read/ write. We are not
- * sure we want to write to it yet but we may and this is a
- * easy way to get the file descriptor. We want the file
- * descriptor so we can lock the file.
- */
- if ((des = open(filename, O_RDWR)) < 0) {
- if (verbose) {
- (void) fprintf(stderr,
- gettext("dmapinfo: Cannot open %s\n"),
- filename);
- }
- exit(1);
- }
- cntr = 0;
-#ifdef CMW
- while ((status = flock(des, LOCK_EX | LOCK_NB) == -1) &&
- (cntr++ < RETRY_COUNT)) {
- (void) sleep(RETRY_SLEEP);
- }
-#else
- while (((status = lockf(des, F_TLOCK, 0)) == -1) &&
- (cntr++ < RETRY_COUNT)) {
- (void) sleep(RETRY_SLEEP);
- }
-#endif
- if (status == -1) {
- if (verbose) {
- (void) fprintf(stderr,
- gettext("dmapinfo: Cannot lock %s\n"), filename);
- }
- exit(1);
- }
- /*
- * Now that we have the device_maps file then lets check
- * for previous entrys with the same name. If it already
- * exists then we will exit with status of 1.
- */
- if (verbose) {
- (void) fprintf(stderr,
- gettext("dmapinfo: Checking %s for name (%s).\n"),
- filename, dmap.dmap_devname);
- }
- if (getdmapnam(dmap.dmap_devname) != NULL) {
- if (verbose) {
- (void) fprintf(stderr,
- gettext("dmapinfo: Device name (%s) found in %s.\n"),
- dmap.dmap_devname, filename);
- }
- exit(1);
- }
- if (verbose) {
- (void) fprintf(stderr,
- gettext("dmapinfo: Device name (%s) not found in %s.\n"),
- dmap.dmap_devname, filename);
- }
- /*
- * We now Know name does not exist and now we need to check
- * to see if any of the devices in the device list are in the
- * device maps file. If the already exist then we will exit
- * with a status of 1.
- */
- nptr = mptr;
- nptr = getdmapdfield(nptr);
- while (nptr) {
- if (verbose) {
-(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);
- }
- exit(1);
- }
- if (verbose) {
-(void) fprintf(stderr, gettext("dmapinfo: Device (%s) not found in %s.\n"),
- nptr, filename);
- }
- nptr = getdmapdfield((char *)NULL);
- }
- /*
- * Good the entry is uniq. So lets find out how long it is
- * and add it to the end of device maps file in a pretty
- * way.
- */
- if (verbose) {
- (void) fprintf(stderr, "dmapinfo: Adding entry to %s\n",
- filename);
- printdmapent(&dmap);
- }
- cntr = strlen(dmap.dmap_devname);
- cntr += strlen(dmap.dmap_devtype);
- cntr += strlen(dmap.dmap_devlist);
- cntr += 15;
- tptr = calloc((unsigned)cntr, sizeof (char));
- if (tptr == NULL) {
- exit(1);
- }
- (void) strcat(tptr, dmap.dmap_devname);
- (void) strcat(tptr, ":\\\n\t");
- (void) strcat(tptr, dmap.dmap_devtype);
- (void) strcat(tptr, ":\\\n\t");
- (void) strcat(tptr, dmap.dmap_devlist);
- (void) strcat(tptr, ":\\\n\t");
- (void) strcat(tptr, "\n");
- cntr = strlen(tptr);
-#ifdef CMW
- if (lseek(des, 0L, L_XTND) == -1L) {
- exit(1);
- }
-#else
- if (lseek(des, 0L, SEEK_END) == -1L) {
- exit(1);
- }
-#endif
- if (write(des, tptr, cntr) == -1) {
- exit(1);
- }
- if (close(des) == -1) {
- exit(1);
- }
- if (verbose) {
- (void) fprintf(stderr, "dmapinfo: Entry added to %s\n",
- filename);
- }
- exit(0);
- }
- /*
- * Look for devices in device_maps file. If verbose switch is set
- * then print entry(s) found. If "any" switch is set then, if any
- * device is found will result in a exit status of 0. If "any" switch
- * is not set then, if any device is not will result in a exit status
- * of 1.
- */
- if (device) {
- while (argc >= 1) {
- if ((dmapp = getdmapdev(*argv)) != NULL) {
- if (verbose) {
- printdmapent(dmapp);
- }
- cntr++;
- } else if (any == 0)
- exit(1);
- argc--;
- argv++;
- }
- if (cntr != 0)
- exit(0);
- exit(1);
- }
- /*
- * Look for names in device_maps file. If verbose switch is set
- * then print entry(s) found. If "any" switch is set then, if any
- * name is found will result in a exit status of 0. If "any" switch
- * is not set then, if any name is not will result in a exit status
- * of 1.
- */
- if (name) {
- while (argc >= 1) {
- if ((dmapp = getdmapnam(*argv)) != NULL) {
- if (verbose) {
- printdmapent(dmapp);
- }
- cntr++;
- } else if (any == 0)
- exit(1);
- argc--;
- argv++;
- }
- if (cntr != 0)
- exit(0);
- exit(1);
- }
- /*
- * Read all entrys from device maps file. If verbose flag is set
- * then all the device maps files are printed. This is useful for
- * piping to grep. Also this option used without the verbose option
- * is useful to check for device maps file and for at least one
- * entry. If the device maps file is found and there is one entry
- * the return status is 0.
- */
- if (tp) {
- cntr = 0;
- while (argc >= 1) {
- setdmapent();
- while ((dmapp = getdmaptype(*argv)) != 0) {
- cntr++;
- if (verbose) {
- printdmapent(dmapp);
- }
- }
- enddmapent();
- if ((any == 0) && (cntr == 0))
- exit(1);
- argc--;
- argv++;
- }
- if (cntr == 0)
- exit(1);
- exit(0);
- }
- /*
- * Read all entrys from device maps file. If verbose flag is set
- * then all the device maps files are printed. This is useful for
- * piping to grep. Also this option used without the verbose option
- * is useful to check for device maps file and for atleast one
- * entry. If the device maps file is found and there is one entry
- * the return status is 0.
- */
- cntr = 0;
- setdmapent();
- while ((dmapp = getdmapent()) != 0) {
- cntr++;
- if (verbose) {
- printdmapent(dmapp);
- }
- }
- enddmapent();
- if (cntr == 0)
- exit(1);
- return (0);
-}
--- a/usr/src/cmd/fs.d/autofs/auto_subr.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/fs.d/autofs/auto_subr.c Fri Mar 24 12:29:20 2006 -0800
@@ -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)
--- a/usr/src/cmd/fs.d/autofs/autod_lookup.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/fs.d/autofs/autod_lookup.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
--- a/usr/src/cmd/fs.d/autofs/autod_main.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/fs.d/autofs/autod_main.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
--- a/usr/src/cmd/fs.d/autofs/autod_nfs.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/fs.d/autofs/autod_nfs.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
+}
--- a/usr/src/cmd/fs.d/nfs/lib/nfs_tbind.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/fs.d/nfs/lib/nfs_tbind.c Fri Mar 24 12:29:20 2006 -0800
@@ -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)
{
--- a/usr/src/cmd/fs.d/nfs/mountd/mountd.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/fs.d/nfs/mountd/mountd.c Fri Mar 24 12:29:20 2006 -0800
@@ -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) {
--- a/usr/src/cmd/fs.d/nfs/nfsd/nfsd.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/fs.d/nfs/nfsd/nfsd.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
--- a/usr/src/cmd/fs.d/nfs/statd/sm_svc.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/fs.d/nfs/statd/sm_svc.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
}
--- a/usr/src/cmd/ldap/Makefile.com Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/ldap/Makefile.com Fri Mar 24 12:29:20 2006 -0800
@@ -1,3 +1,23 @@
+#
+# 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
--- a/usr/src/cmd/ldap/ns_ldap/idsconfig.sh Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/ldap/ns_ldap/idsconfig.sh Fri Mar 24 12:29:20 2006 -0800
@@ -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}"
--- a/usr/src/cmd/ldap/ns_ldap/ldapaddent.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/ldap/ns_ldap/ldapaddent.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
--- a/usr/src/cmd/ldap/ns_ldap/ldapaddent.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/ldap/ns_ldap/ldapaddent.h Fri Mar 24 12:29:20 2006 -0800
@@ -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
}
--- a/usr/src/cmd/ldap/ns_ldap/ldapaddrbac.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/ldap/ns_ldap/ldapaddrbac.c Fri Mar 24 12:29:20 2006 -0800
@@ -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 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/ldap/ns_ldap/ldapaddtsol.c Fri Mar 24 12:29:20 2006 -0800
@@ -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');
+}
--- a/usr/src/cmd/ldap/ns_ldap/mapping.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/ldap/ns_ldap/mapping.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
}
}
--- a/usr/src/cmd/lp/cmd/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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:
--- a/usr/src/cmd/lp/cmd/adaptor/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/adaptor/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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
--- a/usr/src/cmd/lp/cmd/adaptor/cancel_job.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/adaptor/cancel_job.c Fri Mar 24 12:29:20 2006 -0800
@@ -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"));
--- a/usr/src/cmd/lp/cmd/adaptor/misc.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/adaptor/misc.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
}
--- a/usr/src/cmd/lp/cmd/adaptor/misc.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/adaptor/misc.h Fri Mar 24 12:29:20 2006 -0800
@@ -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 */
--- a/usr/src/cmd/lp/cmd/adaptor/show_queue.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/adaptor/show_queue.c Fri Mar 24 12:29:20 2006 -0800
@@ -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
--- a/usr/src/cmd/lp/cmd/adaptor/submit_job.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/adaptor/submit_job.c Fri Mar 24 12:29:20 2006 -0800
@@ -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;
}
--- a/usr/src/cmd/lp/cmd/lpadmin/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/lpadmin/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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
--- a/usr/src/cmd/lp/cmd/lpadmin/do_printer.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/lpadmin/do_printer.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
+}
--- a/usr/src/cmd/lp/cmd/lpadmin/lpadmin.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/lpadmin/lpadmin.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
--- a/usr/src/cmd/lp/cmd/lpadmin/lpadmin.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/lpadmin/lpadmin.h Fri Mar 24 12:29:20 2006 -0800
@@ -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 , ... );
--- a/usr/src/cmd/lp/cmd/lpadmin/rmdest.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/lpadmin/rmdest.c Fri Mar 24 12:29:20 2006 -0800
@@ -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:
--- a/usr/src/cmd/lp/cmd/lpc/process.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/lpc/process.c Fri Mar 24 12:29:20 2006 -0800
@@ -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,
--- a/usr/src/cmd/lp/cmd/lpc/topq.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/lpc/topq.c Fri Mar 24 12:29:20 2006 -0800
@@ -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,
--- a/usr/src/cmd/lp/cmd/lpsched/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/lpsched/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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)
--- a/usr/src/cmd/lp/cmd/lpsched/disp1.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/lpsched/disp1.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
+}
--- a/usr/src/cmd/lp/cmd/lpsched/dispatch.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/lpsched/dispatch.h Fri Mar 24 12:29:20 2006 -0800
@@ -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[]
--- a/usr/src/cmd/lp/cmd/lpsched/disptab.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/lpsched/disptab.c Fri Mar 24 12:29:20 2006 -0800
@@ -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 */
--- a/usr/src/cmd/lp/cmd/lpsched/exec.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/lpsched/exec.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
--- a/usr/src/cmd/lp/cmd/lpsched/validate.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/lpsched/validate.c Fri Mar 24 12:29:20 2006 -0800
@@ -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 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) {
- if ((wants_nobanner == 1) && (lp_or_root != 1)) {
- /* delete "nobanner" */
- char **list;
+ /* 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);
+}
--- a/usr/src/cmd/lp/cmd/lpstat/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/lpstat/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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
--- a/usr/src/cmd/lp/cmd/lpstat/lpstat.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/lpstat/lpstat.h Fri Mar 24 12:29:20 2006 -0800
@@ -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 *);
--- a/usr/src/cmd/lp/cmd/lpstat/output.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/lpstat/output.c Fri Mar 24 12:29:20 2006 -0800
@@ -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;
}
--- a/usr/src/cmd/lp/cmd/lpstat/request.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/lpstat/request.c Fri Mar 24 12:29:20 2006 -0800
@@ -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))) {
/*
--- a/usr/src/cmd/lp/cmd/lpsystem.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/cmd/lpsystem.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
+ }
}
}
/*==================================================================*/
--- a/usr/src/cmd/lp/include/lp.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/include/lp.h Fri Mar 24 12:29:20 2006 -0800
@@ -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
--- a/usr/src/cmd/lp/include/msgs.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/include/msgs.h Fri Mar 24 12:29:20 2006 -0800
@@ -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;
--- a/usr/src/cmd/lp/include/secure.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/include/secure.h Fri Mar 24 12:29:20 2006 -0800
@@ -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;
/**
--- a/usr/src/cmd/lp/lib/access/allowed.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/lib/access/allowed.c Fri Mar 24 12:29:20 2006 -0800
@@ -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));
+}
--- a/usr/src/cmd/lp/lib/lp/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/lib/lp/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/lp/lib/lp/tx.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
+}
--- a/usr/src/cmd/lp/lib/msgs/mlisten.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/lib/msgs/mlisten.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
--- a/usr/src/cmd/lp/lib/msgs/msgfmts.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/lib/msgs/msgfmts.c Fri Mar 24 12:29:20 2006 -0800
@@ -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,
};
--- a/usr/src/cmd/lp/lib/papi/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/lib/papi/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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
--- a/usr/src/cmd/lp/lib/papi/job.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/lib/papi/job.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
--- a/usr/src/cmd/lp/lib/papi/lpsched-jobs.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/lib/papi/lpsched-jobs.c Fri Mar 24 12:29:20 2006 -0800
@@ -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
--- a/usr/src/cmd/lp/lib/papi/mapfile-vers Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/lib/papi/mapfile-vers Fri Mar 24 12:29:20 2006 -0800
@@ -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;
--- a/usr/src/cmd/lp/lib/papi/papi_impl.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/lib/papi/papi_impl.h Fri Mar 24 12:29:20 2006 -0800
@@ -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,
--- a/usr/src/cmd/lp/lib/papi/printer.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/lib/papi/printer.c Fri Mar 24 12:29:20 2006 -0800
@@ -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';
--- a/usr/src/cmd/lp/lib/papi/service.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/lib/papi/service.c Fri Mar 24 12:29:20 2006 -0800
@@ -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)
{
--- a/usr/src/cmd/lp/lib/secure/secure.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/lp/lib/secure/secure.c Fri Mar 24 12:29:20 2006 -0800
@@ -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);
--- a/usr/src/cmd/mdb/common/modules/genunix/genunix.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/mdb/common/modules/genunix/genunix.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
--- a/usr/src/cmd/mdb/common/modules/genunix/net.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/mdb/common/modules/genunix/net.c Fri Mar 24 12:29:20 2006 -0800
@@ -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 ||
+ ire->ire_type == IRE_BROADCAST || ire->ire_type == IRE_LOCAL))
+ return (WALK_NEXT);
+
+ if (*opts & NETSTAT_FIRST) {
+ *opts &= ~NETSTAT_FIRST;
+ mdb_printf("%<u>%s Table: IPv4%</u>\n",
+ (*opts & NETSTAT_VERBOSE) ? "IRE" : "Routing");
+ if (*opts & NETSTAT_VERBOSE) {
+ mdb_printf("%<u>%-?s %-*s %-*s %-*s Device Mxfrg Rtt "
+ " Ref Flg Out In/Fwd%</u>\n",
+ "Address", ADDR_V4_WIDTH, "Destination",
+ ADDR_V4_WIDTH, "Mask", ADDR_V4_WIDTH, "Gateway");
+ } else {
+ mdb_printf("%<u>%-?s %-*s %-*s Flags Ref Use "
+ "Interface%</u>\n",
+ "Address", ADDR_V4_WIDTH, "Destination",
+ ADDR_V4_WIDTH, "Gateway");
+ }
+ }
+
+ gate = (ire->ire_type & (IRE_INTERFACE|IRE_LOOPBACK|IRE_BROADCAST)) ?
+ ire->ire_src_addr : ire->ire_gateway_addr;
+
+ get_v4flags(ire, flags);
+
+ get_ifname(ire, intf);
+
+ if (*opts & NETSTAT_VERBOSE) {
+ mdb_printf("%?p %-*I %-*I %-*I %-6s %5u%c %4u %3u %-3s %5u "
+ "%u\n", kaddr, ADDR_V4_WIDTH, ire->ire_addr, ADDR_V4_WIDTH,
+ ire->ire_mask, ADDR_V4_WIDTH, gate, intf,
+ ire->ire_max_frag, ire->ire_frag_flag ? '*' : ' ',
+ ire->ire_uinfo.iulp_rtt, ire->ire_refcnt, flags,
+ ire->ire_ob_pkt_count, ire->ire_ib_pkt_count);
+ } else {
+ mdb_printf("%?p %-*I %-*I %-5s %4u %5u %s\n", kaddr,
+ ADDR_V4_WIDTH, ire->ire_addr, ADDR_V4_WIDTH, gate, flags,
+ ire->ire_refcnt,
+ ire->ire_ob_pkt_count + ire->ire_ib_pkt_count, intf);
+ }
+
+ return (WALK_NEXT);
+}
+
+static int
+netstat_irev4src_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], srcif[LIFNAMSIZ + 1];
+ char dest[ADDR_V4_WIDTH + 3 + 1];
+ ill_t ill;
+
+ 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 ||
+ ire->ire_type == IRE_BROADCAST || ire->ire_type == IRE_LOCAL))
+ return (WALK_NEXT);
+
+ if (*opts & NETSTAT_FIRST) {
+ *opts &= ~NETSTAT_FIRST;
+ mdb_printf("\n%<u>%s Table: IPv4 Source-Specific%</u>\n",
+ (*opts & NETSTAT_VERBOSE) ? "IRE" : "Routing");
+ if (*opts & NETSTAT_VERBOSE) {
+ mdb_printf("%<u>%-?s %-*s In If %-*s %-*s "
+ "Out If Mxfrg Rtt Ref Flg Out In/Fwd"
+ "%</u>\n",
+ "Address", ADDR_V4_WIDTH+3, "Destination",
+ ADDR_V4_WIDTH, "Source", ADDR_V4_WIDTH, "Gateway");
+ } else {
+ mdb_printf("%<u>%-?s %-*s In If %-*s %-*s Flags "
+ "Ref Use Out If%</u>\n",
+ "Address", ADDR_V4_WIDTH+3, "Destination",
+ ADDR_V4_WIDTH, "Source", ADDR_V4_WIDTH, "Gateway");
+ }
+ }
+
+ gate = (ire->ire_type & (IRE_INTERFACE|IRE_LOOPBACK|IRE_BROADCAST)) ?
+ ire->ire_src_addr : ire->ire_gateway_addr;
+
+ get_v4flags(ire, flags);
+
+ get_ifname(ire, intf);
+
+ srcif[0] = '\0';
+ if (mdb_vread(&ill, sizeof (ill), (uintptr_t)ire->ire_in_ill) != -1)
+ (void) mdb_readstr(srcif, MIN(LIFNAMSIZ, ill.ill_name_length),
+ (uintptr_t)ill.ill_name);
+
+ if (ire->ire_in_src_addr != 0 && ire->ire_addr == 0 &&
+ ire->ire_mask == 0)
+ strcpy(dest, " --");
+ else
+ mdb_snprintf(dest, sizeof (dest), "%I/%d", ire->ire_addr,
+ ip_mask_to_plen(ire->ire_mask));
+
+ if (*opts & NETSTAT_VERBOSE) {
+ mdb_printf("%?p %-*s %-11s %-*I %-*I %-11s %5u%c %4u %3u %-3s "
+ "%5u %u\n", kaddr, ADDR_V4_WIDTH+3, dest, srcif,
+ ADDR_V4_WIDTH, ire->ire_in_src_addr, ADDR_V4_WIDTH, gate,
+ intf, ire->ire_max_frag, ire->ire_frag_flag ? '*' : ' ',
+ ire->ire_uinfo.iulp_rtt, ire->ire_refcnt, flags,
+ ire->ire_ob_pkt_count, ire->ire_ib_pkt_count);
+ } else {
+ mdb_printf("%?p %-*s %-8s %-*I %-*I %-5s %4u %5u %s\n", kaddr,
+ ADDR_V4_WIDTH+3, dest, srcif, ADDR_V4_WIDTH,
+ ire->ire_in_src_addr, ADDR_V4_WIDTH, gate, flags,
+ ire->ire_refcnt,
+ ire->ire_ob_pkt_count + ire->ire_ib_pkt_count, intf);
+ }
+
+ return (WALK_NEXT);
+}
+
+int
+ip_mask_to_plen_v6(const in6_addr_t *v6mask)
+{
+ int plen;
+ int i;
+ uint32_t val;
+
+ for (i = 3; i >= 0; i--)
+ if (v6mask->s6_addr32[i] != 0)
+ break;
+ if (i < 0)
+ return (0);
+ plen = 32 + 32 * i;
+ val = v6mask->s6_addr32[i];
+ while (!(val & 1)) {
+ val >>= 1;
+ plen--;
+ }
+
+ return (plen);
+}
+
+static int
+netstat_irev6_cb(uintptr_t kaddr, const void *walk_data, void *cb_data)
+{
+ const ire_t *ire = walk_data;
+ uint_t *opts = cb_data;
+ const in6_addr_t *gatep;
+ char deststr[ADDR_V6_WIDTH + 5];
+ char flags[10], intf[LIFNAMSIZ + 1];
+ int masklen;
+
+ if (ire->ire_ipversion != IPV6_VERSION)
+ return (WALK_NEXT);
+
+ if (!(*opts & NETSTAT_ALL) && ire->ire_type == IRE_CACHE)
+ return (WALK_NEXT);
+
+ if (*opts & NETSTAT_FIRST) {
+ *opts &= ~NETSTAT_FIRST;
+ mdb_printf("\n%<u>%s Table: IPv6%</u>\n",
+ (*opts & NETSTAT_VERBOSE) ? "IRE" : "Routing");
+ if (*opts & NETSTAT_VERBOSE) {
+ mdb_printf("%<u>%-?s %-*s %-*s If PMTU Rtt Ref "
+ "Flags Out In/Fwd%</u>\n",
+ "Address", ADDR_V6_WIDTH+4, "Destination/Mask",
+ ADDR_V6_WIDTH, "Gateway");
+ } else {
+ mdb_printf("%<u>%-?s %-*s %-*s Flags Ref Use If"
+ "%</u>\n",
+ "Address", ADDR_V6_WIDTH+4, "Destination/Mask",
+ ADDR_V6_WIDTH, "Gateway");
+ }
+ }
+
+ gatep = (ire->ire_type & (IRE_INTERFACE|IRE_LOOPBACK)) ?
+ &ire->ire_src_addr_v6 : &ire->ire_gateway_addr_v6;
+
+ masklen = ip_mask_to_plen_v6(&ire->ire_mask_v6);
+ (void) mdb_snprintf(deststr, sizeof (deststr), "%N/%d",
+ &ire->ire_addr_v6, masklen);
+
+ (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 (masklen == IPV6_ABITS)
+ (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_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");
+
+ get_ifname(ire, intf);
+
+ if (*opts & NETSTAT_VERBOSE) {
+ mdb_printf("%?p %-*s %-*N %-5s %5u%c %5u %3u %-5s %6u %u\n",
+ kaddr, ADDR_V6_WIDTH+4, deststr, ADDR_V6_WIDTH, gatep,
+ intf, ire->ire_max_frag, ire->ire_frag_flag ? '*' : ' ',
+ ire->ire_uinfo.iulp_rtt, ire->ire_refcnt,
+ flags, ire->ire_ob_pkt_count, ire->ire_ib_pkt_count);
+ } else {
+ mdb_printf("%?p %-*s %-*N %-5s %3u %6u %s\n", kaddr,
+ ADDR_V6_WIDTH+4, deststr, ADDR_V6_WIDTH, gatep, flags,
+ ire->ire_refcnt,
+ ire->ire_ob_pkt_count + ire->ire_ib_pkt_count, intf);
+ }
+
+ return (WALK_NEXT);
+}
+
/*ARGSUSED*/
int
netstat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
@@ -800,23 +1104,55 @@
if (mdb_getopts(argc, argv,
'a', MDB_OPT_SETBITS, NETSTAT_ALL, &opts,
- 'v', MDB_OPT_SETBITS, NETSTAT_VERBOSE, &opts,
'f', MDB_OPT_STR, &optf,
'P', MDB_OPT_STR, &optP,
+ 'r', MDB_OPT_SETBITS, NETSTAT_ROUTE, &opts,
+ 'v', MDB_OPT_SETBITS, NETSTAT_VERBOSE, &opts,
NULL) != argc)
return (DCMD_USAGE);
if (optP != NULL) {
if ((strcmp("tcp", optP) != 0) && (strcmp("udp", optP) != 0))
return (DCMD_USAGE);
-
+ if (opts & NETSTAT_ROUTE)
+ return (DCMD_USAGE);
}
- if (optf != NULL) {
- if ((strcmp("inet", optf) != 0) &&
- (strcmp("inet6", optf) != 0) &&
- (strcmp("unix", optf) != 0))
+ if (optf == NULL)
+ opts |= NETSTAT_V4 | NETSTAT_V6 | NETSTAT_UNIX;
+ else if (strcmp("inet", optf) == 0)
+ opts |= NETSTAT_V4;
+ else if (strcmp("inet6", optf) == 0)
+ opts |= NETSTAT_V6;
+ else if (strcmp("unix", optf) == 0)
+ opts |= NETSTAT_UNIX;
+ else
+ return (DCMD_USAGE);
+
+ if (opts & NETSTAT_ROUTE) {
+ if (!(opts & (NETSTAT_V4|NETSTAT_V6)))
return (DCMD_USAGE);
+ if (opts & NETSTAT_V4) {
+ opts |= NETSTAT_FIRST;
+ if (mdb_walk("ip`ire", netstat_irev4_cb, &opts) == -1) {
+ mdb_warn("failed to walk ip`ire");
+ return (DCMD_ERR);
+ }
+ opts |= NETSTAT_FIRST;
+ if (mdb_walk("ip`ire", netstat_irev4src_cb,
+ &opts) == -1) {
+ mdb_warn("failed to walk ip`ire");
+ return (DCMD_ERR);
+ }
+ }
+ if (opts & NETSTAT_V6) {
+ opts |= NETSTAT_FIRST;
+ if (mdb_walk("ip`ire", netstat_irev6_cb, &opts) == -1) {
+ mdb_warn("failed to walk ip`ire");
+ return (DCMD_ERR);
+ }
+ }
+ return (DCMD_OK);
}
if ((optP == NULL) || (strcmp("tcp", optP) == 0)) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/mdb/common/modules/genunix/tsol.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,231 @@
+/*
+ * 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/tsol/tndb.h>
+#include <sys/modhash_impl.h>
+
+#include <mdb/mdb_modapi.h>
+#include <mdb/mdb_ks.h>
+
+#include "tsol.h"
+#include "modhash.h"
+
+/* ****************** tnrh ****************** */
+
+typedef struct tnrh_walk_s {
+ tnrhc_hash_t **hptr;
+ int idx;
+ tnrhc_hash_t *tnrhc_table[TSOL_MASK_TABLE_SIZE];
+ tnrhc_hash_t *tnrhc_table_v6[TSOL_MASK_TABLE_SIZE_V6];
+} tnrh_walk_t;
+
+/*
+ * Free the mdb storage pointed to by the given per-prefix table.
+ */
+static void
+free_table(tnrhc_hash_t **table, int ntable)
+{
+ while (--ntable >= 0) {
+ if (*table != NULL)
+ mdb_free(*table, TNRHC_SIZE * sizeof (**table));
+ table++;
+ }
+}
+
+/*
+ * Read in a list of per-prefix-length hash tables. Allocate storage for the
+ * hashes that are present. On successful return, the table will contain
+ * pointers to mdb-resident storage, not kernel addresses. On failure, the
+ * contents will not point to any mdb storage.
+ */
+static int
+read_table(const char *symname, tnrhc_hash_t **table, int ntable)
+{
+ GElf_Sym tnrhc_hash;
+ tnrhc_hash_t **hp;
+ uintptr_t addr;
+
+ if (mdb_lookup_by_name(symname, &tnrhc_hash) == -1) {
+ mdb_warn("failed to read %s", symname);
+ return (-1);
+ }
+ if (mdb_vread(table, ntable * sizeof (*table),
+ tnrhc_hash.st_value) == -1) {
+ mdb_warn("can't read %s at %p", symname, tnrhc_hash.st_value);
+ return (-1);
+ }
+ for (hp = table; hp < table + ntable; hp++) {
+ if ((addr = (uintptr_t)*hp) != 0) {
+ *hp = mdb_alloc(TNRHC_SIZE * sizeof (**hp), UM_SLEEP);
+ if (mdb_vread(*hp, TNRHC_SIZE * sizeof (**hp),
+ addr) == -1) {
+ mdb_warn("can't read %s[%d] at %p", symname,
+ hp - table, addr);
+ free_table(table, (hp - table) + 1);
+ return (-1);
+ }
+ }
+ }
+ return (0);
+}
+
+int
+tnrh_walk_init(mdb_walk_state_t *wsp)
+{
+ tnrh_walk_t *twp;
+
+ twp = mdb_alloc(sizeof (*twp), UM_SLEEP);
+
+ if (read_table("tnrhc_table", twp->tnrhc_table,
+ TSOL_MASK_TABLE_SIZE) == -1) {
+ mdb_free(twp, sizeof (*twp));
+ return (WALK_ERR);
+ }
+ if (read_table("tnrhc_table_v6", twp->tnrhc_table_v6,
+ TSOL_MASK_TABLE_SIZE_V6) == -1) {
+ free_table(twp->tnrhc_table, TSOL_MASK_TABLE_SIZE);
+ mdb_free(twp, sizeof (*twp));
+ return (WALK_ERR);
+ }
+
+ twp->hptr = twp->tnrhc_table;
+ twp->idx = 0;
+ wsp->walk_addr = 0;
+ wsp->walk_data = twp;
+
+ return (WALK_NEXT);
+}
+
+int
+tnrh_walk_step(mdb_walk_state_t *wsp)
+{
+ tnrh_walk_t *twp = wsp->walk_data;
+ tsol_tnrhc_t tnrhc;
+ int status;
+
+ while (wsp->walk_addr == NULL) {
+ if (*twp->hptr == NULL || twp->idx >= TNRHC_SIZE) {
+ twp->hptr++;
+ if (twp->hptr == twp->tnrhc_table +
+ TSOL_MASK_TABLE_SIZE)
+ twp->hptr = twp->tnrhc_table_v6;
+ else if (twp->hptr == twp->tnrhc_table_v6 +
+ TSOL_MASK_TABLE_SIZE_V6)
+ return (WALK_DONE);
+ twp->idx = 0;
+ } else {
+ wsp->walk_addr = (uintptr_t)(*twp->hptr)[twp->idx++].
+ tnrh_list;
+ }
+ }
+
+ if (mdb_vread(&tnrhc, sizeof (tnrhc), wsp->walk_addr) == -1) {
+ mdb_warn("can't read tsol_tnrhc_t at %p", wsp->walk_addr);
+ return (WALK_ERR);
+ }
+
+ status = wsp->walk_callback(wsp->walk_addr, &tnrhc,
+ wsp->walk_cbdata);
+
+ wsp->walk_addr = (uintptr_t)tnrhc.rhc_next;
+ return (status);
+}
+
+void
+tnrh_walk_fini(mdb_walk_state_t *wsp)
+{
+ tnrh_walk_t *twp = wsp->walk_data;
+
+ free_table(twp->tnrhc_table, TSOL_MASK_TABLE_SIZE);
+ free_table(twp->tnrhc_table_v6, TSOL_MASK_TABLE_SIZE_V6);
+ mdb_free(twp, sizeof (*twp));
+}
+
+/* ****************** tnrhtp ****************** */
+
+typedef struct tnrhtp_walk_data_s {
+ int (*old_callback)(uintptr_t, const void *, void *);
+ void *old_cbdata;
+} tnrhtp_walk_data_t;
+
+/* ARGSUSED */
+static int
+tnrhtp_walk_callback(uintptr_t addr, const void *data, void *private)
+{
+ const struct mod_hash_entry *mhe = data;
+ tnrhtp_walk_data_t *twd = private;
+ tsol_tpc_t tpc;
+
+ if (mdb_vread(&tpc, sizeof (tpc), (uintptr_t)mhe->mhe_val) == -1) {
+ mdb_warn("failed to read tsol_tpc_t at %p", mhe->mhe_val);
+ return (WALK_ERR);
+ } else {
+ return (twd->old_callback((uintptr_t)mhe->mhe_val, &tpc,
+ twd->old_cbdata));
+ }
+}
+
+int
+tnrhtp_walk_init(mdb_walk_state_t *wsp)
+{
+ mod_hash_t *tpc_name_hash;
+
+ if (mdb_readvar(&tpc_name_hash, "tpc_name_hash") == -1) {
+ mdb_warn("failed to read tpc_name_hash");
+ return (WALK_ERR);
+ }
+
+ wsp->walk_addr = (uintptr_t)tpc_name_hash;
+
+ return (modent_walk_init(wsp));
+}
+
+int
+tnrhtp_walk_step(mdb_walk_state_t *wsp)
+{
+ tnrhtp_walk_data_t twd;
+ int retv;
+
+ twd.old_callback = wsp->walk_callback;
+ twd.old_cbdata = wsp->walk_cbdata;
+ wsp->walk_callback = tnrhtp_walk_callback;
+ wsp->walk_cbdata = &twd;
+
+ retv = modent_walk_step(wsp);
+
+ wsp->walk_callback = twd.old_callback;
+ wsp->walk_cbdata = twd.old_cbdata;
+
+ return (retv);
+}
+
+void
+tnrhtp_walk_fini(mdb_walk_state_t *wsp)
+{
+ modent_walk_fini(wsp);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/mdb/common/modules/genunix/tsol.h Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,47 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _TSOL_H
+#define _TSOL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int tnrh_walk_init(mdb_walk_state_t *);
+extern int tnrh_walk_step(mdb_walk_state_t *);
+extern void tnrh_walk_fini(mdb_walk_state_t *);
+
+extern int tnrhtp_walk_init(mdb_walk_state_t *);
+extern int tnrhtp_walk_step(mdb_walk_state_t *);
+extern void tnrhtp_walk_fini(mdb_walk_state_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TSOL_H */
--- a/usr/src/cmd/mdb/intel/amd64/genunix/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/mdb/intel/amd64/genunix/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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 @@
sysevent.c \
thread.c \
tsd.c \
+ tsol.c \
vfs.c \
zone.c
--- a/usr/src/cmd/mdb/intel/ia32/genunix/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/mdb/intel/ia32/genunix/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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 @@
sysevent.c \
thread.c \
tsd.c \
+ tsol.c \
vfs.c \
zone.c
--- a/usr/src/cmd/mdb/sparc/v9/genunix/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/mdb/sparc/v9/genunix/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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 @@
sysevent.c \
thread.c \
tsd.c \
+ tsol.c \
vfs.c \
zone.c
--- a/usr/src/cmd/netfiles/nsswitch.dns Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/netfiles/nsswitch.dns Fri Mar 24 12:29:20 2006 -0800
@@ -1,9 +1,9 @@
+#
# 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,7 +18,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.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -64,3 +64,6 @@
auth_attr: files
prof_attr: files
project: files
+
+tnrhtp: files
+tnrhdb: files
--- a/usr/src/cmd/netfiles/nsswitch.files Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/netfiles/nsswitch.files Fri Mar 24 12:29:20 2006 -0800
@@ -1,9 +1,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,7 +17,7 @@
#
# CDDL HEADER END
#
-# Copyright 2002 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"
@@ -54,3 +53,6 @@
auth_attr: files
prof_attr: files
project: files
+
+tnrhtp: files
+tnrhdb: files
--- a/usr/src/cmd/netfiles/nsswitch.ldap Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/netfiles/nsswitch.ldap Fri Mar 24 12:29:20 2006 -0800
@@ -1,9 +1,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,7 +17,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.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -62,9 +61,12 @@
# for efficient getservbyname() avoid ldap
services: files ldap
-printers: user files ldap
+printers: user files ldap
-auth_attr: files ldap
-prof_attr: files ldap
+auth_attr: files ldap
+prof_attr: files ldap
project: files ldap
+
+tnrhtp: files ldap
+tnrhdb: files ldap
--- a/usr/src/cmd/nscd/server.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/nscd/server.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -70,6 +69,10 @@
#include <ucred.h>
#include <priv.h>
#include <libscf.h>
+#include <tsol/label.h>
+#include <zone.h>
+
+#define TSOL_NAME_SERVICE_DOOR "/var/tsol/doors/name_service_door"
extern int optind;
extern int opterr;
@@ -473,6 +476,18 @@
struct sigaction action;
/*
+ * The admin model for TX is that labeled zones are managed
+ * in global zone where most trusted configuration database
+ * resides.
+ */
+ if (is_system_labeled() && (getzoneid() != GLOBAL_ZONEID)) {
+ (void) fprintf(stderr,
+ "With Trusted Extensions nscd runs only in " \
+ "the global zone.\n");
+ exit(1);
+ }
+
+ /*
* Special case non-root user here - he can just print stats
*/
@@ -802,12 +817,28 @@
/* bind to file system */
- if (stat(NAME_SERVICE_DOOR, &buf) < 0) {
+ if (is_system_labeled()) {
+ if (stat(TSOL_NAME_SERVICE_DOOR, &buf) < 0) {
+ int newfd;
+ if ((newfd = creat(TSOL_NAME_SERVICE_DOOR, 0444)) < 0) {
+ logit("Cannot create %s:%s\n",
+ TSOL_NAME_SERVICE_DOOR, strerror(errno));
+ exit(1);
+ }
+ (void) close(newfd);
+ }
+ if (symlink(TSOL_NAME_SERVICE_DOOR, NAME_SERVICE_DOOR) != 0) {
+ if (errno != EEXIST) {
+ logit("Cannot symlink %s:%s\n",
+ NAME_SERVICE_DOOR, strerror(errno));
+ exit(1);
+ }
+ }
+ } else if (stat(NAME_SERVICE_DOOR, &buf) < 0) {
int newfd;
if ((newfd = creat(NAME_SERVICE_DOOR, 0444)) < 0) {
- logit("Cannot create %s:%s\n",
- NAME_SERVICE_DOOR,
- strerror(errno));
+ logit("Cannot create %s:%s\n", NAME_SERVICE_DOOR,
+ strerror(errno));
exit(1);
}
(void) close(newfd);
--- a/usr/src/cmd/nscd/svc-nscd Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/nscd/svc-nscd Fri Mar 24 12:29:20 2006 -0800
@@ -1,11 +1,11 @@
#!/sbin/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,14 +20,41 @@
#
# 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"
. /lib/svc/share/smf_include.sh
+# Trusted Extensions non-global zones need special handling
+
+if (smf_is_system_labeled); then
+ if (smf_is_nonglobalzone); then
+
+ # If needed create a door to the global zone daemon.
+ if [ ! -L /var/run/name_service_door ]; then
+ ln -s /var/tsol/doors/name_service_door /var/run || \
+ exit $SMF_EXIT_ERR_FATAL
+ fi
+
+ # If current service duration is not "transient", create
+ # a dummy background process to preserve contract lifetime.
+ duration=""
+ if /bin/svcprop -q -c -p startd/duration $SMF_FMRI ; then
+ duration=`/bin/svcprop -c -p startd/duration $SMF_FMRI`
+ fi
+ if [ "$duration" != "transient" ]; then
+ ( while true ; do sleep 3600 ; done ) &
+ fi
+
+ # The real daemon is not started in non-global zones,
+ # so exit now.
+ exit $SMF_EXIT_OK
+ fi
+
+fi
+
if [ -f /etc/nscd.conf -a -f /usr/sbin/nscd ]; then
secure=""
--- a/usr/src/cmd/praudit/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/praudit/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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"
@@ -42,7 +43,9 @@
CPPFLAGS += -D_PRAUDIT -I$(SRC)/lib/libbsm/common
CPPFLAGS += -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
-LDLIBS += -lbsm -lnsl -lpam
+LAZYLIBS = $(ZLAZYLOAD) -ltsol $(ZNOLAZYLOAD)
+lint := LAZYLIBS = -ltsol
+LDLIBS += -lbsm -lnsl -lpam $(LAZYLIBS)
.KEEP_STATE:
--- a/usr/src/cmd/praudit/token.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/praudit/token.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -65,9 +64,8 @@
#include <bsm/audit_record.h>
#include <bsm/libbsm.h>
-#ifdef TSOL
#include <tsol/label.h>
-#endif /* TSOL */
+#include <sys/tsol/label_macro.h>
#include "praudit.h"
#include "toktable.h"
@@ -2154,10 +2152,8 @@
int
slabel_token(pr_context_t *context)
{
-#ifdef TSOL
bslabel_t label;
int returnstat;
- int s;
char strbuf[2048];
char *sp = strbuf;
uval_t uval;
@@ -2166,9 +2162,9 @@
sizeof (label))) == 0) {
uval.uvaltype = PRA_STRING;
if (!(context->format & PRF_RAWM)) {
- /* print in ASCII form using bltos */
- s = bsltos(&label, &sp, sizeof (strbuf), 0);
- if (s > 0) {
+ /* print in ASCII form */
+ if (label_to_str(&label, &sp, M_LABEL,
+ DEF_NAMES) == 0) {
uval.string_val = sp;
returnstat = pa_print(context, &uval, 1);
} else /* cannot convert to string */
@@ -2185,9 +2181,6 @@
}
}
return (returnstat);
-#else /* !TSOL */
- return (-1);
-#endif /* TSOL */
}
/*
@@ -2280,108 +2273,3 @@
/* privilege: */
return (pa_adr_string(context, returnstat, 1));
}
-
-/*
- * -----------------------------------------------------------------------
- * ilabel_token() : Process information label token and display contents
- * return codes : -1 - error
- * : 0 - successful
- * NOTE: At the time of call, the ilabel token id has been retrieved
- *
- * Format of information label token:
- * label token id adr_char
- * label adr_opaque, sizeof (bilabel_t) bytes
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-int
-ilabel_token(pr_context_t *context)
-{
-#ifdef TSOL
- bilabel_t label;
- int returnstat;
- int s;
- char strbuf[2048];
- char *sp = strbuf;
- uval_t uval;
-
- if ((returnstat = pr_adr_char(context, (char *)&label,
- sizeof (label))) == 0) {
- uval.uvaltype = PRA_STRING;
- if (!(context->format & PRF_RAWM)) {
- /* print in ASCII form using bltos */
- s = biltos(&label, &sp, sizeof (strbuf), 0);
- if (s > 0) {
- uval.string_val = sp;
- returnstat = pa_print(context, &uval, 1);
- } else /* cannot convert to string */
- returnstat = 1;
- }
- /* print in hexadecimal form */
- if ((context->format & PRF_RAWM) || (returnstat == 1)) {
- uval.string_val = hexconvert((char *)&label,
- sizeof (bilabel_t), sizeof (bilabel_t));
- if (uval.string_val) {
- returnstat = pa_print(context, &uval, 1);
- free(uval.string_val);
- }
- }
- }
- return (returnstat);
-#else /* !TSOL */
- return (-1);
-#endif /* TSOL */
-}
-
-/*
- * -----------------------------------------------------------------------
- * clearance_token() : Process clearance token and display contents
- * return codes : -1 - error
- * : 0 - successful
- * NOTE: At the time of call, the clearance token id has been retrieved
- *
- * Format of clearance token:
- * clearance token id adr_char
- * clearance adr_char, sizeof (bclear_t) bytes
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-int
-clearance_token(pr_context_t *context)
-{
-#ifdef TSOL
- bclear_t clearance;
- int returnstat;
- int s;
- char strbuf[2048];
- char *sp = strbuf;
- uval_t uval;
-
- if ((returnstat = pr_adr_char(context, (char *)&clearance,
- sizeof (clearance))) == 0) {
- uval.uvaltype = PRA_STRING;
- if (!(context->format & PRF_RAWM)) {
- /* print in ASCII form using bltos */
- s = bcleartos(&clearance, &sp, sizeof (strbuf),
- SHORT_WORDS);
- if (s > 0) {
- uval.string_val = sp;
- returnstat = pa_print(context, &uval, 1);
- } else /* cannot convert to string */
- returnstat = 1;
- }
- /* print in hexadecimal form */
- if ((context->format & PRF_RAWM) || (returnstat == 1)) {
- uval.string_val = hexconvert((char *)&clearance,
- sizeof (bclear_t), sizeof (bclear_t));
- if (uval.string_val) {
- returnstat = pa_print(context, &uval, 1);
- free(uval.string_val);
- }
- }
- }
- return (returnstat);
-#else /* !TSOL */
- return (-1);
-#endif /* TSOL */
-}
--- a/usr/src/cmd/praudit/toktable.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/praudit/toktable.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -116,14 +115,9 @@
table_init(AUT_ACL, "acl", acl_token, T_ENCLOSED);
table_init(AUT_ATTR, "attribute", attribute_token, T_ENCLOSED);
table_init(AUT_IPC_PERM, "IPC_perm", s5_IPC_perm_token, T_ENCLOSED);
- table_initx(AUT_LABEL, "cmw label", "cmw_label",
- NOFUNC, T_UNKNOWN);
table_init(AUT_GROUPS, "group", group_token, T_ELEMENT);
- table_initx(AUT_ILABEL, "information label", "information_label",
- ilabel_token, T_ELEMENT);
- table_initx(AUT_SLABEL, "sensitivity label", "sensitivity_label",
+ table_initx(AUT_LABEL, "sensitivity label", "sensitivity_label",
slabel_token, T_ELEMENT);
- table_init(AUT_CLEAR, "clearance", clearance_token, T_ELEMENT);
table_init(AUT_PRIV, "privilege", privilege_token, T_EXTENDED);
table_initx(AUT_UPRIV, "use of privilege", "use_of_privilege",
useofpriv_token, T_EXTENDED);
--- a/usr/src/cmd/praudit/toktable.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/praudit/toktable.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -200,9 +199,7 @@
extern int attribute_token();
extern int s5_IPC_perm_token();
extern int group_token();
-extern int ilabel_token();
extern int slabel_token();
-extern int clearance_token();
extern int privilege_token();
extern int useofpriv_token();
extern int liaison_token();
--- a/usr/src/cmd/print/gateway/adaptor.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/print/gateway/adaptor.c Fri Mar 24 12:29:20 2006 -0800
@@ -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) 1998-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"
@@ -264,7 +263,7 @@
int
-adaptor_client_access(const char *printer, const char *host)
+adaptor_client_access(const char *printer, const char *host, int peerfd)
{
static int (*fpt)() = NULL;
@@ -272,7 +271,7 @@
((fpt = (int (*)())adaptor_function(paradigm_name,
"client_access")) != NULL))
return ((int)(fpt)((primary_name ? primary_name : printer),
- host));
+ host, peerfd));
return (-1);
}
--- a/usr/src/cmd/print/gateway/adaptor.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/print/gateway/adaptor.h Fri Mar 24 12:29:20 2006 -0800
@@ -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) 1998 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#ifndef _ADAPTOR_H
@@ -47,7 +46,8 @@
extern int adaptor_available(const char *printer);
extern int adaptor_spooler_available(const char *printer);
extern int adaptor_spooler_accepting_jobs(const char *printer);
-extern int adaptor_client_access(const char *printer, const char *host);
+extern int adaptor_client_access(const char *printer, const char *host,
+ int peerfd);
extern int adaptor_restart_printer(const char *printer);
extern char *adaptor_temp_dir(const char *printer, const char *host);
extern int adaptor_submit_job(const char *printer, const char *host,
--- a/usr/src/cmd/print/gateway/main.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/print/gateway/main.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -50,7 +49,6 @@
#include <adaptor.h>
-
#define ACK(fp) { (void) fputc(NULL, fp); (void) fflush(fp); }
#define NACK(fp) { (void) fputc('\001', fp); (void) fflush(fp); }
@@ -147,7 +145,6 @@
return (hostname);
}
-
static int
request_id_no(const char *filename)
{
@@ -559,7 +556,7 @@
exit(1);
}
- if (adaptor_client_access(printer, host) < 0) {
+ if (adaptor_client_access(printer, host, fileno(ifp)) < 0) {
syslog(LOG_ERR, "%s doesn't have permission to talk to %s",
host, printer);
(void) fprintf(ofp,
--- a/usr/src/cmd/ptools/ppriv/ppriv.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/ptools/ppriv/ppriv.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*
* Program to examine or set process privileges.
@@ -61,6 +60,7 @@
static boolean_t Don = B_FALSE;
static boolean_t Doff = B_FALSE;
static boolean_t list = B_FALSE;
+static boolean_t mac_aware = B_FALSE;
static int mode = PRIV_STR_PORT;
int
@@ -78,7 +78,7 @@
else
command = argv[0];
- while ((opt = getopt(argc, argv, "lDNevs:S")) != EOF) {
+ while ((opt = getopt(argc, argv, "lDMNevs:S")) != EOF) {
switch (opt) {
case 'l':
list = B_TRUE;
@@ -87,6 +87,9 @@
set = B_TRUE;
Don = B_TRUE;
break;
+ case 'M':
+ mac_aware = B_TRUE;
+ break;
case 'N':
set = B_TRUE;
Doff = B_TRUE;
@@ -115,7 +118,8 @@
argc -= optind;
argv += optind;
- if ((argc < 1 && !list) || Doff && Don || list && (set || exec))
+ if ((argc < 1 && !list) || Doff && Don || list && (set || exec) ||
+ (mac_aware && !exec))
usage();
/*
@@ -314,7 +318,7 @@
{
(void) fprintf(stderr,
"usage:\t%s [-v] [-S] [-D|-N] [-s spec] { pid | core } ...\n"
- "\t%s -e [-D|-N] [-s spec] cmd [args ...]\n"
+ "\t%s -e [-D|-N] [-M] [-s spec] cmd [args ...]\n"
"\t%s -l [-v] [privilege ...]\n"
" (report, set or list process privileges)\n", command,
command, command);
@@ -535,6 +539,13 @@
{
int set;
+ if (mac_aware) {
+ if (setpflags(NET_MAC_AWARE, 1) != 0)
+ fatal("setpflags(NET_MAC_AWARE)");
+ if (setpflags(NET_MAC_AWARE_INHERIT, 1) != 0)
+ fatal("setpflags(NET_MAC_AWARE_INHERIT)");
+ }
+
if (sets != NULL) {
priv_set_t *target = priv_allocset();
--- a/usr/src/cmd/rpcbind/bind.xml Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/rpcbind/bind.xml Fri Mar 24 12:29:20 2006 -0800
@@ -2,15 +2,15 @@
<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<!--
- Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ Copyright 2006 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
+
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.
@@ -25,6 +25,7 @@
CDDL HEADER END
+
ident "%Z%%M% %I% %E% SMI"
NOTE: This service manifest is not editable; its contents will
@@ -93,7 +94,7 @@
<method_credential
user='root'
group='root'
- privileges='basic,file_chown,file_chown_self,file_owner,net_privaddr,proc_setid,sys_nfs'
+ privileges='basic,file_chown,file_chown_self,file_owner,net_privaddr,proc_setid,sys_nfs,net_bindmlp'
/>
</method_context>
</exec_method>
--- a/usr/src/cmd/rpcbind/rpcbind.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/rpcbind/rpcbind.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -97,7 +96,9 @@
static boolean_t check_hostserv(struct netconfig *, const char *, const char *);
static void rpcb_check_init(void);
-
+static int setopt_reuseaddr(int);
+static int setopt_anon_mlp(int);
+static int setup_callit(int);
/* Global variables */
#ifdef ND_DEBUG
@@ -139,6 +140,7 @@
void *nc_handle; /* Net config handle */
struct rlimit rl;
int maxrecsz = RPC_MAXDATASIZE;
+ boolean_t can_do_mlp;
parseargs(argc, argv);
@@ -167,8 +169,10 @@
* These privileges are required for the t_bind check rpcbind uses
* to determine whether a service is still live or not.
*/
+ can_do_mlp = priv_ineffect(PRIV_NET_BINDMLP);
if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, DAEMON_UID,
- DAEMON_GID, PRIV_NET_PRIVADDR, PRIV_SYS_NFS, (char *)NULL) == -1) {
+ DAEMON_GID, PRIV_NET_PRIVADDR, PRIV_SYS_NFS,
+ can_do_mlp ? PRIV_NET_BINDMLP : NULL, NULL) == -1) {
fprintf(stderr, "Insufficient privileges\n");
exit(1);
}
@@ -399,9 +403,6 @@
int status; /* bound checking ? */
static int msgprt = 0;
- static int setopt_reuseaddr(int);
- static int setup_callit(int);
-
if ((nconf->nc_semantics != NC_TPI_CLTS) &&
(nconf->nc_semantics != NC_TPI_COTS) &&
(nconf->nc_semantics != NC_TPI_COTS_ORD))
@@ -432,6 +433,14 @@
return (1);
}
+ if (is_system_labeled() &&
+ (strcmp(nconf->nc_protofmly, NC_INET) == 0 ||
+ strcmp(nconf->nc_protofmly, NC_INET6) == 0) &&
+ setopt_anon_mlp(fd) == -1) {
+ syslog(LOG_ERR, "%s: couldn't set SO_ANON_MLP option",
+ nconf->nc_netid);
+ }
+
/*
* Negotiate for returning the ucred of the caller. This should
* done before enabling the endpoint for service via
@@ -769,28 +778,27 @@
}
static int
-setopt_reuseaddr(int fd)
+setopt_int(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;
+ } optdata;
- opt = (struct opthdr *)reqbuf;
- opt->level = SOL_SOCKET;
- opt->name = SO_REUSEADDR;
- opt->len = sizeof (int);
+ optdata.opt.level = level;
+ optdata.opt.name = name;
+ optdata.opt.len = sizeof (int);
- ip = (int *)&reqbuf[sizeof (struct opthdr)];
- *ip = 1;
+ optdata.value = value;
req.flags = T_NEGOTIATE;
- req.opt.len = sizeof (struct opthdr) + opt->len;
- req.opt.buf = (char *)opt;
+ req.opt.len = sizeof (optdata);
+ req.opt.buf = (char *)&optdata;
resp.flags = 0;
- resp.opt.buf = reqbuf;
- resp.opt.maxlen = sizeof (reqbuf);
+ resp.opt.buf = (char *)&optdata;
+ resp.opt.maxlen = sizeof (optdata);
if (t_optmgmt(fd, &req, &resp) < 0 || resp.flags != T_SUCCESS) {
t_error("t_optmgmt");
@@ -800,6 +808,18 @@
}
static int
+setopt_reuseaddr(int fd)
+{
+ return (setopt_int(fd, SOL_SOCKET, SO_REUSEADDR, 1));
+}
+
+static int
+setopt_anon_mlp(int fd)
+{
+ return (setopt_int(fd, SOL_SOCKET, SO_ANON_MLP, 1));
+}
+
+static int
setup_callit(int fd)
{
struct ipv6_mreq mreq;
--- a/usr/src/cmd/smserverd/myaudit.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/smserverd/myaudit.c Fri Mar 24 12:29:20 2006 -0800
@@ -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,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2001-2002 Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -40,6 +38,7 @@
#include <unistd.h>
#include <stdlib.h>
#include <sys/smedia.h>
+#include <tsol/label.h>
#include "smserver.h"
#include <bsm/audit.h>
#include <bsm/libbsm.h>
@@ -221,6 +220,10 @@
(void) au_write(ad, au_to_newgroups(ng, grplst));
}
}
+
+ if (is_system_labeled())
+ (void) au_write(ad, au_to_mylabel());
+
if (strlen(door_dp->audit_text) != 0) {
(void) au_write(ad, au_to_text(door_dp->audit_text));
}
--- a/usr/src/cmd/svc/shell/smf_include.sh Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/svc/shell/smf_include.sh Fri Mar 24 12:29:20 2006 -0800
@@ -74,6 +74,17 @@
return 1
}
+# smf_is_system_labeled
+#
+# Returns zero (success) if system is labeled (aka Trusted Extensions).
+# 1 otherwise.
+#
+smf_is_system_labeled() {
+ [ ! -x /bin/plabel ] && return 1
+ /bin/plabel > /dev/null 2>&1
+ return $?
+}
+
# smf_netstrategy
# -> (_INIT_NET_IF, _INIT_NET_STRATEGY)
#
--- a/usr/src/cmd/tar/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/tar/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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"
@@ -35,7 +36,9 @@
CPPFLAGS += -D_FILE_OFFSET_BITS=64 -I../../lib/libcmd/inc
DCFILE= $(PROG).dc
-LDLIBS += -lcmd -lsec
+LAZYLIBS = $(ZLAZYLOAD) -ltsol $(ZNOLAZYLOAD)
+lint := LAZYLIBS = -ltsol
+LDLIBS += -lcmd -lsec $(LAZYLIBS)
CFLAGS += $(CCVERBOSE)
--- a/usr/src/cmd/tar/tar.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/tar/tar.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
@@ -75,6 +74,11 @@
#endif
#include <archives.h>
+/* Trusted Extensions */
+#include <zone.h>
+#include <tsol/label.h>
+#include <sys/tsol/label_macro.h>
+
/*
* Source compatibility
*/
@@ -193,8 +197,6 @@
char attr_info[1];
} *attr;
-#define ACL_HDR 'A'
-
/*
*
* Tar has been changed to support extended attributes.
@@ -382,7 +384,7 @@
static struct file_list *exclude_tbl[TABLE_SIZE],
*include_tbl[TABLE_SIZE];
-static int append_secattr(char **, int *, acl_t *);
+static int append_secattr(char **, int *, int, char *, char);
static void write_ancillary(union hblock *, char *, int, char);
static void add_file_to_table(struct file_list *table[], char *str);
@@ -464,7 +466,7 @@
static int checkf(char *name, int mode, int howmuch);
static int writetbuf(char *buffer, int n);
static int wantit(char *argv[], char **namep, char **dirp, char **comp);
-
+static void append_ext_attr(char *shortname, char **secinfo, int *len);
static int get_xdata(void);
static void gen_num(const char *keyword, const u_longlong_t number);
static void gen_date(const char *keyword, const timestruc_t time_value);
@@ -489,6 +491,15 @@
static int put_xattr_hdr(char *longname, char *shortname, char *prefix,
int typeflag, int filetype, struct linkbuf *lp);
static int read_xattr_hdr();
+
+/* Trusted Extensions */
+#define AUTO_ZONE "/zone"
+
+static void extract_attr(char **file_ptr, struct sec_attr *);
+static int check_ext_attr(char *filename);
+static void rebuild_comp_path(char *str, char **namep);
+static int rebuild_lk_comp_path(char *str, char **namep);
+
static void get_parent(char *path, char *dir);
static char *get_component(char *path);
static int retry_attrdir_open(char *name);
@@ -512,6 +523,22 @@
static int Eflag; /* Allow files greater than 8GB */
static int atflag; /* traverse extended attributes */
static int Dflag; /* Data change flag */
+/* Trusted Extensions */
+static int Tflag; /* Trusted Extensions attr flags */
+static int dir_flag; /* for attribute extract */
+static int mld_flag; /* for attribute extract */
+static char *orig_namep; /* original namep - unadorned */
+static int rpath_flag; /* MLD real path is rebuilt */
+static char real_path[MAXPATHLEN]; /* MLD real path */
+static int lk_rpath_flag; /* linked to real path is rebuilt */
+static char lk_real_path[MAXPATHLEN]; /* linked real path */
+static bslabel_t bs_label; /* for attribute extract */
+static bslabel_t admin_low;
+static bslabel_t admin_high;
+static int ignored_aprivs = 0;
+static int ignored_fprivs = 0;
+static int ignored_fattrs = 0;
+
static int term, chksum, wflag,
first = TRUE, defaults_used = FALSE, linkerrok;
static blkcnt_t recno;
@@ -804,6 +831,10 @@
Eflag++;
Pflag++; /* Only POSIX archive made */
break;
+ case 'T':
+ Tflag++; /* Handle Trusted Extensions attrs */
+ pflag++; /* also set flag for ACL */
+ break;
default:
(void) fprintf(stderr, gettext(
"tar: %c: unknown function modifier\n"), *cp);
@@ -825,6 +856,15 @@
"tar: specify only one of [ctxru].\n"));
usage();
}
+ /* Trusted Extensions attribute handling */
+ if (Tflag && ((getzoneid() != GLOBAL_ZONEID) ||
+ !is_system_labeled())) {
+ (void) fprintf(stderr, gettext(
+ "tar: the 'T' option is only available with "
+ "Trusted Extensions\nand must be run from "
+ "the global zone.\n"));
+ usage();
+ }
if (cflag && *argv == NULL && Filefile == NULL)
fatal(gettext("Missing filenames"));
if (usefile == NULL)
@@ -1000,9 +1040,9 @@
if (sysv3_env) {
(void) fprintf(stderr, gettext(
#if defined(O_XATTR)
- "Usage: tar {c|r|t|u|x}[BDeEhilmnopPqvw@[0-7]][bfFk][X...] "
+ "Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw@[0-7]][bfFk][X...] "
#else
- "Usage: tar {c|r|t|u|x}[BDeEhilmnopPqvw[0-7]][bfFk][X...] "
+ "Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw[0-7]][bfFk][X...] "
#endif
"[blocksize] [tarfile] [filename] [size] [exclude-file...] "
"{file | -I include-file | -C directory file}...\n"));
@@ -1011,9 +1051,9 @@
{
(void) fprintf(stderr, gettext(
#if defined(O_XATTR)
- "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqvw@[0-7]][bfk][X...] "
+ "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw@[0-7]][bfk][X...] "
#else
- "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqvw[0-7]][bfk][X...] "
+ "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw[0-7]][bfk][X...] "
#endif
"[blocksize] [tarfile] [size] [exclude-file...] "
"{file | -I include-file | -C directory file}...\n"));
@@ -2396,14 +2436,23 @@
int symflag;
int want;
acl_t *aclp = NULL; /* acl info */
+ char dot[] = "."; /* dirp for using realpath */
timestruc_t time_zero; /* used for call to doDirTimes */
int dircreate;
int convflag;
- int cnt;
-
time_zero.tv_sec = 0;
time_zero.tv_nsec = 0;
+ /* reset Trusted Extensions variables */
+ rpath_flag = 0;
+ lk_rpath_flag = 0;
+ dir_flag = 0;
+ mld_flag = 0;
+ bslundef(&bs_label);
+ bsllow(&admin_low);
+ bslhigh(&admin_high);
+ orig_namep = 0;
+
dumping = 0; /* for newvol(), et al: we are not writing */
/*
@@ -2439,6 +2488,26 @@
if (want == -1)
break;
+/* Trusted Extensions */
+ /*
+ * During tar extract (x):
+ * If the pathname of the restored file has been
+ * reconstructed from the ancillary file,
+ * use it to process the normal file.
+ */
+ if (mld_flag) { /* Skip over .MLD. directory */
+ mld_flag = 0;
+ passtape();
+ continue;
+ }
+ orig_namep = namep; /* save original */
+ if (rpath_flag) {
+ namep = real_path; /* use zone path */
+ comp = real_path; /* use zone path */
+ dirp = dot; /* work from the top */
+ rpath_flag = 0; /* reset */
+ }
+
if (dirfd != -1)
(void) close(dirfd);
@@ -2479,12 +2548,12 @@
xattr_linkp = NULL;
xattrhead = NULL;
} else {
- fprintf(vfile,
+ (void) fprintf(vfile,
gettext("tar: cannot open %s %s\n"),
dirp, strerror(errno));
}
#else
- fprintf(vfile,
+ (void) fprintf(vfile,
gettext("tar: cannot open %s %s\n"),
dirp, strerror(errno));
#endif
@@ -2724,7 +2793,10 @@
continue;
}
if (dblock.dbuf.typeflag == '2') { /* symlink */
- linkp = templink;
+ if ((Tflag) && (lk_rpath_flag == 1))
+ linkp = lk_real_path;
+ else
+ linkp = templink;
if (Aflag && *linkp == '/')
linkp++;
if (rmdir(namep) < 0) {
@@ -2864,6 +2936,15 @@
continue;
}
+ if (Tflag && (check_ext_attr(namep) == 0)) {
+ if (errflag)
+ done(1);
+ else
+ Errflg = 1;
+ passtape();
+ continue;
+ }
+
if (extno != 0) { /* file is in pieces */
if (extotal < 1 || extotal > MAXEXT)
(void) fprintf(stderr, gettext(
@@ -2928,7 +3009,7 @@
ret = acl_set(namep, aclp);
}
#else
- ret = acl_set(namep, &aclp);
+ ret = acl_set(namep, aclp);
#endif
if (ret < 0) {
if (pflag) {
@@ -2979,13 +3060,24 @@
}
xcnt++; /* increment # files extracted */
}
- if (dblock.dbuf.typeflag == 'A') { /* acl info */
+
+ /*
+ * Process ancillary file.
+ *
+ */
+
+ if (dblock.dbuf.typeflag == 'A') { /* acl info */
char buf[TBLOCK];
char *secp;
char *tp;
int attrsize;
int cnt;
+ /* reset Trusted Extensions flags */
+ dir_flag = 0;
+ mld_flag = 0;
+ lk_rpath_flag = 0;
+ rpath_flag = 0;
if (pflag) {
bytes = stbuf.st_size;
@@ -2997,6 +3089,16 @@
}
tp = secp;
blocks = TBLOCKS(bytes);
+
+ /*
+ * Display a line for each ancillary file.
+ */
+ if (vflag && Tflag)
+ (void) fprintf(vfile, "x %s(A), %"
+ FMT_blkcnt_t " bytes, %"
+ FMT_blkcnt_t " tape blocks\n",
+ namep, bytes, blocks);
+
while (blocks-- > 0) {
readtape(buf);
if (bytes <= TBLOCK) {
@@ -3049,7 +3151,23 @@
bytes -= attrsize;
break;
- /* SunFed case goes here */
+ /* Trusted Extensions */
+
+ case DIR_TYPE:
+ case LBL_TYPE:
+ case APRIV_TYPE:
+ case FPRIV_TYPE:
+ case COMP_TYPE:
+ case LK_COMP_TYPE:
+ case ATTR_FLAG_TYPE:
+ attrsize =
+ sizeof (struct sec_attr) +
+ strlen(&attr->attr_info[0]);
+ bytes -= attrsize;
+ if (Tflag)
+ extract_attr(&namep,
+ attr);
+ break;
default:
(void) fprintf(stderr, gettext(
@@ -5556,21 +5674,24 @@
append_secattr(
char **secinfo, /* existing security info */
int *secinfo_len, /* length of existing security info */
- acl_t *aclp)
+ int size, /* new attribute size: unit depends on type */
+ char *attrtext, /* new attribute text */
+ char attr_type) /* new attribute type */
{
char *new_secinfo;
- char *attrtext;
int newattrsize;
int oldsize;
+ struct sec_attr *attr;
/* no need to add */
- if (aclp == (void *)NULL)
- return (0);
-
- switch (acl_type(aclp)) {
- case ACLENT_T:
- case ACE_T:
- attrtext = acl_totext(aclp, ACL_APPEND_ID | ACL_COMPACT_FMT);
+ if (attr_type != DIR_TYPE) {
+ if (attrtext == NULL)
+ return (0);
+ }
+
+ switch (attr_type) {
+ case UFSD_ACL:
+ case ACE_ACL:
if (attrtext == NULL) {
(void) fprintf(stderr, "acltotext failed\n");
return (-1);
@@ -5582,15 +5703,28 @@
(void) fprintf(stderr, "can't allocate memory\n");
return (-1);
}
- attr->attr_type = (acl_type(aclp) == ACLENT_T) ?
- UFSD_ACL : ACE_ACL;
+ attr->attr_type = attr_type;
(void) sprintf(attr->attr_len,
- "%06o", acl_cnt(aclp)); /* acl entry count */
+ "%06o", size); /* acl entry count */
(void) strcpy((char *)&attr->attr_info[0], attrtext);
free(attrtext);
break;
- /* SunFed's case goes here */
+ /* Trusted Extensions */
+ case DIR_TYPE:
+ case LBL_TYPE:
+ newattrsize = sizeof (struct sec_attr) + strlen(attrtext);
+ attr = (struct sec_attr *)malloc(newattrsize);
+ if (attr == NULL) {
+ (void) fprintf(stderr,
+ gettext("can't allocate memory\n"));
+ return (-1);
+ }
+ attr->attr_type = attr_type;
+ (void) sprintf(attr->attr_len,
+ "%06d", size); /* len of attr data */
+ (void) strcpy((char *)&attr->attr_info[0], attrtext);
+ break;
default:
(void) fprintf(stderr, "unrecognized attribute type\n");
@@ -5604,6 +5738,7 @@
if (new_secinfo == NULL) {
(void) fprintf(stderr, "can't allocate memory\n");
*secinfo_len -= newattrsize;
+ free(attr);
return (-1);
}
@@ -5611,6 +5746,7 @@
(void) memcpy(new_secinfo + oldsize, attr, newattrsize);
free(*secinfo);
+ free(attr);
*secinfo = new_secinfo;
return (0);
}
@@ -6779,7 +6915,17 @@
/* append security attributes if any */
if (aclp != NULL) {
- (void) append_secattr(&secinfo, &len, aclp);
+ (void) append_secattr(&secinfo, &len, acl_cnt(aclp),
+ acl_totext(aclp, ACL_APPEND_ID | ACL_COMPACT_FMT),
+ (acl_type(aclp) == ACLENT_T) ? UFSD_ACL : ACE_ACL);
+ }
+
+ if (Tflag) {
+ /* append Trusted Extensions extended attributes */
+ append_ext_attr(shortname, &secinfo, &len);
+ (void) write_ancillary(&dblock, secinfo, len, ACL_HDR);
+
+ } else if (aclp != NULL) {
(void) write_ancillary(&dblock, secinfo, len, ACL_HDR);
}
}
@@ -7160,3 +7306,629 @@
}
}
}
+/* Trusted Extensions */
+
+/*
+ * append_ext_attr():
+ *
+ * Append extended attributes and other information into the buffer
+ * that gets written to the ancillary file.
+ *
+ * With option 'T', we create a tarfile which
+ * has an ancillary file each corresponding archived file.
+ * Each ancillary file contains 1 or more of the
+ * following attributes:
+ *
+ * attribute type attribute process procedure
+ * ---------------- ---------------- --------------------------
+ * DIR_TYPE = 'D' directory flag append if a directory
+ * LBL_TYPE = 'L' SL[IL] or SL append ascii label
+ *
+ *
+ */
+static void
+append_ext_attr(char *shortname, char **secinfo, int *len)
+{
+ bslabel_t b_slabel; /* binary sensitvity label */
+ char *ascii = NULL; /* ascii label */
+
+ /*
+ * For each attribute type, append it if it is
+ * relevant to the file type.
+ */
+
+ /*
+ * For attribute type DIR_TYPE,
+ * append it to the following file type:
+ *
+ * S_IFDIR: directories
+ */
+
+ /*
+ * For attribute type LBL_TYPE,
+ * append it to the following file type:
+ *
+ * S_IFDIR: directories (including mld, sld)
+ * S_IFLNK: symbolic link
+ * S_IFREG: regular file but not hard link
+ * S_IFIFO: FIFO file but not hard link
+ * S_IFCHR: char special file but not hard link
+ * S_IFBLK: block special file but not hard link
+ */
+ switch (stbuf.st_mode & S_IFMT) {
+
+ case S_IFDIR:
+
+ /*
+ * append DIR_TYPE
+ */
+ (void) append_secattr(secinfo, len, 1,
+ "\0", DIR_TYPE);
+
+ /*
+ * Get and append attribute types LBL_TYPE.
+ * For directories, LBL_TYPE contains SL.
+ */
+ /* get binary sensitivity label */
+ if (getlabel(shortname, &b_slabel) != 0) {
+ (void) fprintf(stderr,
+ gettext("tar: can't get sensitvity label for "
+ " %s, getlabel() error: %s\n"),
+ shortname, strerror(errno));
+ } else {
+ /* get ascii SL */
+ if (bsltos(&b_slabel, &ascii,
+ 0, 0) <= 0) {
+ (void) fprintf(stderr,
+ gettext("tar: can't get ascii SL for"
+ " %s\n"), shortname);
+ } else {
+ /* append LBL_TYPE */
+ (void) append_secattr(secinfo, len,
+ strlen(ascii) + 1, ascii,
+ LBL_TYPE);
+
+ /* free storage */
+ if (ascii != NULL) {
+ free(ascii);
+ ascii = (char *)0;
+ }
+ }
+
+ }
+ break;
+
+ case S_IFLNK:
+ case S_IFREG:
+ case S_IFIFO:
+ case S_IFCHR:
+ case S_IFBLK:
+
+ /* get binary sensitivity label */
+ if (getlabel(shortname, &b_slabel) != 0) {
+ (void) fprintf(stderr,
+ gettext("tar: can't get sensitivty label for %s, "
+ "getlabel() error: %s\n"),
+ shortname, strerror(errno));
+ } else {
+ /* get ascii IL[SL] */
+ if (bsltos(&b_slabel, &ascii, 0, 0) <= 0) {
+ (void) fprintf(stderr,
+ gettext("tar: can't translate sensitivity "
+ " label for %s\n"), shortname);
+ } else {
+ char *cmw_label;
+ size_t cmw_length;
+
+ cmw_length = strlen("ADMIN_LOW [] ") +
+ strlen(ascii);
+ if ((cmw_label = malloc(cmw_length)) == NULL) {
+ (void) fprintf(stderr, gettext(
+ "Insufficient memory for label\n"));
+ exit(1);
+ }
+ /* append LBL_TYPE */
+ (void) snprintf(cmw_label, cmw_length,
+ "ADMIN_LOW [%s]", ascii);
+ (void) append_secattr(secinfo, len,
+ strlen(cmw_label) + 1, cmw_label,
+ LBL_TYPE);
+
+ /* free storage */
+ if (ascii != NULL) {
+ free(cmw_label);
+ free(ascii);
+ ascii = (char *)0;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ } /* end switch for LBL_TYPE */
+
+
+ /* DONE !! */
+ return;
+
+} /* end of append_ext_attr */
+
+
+/*
+ * Name: extract_attr()
+ *
+ * Description:
+ * Process attributes from the ancillary file due to
+ * the T option.
+ *
+ * Call by doxtract() as part of the switch case structure.
+ * Making this a separate routine because the nesting are too
+ * deep in doxtract, thus, leaving very little space
+ * on each line for instructions.
+ *
+ * With option 'T', we extract from a TS 8 or TS 2.5 ancillary file
+ *
+ * For option 'T', following are possible attributes in
+ * a TS 8 ancillary file: (NOTE: No IL support)
+ *
+ * attribute type attribute process procedure
+ * ---------------- ---------------- -------------------------
+ * # LBL_TYPE = 'L' SL construct binary label
+ * # APRIV_TYPE = 'P' allowed priv construct privileges
+ * # FPRIV_TYPE = 'p' forced priv construct privileges
+ * # COMP_TYPE = 'C' path component construct real path
+ * # DIR_TYPE = 'D' directory flag note it is a directory
+ * $ UFSD_ACL = '1' ACL data construct ACL entries
+ * ATTR_FLAG_TYPE = 'F' file attr flags construct binary flags
+ * LK_COMP_TYPE = 'K' linked path comp construct linked real path
+ *
+ * note: # = attribute names common between TS 8 & TS 2.5 ancillary
+ * files.
+ * $ = ACL attribute is processed for the option 'p', it doesn't
+ * need option 'T'.
+ *
+ * Trusted Extensions ignores APRIV_TYPE, FPRIV_TYPE, and ATTR_FLAG_TYPE
+ *
+ */
+static void
+extract_attr(char **file_ptr, struct sec_attr *attr)
+{
+ int reterr, err;
+ char *dummy_buf; /* for attribute extract */
+
+ dummy_buf = attr->attr_info;
+
+ switch (attr->attr_type) {
+
+ case DIR_TYPE:
+
+ dir_flag++;
+ break;
+
+ case LBL_TYPE:
+
+ /*
+ * LBL_TYPE is used to indicate SL for directory, and
+ * CMW label for other file types.
+ */
+
+ if (!dir_flag) { /* not directory */
+ /* Skip over IL portion */
+ char *sl_ptr = strchr(dummy_buf, '[');
+
+ if (sl_ptr == NULL)
+ err = 0;
+ else
+ err = stobsl(sl_ptr, &bs_label,
+ NEW_LABEL, &reterr);
+ } else { /* directory */
+ err = stobsl(dummy_buf, &bs_label,
+ NEW_LABEL, &reterr);
+ }
+ if (err == 0) {
+ (void) fprintf(stderr, gettext("tar: "
+ "can't convert %s to binary label\n"),
+ dummy_buf);
+ bslundef(&bs_label);
+ } else if (!blequal(&bs_label, &admin_low) &&
+ !blequal(&bs_label, &admin_high)) {
+ bslabel_t *from_label;
+ char *buf;
+ char tempbuf[MAXPATHLEN];
+
+ if (*orig_namep != '/') {
+ /* got relative linked to path */
+ (void) getcwd(tempbuf, (sizeof (tempbuf)));
+ (void) strncat(tempbuf, "/", MAXPATHLEN);
+ } else
+ *tempbuf = '\0';
+
+ buf = real_path;
+ (void) strncat(tempbuf, orig_namep, MAXPATHLEN);
+ from_label = getlabelbypath(tempbuf);
+ if (from_label != NULL) {
+ if (blequal(from_label, &admin_low)) {
+ if ((getpathbylabel(tempbuf, buf,
+ MAXPATHLEN, &bs_label) == NULL)) {
+ (void) fprintf(stderr,
+ gettext("tar: "
+ "can't get zone root path for "
+ "%s\n"), tempbuf);
+ } else
+ rpath_flag = 1;
+ }
+ free(from_label);
+ }
+ }
+ break;
+
+ case COMP_TYPE:
+
+ rebuild_comp_path(dummy_buf, file_ptr);
+ break;
+
+ case LK_COMP_TYPE:
+
+ if (rebuild_lk_comp_path(dummy_buf, file_ptr)
+ == 0) {
+ lk_rpath_flag = 1;
+ } else {
+ (void) fprintf(stderr, gettext("tar: warning: link's "
+ "target pathname might be invalid.\n"));
+ lk_rpath_flag = 0;
+ }
+ break;
+ case APRIV_TYPE:
+ ignored_aprivs++;
+ break;
+ case FPRIV_TYPE:
+ ignored_fprivs++;
+ break;
+ case ATTR_FLAG_TYPE:
+ ignored_fattrs++;
+ break;
+
+ default:
+
+ break;
+ }
+
+ /* done */
+ return;
+
+} /* end extract_attr */
+
+
+
+/*
+ * Name: rebuild_comp_path()
+ *
+ * Description:
+ * Take the string of components passed down by the calling
+ * routine and parse the values and rebuild the path.
+ * This routine no longer needs to produce a new real_path
+ * string because it is produced when the 'L' LABEL_TYPE is
+ * interpreted. So the only thing done here is to distinguish
+ * between an SLD and an MLD entry. We only want one, so we
+ * ignore the MLD entry by setting the mld_flag.
+ *
+ * return value:
+ * none
+ */
+static void
+rebuild_comp_path(char *str, char **namep)
+{
+ char *cp;
+
+ while (*str != '\0') {
+
+ switch (*str) {
+
+ case MLD_TYPE:
+
+ str++;
+ if ((cp = strstr(str, ";;")) != NULL) {
+ *cp = '\0';
+ str = cp + 2;
+ *cp = ';';
+ }
+ mld_flag = 1;
+ break;
+
+ case SLD_TYPE:
+
+ str++;
+ if ((cp = strstr(str, ";;")) != NULL) {
+ *cp = '\0';
+ str = cp + 2;
+ *cp = ';';
+ }
+ mld_flag = 0;
+ break;
+
+ case PATH_TYPE:
+
+ str++;
+ if ((cp = strstr(str, ";;")) != NULL) {
+ *cp = '\0';
+ str = cp + 2;
+ *cp = ';';
+ }
+ break;
+ }
+ }
+ if (rpath_flag)
+ *namep = real_path;
+ return;
+
+} /* end rebuild_comp_path() */
+
+/*
+ * Name: rebuild_lk_comp_path()
+ *
+ * Description:
+ * Take the string of components passed down by the calling
+ * routine and parse the values and rebuild the path.
+ *
+ * return value:
+ * 0 = succeeded
+ * -1 = failed
+ */
+static int
+rebuild_lk_comp_path(char *str, char **namep)
+{
+ char *cp;
+ int reterr;
+ bslabel_t bslabel;
+ char *buf;
+ char pbuf[MAXPATHLEN];
+ char *ptr1, *ptr2;
+ int plen;
+ int use_pbuf;
+ char tempbuf[MAXPATHLEN];
+ int mismatch;
+ bslabel_t *from_label;
+ char zonename[ZONENAME_MAX];
+ zoneid_t zoneid;
+
+ /* init stuff */
+ use_pbuf = 0;
+ mismatch = 0;
+
+ /*
+ * For linked to pathname (LK_COMP_TYPE):
+ * - If the linked to pathname is absolute (start with /), we
+ * will use it as is.
+ * - If it is a relative pathname then it is relative to 1 of 2
+ * directories. For a hardlink, it is relative to the current
+ * directory. For a symbolic link, it is relative to the
+ * directory the symbolic link is in. For the symbolic link
+ * case, set a flag to indicate we need to use the prefix of
+ * the restored file's pathname with the linked to pathname.
+ *
+ * NOTE: At this point, we have no way to determine if we have
+ * a hardlink or a symbolic link. We will compare the 1st
+ * component in the prefix portion of the restore file's
+ * pathname to the 1st component in the attribute data
+ * (the linked pathname). If they are the same, we will assume
+ * the link pathname to reconstruct is relative to the current
+ * directory. Otherwise, we will set a flag indicate we need
+ * to use a prefix with the reconstructed name. Need to compare
+ * both the adorned and unadorned version before deciding a
+ * mismatch.
+ */
+
+ buf = lk_real_path;
+ if (*(str + 1) != '/') { /* got relative linked to path */
+ ptr1 = orig_namep;
+ ptr2 = strrchr(ptr1, '/');
+ plen = ptr2 - ptr1;
+ if (plen > 0) {
+ pbuf[0] = '\0';
+ plen++; /* include '/' */
+ (void) strncpy(pbuf, ptr1, plen);
+ *(pbuf + plen) = '\0';
+ ptr2 = strchr(pbuf, '/');
+ if (strncmp(pbuf, str + 1, ptr2 - pbuf) != 0)
+ mismatch = 1;
+ }
+
+ if (mismatch == 1)
+ use_pbuf = 1;
+ }
+
+ buf[0] = '\0';
+
+ while (*str != '\0') {
+
+ switch (*str) {
+
+ case MLD_TYPE:
+
+ str++;
+ if ((cp = strstr(str, ";;")) != NULL) {
+ *cp = '\0';
+
+ /*
+ * Ignore attempts to backup over .MLD.
+ */
+ if (strcmp(str, "../") != 0)
+ (void) strncat(buf, str, MAXPATHLEN);
+ str = cp + 2;
+ *cp = ';';
+ }
+ break;
+
+ case SLD_TYPE:
+
+ str++;
+ if ((cp = strstr(str, ";;")) != NULL) {
+ *cp = '\0';
+
+ /*
+ * Use the path name in the header if
+ * error occurs when processing the
+ * SLD type.
+ */
+
+ if (!stobsl(str, &bslabel,
+ NO_CORRECTION, &reterr)) {
+ (void) fprintf(stderr, gettext(
+ "tar: can't translate to binary"
+ "SL for SLD, stobsl() error:"
+ " %s\n"), strerror(errno));
+ return (-1);
+ }
+
+ str = cp + 2;
+ *cp = ';';
+
+ if (use_pbuf == 1) {
+ if (*pbuf != '/') {
+ /* relative linked to path */
+
+ (void) getcwd(tempbuf,
+ (sizeof (tempbuf)));
+ (void) strncat(tempbuf, "/",
+ MAXPATHLEN);
+ (void) strncat(tempbuf, pbuf,
+ MAXPATHLEN);
+ }
+ else
+ (void) strcpy(tempbuf, pbuf);
+
+ } else if (*buf != '/') {
+ /* got relative linked to path */
+
+ (void) getcwd(tempbuf,
+ (sizeof (tempbuf)));
+ (void) strncat(tempbuf, "/",
+ MAXPATHLEN);
+ } else
+ *tempbuf = '\0';
+
+ (void) strncat(tempbuf, buf, MAXPATHLEN);
+ *buf = '\0';
+
+ if (blequal(&bslabel, &admin_high)) {
+ bslabel = admin_low;
+ }
+
+
+ /*
+ * Check for cross-zone symbolic links
+ */
+ from_label = getlabelbypath(real_path);
+ if (rpath_flag && (from_label != NULL) &&
+ !blequal(&bslabel, from_label)) {
+ if ((zoneid =
+ getzoneidbylabel(&bslabel)) == -1) {
+ (void) fprintf(stderr,
+ gettext("tar: can't get "
+ "zone ID for %s\n"),
+ tempbuf);
+ return (-1);
+ }
+ if (zone_getattr(zoneid, ZONE_ATTR_NAME,
+ &zonename, ZONENAME_MAX) == -1) {
+ /* Badly configured zone info */
+ (void) fprintf(stderr,
+ gettext("tar: can't get "
+ "zonename for %s\n"),
+ tempbuf);
+ return (-1);
+ }
+ (void) strncpy(buf, AUTO_ZONE,
+ MAXPATHLEN);
+ (void) strncat(buf, "/",
+ MAXPATHLEN);
+ (void) strncat(buf, zonename,
+ MAXPATHLEN);
+ }
+ if (from_label != NULL)
+ free(from_label);
+ (void) strncat(buf, tempbuf, MAXPATHLEN);
+ break;
+ }
+ mld_flag = 0;
+ break;
+
+ case PATH_TYPE:
+
+ str++;
+ if ((cp = strstr(str, ";;")) != NULL) {
+ *cp = '\0';
+ (void) strncat(buf, str, MAXPATHLEN);
+ str = cp + 2;
+ *cp = ';';
+ }
+ break;
+
+ default:
+
+ (void) fprintf(stderr, gettext(
+ "tar: error rebuilding path %s\n"),
+ *namep);
+ *buf = '\0';
+ str++;
+ return (-1);
+ }
+ }
+
+ /*
+ * Done for LK_COMP_TYPE
+ */
+
+ return (0); /* component path is rebuilt successfully */
+
+} /* end rebuild_lk_comp_path() */
+
+/*
+ * Name: check_ext_attr()
+ *
+ * Description:
+ * Check the extended attributes for a file being extracted.
+ * The attributes being checked here are CMW labels.
+ * ACLs are not set here because they are set by the
+ * pflag in doxtract().
+ *
+ * If the label doesn't match, return 0
+ * else return 1
+ */
+static int
+check_ext_attr(char *filename)
+{
+ bslabel_t currentlabel; /* label from zone */
+
+ if (bltype(&bs_label, SUN_SL_UN)) {
+ /* No label check possible */
+ return (0);
+ }
+ if (getlabel(filename, ¤tlabel) != 0) {
+ (void) fprintf(stderr,
+ gettext("tar: can't get label for "
+ " %s, getlabel() error: %s\n"),
+ filename, strerror(errno));
+ return (0);
+ } else if ((blequal(¤tlabel, &bs_label)) == 0) {
+ char *src_label = NULL; /* ascii label */
+
+ /* get current src SL */
+ if (bsltos(&bs_label, &src_label, 0, 0) <= 0) {
+ (void) fprintf(stderr,
+ gettext("tar: can't interpret requested label for"
+ " %s\n"), filename);
+ } else {
+ (void) fprintf(stderr,
+ gettext("tar: can't apply label %s to %s\n"),
+ src_label, filename);
+ free(src_label);
+ }
+ (void) fprintf(stderr,
+ gettext("tar: %s not restored\n"), filename);
+ return (0);
+ }
+ return (1);
+
+} /* end check_ext_attr */
--- a/usr/src/cmd/truss/Makefile.com Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/truss/Makefile.com Fri Mar 24 12:29:20 2006 -0800
@@ -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.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -40,7 +39,9 @@
CFLAGS += $(CCVERBOSE)
CFLAGS64 += $(CCVERBOSE)
-LDLIBS += -lproc -lrtld_db -lc_db -lnsl -lsocket
+LAZYLIBS = $(ZLAZYLOAD) -ltsol $(ZNOLAZYLOAD)
+lint := LAZYLIBS = -ltsol
+LDLIBS += -lproc -lrtld_db -lc_db -lnsl -lsocket $(LAZYLIBS)
CPPFLAGS += -D_REENTRANT -D_LARGEFILE64_SOURCE=1
--- a/usr/src/cmd/truss/expound.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/truss/expound.c Fri Mar 24 12:29:20 2006 -0800
@@ -90,6 +90,7 @@
#include <sys/zone.h>
#include <sys/priv_impl.h>
#include <sys/priv.h>
+#include <tsol/label.h>
#include "ramdata.h"
#include "systable.h"
@@ -4440,6 +4441,33 @@
(void) printf("%s\textended_error: 0x%p\n", pri->pname,
(void *)args.extended_error);
+ if (is_system_labeled()) {
+ char *label_str = NULL;
+ bslabel_t zone_label;
+
+ (void) printf("%s\t match: %d\n", pri->pname,
+ args.match);
+ (void) printf("%s\t doi: %d\n", pri->pname,
+ args.doi);
+
+ if (Pread_string(Proc, (char *)&zone_label,
+ sizeof (zone_label), (uintptr_t)args.label) != -1) {
+ /* show the label as string */
+ if (label_to_str(&zone_label, &label_str,
+ M_LABEL, SHORT_NAMES) != 0) {
+ /* have to dump label as raw string */
+ (void) label_to_str(&zone_label,
+ &label_str, M_INTERNAL,
+ SHORT_NAMES);
+ }
+ }
+
+ (void) printf("%s\t label: %s\n",
+ pri->pname, label_str != NULL ? label_str : "<?>");
+ if (label_str)
+ free(label_str);
+ }
+
if (args.zfsbufsz > 0)
free(zone_zfs);
}
@@ -4495,6 +4523,32 @@
(void) printf("%s\textended_error: 0x%x\n", pri->pname,
(caddr32_t)args.extended_error);
+ if (is_system_labeled()) {
+ char *label_str = NULL;
+ bslabel_t zone_label;
+
+ (void) printf("%s\t match: %d\n", pri->pname,
+ args.match);
+ (void) printf("%s\t doi: %d\n", pri->pname,
+ args.doi);
+
+ if (Pread_string(Proc, (char *)&zone_label,
+ sizeof (zone_label), (caddr32_t)args.label) != -1) {
+ /* show the label as string */
+ if (label_to_str(&zone_label, &label_str,
+ M_LABEL, SHORT_NAMES) != 0) {
+ /* have to dump label as raw string */
+ (void) label_to_str(&zone_label,
+ &label_str, M_INTERNAL,
+ SHORT_NAMES);
+ }
+ }
+ (void) printf("%s\t label: %s\n",
+ pri->pname, label_str != NULL ? label_str : "<?>");
+ if (label_str)
+ free(label_str);
+ }
+
if (args.zfsbufsz > 0)
free(zone_zfs);
}
--- a/usr/src/cmd/truss/print.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/truss/print.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -77,6 +76,7 @@
#include <sys/utrap.h>
#include <sys/lgrp_user.h>
#include <sys/door.h>
+#include <sys/tsol/tndb.h>
#include "ramdata.h"
#include "print.h"
#include "proto.h"
@@ -2310,6 +2310,7 @@
case ZONE_ATTR_UNIQID: s = "ZONE_ATTR_UNIQID"; break;
case ZONE_ATTR_POOLID: s = "ZONE_ATTR_POOLID"; break;
case ZONE_ATTR_INITPID: s = "ZONE_ATTR_INITPID"; break;
+ case ZONE_ATTR_SLBL: s = "ZONE_ATTR_SLBL"; break;
}
}
@@ -2332,6 +2333,30 @@
}
/*
+ * Print Trusted Networking database operation codes (labelsys; tn*)
+ */
+static void
+prt_tnd(private_t *pri, int raw, long val)
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch ((tsol_dbops_t)val) {
+ case TNDB_NOOP: s = "TNDB_NOOP"; break;
+ case TNDB_LOAD: s = "TNDB_LOAD"; break;
+ case TNDB_DELETE: s = "TNDB_DELETE"; break;
+ case TNDB_FLUSH: s = "TNDB_FLUSH"; break;
+ case TNDB_GET: s = "TNDB_GET"; break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+/*
* Print LIO_XX flags
*/
void
@@ -2501,5 +2526,6 @@
prt_lio, /* LIO -- print LIO_XX flags */
prt_dfl, /* DFL -- print door_create() flags */
prt_dpm, /* DPM -- print DOOR_PARAM_XX flags */
+ prt_tnd, /* TND -- print trusted network data base opcode */
prt_dec, /* HID -- hidden argument, make this the last one */
};
--- a/usr/src/cmd/truss/print.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/truss/print.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -128,7 +127,8 @@
#define LIO 85 /* print LIO_XX flags */
#define DFL 86 /* print door_create() flags */
#define DPM 87 /* print DOOR_PARAM_XX flags */
-#define HID 88 /* hidden argument, don't print */
+#define TND 88 /* print trusted network data base opcode */
+#define HID 89 /* hidden argument, don't print */
/* make sure HID is always the last member */
/*
--- a/usr/src/cmd/truss/systable.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/truss/systable.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -410,7 +409,7 @@
{"rusagesys", 2, DEC, NOV, DEC, HEX}, /* 181 */
{"portfs", 6, HEX, HEX, DEC, HEX, HEX, HEX, HEX, HEX}, /* 182 */
{"pollsys", 4, DEC, NOV, HEX, DEC, HEX, HEX}, /* 183 */
-{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
+{"labelsys", 2, DEC, NOV, DEC, HEX}, /* 184 */
{"acl", 4, DEC, NOV, STG, ACL, DEC, HEX}, /* 185 */
{"auditsys", 4, DEC, NOV, AUD, HEX, HEX, HEX}, /* 186 */
{"processor_bind", 4, DEC, NOV, IDT, DEC, DEC, HEX}, /* 187 */
@@ -793,6 +792,17 @@
};
#define NZONECODE (sizeof (zonetable) / sizeof (struct systable))
+static const struct systable labeltable[] = {
+{"labelsys", 3, DEC, NOV, HID, HEX, HEX}, /* 0 */
+{"is_system_labeled", 1, DEC, NOV, HID}, /* 1 */
+{"tnrh", 3, DEC, NOV, HID, TND, HEX}, /* 2 */
+{"tnrhtp", 3, DEC, NOV, HID, TND, HEX}, /* 3 */
+{"tnmlp", 3, DEC, NOV, HID, TND, HEX}, /* 4 */
+{"getlabel", 3, DEC, NOV, HID, STG, HEX}, /* 5 */
+{"fgetlabel", 3, DEC, NOV, HID, DEC, HEX}, /* 6 */
+};
+#define NLABELCODE (sizeof (labeltable) / sizeof (struct systable))
+
const struct sysalias sysalias[] = {
{ "exit", SYS_exit },
{ "fork", SYS_fork1 },
@@ -928,10 +938,15 @@
{ "getzoneid", SYS_zone },
{ "zone_list", SYS_zone },
{ "zone_shutdown", SYS_zone },
+ { "is_system_labeled", SYS_labelsys },
+ { "tnrh", SYS_labelsys },
+ { "tnrhtp", SYS_labelsys },
+ { "tnmlp", SYS_labelsys },
+ { "getlabel", SYS_labelsys },
+ { "fgetlabel", SYS_labelsys },
{ NULL, 0 } /* end-of-list */
};
-
/*
* Return structure to interpret system call with sub-codes.
*/
@@ -1062,6 +1077,10 @@
if ((unsigned)subcode < NZONECODE)
stp = &zonetable[subcode];
break;
+ case SYS_labelsys: /* label family */
+ if ((unsigned)subcode < NLABELCODE)
+ stp = &labeltable[subcode];
+ break;
}
}
@@ -1212,6 +1231,7 @@
case SYS_rusagesys: /* rusagesys */
case SYS_ucredsys: /* ucredsys */
case SYS_zone: /* zone */
+ case SYS_labelsys: /* labelsys */
subcode = arg0;
break;
case SYS_fcntl: /* fcntl() */
@@ -1271,7 +1291,8 @@
+ NPRIVSYSCODE - 1
+ NUCREDSYSCODE - 1
+ NPORTCODE - 1
- + NZONECODE - 1);
+ + NZONECODE - 1
+ + NLABELCODE - 1);
}
/*
@@ -1341,6 +1362,8 @@
return (NPORTCODE);
case SYS_zone: /* zone */
return (NZONECODE);
+ case SYS_labelsys:
+ return (NLABELCODE);
default:
return (1);
}
--- a/usr/src/cmd/volmgt/rmm/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/volmgt/rmm/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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 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"
@@ -54,7 +54,7 @@
CPPFLAGS += -DACT_VERS=${ACT_VERS} -DIDENT_VERS=${IDENT_VERS}
-$(PROG) := LDLIBS += -lvolmgt -ladm
+$(PROG) := LDLIBS += -lvolmgt -ladm -lcontract
$(ACTSVOL) := LDLIBS += -lvolmgt
$(ACTS) := LDLIBS += -lc
--- a/usr/src/cmd/volmgt/rmm/rmm.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/volmgt/rmm/rmm.c Fri Mar 24 12:29:20 2006 -0800
@@ -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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -31,6 +31,7 @@
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
+#include <strings.h>
#include <errno.h>
#include <rmmount.h>
#include <locale.h>
@@ -46,6 +47,11 @@
#include <string.h>
#include <regex.h>
#include <ctype.h>
+#include <zone.h>
+#include <libcontract.h>
+#include <sys/contract/process.h>
+#include <sys/ctfs.h>
+#include <pwd.h>
#include "rmm_int.h"
extern int audio_only(struct action_arg *);
@@ -66,6 +72,13 @@
char *prog_name = NULL;
pid_t prog_pid = 0;
+int system_labeled = 0;
+uid_t mnt_uid = -1;
+gid_t mnt_gid = -1;
+zoneid_t mnt_zoneid = -1;
+char mnt_zoneroot[MAXPATHLEN];
+char mnt_userdir[MAXPATHLEN];
+
#define DEFAULT_CONFIG "/etc/rmmount.conf"
#define DEFAULT_DSODIR "/usr/lib/rmmount"
@@ -160,6 +173,8 @@
char *volume_path;
char *volume_pcfs_id;
char *volume_symdev;
+ char *volume_zonename;
+ char *volume_user;
/*
* Make sure core files appear in a volmgt directory.
@@ -190,6 +205,10 @@
return (-1);
}
+ system_labeled = is_system_labeled();
+ mnt_zoneroot[0] = '\0';
+ mnt_userdir[0] = '\0';
+
while ((c = getopt(argc, argv, "d:c:D")) != EOF) {
switch (c) {
case 'D':
@@ -216,6 +235,11 @@
volume_pcfs_id = getenv("VOLUME_PCFS_ID");
volume_symdev = getenv("VOLUME_SYMDEV");
+ if (system_labeled) {
+ volume_zonename = getenv("VOLUME_ZONE_NAME");
+ volume_user = getenv("VOLUME_USER");
+ }
+
if (volume_action == NULL) {
dprintf("%s(%ld): VOLUME_ACTION was null!!\n",
prog_name, prog_pid);
@@ -248,6 +272,43 @@
return (-1);
}
+ if (system_labeled) {
+ if (volume_zonename != NULL &&
+ strcmp(volume_zonename, GLOBAL_ZONENAME) != 0) {
+ if ((mnt_zoneid =
+ getzoneidbyname(volume_zonename)) != -1) {
+ if (zone_getattr(mnt_zoneid, ZONE_ATTR_ROOT,
+ mnt_zoneroot, MAXPATHLEN) == -1) {
+ dprintf("%s(%ld): NO ZONEPATH!!\n",
+ prog_name, prog_pid);
+ return (-1);
+ }
+ }
+ } else {
+ mnt_zoneid = GLOBAL_ZONEID;
+ mnt_zoneroot[0] = '\0';
+ }
+ if (volume_user != NULL) {
+ struct passwd *pw;
+
+ if ((pw = getpwnam(volume_user)) == NULL) {
+ dprintf("%s(%ld) %s\n", prog_name, prog_pid,
+ ": VOLUME_USER was not a valid user!");
+ return (-1);
+ }
+ mnt_uid = pw->pw_uid;
+ mnt_gid = pw->pw_gid;
+
+ if (snprintf(mnt_userdir, sizeof (mnt_userdir),
+ "/%s-%s", volume_user, volume_symdev) >=
+ sizeof (mnt_userdir))
+ return (-1);
+ } else {
+ mnt_uid = 0;
+ mnt_userdir[0] = '\0';
+ }
+ }
+
dprintf("%s[%d]: VOLUME_NAME = %s\n", __FILE__, __LINE__, volume_name);
dprintf("%s[%d]: VOLUME_PATH = %s\n", __FILE__, __LINE__, volume_path);
dprintf("%s[%d]: VOLUME_ACTION = %s\n", __FILE__, __LINE__,
@@ -260,6 +321,12 @@
volume_mount_mode);
dprintf("%s[%d]: VOLUME_PCFS_ID = %s\n", __FILE__, __LINE__,
volume_pcfs_id);
+ if (system_labeled) {
+ dprintf("%s[%d]: VOLUME_ZONE_NAME = %s\n", __FILE__, __LINE__,
+ volume_zonename);
+ dprintf("%s[%d]: VOLUME_USER = %s\n", __FILE__, __LINE__,
+ volume_user);
+ }
/*
* Read in the configuration file to build
@@ -318,7 +385,11 @@
}
ai = 0;
while ((aa[ai] != NULL) && (aa[ai]->aa_path != NULL)) {
- aa[ai]->aa_type = "unknown";
+ if (system_labeled &&
+ (strcmp(volume_mediatype, "rmdisk") == 0))
+ aa[ai]->aa_type = "pcfs";
+ else
+ aa[ai]->aa_type = "unknown";
ai++;
}
}
@@ -688,20 +759,76 @@
action_list[i]->a_action = act_func;
}
if (act_func != NULL) {
- dprintf("%s[%d]: executing action() in %s\n",
- __FILE__, __LINE__,
- action_list[i]->a_dsoname);
- retval = (*act_func)(aa,
- action_list[i]->a_argc,
- action_list[i]->a_argv);
- dprintf("%s[%d]: action() returns %d\n",
- __FILE__, __LINE__, retval);
+ if (!premount && mnt_zoneid > GLOBAL_ZONEID) {
+ pid_t pid;
+ int status;
+ int ifx;
+ int tmpl_fd;
+ int err = 0;
+
+ tmpl_fd = open64(CTFS_ROOT "/process/template",
+ O_RDWR);
+ if (tmpl_fd == -1)
+ break;
+
/*
- * If action returns 0, no further actions
- * will be executed. (see rmmount.conf(4))
+ * Deliver no events, don't inherit,
+ * and allow it to be orphaned.
*/
- if (retval == 0)
+ err |= ct_tmpl_set_critical(tmpl_fd, 0);
+ err |= ct_tmpl_set_informative(tmpl_fd, 0);
+ err |= ct_pr_tmpl_set_fatal(tmpl_fd,
+ CT_PR_EV_HWERR);
+ err |= ct_pr_tmpl_set_param(tmpl_fd,
+ CT_PR_PGRPONLY |
+ CT_PR_REGENT);
+ if (err || ct_tmpl_activate(tmpl_fd)) {
+ (void) close(tmpl_fd);
+ break;
+ }
+ switch (pid = fork1()) {
+ case 0:
+ (void) ct_tmpl_clear(tmpl_fd);
+ for (ifx = 0; ifx < _NFILE; ifx++)
+ (void) close(ifx);
+
+ if (zone_enter(mnt_zoneid) == -1)
+ _exit(0);
+ (void) (*act_func)(aa,
+ action_list[i]->a_argc,
+ action_list[i]->a_argv);
+ _exit(0);
+ case -1:
+ dprintf("fork1 failed \n ");
break;
+ default :
+ (void) ct_tmpl_clear(tmpl_fd);
+ (void) close(tmpl_fd);
+ if (waitpid(pid, &status, 0) < 0) {
+ dprintf("%s(%ld): waitpid() "
+ "failed (errno %d) \n",
+ prog_name, prog_pid, errno);
+ break;
+ }
+ }
+ } else {
+ dprintf("%s[%d]: executing action() "
+ "in %s\n",
+ __FILE__, __LINE__,
+ action_list[i]->a_dsoname);
+ retval = (*act_func)(aa,
+ action_list[i]->a_argc,
+ action_list[i]->a_argv);
+ dprintf("%s[%d]: action() returns %d\n",
+ __FILE__, __LINE__, retval);
+ /*
+ * If action returns 0, no further
+ * actions will be executed.
+ * (see rmmount.conf(4))
+ */
+ if (retval == 0)
+ break;
+ }
}
}
i++;
@@ -874,7 +1001,6 @@
if (aa[ai]->aa_mountpoint)
mnt_ai = ai;
}
-
if (ma[CMD_SHARE] != NULL) {
/*
* export the file system.
@@ -904,10 +1030,17 @@
(void) symlink(aa[mnt_ai]->aa_mountpoint, symname);
}
#else /* !OLD_SLICE_HANDLING_CODE */
- (void) snprintf(symcontents, sizeof (symcontents),
- "./%s", name);
- (void) snprintf(symname, sizeof (symname),
- "/%s/%s", aa[mnt_ai]->aa_media, symdev);
+ if (system_labeled) {
+ (void) snprintf(symcontents, sizeof (symcontents),
+ ".%s/%s", mnt_userdir, name);
+ (void) snprintf(symname, sizeof (symname), "%s/%s/%s",
+ mnt_zoneroot, aa[mnt_ai]->aa_media, symdev);
+ } else {
+ (void) snprintf(symcontents, sizeof (symcontents),
+ "./%s", name);
+ (void) snprintf(symname, sizeof (symname),
+ "/%s/%s", aa[mnt_ai]->aa_media, symdev);
+ }
(void) unlink(symname);
(void) symlink(symcontents, symname);
#endif /* !OLD_SLICE_HANDLING_CODE */
@@ -957,10 +1090,9 @@
dprintf("%s[%d]: mount path = %s\n",
__FILE__, __LINE__, mnt_path);
+ if ((mountpoint = getmntpoint(mnt_path)) == NULL)
+ continue;
- if ((mountpoint = getmntpoint(mnt_path)) == NULL) {
- continue;
- }
/*
* find the right mount arguments for this device
*/
@@ -1006,7 +1138,6 @@
if (ma != NULL) {
unshare_mount(aa[ai], ma);
}
-
/*
* do the actual umount
*/
@@ -1020,13 +1151,11 @@
}
/* save a good mountpoint */
- if (oldmountpoint == NULL) {
+ if (oldmountpoint == NULL)
oldmountpoint = strdup(mountpoint);
- }
free(mountpoint);
mountpoint = NULL;
}
-
/*
* clean up our directories and such if all went well
*/
@@ -1053,28 +1182,60 @@
* try to remove the symlink
*/
- if (snprintf(rmm_mountpoint, sizeof (rmm_mountpoint),
- "/%s/%s", aa[0]->aa_media, volume_name)
- >= sizeof (rmm_mountpoint))
- success = FALSE;
-
- if (success && (oldmountpoint != NULL) &&
- (strcmp(oldmountpoint, rmm_mountpoint) == 0)) {
+ if (system_labeled) {
+ /* Prefix with zoneroot and userdir */
+ if (snprintf(rmm_mountpoint, MAXPATHLEN, "%s/%s%s/%s",
+ mnt_zoneroot, aa[0]->aa_media, mnt_userdir,
+ volume_name) >= MAXPATHLEN)
+ success = FALSE;
+ } else {
+ if (snprintf(rmm_mountpoint, sizeof (rmm_mountpoint),
+ "/%s/%s", aa[0]->aa_media, volume_name)
+ >= sizeof (rmm_mountpoint))
+ success = FALSE;
+ }
+ if ((system_labeled && success) ||
+ (success && (oldmountpoint != NULL) &&
+ (strcmp(oldmountpoint, rmm_mountpoint) == 0))) {
char symname[MAXNAMELEN];
/* remove volmgt mount point */
- (void) rmdir(oldmountpoint);
+ if (oldmountpoint)
+ (void) rmdir(oldmountpoint);
+ if (system_labeled && (strlen(mnt_userdir) > 0)) {
+ char *p = NULL;
+
+ /*
+ * We may also need to remove the
+ * user's private directory which
+ * we created during mount.
+ */
+ (void) rmdir(rmm_mountpoint);
+ if (p = rindex(rmm_mountpoint, '/')) {
+ *p = '\0';
+ (void) rmdir(rmm_mountpoint);
+ }
+ }
/* remove symlink (what harm if it does not exist?) */
- if (snprintf(symname, sizeof (symname), "/%s/%s",
- aa[0]->aa_media, symdev) >= sizeof (symname)) {
- success = FALSE;
+ if (system_labeled) {
+ /* Prefix with zoneroot */
+ if (snprintf(symname, sizeof (symname),
+ "%s/%s/%s",
+ mnt_zoneroot, aa[0]->aa_media, symdev)
+ >= sizeof (symname))
+ success = FALSE;
+ } else {
+ if (snprintf(symname, sizeof (symname),
+ "/%s/%s",
+ aa[0]->aa_media, symdev)
+ >= sizeof (symname))
+ success = FALSE;
}
if (success)
(void) unlink(symname);
}
}
-
if (oldmountpoint != NULL) {
free(oldmountpoint);
}
@@ -1249,7 +1410,8 @@
*/
char *targ_dir;
char options[RMM_OPTSTRLEN]; /* mount option string */
- char *mountpoint = NULL;
+ char mountpoint[MAXPATHLEN];
+ char *zonemountpoint;
int mountpoint_bufcount = 0;
struct stat sb;
mode_t mpmode;
@@ -1330,33 +1492,45 @@
return (FALSE);
}
+ if (system_labeled && (strlen(mnt_userdir) > 0)) {
+ if (snprintf(mountpoint, MAXPATHLEN, "%s/%s%s",
+ mnt_zoneroot, aa->aa_media, mnt_userdir) > MAXPATHLEN) {
+ return (FALSE);
+
+ }
+ (void) makepath(mountpoint, 0700);
+ (void) chown(mountpoint, mnt_uid, mnt_gid);
+ /*
+ * set the top level directory bits to 0755 so user
+ * can access it.
+ */
+ if (snprintf(mountpoint, MAXPATHLEN, "%s/%s", mnt_zoneroot,
+ aa->aa_media) <= MAXPATHLEN)
+ (void) chmod(mountpoint, 0755);
+ }
+
if (aa->aa_partname) {
- mountpoint_bufcount = strlen(aa->aa_media) +
- strlen(targ_dir) + strlen(aa->aa_partname) + 3 + 1;
- /* 1 - for NULL terminator, 3 - for "/"s */
- mountpoint = malloc(mountpoint_bufcount);
- if (mountpoint == NULL) {
+ if (snprintf(mountpoint, MAXPATHLEN,
+ "%s/%s%s/%s/%s", mnt_zoneroot, aa->aa_media, mnt_userdir,
+ targ_dir, aa->aa_partname) > MAXPATHLEN) {
+ (void) fprintf(stderr,
+ gettext("%s(%ld) error: path too long\n"),
+ prog_name, prog_pid);
+ return (FALSE);
+ }
+ } else {
+ if (snprintf(mountpoint, MAXPATHLEN,
+ "%s/%s%s/%s", mnt_zoneroot, aa->aa_media, mnt_userdir,
+ targ_dir) > MAXPATHLEN) {
(void) fprintf(stderr,
gettext("%s(%ld) error: malloc failed\n"),
prog_name, prog_pid);
return (FALSE);
}
- (void) sprintf(mountpoint, "/%s/%s/%s", aa->aa_media,
- targ_dir, aa->aa_partname);
- } else {
- mountpoint_bufcount = strlen(aa->aa_media) +
- strlen(targ_dir) + 2 + 1;
- /* 1 - for NULL terminator, 2 - for "/"s */
- mountpoint = malloc(mountpoint_bufcount);
- if (mountpoint == NULL) {
- (void) fprintf(stderr,
- gettext("%s(%ld) error: malloc failed\n"),
- prog_name, prog_pid);
- return (FALSE);
- }
- (void) sprintf(mountpoint, "/%s/%s", aa->aa_media, targ_dir);
}
+ zonemountpoint = mountpoint + strlen(mnt_zoneroot);
+
/* make our mountpoint */
(void) makepath(mountpoint, 0755);
@@ -1455,7 +1629,7 @@
prog_name, prog_pid, mountpoint, options);
}
aa->aa_mnt = TRUE;
- aa->aa_mountpoint = strdup(mountpoint);
+ aa->aa_mountpoint = strdup(zonemountpoint);
dprintf(
"\nDEBUG: Setting u.g of \"%s\" to %d.%d (me=%d.%d)\n\n",
mountpoint, sb.st_uid, sb.st_gid, getuid(), getgid());
@@ -1489,9 +1663,6 @@
(void) rmdir(mountpoint); /* cleanup */
ret_val = FALSE;
}
- if (mountpoint != NULL)
- free(mountpoint);
-
return (ret_val);
}
--- a/usr/src/cmd/zoneadm/zoneadm.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/zoneadm/zoneadm.c Fri Mar 24 12:29:20 2006 -0800
@@ -398,7 +398,7 @@
static int
lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent)
{
- char root[MAXPATHLEN];
+ char root[MAXPATHLEN], *cp;
int err;
(void) strlcpy(zent->zname, zone_name, sizeof (zent->zname));
@@ -407,13 +407,33 @@
zent->zid = zid;
- if ((err = zone_get_zonepath(zent->zname, root, sizeof (root))) !=
- Z_OK) {
- errno = err;
- zperror2(zent->zname, gettext("could not get zone path"));
- return (Z_ERR);
- }
- (void) strlcpy(zent->zroot, root, sizeof (zent->zroot));
+ /*
+ * For labeled zones which query the zone path of lower-level
+ * zones, the path needs to be adjusted to drop the final
+ * "/root" component. This adjusted path is then useful
+ * for reading down any exported directories from the
+ * lower-level zone.
+ */
+ if (is_system_labeled() && zent->zid != ZONE_ID_UNDEFINED) {
+ if (zone_getattr(zent->zid, ZONE_ATTR_ROOT, zent->zroot,
+ sizeof (zent->zroot)) == -1) {
+ zperror2(zent->zname,
+ gettext("could not get zone path."));
+ return (Z_ERR);
+ }
+ cp = zent->zroot + strlen(zent->zroot) - 5;
+ if (cp > zent->zroot && strcmp(cp, "/root") == 0)
+ *cp = 0;
+ } else {
+ if ((err = zone_get_zonepath(zent->zname, root,
+ sizeof (root))) != Z_OK) {
+ errno = err;
+ zperror2(zent->zname,
+ gettext("could not get zone path."));
+ return (Z_ERR);
+ }
+ (void) strlcpy(zent->zroot, root, sizeof (zent->zroot));
+ }
if ((err = zone_get_state(zent->zname, &zent->zstate_num)) != Z_OK) {
errno = err;
@@ -1342,7 +1362,12 @@
*/
result = getzonenamebyid(zid, zeptr->zname, sizeof (zeptr->zname));
assert(result >= 0);
- (void) strlcpy(zeptr->zroot, "/", sizeof (zeptr->zroot));
+ if (!is_system_labeled()) {
+ (void) strlcpy(zeptr->zroot, "/", sizeof (zeptr->zroot));
+ } else {
+ (void) zone_getattr(zid, ZONE_ATTR_ROOT, zeptr->zroot,
+ sizeof (zeptr->zroot));
+ }
zeptr->zstate_str = "running";
}
@@ -1395,7 +1420,7 @@
cmd_to_str(CMD_LIST));
return (Z_ERR);
}
- if (zone_id == GLOBAL_ZONEID) {
+ if (zone_id == GLOBAL_ZONEID || is_system_labeled()) {
retv = zone_print_list(min_state, verbose, parsable);
} else {
retv = Z_OK;
@@ -3024,6 +3049,14 @@
}
/*
+ * Trusted Extensions requires that cloned zones use the
+ * same sysid configuration, so it is not appropriate to
+ * unconfigure the zone.
+ */
+ if (is_system_labeled())
+ return (Z_OK);
+
+ /*
* Check if the zone is already sys-unconfiged. This saves us
* the work of bringing up the scratch zone so we can unconfigure it.
*/
--- a/usr/src/cmd/zoneadmd/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/zoneadmd/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -17,6 +17,8 @@
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
+
+
#
#
@@ -38,8 +40,10 @@
POFILES= $(OBJS:%.o=%.po)
CFLAGS += $(CCVERBOSE)
+LAZYLIBS = $(ZLAZYLOAD) -ltsol $(ZNOLAZYLOAD)
+lint := LAZYLIBS = -ltsol
LDLIBS += -lsocket -lzonecfg -lnsl -ldevinfo -ldevice -lnvpair -lpool \
- -lgen -lbsm -lcontract -lzfs
+ -lgen -lbsm -lcontract -lzfs -ltsnet $(LAZYLIBS)
XGETFLAGS += -a -x zoneadmd.xcl
.KEEP_STATE:
--- a/usr/src/cmd/zoneadmd/vplat.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/cmd/zoneadmd/vplat.c Fri Mar 24 12:29:20 2006 -0800
@@ -106,6 +106,9 @@
#include <libzonecfg.h>
#include "zoneadmd.h"
+#include <tsol/label.h>
+#include <libtsnet.h>
+#include <sys/priv.h>
#define V4_ADDR_LEN 32
#define V6_ADDR_LEN 128
@@ -118,6 +121,7 @@
MNTOPT_RO "," MNTOPT_LOFS_NOSUB "," MNTOPT_NODEVICES
#define DFSTYPES "/etc/dfs/fstypes"
+#define MAXTNZLEN 2048
/*
* A list of directories which should be created.
@@ -176,6 +180,14 @@
/* array of cached mount entries for resolve_lofs */
static struct mnttab *resolve_lofs_mnts, *resolve_lofs_mnt_max;
+/* for Trusted Extensions */
+static tsol_zcent_t *get_zone_label(zlog_t *, priv_set_t *);
+static int tsol_mounts(zlog_t *, char *, char *);
+static void tsol_unmounts(zlog_t *, char *);
+static m_label_t *zlabel = NULL;
+static m_label_t *zid_label = NULL;
+static priv_set_t *zprivs = NULL;
+
/* from libsocket, not in any header file */
extern int getnetmaskbyaddr(struct in_addr, struct in_addr *);
@@ -457,8 +469,24 @@
* and we don't need to second guess him.
*/
if (!S_ISDIR(st.st_mode)) {
- zerror(zlogp, B_FALSE, "%s is not a directory", path);
- return (-1);
+ if (is_system_labeled() &&
+ S_ISREG(st.st_mode)) {
+ /*
+ * The need to mount readonly copies of
+ * global zone /etc/ files is unique to
+ * Trusted Extensions.
+ */
+ if (strncmp(subdir, "/etc/",
+ strlen("/etc/")) != 0) {
+ zerror(zlogp, B_FALSE,
+ "%s is not in /etc", path);
+ return (-1);
+ }
+ } else {
+ zerror(zlogp, B_FALSE,
+ "%s is not a directory", path);
+ return (-1);
+ }
}
} else if (mkdirp(path, mode) != 0) {
if (errno == EROFS)
@@ -690,6 +718,12 @@
(void) strcat(zroot, "/");
zrootlen = strlen(zroot);
+ /*
+ * For Trusted Extensions unmount each higher level zone's mount
+ * of our zone's /export/home
+ */
+ tsol_unmounts(zlogp, zone_name);
+
if ((mnttab = fopen(MNTTAB, "r")) == NULL) {
zerror(zlogp, B_TRUE, "failed to open %s", MNTTAB);
return (-1);
@@ -959,8 +993,23 @@
return (-1);
}
if (!S_ISDIR(statbuf.st_mode)) {
- zerror(zlogp, B_FALSE, "%s is not a directory", path);
- return (-1);
+ if (is_system_labeled() && S_ISREG(statbuf.st_mode)) {
+ /*
+ * The need to mount readonly copies of
+ * global zone /etc/ files is unique to
+ * Trusted Extensions.
+ * The check for /etc/ via strstr() is to
+ * allow paths like $ZONEROOT/etc/passwd
+ */
+ if (strstr(path, "/etc/") == NULL) {
+ zerror(zlogp, B_FALSE,
+ "%s is not in /etc", path);
+ return (-1);
+ }
+ } else {
+ zerror(zlogp, B_FALSE, "%s is not a directory", path);
+ return (-1);
+ }
}
if ((res = resolvepath(path, respath, sizeof (respath))) == -1) {
zerror(zlogp, B_TRUE, "unable to resolve path %s", path);
@@ -1476,6 +1525,13 @@
if (mount_one(zlogp, &fs_ptr[i], rootpath) != 0)
goto bad;
}
+
+ /*
+ * For Trusted Extensions cross-mount each lower level /export/home
+ */
+ if (tsol_mounts(zlogp, zone_name, rootpath) != 0)
+ goto bad;
+
free_fs_data(fs_ptr, num_fs);
/*
@@ -2706,6 +2762,507 @@
return (0);
}
+/*
+ * Mount lower level home directories into/from current zone
+ * Share exported directories specified in dfstab for zone
+ */
+static int
+tsol_mounts(zlog_t *zlogp, char *zone_name, char *rootpath)
+{
+ zoneid_t *zids = NULL;
+ priv_set_t *zid_privs;
+ const priv_impl_info_t *ip = NULL;
+ uint_t nzents_saved;
+ uint_t nzents;
+ int i;
+ char readonly[] = "ro";
+ struct zone_fstab lower_fstab;
+ char *argv[4];
+
+ if (!is_system_labeled())
+ return (0);
+
+ if (zid_label == NULL) {
+ zid_label = m_label_alloc(MAC_LABEL);
+ if (zid_label == NULL)
+ return (-1);
+ }
+
+ /* Make sure our zone has an /export/home dir */
+ (void) make_one_dir(zlogp, rootpath, "/export/home",
+ DEFAULT_DIR_MODE);
+
+ lower_fstab.zone_fs_raw[0] = '\0';
+ (void) strlcpy(lower_fstab.zone_fs_type, MNTTYPE_LOFS,
+ sizeof (lower_fstab.zone_fs_type));
+ lower_fstab.zone_fs_options = NULL;
+ (void) zonecfg_add_fs_option(&lower_fstab, readonly);
+
+ /*
+ * Get the list of zones from the kernel
+ */
+ if (zone_list(NULL, &nzents) != 0) {
+ zerror(zlogp, B_TRUE, "unable to list zones");
+ zonecfg_free_fs_option_list(lower_fstab.zone_fs_options);
+ return (-1);
+ }
+again:
+ if (nzents == 0) {
+ zonecfg_free_fs_option_list(lower_fstab.zone_fs_options);
+ return (-1);
+ }
+
+ zids = malloc(nzents * sizeof (zoneid_t));
+ if (zids == NULL) {
+ zerror(zlogp, B_TRUE, "unable to allocate memory");
+ return (-1);
+ }
+ nzents_saved = nzents;
+
+ if (zone_list(zids, &nzents) != 0) {
+ zerror(zlogp, B_TRUE, "unable to list zones");
+ zonecfg_free_fs_option_list(lower_fstab.zone_fs_options);
+ free(zids);
+ return (-1);
+ }
+ if (nzents != nzents_saved) {
+ /* list changed, try again */
+ free(zids);
+ goto again;
+ }
+
+ ip = getprivimplinfo();
+ if ((zid_privs = priv_allocset()) == NULL) {
+ zerror(zlogp, B_TRUE, "%s failed", "priv_allocset");
+ zonecfg_free_fs_option_list(
+ lower_fstab.zone_fs_options);
+ free(zids);
+ return (-1);
+ }
+
+ for (i = 0; i < nzents; i++) {
+ char zid_name[ZONENAME_MAX];
+ zone_state_t zid_state;
+ char zid_rpath[MAXPATHLEN];
+ struct stat stat_buf;
+
+ if (zids[i] == GLOBAL_ZONEID)
+ continue;
+
+ if (getzonenamebyid(zids[i], zid_name, ZONENAME_MAX) == -1)
+ continue;
+
+ /*
+ * Do special setup for the zone we are booting
+ */
+ if (strcmp(zid_name, zone_name) == 0) {
+ struct zone_fstab autofs_fstab;
+ char map_path[MAXPATHLEN];
+ int fd;
+
+ /*
+ * Create auto_home_<zone> map for this zone
+ * in the global zone. The local zone entry
+ * will be created by automount when the zone
+ * is booted.
+ */
+
+ (void) snprintf(autofs_fstab.zone_fs_special,
+ MAXPATHLEN, "auto_home_%s", zid_name);
+
+ (void) snprintf(autofs_fstab.zone_fs_dir, MAXPATHLEN,
+ "/zone/%s/home", zid_name);
+
+ (void) snprintf(map_path, sizeof (map_path),
+ "/etc/%s", autofs_fstab.zone_fs_special);
+ /*
+ * 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",
+ autofs_fstab.zone_fs_special, rootpath);
+ (void) write(fd, map_rec, len);
+ (void) close(fd);
+ }
+
+ /*
+ * Mount auto_home_<zone> in the global zone if absent.
+ * If it's already of type autofs, then
+ * don't mount it again.
+ */
+ if ((stat(autofs_fstab.zone_fs_dir, &stat_buf) == -1) ||
+ strcmp(stat_buf.st_fstype, MNTTYPE_AUTOFS) != 0) {
+ char optstr[] = "indirect,ignore,nobrowse";
+
+ (void) make_one_dir(zlogp, "",
+ autofs_fstab.zone_fs_dir, DEFAULT_DIR_MODE);
+
+ /*
+ * Mount will fail if automounter has already
+ * processed the auto_home_<zonename> map
+ */
+ (void) domount(zlogp, MNTTYPE_AUTOFS, optstr,
+ autofs_fstab.zone_fs_special,
+ autofs_fstab.zone_fs_dir);
+ }
+ continue;
+ }
+
+
+ if (zone_get_state(zid_name, &zid_state) != Z_OK ||
+ (zid_state != ZONE_STATE_MOUNTED &&
+ zid_state != ZONE_STATE_RUNNING)) {
+
+ /* Skip over zones without mounted filesystems */
+ continue;
+ }
+
+ if (zone_getattr(zids[i], ZONE_ATTR_SLBL, zid_label,
+ sizeof (m_label_t)) < 0)
+ /* Skip over zones with unspecified label */
+ continue;
+
+ if (zone_getattr(zids[i], ZONE_ATTR_ROOT, zid_rpath,
+ sizeof (zid_rpath)) == -1)
+ /* Skip over zones with bad path */
+ continue;
+
+ if (zone_getattr(zids[i], ZONE_ATTR_PRIVSET, zid_privs,
+ sizeof (priv_chunk_t) * ip->priv_setsize) == -1)
+ /* Skip over zones with bad privs */
+ continue;
+
+ /*
+ * Reading down is valid according to our label model
+ * but some customers want to disable it because it
+ * allows execute down and other possible attacks.
+ * Therefore, we restrict this feature to zones that
+ * have the NET_MAC_AWARE privilege which is required
+ * for NFS read-down semantics.
+ */
+ if ((bldominates(zlabel, zid_label)) &&
+ (priv_ismember(zprivs, PRIV_NET_MAC_AWARE))) {
+ /*
+ * Our zone dominates this one.
+ * Create a lofs mount from lower zone's /export/home
+ */
+ (void) snprintf(lower_fstab.zone_fs_dir, MAXPATHLEN,
+ "%s/zone/%s/export/home", rootpath, zid_name);
+
+ /*
+ * If the target is already an LOFS mount
+ * then don't do it again.
+ */
+ if ((stat(lower_fstab.zone_fs_dir, &stat_buf) == -1) ||
+ strcmp(stat_buf.st_fstype, MNTTYPE_LOFS) != 0) {
+
+ if (snprintf(lower_fstab.zone_fs_special,
+ MAXPATHLEN, "%s/export",
+ zid_rpath) > MAXPATHLEN)
+ continue;
+
+ /*
+ * Make sure the lower-level home exists
+ */
+ if (make_one_dir(zlogp,
+ lower_fstab.zone_fs_special,
+ "/home", DEFAULT_DIR_MODE) != 0)
+ continue;
+
+ (void) strlcat(lower_fstab.zone_fs_special,
+ "/home", MAXPATHLEN);
+
+ /*
+ * Mount can fail because the lower-level
+ * zone may have already done a mount up.
+ */
+ (void) mount_one(zlogp, &lower_fstab, "");
+ }
+ } else if ((bldominates(zid_label, zlabel)) &&
+ (priv_ismember(zid_privs, PRIV_NET_MAC_AWARE))) {
+ /*
+ * This zone dominates our zone.
+ * Create a lofs mount from our zone's /export/home
+ */
+ if (snprintf(lower_fstab.zone_fs_dir, MAXPATHLEN,
+ "%s/zone/%s/export/home", zid_rpath,
+ zone_name) > MAXPATHLEN)
+ continue;
+
+ /*
+ * If the target is already an LOFS mount
+ * then don't do it again.
+ */
+ if ((stat(lower_fstab.zone_fs_dir, &stat_buf) == -1) ||
+ strcmp(stat_buf.st_fstype, MNTTYPE_LOFS) != 0) {
+
+ (void) snprintf(lower_fstab.zone_fs_special,
+ MAXPATHLEN, "%s/export/home", rootpath);
+
+ /*
+ * Mount can fail because the higher-level
+ * zone may have already done a mount down.
+ */
+ (void) mount_one(zlogp, &lower_fstab, "");
+ }
+ }
+ }
+ zonecfg_free_fs_option_list(lower_fstab.zone_fs_options);
+ priv_freeset(zid_privs);
+ free(zids);
+
+ /*
+ * Now share any exported directories from this zone.
+ * Each zone can have its own dfstab.
+ */
+
+ argv[0] = "zoneshare";
+ argv[1] = "-z";
+ argv[2] = zone_name;
+ argv[3] = NULL;
+
+ (void) forkexec(zlogp, "/usr/lib/zones/zoneshare", argv);
+ /* Don't check for errors since they don't affect the zone */
+
+ return (0);
+}
+
+/*
+ * Unmount lofs mounts from higher level zones
+ * Unshare nfs exported directories
+ */
+static void
+tsol_unmounts(zlog_t *zlogp, char *zone_name)
+{
+ zoneid_t *zids = NULL;
+ uint_t nzents_saved;
+ uint_t nzents;
+ int i;
+ char *argv[4];
+ char path[MAXPATHLEN];
+
+ if (!is_system_labeled())
+ return;
+
+ /*
+ * Get the list of zones from the kernel
+ */
+ if (zone_list(NULL, &nzents) != 0) {
+ return;
+ }
+
+ if (zid_label == NULL) {
+ zid_label = m_label_alloc(MAC_LABEL);
+ if (zid_label == NULL)
+ return;
+ }
+
+again:
+ if (nzents == 0)
+ return;
+
+ zids = malloc(nzents * sizeof (zoneid_t));
+ if (zids == NULL) {
+ zerror(zlogp, B_TRUE, "unable to allocate memory");
+ return;
+ }
+ 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 zid_name[ZONENAME_MAX];
+ zone_state_t zid_state;
+ char zid_rpath[MAXPATHLEN];
+
+ if (zids[i] == GLOBAL_ZONEID)
+ continue;
+
+ if (getzonenamebyid(zids[i], zid_name, ZONENAME_MAX) == -1)
+ continue;
+
+ /*
+ * Skip the zone we are halting
+ */
+ if (strcmp(zid_name, zone_name) == 0)
+ continue;
+
+ if ((zone_getattr(zids[i], ZONE_ATTR_STATUS, &zid_state,
+ sizeof (zid_state)) < 0) ||
+ (zid_state < ZONE_IS_READY))
+ /* Skip over zones without mounted filesystems */
+ continue;
+
+ if (zone_getattr(zids[i], ZONE_ATTR_SLBL, zid_label,
+ sizeof (m_label_t)) < 0)
+ /* Skip over zones with unspecified label */
+ continue;
+
+ if (zone_getattr(zids[i], ZONE_ATTR_ROOT, zid_rpath,
+ sizeof (zid_rpath)) == -1)
+ /* Skip over zones with bad path */
+ continue;
+
+ if (zlabel != NULL && bldominates(zid_label, zlabel)) {
+ /*
+ * This zone dominates our zone.
+ * Unmount the lofs mount of our zone's /export/home
+ */
+
+ if (snprintf(path, MAXPATHLEN,
+ "%s/zone/%s/export/home", zid_rpath,
+ zone_name) > MAXPATHLEN)
+ continue;
+
+ /* Skip over mount failures */
+ (void) umount(path);
+ }
+ }
+ free(zids);
+
+ /*
+ * Unmount global zone autofs trigger for this zone
+ */
+ (void) snprintf(path, MAXPATHLEN, "/zone/%s/home", zone_name);
+ /* Skip over mount failures */
+ (void) umount(path);
+
+ /*
+ * Next unshare any exported directories from this zone.
+ */
+
+ argv[0] = "zoneunshare";
+ argv[1] = "-z";
+ argv[2] = zone_name;
+ argv[3] = NULL;
+
+ (void) forkexec(zlogp, "/usr/lib/zones/zoneunshare", argv);
+ /* Don't check for errors since they don't affect the zone */
+
+ /*
+ * Finally, deallocate any devices in the zone.
+ */
+
+ argv[0] = "deallocate";
+ argv[1] = "-Isz";
+ argv[2] = zone_name;
+ argv[3] = NULL;
+
+ (void) forkexec(zlogp, "/usr/sbin/deallocate", argv);
+ /* Don't check for errors since they don't affect the zone */
+}
+
+/*
+ * Fetch the Trusted Extensions label and multi-level ports (MLPs) for
+ * this zone.
+ */
+static tsol_zcent_t *
+get_zone_label(zlog_t *zlogp, priv_set_t *privs)
+{
+ FILE *fp;
+ tsol_zcent_t *zcent = NULL;
+ char line[MAXTNZLEN];
+
+ if ((fp = fopen(TNZONECFG_PATH, "r")) == NULL) {
+ zerror(zlogp, B_TRUE, "%s", TNZONECFG_PATH);
+ return (NULL);
+ }
+
+ while (fgets(line, sizeof (line), fp) != NULL) {
+ /*
+ * Check for malformed database
+ */
+ if (strlen(line) == MAXTNZLEN - 1)
+ break;
+ if ((zcent = tsol_sgetzcent(line, NULL, NULL)) == NULL)
+ continue;
+ if (strcmp(zcent->zc_name, zone_name) == 0)
+ break;
+ tsol_freezcent(zcent);
+ zcent = NULL;
+ }
+ (void) fclose(fp);
+
+ if (zcent == NULL) {
+ zerror(zlogp, B_FALSE, "zone requires a label assignment. "
+ "See tnzonecfg(4)");
+ } else {
+ if (zlabel == NULL)
+ zlabel = m_label_alloc(MAC_LABEL);
+ /*
+ * Save this zone's privileges for later read-down processing
+ */
+ if ((zprivs = priv_allocset()) == NULL) {
+ zerror(zlogp, B_TRUE, "%s failed", "priv_allocset");
+ return (NULL);
+ } else {
+ priv_copyset(privs, zprivs);
+ }
+ }
+ return (zcent);
+}
+
+/*
+ * Add the Trusted Extensions multi-level ports for this zone.
+ */
+static void
+set_mlps(zlog_t *zlogp, zoneid_t zoneid, tsol_zcent_t *zcent)
+{
+ tsol_mlp_t *mlp;
+ tsol_mlpent_t tsme;
+
+ if (!is_system_labeled())
+ return;
+
+ tsme.tsme_zoneid = zoneid;
+ tsme.tsme_flags = 0;
+ for (mlp = zcent->zc_private_mlp; !TSOL_MLP_END(mlp); mlp++) {
+ tsme.tsme_mlp = *mlp;
+ if (tnmlp(TNDB_LOAD, &tsme) != 0) {
+ zerror(zlogp, B_TRUE, "cannot set zone-specific MLP "
+ "on %d-%d/%d", mlp->mlp_port,
+ mlp->mlp_port_upper, mlp->mlp_ipp);
+ }
+ }
+
+ tsme.tsme_flags = TSOL_MEF_SHARED;
+ for (mlp = zcent->zc_shared_mlp; !TSOL_MLP_END(mlp); mlp++) {
+ tsme.tsme_mlp = *mlp;
+ if (tnmlp(TNDB_LOAD, &tsme) != 0) {
+ zerror(zlogp, B_TRUE, "cannot set shared MLP "
+ "on %d-%d/%d", mlp->mlp_port,
+ mlp->mlp_port_upper, mlp->mlp_ipp);
+ }
+ }
+}
+
+static void
+remove_mlps(zlog_t *zlogp, zoneid_t zoneid)
+{
+ tsol_mlpent_t tsme;
+
+ if (!is_system_labeled())
+ return;
+
+ (void) memset(&tsme, 0, sizeof (tsme));
+ tsme.tsme_zoneid = zoneid;
+ if (tnmlp(TNDB_FLUSH, &tsme) != 0)
+ zerror(zlogp, B_TRUE, "cannot flush MLPs");
+}
+
int
prtmount(const char *fs, void *x) {
zerror((zlog_t *)x, B_FALSE, " %s", fs);
@@ -2816,6 +3373,9 @@
int xerr;
char *kzone;
FILE *fp = NULL;
+ tsol_zcent_t *zcent = NULL;
+ int match = 0;
+ int doi = 0;
if (zone_get_rootpath(zone_name, rootpath, sizeof (rootpath)) != Z_OK) {
zerror(zlogp, B_TRUE, "unable to determine zone root");
@@ -2842,6 +3402,17 @@
goto error;
}
+ if (is_system_labeled()) {
+ zcent = get_zone_label(zlogp, privs);
+ if (zcent) {
+ match = zcent->zc_match;
+ doi = zcent->zc_doi;
+ *zlabel = zcent->zc_label;
+ } else {
+ goto error;
+ }
+ }
+
kzone = zone_name;
/*
@@ -2911,7 +3482,7 @@
xerr = 0;
if ((zoneid = zone_create(kzone, rootpath, privs, rctlbuf,
- rctlbufsz, zfsbuf, zfsbufsz, &xerr)) == -1) {
+ rctlbufsz, zfsbuf, zfsbufsz, &xerr, match, doi, zlabel)) == -1) {
if (xerr == ZE_AREMOUNTS) {
if (zonecfg_find_mounts(rootpath, NULL, NULL) < 1) {
zerror(zlogp, B_FALSE,
@@ -2949,6 +3520,7 @@
if (!mount_cmd && bind_to_pool(zlogp, zoneid) != 0)
zerror(zlogp, B_FALSE, "WARNING: unable to bind zone to "
"requested pool; using default pool.");
+ set_mlps(zlogp, zoneid, zcent);
rval = zoneid;
zoneid = -1;
@@ -2961,6 +3533,8 @@
if (fp != NULL)
zonecfg_close_scratch(fp);
lofs_discard_mnttab();
+ if (zcent != NULL)
+ tsol_freezcent(zcent);
return (rval);
}
@@ -3109,6 +3683,8 @@
goto error;
}
+ remove_mlps(zlogp, zoneid);
+
if (zone_destroy(zoneid) != 0) {
zerror(zlogp, B_TRUE, "unable to destroy zone");
goto error;
--- a/usr/src/common/ipf/ip_compat.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/common/ipf/ip_compat.h Fri Mar 24 12:29:20 2006 -0800
@@ -1,9 +1,29 @@
+/*
+ * 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 (C) 1999-2001, 2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -1305,6 +1325,7 @@
#undef IPOPT_LSRR
#define IPOPT_LSRR 131
#define IPOPT_E_SEC 133 /* E-SEC */
+#undef IPOPT_CIPSO
#define IPOPT_CIPSO 134 /* CIPSO */
#undef IPOPT_SATID
#define IPOPT_SATID 136
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/tsol/blabel.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,383 @@
+/*
+ * 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"
+
+/*
+ * bl.c - Binary label operations for kernel and user.
+ *
+ * These routines initialize, compare, set and extract portions
+ * of binary labels.
+ */
+
+#include <sys/tsol/label.h>
+#include <sys/tsol/label_macro.h>
+
+
+/*
+ * bltype - Check the type of a label structure.
+ *
+ * Entry label = Address of the label to check.
+ * type = Label type to check:
+ * SUN_SL_ID = Sensitivity Label,
+ * SUN_SL_UN = Undefined Sensitivity Label structure,
+ * SUN_IL_ID = Information Label,
+ * SUN_IL_UN = Undefined Information Label structure,
+ * SUN_CLR_ID = Clearance, or
+ * SUN_CLR_UN = Undefined Clearance structure.
+ *
+ * Exit None.
+ *
+ * Returns True if the label is the type requested,
+ * otherwise false.
+ *
+ * Calls BLTYPE.
+ */
+
+int
+bltype(const void *label, uint8_t type)
+{
+
+ return (BLTYPE(label, type));
+}
+
+
+/*
+ * blequal - Compare two labels for Classification and Compartments set
+ * equality.
+ *
+ * Entry label1, label2 = label levels to compare.
+ *
+ * Exit None.
+ *
+ * Returns True if labels equal,
+ * otherwise false.
+ *
+ * Calls BLEQUAL.
+ */
+
+int
+blequal(const m_label_t *label1, const m_label_t *label2)
+{
+
+ return (BLEQUAL(label1, label2));
+}
+
+
+/*
+ * bldominates - Compare two labels for Classification and Compartments
+ * sets dominance.
+ *
+ * Entry label1, label2 = labels levels to compare.
+ *
+ * Exit None.
+ *
+ * Returns True if label1 dominates label2,
+ * otherwise false.
+ *
+ * Calls BLDOMINATES.
+ */
+
+int
+bldominates(const m_label_t *label1, const m_label_t *label2)
+{
+
+ return (BLDOMINATES(label1, label2));
+}
+
+
+/*
+ * blstrictdom - Compare two labels for Classification and Compartments
+ * sets strict dominance.
+ *
+ * Entry label1, label2 = labels levels to compare.
+ *
+ * Exit None.
+ *
+ * Returns True if label1 dominates and is not equal to label2,
+ * otherwise false.
+ *
+ * Calls BLSTRICTDOM.
+ */
+
+int
+blstrictdom(const m_label_t *label1, const m_label_t *label2)
+{
+
+ return (BLSTRICTDOM(label1, label2));
+}
+
+
+/*
+ * blinrange - Compare a label's classification and compartments set to
+ * be within a lower and upper bound (range).
+ *
+ * Entry label = label level to compare.
+ * range = level range to compare against.
+ *
+ * Exit None.
+ *
+ * Returns True if label is within the range,
+ * otherwise false.
+ *
+ * Calls BLINRANGE.
+ */
+
+int
+blinrange(const m_label_t *label, const m_range_t *range)
+{
+ return (BLDOMINATES((label), ((range)->lower_bound)) &&
+ BLDOMINATES(((range)->upper_bound), (label)));
+}
+
+/*
+ * This is the TS8 version which is used in the kernel
+ */
+
+int
+_blinrange(const m_label_t *label, const brange_t *range)
+{
+ return (BLINRANGE(label, range));
+}
+
+#ifdef _KERNEL
+/*
+ * blinlset - Check if the label belongs to the set
+ *
+ * Entry label = label level to compare.
+ * lset = label set to compare against.
+ *
+ * Exit None.
+ *
+ * Returns True if label is an element of the set,
+ * otherwise false.
+ *
+ */
+
+int
+blinlset(const m_label_t *label, const blset_t lset)
+{
+ int i;
+
+ for (i = 0; i < NSLS_MAX; i++)
+ if (BLEQUAL(label, &lset[i]))
+ return (B_TRUE);
+ return (B_FALSE);
+}
+#endif /* _KERNEL */
+
+
+/*
+ * blmaximum - Least Upper Bound of two levels.
+ *
+ * Entry label1, label2 = levels to bound.
+ *
+ * Exit label1 replaced by the LUB of label1 and label2.
+ *
+ * Returns None.
+ *
+ * Calls BLMAXIMUM.
+ */
+
+void
+blmaximum(m_label_t *label1, const m_label_t *label2)
+{
+
+ BLMAXIMUM(label1, label2);
+}
+
+
+/*
+ * blminimum - Greatest Lower Bound of two levels.
+ *
+ * Entry label1, label2 = levels to bound.
+ *
+ * Exit label1 replaced by the GLB of label1 and label2.
+ *
+ * Returns None.
+ *
+ * Calls BLMINIMUM.
+ */
+
+void
+blminimum(m_label_t *label1, const m_label_t *label2)
+{
+
+ BLMINIMUM(label1, label2);
+}
+
+
+/*
+ * bsllow - Initialize an admin_low Sensitivity Label.
+ *
+ * Entry label = Sensitivity Label structure to be initialized.
+ *
+ * Exit label = Initialized to the admin_low Sensitivity Label.
+ *
+ * Returns None.
+ *
+ * Calls BSLLOW.
+ */
+
+void
+bsllow(bslabel_t *label)
+{
+
+ BSLLOW(label);
+}
+
+
+/*
+ * bslhigh - Initialize an admin_high Sensitivity Label.
+ *
+ * Entry label = Sensitivity Label structure to be initialized.
+ *
+ * Exit label = Initialized to the admin_high Sensitivity Label.
+ *
+ * Returns None.
+ *
+ * Calls BSLHIGH.
+ */
+
+void
+bslhigh(bslabel_t *label)
+{
+
+ BSLHIGH(label);
+}
+
+/*
+ * bclearlow - Initialize an admin_low Clearance.
+ *
+ * Entry clearance = Clearnace structure to be initialized.
+ *
+ * Exit clearance = Initialized to the admin_low Clearance.
+ *
+ * Returns None.
+ *
+ * Calls BCLEARLOW.
+ */
+
+void
+bclearlow(bclear_t *clearance)
+{
+
+ BCLEARLOW(clearance);
+}
+
+
+/*
+ * bclearhigh - Initialize an admin_high Clearance.
+ *
+ * Entry clearance = Clearance structure to be initialized.
+ *
+ * Exit clearance = Initialized to the admin_high Clearance.
+ *
+ * Returns None.
+ *
+ * Calls BCLEARHIGH.
+ */
+
+void
+bclearhigh(bclear_t *clearance)
+{
+
+ BCLEARHIGH(clearance);
+}
+
+/*
+ * bslundef - Initialize an undefined Sensitivity Label.
+ *
+ * Entry label = Sensitivity Label structure to be initialized.
+ *
+ * Exit label = Initialized to undefined Sensitivity Label.
+ *
+ * Returns None.
+ *
+ * Calls BSLUNDEF.
+ */
+
+void
+bslundef(bslabel_t *label)
+{
+
+ BSLUNDEF(label);
+}
+
+
+/*
+ * bclearundef - Initialize an undefined Clearance.
+ *
+ * Entry clearance = Clearance structure to be initialized.
+ *
+ * Exit clearance = Initialized to undefined Clearance.
+ *
+ * Returns None.
+ *
+ * Calls BCLEARUNDEF.
+ */
+
+void
+bclearundef(bclear_t *clearance)
+{
+
+ BCLEARUNDEF(clearance);
+}
+
+
+/*
+ * setbltype - Set the type of a label structure.
+ *
+ * Entry label = Address of the label to set.
+ * type = Label type to set:
+ * SUN_SL_ID = Sensitivity Label,
+ * SUN_SL_UN = Undefined Sensitivity Label structure,
+ * SUN_IL_ID = Information Label,
+ * SUN_IL_UN = Undefined Information Label structure,
+ * SUN_CLR_ID = Clearance, or
+ * SUN_CLR_UN = Undefined Clearance structure.
+ *
+ * Exit label = Type set to specified type.
+ *
+ * Returns None.
+ *
+ * Calls SETBLTYPE.
+ */
+
+void
+setbltype(void *label, uint8_t type)
+{
+
+ SETBLTYPE(label, type);
+}
+
+/*
+ * Returns B_TRUE if the label is invalid (initialized to all zeros).
+ */
+boolean_t
+bisinvalid(const void *label)
+{
+ return (GETBLTYPE(label) == SUN_INVALID_ID);
+}
--- a/usr/src/head/auth_list.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/head/auth_list.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*
* This is an internal header file. Not to be shipped.
@@ -50,6 +49,27 @@
#define WIFI_CONFIG_AUTH "solaris.network.wifi.config"
#define WIFI_WEP_AUTH "solaris.network.wifi.wep"
+/*
+ * Authorizations used by Trusted Solaris.
+ */
+#define BYPASS_FILE_VIEW_AUTH "solaris.label.win.noview"
+#define DEVICE_CONFIG_AUTH "solaris.device.config"
+#define FILE_CHOWN_AUTH "solaris.file.chown"
+#define FILE_DOWNGRADE_SL_AUTH "solaris.label.file.downgrade"
+#define FILE_OWNER_AUTH "solaris.file.owner"
+#define FILE_UPGRADE_SL_AUTH "solaris.label.file.upgrade"
+#define PRINT_ADMIN_AUTH "solaris.print.admin"
+#define PRINT_CANCEL_AUTH "solaris.print.cancel"
+#define PRINT_LIST_AUTH "solaris.print.list"
+#define PRINT_MAC_AUTH "solaris.label.print"
+#define PRINT_NOBANNER_AUTH "solaris.print.nobanner"
+#define PRINT_POSTSCRIPT_AUTH "solaris.print.ps"
+#define PRINT_UNLABELED_AUTH "solaris.print.unlabeled"
+#define SHUTDOWN_AUTH "solaris.system.shutdown"
+#define SYS_ACCRED_SET_AUTH "solaris.label.range"
+#define WIN_DOWNGRADE_SL_AUTH "solaris.label.win.downgrade"
+#define WIN_UPGRADE_SL_AUTH "solaris.label.win.upgrade"
+
#ifdef __cplusplus
}
#endif
--- a/usr/src/head/nss_dbdefs.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/head/nss_dbdefs.h Fri Mar 24 12:29:20 2006 -0800
@@ -22,7 +22,7 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
- * Database-speficic definitions for the getXXXbyYYY routines
+ * Database-specific definitions for the getXXXbyYYY routines
* (e.g getpwuid_r(), ether_ntohost()) that use the name-service switch.
* Database-independent definitions are in <nss_common.h>
*
@@ -80,6 +80,10 @@
#define NSS_DBNAM_PROFATTR "prof_attr"
#define NSS_DBNAM_USERATTR "user_attr"
+#define NSS_DBNAM_TSOL_TP "tnrhtp"
+#define NSS_DBNAM_TSOL_RH "tnrhdb"
+#define NSS_DBNAM_TSOL_ZC "tnzonecfg"
+
/* getspnam() et al use the "passwd" config entry but the "shadow" backend */
#define NSS_DBNAM_SHADOW "shadow"
@@ -97,6 +101,7 @@
#define NSS_FILES_NS "files nis"
#define NSS_NS_FALLBACK "nis [NOTFOUND=return] files"
#define NSS_NS_ONLY "nis"
+#define NSS_TSOL_FALLBACK "files ldap"
#define NSS_DEFCONF_ALIASES NSS_FILES_NS
#define NSS_DEFCONF_AUTOMOUNT NSS_FILES_NS
@@ -127,6 +132,10 @@
#define NSS_DEFCONF_PROFATTR NSS_DEFCONF_ATTRDB
#define NSS_DEFCONF_EXECATTR NSS_DEFCONF_PROFATTR
+#define NSS_DEFCONF_TSOL_TP NSS_TSOL_FALLBACK
+#define NSS_DEFCONF_TSOL_RH NSS_TSOL_FALLBACK
+#define NSS_DEFCONF_TSOL_ZC NSS_TSOL_FALLBACK
+
/*
* Line-lengths that the "files" and "compat" backends will try to support.
* It may be reasonable (even advisable) to use smaller values than these.
@@ -160,6 +169,12 @@
#define NSS_MMAPLEN_EXECATTR NSS_LINELEN_EXECATTR * 8
+#define NSS_LINELEN_TSOL NSS_BUFSIZ
+
+#define NSS_LINELEN_TSOL_TP NSS_LINELEN_TSOL
+#define NSS_LINELEN_TSOL_RH NSS_LINELEN_TSOL
+#define NSS_LINELEN_TSOL_ZC NSS_LINELEN_TSOL
+
/*
* Reasonable defaults for 'buflen' values passed to _r functions. The BSD
* and SunOS 4.x implementations of the getXXXbyYYY() functions used hard-
@@ -193,6 +208,11 @@
#define NSS_BUFLEN_PROFATTR NSS_BUFLEN_ATTRDB
#define NSS_BUFLEN_USERATTR ((NSS_BUFLEN_ATTRDB) * 8)
+#define NSS_BUFLEN_TSOL NSS_LINELEN_TSOL
+
+#define NSS_BUFLEN_TSOL_TP NSS_BUFLEN_TSOL
+#define NSS_BUFLEN_TSOL_RH NSS_BUFLEN_TSOL
+#define NSS_BUFLEN_TSOL_ZC NSS_BUFLEN_TSOL
/*
* Arguments and results, passed between the frontends and backends for
@@ -553,6 +573,10 @@
#define NSS_DBOP_PROFATTR_BYNAME NSS_DBOP_ATTRDB_BYNAME
#define NSS_DBOP_USERATTR_BYNAME NSS_DBOP_ATTRDB_BYNAME
+#define NSS_DBOP_TSOL_TP_BYNAME (NSS_DBOP_next_iter)
+#define NSS_DBOP_TSOL_RH_BYADDR (NSS_DBOP_next_iter)
+#define NSS_DBOP_TSOL_ZC_BYNAME (NSS_DBOP_next_iter)
+
/*
* Used all over in the switch code. The best home for it I can think of.
* Power-of-two alignments only.
--- a/usr/src/head/protocols/routed.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/head/protocols/routed.h Fri Mar 24 12:29:20 2006 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -108,6 +108,18 @@
} au;
};
+struct rip_emetric {
+ uint16_t rip_metric;
+ uint16_t rip_mask;
+ uint32_t rip_token[1];
+};
+
+struct rip_sec_entry {
+ uint32_t rip_dst;
+ uint32_t rip_count;
+ struct rip_emetric rip_emetric[1];
+};
+
struct rip {
uint8_t rip_cmd; /* request/response */
uint8_t rip_vers; /* protocol version # */
@@ -116,10 +128,15 @@
struct netinfo ru_nets[1]; /* variable length... */
char ru_tracefile[1]; /* ditto ... */
struct netauth ru_auth[1];
+ struct {
+ uint32_t rip_generation;
+ struct rip_sec_entry rip_sec_entry[1];
+ } ru_tsol;
} ripun;
#define rip_nets ripun.ru_nets
#define rip_tracefile ripun.ru_tracefile
#define rip_auths ripun.ru_auth
+#define rip_tsol ripun.ru_tsol
};
struct entryinfo {
@@ -149,6 +166,9 @@
#define RIPCMD_POLL 5 /* like request, but anyone answers */
#define RIPCMD_POLLENTRY 6 /* like poll, but for entire entry */
+#define RIPCMD_SEC_RESPONSE 51 /* response includes E-metrics */
+#define RIPCMD_SEC_T_RESPONSE 52 /* tunneling */
+
#define RIPCMD_MAX 7
#define HOPCNT_INFINITY 16 /* per Xerox NS */
--- a/usr/src/head/tar.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/head/tar.h Fri Mar 24 12:29:20 2006 -0800
@@ -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,10 +18,13 @@
*
* CDDL HEADER END
*/
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
-
#ifndef _TAR_H
#define _TAR_H
@@ -68,6 +70,25 @@
#define TOWRITE 00002
#define TOEXEC 00001
+/*
+ * Types used in ancillary files
+ */
+#define ACL_HDR 'A' /* Access Control List */
+#define LBL_TYPE 'L' /* Trusted Extensions file label */
+#define DIR_TYPE 'D' /* Trusted Extensions directory label */
+/*
+ * Attribute types used in Trusted Solaris ancillary files
+ * that are interpreted for backward compatibility
+ */
+#define SLD_TYPE 'S' /* single-level directory component */
+#define PATH_TYPE 'P' /* Path component */
+#define MLD_TYPE 'M' /* multi-level directory component */
+#define FILE_TYPE 'F' /* Have to handle files differently */
+#define APRIV_TYPE 'P' /* allowed privileges data type in file */
+#define FPRIV_TYPE 'p' /* forced privileges data type in file */
+#define COMP_TYPE 'C' /* path components, use for MLD */
+#define ATTR_FLAG_TYPE 'F' /* file attribute flag bytes data type */
+#define LK_COMP_TYPE 'K' /* link data path component */
#ifdef __cplusplus
}
#endif
--- a/usr/src/head/ucred.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/head/ucred.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -31,6 +30,7 @@
#include <sys/types.h>
#include <sys/priv.h>
+#include <sys/tsol/label.h>
#ifdef __cplusplus
extern "C" {
@@ -66,6 +66,8 @@
extern zoneid_t ucred_getzoneid(const ucred_t *);
+extern bslabel_t *ucred_getlabel(const ucred_t *);
+
extern projid_t ucred_getprojid(const ucred_t *);
#else /* Non ANSI */
@@ -93,6 +95,8 @@
extern zoneid_t ucred_getzoneid(/* ucred_t * */);
+extern bslabel_t *ucred_getlabel(/* const ucred_t * */);
+
extern projid_t ucred_getprojid(/* ucred_t * */);
#endif /* __STDC__ */
--- a/usr/src/head/user_attr.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/head/user_attr.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -93,6 +92,21 @@
#define USERATTR_LIMPRIV_KW "limitpriv"
#define USERATTR_DFLTPRIV_KW "defaultpriv"
#define USERATTR_LOCK_AFTER_RETRIES_KW "lock_after_retries"
+#define USERATTR_CLEARANCE "clearance"
+#define USERATTR_LABELVIEW "labelview"
+#define USERATTR_LABELVIEW_EXTERNAL "external"
+#define USERATTR_LABELVIEW_HIDESL "hidesl"
+#define USERATTR_HIDESL USERATTR_LABELVIEW_HIDESL
+#define USERATTR_LABELVIEW_INTERNAL "internal"
+#define USERATTR_LABELVIEW_SHOWSL "showsl"
+#define USERATTR_LABELTRANS "labeltrans"
+#define USERATTR_LOCK_NO "no"
+#define USERATTR_LOCK_YES "yes"
+#define USERATTR_MINLABEL "min_label"
+#define USERATTR_PASSWD "password"
+#define USERATTR_PASSWD_AUTOMATIC "automatic"
+#define USERATTR_PASSWD_MANUAL "manual"
+#define USERATTR_TYPE_ROLE USERATTR_TYPE_NONADMIN_KW
/*
--- a/usr/src/head/zone.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/head/zone.h Fri Mar 24 12:29:20 2006 -0800
@@ -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 <sys/types.h>
#include <sys/zone.h>
#include <sys/priv.h>
+#include <tsol/label.h>
#ifdef __cplusplus
extern "C" {
@@ -57,7 +57,8 @@
/* System call API */
extern zoneid_t zone_create(const char *, const char *,
- const struct priv_set *, const char *, size_t, const char *, size_t, int *);
+ const struct priv_set *, const char *, size_t, const char *, size_t, int *,
+ int, int, const bslabel_t *);
extern int zone_boot(zoneid_t, const char *);
extern int zone_destroy(zoneid_t);
extern ssize_t zone_getattr(zoneid_t, int, void *, size_t);
--- a/usr/src/lib/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -184,6 +184,8 @@
libxnet \
libzonecfg \
libzoneinfo \
+ libtsnet \
+ libtsol \
gss_mechs/mech_spnego \
gss_mechs/mech_dummy \
gss_mechs/mech_dh \
@@ -268,6 +270,7 @@
libsldap \
libslp \
libsmedia \
+ libtsol \
libuutil \
libwanboot \
libwanbootutil \
@@ -327,6 +330,7 @@
libmail \
libmtmalloc \
libnvpair \
+ libnsl \
libpam \
libpctx \
libpicl \
@@ -349,6 +353,8 @@
libtnf \
libtnfctl \
libtnfprobe \
+ libtsnet \
+ libtsol \
libvolmgt \
libumem \
libuutil \
@@ -425,6 +431,7 @@
gss_mechs/mech_krb5: libgss libnsl libsocket libresolv pkcs11
libadt_jni: libbsm
$(CLOSED_BUILD)libc: $(CLOSED)/lib/libc_i18n
+libbsm: libtsol
libcmdutils: libavl
libcontract: libnvpair
libdevid: libdevinfo
@@ -450,9 +457,10 @@
libsctp: libsocket
libsocket: libnsl
libldap5: libsasl libsocket libnsl libmd5
-libsldap: libldap5
+libsldap: libldap5 libtsol
libpool: libnvpair libexacct
libproject: libpool libproc libsecdb
+libtsnet: libnsl libtsol libsecdb
libwrap: libnsl libsocket
libwanboot: libnvpair libresolv libnsl libsocket libdevinfo libinetutil \
libdhcputil openssl
--- a/usr/src/lib/auditd_plugins/syslog/systoken.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/auditd_plugins/syslog/systoken.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -46,6 +45,7 @@
#include <string.h>
#include <sys/types.h>
#include <bsm/libbsm.h>
+#include <sys/tsol/label.h>
#include "toktable.h" /* ../praudit */
#include "sysplugin.h"
#include "systoken.h"
@@ -1381,46 +1381,6 @@
return (0);
}
-/*
- * Format of clearance token:
- * clearance adr_char*(sizeof (bclear_t))
- *
- * ifdef TSOL because of bclear_t
- */
-#ifndef TSOL
-/* ARGSUSED */
-#endif /* !TSOL */
-int
-clearance_token(parse_context_t *ctx)
-{
-#ifdef TSOL
-
- ctx->adr.adr_now += sizeof (bclear_t);
-
- return (0);
-#else /* !TSOL */
- return (-1);
-#endif /* TSOL */
-}
-/*
- * Format of ilabel token:
- * ilabel adr_char*(sizeof (bilabel_t))
- */
-#ifndef TSOL
-/* ARGSUSED */
-#endif /* !TSOL */
-int
-ilabel_token(parse_context_t *ctx)
-{
-#ifdef TSOL
-
- ctx->adr.adr_now += sizeof (bilabel_t);
-
- return (0);
-#else /* !TSOL */
- return (-1);
-#endif /* TSOL */
-}
/*
* -----------------------------------------------------------------------
@@ -1445,22 +1405,23 @@
/*
* Format of slabel token:
- * slabel adr_char*(sizeof (bslabel_t))
+ * label ID 1 byte
+ * compartment length 1 byte
+ * classification 2 bytes
+ * compartment words <compartment length> * 4 bytes
*/
-#ifndef TSOL
-/* ARGSUSED */
-#endif /* !TSOL */
int
slabel_token(parse_context_t *ctx)
{
-#ifdef TSOL
+ char c;
- ctx->adr.adr_now += sizeof (bslabel_t);
+ ctx->adr.adr_now += sizeof (char); /* label ID */
+ adrm_char(&(ctx->adr), &c, 1);
+
+ ctx->adr.adr_now += sizeof (ushort_t); /* classification */
+ ctx->adr.adr_now += 4 * c; /* compartments */
return (0);
-#else /* !TSOL */
- return (-1);
-#endif /* TSOL */
}
/*
--- a/usr/src/lib/auditd_plugins/syslog/systoken.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/auditd_plugins/syslog/systoken.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -97,9 +96,7 @@
extern void attribute_token(adr_t *, parse_context_t *);
extern void s5_IPC_perm_token(adr_t *, parse_context_t *);
extern void group_token();
-extern void ilabel_token(adr_t *, parse_context_t *);
extern void slabel_token(adr_t *, parse_context_t *);
-extern void clearance_token(adr_t *, parse_context_t *);
extern void privilege_token(adr_t *, parse_context_t *);
extern void useofpriv_token(adr_t *, parse_context_t *);
extern void zonename_token(adr_t *, parse_context_t *);
--- a/usr/src/lib/common/inc/c_synonyms.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/common/inc/c_synonyms.h Fri Mar 24 12:29:20 2006 -0800
@@ -414,6 +414,7 @@
#define isastream _isastream
#define isatty _isatty
#define issetugid _issetugid
+#define is_system_labeled _is_system_labeled
#define jrand48 _jrand48
#define kaio _kaio
#define kill _kill
--- a/usr/src/lib/libbsm/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libbsm/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -18,6 +18,7 @@
#
# CDDL HEADER END
#
+
#
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
@@ -27,7 +28,6 @@
# lib/libbsm/Makefile
#
-include ../../Makefile.master
include ../Makefile.lib
SUBDIRS= spec .WAIT $(MACH) $(BUILD64) $(MACH64)
@@ -46,54 +46,13 @@
all clean clobber delete install lint package: $(SUBDIRS)
-OBJECTS= adr.o \
- adrf.o \
- adrm.o \
- adt.o \
- adt_token.o \
- adt_xlate.o \
- au_open.o \
- au_preselect.o \
- au_to.o \
- au_usermask.o \
- audit_allocate.o \
- audit_class.o \
- audit_cron.o \
- audit_crontab.o \
- audit_at.o \
- audit_event.o \
- audit_ftpd.o \
- audit_halt.o \
- audit_inetd.o \
- audit_kadmind.o \
- audit_krb5kdc.o \
- audit_mountd.o \
- audit_newgrp.o \
- audit_plugin.o \
- audit_reboot.o \
- audit_rexd.o \
- audit_rexecd.o \
- audit_rshd.o \
- audit_settid.o \
- audit_shutdown.o \
- audit_uadmin.o \
- audit_user.o \
- bsm.o \
- generic.o \
- getacinfo.o \
- getacval.o \
- getauditflags.o \
- getdaent.o \
- getdment.o \
- getfaudflgs.o
-
COMMONDIR = common
#
# Macros for libbsm header files. These define user-level only interfaces.
#
GENHDRS = audit_uevents.h
-HDRS = libbsm.h devices.h adt.h adt_event.h audit_private.h
+HDRS = libbsm.h devices.h devalloc.h adt.h adt_event.h audit_private.h
COMMONHDRS = $(HDRS:%=$(COMMONDIR)/%)
ROOTHDRDIR = $(ROOT)/usr/include/bsm
ROOTCHDRS = $(HDRS:%=$(ROOTHDRDIR)/%)
@@ -154,10 +113,8 @@
#
# message catalogue file
#
-TEXT_DOMAIN= SUNW_OST_OSLIB
-POFILE= libbsm.po
-CATALOG=libbsm.po
-POFILES= $(OBJECTS:%.o=%.po)
+MSGFILES = `$(GREP) -l gettext $(COMMONDIR)/*.c`
+POFILE = libbsm.po
#
# Definitions for XML (DTD AND XSL)
@@ -241,24 +198,9 @@
$(ROOTETCSECURITY)/%: %.txt
$(INS.rename)
-%.po: $(COMMONDIR)/%.c
- $(COMPILE.cpp) $< > $<.i
- $(BUILD.po)
-
-_msg: $(MSGDOMAIN) $(POFILE)
- $(RM) $(MSGDOMAIN)/$(CATALOG)
- $(CP) $(POFILE) $(MSGDOMAIN)
+$(POFILE): pofile_MSGFILES
-catalog: _msg
-
-po_clean:
- $(RM) $(POFILES) $(POFILE)
-
-clobber: po_clean
-
-$(POFILE): .WAIT $(POFILES)
- $(RM) $@
- $(CAT) $(POFILES) > $@
+_msg: $(MSGDOMAINPOFILE)
# has strings but doesn't use gettext
adt_xlate.po: $(COMMONDIR)/adt_xlate.c
@@ -267,11 +209,10 @@
$(SED) "/^domain/d" < messages.po > adt_xlate.po
$(RM) messages.po
-$(MSGDOMAIN):
- $(INS.dir)
-
-
spec $(MACH) $(MACH64) : FRC
@cd $@; pwd; $(MAKE) $(TARGET)
FRC:
+
+include ../Makefile.targ
+include ../../Makefile.msg.targ
--- a/usr/src/lib/libbsm/Makefile.com Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libbsm/Makefile.com Fri Mar 24 12:29:20 2006 -0800
@@ -24,7 +24,7 @@
#
# ident "%Z%%M% %I% %E% SMI"
#
-# lib/libbsm/Makefile
+# lib/libbsm/Makefile.com
#
LIBRARY = libbsm.a
@@ -67,7 +67,10 @@
getacval.o \
getauditflags.o \
getdaent.o \
+ getdevicerange.o \
getdment.o \
+ getdadefs.o \
+ devalloc.o \
getfaudflgs.o
#
@@ -94,7 +97,10 @@
CFLAGS += $(CCVERBOSE)
DYNFLAGS += -M$(MAPFILE)
-LDLIBS += -lsocket -lnsl -lmd5 -lc -lsecdb
+
+LAZYLIBS = $(ZLAZYLOAD) -ltsol $(ZNOLAZYLOAD)
+LDLIBS += -lsocket -lnsl -lmd5 -lc -lsecdb $(LAZYLIBS)
+lint := LAZYLIBS = -ltsol
COMDIR= ../common
--- a/usr/src/lib/libbsm/audit_class.txt Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libbsm/audit_class.txt Fri Mar 24 12:29:20 2006 -0800
@@ -1,13 +1,12 @@
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# 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.
@@ -62,6 +61,29 @@
0x00100000:ps:process start/stop
0x00200000:pm:process modify
0x00300000:pc:process (meta-class)
+#
+# The following four masks define X server related audit classes which
+# are applicable to Trusted Extensions. X server audit events are mapped
+# to these classes per the following criteria:
+#
+# xp : Protocols audited for use of privilege (successful or otherwise).
+# E.g., ChangeWindowAttributes is audited when issued by a client to
+# change attributes of another client's window. This class also includes
+# any administrative protocols (e.g. SetAccessControl).
+# xc : Server objects creation/destruction; e.g., CreateWindow.
+# xs : Protocols that do not return X error messages to clients on failure for
+# lack for security attributes. E.g., GetImage does not return BadWindow
+# error if it cannot read from a window for lack of privilege. It just
+# does not read from that window.
+# These events should be selected for audit on success only. Selecting
+# them for failure will cause a lot of noise in the audit trail.
+# xx : All above X classes.
+#
+0x00400000:xp:X - privileged/administrative operations
+0x00800000:xc:X - object create/destroy
+0x01000000:xs:X - operations that always silently fail, if bad
+0x01c00000:xx:X - all X events (meta-class)
+#
0x20000000:io:ioctl
0x40000000:ex:exec
0x80000000:ot:other
--- a/usr/src/lib/libbsm/audit_event.txt Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libbsm/audit_event.txt Fri Mar 24 12:29:20 2006 -0800
@@ -1,13 +1,13 @@
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
+#
# 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.
@@ -48,10 +48,25 @@
# 2048 - 32767 Reserved for the Solaris TCB programs.
# 32768 - 65535 Available for third party TCB applications.
#
-# 6144 - 32767 SunOS 5.X user level audit events
+#
+# Allocation of reserved kernel events:
+# (NOTE: the kernel event table, and possibly MAX_KEVENTS, must be updated
+# in audit_kevents.h when changes are made to kernel events.)
+# 1 - 511 allocated for Solaris
+# 512 - 1023 allocated for Trusted Solaris/Trusted Extensions
+# 1024 - 2047 (reserved but not allocated)
+#
+# Allocation of user level audit events:
+# 2048 - 5999 (reserved but not allocated)
+# 6000 - 7999 allocated for Solaris
+# 8000 - 8999 (reserved but not allocated)
+# 9000 - 9999 allocated for Trusted Solaris/Trusted Extensions
+# 10000 - 32767 (reserved but not allocated)
+# 32768 - 65535 (Available for third party TCB applications)
#
#
# kernel audit events
+# 1 - 511 allocated for Solaris
#
0:AUE_NULL:indir system call:no
1:AUE_EXIT:exit(2):ps
@@ -173,8 +188,6 @@
113:AUE_SYSTEMBOOT:system booted:na
114:AUE_ASYNC_DAEMON_EXIT:async_daemon(2) exited:no
115:AUE_NFSSVC_EXIT:nfssvc(2) exited:no
-128:AUE_WRITEL:writel(2):no
-129:AUE_WRITEVL:writevl(2):no
130:AUE_GETAUID:getauid(2):aa
131:AUE_SETAUID:setauid(2):aa
132:AUE_GETAUDIT:getaudit(2):aa
@@ -328,7 +341,12 @@
292:AUE_CRYPTOADM:kernel cryptographic framework:as
293:AUE_CONFIGSSL:configure kernel SSL:as
#
+# Trusted Solaris/Trusted Extensions kernel audit events
+# 512 - 1023 allocated for Trusted Solaris/Trusted Extensions
+#
+#
# user level audit events
+# 6000 - 7999 allocated for Solaris
#
# 2048 - 6143 Reserved
#
@@ -409,3 +427,113 @@
6225:AUE_inetd_failrate:inetd failrate:na
6226:AUE_inetd_ratelimit:inetd ratelimit:na
6227:AUE_zlogin:login - zlogin:lo
+#
+# Trusted Solaris/Trusted Extensions user level audit events
+# 9000 - 9999 allocated for Trusted Solaris/Trusted Extensions
+#
+9035:AUE_sl_change:Workspace label change:ap
+9037:AUE_file_copy:file copy:fm
+9038:AUE_file_move:file move:fm
+9039:AUE_sel_mgr_xfer:selection manager transfer:fm
+9101:AUE_ClientConnect:client connection to x server:lo
+9102:AUE_ClientDisconnect:client disconn. from x server:lo
+9120:AUE_ChangeProperty:XChangeProperty(3X11):xc
+9121:AUE_DeleteProperty:XDeleteProperty(3X11):xc
+9137:AUE_GrabServer:XGrabServer(3X11):ot
+9138:AUE_UngrabServer:XUngrabServer(3X11):ot
+9146:AUE_SetFontPath:XSetFontPath(3X11):ot
+9173:AUE_InstallColormap:XInstallColormap(3X11):ot
+9174:AUE_UninstallColormap:XUninstallColormap(3X11):xp
+9193:AUE_SetScreenSaver:XSetScreenSaver(3X11):xp
+9194:AUE_ChangeHosts:XChangeHosts(3X11):ot
+9195:AUE_SetAccessControl:XSetAccessControl(3X11):xp
+9196:AUE_SetCloseDownMode:XSetCloseDownMode(3X11):xs
+9197:AUE_KillClient:XKillClient(3X11):xc
+9202:AUE_XExtensions:X server extensions:xp
+9103:AUE_CreateWindow:XCreateWindow(3X11):xc
+9104:AUE_ChangeWindowAttributes:XChangeWindowAttributes(3X11):xp
+9105:AUE_GetWindowAttributes:XGetWindowAttributes(3X11):xp
+9106:AUE_DestroyWindow:XDestroyWindow(3X11):xc
+9107:AUE_DestroySubwindows:XDestroySubwindows(3X11):xc
+9108:AUE_ChangeSaveSet:XChangeSaveSet(3X11):xp
+9109:AUE_ReparentWindow:XReparentWindow(3X11):xp
+9110:AUE_MapWindow:XMapWindow(3X11):xp
+9111:AUE_MapSubwindows:XMapSubwindows(3X11):xp
+9112:AUE_UnmapWindow:XUnmapWindow(3X11):xp
+9113:AUE_UnmapSubwindows:XUnmapSubwindows(3X11):xp
+9114:AUE_ConfigureWindow:XConfigureWindow(3X11):xp
+9115:AUE_CirculateWindow:XCirculateWindow(3X11):xp
+9116:AUE_GetGeometry:XGetGeometry(3X11):xp
+9117:AUE_QueryTree:XQueryTree(3X11):xp
+9118:AUE_InternAtom:XInternAtom(3X11):xs
+9119:AUE_GetAtomName:XGetAtomName(3X11):xs
+9122:AUE_GetProperty:XGetProperty(3X11):xp
+9123:AUE_ListProperties:XListProperties(3X11):xp
+9124:AUE_SetSelectionOwner:XSetSelectionOwner(3X11):xp
+9125:AUE_GetSelectionOwner:XGetSelectionOwner(3X11):xs
+9126:AUE_ConvertSelection:XConvertSelection(3X11):xs
+9127:AUE_SendEvent:XSendEvent(3X11):xs
+9128:AUE_GrabPointer:XGrabPointer(3X11):xs
+9129:AUE_UngrabPointer:XUngrabPointer(3X11):xs
+9130:AUE_GrabButton:XGrabButton(3X11):xp
+9131:AUE_UngrabButton:XUngrabButton(3X11):xs
+9132:AUE_ChangeActivePointerGrab:XChangeActivePointerGrab(3X11):xs
+9133:AUE_GrabKeyboard:XGrabKeyboard(3X11):xp
+9134:AUE_UngrabKeyboard:XUngrabKeyboard(3X11):xs
+9135:AUE_GrabKey:XGrabKey(3X11):xp
+9136:AUE_UngrabKey:XUngrabKey(3X11):xp
+9139:AUE_QueryPointer:XQueryPointer(3X11):xp
+9140:AUE_GetMotionEvents:XGetMotionEvents(3X11):xp
+9141:AUE_TranslateCoords:XTranslateCoords(3X11):xp
+9142:AUE_WarpPointer:XWarpPointer(3X11):xs
+9143:AUE_SetInputFocus:XSetInputFocus(3X11):xs
+9144:AUE_GetInputFocus:XGetInputFocus(3X11):xs
+9145:AUE_QueryKeymap:XQueryKeymap(3X11):xp
+9147:AUE_FreePixmap:XFreePixmap(3X11):xc
+9148:AUE_ChangeGC:XChangeGC(3X11):xp
+9149:AUE_CopyGC:XCopyGC(3X11):xp
+9150:AUE_SetDashes:XSetDashes(3X11):xp
+9151:AUE_SetClipRectangles:XSetClipRectangles(3X11):xp
+9152:AUE_FreeGC:XFreeGC(3X11):xc
+9153:AUE_ClearArea:XClearArea(3X11):xp
+9154:AUE_CopyArea:XCopyArea(3X11):xs
+9155:AUE_CopyPlane:XCopyPlane(3X11):xs
+9156:AUE_PolyPoint:XPolyPoint(3X11):xp
+9157:AUE_PolyLine:XPolyLine(3X11):xp
+9158:AUE_PolySegment:XPolySegment(3X11):xp
+9159:AUE_PolyRectangle:XPolyRectangle(3X11):xs
+9160:AUE_PolyArc:XPolyArc(3X11):xp
+9161:AUE_FillPolygon:XFillPolygon(3X11):xp
+9162:AUE_PolyFillRectangle:XPolyFillRectangle(3X11):xp
+9163:AUE_PolyFillArc:XPolyFillArc(3X11):xp
+9164:AUE_PutImage:XPutImage(3X11):xp
+9165:AUE_GetImage:XGetImage(3X11):xs
+9166:AUE_PolyText8:XPolyText8(3X11):xp
+9167:AUE_PolyText16:XPolyText16(3X11):xp
+9168:AUE_ImageText8:XImageText8(3X11):xp
+9169:AUE_ImageText16:XImageText16(3X11):xp
+9170:AUE_CreateColormap:XCreateColormap(3X11):xc
+9171:AUE_FreeColormap:XFreeColormap(3X11):xc
+9172:AUE_CopyColormapAndFree:XCopyColormapAndFree(3X11):xp
+9175:AUE_ListInstalledColormaps:XListInstalledColormaps(3X11):xs
+9176:AUE_AllocColor:XAllocColor(3X11):xc
+9177:AUE_AllocNamedColor:XAllocNamedColor(3X11):xc
+9178:AUE_AllocColorCells:XAllocColorCells(3X11):xc
+9179:AUE_AllocColorPlanes:XAllocColorPlanes(3X11):xc
+9180:AUE_FreeColors:XFreeColors(3X11):xc
+9181:AUE_StoreColors:XStoreColors(3X11):xp
+9182:AUE_StoreNamedColor:XStoreNamedColor(3X11):xp
+9183:AUE_QueryColors:XQueryColors(3X11):xp
+9184:AUE_LookupColor:XLookupColor(3X11):xp
+9185:AUE_CreateCursor:XCreateCursor(3X11):xc
+9186:AUE_CreateGlyphCursor:XCreateGlyphCursor(3X11):xc
+9187:AUE_FreeCursor:XFreeCursor(3X11):xc
+9188:AUE_RecolorCursor:XRecolorCursor(3X11):xp
+9189:AUE_ChangeKeyboardMapping:XChangeKeyboardMapping(3X11):xs
+9190:AUE_ChangeKeyboardControl:XChangeKeyboardControl(3X11):xs
+9191:AUE_Bell:XBell(3X11):xs
+9192:AUE_ChangePointerControl:XChangePointerControl(3X11):xs
+9198:AUE_RotateProperties:XRotateProperties(3X11):xp
+9199:AUE_ForceScreenSaver:XForceScreenSaver(3X11):xp
+9200:AUE_SetPointerMapping:XSetPointerMapping(3X11):xs
+9201:AUE_SetModifierMapping:XSetModifierMapping(3X11):xs
--- a/usr/src/lib/libbsm/common/adt_token.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libbsm/common/adt_token.c Fri Mar 24 12:29:20 2006 -0800
@@ -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 @@
/*
* adt_token.c
*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* This file does not provide any user callable functions. See adt.c
@@ -41,6 +40,7 @@
#include <sys/priv_names.h>
#include <sys/types.h>
#include <sys/vnode.h>
+#include <tsol/label.h>
#include <time.h>
#include <unistd.h>
@@ -530,6 +530,9 @@
au_to_newgroups(0, grouplist));
}
}
+
+ if (is_system_labeled())
+ (void) au_write(event->ae_event_handle, au_to_mylabel());
}
/*
--- a/usr/src/lib/libbsm/common/au_to.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libbsm/common/au_to.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -42,6 +41,9 @@
#include <netinet/in.h>
#include <netinet/in_pcb.h>
#include <string.h>
+#include <zone.h>
+#include <sys/tsol/label.h>
+#include <sys/tsol/label_macro.h>
#define NGROUPS 16 /* XXX - temporary */
@@ -1242,6 +1244,50 @@
}
/*
+ * au_to_label
+ * return s:
+ * pointer to token chain containing a sensitivity label token.
+ */
+token_t *
+au_to_label(bslabel_t *label)
+{
+ token_t *token; /* local token */
+ adr_t adr; /* adr memory stream header */
+ char data_header = AUT_LABEL; /* header for this token */
+ short bs = sizeof (bslabel_t);
+
+ token = get_token(sizeof (char) + bs);
+ if (token == NULL)
+ return (NULL);
+ adr_start(&adr, token->tt_data);
+ adr_char(&adr, &data_header, 1);
+ adr_char(&adr, (char *)label, bs);
+
+ return (token);
+}
+
+/*
+ * au_to_mylabel
+ * return s:
+ * pointer to a slabel token.
+ */
+token_t *
+au_to_mylabel(void)
+{
+ bslabel_t slabel;
+ zoneid_t zid = getzoneid();
+
+ if (zid == GLOBAL_ZONEID) {
+ bsllow(&slabel);
+ } else {
+ if (zone_getattr(zid, ZONE_ATTR_SLBL, &slabel,
+ sizeof (bslabel_t)) < 0)
+ return (NULL);
+ }
+ return (au_to_label(&slabel));
+}
+
+/*
* au_to_zonename
* return s:
* pointer to a zonename token.
--- a/usr/src/lib/libbsm/common/audit_allocate.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libbsm/common/audit_allocate.c Fri Mar 24 12:29:20 2006 -0800
@@ -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 2003 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"
#include <sys/types.h>
+#include <tsol/label.h>
#include <bsm/audit.h>
#include <bsm/libbsm.h>
#include <bsm/audit_private.h>
@@ -136,6 +136,8 @@
}
(void) au_write(ad, au_to_newgroups(ng, grplst));
}
+ if (is_system_labeled())
+ (void) au_write(ad, au_to_mylabel());
if (status)
(void) au_write(ad, au_to_exit(status, -1));
--- a/usr/src/lib/libbsm/common/audit_ftpd.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libbsm/common/audit_ftpd.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -37,6 +36,7 @@
#include <sys/socket.h>
#include <sys/sockio.h>
#include <netinet/in.h>
+#include <tsol/label.h>
#include <bsm/audit.h>
#include <bsm/audit_record.h>
@@ -187,6 +187,9 @@
(void) au_write(rd, au_to_subject_ex(uid, uid, gid,
ruid, rgid, pid, pid, &info.ai_termid));
+ if (is_system_labeled())
+ (void) au_write(rd, au_to_mylabel());
+
/* add return token */
errno = 0;
if (err) {
@@ -291,6 +294,9 @@
(void) au_write(rd, au_to_subject_ex(info.ai_auid, euid,
egid, uid, gid, pid, pid, &info.ai_termid));
+ if (is_system_labeled())
+ (void) au_write(rd, au_to_mylabel());
+
/* add return token */
errno = 0;
#ifdef _LP64
--- a/usr/src/lib/libbsm/common/audit_rexd.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libbsm/common/audit_rexd.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -39,6 +38,7 @@
#include <syslog.h>
#include <pwd.h>
#include <netinet/in.h>
+#include <tsol/label.h>
#include <locale.h>
#include "generic.h"
@@ -204,6 +204,8 @@
(void) au_write(rd,
au_to_subject_ex(uid, uid, gid, uid, gid, pid, pid,
&info.ai_termid));
+ if (is_system_labeled())
+ (void) au_write(rd, au_to_mylabel());
/* add reason for failure */
(void) au_write(rd, au_to_text(msg));
@@ -328,6 +330,8 @@
(void) au_write(rd,
au_to_subject_ex(uid, uid, gid, uid, gid, pid, pid,
&info.ai_termid));
+ if (is_system_labeled())
+ (void) au_write(rd, au_to_mylabel());
/* add hostname of machine requesting service */
--- a/usr/src/lib/libbsm/common/audit_rexecd.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libbsm/common/audit_rexecd.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -39,6 +38,7 @@
#include <syslog.h>
#include <pwd.h>
#include <netinet/in.h>
+#include <tsol/label.h>
#include <locale.h>
#include "generic.h"
@@ -197,6 +197,8 @@
/* add subject token */
(void) au_write(rd,
au_to_subject_ex(uid, uid, gid, uid, gid, pid, pid, &tid));
+ if (is_system_labeled())
+ (void) au_write(rd, au_to_mylabel());
/* add reason for failure */
(void) au_write(rd, au_to_text(msg));
@@ -306,6 +308,8 @@
/* add subject token */
(void) au_write(rd,
au_to_subject_ex(uid, uid, gid, uid, gid, pid, pid, &tid));
+ if (is_system_labeled())
+ (void) au_write(rd, au_to_mylabel());
/* add hostname of machine requesting service */
(void) snprintf(buf, sizeof (buf), dgettext(bsm_dom,
--- a/usr/src/lib/libbsm/common/audit_rshd.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libbsm/common/audit_rshd.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -37,6 +36,7 @@
#include <string.h>
#include <syslog.h>
#include <netinet/in.h>
+#include <tsol/label.h>
#include <locale.h>
#include <unistd.h>
#include <generic.h>
@@ -134,6 +134,8 @@
(void) au_write(rd, au_to_subject_ex(uid, uid, gid, uid, gid, pid, pid,
&info.ai_termid));
+ if (is_system_labeled())
+ (void) au_write(rd, au_to_mylabel());
gtxt = dgettext(bsm_dom, "cmd %s");
tlen = strlen(gtxt) + strlen(cmdbuf) + 1;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libbsm/common/devalloc.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,1723 @@
+/*
+ * 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 <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <utime.h>
+#include <synch.h>
+#include <strings.h>
+#include <string.h>
+#include <libintl.h>
+#include <errno.h>
+#include <auth_list.h>
+#include <bsm/devices.h>
+#include <bsm/devalloc.h>
+
+#define DA_DEFS "/etc/security/tsol/devalloc_defaults"
+
+extern int _readbufline(char *, int, char *, int, int *);
+extern char *strtok_r(char *, const char *, char **);
+extern char *_strtok_escape(char *, char *, char **);
+extern int getdaon(void);
+extern int da_matchname(devalloc_t *, char *);
+extern int da_match(devalloc_t *, da_args *);
+extern int dmap_matchname(devmap_t *, char *);
+extern int dm_match(devmap_t *, da_args *);
+
+/*
+ * The following structure is for recording old entries to be retained.
+ * We read the entries from the database into a linked list in memory,
+ * then turn around and write them out again.
+ */
+typedef struct strentry {
+ struct strentry *se_next;
+ char se_str[4096 + 1];
+} strentry_t;
+
+/*
+ * da_check_longindevperm -
+ * reads /etc/logindevperm and checks if specified device is in the file.
+ * returns 1 if specified device found in /etc/logindevperm, else returns 0
+ */
+int
+da_check_logindevperm(char *devname)
+{
+ int ret = 0;
+ int fd = -1;
+ int nlen, plen, slen, lineno, fsize;
+ char line[MAX_CANON];
+ char *field_delims = " \t\n";
+ char *fbuf = NULL;
+ char *ptr, *device;
+ char *lasts = NULL;
+ FILE *fp;
+ struct stat f_stat;
+
+ /*
+ * check if /etc/logindevperm exists and get its size
+ */
+ if ((fd = open(LOGINDEVPERM, O_RDONLY)) == -1)
+ return (0);
+ if (fstat(fd, &f_stat) != 0) {
+ (void) close(fd);
+ return (0);
+ }
+ fsize = f_stat.st_size;
+ if ((fbuf = (char *)malloc(fsize)) == NULL) {
+ (void) close(fd);
+ return (0);
+ }
+ if ((fp = fdopen(fd, "r")) == NULL) {
+ free(fbuf);
+ (void) close(fd);
+ return (0);
+ }
+
+ /*
+ * read and parse /etc/logindevperm
+ */
+ plen = nlen = lineno = 0;
+ while (fgets(line, MAX_CANON, fp) != NULL) {
+ lineno++;
+ if ((ptr = strchr(line, '#')) != NULL)
+ *ptr = '\0'; /* handle comments */
+ if (strtok_r(line, field_delims, &lasts) == NULL)
+ continue; /* ignore blank lines */
+ if (strtok_r(NULL, field_delims, &lasts) == NULL)
+ /* invalid entry */
+ continue;
+ if ((ptr = strtok_r(NULL, field_delims, &lasts)) == NULL)
+ /* empty device list */
+ continue;
+ nlen = strlen(ptr) + 1; /* +1 terminator */
+ nlen += (plen + 1);
+ if (plen == 0)
+ slen = snprintf(fbuf, nlen, "%s", ptr);
+ else
+ slen = snprintf(fbuf + plen, nlen - plen, ":%s", ptr);
+ if (slen >= fsize) {
+ fbuf[0] = '\0';
+ (void) fclose(fp);
+ return (slen);
+ }
+ plen += slen;
+ }
+ (void) fclose(fp);
+
+ /*
+ * check if devname exists in /etc/logindevperm
+ */
+ device = strtok_r(fbuf, ":", &lasts);
+ while (device != NULL) {
+ /*
+ * device and devname may be one of these types -
+ * /dev/xx
+ * /dev/xx*
+ * /dev/dir/xx
+ * /dev/dir/xx*
+ * /dev/dir/"*"
+ */
+ if (strcmp(device, devname) == 0) {
+ /* /dev/xx, /dev/dir/xx */
+ free(fbuf);
+ return (1);
+ }
+ if ((ptr = strrchr(device, KV_WILDCHAR)) != NULL) {
+ /* all wildcard types */
+ *ptr = '\0';
+ if (strncmp(device, devname, strlen(device)) == 0) {
+ free(fbuf);
+ return (1);
+ }
+ }
+ device = strtok_r(NULL, ":", &lasts);
+ }
+
+ return (ret);
+}
+
+/*
+ * _da_read_file -
+ * establishes readers/writer lock on fname; reads in the file if its
+ * contents changed since the last time we read it.
+ * returns size of buffer read, or -1 on failure.
+ */
+int
+_da_read_file(char *fname, char **fbuf, time_t *ftime, rwlock_t *flock,
+ int flag)
+{
+ int fd = -1;
+ int fsize = 0;
+ time_t newtime;
+ FILE *fp = NULL;
+ struct stat f_stat;
+
+ if (flag & DA_FORCE)
+ *ftime = 0;
+
+ /* check the size and the time stamp on the file */
+ if (rw_rdlock(flock) != 0)
+ return (-1);
+ if (stat(fname, &f_stat) != 0) {
+ (void) rw_unlock(flock);
+ return (-1);
+ }
+ fsize = f_stat.st_size;
+ newtime = f_stat.st_mtime;
+ (void) rw_unlock(flock);
+
+ while (newtime > *ftime) {
+ /*
+ * file has been modified since we last read it; or this
+ * is a forced read.
+ * read file into the buffer with rw lock.
+ */
+ if (rw_wrlock(flock) != 0)
+ return (-1);
+ if ((fp = fopen(fname, "r")) == NULL) {
+ (void) rw_unlock(flock);
+ return (-1);
+ }
+ fd = fileno(fp);
+ if (*fbuf != NULL) {
+ free(*fbuf);
+ *fbuf = NULL;
+ }
+ if ((*fbuf = malloc(fsize)) == NULL) {
+ (void) rw_unlock(flock);
+ (void) close(fd);
+ return (-1);
+ }
+ if (read(fd, *fbuf, fsize) < fsize) {
+ free(*fbuf);
+ (void) rw_unlock(flock);
+ (void) close(fd);
+ return (-1);
+ }
+ (void) rw_unlock(flock);
+ /*
+ * verify that the file did not change just after we read it.
+ */
+ if (rw_rdlock(flock) != 0) {
+ free(*fbuf);
+ (void) close(fd);
+ return (-1);
+ }
+ if (stat(fname, &f_stat) != 0) {
+ free(*fbuf);
+ (void) rw_unlock(flock);
+ (void) close(fd);
+ return (-1);
+ }
+ fsize = f_stat.st_size;
+ newtime = f_stat.st_mtime;
+ (void) rw_unlock(flock);
+ (void) close(fd);
+ *ftime = newtime;
+ }
+
+ return (fsize);
+}
+
+/*
+ * _update_zonename -
+ * add/remove current zone's name to the given devalloc_t.
+ */
+void
+_update_zonename(da_args *dargs, devalloc_t *dap)
+{
+ int i, j;
+ int oldsize, newsize;
+ int has_zonename = 0;
+ char *zonename;
+ kva_t *newkva, *oldkva;
+ kv_t *newdata, *olddata;
+ devinfo_t *devinfo;
+
+ devinfo = dargs->devinfo;
+ oldkva = dap->da_devopts;
+ if (oldkva == NULL) {
+ if (dargs->optflag & DA_REMOVE_ZONE)
+ return;
+ if (dargs->optflag & DA_ADD_ZONE) {
+ newkva = _str2kva(devinfo->devopts, KV_ASSIGN,
+ KV_TOKEN_DELIMIT);
+ if (newkva != NULL)
+ dap->da_devopts = newkva;
+ return;
+ }
+ }
+ newsize = oldsize = oldkva->length;
+ if (kva_match(oldkva, DAOPT_ZONE))
+ has_zonename = 1;
+ if (dargs->optflag & DA_ADD_ZONE) {
+ if ((zonename = index(devinfo->devopts, '=')) == NULL)
+ return;
+ zonename++;
+ if (has_zonename) {
+ (void) _insert2kva(oldkva, DAOPT_ZONE, zonename);
+ return;
+ }
+ newsize += 1;
+ } else if (dargs->optflag & DA_REMOVE_ZONE) {
+ if (has_zonename) {
+ newsize -= 1;
+ if (newsize == 0) {
+ /*
+ * If zone name was the only key/value pair,
+ * put 'reserved' in the empty slot.
+ */
+ _kva_free(oldkva);
+ dap->da_devopts = NULL;
+ return;
+ }
+ } else {
+ return;
+ }
+ }
+ newkva = _new_kva(newsize);
+ newkva->length = 0;
+ newdata = newkva->data;
+ olddata = oldkva->data;
+ for (i = 0, j = 0; i < oldsize; i++) {
+ if ((dargs->optflag & DA_REMOVE_ZONE) &&
+ (strcmp(olddata[i].key, DAOPT_ZONE) == 0))
+ continue;
+ newdata[j].key = strdup(olddata[i].key);
+ newdata[j].value = strdup(olddata[i].value);
+ newkva->length++;
+ j++;
+ }
+ if (dargs->optflag & DA_ADD_ZONE) {
+ newdata[j].key = strdup(DAOPT_ZONE);
+ newdata[j].value = strdup(zonename);
+ newkva->length++;
+ }
+ _kva_free(oldkva);
+ dap->da_devopts = newkva;
+}
+
+/*
+ * _dmap2str -
+ * converts a device_map entry into a printable string
+ * returns 0 on success, -1 on error.
+ */
+/*ARGSUSED*/
+static int
+_dmap2str(da_args *dargs, devmap_t *dmp, char *buf, int size, const char *sep)
+{
+ int length;
+
+ length = snprintf(buf, size, "%s%s", dmp->dmap_devname, sep);
+ if (length >= size)
+ return (-1);
+ length += snprintf(buf + length, size - length, "%s%s",
+ dmp->dmap_devtype, sep);
+ if (length >= size)
+ return (-1);
+ length += snprintf(buf + length, size - length, "%s\n",
+ dmp->dmap_devlist);
+ if (length >= size)
+ return (-1);
+ return (0);
+}
+
+/*
+ * _dmap2strentry -
+ * calls dmap2str to break given devmap_t into printable entry.
+ * returns pointer to decoded entry, NULL on error.
+ */
+static strentry_t *
+_dmap2strentry(da_args *dargs, devmap_t *devmapp)
+{
+ strentry_t *sep;
+
+ if ((sep = (strentry_t *)malloc(sizeof (strentry_t))) == NULL)
+ return (NULL);
+ if (_dmap2str(dargs, devmapp, sep->se_str, sizeof (sep->se_str),
+ KV_TOKEN_DELIMIT"\\\n\t") != 0) {
+ free(sep);
+ return (NULL);
+ }
+ return (sep);
+}
+
+/*
+ * fix_optstr -
+ * removes trailing ':' from buf.
+ */
+void
+fix_optstr(char *buf)
+{
+ char *p = NULL;
+
+ if (p = rindex(buf, ':'))
+ *p = ';';
+}
+
+/*
+ * _da2str -
+ * converts a device_allocate entry into a printable string
+ * returns 0 on success, -1 on error.
+ */
+static int
+_da2str(da_args *dargs, devalloc_t *dap, char *buf, int size, const char *sep,
+ const char *osep)
+{
+ int length;
+ int matching_entry = 0;
+ char **dnames;
+
+ if (dargs->optflag & DA_UPDATE &&
+ (dargs->optflag & DA_ADD_ZONE ||
+ dargs->optflag & DA_REMOVE_ZONE) &&
+ dargs->devnames) {
+ for (dnames = dargs->devnames; *dnames != NULL; dnames++) {
+ if (da_matchname(dap, *dnames)) {
+ matching_entry = 1;
+ break;
+ }
+ }
+ }
+ length = snprintf(buf, size, "%s%s", dap->da_devname, sep);
+ if (length >= size)
+ return (-1);
+ length += snprintf(buf + length, size - length, "%s%s",
+ dap->da_devtype, sep);
+ if (length >= size)
+ return (-1);
+ if (matching_entry)
+ _update_zonename(dargs, dap);
+ if ((dap->da_devopts == NULL) || ((dap->da_devopts->length == 1) &&
+ (strcmp(dap->da_devopts->data->key, DA_RESERVED) == 0))) {
+ length += snprintf(buf + length, size - length, "%s%s",
+ DA_RESERVED, sep);
+ } else {
+ if (_kva2str(dap->da_devopts, buf + length, size - length,
+ KV_ASSIGN, (char *)osep) != 0)
+ return (-1);
+ length = strlen(buf);
+ }
+ if (dap->da_devopts)
+ fix_optstr(buf);
+ if (length >= size)
+ return (-1);
+ length += snprintf(buf + length, size - length, "%s%s",
+ DA_RESERVED, sep);
+ if (length >= size)
+ return (-1);
+ length += snprintf(buf + length, size - length, "%s%s",
+ dap->da_devauth ? dap->da_devauth : DA_ANYUSER, sep);
+ if (length >= size)
+ return (-1);
+ length += snprintf(buf + length, size - length, "%s\n",
+ dap->da_devexec ? dap->da_devexec : "");
+ if (length >= size)
+ return (-1);
+
+ return (0);
+}
+
+/*
+ * _da2strentry -
+ * calls da2str to break given devalloc_t into printable entry.
+ * returns pointer to decoded entry, NULL on error.
+ */
+static strentry_t *
+_da2strentry(da_args *dargs, devalloc_t *dap)
+{
+ strentry_t *sep;
+
+ if ((sep = (strentry_t *)malloc(sizeof (strentry_t))) == NULL)
+ return (NULL);
+ if (_da2str(dargs, dap, sep->se_str, sizeof (sep->se_str),
+ KV_DELIMITER "\\\n\t", KV_TOKEN_DELIMIT "\\\n\t") != 0) {
+ free(sep);
+ return (NULL);
+ }
+ return (sep);
+}
+
+/*
+ * _def2str
+ * converts da_defs_t into a printable string.
+ * returns 0 on success, -1 on error.
+ */
+static int
+_def2str(da_defs_t *da_defs, char *buf, int size, const char *sep)
+{
+ int length;
+
+ length = snprintf(buf, size, "%s%s", da_defs->devtype, sep);
+ if (length >= size)
+ return (-1);
+ if (da_defs->devopts) {
+ if (_kva2str(da_defs->devopts, buf + length, size - length,
+ KV_ASSIGN, KV_DELIMITER) != 0)
+ return (-1);
+ length = strlen(buf);
+ }
+ if (length >= size)
+ return (-1);
+
+ return (0);
+}
+
+/*
+ * _def2strentry
+ * calls _def2str to break given da_defs_t into printable entry.
+ * returns pointer decoded entry, NULL on error.
+ */
+static strentry_t *
+_def2strentry(da_defs_t *da_defs)
+{
+ strentry_t *sep;
+
+ if ((sep = (strentry_t *)malloc(sizeof (strentry_t))) == NULL)
+ return (NULL);
+ if (_def2str(da_defs, sep->se_str, sizeof (sep->se_str),
+ KV_TOKEN_DELIMIT) != 0) {
+ free(sep);
+ return (NULL);
+ }
+
+ return (sep);
+}
+
+/*
+ * _build_defattrs
+ * cycles through all defattr entries, stores them in memory. removes
+ * entries with the given search_key (device type).
+ * returns 0 if given entry not found, 1 if given entry removed, 2 on
+ * error.
+ */
+static int
+_build_defattrs(da_args *dargs, strentry_t **head_defent)
+{
+ int rc = 0;
+ da_defs_t *da_defs;
+ strentry_t *tail_str, *tmp_str;
+
+ setdadefent();
+ while ((da_defs = getdadefent()) != NULL) {
+ rc = !(strcmp(da_defs->devtype, dargs->devinfo->devtype));
+ if (rc && dargs->optflag & DA_ADD &&
+ !(dargs->optflag & DA_FORCE)) {
+ /*
+ * During DA_ADD, we keep an existing entry unless
+ * we have DA_FORCE set to override that entry.
+ */
+ dargs->optflag |= DA_NO_OVERRIDE;
+ rc = 0;
+ }
+ if (rc == 0) {
+ tmp_str = _def2strentry(da_defs);
+ if (tmp_str == NULL) {
+ freedadefent(da_defs);
+ enddadefent();
+ return (2);
+ }
+ /* retaining defattr entry: tmp_str->se_str */
+ tmp_str->se_next = NULL;
+ if (*head_defent == NULL) {
+ *head_defent = tail_str = tmp_str;
+ } else {
+ tail_str->se_next = tmp_str;
+ tail_str = tmp_str;
+ }
+ }
+ freedadefent(da_defs);
+ }
+ enddadefent();
+
+ return (rc);
+}
+
+/*
+ * _build_lists -
+ * cycles through all the entries, stores them in memory. removes entries
+ * with the given search_key (device name or type).
+ * returns 0 if given entry not found, 1 if given entry removed, 2 on
+ * error.
+ */
+static int
+_build_lists(da_args *dargs, strentry_t **head_devallocp,
+ strentry_t **head_devmapp)
+{
+ int rc = 0;
+ devalloc_t *devallocp;
+ devmap_t *devmapp;
+ strentry_t *tail_str;
+ strentry_t *tmp_str;
+
+ if (dargs->optflag & DA_MAPS_ONLY)
+ goto dmap_only;
+
+ /* build device_allocate */
+ setdaent();
+ while ((devallocp = getdaent()) != NULL) {
+ rc = da_match(devallocp, dargs);
+ if (rc && dargs->optflag & DA_ADD &&
+ !(dargs->optflag & DA_FORCE)) {
+ /*
+ * During DA_ADD, we keep an existing entry unless
+ * we have DA_FORCE set to override that entry.
+ */
+ dargs->optflag |= DA_NO_OVERRIDE;
+ rc = 0;
+ }
+ if (rc == 0) {
+ tmp_str = _da2strentry(dargs, devallocp);
+ if (tmp_str == NULL) {
+ freedaent(devallocp);
+ enddaent();
+ return (2);
+ }
+ /* retaining devalloc entry: tmp_str->se_str */
+ tmp_str->se_next = NULL;
+ if (*head_devallocp == NULL) {
+ *head_devallocp = tail_str = tmp_str;
+ } else {
+ tail_str->se_next = tmp_str;
+ tail_str = tmp_str;
+ }
+ }
+ freedaent(devallocp);
+ }
+ enddaent();
+
+dmap_only:
+ if (dargs->optflag & DA_ALLOC_ONLY)
+ return (rc);
+
+ /* build device_maps */
+ rc = 0;
+ setdmapent();
+ while ((devmapp = getdmapent()) != NULL) {
+ rc = dm_match(devmapp, dargs);
+ if (rc && dargs->optflag & DA_ADD &&
+ !(dargs->optflag & DA_FORCE)) {
+ /*
+ * During DA_ADD, we keep an existing entry unless
+ * we have DA_FORCE set to override that entry.
+ */
+ dargs->optflag |= DA_NO_OVERRIDE;
+ rc = 0;
+ }
+ if (rc == 0) {
+ tmp_str = _dmap2strentry(dargs, devmapp);
+ if (tmp_str == NULL) {
+ freedmapent(devmapp);
+ enddmapent();
+ return (2);
+ }
+ /* retaining devmap entry: tmp_str->se_str */
+ tmp_str->se_next = NULL;
+ if (*head_devmapp == NULL) {
+ *head_devmapp = tail_str = tmp_str;
+ } else {
+ tail_str->se_next = tmp_str;
+ tail_str = tmp_str;
+ }
+ }
+ freedmapent(devmapp);
+ }
+ enddmapent();
+
+ return (rc);
+}
+
+/*
+ * _write_defattrs
+ * writes current entries to devalloc_defaults.
+ */
+static void
+_write_defattrs(FILE *fp, strentry_t *head_defent)
+{
+ strentry_t *tmp_str;
+
+ for (tmp_str = head_defent; tmp_str != NULL;
+ tmp_str = tmp_str->se_next) {
+ (void) fputs(tmp_str->se_str, fp);
+ (void) fputs("\n", fp);
+ }
+
+}
+
+/*
+ * _write_device_allocate -
+ * writes current entries in the list to device_allocate.
+ */
+static void
+_write_device_allocate(char *odevalloc, FILE *dafp, strentry_t *head_devallocp)
+{
+ int is_on = -1;
+ strentry_t *tmp_str;
+ struct stat dastat;
+
+ (void) fseek(dafp, (off_t)0, SEEK_SET);
+
+ /*
+ * if the devalloc on/off string existed before,
+ * put it back before anything else.
+ * we need to check for the string only if the file
+ * exists.
+ */
+ if (stat(odevalloc, &dastat) == 0) {
+ is_on = da_is_on();
+ if (is_on == 0)
+ (void) fputs(DA_OFF_STR, dafp);
+ else if (is_on == 1)
+ (void) fputs(DA_ON_STR, dafp);
+ }
+ tmp_str = head_devallocp;
+ while (tmp_str) {
+ (void) fputs(tmp_str->se_str, dafp);
+ (void) fputs("\n", dafp);
+ tmp_str = tmp_str->se_next;
+ }
+}
+
+/*
+ * _write_device_maps -
+ * writes current entries in the list to device_maps.
+ */
+static void
+_write_device_maps(FILE *dmfp, strentry_t *head_devmapp)
+{
+ strentry_t *tmp_str;
+
+ (void) fseek(dmfp, (off_t)0, SEEK_SET);
+
+ tmp_str = head_devmapp;
+ while (tmp_str) {
+ (void) fputs(tmp_str->se_str, dmfp);
+ (void) fputs("\n", dmfp);
+ tmp_str = tmp_str->se_next;
+ }
+}
+
+/*
+ * _write_new_defattrs
+ * writes the new entry to devalloc_defaults.
+ * returns 0 on success, -1 on error.
+ */
+static int
+_write_new_defattrs(FILE *fp, da_args *dargs)
+{
+ int count;
+ char *tok = NULL, *tokp = NULL;
+ char *lasts;
+ devinfo_t *devinfo = dargs->devinfo;
+
+ if (fseek(fp, (off_t)0, SEEK_END) == (off_t)-1)
+ return (-1);
+ if (!devinfo->devopts)
+ return (0);
+ (void) fprintf(fp, "%s%s", (devinfo->devtype ? devinfo->devtype : ""),
+ KV_TOKEN_DELIMIT);
+ if ((tokp = (char *)malloc(strlen(devinfo->devopts))) != NULL) {
+ (void) strcpy(tokp, devinfo->devopts);
+ if ((tok = strtok_r(tokp, KV_DELIMITER, &lasts)) != NULL) {
+ (void) fprintf(fp, "%s", tok);
+ count = 1;
+ }
+ while ((tok = strtok_r(NULL, KV_DELIMITER, &lasts)) != NULL) {
+ if (count)
+ (void) fprintf(fp, "%s", KV_DELIMITER);
+ (void) fprintf(fp, "%s", tok);
+ count++;
+ }
+ } else {
+ (void) fprintf(fp, "%s", devinfo->devopts);
+ }
+
+ return (0);
+}
+
+/*
+ * _write_new_entry -
+ * writes the new devalloc_t to device_allocate or the new devmap_t to
+ * device_maps.
+ * returns 0 on success, -1 on error.
+ */
+static int
+_write_new_entry(FILE *fp, da_args *dargs, int flag)
+{
+ int count;
+ char *tok = NULL, *tokp = NULL;
+ char *lasts;
+ devinfo_t *devinfo = dargs->devinfo;
+
+ if (flag & DA_MAPS_ONLY)
+ goto dmap_only;
+
+ if (fseek(fp, (off_t)0, SEEK_END) == (off_t)-1)
+ return (-1);
+
+ (void) fprintf(fp, "%s%s\\\n\t",
+ (devinfo->devname ? devinfo->devname : ""), KV_DELIMITER);
+ (void) fprintf(fp, "%s%s\\\n\t",
+ (devinfo->devtype ? devinfo->devtype : ""), KV_DELIMITER);
+ if (devinfo->devopts == NULL) {
+ (void) fprintf(fp, "%s%s\\\n\t", DA_RESERVED,
+ KV_DELIMITER);
+ } else {
+ if ((tokp = (char *)malloc(strlen(devinfo->devopts))) != NULL) {
+ (void) strcpy(tokp, devinfo->devopts);
+ if ((tok = strtok_r(tokp, KV_TOKEN_DELIMIT, &lasts)) !=
+ NULL) {
+ (void) fprintf(fp, "%s", tok);
+ count = 1;
+ }
+ while ((tok = strtok_r(NULL, KV_TOKEN_DELIMIT,
+ &lasts)) != NULL) {
+ if (count)
+ (void) fprintf(fp, "%s",
+ KV_TOKEN_DELIMIT "\\\n\t");
+ (void) fprintf(fp, "%s", tok);
+ count++;
+ }
+ if (count)
+ (void) fprintf(fp, "%s",
+ KV_DELIMITER "\\\n\t");
+ } else {
+ (void) fprintf(fp, "%s%s", devinfo->devopts,
+ KV_DELIMITER "\\\n\t");
+ }
+ }
+ (void) fprintf(fp, "%s%s\\\n\t", DA_RESERVED, KV_DELIMITER);
+ (void) fprintf(fp, "%s%s\\\n\t",
+ (devinfo->devauths ? devinfo->devauths : DA_ANYUSER),
+ KV_DELIMITER);
+ (void) fprintf(fp, "%s\n",
+ (devinfo->devexec ? devinfo->devexec : KV_DELIMITER));
+
+dmap_only:
+ if (flag & DA_ALLOC_ONLY)
+ return (0);
+
+ if (fseek(fp, (off_t)0, SEEK_END) == (off_t)-1)
+ return (-1);
+
+ (void) fprintf(fp, "%s%s\\\n",
+ (devinfo->devname ? devinfo->devname : ""), KV_TOKEN_DELIMIT);
+ (void) fprintf(fp, "\t%s%s\\\n",
+ (devinfo->devtype ? devinfo->devtype : ""), KV_TOKEN_DELIMIT);
+ (void) fprintf(fp, "\t%s\n",
+ (devinfo->devlist ? devinfo->devlist : KV_TOKEN_DELIMIT));
+
+ return (0);
+}
+
+/*
+ * _da_lock_devdb -
+ * locks the database files; lock can be either broken explicitly by
+ * closing the fd of the lock file, or it expires automatically at process
+ * termination.
+ * returns fd of the lock file or -1 on error.
+ */
+int
+_da_lock_devdb(char *rootdir)
+{
+ int lockfd = -1;
+ char *lockfile;
+ char path[MAXPATHLEN];
+ int size = sizeof (path);
+
+ if (rootdir == NULL) {
+ lockfile = DA_DB_LOCK;
+ } else {
+ path[0] = '\0';
+ if (snprintf(path, size, "%s%s", rootdir, DA_DB_LOCK) >= size)
+ return (-1);
+ lockfile = path;
+ }
+
+ if ((lockfd = open(lockfile, O_RDWR | O_CREAT, 0600)) == -1)
+ /* cannot open lock file */
+ return (-1);
+
+ (void) fchown(lockfd, DA_UID, DA_GID);
+
+ if (lseek(lockfd, (off_t)0, SEEK_SET) == -1) {
+ /* cannot position lock file */
+ (void) close(lockfd);
+ return (-1);
+ }
+ if (lockf(lockfd, F_TLOCK, 0) == -1) {
+ /* cannot set lock */
+ (void) close(lockfd);
+ return (-1);
+ }
+ (void) utime(lockfile, NULL);
+
+ return (lockfd);
+}
+
+/*
+ * da_open_devdb -
+ * opens one or both database files - device_allocate, device_maps - in
+ * the specified mode.
+ * locks the database files; lock is either broken explicitly by the
+ * caller by closing the lock file fd, or it expires automatically at
+ * process termination.
+ * writes the file pointer of opened file in the input args - dafp, dmfp.
+ * returns fd of the lock file on success, -2 if database file does not
+ * exist, -1 on other errors.
+ */
+int
+da_open_devdb(char *rootdir, FILE **dafp, FILE **dmfp, int flag)
+{
+ int oflag = 0;
+ int fda = -1;
+ int fdm = -1;
+ int lockfd = -1;
+ char *fname;
+ char *fmode;
+ char path[MAXPATHLEN];
+ FILE *devfile;
+
+ if ((dafp == NULL) && (dmfp == NULL))
+ return (-1);
+
+ if (flag & DA_RDWR) {
+ oflag = DA_RDWR;
+ fmode = "r+";
+ } else if (flag & DA_RDONLY) {
+ oflag = DA_RDONLY;
+ fmode = "r";
+ }
+
+ if ((lockfd = _da_lock_devdb(rootdir)) == -1)
+ return (-1);
+
+ if ((dafp == NULL) || (flag & DA_MAPS_ONLY))
+ goto dmap_only;
+
+ path[0] = '\0';
+
+ /*
+ * open the device allocation file
+ */
+ if (rootdir == NULL) {
+ fname = DEVALLOC;
+ } else {
+ if (snprintf(path, sizeof (path), "%s%s", rootdir,
+ DEVALLOC) >= sizeof (path)) {
+ if (lockfd != -1)
+ (void) close(lockfd);
+ return (-1);
+ }
+ fname = path;
+ }
+ if ((fda = open(fname, oflag, DA_DBMODE)) == -1) {
+ if (lockfd != -1)
+ (void) close(lockfd);
+ return ((errno == ENOENT) ? -2 : -1);
+ }
+ if ((devfile = fdopen(fda, fmode)) == NULL) {
+ (void) close(fda);
+ if (lockfd != -1)
+ (void) close(lockfd);
+ return (-1);
+ }
+ *dafp = devfile;
+ (void) fchmod(fda, DA_DBMODE);
+
+ if ((flag & DA_ALLOC_ONLY))
+ goto out;
+
+dmap_only:
+ path[0] = '\0';
+ /*
+ * open the device map file
+ */
+ if (rootdir == NULL) {
+ fname = DEVMAP;
+ } else {
+ if (snprintf(path, sizeof (path), "%s%s", rootdir,
+ DEVMAP) >= sizeof (path)) {
+ (void) close(fda);
+ if (lockfd != -1)
+ (void) close(lockfd);
+ return (-1);
+ }
+ fname = path;
+ }
+
+ if ((fdm = open(fname, oflag, DA_DBMODE)) == -1) {
+ if (lockfd != -1)
+ (void) close(lockfd);
+ return ((errno == ENOENT) ? -2 : -1);
+ }
+
+ if ((devfile = fdopen(fdm, fmode)) == NULL) {
+ (void) close(fdm);
+ (void) close(fda);
+ if (lockfd != -1)
+ (void) close(lockfd);
+ return (-1);
+ }
+ *dmfp = devfile;
+ (void) fchmod(fdm, DA_DBMODE);
+
+out:
+ return (lockfd);
+}
+
+/*
+ * _record_on_off -
+ * adds either DA_ON_STR or DA_OFF_STR to device_allocate
+ * returns 0 on success, -1 on error.
+ */
+static int
+_record_on_off(da_args *dargs, FILE *tafp, FILE *dafp)
+{
+ int dafd;
+ int nsize;
+ int nitems = 1;
+ int actionlen;
+ int str_found = 0;
+ int len = 0, nlen = 0, plen = 0;
+ char *ptr = NULL;
+ char *actionstr;
+ char *nbuf = NULL;
+ char line[MAX_CANON];
+ struct stat dastat;
+
+ if (dargs->optflag & DA_ON)
+ actionstr = DA_ON_STR;
+ else
+ actionstr = DA_OFF_STR;
+ actionlen = strlen(actionstr);
+ dafd = fileno(dafp);
+ if (fstat(dafd, &dastat) == -1)
+ return (-1);
+
+ /* check the old device_allocate for on/off string */
+ ptr = fgets(line, MAX_CANON, dafp);
+ if (ptr != NULL) {
+ if ((strcmp(line, DA_ON_STR) == 0) ||
+ (strcmp(line, DA_OFF_STR) == 0)) {
+ str_found = 1;
+ nsize = dastat.st_size;
+ }
+ }
+ if (!ptr || !str_found) {
+ /*
+ * the file never had either the on or the off string;
+ * make room for it.
+ */
+ str_found = 0;
+ nsize = dastat.st_size + actionlen + 1;
+ }
+ if ((nbuf = (char *)malloc(nsize)) == NULL)
+ return (-1);
+ nbuf[0] = '\0';
+ /* put the on/off string */
+ (void) strcpy(nbuf, actionstr);
+ nlen = strlen(nbuf);
+ plen = nlen;
+ if (ptr && !str_found) {
+ /* now put the first line that we read in fgets */
+ nlen = plen + strlen(line) + 1;
+ len = snprintf(nbuf + plen, nlen - plen, "%s", line);
+ if (len >= nsize) {
+ free(nbuf);
+ return (-1);
+ }
+ plen += len;
+ }
+
+ /* now get the rest of the old file */
+ while (fgets(line, MAX_CANON, dafp) != NULL) {
+ nlen = plen + strlen(line) + 1;
+ len = snprintf(nbuf + plen, nlen - plen, "%s", line);
+ if (len >= nsize) {
+ free(nbuf);
+ return (-1);
+ }
+ plen += len;
+ }
+ len = strlen(nbuf) + 1;
+ if (len < nsize)
+ nbuf[len] = '\n';
+
+ /* write the on/off str + the old device_allocate to the temp file */
+ if (fwrite(nbuf, nsize, nitems, tafp) < nitems) {
+ free(nbuf);
+ return (-1);
+ }
+
+ free(nbuf);
+
+ return (0);
+}
+
+/*
+ * da_update_defattrs -
+ * writes default attributes to devalloc_defaults
+ * returns 0 on success, -1 on error.
+ */
+int
+da_update_defattrs(da_args *dargs)
+{
+ int rc = 0, lockfd = 0, tmpfd = 0;
+ char *defpath = DEFATTRS;
+ char *tmpdefpath = TMPATTRS;
+ FILE *tmpfp = NULL;
+ struct stat dstat;
+ strentry_t *head_defent = NULL;
+
+ if (dargs == NULL)
+ return (0);
+ if ((lockfd = _da_lock_devdb(NULL)) == -1)
+ return (-1);
+ if ((tmpfd = open(tmpdefpath, O_RDWR|O_CREAT, DA_DBMODE)) == -1) {
+ (void) close(lockfd);
+ return (-1);
+ }
+ (void) fchown(tmpfd, DA_UID, DA_GID);
+ if ((tmpfp = fdopen(tmpfd, "r+")) == NULL) {
+ (void) close(tmpfd);
+ (void) unlink(tmpdefpath);
+ (void) close(lockfd);
+ return (-1);
+ }
+ /*
+ * examine all entries, remove an old one if required, check
+ * if a new one needs to be added.
+ */
+ if (stat(defpath, &dstat) == 0) {
+ if ((rc = _build_defattrs(dargs, &head_defent)) != 0) {
+ if (rc == 1) {
+ (void) close(tmpfd);
+ (void) unlink(tmpdefpath);
+ (void) close(lockfd);
+ return (rc);
+ }
+ }
+ }
+ /*
+ * write back any existing entries.
+ */
+ _write_defattrs(tmpfp, head_defent);
+
+ if (dargs->optflag & DA_ADD && !(dargs->optflag & DA_NO_OVERRIDE)) {
+ /* add new entries */
+ rc = _write_new_defattrs(tmpfp, dargs);
+ (void) fclose(tmpfp);
+ } else {
+ (void) fclose(tmpfp);
+ }
+ if (rename(tmpdefpath, defpath) != 0) {
+ rc = -1;
+ (void) unlink(tmpdefpath);
+ }
+ (void) close(lockfd);
+
+ return (rc);
+}
+
+/*
+ * da_update_device -
+ * writes devices entries to device_allocate and device_maps.
+ * returns 0 on success, -1 on error.
+ */
+int
+da_update_device(da_args *dargs)
+{
+ int rc;
+ int tafd = -1, tmfd = -1;
+ int lockfd = -1;
+ char *rootdir = NULL;
+ char *apathp = NULL, *mpathp = NULL, *dapathp = NULL,
+ *dmpathp = NULL;
+ char apath[MAXPATHLEN], mpath[MAXPATHLEN],
+ dapath[MAXPATHLEN], dmpath[MAXPATHLEN];
+ FILE *tafp = NULL, *tmfp = NULL, *dafp = NULL;
+ struct stat dastat;
+ devinfo_t *devinfo;
+ strentry_t *head_devmapp = NULL;
+ strentry_t *head_devallocp = NULL;
+
+ if (dargs == NULL)
+ return (0);
+
+ rootdir = dargs->rootdir;
+ devinfo = dargs->devinfo;
+
+ /*
+ * adding/removing entries should be done in both
+ * device_allocate and device_maps. updates can be
+ * done in both or either of the files.
+ */
+ if (dargs->optflag & DA_ADD || dargs->optflag & DA_REMOVE) {
+ if (dargs->optflag & DA_ALLOC_ONLY ||
+ dargs->optflag & DA_MAPS_ONLY)
+ return (0);
+ }
+
+ /*
+ * name, type and list are required fields for adding a new
+ * device.
+ */
+ if ((dargs->optflag & DA_ADD) &&
+ ((devinfo->devname == NULL) ||
+ (devinfo->devtype == NULL) ||
+ (devinfo->devlist == NULL))) {
+ return (-1);
+ }
+
+ if (rootdir != NULL) {
+ if (snprintf(apath, sizeof (apath), "%s%s", rootdir,
+ TMPALLOC) >= sizeof (apath))
+ return (-1);
+ apathp = apath;
+ if (snprintf(dapath, sizeof (dapath), "%s%s", rootdir,
+ DEVALLOC) >= sizeof (dapath))
+ return (-1);
+ dapathp = dapath;
+ if (!(dargs->optflag & DA_ALLOC_ONLY)) {
+ if (snprintf(mpath, sizeof (mpath), "%s%s", rootdir,
+ TMPMAP) >= sizeof (mpath))
+ return (-1);
+ mpathp = mpath;
+ if (snprintf(dmpath, sizeof (dmpath), "%s%s", rootdir,
+ DEVMAP) >= sizeof (dmpath))
+ return (-1);
+ dmpathp = dmpath;
+ }
+ } else {
+ apathp = TMPALLOC;
+ dapathp = DEVALLOC;
+ mpathp = TMPMAP;
+ dmpathp = DEVMAP;
+ }
+
+ if (dargs->optflag & DA_MAPS_ONLY)
+ goto dmap_only;
+
+ /*
+ * Check if we are here just to record on/off status of
+ * device_allocation.
+ */
+ if (dargs->optflag & DA_ON || dargs->optflag & DA_OFF)
+ lockfd = da_open_devdb(dargs->rootdir, &dafp, NULL,
+ DA_RDONLY|DA_ALLOC_ONLY);
+ else
+ lockfd = _da_lock_devdb(rootdir);
+ if (lockfd == -1)
+ return (-1);
+
+ if ((tafd = open(apathp, O_RDWR|O_CREAT, DA_DBMODE)) == -1) {
+ (void) close(lockfd);
+ (void) fclose(dafp);
+ return (-1);
+ }
+ (void) fchown(tafd, DA_UID, DA_GID);
+ if ((tafp = fdopen(tafd, "r+")) == NULL) {
+ (void) close(tafd);
+ (void) unlink(apathp);
+ (void) fclose(dafp);
+ (void) close(lockfd);
+ return (-1);
+ }
+
+ /*
+ * We don't need to parse the file if we are here just to record
+ * on/off status of device_allocation.
+ */
+ if (dargs->optflag & DA_ON || dargs->optflag & DA_OFF) {
+ if (_record_on_off(dargs, tafp, dafp) == -1) {
+ (void) close(tafd);
+ (void) unlink(apathp);
+ (void) fclose(dafp);
+ (void) close(lockfd);
+ return (-1);
+ }
+ (void) fclose(dafp);
+ goto out;
+ }
+
+ /*
+ * examine all the entries, remove an old one if forced to,
+ * and check that they are suitable for updating.
+ * we need to do this only if the file exists already.
+ */
+ if (stat(dapathp, &dastat) == 0) {
+ if ((rc = _build_lists(dargs, &head_devallocp,
+ &head_devmapp)) != 0) {
+ if (rc != 1) {
+ (void) close(tafd);
+ (void) unlink(apathp);
+ (void) close(lockfd);
+ return (rc);
+ }
+ }
+ }
+
+ /*
+ * write back any existing devalloc entries, along with
+ * the devalloc on/off string.
+ */
+ _write_device_allocate(dapathp, tafp, head_devallocp);
+
+ if (dargs->optflag & DA_ALLOC_ONLY)
+ goto out;
+
+dmap_only:
+ if ((tmfd = open(mpathp, O_RDWR|O_CREAT, DA_DBMODE)) == -1) {
+ (void) close(tafd);
+ (void) unlink(apathp);
+ (void) close(lockfd);
+ return (-1);
+ }
+ (void) fchown(tmfd, DA_UID, DA_GID);
+ if ((tmfp = fdopen(tmfd, "r+")) == NULL) {
+ (void) close(tafd);
+ (void) unlink(apathp);
+ (void) close(tmfd);
+ (void) unlink(mpathp);
+ (void) close(lockfd);
+ return (-1);
+ }
+
+ /* write back any existing devmap entries */
+ if (head_devmapp != NULL)
+ _write_device_maps(tmfp, head_devmapp);
+
+out:
+ if (dargs->optflag & DA_ADD && !(dargs->optflag & DA_NO_OVERRIDE)) {
+ /* add any new entries */
+ rc = _write_new_entry(tafp, dargs, DA_ALLOC_ONLY);
+ (void) fclose(tafp);
+
+ if (rc == 0)
+ rc = _write_new_entry(tmfp, dargs, DA_MAPS_ONLY);
+ (void) fclose(tmfp);
+ } else {
+ if (tafp)
+ (void) fclose(tafp);
+ if (tmfp)
+ (void) fclose(tmfp);
+ }
+
+ rc = 0;
+ if (!(dargs->optflag & DA_MAPS_ONLY)) {
+ if (rename(apathp, dapathp) != 0) {
+ rc = -1;
+ (void) unlink(apathp);
+ }
+ }
+ if (!(dargs->optflag & DA_ALLOC_ONLY)) {
+ if (rename(mpathp, dmpathp) != 0) {
+ rc = -1;
+ (void) unlink(mpathp);
+ }
+ }
+
+ (void) close(lockfd);
+
+ return (rc);
+}
+
+/*
+ * da_add_list -
+ * adds new /dev link name to the linked list of devices.
+ * returns 0 if link added successfully, -1 on error.
+ */
+int
+da_add_list(devlist_t *dlist, char *link, int new_instance, int flag)
+{
+ int instance;
+ int nlen, plen;
+ int new_entry = 0;
+ char *dtype, *dexec, *tname, *kval;
+ char *minstr = NULL, *maxstr = NULL;
+ char dname[DA_MAXNAME];
+ kva_t *kva;
+ deventry_t *dentry = NULL, *nentry = NULL, *pentry = NULL;
+ da_defs_t *da_defs;
+
+ if (dlist == NULL || link == NULL)
+ return (-1);
+
+ dname[0] = '\0';
+ if (flag & DA_AUDIO) {
+ dentry = dlist->audio;
+ tname = DA_AUDIO_NAME;
+ dtype = DA_AUDIO_TYPE;
+ dexec = DA_DEFAULT_AUDIO_CLEAN;
+ } else if (flag & DA_CD) {
+ dentry = dlist->cd;
+ tname = DA_CD_NAME;
+ dtype = DA_CD_TYPE;
+ dexec = DA_DEFAULT_DISK_CLEAN;
+ } else if (flag & DA_FLOPPY) {
+ dentry = dlist->floppy;
+ tname = DA_FLOPPY_NAME;
+ dtype = DA_FLOPPY_TYPE;
+ dexec = DA_DEFAULT_DISK_CLEAN;
+ } else if (flag & DA_TAPE) {
+ dentry = dlist->tape;
+ tname = DA_TAPE_NAME;
+ dtype = DA_TAPE_TYPE;
+ dexec = DA_DEFAULT_TAPE_CLEAN;
+ } else if (flag & DA_RMDISK) {
+ dentry = dlist->rmdisk;
+ tname = DA_RMDISK_NAME;
+ dtype = DA_RMDISK_TYPE;
+ dexec = DA_DEFAULT_DISK_CLEAN;
+ } else {
+ return (-1);
+ }
+
+ for (nentry = dentry; nentry != NULL; nentry = nentry->next) {
+ pentry = nentry;
+ (void) sscanf(nentry->devinfo.devname, "%*[a-z]%d", &instance);
+ if (nentry->devinfo.instance == new_instance)
+ /*
+ * Add the new link name to the list of links
+ * that the device 'dname' has.
+ */
+ break;
+ }
+
+ if (nentry == NULL) {
+ /*
+ * Either this is the first entry ever, or no matching entry
+ * was found. Create a new one and add to the list.
+ */
+ if (dentry == NULL) /* first entry ever */
+ instance = 0;
+ else /* no matching entry */
+ instance++;
+ (void) snprintf(dname, sizeof (dname), "%s%d", tname, instance);
+ if ((nentry = (deventry_t *)malloc(sizeof (deventry_t))) ==
+ NULL)
+ return (-1);
+ if (pentry != NULL)
+ pentry->next = nentry;
+ new_entry = 1;
+ nentry->devinfo.devname = strdup(dname);
+ nentry->devinfo.devtype = dtype;
+ nentry->devinfo.devauths = DEFAULT_DEV_ALLOC_AUTH;
+ nentry->devinfo.devexec = dexec;
+ nentry->devinfo.instance = new_instance;
+ /*
+ * Look for default label range, authorizations and cleaning
+ * program in devalloc_defaults. If label range is not
+ * specified in devalloc_defaults, assume it to be admin_low
+ * to admin_high.
+ */
+ minstr = DA_DEFAULT_MIN;
+ maxstr = DA_DEFAULT_MAX;
+ setdadefent();
+ if (da_defs = getdadeftype(nentry->devinfo.devtype)) {
+ kva = da_defs->devopts;
+ if ((kval = kva_match(kva, DAOPT_MINLABEL)) != NULL)
+ minstr = strdup(kval);
+ if ((kval = kva_match(kva, DAOPT_MAXLABEL)) != NULL)
+ maxstr = strdup(kval);
+ if ((kval = kva_match(kva, DAOPT_AUTHS)) != NULL)
+ nentry->devinfo.devauths = strdup(kval);
+ if ((kval = kva_match(kva, DAOPT_CSCRIPT)) != NULL)
+ nentry->devinfo.devexec = strdup(kval);
+ freedadefent(da_defs);
+ }
+ enddadefent();
+ kval = NULL;
+ nlen = strlen(DAOPT_MINLABEL) + strlen(KV_ASSIGN) +
+ strlen(minstr) + strlen(KV_TOKEN_DELIMIT) +
+ strlen(DAOPT_MAXLABEL) + strlen(KV_ASSIGN) + strlen(maxstr)
+ + 1; /* +1 for terminator */
+ if (kval = (char *)malloc(nlen))
+ (void) snprintf(kval, nlen, "%s%s%s%s%s%s%s",
+ DAOPT_MINLABEL, KV_ASSIGN, minstr, KV_TOKEN_DELIMIT,
+ DAOPT_MAXLABEL, KV_ASSIGN, maxstr);
+ nentry->devinfo.devopts = kval;
+
+ nentry->devinfo.devlist = NULL;
+ nentry->next = NULL;
+ }
+
+ nlen = strlen(link) + 1; /* +1 terminator */
+ if (nentry->devinfo.devlist) {
+ plen = strlen(nentry->devinfo.devlist);
+ nlen = nlen + plen + 1; /* +1 for blank to separate entries */
+ } else {
+ plen = 0;
+ }
+
+ if ((nentry->devinfo.devlist =
+ (char *)realloc(nentry->devinfo.devlist, nlen)) == NULL) {
+ if (new_entry) {
+ nentry->devinfo.devname = NULL;
+ free(nentry->devinfo.devname);
+ nentry = NULL;
+ free(nentry);
+ if (pentry != NULL)
+ pentry->next = NULL;
+ }
+ return (-1);
+ }
+
+ if (plen == 0)
+ (void) snprintf(nentry->devinfo.devlist, nlen, "%s", link);
+ else
+ (void) snprintf(nentry->devinfo.devlist + plen, nlen - plen,
+ " %s", link);
+
+ if (pentry == NULL) {
+ /*
+ * This is the first entry of this device type.
+ */
+ if (flag & DA_AUDIO)
+ dlist->audio = nentry;
+ else if (flag & DA_CD)
+ dlist->cd = nentry;
+ else if (flag & DA_FLOPPY)
+ dlist->floppy = nentry;
+ else if (flag & DA_TAPE)
+ dlist->tape = nentry;
+ else if (flag & DA_RMDISK)
+ dlist->rmdisk = nentry;
+ }
+
+ return (0);
+}
+
+/*
+ * da_remove_list -
+ * removes a /dev link name from the linked list of devices.
+ * returns type of device if link for that device removed
+ * successfully, else returns -1 on error.
+ * if all links for a device are removed, stores that device
+ * name in devname.
+ */
+int
+da_remove_list(devlist_t *dlist, char *link, int type, char *devname, int size)
+{
+ int flag;
+ int remove_dev = 0;
+ int nlen, plen, slen;
+ char *lasts, *lname, *oldlist;
+ struct stat rmstat;
+ deventry_t *dentry, *current, *prev;
+
+ if (type != NULL)
+ flag = type;
+ else if (link == NULL)
+ return (-1);
+ else if (strstr(link, DA_AUDIO_NAME) || strstr(link, DA_SOUND_NAME))
+ flag = DA_AUDIO;
+ else if (strstr(link, "dsk") || strstr(link, "rdsk") ||
+ strstr(link, "sr") || strstr(link, "rsr"))
+ flag = DA_CD;
+ else if (strstr(link, "fd") || strstr(link, "rfd") ||
+ strstr(link, "diskette") || strstr(link, "rdiskette"))
+ flag = DA_FLOPPY;
+ else if (strstr(link, DA_TAPE_NAME))
+ flag = DA_TAPE;
+ else
+ flag = DA_RMDISK;
+
+ switch (type) {
+ case DA_AUDIO:
+ dentry = dlist->audio;
+ break;
+ case DA_CD:
+ dentry = dlist->cd;
+ break;
+ case DA_FLOPPY:
+ dentry = dlist->floppy;
+ break;
+ case DA_TAPE:
+ dentry = dlist->tape;
+ break;
+ case DA_RMDISK:
+ dentry = dlist->rmdisk;
+ break;
+ default:
+ return (-1);
+ }
+
+ if ((type != NULL) && (link == NULL)) {
+ for (current = dentry, prev = dentry; current != NULL;
+ current = current->next) {
+ oldlist = strdup(current->devinfo.devlist);
+ for (lname = strtok_r(oldlist, " ", &lasts);
+ lname != NULL;
+ lname = strtok_r(NULL, " ", &lasts)) {
+ if (stat(lname, &rmstat) != 0) {
+ remove_dev = 1;
+ goto remove_dev;
+ }
+ }
+ prev = current;
+ }
+ return (-1);
+ }
+
+ for (current = dentry, prev = dentry; current != NULL;
+ current = current->next) {
+ plen = strlen(current->devinfo.devlist);
+ nlen = strlen(link);
+ if (plen == nlen) {
+ if (strcmp(current->devinfo.devlist, link) == 0) {
+ /* last name in the list */
+ remove_dev = 1;
+ break;
+ }
+ }
+ if (strstr(current->devinfo.devlist, link)) {
+ nlen = plen - nlen + 1;
+ oldlist = strdup(current->devinfo.devlist);
+ if ((current->devinfo.devlist =
+ (char *)realloc(current->devinfo.devlist,
+ nlen)) == NULL) {
+ free(oldlist);
+ return (-1);
+ }
+ current->devinfo.devlist[0] = '\0';
+ nlen = plen = slen = 0;
+ for (lname = strtok_r(oldlist, " ", &lasts);
+ lname != NULL;
+ lname = strtok_r(NULL, " ", &lasts)) {
+ if (strcmp(lname, link) == 0)
+ continue;
+ nlen = strlen(lname) + plen + 1;
+ if (plen == 0) {
+ slen =
+ snprintf(current->devinfo.devlist,
+ nlen, "%s", lname);
+ } else {
+ slen =
+ snprintf(current->devinfo.devlist +
+ plen, nlen - plen, " %s",
+ lname);
+ }
+ plen = plen + slen + 1;
+ }
+ free(oldlist);
+ break;
+ }
+ prev = current;
+ }
+
+remove_dev:
+ if (remove_dev == 1) {
+ (void) strlcpy(devname, current->devinfo.devname, size);
+ free(current->devinfo.devname);
+ free(current->devinfo.devlist);
+ current->devinfo.devname = current->devinfo.devlist = NULL;
+ prev->next = current->next;
+ free(current);
+ current = NULL;
+ }
+ if ((remove_dev == 1) && (prev->devinfo.devname == NULL)) {
+ if (prev->next) {
+ /*
+ * what we removed above was the first entry
+ * in the list. make the next entry to be the
+ * first.
+ */
+ current = prev->next;
+ } else {
+ /*
+ * the matching entry was the only entry in the list
+ * for this type.
+ */
+ current = NULL;
+ }
+ if (flag & DA_AUDIO)
+ dlist->audio = current;
+ else if (flag & DA_CD)
+ dlist->cd = current;
+ else if (flag & DA_FLOPPY)
+ dlist->floppy = current;
+ else if (flag & DA_TAPE)
+ dlist->tape = current;
+ else if (flag & DA_RMDISK)
+ dlist->rmdisk = current;
+ }
+
+ return (flag);
+}
+
+/*
+ * da_is_on -
+ * checks if device allocation feature is turned on.
+ * returns 1 if on, 0 if off, -1 if status string not
+ * found in device_allocate.
+ */
+int
+da_is_on()
+{
+ return (getdaon());
+}
+
+/*
+ * da_print_device -
+ * debug routine to print device entries.
+ */
+void
+da_print_device(int flag, devlist_t *devlist)
+{
+ deventry_t *entry, *dentry;
+ devinfo_t *devinfo;
+
+ if (flag & DA_AUDIO)
+ dentry = devlist->audio;
+ else if (flag & DA_CD)
+ dentry = devlist->cd;
+ else if (flag & DA_FLOPPY)
+ dentry = devlist->floppy;
+ else if (flag & DA_TAPE)
+ dentry = devlist->tape;
+ else if (flag & DA_RMDISK)
+ dentry = devlist->rmdisk;
+ else
+ return;
+
+ for (entry = dentry; entry != NULL; entry = entry->next) {
+ devinfo = &(entry->devinfo);
+ (void) fprintf(stdout, "name: %s\n", devinfo->devname);
+ (void) fprintf(stdout, "type: %s\n", devinfo->devtype);
+ (void) fprintf(stdout, "auth: %s\n", devinfo->devauths);
+ (void) fprintf(stdout, "exec: %s\n", devinfo->devexec);
+ (void) fprintf(stdout, "list: %s\n\n", devinfo->devlist);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libbsm/common/devalloc.h Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,185 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _DEVALLOC_H
+#define _DEVALLOC_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/param.h>
+#include <secdb.h>
+
+/*
+ * These are unsupported, SUNWprivate interfaces.
+ */
+
+#define DA_UID (uid_t)0 /* root */
+#define DA_GID (gid_t)3 /* sys */
+#define LOGINDEVPERM "/etc/logindevperm"
+#define DA_DB_LOCK "/etc/security/.da_db_lock"
+#define DA_DEV_LOCK "/etc/security/.da_dev_lock"
+#define DEVALLOC "/etc/security/device_allocate"
+#define DEVMAP "/etc/security/device_maps"
+#define DEFATTRS "/etc/security/tsol/devalloc_defaults"
+#define TMPALLOC "/etc/security/.device_allocate"
+#define TMPMAP "/etc/security/.device_maps"
+#define TMPATTRS "/etc/security/tsol/.devalloc_defaults"
+
+#define DA_DEFAULT_MIN "admin_low"
+#define DA_DEFAULT_MAX "admin_high"
+#define DA_DEFAULT_CLEAN "/bin/true"
+#define DA_DEFAULT_AUDIO_CLEAN "/etc/security/lib/audio_clean_wrapper"
+#define DA_DEFAULT_DISK_CLEAN "/etc/security/lib/disk_clean"
+#define DA_DEFAULT_TAPE_CLEAN "/etc/security/lib/st_clean"
+
+#define DA_ON_STR "DEVICE_ALLOCATION=ON\n"
+#define DA_OFF_STR "DEVICE_ALLOCATION=OFF\n"
+#define DA_IS_LABELED "system_labeled"
+#define DA_LABEL_CHECK "/usr/bin/plabel"
+#define DA_DBMODE 0644
+#define DA_COUNT 5 /* allocatable devices suppported */
+ /* audio, cd, floppy, rmdisk, tape */
+#define DA_AUTHLEN MAX_CANON /* approx. sum of strlen of all */
+ /* device auths in auth_list.h */
+#define DA_MAXNAME 80
+#define DA_BUFSIZE 4096
+
+#define DA_RDWR O_RDWR|O_CREAT|O_NONBLOCK
+#define DA_RDONLY O_RDONLY|O_NONBLOCK
+
+#define DA_ANYUSER "*"
+#define DA_NOUSER "@"
+
+#define ALLOC_UID (uid_t)0 /* root */
+#define ALLOC_GID (gid_t)3 /* sys */
+#define ALLOC_ERRID (uid_t)2 /* bin */
+#define ALLOC_MODE 0600
+#define DEALLOC_MODE 0000
+
+#define DA_SILENT 0x00000001
+#define DA_VERBOSE 0x00000002
+#define DA_ADD 0x00000004
+#define DA_REMOVE 0x00000008
+#define DA_UPDATE 0x00000010
+#define DA_ADD_ZONE 0x00000020
+#define DA_REMOVE_ZONE 0x00000040
+#define DA_FORCE 0x00000080
+#define DA_ALLOC_ONLY 0x00000100
+#define DA_MAPS_ONLY 0x00000200
+#define DA_ON 0x00000400
+#define DA_OFF 0x00000800
+#define DA_NO_OVERRIDE 0x00001000
+#define DA_DEFATTRS 0x00002000
+
+#define DA_AUDIO 0x00001000
+#define DA_CD 0x00002000
+#define DA_FLOPPY 0x00004000
+#define DA_TAPE 0x00008000
+#define DA_RMDISK 0x00010000
+
+#define DA_AUDIO_NAME "audio"
+#define DA_SOUND_NAME "sound"
+#define DA_AUDIO_TYPE DA_AUDIO_NAME
+#define DA_AUDIO_DIR "/dev/sound/"
+
+#define DA_CD_NAME "cdrom"
+#define DA_CD_TYPE "sr"
+
+#define DA_DISK_DIR "/dev/dsk/"
+#define DA_DISK_DIRR "/dev/rdsk/"
+#define DA_DISKR_DIR "/dev/(r)dsk"
+
+#define DA_FLOPPY_NAME "floppy"
+#define DA_FLOPPY_TYPE "fd"
+
+#define DA_RMDISK_NAME "rmdisk"
+#define DA_RMDISK_TYPE DA_RMDISK_NAME
+
+#define DA_TAPE_NAME "tape"
+#define DA_TAPE_DIR "/dev/rmt/"
+#define DA_TAPE_TYPE "st"
+
+typedef struct _devinfo_t {
+ char *devname;
+ char *devtype;
+ char *devauths;
+ char *devexec;
+ char *devopts;
+ char *devlist;
+ int instance;
+} devinfo_t;
+
+typedef struct _deventry_t {
+ devinfo_t devinfo;
+ struct _deventry_t *next;
+} deventry_t;
+
+typedef struct _devlist_t {
+ deventry_t *audio;
+ deventry_t *cd;
+ deventry_t *floppy;
+ deventry_t *tape;
+ deventry_t *rmdisk;
+} devlist_t;
+
+typedef struct _da_optargs {
+ int optflag;
+ char *rootdir;
+ char **devnames;
+ devinfo_t *devinfo;
+} da_args;
+
+typedef struct _da_defs {
+ char *devtype;
+ kva_t *devopts;
+} da_defs_t;
+
+da_defs_t *getdadefent(void);
+da_defs_t *getdadeftype(char *);
+void freedadefent(da_defs_t *);
+void setdadefent(void);
+void enddadefent(void);
+int da_is_on(void);
+int da_check_logindevperm(char *);
+int da_open_devdb(char *, FILE **, FILE **, int);
+int da_update_device(da_args *);
+int da_update_defattrs(da_args *);
+int da_add_list(devlist_t *, char *, int, int);
+int da_remove_list(devlist_t *, char *, int, char *, int);
+void da_print_device(int, devlist_t *);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DEVALLOC_H */
--- a/usr/src/lib/libbsm/common/devices.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libbsm/common/devices.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -33,36 +32,55 @@
extern "C" {
#endif
-typedef struct { /* see getdmapent(3) */
- char *dmap_devname;
- char *dmap_devtype;
- char *dmap_devlist;
+#include <stdio.h>
+#include <secdb.h>
+
+/*
+ * These are unsupported, SUN-private interfaces.
+ */
+
+#define DAOPT_AUTHS "auths"
+#define DAOPT_CSCRIPT "cleanscript"
+#define DAOPT_MINLABEL "minlabel"
+#define DAOPT_MAXLABEL "maxlabel"
+#define DAOPT_ZONE "zone"
+#define DA_RESERVED "reserved"
+
+typedef struct {
+ char *da_devname;
+ char *da_devtype;
+ char *da_devauth;
+ char *da_devexec;
+ kva_t *da_devopts;
+} devalloc_t;
+
+typedef struct {
+ char *dmap_devname;
+ char *dmap_devtype;
+ char *dmap_devlist;
+ char **dmap_devarray;
} devmap_t;
-devmap_t *getdmapent(void);
-devmap_t *getdmaptype(char *);
-devmap_t *getdmapnam(char *);
-devmap_t *getdmapdev(char *);
-void setdmapent(void);
-void enddmapent(void);
-void setdmapfile(char *);
+int getdadmline(char *, int, FILE *);
+
+devalloc_t *getdaent(void);
+devalloc_t *getdatype(char *);
+devalloc_t *getdanam(char *);
+void setdaent(void);
+void enddaent(void);
+void freedaent(devalloc_t *);
+void setdafile(char *);
-typedef struct { /* see getdaent(3) */
- char *da_devname;
- char *da_devtype;
- char *da_devmin;
- char *da_devmax;
- char *da_devauth;
- char *da_devexec;
-} devalloc_t;
-
-devalloc_t *getdaent(void);
-devalloc_t *getdatype(char *);
-devalloc_t *getdanam(char *);
-devalloc_t *getdadev(char *);
-void setdaent(void);
-void enddaent(void);
-void setdafile(char *);
+devmap_t *getdmapent(void);
+devmap_t *getdmaptype(char *);
+devmap_t *getdmapnam(char *);
+devmap_t *getdmapdev(char *);
+void setdmapent(void);
+void enddmapent(void);
+void freedmapent(devmap_t *);
+void setdmapfile(char *);
+char *getdmapfield(char *);
+char *getdmapdfield(char *);
#ifdef __cplusplus
}
--- a/usr/src/lib/libbsm/common/generic.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libbsm/common/generic.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -37,6 +36,7 @@
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
+#include <tsol/label.h>
#include <bsm/audit.h>
#include <bsm/libbsm.h>
#include <bsm/audit_uevents.h>
@@ -426,6 +426,9 @@
(void) au_write(ad, au_to_newgroups(ng, grplst));
}
}
+ if (is_system_labeled())
+ (void) au_write(ad, au_to_mylabel());
+
if (aug_text != NULL) {
(void) au_write(ad, au_to_text(aug_text));
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libbsm/common/getdadefs.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,234 @@
+/*
+ * 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 <string.h>
+#include <stdlib.h>
+#include <bsm/devices.h>
+#include <bsm/devalloc.h>
+
+char *strtok_r(char *, const char *, char **);
+
+/* externs from getdaent.c */
+extern char *trim_white(char *);
+extern int pack_white(char *);
+extern char *getdadmfield(char *, char *);
+extern int getdadmline(char *, int, FILE *);
+
+extern char *_strdup_null(char *);
+
+static struct _dadefbuff {
+ FILE *_dadeff;
+ /* pointer into /etc/security/tsol/devalloc_defaults */
+ da_defs_t _interpdadefs;
+ char _interpdadefline[DA_BUFSIZE + 1];
+ char *_DADEFS;
+} *__dadefbuff;
+
+#define dadeff (_df->_dadeff)
+#define interpdadefs (_df->_interpdadefs)
+#define interpdadefline (_df->_interpdadefline)
+#define DADEFS_FILE (_df->_DADEFS)
+
+static da_defs_t *dadef_interpret(char *);
+int dadef_matchtype(da_defs_t *, char *);
+
+/*
+ * _dadefalloc -
+ * allocates common buffers and structures.
+ * returns pointer to the new structure, else returns NULL on error.
+ */
+static struct _dadefbuff *
+_dadefalloc(void)
+{
+ struct _dadefbuff *_df = __dadefbuff;
+
+ if (_df == NULL) {
+ _df = (struct _dadefbuff *)calloc((unsigned)1,
+ (unsigned)sizeof (*__dadefbuff));
+ if (_df == NULL)
+ return (NULL);
+ DADEFS_FILE = "/etc/security/tsol/devalloc_defaults";
+ __dadefbuff = _df;
+ }
+
+ return (__dadefbuff);
+}
+
+/*
+ * setdadefent -
+ * rewinds devalloc_defaults file to the begining.
+ */
+
+void
+setdadefent(void)
+{
+ struct _dadefbuff *_df = _dadefalloc();
+
+ if (_df == NULL)
+ return;
+ if (dadeff == NULL)
+ dadeff = fopen(DADEFS_FILE, "r");
+ else
+ rewind(dadeff);
+}
+
+/*
+ * enddadefent -
+ * closes devalloc_defaults file.
+ */
+
+void
+enddadefent(void)
+{
+ struct _dadefbuff *_df = _dadefalloc();
+
+ if (_df == NULL)
+ return;
+ if (dadeff != NULL) {
+ (void) fclose(dadeff);
+ dadeff = NULL;
+ }
+}
+
+void
+freedadefent(da_defs_t *da_def)
+{
+ if (da_def == NULL)
+ return;
+ _kva_free(da_def->devopts);
+ da_def->devopts = NULL;
+}
+
+/*
+ * getdadefent -
+ * When first called, returns a pointer to the first da_defs_t
+ * structure in devalloc_defaults; thereafter, it returns a pointer to the
+ * next da_defs_t structure in the file. Thus, successive calls can be
+ * used to search the entire file.
+ * call to getdadefent should be bracketed by setdadefent and enddadefent.
+ * returns NULL on error.
+ */
+da_defs_t *
+getdadefent(void)
+{
+ char line1[DA_BUFSIZE + 1];
+ da_defs_t *da_def;
+ struct _dadefbuff *_df = _dadefalloc();
+
+ if ((_df == 0) || (dadeff == NULL))
+ return (NULL);
+
+ while (getdadmline(line1, (int)sizeof (line1), dadeff) != 0) {
+ if ((da_def = dadef_interpret(line1)) == NULL)
+ continue;
+ return (da_def);
+ }
+
+ return (NULL);
+}
+
+/*
+ * getdadeftype -
+ * searches from the beginning of devalloc_defaults for the device
+ * specified by its type.
+ * call to getdadeftype should be bracketed by setdadefent and enddadefent.
+ * returns pointer to da_defs_t for the device if it is found, else
+ * returns NULL if device not found or in case of error.
+ */
+da_defs_t *
+getdadeftype(char *type)
+{
+ char line1[DA_BUFSIZE + 1];
+ da_defs_t *da_def;
+ struct _dadefbuff *_df = _dadefalloc();
+
+ if ((type == NULL) || (_df == NULL) || (dadeff == NULL))
+ return (NULL);
+
+ while (getdadmline(line1, (int)sizeof (line1), dadeff) != 0) {
+ if (strstr(line1, type) == NULL)
+ continue;
+ if ((da_def = dadef_interpret(line1)) == NULL)
+ continue;
+ if (dadef_matchtype(da_def, type))
+ return (da_def);
+ freedadefent(da_def);
+ }
+
+ return (NULL);
+}
+
+/*
+ * dadef_matchtype -
+ * checks if the specified da_defs_t is for the device type specified.
+ * returns 1 if match found, else, returns 0.
+ */
+int
+dadef_matchtype(da_defs_t *da_def, char *type)
+{
+ if (da_def->devtype == NULL)
+ return (0);
+
+ return ((strcmp(da_def->devtype, type) == 0));
+}
+
+/*
+ * dadef_interpret -
+ * parses val and initializes pointers in da_defs_t.
+ * returns pointer to parsed da_defs_t entry, else returns NULL on error.
+ */
+static da_defs_t *
+dadef_interpret(char *val)
+{
+ struct _dadefbuff *_df = _dadefalloc();
+ int i;
+ char *opts;
+ kva_t *kvap;
+ kv_t *kvp;
+
+ if (_df == NULL)
+ return (NULL);
+
+ (void) strcpy(interpdadefline, val);
+ interpdadefs.devtype = getdadmfield(interpdadefline, KV_TOKEN_DELIMIT);
+ opts = getdadmfield(NULL, KV_TOKEN_DELIMIT);
+ interpdadefs.devopts = NULL;
+ if (interpdadefs.devtype == NULL)
+ return (NULL);
+ if (opts != NULL)
+ interpdadefs.devopts =
+ _str2kva(opts, KV_ASSIGN, KV_DELIMITER);
+ /* remove any extraneous whitespace in the options */
+ if ((kvap = interpdadefs.devopts) != NULL) {
+ for (i = 0, kvp = kvap->data; i < kvap->length; i++, kvp++) {
+ (void) pack_white(kvp->key);
+ (void) pack_white(kvp->value);
+ }
+ }
+
+ return (&interpdadefs);
+}
--- a/usr/src/lib/libbsm/common/getdaent.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libbsm/common/getdaent.c Fri Mar 24 12:29:20 2006 -0800
@@ -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,320 +18,242 @@
*
* 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"
-#include <stdio.h>
-#include <string.h>
-#include <malloc.h>
-#include <bsm/devices.h>
+#ifndef lint
+static char sccsid[] = "%Z%%M% %I% %E% SMI";
+#endif
-#define MAXINT 0x7fffffff;
-#ifdef SunOS_CMW
-extern char *calloc();
-#endif
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <tsol/label.h>
+#include <bsm/devices.h>
+#include <bsm/devalloc.h>
+
+extern char *_strdup_null(char *);
static struct _dabuff {
- devalloc_t _NULLDA;
- FILE *_daf; /* pointer into /etc/security/device_allocate */
- devalloc_t _interpdevalloc;
- char _interpline[BUFSIZ + 1];
- char *_DEVALLOC;
+ FILE *_daf; /* pointer into /etc/security/device_allocate */
+ devalloc_t _interpdevalloc;
+ char _interpdaline[DA_BUFSIZE + 1];
+ char *_DEVALLOC;
} *__dabuff;
-#define NULLDA (_da->_NULLDA)
-#define daf (_da->_daf)
-#define interpdevalloc (_da->_interpdevalloc)
-#define interpline (_da->_interpline)
-#define DEVALLOC (_da->_DEVALLOC)
-static devalloc_t *interpret();
-static int matchname();
+#define daf (_da->_daf)
+#define interpdevalloc (_da->_interpdevalloc)
+#define interpdaline (_da->_interpdaline)
+#define DEVALLOC_FILE (_da->_DEVALLOC)
+static devalloc_t *da_interpret(char *);
+
+int da_matchname(devalloc_t *, char *);
+int da_matchtype(devalloc_t *, char *);
+
+static int system_labeled = 0;
/*
- * trim_white(ptr) trims off leading and trailing white space from a NULL
- * terminated string pointed to by "ptr". The leading white space is skipped
- * by moving the pointer forward. The trailing white space is removed by
- * nulling the white space characters. The pointer is returned to the white
- * string. If the resulting string is null in length then a NULL pointer is
- * returned. If "ptr" is NULL then a NULL pointer is returned.
+ * trim_white -
+ * trims off leading and trailing white space from input string.
+ * The leading white space is skipped by moving the pointer forward.
+ * The trailing white space is removed by nulling the white space
+ * characters.
+ * returns pointer to non-white string, else returns NULL if input string
+ * is null or if the resulting string has zero length.
*/
-static char *
-trim_white(ptr)
-char *ptr;
+char *
+trim_white(char *ptr)
{
- register char *tptr;
- register int cnt;
+ char *tptr;
+
if (ptr == NULL)
return (NULL);
- while ((*ptr == ' ') || (*ptr == '\t')) {
+ while (isspace(*ptr))
ptr++;
- }
- cnt = strlen(ptr);
- if (cnt != 0) {
- tptr = ptr + cnt - 1;
- while ((*tptr == ' ') || (*tptr == '\t')) {
- *tptr = '\0';
- tptr--;
- }
- }
- if (*ptr == NULL)
+ tptr = ptr + strlen(ptr);
+ while (tptr != ptr && isspace(tptr[-1]))
+ --tptr;
+ *tptr = '\0';
+ if (*ptr == '\0')
return (NULL);
+
return (ptr);
}
-
/*
- * scan string pointed to by pointer "p"
- * find next colin or end of line. Null it and
- * return pointer to next char.
+ * pack_white -
+ * trims off multiple occurrences of white space from input string.
+ * returns the number of spaces retained
*/
-static char *
-daskip(p)
-register char *p;
+int
+pack_white(char *ptr)
{
- while (*p && *p != ';' && *p != '\n')
- ++p;
- if (*p == '\n')
- *p = '\0';
- else if (*p != '\0')
- *p++ = '\0';
- return (p);
+ int cnt = 0;
+ char *tptr, ch;
+
+ if (ptr == NULL)
+ return (0);
+ tptr = ptr;
+ while (isspace(*tptr))
+ tptr++;
+ for (;;) {
+ while ((ch = *tptr) != '\0' && !isspace(ch)) {
+ *ptr++ = ch;
+ tptr++;
+ }
+ while (isspace(*tptr))
+ tptr++;
+ if (*tptr == '\0')
+ break;
+ *ptr++ = ' ';
+ cnt++;
+ }
+ *ptr = '\0';
+
+ return (cnt);
}
-
-/*
- * scan string pointed to by pointer "p"
- * find next colin or end of line. Null it and
- * return pointer to next char.
- */
-static char *
-dadskip(p)
-register char *p;
-{
- while (*p && *p != ' ' && *p != '\n')
- ++p;
- if (*p != '\0')
- *p++ = '\0';
- return (p);
-}
-
-
/*
- * _daalloc() allocates common buffers and structures used by the device
- * allocate library routines. Then returns a pointer to a structure. The
- * returned pointer will be null if there is an error condition.
+ * getdadmline -
+ * reads one device_alloc/device_maps line from stream into buff of len
+ * bytes. Continued lines from stream are concatenated into one line in
+ * buff. Comments are removed from buff.
+ * returns the number of characters in buff, else returns 0 if no
+ * characters are read or an error occurred.
*/
-static struct _dabuff *
-_daalloc()
+int
+getdadmline(char *buff, int len, FILE *stream)
{
- register struct _dabuff *_da = __dabuff;
-
- if (_da == 0) {
- _da = (struct _dabuff *)
- calloc((size_t)1, sizeof (*__dabuff));
- if (_da == 0)
- return (0);
- DEVALLOC = "/etc/security/device_allocate";
- __dabuff = _da;
- }
- return (__dabuff);
-}
-
+ int tmpcnt;
+ int charcnt = 0;
+ int fileerr = 0;
+ int contline = 0;
+ char *cp;
+ char *ccp;
-/*
- * getdaline(buff,len,stream) reads one device allocate line from "stream" into
- * "buff" on "len" bytes. Continued lines from "stream" are concatinated
- * into one line in "buff". Comments are removed from "buff". The number of
- * characters in "buff" is returned. If no characters are read or an err or
- * occured then "0" is returned
- */
-static int
-getdaline(buff, len, stream)
- char *buff;
- int len;
- FILE *stream;
-{
- register struct _dabuff *_da = _daalloc();
- char *cp;
- char *ccp;
- int tmpcnt;
- int charcnt = 0;
- int fileerr = 0;
- int contline;
- if (_da == 0)
- return (0);
do {
cp = buff;
*cp = NULL;
do {
+ contline = 0;
if (fgets(cp, len - charcnt, stream) == NULL) {
fileerr = 1;
break;
}
- ccp = strpbrk(cp, "\\\n");
+ ccp = strchr(cp, '\n');
if (ccp != NULL) {
- if (*ccp == '\\')
+ if (ccp != cp && ccp[-1] == '\\') {
+ ccp--;
contline = 1;
- else
+ }
+ else
contline = 0;
*ccp = NULL;
}
tmpcnt = strlen(cp);
- if (tmpcnt != 0) {
- cp += tmpcnt;
- charcnt += tmpcnt;
- }
+ cp += tmpcnt;
+ charcnt += tmpcnt;
} while ((contline) || (charcnt == 0));
ccp = strpbrk(buff, "#");
if (ccp != NULL)
*ccp = NULL;
charcnt = strlen(buff);
} while ((fileerr == 0) && (charcnt == 0));
- if (fileerr)
+
+ if (fileerr && !charcnt)
return (0);
- else
+ else
return (charcnt);
}
-char *
-getdafield(ptr)
-char *ptr;
+/*
+ * _daalloc -
+ * allocates common buffers and structures.
+ * returns pointer to the new structure, else returns NULL on error.
+ */
+static struct _dabuff *
+_daalloc(void)
{
- static char *tptr;
- if (ptr == NULL)
- ptr = tptr;
- if (ptr == NULL)
- return (NULL);
- tptr = daskip(ptr);
- ptr = trim_white(ptr);
- if (ptr == NULL)
- return (NULL);
- if (*ptr == NULL)
- return (NULL);
- return (ptr);
-}
+ struct _dabuff *_da = __dabuff;
-char *
-getdadfield(ptr)
-char *ptr;
-{
- static char *tptr;
- if (ptr != NULL) {
- ptr = trim_white(ptr);
- } else {
- ptr = tptr;
+ if (_da == NULL) {
+ _da = (struct _dabuff *)calloc((unsigned)1,
+ (unsigned)sizeof (*__dabuff));
+ if (_da == NULL)
+ return (NULL);
+ DEVALLOC_FILE = "/etc/security/device_allocate";
+ daf = NULL;
+ __dabuff = _da;
+ system_labeled = is_system_labeled();
}
- if (ptr == NULL)
- return (NULL);
- tptr = dadskip(ptr);
- if (ptr == NULL)
- return (NULL);
- if (*ptr == NULL)
- return (NULL);
- return (ptr);
+
+ return (__dabuff);
}
/*
- * getdadev(dev) searches from the beginning of the file until a logical
- * device matching "dev" is found and returns a pointer to the particular
- * structure in which it was found. If an EOF or an error is encountered on
- * reading, these functions return a NULL pointer.
+ * getdadmfield -
+ * gets individual fields separated by skip in ptr.
*/
-#ifdef NOTDEF
-devalloc_t *
-getdadev(name)
- register char *name;
+char *
+getdadmfield(char *ptr, char *skip)
{
- register struct _dabuff *_da = _daalloc();
- devalloc_t *da;
- char line[BUFSIZ + 1];
+ static char *tptr = NULL;
+ char *pend;
- if (_da == 0)
- return (0);
- setdaent();
- if (!daf)
- return ((devalloc_t *)NULL);
- while (getdaline(line, sizeof (line), daf) != 0) {
- if ((da = interpret(line)) == NULL)
- continue;
- if (matchdev(&da, name)) {
- enddaent();
- return (da);
- }
- }
- enddaent();
- return ((devalloc_t *)NULL);
+ /* check for a continuing search */
+ if (ptr == NULL)
+ ptr = tptr;
+ /* check for source end */
+ if (ptr == NULL || *ptr == '\0')
+ return (NULL);
+ /* find terminator */
+ pend = strpbrk(ptr, skip);
+ /* terminate and set continuation pointer */
+ if (pend != NULL) {
+ *pend++ = '\0';
+ tptr = pend;
+ } else
+ tptr = NULL;
+ /*
+ * trim off any surrounding white space, return what's left
+ */
+
+ return (trim_white(ptr));
}
-
-#endif /* NOTDEF */
-
/*
- * getdanam(name) searches from the beginning of the file until a audit-name
- * matching "name" is found and returns a pointer to the particular structure
- * in which it was found. If an EOF or an error is encountered on reading,
- * these functions return a NULL pointer.
- */
-devalloc_t *
-getdanam(name)
- register char *name;
-{
- register struct _dabuff *_da = _daalloc();
- devalloc_t *da;
- char line[BUFSIZ + 1];
-
- if (_da == 0)
- return (0);
- setdaent();
- if (!daf)
- return ((devalloc_t *)NULL);
- while (getdaline(line, (int)sizeof (line), daf) != 0) {
- if ((da = interpret(line)) == NULL)
- continue;
- if (matchname(&da, name)) {
- enddaent();
- return (da);
- }
- }
- enddaent();
- return ((devalloc_t *)NULL);
-}
-
-
-/*
- * setdaent() essentially rewinds the device_allocate file to the begining.
+ * setdaent -
+ * rewinds the device_allocate file to the begining.
*/
void
-setdaent()
+setdaent(void)
{
- register struct _dabuff *_da = _daalloc();
+ struct _dabuff *_da = _daalloc();
- if (_da == 0)
+ if (_da == NULL)
return;
- if (daf == NULL) {
- daf = fopen(DEVALLOC, "r");
- } else
+ if (daf == NULL)
+ daf = fopen(DEVALLOC_FILE, "r");
+ else
rewind(daf);
}
-
/*
- * enddaent() may be called to close the device_allocate file when processing
- * is complete.
+ * enddaent -
+ * closes device_allocate file.
*/
void
-enddaent()
+enddaent(void)
{
- register struct _dabuff *_da = _daalloc();
+ struct _dabuff *_da = _daalloc();
- if (_da == 0)
+ if (_da == NULL)
return;
if (daf != NULL) {
(void) fclose(daf);
@@ -340,173 +261,294 @@
}
}
-
/*
- * setdafile(name) changes the default device_allocate file to "name" thus
- * allowing alternate device_allocate files to be used. Note: it does not
- * close the previous file . If this is desired, enddaent should be called
- * prior to it.
+ * setdafile -
+ * changes the default device_allocate file to the one specified.
+ * It does not close the previous file. If this is desired, enddaent
+ * should be called prior to setdafile.
*/
void
-setdafile(file)
-char *file;
+setdafile(char *file)
{
- register struct _dabuff *_da = _daalloc();
+ struct _dabuff *_da = _daalloc();
- if (_da == 0)
+ if (_da == NULL)
return;
if (daf != NULL) {
(void) fclose(daf);
daf = NULL;
}
- DEVALLOC = file;
+ DEVALLOC_FILE = file;
}
+void
+freedaent(devalloc_t *dap)
+{
+ if (dap == NULL)
+ return;
+ _kva_free(dap->da_devopts);
+ dap->da_devopts = NULL;
+}
/*
- * getdatype(tp) When first called, returns a pointer to the
- * first devalloc_t structure in the file with device-type matching
- * "tp"; thereafter, it returns a pointer to the next devalloc_t
- * structure in the file with device-type matching "tp".
- * Thus successive calls can be used to search the
- * entire file for entries having device-type matching "tp".
- * A null pointer is returned on error.
+ * getdaon -
+ * checks if device_allocate has string DEVICE_ALLOCATION=ON or
+ * DEVICE_ALLOCATION=OFF string in it.
+ * returns 1 if the string is DEVICE_ALLOCATION=ON, 0 if it is
+ * DEVICE_ALLOCATION=OFF, -1 if neither string present.
+ */
+int
+getdaon()
+{
+ int is_on = -1;
+ char line1[DA_BUFSIZE + 1];
+ struct _dabuff *_da = _daalloc();
+
+ setdaent();
+ if ((_da == NULL) || (daf == NULL)) {
+ enddaent();
+ return (is_on);
+ }
+ while (getdadmline(line1, (int)sizeof (line1), daf) != 0) {
+ if (strncmp(line1, DA_ON_STR, (strlen(DA_ON_STR) - 1)) == 0) {
+ is_on = 1;
+ break;
+ } else if (strncmp(line1, DA_OFF_STR,
+ (strlen(DA_OFF_STR) - 1)) == 0) {
+ is_on = 0;
+ break;
+ }
+ }
+ enddaent();
+
+ return (is_on);
+}
+
+/*
+ * getdaent -
+ * When first called, returns a pointer to the first devalloc_t
+ * structure in device_allocate; thereafter, it returns a pointer to the
+ * next devalloc_t structure in the file. Thus, successive calls can be
+ * used to search the entire file.
+ * call to getdaent should be bracketed by setdaent and enddaent.
+ * returns NULL on error.
*/
devalloc_t *
-getdatype(tp)
- char *tp;
+getdaent(void)
{
- register struct _dabuff *_da = _daalloc();
- char line1[BUFSIZ + 1];
- devalloc_t *da;
+ char line1[DA_BUFSIZE + 1];
+ devalloc_t *da;
+ struct _dabuff *_da = _daalloc();
+
+ if ((_da == 0) || (daf == NULL))
+ return (NULL);
- if (_da == 0)
- return (0);
- if (daf == NULL && (daf = fopen(DEVALLOC, "r")) == NULL) {
- return (NULL);
+ while (getdadmline(line1, (int)sizeof (line1), daf) != 0) {
+ if ((strncmp(line1, DA_ON_STR, (strlen(DA_ON_STR) - 1)) == 0) ||
+ (strncmp(line1, DA_OFF_STR, (strlen(DA_OFF_STR) - 1)) == 0))
+ continue;
+ if ((da = da_interpret(line1)) == NULL)
+ continue;
+ return (da);
}
- do {
- if (getdaline(line1, (int)sizeof (line1), daf) == 0)
- return (NULL);
- if ((da = interpret(line1)) == NULL)
- return (NULL);
- } while (strcmp(tp, da->da_devtype) != 0);
- return (da);
+ return (NULL);
}
-
/*
- * getdaent() When first called, returns a pointer to the first devalloc_t
- * structure in the file; thereafter, it returns a pointer to the next
- * devalloc_t structure in the file. Thus successive calls can be used to
- * search the entire file. A null pointer is returned on error.
+ * getdanam
+ * searches from the beginning of device_allocate for the device specified
+ * by its name.
+ * call to getdanam should be bracketed by setdaent and enddaent.
+ * returns pointer to devalloc_t for the device if it is found, else
+ * returns NULL if device not found or in case of error.
*/
devalloc_t *
-getdaent()
+getdanam(char *name)
{
- register struct _dabuff *_da = _daalloc();
- char line1[BUFSIZ + 1];
- devalloc_t *da;
+ char line[DA_BUFSIZE + 1];
+ devalloc_t *da;
+ struct _dabuff *_da = _daalloc();
- if (_da == 0)
- return (0);
- if (daf == NULL && (daf = fopen(DEVALLOC, "r")) == NULL) {
- return (NULL);
- }
- if (getdaline(line1, (int)sizeof (line1), daf) == 0)
+ if ((name == NULL) || (_da == 0) || (daf == NULL))
return (NULL);
- if ((da = interpret(line1)) == NULL)
- return (NULL);
- return (da);
+ while (getdadmline(line, (int)sizeof (line), daf) != 0) {
+ if (strstr(line, name) == NULL)
+ continue;
+ if ((da = da_interpret(line)) == NULL)
+ continue;
+ if (da_matchname(da, name)) {
+ enddaent();
+ return (da);
+ }
+ freedaent(da);
+ }
+
+ return (NULL);
}
-
/*
- * matchdev(dap,dev) The dev_list in the structure pointed to by "dap" is
- * searched for string "dev". If a match occures then a "1" is returned
- * otherwise a "0" is returned.
+ * getdatype -
+ * searches from the beginning of device_allocate for the device specified
+ * by its type.
+ * call to getdatype should be bracketed by setdaent and enddaent.
+ * returns pointer to devalloc_t for the device if it is found, else
+ * returns NULL if device not found or in case of error.
*/
-#ifdef NOTDEF
-static
-matchdev(dap, dev)
- devalloc_t **dap;
- char *dev;
+devalloc_t *
+getdatype(char *type)
{
- register struct _dabuff *_da = _daalloc();
- devalloc_t *da = *dap;
- char tmpdev[BUFSIZ + 1];
- int charcnt;
- int tmpcnt;
- char *cp;
- char *tcp;
- char *last;
+ char line1[DA_BUFSIZE + 1];
+ devalloc_t *da;
+ struct _dabuff *_da = _daalloc();
+
+ if ((type == NULL) || (_da == NULL) || (daf == NULL))
+ return (NULL);
- charcnt = strlen(dev);
- if (_da == 0)
+ while (getdadmline(line1, (int)sizeof (line1), daf) != 0) {
+ if (strstr(line1, type) == NULL)
+ continue;
+ if ((da = da_interpret(line1)) == NULL)
+ continue;
+ if (da_matchtype(da, type))
+ return (da);
+ freedaent(da);
+ }
+
+ return (NULL);
+}
+
+/*
+ * da_matchname -
+ * checks if the specified devalloc_t is for the device specified.
+ * returns 1 if it is, else returns 0.
+ */
+int
+da_matchname(devalloc_t *dap, char *name)
+{
+ if (dap->da_devname == NULL)
return (0);
- if (da->da_devlist == NULL)
+
+ return ((strcmp(dap->da_devname, name) == 0));
+}
+
+/*
+ * da_matchtype -
+ * checks if the specified devalloc_t is for the device type specified.
+ * returns 1 if match found, else, returns 0.
+ */
+int
+da_matchtype(devalloc_t *da, char *type)
+{
+ if (da->da_devtype == NULL)
return (0);
- (void) strcpy(tmpdev, da->da_devlist);
- tcp = tmpdev;
- while ((cp = strtok_r(tcp, " ", &last)) != NULL) {
- tcp = NULL;
- tmpcnt = strlen(cp);
- if (tmpcnt != charcnt)
- continue;
- if (strcmp(cp, dev) == 0)
- return (1);
- }
+
+ return ((strcmp(da->da_devtype, type) == 0));
+}
+
+/*
+ * da_match -
+ * calls da_matchname or da_matchdev as appropriate.
+ */
+int
+da_match(devalloc_t *dap, da_args *dargs)
+{
+ if (dargs->devinfo->devname)
+ return (da_matchname(dap, dargs->devinfo->devname));
+ else if (dargs->devinfo->devtype)
+ return (da_matchtype(dap, dargs->devinfo->devtype));
+
return (0);
}
-#endif /* NOTDEF */
/*
- * matchname(dap,name) The audit-name in the structure pointed to by "dap" is
- * searched for string "name". If a match occures then a "1" is returned
- * otherwise a "0" is returned.
- */
-static int
-matchname(dap, name)
- devalloc_t **dap;
- char *name;
-{
- register struct _dabuff *_da = _daalloc();
- devalloc_t *da = *dap;
-
- if (_da == 0)
- return (0);
- if (da->da_devname == NULL)
- return (0);
- if (strlen(da->da_devname) != strlen(name))
- return (0);
- if (strcmp(da->da_devname, name) == 0)
- return (1);
- return (0);
-}
-
-
-/*
- * interpret(val) string "val" is parsed and the pointers in a devalloc_t
- * structure are initialized to point to fields in "val". A pointer to this
- * structure is returned.
+ * da_interpret -
+ * parses val and initializes pointers in devalloc_t.
+ * returns pointer to parsed devalloc_t entry, else returns NULL on error.
*/
static devalloc_t *
-interpret(val)
-char *val;
+da_interpret(char *val)
{
- register struct _dabuff *_da = _daalloc();
+ struct _dabuff *_da = _daalloc();
+ char *opts;
+ int i;
+ kva_t *kvap;
+ kv_t *kvp;
+
+ if (_da == NULL)
+ return (NULL);
+
+ (void) strcpy(interpdaline, val);
+ interpdevalloc.da_devname = getdadmfield(interpdaline, KV_DELIMITER);
+ interpdevalloc.da_devtype = getdadmfield(NULL, KV_DELIMITER);
+ opts = getdadmfield(NULL, KV_DELIMITER);
+ (void) getdadmfield(NULL, KV_DELIMITER); /* reserved field */
+ interpdevalloc.da_devauth = getdadmfield(NULL, KV_DELIMITER);
+ interpdevalloc.da_devexec = getdadmfield(NULL, KV_DELIMITER);
+ interpdevalloc.da_devopts = NULL;
+ if (interpdevalloc.da_devname == NULL ||
+ interpdevalloc.da_devtype == NULL)
+ return (NULL);
+ if ((opts != NULL) &&
+ (strncmp(opts, DA_RESERVED, strlen(DA_RESERVED)) != 0)) {
+ interpdevalloc.da_devopts =
+ _str2kva(opts, KV_ASSIGN, KV_TOKEN_DELIMIT);
+ }
+ /* remove any extraneous whitespace in the options */
+ if ((kvap = interpdevalloc.da_devopts) != NULL) {
+ for (i = 0, kvp = kvap->data; i < kvap->length; i++, kvp++) {
+ (void) pack_white(kvp->key);
+ (void) pack_white(kvp->value);
+ }
+ }
- if (_da == 0)
- return (0);
- (void) strcpy(interpline, val);
- interpdevalloc.da_devname = getdafield(interpline);
- interpdevalloc.da_devtype = getdafield((char *)NULL);
- interpdevalloc.da_devmin = getdafield((char *)NULL);
- interpdevalloc.da_devmax = getdafield((char *)NULL);
- interpdevalloc.da_devauth = getdafield((char *)NULL);
- interpdevalloc.da_devexec = getdafield((char *)NULL);
+ if (system_labeled) {
+ /* if label range is not defined, use the default range. */
+ int i = 0, nlen = 0;
+ char *minstr = NULL, *maxstr = NULL;
+ kva_t *nkvap = NULL;
+ kv_t *ndata = NULL, *odata = NULL;
+ if (kvap == NULL) {
+ nlen = 2; /* minlabel, maxlabel */
+ } else {
+ nlen += kvap->length;
+ if ((minstr = kva_match(kvap, DAOPT_MINLABEL)) == NULL)
+ nlen++;
+ if ((maxstr = kva_match(kvap, DAOPT_MAXLABEL)) == NULL)
+ nlen++;
+ }
+ if ((minstr != NULL) && (maxstr != NULL))
+ /*
+ * label range provided; we don't need to construct
+ * default range.
+ */
+ goto out;
+ nkvap = _new_kva(nlen);
+ ndata = nkvap->data;
+ if (kvap != NULL) {
+ for (i = 0; i < kvap->length; i++) {
+ odata = kvap->data;
+ ndata[i].key = _strdup_null(odata[i].key);
+ ndata[i].value = _strdup_null(odata[i].value);
+ nkvap->length++;
+ }
+ }
+ if (minstr == NULL) {
+ ndata[i].key = strdup(DAOPT_MINLABEL);
+ ndata[i].value = strdup(DA_DEFAULT_MIN);
+ nkvap->length++;
+ i++;
+ }
+ if (maxstr == NULL) {
+ ndata[i].key = strdup(DAOPT_MAXLABEL);
+ ndata[i].value = strdup(DA_DEFAULT_MAX);
+ nkvap->length++;
+ }
+ interpdevalloc.da_devopts = nkvap;
+ }
+
+out:
return (&interpdevalloc);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libbsm/common/getdevicerange.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,109 @@
+/*
+ * 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 <stdlib.h>
+#include <errno.h>
+#include <tsol/label.h>
+#include <bsm/devices.h>
+
+
+/*
+ * getdevicerange
+ * Gets the minimum and maximum labels within which the device can
+ * be used. If label range is not specified for the device in
+ * device_allocate, defaults to admin_low and admin_high.
+ * Returns malloc'ed blrange pointer, or NULL on any error.
+ */
+blrange_t *
+getdevicerange(const char *dev)
+{
+ int err;
+ char *lstr;
+ devalloc_t *da;
+ devmap_t *dm;
+ blrange_t *range;
+
+ errno = 0;
+ if ((range = malloc(sizeof (blrange_t))) == NULL)
+ return (NULL);
+ if ((range->lower_bound = blabel_alloc()) == NULL) {
+ free(range);
+ return (NULL);
+ }
+ if ((range->upper_bound = blabel_alloc()) == NULL) {
+ blabel_free(range->lower_bound);
+ free(range);
+ return (NULL);
+ }
+
+ /*
+ * If an entry is found for the named device,
+ * return its label range.
+ */
+ setdaent();
+ if ((da = getdanam((char *)dev)) == NULL) {
+ setdmapent();
+ /* check for an actual device file */
+ if ((dm = getdmapdev((char *)dev)) != NULL) {
+ da = getdanam(dm->dmap_devname);
+ freedmapent(dm);
+ }
+ enddmapent();
+ }
+ enddaent();
+ if (da == NULL) {
+ bsllow(range->lower_bound);
+ bslhigh(range->upper_bound);
+ } else {
+ lstr = kva_match(da->da_devopts, DAOPT_MINLABEL);
+ if (lstr == NULL) {
+ bsllow(range->lower_bound);
+ } else if (stobsl(lstr, range->lower_bound, NO_CORRECTION,
+ &err) == 0) {
+ blabel_free(range->lower_bound);
+ blabel_free(range->upper_bound);
+ free(range);
+ errno = ENOTSUP;
+ return (NULL);
+ }
+ lstr = kva_match(da->da_devopts, DAOPT_MAXLABEL);
+ if (lstr == NULL) {
+ bslhigh(range->upper_bound);
+ } else if (stobsl(lstr, range->upper_bound, NO_CORRECTION,
+ &err) == 0) {
+ blabel_free(range->lower_bound);
+ blabel_free(range->upper_bound);
+ free(range);
+ errno = ENOTSUP;
+ return (NULL);
+ }
+ freedaent(da);
+ }
+
+ return (range);
+}
--- a/usr/src/lib/libbsm/common/getdment.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libbsm/common/getdment.c Fri Mar 24 12:29:20 2006 -0800
@@ -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,73 +19,423 @@
* 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"
-#include <stdio.h>
#include <string.h>
-#include <malloc.h>
+#include <stdlib.h>
#include <bsm/devices.h>
-#include <sys/errno.h>
+#include <bsm/devalloc.h>
+
+char *strtok_r(char *, const char *, char **);
-#define MAXINT 0x7fffffff;
+/* externs from getdaent.c */
+extern char *trim_white(char *);
+extern int pack_white(char *);
+extern char *getdadmfield(char *, char *);
+extern int getdadmline(char *, int, FILE *);
static struct _dmapbuff {
- devmap_t _NULLDM;
- FILE *_dmapf; /* pointer into /etc/security/device_maps */
- devmap_t _interpdevmap;
- char _interpline[BUFSIZ + 1];
- char *_DEVMAP;
+ FILE *_dmapf; /* for /etc/security/device_maps */
+ devmap_t _interpdevmap;
+ char _interpdmline[DA_BUFSIZE + 1];
+ char *_DEVMAP;
} *__dmapbuff;
-#define NULLDM (_dmap->_NULLDM)
-#define dmapf (_dmap->_dmapf)
-#define interpdevmap (_dmap->_interpdevmap)
-#define interpline (_dmap->_interpline)
-#define DEVMAP (_dmap->_DEVMAP)
-static devmap_t *interpret();
-static int matchdev();
-static int matchname();
+#define dmapf (_dmap->_dmapf)
+#define interpdevmap (_dmap->_interpdevmap)
+#define interpdmline (_dmap->_interpdmline)
+#define DEVMAPS_FILE (_dmap->_DEVMAP)
+
+devmap_t *dmap_interpret(char *, devmap_t *);
+static devmap_t *dmap_interpretf(char *, devmap_t *);
+static devmap_t *dmap_dlexpand(devmap_t *);
+
+int dmap_matchdev(devmap_t *, char *);
+int dmap_matchname(devmap_t *, char *);
+
+
+/*
+ * _dmapalloc -
+ * allocates common buffers and structures.
+ * returns pointer to the new structure, else returns NULL on error.
+ */
+static struct _dmapbuff *
+_dmapalloc(void)
+{
+ struct _dmapbuff *_dmap = __dmapbuff;
+
+ if (_dmap == NULL) {
+ _dmap = (struct _dmapbuff *)calloc((unsigned)1,
+ (unsigned)sizeof (*__dmapbuff));
+ if (_dmap == NULL)
+ return (NULL);
+ DEVMAPS_FILE = "/etc/security/device_maps";
+ dmapf = NULL;
+ __dmapbuff = _dmap;
+ }
+
+ return (_dmap);
+}
+
+/*
+ * setdmapent -
+ * rewinds the device_maps file to the beginning.
+ */
+void
+setdmapent(void)
+{
+ struct _dmapbuff *_dmap = _dmapalloc();
+
+ if (_dmap == NULL)
+ return;
+ if (dmapf == NULL)
+ dmapf = fopen(DEVMAPS_FILE, "r");
+ else
+ rewind(dmapf);
+}
+
+/*
+ * enddmapent -
+ * closes device_maps file.
+ */
+void
+enddmapent(void)
+{
+ struct _dmapbuff *_dmap = _dmapalloc();
+
+ if (_dmap == NULL)
+ return;
+ if (dmapf != NULL) {
+ (void) fclose(dmapf);
+ dmapf = NULL;
+ }
+}
+
+void
+freedmapent(devmap_t *dmap)
+{
+ char **darp;
+
+ if ((darp = dmap->dmap_devarray) != NULL) {
+ while (*darp != NULL)
+ free(*darp++);
+ free(dmap->dmap_devarray);
+ dmap->dmap_devarray = NULL;
+ }
+}
+
+/*
+ * setdmapfile -
+ * changes the default device_maps file to the one specified.
+ * It does not close the previous file. If this is desired, enddmapent
+ * should be called prior to setdampfile.
+ */
+void
+setdmapfile(char *file)
+{
+ struct _dmapbuff *_dmap = _dmapalloc();
+
+ if (_dmap == NULL)
+ return;
+ if (dmapf != NULL) {
+ (void) fclose(dmapf);
+ dmapf = NULL;
+ }
+ DEVMAPS_FILE = file;
+}
+
+/*
+ * getdmapent -
+ * When first called, returns a pointer to the first devmap_t structure
+ * in device_maps; thereafter, it returns a pointer to the next devmap_t
+ * structure in the file. Thus successive calls can be used to read the
+ * entire file.
+ * call to getdmapent should be bracketed by setdmapent and enddmapent.
+ * returns pointer to devmap_t found, else returns NULL if no entry found
+ * or on error.
+ */
+devmap_t *
+getdmapent(void)
+{
+ devmap_t *dmap;
+ struct _dmapbuff *_dmap = _dmapalloc();
+
+ if ((_dmap == 0) || (dmapf == NULL))
+ return (NULL);
+
+ while (getdadmline(interpdmline, (int)sizeof (interpdmline),
+ dmapf) != 0) {
+ if ((dmap = dmap_interpret(interpdmline,
+ &interpdevmap)) == NULL)
+ continue;
+ return (dmap);
+ }
+
+ return (NULL);
+}
+
+/*
+ * getdmapnam -
+ * searches from the beginning of device_maps for the device specified by
+ * its name.
+ * call to getdmapnam should be bracketed by setdmapent and enddmapent.
+ * returns pointer to devmapt_t for the device if it is found, else
+ * returns NULL if device not found or in case of error.
+ */
+devmap_t *
+getdmapnam(char *name)
+{
+ devmap_t *dmap;
+ struct _dmapbuff *_dmap = _dmapalloc();
+
+ if ((name == NULL) || (_dmap == 0) || (dmapf == NULL))
+ return (NULL);
+
+ while (getdadmline(interpdmline, (int)sizeof (interpdmline),
+ dmapf) != 0) {
+ if (strstr(interpdmline, name) == NULL)
+ continue;
+ if ((dmap = dmap_interpretf(interpdmline,
+ &interpdevmap)) == NULL)
+ continue;
+ if (dmap_matchname(dmap, name)) {
+ if ((dmap = dmap_dlexpand(dmap)) == NULL)
+ continue;
+ enddmapent();
+ return (dmap);
+ }
+ freedmapent(dmap);
+ }
+
+ return (NULL);
+}
+
/*
- * trim_white(ptr) trims off leading and trailing white space from a NULL
- * terminated string pointed to by "ptr". The leading white space is skipped
- * by moving the pointer forward. The trailing white space is removed by
- * nulling the white space characters. The pointer is returned to the white
- * string. If the resulting string is null in length then a NULL pointer is
- * returned. If "ptr" is NULL then a NULL pointer is returned.
+ * getdmapdev -
+ * searches from the beginning of device_maps for the device specified by
+ * its logical name.
+ * call to getdmapdev should be bracketed by setdmapent and enddmapent.
+ * returns pointer to the devmap_t for the device if device is found,
+ * else returns NULL if device not found or on error.
+ */
+devmap_t *
+getdmapdev(char *dev)
+{
+ devmap_t *dmap;
+ struct _dmapbuff *_dmap = _dmapalloc();
+
+ if ((dev == NULL) || (_dmap == 0) || (dmapf == NULL))
+ return (NULL);
+
+ while (getdadmline(interpdmline, (int)sizeof (interpdmline),
+ dmapf) != 0) {
+ if ((dmap = dmap_interpret(interpdmline,
+ &interpdevmap)) == NULL)
+ continue;
+ if (dmap_matchdev(dmap, dev)) {
+ enddmapent();
+ return (dmap);
+ }
+ freedmapent(dmap);
+ }
+
+ return (NULL);
+}
+
+/*
+ * getdmaptype -
+ * searches from the beginning of device_maps for the device specified by
+ * its type.
+ * call to getdmaptype should be bracketed by setdmapent and enddmapent.
+ * returns pointer to devmap_t found, else returns NULL if no entry found
+ * or on error.
+ */
+devmap_t *
+getdmaptype(char *type)
+{
+ devmap_t *dmap;
+ struct _dmapbuff *_dmap = _dmapalloc();
+
+ if ((type == NULL) || (_dmap == 0) || (dmapf == NULL))
+ return (NULL);
+
+ while (getdadmline(interpdmline, (int)sizeof (interpdmline),
+ dmapf) != 0) {
+ if ((dmap = dmap_interpretf(interpdmline,
+ &interpdevmap)) == NULL)
+ continue;
+ if (dmap->dmap_devtype != NULL &&
+ strcmp(type, dmap->dmap_devtype) == 0) {
+ if ((dmap = dmap_dlexpand(dmap)) == NULL)
+ continue;
+ return (dmap);
+ }
+ freedmapent(dmap);
+ }
+
+ return (NULL);
+}
+
+/*
+ * dmap_matchdev -
+ * checks if the specified devmap_t is for the device specified.
+ * returns 1 if it is, else returns 0.
+ */
+int
+dmap_matchdev(devmap_t *dmap, char *dev)
+{
+ char **dva;
+ char *dv;
+
+ if (dmap->dmap_devarray == NULL)
+ return (0);
+ for (dva = dmap->dmap_devarray; (dv = *dva) != NULL; dva ++) {
+ if (strcmp(dv, dev) == 0)
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+ * dmap_matchtype -
+ * checks if the specified devmap_t is for the device specified.
+ * returns 1 if it is, else returns 0.
+ */
+int
+dmap_matchtype(devmap_t *dmap, char *type)
+{
+ if ((dmap->dmap_devtype == NULL) || (type == NULL))
+ return (0);
+
+ return ((strcmp(dmap->dmap_devtype, type) == 0));
+}
+
+/*
+ * dmap_matchname -
+ * checks if the specified devmap_t is for the device specified.
+ * returns 1 if it is, else returns 0.
+ */
+int
+dmap_matchname(devmap_t *dmap, char *name)
+{
+ if (dmap->dmap_devname == NULL)
+ return (0);
+
+ return ((strcmp(dmap->dmap_devname, name) == 0));
+}
+
+/*
+ * dm_match -
+ * calls dmap_matchname or dmap_matchtype as appropriate.
+ */
+int
+dm_match(devmap_t *dmap, da_args *dargs)
+{
+ if (dargs->devinfo->devname)
+ return (dmap_matchname(dmap, dargs->devinfo->devname));
+ else if (dargs->devinfo->devtype)
+ return (dmap_matchtype(dmap, dargs->devinfo->devtype));
+
+ return (0);
+}
+
+/*
+ * dmap_interpret -
+ * calls dmap_interpretf and dmap_dlexpand to parse devmap_t line.
+ * returns pointer to parsed devmapt_t entry, else returns NULL on error.
+ */
+devmap_t *
+dmap_interpret(char *val, devmap_t *dm)
+{
+ if (dmap_interpretf(val, dm) == NULL)
+ return (NULL);
+
+ return (dmap_dlexpand(dm));
+}
+
+/*
+ * dmap_interpretf -
+ * parses string "val" and initializes pointers in the given devmap_t to
+ * fields in "val".
+ * returns pointer to updated devmap_t.
+ */
+static devmap_t *
+dmap_interpretf(char *val, devmap_t *dm)
+{
+ dm->dmap_devname = getdadmfield(val, KV_TOKEN_DELIMIT);
+ dm->dmap_devtype = getdadmfield(NULL, KV_TOKEN_DELIMIT);
+ dm->dmap_devlist = getdadmfield(NULL, KV_TOKEN_DELIMIT);
+ dm->dmap_devarray = NULL;
+ if (dm->dmap_devname == NULL ||
+ dm->dmap_devtype == NULL ||
+ dm->dmap_devlist == NULL)
+ return (NULL);
+
+ return (dm);
+}
+
+/*
+ * dmap_dlexpand -
+ * expands dmap_devlist of the form `devlist_generate`
+ * returns unexpanded form if there is no '\`' or in case of error.
+ */
+static devmap_t *
+dmap_dlexpand(devmap_t *dmp)
+{
+ char tmplist[DA_BUFSIZE + 1];
+ char *cp, *cpl, **darp;
+ int count;
+ FILE *expansion;
+
+ dmp->dmap_devarray = NULL;
+ if (dmp->dmap_devlist == NULL)
+ return (NULL);
+ if (*(dmp->dmap_devlist) != '`') {
+ (void) strcpy(tmplist, dmp->dmap_devlist);
+ } else {
+ (void) strcpy(tmplist, dmp->dmap_devlist + 1);
+ if ((cp = strchr(tmplist, '`')) != NULL)
+ *cp = '\0';
+ if ((expansion = popen(tmplist, "r")) == NULL)
+ return (NULL);
+ count = fread(tmplist, 1, sizeof (tmplist) - 1, expansion);
+ (void) pclose(expansion);
+ tmplist[count] = '\0';
+ }
+
+ /* cleanup the list */
+ count = pack_white(tmplist);
+ dmp->dmap_devarray = darp =
+ (char **)malloc((count + 2) * sizeof (char *));
+ if (darp == NULL)
+ return (NULL);
+ cp = tmplist;
+ while ((cp = strtok_r(cp, " ", &cpl)) != NULL) {
+ *darp = strdup(cp);
+ if (*darp == NULL) {
+ freedmapent(dmp);
+ return (NULL);
+ }
+ darp++;
+ cp = NULL;
+ }
+ *darp = NULL;
+
+ return (dmp);
+}
+
+/*
+ * dmapskip -
+ * scans input string to find next colon or end of line.
+ * returns pointer to next char.
*/
static char *
-trim_white(char *ptr)
-{
- register char *tptr;
- register int cnt;
- if (ptr == NULL)
- return (NULL);
- while ((*ptr == ' ') || (*ptr == '\t')) {
- ptr++;
- }
- cnt = strlen(ptr);
- if (cnt != 0) {
- tptr = ptr + cnt - 1;
- while ((*tptr == ' ') || (*tptr == '\t')) {
- *tptr = '\0';
- tptr--;
- }
- }
- if (*ptr == NULL)
- return (NULL);
- return (ptr);
-}
-/*
- * scan string pointed to by pointer "p"
- * find next colin or end of line. Null it and
- * return pointer to next char.
- */
-static char *
-dmapskip(register char *p)
+dmapskip(char *p)
{
while (*p && *p != ':' && *p != '\n')
++p;
@@ -94,99 +443,32 @@
*p = '\0';
else if (*p != '\0')
*p++ = '\0';
+
return (p);
}
+
/*
- * scan string pointed to by pointer "p"
- * find next colin or end of line. Null it and
- * return pointer to next char.
+ * dmapdskip -
+ * scans input string to find next space or end of line.
+ * returns pointer to next char.
*/
static char *
-dmapdskip(register char *p)
+dmapdskip(p)
+ register char *p;
{
while (*p && *p != ' ' && *p != '\n')
++p;
if (*p != '\0')
*p++ = '\0';
+
return (p);
}
-/*
- * _dmapalloc() allocates common buffers and structures used by the device
- * maps library routines. Then returns a pointer to a structure. The
- * returned pointer will be null if there is an error condition.
- */
-static struct _dmapbuff *
-_dmapalloc(void)
-{
- register struct _dmapbuff *_dmap = __dmapbuff;
-
- if (_dmap == 0) {
- _dmap = (struct _dmapbuff *)
- calloc((unsigned)1, (unsigned)sizeof (*__dmapbuff));
- if (_dmap == 0)
- return (0);
- DEVMAP = "/etc/security/device_maps";
- __dmapbuff = _dmap;
- }
- return (__dmapbuff);
-}
-/*
- * getdmapline(buff,len,stream) reads one device maps line from "stream" into
- * "buff" on "len" bytes. Continued lines from "stream" are concatinated
- * into one line in "buff". Comments are removed from "buff". The number of
- * characters in "buff" is returned. If no characters are read or an error
- * occured then "0" is returned
- */
-static int
-getdmapline(char *buff, int len, FILE *stream)
-{
- register struct _dmapbuff *_dmap = _dmapalloc();
- char *cp;
- char *ccp;
- size_t tmpcnt;
- int charcnt = 0;
- int fileerr = 0;
- int contline;
- if (_dmap == 0)
- return (0);
- do {
- cp = buff;
- *cp = NULL;
- do {
- if ((len - charcnt <= 1) ||
- (fgets(cp, len - charcnt, stream) == NULL)) {
- fileerr = 1;
- break;
- }
- ccp = strpbrk(cp, "\\\n");
- if (ccp != NULL) {
- if (*ccp == '\\')
- contline = 1;
- else
- contline = 0;
- *ccp = NULL;
- }
- tmpcnt = strlen(cp);
- if (tmpcnt != 0) {
- cp += tmpcnt;
- charcnt += tmpcnt;
- }
- } while ((contline) || (charcnt == 0));
- ccp = strpbrk(buff, "#");
- if (ccp != NULL)
- *ccp = NULL;
- charcnt = strlen(buff);
- } while ((fileerr == 0) && (charcnt == 0));
- if (fileerr && !charcnt)
- return (0);
- else
- return (charcnt);
-}
-char
-*getdmapfield(char *ptr)
+char *
+getdmapfield(char *ptr)
{
static char *tptr;
+
if (ptr == NULL)
ptr = tptr;
if (ptr == NULL)
@@ -197,10 +479,12 @@
return (NULL);
if (*ptr == NULL)
return (NULL);
+
return (ptr);
}
-char
-*getdmapdfield(char *ptr)
+
+char *
+getdmapdfield(char *ptr)
{
static char *tptr;
if (ptr != NULL) {
@@ -215,251 +499,6 @@
return (NULL);
if (*ptr == NULL)
return (NULL);
+
return (ptr);
}
-/*
- * getdmapdev(dev) searches from the beginning of the file until a logical
- * device matching "dev" is found and returns a pointer to the particular
- * structure in which it was found. If an EOF or an error is encountered on
- * reading, these functions return a NULL pointer.
- */
-devmap_t *
-getdmapdev(register char *name)
-{
- register struct _dmapbuff *_dmap = _dmapalloc();
- devmap_t *dmap;
- char line[BUFSIZ + 1];
-
- if (_dmap == 0)
- return (0);
- setdmapent();
- if (!dmapf)
- return (NULL);
- while (getdmapline(line, (int)sizeof (line), dmapf) != 0) {
- if ((dmap = interpret(line)) == NULL)
- continue;
- if (matchdev(&dmap, name)) {
- enddmapent();
- return (dmap);
- }
- }
- enddmapent();
- return (NULL);
-}
-/*
- * getdmapnam(name) searches from the beginning of the file until a audit-name
- * matching "name" is found and returns a pointer to the particular structure
- * in which it was found. If an EOF or an error is encountered on reading,
- * these functions return a NULL pointer.
- */
-devmap_t *
-getdmapnam(register char *name)
-{
- register struct _dmapbuff *_dmap = _dmapalloc();
- devmap_t *dmap;
- char line[BUFSIZ + 1];
-
- if (_dmap == 0)
- return (0);
- setdmapent();
- if (!dmapf)
- return (NULL);
- while (getdmapline(line, (int)sizeof (line), dmapf) != 0) {
- if ((dmap = interpret(line)) == NULL)
- continue;
- if (matchname(&dmap, name)) {
- enddmapent();
- return (dmap);
- }
- }
- enddmapent();
- return (NULL);
-}
-
-/*
- * setdmapent() essentially rewinds the device_maps file to the begining.
- */
-
-void
-setdmapent(void)
-{
- register struct _dmapbuff *_dmap = _dmapalloc();
-
-
- if (_dmap == 0)
- return;
-
- if (dmapf == NULL) {
- dmapf = fopen(DEVMAP, "r");
- } else
- rewind(dmapf);
-}
-
-
-/*
- * enddmapent() may be called to close the device_maps file when processing
- * is complete.
- */
-
-void
-enddmapent(void)
-{
- register struct _dmapbuff *_dmap = _dmapalloc();
-
- if (_dmap == 0)
- return;
- if (dmapf != NULL) {
- (void) fclose(dmapf);
- dmapf = NULL;
- }
-}
-
-
-/*
- * setdmapfile(name) changes the default device_maps file to "name" thus
- * allowing alternate device_maps files to be used. Note: it does not
- * close the previous file . If this is desired, enddmapent should be called
- * prior to it.
- */
-void
-setdmapfile(char *file)
-{
- register struct _dmapbuff *_dmap = _dmapalloc();
-
- if (_dmap == 0)
- return;
- if (dmapf != NULL) {
- (void) fclose(dmapf);
- dmapf = NULL;
- }
- DEVMAP = file;
-}
-/*
- * getdmaptype(tp) When first called, returns a pointer to the
- * first devmap_t structure in the file with device-type matching
- * "tp"; thereafter, it returns a pointer to the next devmap_t
- * structure in the file with device-type matching "tp".
- * Thus successive calls can be used to search the
- * entire file for entries having device-type matching "tp".
- * A null pointer is returned on error.
- */
-devmap_t *
-getdmaptype(char *tp)
-{
- register struct _dmapbuff *_dmap = _dmapalloc();
- char line1[BUFSIZ + 1];
- devmap_t *dmap;
-
- if (_dmap == 0)
- return (0);
- if (dmapf == NULL && (dmapf = fopen(DEVMAP, "r")) == NULL) {
- return (NULL);
- }
- do {
- if (getdmapline(line1, (int)sizeof (line1), dmapf) == 0)
- return (NULL);
-
- if ((dmap = interpret(line1)) == NULL)
- return (NULL);
- } while (strcmp(tp, dmap->dmap_devtype) != 0);
- return (dmap);
-}
-
-/*
- * getdmapent() When first called, returns a pointer to the first devmap_t
- * structure in the file; thereafter, it returns a pointer to the next devmap_t
- * structure in the file. Thus successive calls can be used to search the
- * entire file. A null pointer is returned on error.
- */
-devmap_t *
-getdmapent(void)
-{
- register struct _dmapbuff *_dmap = _dmapalloc();
- char line1[BUFSIZ + 1];
- devmap_t *dmap;
-
- if (_dmap == 0)
- return (0);
- if (dmapf == NULL && (dmapf = fopen(DEVMAP, "r")) == NULL) {
- return (NULL);
- }
- if (getdmapline(line1, (int)sizeof (line1), dmapf) == 0)
- return (NULL);
-
- if ((dmap = interpret(line1)) == NULL)
- return (NULL);
- return (dmap);
-}
-/*
- * matchdev(dmapp,dev) The dev_list in the structure pointed to by "dmapp" is
- * searched for string "dev". If a match occures then a "1" is returned
- * otherwise a "0" is returned.
- */
-static int
-matchdev(devmap_t **dmapp, char *dev)
-{
- register struct _dmapbuff *_dmap = _dmapalloc();
- devmap_t *dmap = *dmapp;
- char tmpdev[BUFSIZ + 1];
- int charcnt;
- int tmpcnt;
- char *cp;
- char *tcp;
- char *last;
- charcnt = strlen(dev);
- if (_dmap == 0)
- return (0);
- if (dmap->dmap_devlist == NULL)
- return (0);
- (void) strcpy(tmpdev, dmap->dmap_devlist);
- tcp = tmpdev;
- while ((cp = strtok_r(tcp, " ", &last)) != NULL) {
- tcp = NULL;
- tmpcnt = strlen(cp);
- if (tmpcnt != charcnt)
- continue;
- if (strcmp(cp, dev) == 0)
- return (1);
- }
- return (0);
-}
-/*
- * matchname(dmapp,name) The audit-name in the structure pointed to by "dmapp"
- * is searched for string "name". If a match occures then a "1" is returned
- * otherwise a "0" is returned.
- */
-static int
-matchname(devmap_t **dmapp, char *name)
-{
- register struct _dmapbuff *_dmap = _dmapalloc();
- devmap_t *dmap = *dmapp;
-
- if (_dmap == 0)
- return (0);
- if (dmap->dmap_devname == NULL)
- return (0);
- if (strlen(dmap->dmap_devname) != strlen(name))
- return (0);
- if (strcmp(dmap->dmap_devname, name) == 0)
- return (1);
- return (0);
-}
-/*
- * interpret(val) string "val" is parsed and the pointers in a devmap_t
- * structure are initialized to point to fields in "val". A pointer to this
- * structure is returned.
- */
-static devmap_t *
-interpret(char *val)
-{
- register struct _dmapbuff *_dmap = _dmapalloc();
-
- if (_dmap == 0)
- return (0);
- (void) strcpy(interpline, val);
- interpdevmap.dmap_devname = getdmapfield(interpline);
- interpdevmap.dmap_devtype = getdmapfield((char *)NULL);
- interpdevmap.dmap_devlist = getdmapfield((char *)NULL);
-
- return (&interpdevmap);
-}
--- a/usr/src/lib/libbsm/common/llib-lbsm Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libbsm/common/llib-lbsm Fri Mar 24 12:29:20 2006 -0800
@@ -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,12 +22,13 @@
/* PROTOLIB1 */
/*
- * Copyright 2003 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"
#include <bsm/devices.h>
+#include <bsm/devalloc.h>
#include <bsm/audit.h>
#include <bsm/libbsm.h>
#include <bsm/audit_record.h>
--- a/usr/src/lib/libbsm/mkhdr.sh Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libbsm/mkhdr.sh Fri Mar 24 12:29:20 2006 -0800
@@ -3,9 +3,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,8 +20,12 @@
# CDDL HEADER END
#
#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
# ident "%Z%%M% %I% %E% SMI"
#
+
# Automagically generate the audit_uevents.h header file.
#
DATABASE=audit_event.txt
@@ -30,8 +33,8 @@
cat <<EOF > $HEADER_FILE
/*
- * Copyright (c) 1993-2001, Sun Microsystems, Inc.
- * All Rights Reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#ifndef _BSM_AUDIT_UEVENTS_H
@@ -57,12 +60,31 @@
nawk -F: '{if ((NF == 4) && substr($1,0,1) != "#")
if ($1 >= 2048) {
- printf("#define %s ",$2)
- if (length($2) < 8)
- printf(" ")
- if (length($2) < 16)
- printf(" ")
- printf("%s /* =%s %s */\n",$1,$4,$3)
+ # compute total output line length first
+ tlen = length($2);
+ llen = 8 + tlen;
+ llen += 8 - (llen % 8);
+ if (llen < 32)
+ llen = 32;
+ llen += length($1);
+ llen += 8 - (llen % 8);
+ llen += 5 + length($4) + length($3) + 3;
+
+ # if line is too long, then print the comment first
+ if (llen > 80)
+ printf("/* =%s %s */\n", $4, $3);
+
+ printf("#define\t%s\t", $2)
+ if (tlen < 8)
+ printf("\t");
+ if (tlen < 16)
+ printf("\t")
+ printf("%s", $1);
+
+ if (llen > 80)
+ printf("\n");
+ else
+ printf("\t/* =%s %s */\n", $4, $3);
}
}' \
< $DATABASE >> $HEADER_FILE
--- a/usr/src/lib/libbsm/spec/Makefile.targ Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libbsm/spec/Makefile.targ Fri Mar 24 12:29:20 2006 -0800
@@ -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 (c) 1998-1999 by Sun Microsystems, Inc.
-# All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
#
# lib/libbsm/spec/Makefile.targ
@@ -36,6 +37,7 @@
audit.o \
auditon.o \
auditsvc.o \
+ devalloc.o \
exceptions.o \
getacinfo.o \
getauclassent.o \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libbsm/spec/devalloc.spec Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,220 @@
+#
+# 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"
+#
+# lib/libbsm/spec/devalloc.spec
+
+function getdadmline
+include <bsm/devices.h>
+declaration int getdadmline(char *, int, FILE *)
+version SUNWprivate_1.1
+end
+
+function getdmapdfield
+include <bsm/devices.h>
+declaration char *getdmapdfield(char *)
+version SUNWprivate_1.1
+end
+
+function setdaent
+include <bsm/devices.h>
+declaration void setdaent(void)
+version SUNWprivate_1.1
+end
+
+function enddaent
+include <bsm/devices.h>
+declaration void enddaent(void)
+version SUNWprivate_1.1
+end
+
+function setdafile
+include <bsm/devices.h>
+declaration void setdafile(char *)
+version SUNWprivate_1.1
+end
+
+function freedaent
+include <bsm/devices.h>
+declaration void freedaent(devalloc_t *)
+version SUNWprivate_1.1
+end
+
+function getdaent
+include <bsm/devices.h>
+declaration devalloc_t *getdaent(void)
+version SUNWprivate_1.1
+end
+
+function getdanam
+include <bsm/devices.h>
+declaration devalloc_t *getdanam(char *)
+version SUNWprivate_1.1
+end
+
+function getdatype
+include <bsm/devices.h>
+declaration devalloc_t *getdatype(char *)
+version SUNWprivate_1.1
+end
+
+function setdmapent
+include <bsm/devices.h>
+declaration void setdmapent(void)
+version SUNWprivate_1.1
+end
+
+function enddmapent
+include <bsm/devices.h>
+declaration void enddmapent(void)
+version SUNWprivate_1.1
+end
+
+function setdmapfile
+include <bsm/devices.h>
+declaration void setdmapfile(char *)
+version SUNWprivate_1.1
+end
+
+function freedmapent
+include <bsm/devices.h>
+declaration void freedmapent(devmap_t *)
+version SUNWprivate_1.1
+end
+
+function getdmapent
+include <bsm/devices.h>
+declaration devmap_t *getdmapent(void)
+version SUNWprivate_1.1
+end
+
+function getdmapnam
+include <bsm/devices.h>
+declaration devmap_t *getdmapnam(char *)
+version SUNWprivate_1.1
+end
+
+function getdmapdev
+include <bsm/devices.h>
+declaration devmap_t *getdmapdev(char *)
+version SUNWprivate_1.1
+end
+
+function getdmaptype
+include <bsm/devices.h>
+declaration devmap_t *getdmaptype(char *)
+version SUNWprivate_1.1
+end
+
+function getdmapfield
+include <bsm/devices.h>
+declaration char *getdmapfield(char *)
+version SUNWprivate_1.1
+end
+
+function setdadefent
+include <bsm/devalloc.h>
+declaration void setdadefent(void)
+version SUNWprivate_1.1
+end
+
+function enddadefent
+include <bsm/devalloc.h>
+declaration void enddadefent(void)
+version SUNWprivate_1.1
+end
+
+function freedadefent
+include <bsm/devalloc.h>
+declaration void freedadefent(da_defs_t *)
+version SUNWprivate_1.1
+end
+
+function getdadefent
+include <bsm/devalloc.h>
+declaration da_defs_t *getdadefent(void)
+version SUNWprivate_1.1
+end
+
+function getdadeftype
+include <bsm/devalloc.h>
+declaration da_defs_t *getdadeftype(char *)
+version SUNWprivate_1.1
+end
+
+function da_is_on
+include <bsm/devalloc.h>
+declaration int da_is_on(void)
+version SUNWprivate_1.1
+end
+
+function da_check_logindevperm
+include <bsm/devalloc.h>
+declaration int da_check_logindevperm(char *)
+version SUNWprivate_1.1
+end
+
+function da_open_devdb
+include <bsm/devalloc.h>
+declaration int da_open_devdb(char *, FILE **, FILE **, int)
+version SUNWprivate_1.1
+end
+
+function da_update_device
+include <bsm/devalloc.h>
+declaration int da_update_device(da_args *)
+version SUNWprivate_1.1
+end
+
+function da_update_defattrs
+include <bsm/devalloc.h>
+declaration int da_update_defattrs(da_args *)
+version SUNWprivate_1.1
+end
+
+function da_add_list
+include <bsm/devalloc.h>
+declaration int da_add_list(devlist_t *, char *, int, int)
+version SUNWprivate_1.1
+end
+
+function da_remove_list
+include <bsm/devalloc.h>
+declaration int da_remove_list(devlist_t *, char *, int, char *, int)
+version SUNWprivate_1.1
+end
+
+function da_print_device
+include <bsm/devalloc.h>
+declaration void da_print_device(int, devlist_t *)
+version SUNWprivate_1.1
+end
+
+function getdevicerange
+include <sys/tsol/label.h> <bsm/devices.h>
+declaration int getdevicerange(const char *, brange_t *);
+version SUNWprivate_1.1
+end
--- a/usr/src/lib/libbsm/spec/private.spec Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libbsm/spec/private.spec Fri Mar 24 12:29:20 2006 -0800
@@ -242,6 +242,18 @@
version SUNWprivate_1.1
end
+function au_to_mylabel
+include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
+declaration token_t *au_to_mylabel(void)
+version SUNWprivate_1.1
+end
+
+function au_to_label
+include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
+declaration token_t *au_to_label(bslabel_t *label)
+version SUNWprivate_1.1
+end
+
function audit_allocate_argv
include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
declaration int audit_allocate_argv(int flg, int argc, char *argv[])
@@ -644,18 +656,6 @@
version SUNWprivate_1.1
end
-function enddaent
-include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
-declaration void enddaent(void)
-version SUNWprivate_1.1
-end
-
-function enddmapent
-include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
-declaration void enddmapent(void)
-version SUNWprivate_1.1
-end
-
function _openac
include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>
declaration au_acinfo_t *_openac(char *)
@@ -704,96 +704,6 @@
version SUNWprivate_1.1
end
-function getdadfield
-include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
-declaration char *getdadfield(char *ptr)
-version SUNWprivate_1.1
-end
-
-function getdaent
-include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
-declaration devalloc_t *getdaent(void)
-version SUNWprivate_1.1
-end
-
-function getdafield
-include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
-declaration char *getdafield(char *ptr)
-version SUNWprivate_1.1
-end
-
-function getdanam
-include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
-declaration devalloc_t *getdanam(char *name)
-version SUNWprivate_1.1
-end
-
-function getdatype
-include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
-declaration devalloc_t *getdatype(char *tp)
-version SUNWprivate_1.1
-end
-
-function getdmapdev
-include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
-declaration devmap_t *getdmapdev(char *name)
-version SUNWprivate_1.1
-end
-
-function getdmapdfield
-include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
-declaration char *getdmapdfield(char *ptr)
-version SUNWprivate_1.1
-end
-
-function getdmapent
-include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
-declaration devmap_t *getdmapent(void)
-version SUNWprivate_1.1
-end
-
-function getdmapfield
-include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
-declaration char *getdmapfield(char *ptr)
-version SUNWprivate_1.1
-end
-
-function getdmapnam
-include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
-declaration devmap_t *getdmapnam(char *name)
-version SUNWprivate_1.1
-end
-
-function getdmaptype
-include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
-declaration devmap_t *getdmaptype(char *tp)
-version SUNWprivate_1.1
-end
-
-function setdaent
-include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
-declaration void setdaent(void)
-version SUNWprivate_1.1
-end
-
-function setdafile
-include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
-declaration void setdafile(char *file)
-version SUNWprivate_1.1
-end
-
-function setdmapent
-include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
-declaration void setdmapent(void)
-version SUNWprivate_1.1
-end
-
-function setdmapfile
-include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
-declaration void setdmapfile(char *file)
-version SUNWprivate_1.1
-end
-
function audit_at_create
include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
version SUNWprivate_1.1
@@ -1124,3 +1034,15 @@
ENXIO EPERM EWOULDBLOCK
exception $return == -1
end
+
+function au_to_privset
+include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
+declaration token_t *au_to_privset(const char *priv_type, const priv_set_t *privilege)
+version SUNWprivate_1.1
+end
+
+function au_to_uauth
+include <sys/types.h>, <bsm/audit.h>, <bsm/libbsm.h>, <bsm/audit_record.h>, <bsm/devices.h>, <pwd.h>
+declaration token_t *au_to_uauth(char *text)
+version SUNWprivate_1.1
+end
--- a/usr/src/lib/libc/amd64/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libc/amd64/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -772,6 +772,7 @@
getpeerucred.o \
inst_sync.o \
issetugid.o \
+ label.o \
libc_link.o \
libc_open.o \
lockf.o \
--- a/usr/src/lib/libc/i386/Makefile.com Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libc/i386/Makefile.com Fri Mar 24 12:29:20 2006 -0800
@@ -811,6 +811,7 @@
getpeerucred.o \
inst_sync.o \
issetugid.o \
+ label.o \
libc_link.o \
libc_open.o \
lockf.o \
--- a/usr/src/lib/libc/inc/synonyms.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libc/inc/synonyms.h Fri Mar 24 12:29:20 2006 -0800
@@ -481,6 +481,7 @@
#define isphonogram _isphonogram
#define issetugid _issetugid
#define isspecial _isspecial
+#define is_system_labeled _is_system_labeled
#define iswalnum _iswalnum
#define iswalpha _iswalpha
#define iswcntrl _iswcntrl
@@ -1039,6 +1040,7 @@
#define ucred_getegid _ucred_getegid
#define ucred_geteuid _ucred_geteuid
#define ucred_getgroups _ucred_getgroups
+#define ucred_getlabel _ucred_getlabel
#define ucred_getpflags _ucred_getpflags
#define ucred_getpid _ucred_getpid
#define ucred_getprivset _ucred_getprivset
--- a/usr/src/lib/libc/port/gen/ucred.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libc/port/gen/ucred.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -43,6 +42,7 @@
#pragma weak ucred_getauid = _ucred_getauid
#pragma weak ucred_getasid = _ucred_getasid
#pragma weak ucred_getatid = _ucred_getatid
+#pragma weak ucred_getlabel = _ucred_getlabel
#pragma weak ucred_getamask = _ucred_getamask
#pragma weak ucred_size = _ucred_size
@@ -66,6 +66,7 @@
#include <sys/procfs.h>
#include <sys/sysmacros.h>
#include <sys/zone.h>
+#include <tsol/label.h>
ucred_t *
_ucred_alloc(void)
@@ -260,6 +261,20 @@
return (uc->uc_zoneid);
}
+bslabel_t *
+ucred_getlabel(const ucred_t *uc)
+{
+ /* LINTED: alignment */
+ bslabel_t *slabel = UCLABEL(uc);
+
+ if (!is_system_labeled() || slabel == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ return (slabel);
+}
+
/*
* For now, assume single bit flags.
*/
--- a/usr/src/lib/libc/port/llib-lc Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libc/port/llib-lc Fri Mar 24 12:29:20 2006 -0800
@@ -1740,3 +1740,6 @@
/* private interface to unmount all autofs mounts */
int _autofssys(enum autofssys_op, void *);
+
+/* label.c */
+extern int is_system_labeled(void);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libc/port/sys/label.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,54 @@
+/*
+ * 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"
+
+#pragma weak is_system_labeled = _is_system_labeled
+
+#include "synonyms.h"
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <sys/tsol/tsyscall.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "libc.h"
+
+static int _is_labeled = -1;
+
+/*
+ * is_system_labeled :
+ * Return the status of MAC labeling on this system.
+ * Returns 0 if labeling is not installed or not active,
+ */
+int
+is_system_labeled(void)
+{
+ if (_is_labeled >= 0)
+ return (_is_labeled); /* fast path if cached */
+
+ return (_is_labeled = syscall(SYS_labelsys, TSOL_SYSLABELING));
+}
--- a/usr/src/lib/libc/port/sys/zone.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libc/port/sys/zone.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -37,14 +36,15 @@
#include <sys/priv.h>
#include <priv_private.h>
#include <zone.h>
+#include <sys/tsol/label.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <errno.h>
-extern zoneid_t
+zoneid_t
zone_create(const char *name, const char *root, const struct priv_set *privs,
const char *rctls, size_t rctlsz, const char *zfs, size_t zfssz,
- int *extended_error)
+ int *extended_error, int match, int doi, const bslabel_t *label)
{
zone_def zd;
priv_data_t *d;
@@ -60,6 +60,9 @@
zd.zfsbuf = zfs;
zd.zfsbufsz = zfssz;
zd.extended_error = extended_error;
+ zd.match = match;
+ zd.doi = doi;
+ zd.label = label;
return ((zoneid_t)syscall(SYS_zone, ZONE_CREATE, &zd));
}
--- a/usr/src/lib/libc/sparc/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libc/sparc/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -836,6 +836,7 @@
getpeerucred.o \
inst_sync.o \
issetugid.o \
+ label.o \
libc_link.o \
libc_open.o \
lockf.o \
--- a/usr/src/lib/libc/sparcv9/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libc/sparcv9/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -781,6 +781,7 @@
getpeerucred.o \
inst_sync.o \
issetugid.o \
+ label.o \
libc_link.o \
libc_open.o \
lockf.o \
--- a/usr/src/lib/libc/spec/gen.spec Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libc/spec/gen.spec Fri Mar 24 12:29:20 2006 -0800
@@ -4698,6 +4698,17 @@
version SUNW_1.22
end
+function ucred_getlabel
+include <ucred.h>
+declaration bslabel_t *ucred_getlabel(const ucred_t *)
+version SUNW_1.22.2
+end
+
+function _ucred_getlabel
+weak ucred_getlabel
+version SUNW_1.22.2
+end
+
function ucred_getpflags
include <ucred.h>
declaration uint_t ucred_getpflags(const ucred_t *, uint_t)
--- a/usr/src/lib/libc/spec/sys.spec Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libc/spec/sys.spec Fri Mar 24 12:29:20 2006 -0800
@@ -1,13 +1,12 @@
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# 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.
@@ -3432,9 +3431,11 @@
function zone_create
include <zone.h>
-declaration zoneid_t zone_create(const char *zone_name, \
- const char *zone_root, const priv_set_t *zone_privs, \
- const char *rctlbuf, size_t rctlbufsz, int *)
+declaration zoneid_t zone_create(const char *name, const char *root, \
+ const struct priv_set *privs, const char *rctls, \
+ size_t rctlsz, const char *zfs, size_t zfssz, \
+ int *extended_error, int match, \
+ int doi, const bslabel_t *label)
version SUNWprivate_1.1
exception $return == -1
end
@@ -3519,3 +3520,13 @@
weak getzonenamebyid
version SUNWprivate_1.1
end
+
+function is_system_labeled
+declaration int is_system_labeled(void)
+version SUNW_1.22.2
+end
+
+function _is_system_labeled
+weak is_system_labeled
+version SUNWprivate_1.1
+end
--- a/usr/src/lib/libc/spec/versions Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libc/spec/versions Fri Mar 24 12:29:20 2006 -0800
@@ -1,13 +1,12 @@
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# 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.
@@ -26,6 +25,7 @@
#
i386 {
+ SUNW_1.22.2: {SUNW_1.22.1};
SUNW_1.22.1: {SUNW_1.22};
SUNW_1.22: {SUNW_1.21.3};
SUNW_1.21.3: {SUNW_1.21.2};
@@ -62,6 +62,7 @@
SUNWprivate_1.1;
}
amd64 {
+ SUNW_1.22.2: {SUNW_1.22.1};
SUNW_1.22.1: {SUNW_1.22};
SUNW_1.22: {SUNW_1.21.3};
SUNW_1.21.3: {SUNW_1.21.2};
@@ -98,6 +99,7 @@
SUNWprivate_1.1;
}
sparc {
+ SUNW_1.22.2: {SUNW_1.22.1};
SUNW_1.22.1: {SUNW_1.22};
SUNW_1.22: {SUNW_1.21.3};
SUNW_1.21.3: {SUNW_1.21.2};
@@ -135,6 +137,7 @@
SUNWprivate_1.1;
}
sparcv9 {
+ SUNW_1.22.2: {SUNW_1.22.1};
SUNW_1.22.1: {SUNW_1.22};
SUNW_1.22: {SUNW_1.21.3};
SUNW_1.21.3: {SUNW_1.21.2};
--- a/usr/src/lib/libipsecutil/common/ipsec_util.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libipsecutil/common/ipsec_util.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -45,9 +44,11 @@
#include <err.h>
#include <net/pfpolicy.h>
+#ifndef A_CNT
/* macros for array manipulation */
#define A_CNT(arr) (sizeof (arr)/sizeof (arr[0]))
#define A_END(arr) (&arr[A_CNT(arr)])
+#endif
/* used for file parsing */
#define NBUF_SIZE 16
--- a/usr/src/lib/libldap5/Makefile.com Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libldap5/Makefile.com Fri Mar 24 12:29:20 2006 -0800
@@ -1,5 +1,25 @@
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -68,7 +88,7 @@
LIBS = $(DYNLIB) $(LINTLIB)
DYNFLAGS += $(ZNODELETE)
-CPPFLAGS += -I$(COM_INC)
+CPPFLAGS= $(COM_INC) $(CPPFLAGS.master)
# definitions for lint
--- a/usr/src/lib/libnsl/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libnsl/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -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,6 +17,8 @@
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
+
+
#
#
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
@@ -27,7 +28,7 @@
#
# lib/libnsl/Makefile
#
-PROTOCOL_DIR= $(ROOT)/usr/include/rpcsvc
+PROTOCOL_DIR= $(ROOTHDRDIR)/rpcsvc
PROTOCOL_SRCDIR= $(SRC)/head/rpcsvc
PROTOCOL_UTS_SRCDIR= $(SRC)/uts/common/rpc
@@ -71,9 +72,9 @@
# include library definitions
include ../Makefile.lib
-SED= sed
-CP= cp
-GREP= grep
+# header file delivered to /usr/include; internal to ON build process
+HDRS = nss.h
+HDRDIR = nss
LIBRARY= libnsl.a
TEXT_DOMAIN= SUNW_OST_NETRPC
@@ -99,6 +100,11 @@
install: all $(SUBDIRS)
+install_h: $(ROOTHDRS)
+
+# nss.h isn't delivered; no reason to check
+check:
+
clean clobber delete lint package: $(SUBDIRS)
$(PROTOCOL_DIR):
--- a/usr/src/lib/libnsl/Makefile.com Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libnsl/Makefile.com Fri Mar 24 12:29:20 2006 -0800
@@ -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,6 +17,8 @@
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
+
+
#
#
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
@@ -190,7 +191,8 @@
# then use the environment variable LD_OPTIONS=-Dgot,detail to have the
# linker print out the list of GOT hogs..
-GOTHOGS = dial.o print_obj.o clnt_perror.o
+GOTHOGS = dial.o print_obj.o clnt_perror.o nsl_stdio_prv.o netdir.o \
+ algs.o netselect.o
BIGPICS = $(GOTHOGS:%=pics/%)
$(BIGPICS) := sparc_C_PICFLAGS = $(C_BIGPICFLAGS)
$(BIGPICS) := i386_C_PICFLAGS = $(C_BIGPICFLAGS)
--- a/usr/src/lib/libnsl/nss/nss.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libnsl/nss/nss.h Fri Mar 24 12:29:20 2006 -0800
@@ -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 2002-2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -64,6 +63,14 @@
extern void order_haddrlist_af(sa_family_t, char **);
extern int nss_ioctl(int, int, void *);
+/* parse.c */
+extern char *_strtok_escape(char *, char *, char **);
+extern char *_strpbrk_escape(char *, char *);
+extern char *_escape(char *, char *);
+extern char *_unescape(char *, char *);
+extern char *_strdup_null(char *);
+extern int _readbufline(char *, int, char *, int, int *);
+
#ifdef __cplusplus
}
#endif
--- a/usr/src/lib/libnsl/rpc/clnt_bcast.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libnsl/rpc/clnt_bcast.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
@@ -43,6 +42,7 @@
*/
#include "mt.h"
+#include "rpc_mt.h"
#include <string.h>
#include <strings.h>
#include <rpc/rpc.h>
@@ -51,8 +51,6 @@
#include <netdir.h>
#ifdef PORTMAP
#include <rpc/pmap_prot.h>
-#include <rpc/pmap_clnt.h>
-#include <rpc/pmap_rmt.h>
#endif
#ifdef RPC_DEBUG
#include <stdio.h>
@@ -187,11 +185,13 @@
stat = RPC_CANTSEND;
continue;
}
+ __rpc_set_mac_options(fd, nconf, prog);
if (t_bind(fd, NULL, NULL) == -1) {
(void) t_close(fd);
stat = RPC_CANTSEND;
continue;
}
+
/* Do protocol specific negotiating for broadcast */
if (netdir_options(nconf, ND_SET_BROADCAST, fd, NULL)) {
(void) t_close(fd);
--- a/usr/src/lib/libnsl/rpc/clnt_generic.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libnsl/rpc/clnt_generic.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
@@ -403,6 +402,8 @@
if (fd < __rpc_minfd)
fd = __rpc_raise_fd(fd);
+ __rpc_set_mac_options(fd, nconf, prog);
+
/* LINTED pointer cast */
if ((tbind = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR))
== NULL) {
@@ -622,6 +623,7 @@
if (fd < __rpc_minfd)
fd = __rpc_raise_fd(fd);
madefd = TRUE;
+ __rpc_set_mac_options(fd, nconf, prog);
if (t_bind(fd, NULL, NULL) == -1)
goto err;
switch (nconf->nc_semantics) {
--- a/usr/src/lib/libnsl/rpc/rpc_mt.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libnsl/rpc/rpc_mt.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
@@ -36,6 +35,7 @@
#include <sys/types.h>
#include <rpc/rpc.h>
+#include <netconfig.h>
#ifdef __cplusplus
extern "C" {
@@ -94,6 +94,8 @@
extern void __getpublickey_flush(const char *);
extern int __can_use_af(sa_family_t);
extern int __rpc_raise_fd(int);
+extern void __rpc_set_mac_options(int, const struct netconfig *,
+ rpcprog_t);
extern void __tli_sys_strerror(char *, size_t, int, int);
#ifdef __cplusplus
--- a/usr/src/lib/libnsl/rpc/svc_dg.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libnsl/rpc/svc_dg.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -44,6 +43,7 @@
#include "rpc_mt.h"
#include <stdio.h>
#include <sys/types.h>
+#include <sys/sysmacros.h>
#include <rpc/rpc.h>
#include <errno.h>
#include <syslog.h>
@@ -284,6 +284,37 @@
return (XPRT_IDLE);
}
+/*
+ * Find the SCM_UCRED in src and place a pointer to that option alone in dest.
+ * Note that these two 'netbuf' structures might be the same one, so the code
+ * has to be careful about referring to src after changing dest.
+ */
+static void
+extract_cred(const struct netbuf *src, struct netbuf *dest)
+{
+ char *cp = src->buf;
+ unsigned int len = src->len;
+ const struct T_opthdr *opt;
+ unsigned int olen;
+
+ while (len >= sizeof (*opt)) {
+ /* LINTED: pointer alignment */
+ opt = (const struct T_opthdr *)cp;
+ olen = opt->len;
+ if (olen > len || olen < sizeof (*opt) ||
+ !IS_P2ALIGNED(olen, sizeof (t_uscalar_t)))
+ break;
+ if (opt->level == SOL_SOCKET && opt->name == SCM_UCRED) {
+ dest->buf = cp;
+ dest->len = olen;
+ return;
+ }
+ cp += olen;
+ len -= olen;
+ }
+ dest->len = 0;
+}
+
static bool_t
svc_dg_recv(SVCXPRT *xprt, struct rpc_msg *msg)
{
@@ -354,9 +385,10 @@
/* tu_data.addr is already set */
tu_data->udata.buf = reply;
tu_data->udata.len = (uint_t)replylen;
- tu_data->opt.len = 0;
+ extract_cred(&tu_data->opt, &tu_data->opt);
(void) t_sndudata(xprt->xp_fd, tu_data);
tu_data->udata.buf = (char *)rpc_buffer(xprt);
+ tu_data->opt.buf = (char *)su->opts;
return (FALSE);
}
}
@@ -425,7 +457,7 @@
slen = (int)XDR_GETPOS(xdrs);
tu_data->udata.len = slen;
- tu_data->opt.len = 0;
+ extract_cred(&su->optbuf, &tu_data->opt);
try_again:
if (t_sndudata(xprt->xp_fd, tu_data) == 0) {
stat = TRUE;
@@ -440,6 +472,7 @@
"svc_dg_reply: t_sndudata error t_errno=%d errno=%d\n",
t_errno, errno);
}
+ tu_data->opt.buf = (char *)su->opts;
}
return (stat);
}
--- a/usr/src/lib/libnsl/rpc/svc_generic.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libnsl/rpc/svc_generic.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -52,7 +51,14 @@
#include <malloc.h>
#include <string.h>
#include <stropts.h>
-
+#include <tsol/label.h>
+#include <nfs/nfs.h>
+#include <nfs/nfs_acl.h>
+#include <rpcsvc/mount.h>
+#include <rpcsvc/nsm_addr.h>
+#include <rpcsvc/rquota.h>
+#include <rpcsvc/sm_inter.h>
+#include <rpcsvc/nlm_prot.h>
extern int __svc_vc_setflag(SVCXPRT *, int);
@@ -80,6 +86,22 @@
SVCXPRT_LIST *_svc_xprtlist = NULL;
extern mutex_t xprtlist_lock;
+static SVCXPRT * svc_tli_create_common(int, const struct netconfig *,
+ const struct t_bind *, uint_t, uint_t, boolean_t);
+
+boolean_t
+is_multilevel(rpcprog_t prognum)
+{
+ /* This is a list of identified multilevel service provider */
+ if ((prognum == MOUNTPROG) || (prognum == NFS_PROGRAM) ||
+ (prognum == NFS_ACL_PROGRAM) || (prognum == NLM_PROG) ||
+ (prognum == NSM_ADDR_PROGRAM) || (prognum == RQUOTAPROG) ||
+ (prognum == SM_PROG))
+ return (B_TRUE);
+
+ return (B_FALSE);
+}
+
void
__svc_free_xprtlist(void)
{
@@ -162,6 +184,7 @@
const rpcvers_t versnum, const struct netconfig *nconf)
{
SVCXPRT *xprt;
+ boolean_t anon_mlp = B_FALSE;
if (nconf == NULL) {
(void) syslog(LOG_ERR,
@@ -169,7 +192,11 @@
prognum, versnum);
return (NULL);
}
- xprt = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0);
+
+ /* Some programs need to allocate MLP for multilevel services */
+ if (is_system_labeled() && is_multilevel(prognum))
+ anon_mlp = B_TRUE;
+ xprt = svc_tli_create_common(RPC_ANYFD, nconf, NULL, 0, 0, anon_mlp);
if (xprt == NULL)
return (NULL);
(void) rpcb_unset(prognum, versnum, (struct netconfig *)nconf);
@@ -183,6 +210,13 @@
return (xprt);
}
+SVCXPRT *
+svc_tli_create(const int fd, const struct netconfig *nconf,
+ const struct t_bind *bindaddr, const uint_t sendsz, const uint_t recvsz)
+{
+ return (svc_tli_create_common(fd, nconf, bindaddr, sendsz, recvsz, 0));
+}
+
/*
* If fd is RPC_ANYFD, then it opens a fd for the given transport
* provider (nconf cannot be NULL then). If the t_state is T_UNBND and
@@ -193,8 +227,9 @@
* If sendsz or recvsz are zero, their default values are chosen.
*/
SVCXPRT *
-svc_tli_create(const int ofd, const struct netconfig *nconf,
- const struct t_bind *bindaddr, const uint_t sendsz, const uint_t recvsz)
+svc_tli_create_common(const int ofd, const struct netconfig *nconf,
+ const struct t_bind *bindaddr, const uint_t sendsz,
+ const uint_t recvsz, boolean_t mlp_flag)
{
SVCXPRT *xprt = NULL; /* service handle */
struct t_info tinfo; /* transport info */
@@ -293,6 +328,17 @@
switch (state) {
bool_t tcp, exclbind;
case T_UNBND:
+ /* If this is a labeled system, then ask for an MLP */
+ if (is_system_labeled() &&
+ (strcmp(nconf->nc_protofmly, NC_INET) == 0 ||
+ strcmp(nconf->nc_protofmly, NC_INET6) == 0)) {
+ (void) __rpc_tli_set_options(fd, SOL_SOCKET,
+ SO_RECVUCRED, 1);
+ if (mlp_flag)
+ (void) __rpc_tli_set_options(fd, SOL_SOCKET,
+ SO_ANON_MLP, 1);
+ }
+
/*
* {TCP,UDP}_EXCLBIND has the following properties
* - an fd bound to port P via IPv4 will prevent an IPv6
--- a/usr/src/lib/libnsl/rpc/ti_opts.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libnsl/rpc/ti_opts.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
@@ -59,11 +58,10 @@
#include <alloca.h>
#include <stdlib.h>
#include <zone.h>
+#include <tsol/label.h>
-extern const char *inet_ntop(int, const void *, char *, socklen_t);
extern bool_t __svc_get_door_ucred(const SVCXPRT *, ucred_t *);
-
/*
* This routine is typically called on the server side if the server
* wants to know the caller ucred. Called typically by rpcbind. It
@@ -494,6 +492,8 @@
case SO_REUSEADDR:
case SO_DGRAM_ERRIND:
case SO_RECVUCRED:
+ case SO_ANON_MLP:
+ case SO_MAC_EXEMPT:
case TCP_EXCLBIND:
case UDP_EXCLBIND:
/* LINTED */
@@ -548,3 +548,34 @@
(void) strlcpy(buf, errorstr, buflen);
}
}
+
+/*
+ * Depending on the specified RPC number, attempt to set mac_exempt
+ * option on the opened socket; these requests need to be able to do MAC
+ * MAC read-down operations. Privilege is needed to set this option.
+ */
+
+void
+__rpc_set_mac_options(int fd, const struct netconfig *nconf, rpcprog_t prognum)
+{
+ int ret = 0;
+
+ if (!is_system_labeled())
+ return;
+
+ if (strcmp(nconf->nc_protofmly, NC_INET) != 0 &&
+ strcmp(nconf->nc_protofmly, NC_INET6) != 0)
+ return;
+
+ if (is_multilevel(prognum)) {
+ ret = __rpc_tli_set_options(fd, SOL_SOCKET, SO_MAC_EXEMPT, 1);
+ if (ret < 0) {
+ char errorstr[100];
+
+ __tli_sys_strerror(errorstr, sizeof (errorstr),
+ t_errno, errno);
+ (void) syslog(LOG_ERR, "rpc_set_mac_options: %s",
+ errorstr);
+ }
+ }
+}
--- a/usr/src/lib/libsldap/common/ns_common.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libsldap/common/ns_common.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -82,6 +81,8 @@
{ "profile", "ou=profile,", NULL },
{ "printers", "ou=printers,", NULL },
{ "automount", "", NULL },
+ { "tnrhtp", "ou=ipTnet,", NULL },
+ { "tnrhdb", "ou=ipTnet,", "tnrhtp" },
{ NULL, NULL, NULL }
};
--- a/usr/src/lib/libsldap/common/ns_sldap.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libsldap/common/ns_sldap.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -450,6 +449,8 @@
#define NS_LDAP_TYPE_AUUSER "audit_user"
#define NS_LDAP_TYPE_BOOTPARAMS "bootparams"
#define NS_LDAP_TYPE_AUTOMOUNT "auto_"
+#define NS_LDAP_TYPE_TNRHDB "tnrhdb"
+#define NS_LDAP_TYPE_TNRHTP "tnrhtp"
/*
* service descriptor/attribute mapping structure
--- a/usr/src/lib/libsldap/common/ns_writes.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libsldap/common/ns_writes.c Fri Mar 24 12:29:20 2006 -0800
@@ -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,8 @@
#include <prof_attr.h>
#include <user_attr.h>
#include <bsm/libbsm.h>
+#include <sys/tsol/tndb.h>
+#include <tsol/label.h>
/*
@@ -3246,7 +3247,128 @@
return (NS_LDAP_SUCCESS);
}
-
+/*
+ * Conversion: tnrhtp
+ * Input format: tsol_tpstr_t
+ * Exported objectclass: ipTnetTemplate
+ */
+static int
+__s_cvt_tnrhtp(const void *data, char **rdn,
+ ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
+{
+ ns_ldap_entry_t *e;
+ int rc;
+ char trdn[RDNSIZE];
+ /* routine specific */
+ int max_attr = 2;
+ tsol_tpstr_t *ptr;
+ static char *oclist[] = {
+ "ipTnetTemplate",
+ "top",
+ NULL
+ };
+
+ if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
+ return (NS_LDAP_OP_FAILED);
+
+ *entry = e = __s_mk_entry(oclist, max_attr);
+ if (e == NULL)
+ return (NS_LDAP_MEMORY);
+
+ /* Convert the structure */
+ ptr = (tsol_tpstr_t *)data;
+
+ if ((ptr->template == NULL) || (strlen(ptr->template) <= 1)) {
+ __ns_ldap_freeEntry(e);
+ *entry = NULL;
+ return (NS_LDAP_INVALID_PARAM);
+ }
+
+ /* Create an appropriate rdn */
+ (void) snprintf(trdn, RDNSIZE, "ipTnetTemplateName=%s", ptr->template);
+ *rdn = strdup(trdn);
+ if (*rdn == NULL) {
+ __ns_ldap_freeEntry(e);
+ *entry = NULL;
+ return (NS_LDAP_MEMORY);
+ }
+
+ rc = __s_add_attr(e, "ipTnetTemplateName", ptr->template);
+ if (rc != NS_LDAP_SUCCESS) {
+ __s_cvt_freeEntryRdn(entry, rdn);
+ return (rc);
+ }
+
+ rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attrs);
+ if (rc != NS_LDAP_SUCCESS) {
+ __s_cvt_freeEntryRdn(entry, rdn);
+ return (rc);
+ }
+
+ return (NS_LDAP_SUCCESS);
+}
+/*
+ * Conversion: tnrhdb
+ * Input format: tsol_rhstr_t
+ * Exported objectclass: ipTnetHost
+ */
+static int
+__s_cvt_tnrhdb(const void *data, char **rdn,
+ ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
+{
+ ns_ldap_entry_t *e;
+ int rc;
+ char trdn[RDNSIZE];
+ /* routine specific */
+ tsol_rhstr_t *ptr;
+ int max_attr = 2;
+ static char *oclist[] = {
+ "ipTnetHost",
+ "ipTnetTemplate",
+ "top",
+ NULL
+ };
+
+ if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
+ return (NS_LDAP_OP_FAILED);
+
+ *entry = e = __s_mk_entry(oclist, max_attr);
+ if (e == NULL)
+ return (NS_LDAP_MEMORY);
+
+ /* Convert the structure */
+ ptr = (tsol_rhstr_t *)data;
+
+ if ((ptr->address == NULL) || (strlen(ptr->address) <= 1) ||
+ (ptr->template == NULL) || (strlen(ptr->template) <= 1)) {
+ __ns_ldap_freeEntry(e);
+ *entry = NULL;
+ return (NS_LDAP_INVALID_PARAM);
+ }
+
+ /* Create an appropriate rdn */
+ (void) snprintf(trdn, RDNSIZE, "ipTnetNumber=%s", ptr->address);
+ *rdn = strdup(trdn);
+ if (*rdn == NULL) {
+ __ns_ldap_freeEntry(e);
+ *entry = NULL;
+ return (NS_LDAP_MEMORY);
+ }
+
+ rc = __s_add_attr(e, "ipTnetNumber", ptr->address);
+ if (rc != NS_LDAP_SUCCESS) {
+ __s_cvt_freeEntryRdn(entry, rdn);
+ return (rc);
+ }
+
+ rc = __s_add_attr(e, "ipTnetTemplateName", ptr->template);
+ if (rc != NS_LDAP_SUCCESS) {
+ __s_cvt_freeEntryRdn(entry, rdn);
+ return (rc);
+ }
+
+ return (NS_LDAP_SUCCESS);
+}
/*
* Add Typed Entry Conversion data structures
*/
@@ -3283,6 +3405,8 @@
{ NS_LDAP_TYPE_AUTOMOUNT, 0, __s_cvt_auto_mount },
{ NS_LDAP_TYPE_PUBLICKEY, AE, __s_cvt_publickey },
{ NS_LDAP_TYPE_AUUSER, AE, __s_cvt_audituser },
+ { NS_LDAP_TYPE_TNRHTP, 0, __s_cvt_tnrhtp },
+ { NS_LDAP_TYPE_TNRHDB, 0, __s_cvt_tnrhdb },
{ NULL, 0, NULL },
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,67 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.lib
+
+HDRS = libtsnet.h
+HDRDIR = common
+SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+install := TARGET= install
+lint := TARGET= lint
+
+POFILE = libtsnet.po
+MSGFILES = common/misc.i
+
+.KEEP_STATE:
+
+all install: spec .WAIT $(SUBDIRS)
+
+clean clobber: spec $(SUBDIRS)
+
+lint: $(SUBDIRS)
+
+install_h: $(ROOTHDRS)
+
+check: $(CHECKHDRS)
+
+_msg: $(MSGDOMAINPOFILE)
+
+$(POFILE): $(MSGFILES)
+ $(BUILDPO.msgfiles)
+
+spec $(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include $(SRC)/Makefile.msg.targ
+include ../Makefile.targ
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/Makefile.com Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,63 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+
+LIBRARY = libtsnet.a
+VERS = .1
+
+OBJECTS = \
+ misc.o \
+ tnrh.o tnrhtp.o tnmlp.o \
+ tsol_getrhent.o tsol_gettpent.o \
+ tsol_sgetrhent.o tsol_sgettpent.o tsol_sgetzcent.o
+
+include ../../Makefile.lib
+
+# install this library in the root filesystem
+include ../../Makefile.rootfs
+
+LIBS = $(DYNLIB) $(LINTLIB)
+$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
+
+LAZYLIBS = $(ZLAZYLOAD) -ltsol $(ZNOLAZYLOAD)
+LDLIBS += -lsocket -lnsl -lc -lsecdb $(LAZYLIBS)
+lint := LAZYLIBS = -ltsol
+
+SRCDIR = ../common
+MAPDIR = ../spec/$(TRANSMACH)
+SPECMAPFILE = $(MAPDIR)/mapfile
+
+LIBTSOLINC = $(SRC)/lib/libtsol/common
+
+CPPFLAGS += -D_REENTRANT -I$(LIBTSOLINC)
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+include ../../Makefile.targ
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/amd64/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,31 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/common/libtsnet.h Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ *
+ * All symbols and functions in this header file and library are private to Sun
+ * Microsystems. The only guarantee that is made is that if your application
+ * uses them, it will break on upgrade.
+ */
+
+#ifndef _LIBTSNET_H
+#define _LIBTSNET_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <sys/tsol/tndb.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TNRHTP_PATH "/etc/security/tsol/tnrhtp"
+#define TNRHDB_PATH "/etc/security/tsol/tnrhdb"
+#define TNZONECFG_PATH "/etc/security/tsol/tnzonecfg"
+
+#define TNDB_COMMA ", \t"
+
+/*
+ * String parsing routines
+ *
+ * These functions are in four logical groups: one for template (tnrhtp)
+ * entries, one for remote host (tnrhdb) entries, one for zone configuration
+ * (tnzonecfg) entries, and a fourth for routing attributes.
+ *
+ * In each group, there are functions that parse from a string or database, and
+ * a function to free returned entries. The parsing functions all take a
+ * pointer to an integer and a pointer to a character pointer for returning
+ * errors. On error, the returned entry pointer is NULL, the integer is set to
+ * one of the LTSNET_* errors below, and the character pointer points to the
+ * location of the error. (For the functions that iterate on a database, this
+ * points into static storage in the library. This storage is associated with
+ * the iterator.)
+ *
+ * The functions that do look-ups based on a value (name or address) do not
+ * return errors other than "not found," which is signaled by a return value of
+ * NULL.
+ */
+
+/* Template entry parsing */
+extern tsol_tpent_t *tsol_gettpbyname(const char *);
+extern tsol_tpent_t *tsol_gettpent(void);
+extern tsol_tpent_t *tsol_fgettpent(FILE *);
+extern void tsol_freetpent(tsol_tpent_t *);
+extern void tsol_settpent(int);
+extern void tsol_endtpent(void);
+extern int str_to_tpstr(const char *, int, void *, char *, int);
+extern tsol_tpent_t *tpstr_to_ent(tsol_tpstr_t *, int *, char **);
+
+/* Remote host entry parsing */
+extern tsol_rhent_t *tsol_getrhbyaddr(const void *, size_t, int);
+extern tsol_rhent_t *tsol_getrhent(void);
+extern tsol_rhent_t *tsol_fgetrhent(FILE *);
+extern void tsol_freerhent(tsol_rhent_t *);
+extern void tsol_setrhent(int);
+extern void tsol_endrhent(void);
+extern int str_to_rhstr(const char *, int, void *, char *, int);
+extern tsol_rhent_t *rhstr_to_ent(tsol_rhstr_t *, int *, char **);
+extern tsol_host_type_t tsol_getrhtype(char *);
+
+
+/* Zone configuration parsing */
+extern tsol_zcent_t *tsol_sgetzcent(const char *, int *, char **);
+extern void tsol_freezcent(tsol_zcent_t *);
+
+/* Routing attribute parsing */
+extern const char *sl_to_str(const bslabel_t *);
+struct rtsa_s;
+extern const char *rtsa_to_str(const struct rtsa_s *, char *, size_t);
+extern boolean_t rtsa_keyword(const char *, struct rtsa_s *, int *, char **);
+extern const char *parse_entry(char *, size_t, const char *, const char *);
+
+/* Convert LTSNET_* to a printable string */
+extern const char *tsol_strerror(int, int);
+
+/* System calls; these return -1 on error and set errno */
+extern int tnrhtp(int, tsol_tpent_t *);
+extern int tnrh(int, tsol_rhent_t *);
+extern int tnmlp(int, tsol_mlpent_t *);
+
+/*
+ * Errors that can occur in the parsing routines. Note that not all errors are
+ * possible with every routine. Must be kept in sync with list in misc.c.
+ */
+#define LTSNET_NONE 0 /* No error */
+#define LTSNET_SYSERR 1 /* System error; see errno */
+#define LTSNET_EMPTY 2 /* Empty string or end of list */
+#define LTSNET_ILL_ENTRY 3 /* Entry is malformed */
+#define LTSNET_NO_NAME 4 /* Missing name */
+#define LTSNET_NO_ATTRS 5 /* Missing template attributes */
+#define LTSNET_ILL_NAME 6 /* Illegal name */
+#define LTSNET_ILL_KEYDELIM 7 /* Illegal keyword delimiter */
+#define LTSNET_ILL_KEY 8 /* Unknown keyword */
+#define LTSNET_DUP_KEY 9 /* Duplicate keyword */
+#define LTSNET_ILL_VALDELIM 10 /* Illegal value delimiter */
+#define LTSNET_NO_HOSTTYPE 11 /* Missing host type */
+#define LTSNET_ILL_HOSTTYPE 12 /* Illegal host type */
+#define LTSNET_NO_LABEL 13 /* Missing label */
+#define LTSNET_ILL_LABEL 14 /* Illegal label */
+#define LTSNET_NO_RANGE 15 /* Missing label range */
+#define LTSNET_ILL_RANGE 16 /* Illegal label range */
+#define LTSNET_NO_LOWERBOUND 17 /* No lower bound in range */
+#define LTSNET_ILL_LOWERBOUND 18 /* Illegal lower bound in range */
+#define LTSNET_NO_UPPERBOUND 19 /* No upper bound in range */
+#define LTSNET_ILL_UPPERBOUND 20 /* Illegal upper bound in range */
+#define LTSNET_NO_DOI 21 /* Missing DOI */
+#define LTSNET_ILL_DOI 22 /* Illegal DOI */
+#define LTSNET_SET_TOO_BIG 23 /* Too many entries in set */
+#define LTSNET_NO_ADDR 24 /* Missing address/network */
+#define LTSNET_ILL_ADDR 25 /* Illegal address/network */
+#define LTSNET_ILL_FLAG 26 /* Illegal flag */
+#define LTSNET_ILL_MLP 27 /* Illegal MLP specification */
+#define LTSNET_BAD_TYPE 28 /* Unacceptable keyword for type */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBTSNET_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/common/llib-ltsnet Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,32 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* LINTLIBRARY */
+/* PROTOLIB1 */
+
+#include <libtsnet.h>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/common/misc.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,359 @@
+/*
+ * 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.
+ *
+ * From "misc.c 5.15 00/05/31 SMI; TSOL 2.x"
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Miscellaneous user interfaces to trusted label functions.
+ */
+
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <errno.h>
+#include <libintl.h>
+#include <libtsnet.h>
+#include <tsol/label.h>
+
+#include <net/route.h>
+
+#define MAX_STRING_SIZE 256
+#define MAX_ATTR_LEN 1024
+
+/*
+ * Parse off an entry from a line. Entry is stored in 'outbuf'. Returned
+ * value is a pointer to the first unprocessed input character from 'instr'.
+ */
+const char *
+parse_entry(char *outbuf, size_t outlen, const char *instr,
+ const char *delimit)
+{
+ boolean_t escape_state = B_FALSE;
+ boolean_t any_white;
+ char chr;
+
+ any_white = strchr(delimit, '\n') != NULL;
+
+ /*
+ * User may specify outlen as 0 to skip over a field without storing
+ * it anywhere. Otherwise, we need at least one byte for the
+ * terminating NUL plus one byte to store another byte from instr.
+ */
+ while (outlen != 1 && (chr = *instr++) != '\0') {
+ if (!escape_state) {
+ if (chr == '\\') {
+ escape_state = B_TRUE;
+ continue;
+ }
+ if (strchr(delimit, chr) != NULL)
+ break;
+ if (any_white && isspace(chr))
+ break;
+ }
+ escape_state = B_FALSE;
+ if (outlen > 0) {
+ *outbuf++ = chr;
+ outlen--;
+ }
+ }
+ if (outlen != 1)
+ instr--;
+ if (escape_state)
+ instr--;
+ if (outlen > 0)
+ *outbuf = '\0';
+ return (instr);
+}
+
+const char *
+sl_to_str(const bslabel_t *sl)
+{
+ const char *sl_str;
+ static const char unknown_str[] = "UNKNOWN";
+
+ if (sl == NULL)
+ return (unknown_str);
+
+ if ((sl_str = sbsltos(sl, MAX_STRING_SIZE)) == NULL &&
+ (sl_str = bsltoh(sl)) == NULL)
+ sl_str = unknown_str;
+ return (sl_str);
+}
+
+static const char *rtsa_keywords[] = {
+#define SAK_MINSL 0
+ "min_sl",
+#define SAK_MAXSL 1
+ "max_sl",
+#define SAK_DOI 2
+ "doi",
+#define SAK_CIPSO 3
+ "cipso",
+#define SAK_INVAL 4
+ NULL
+};
+
+const char *
+rtsa_to_str(const struct rtsa_s *rtsa, char *line, size_t len)
+{
+ size_t slen;
+ uint32_t mask, i;
+
+ slen = 0;
+ *line = '\0';
+ mask = rtsa->rtsa_mask;
+
+ for (i = 1; mask != 0 && i != 0 && slen < len - 1; i <<= 1) {
+ if (!(i & (RTSA_MINSL|RTSA_MAXSL|RTSA_DOI|RTSA_CIPSO)))
+ continue;
+ if (!(i & mask))
+ continue;
+ if (slen != 0)
+ line[slen++] = ',';
+ switch (i & mask) {
+ case RTSA_MINSL:
+ slen += snprintf(line + slen, len - slen, "min_sl=%s",
+ sl_to_str(&rtsa->rtsa_slrange.lower_bound));
+ break;
+ case RTSA_MAXSL:
+ slen += snprintf(line + slen, len - slen, "max_sl=%s",
+ sl_to_str(&rtsa->rtsa_slrange.upper_bound));
+ break;
+ case RTSA_DOI:
+ slen += snprintf(line + slen, len - slen, "doi=%d",
+ rtsa->rtsa_doi);
+ break;
+ case RTSA_CIPSO:
+ slen += snprintf(line + slen, len - slen, "cipso");
+ break;
+ }
+ }
+
+ return (line);
+}
+
+boolean_t
+rtsa_keyword(const char *options, struct rtsa_s *sp, int *errp, char **errstrp)
+{
+ const char *valptr, *nxtopt;
+ uint32_t mask = 0, doi;
+ int key;
+ bslabel_t min_sl, max_sl;
+ char attrbuf[MAX_ATTR_LEN];
+ const char **keyword;
+ int err;
+ char *errstr, *cp;
+
+ if (errp == NULL)
+ errp = &err;
+ if (errstrp == NULL)
+ errstrp = &errstr;
+
+ *errstrp = (char *)options;
+
+ while (*options != '\0') {
+ valptr = parse_entry(attrbuf, sizeof (attrbuf), options, ",=");
+
+ if (attrbuf[0] == '\0') {
+ *errstrp = (char *)options;
+ *errp = LTSNET_ILL_ENTRY;
+ return (B_FALSE);
+ }
+ for (keyword = rtsa_keywords; *keyword != NULL; keyword++)
+ if (strcmp(*keyword, attrbuf) == 0)
+ break;
+ if ((key = keyword - rtsa_keywords) == SAK_INVAL) {
+ *errstrp = (char *)options;
+ *errp = LTSNET_ILL_KEY;
+ return (B_FALSE);
+ }
+ if ((key == SAK_CIPSO && *valptr == '=') ||
+ (key != SAK_CIPSO && *valptr != '=')) {
+ *errstrp = (char *)valptr;
+ *errp = LTSNET_ILL_VALDELIM;
+ return (B_FALSE);
+ }
+
+ nxtopt = valptr;
+ if (*valptr == '=') {
+ valptr++;
+ nxtopt = parse_entry(attrbuf, sizeof (attrbuf),
+ valptr, ",=");
+ if (*nxtopt == '=') {
+ *errstrp = (char *)nxtopt;
+ *errp = LTSNET_ILL_KEYDELIM;
+ return (B_FALSE);
+ }
+ }
+ if (*nxtopt == ',')
+ nxtopt++;
+
+ switch (key) {
+ case SAK_MINSL:
+ if (mask & RTSA_MINSL) {
+ *errstrp = (char *)options;
+ *errp = LTSNET_DUP_KEY;
+ return (B_FALSE);
+ }
+ if (stobsl(attrbuf, &min_sl, NO_CORRECTION,
+ &err) != 1) {
+ *errstrp = (char *)valptr;
+ *errp = LTSNET_ILL_LOWERBOUND;
+ return (B_FALSE);
+ }
+ mask |= RTSA_MINSL;
+ break;
+
+ case SAK_MAXSL:
+ if (mask & RTSA_MAXSL) {
+ *errstrp = (char *)options;
+ *errp = LTSNET_DUP_KEY;
+ return (B_FALSE);
+ }
+ if (stobsl(attrbuf, &max_sl, NO_CORRECTION,
+ &err) != 1) {
+ *errstrp = (char *)valptr;
+ *errp = LTSNET_ILL_UPPERBOUND;
+ return (B_FALSE);
+ }
+ mask |= RTSA_MAXSL;
+ break;
+
+ case SAK_DOI:
+ if (mask & RTSA_DOI) {
+ *errstrp = (char *)options;
+ *errp = LTSNET_DUP_KEY;
+ return (B_FALSE);
+ }
+ errno = 0;
+ doi = strtoul(attrbuf, &cp, 0);
+ if (doi == 0 || errno != 0 || *cp != '\0') {
+ *errstrp = (char *)valptr;
+ *errp = LTSNET_ILL_DOI;
+ return (B_FALSE);
+ }
+ mask |= RTSA_DOI;
+ break;
+
+ case SAK_CIPSO:
+ if (mask & RTSA_CIPSO) {
+ *errstrp = (char *)options;
+ *errp = LTSNET_DUP_KEY;
+ return (B_FALSE);
+ }
+ mask |= RTSA_CIPSO;
+ break;
+ }
+
+ options = nxtopt;
+ }
+
+ /* Defaults to CIPSO if not specified */
+ mask |= RTSA_CIPSO;
+
+ /* If RTSA_CIPSO is specified, RTSA_DOI must be specified */
+ if (!(mask & RTSA_DOI)) {
+ *errp = LTSNET_NO_DOI;
+ return (B_FALSE);
+ }
+
+ /* SL range must be specified */
+ if (!(mask & (RTSA_MINSL|RTSA_MAXSL))) {
+ *errp = LTSNET_NO_RANGE;
+ return (B_FALSE);
+ }
+ if (!(mask & RTSA_MINSL)) {
+ *errp = LTSNET_NO_LOWERBOUND;
+ return (B_FALSE);
+ }
+ if (!(mask & RTSA_MAXSL)) {
+ *errp = LTSNET_NO_UPPERBOUND;
+ return (B_FALSE);
+ }
+
+ /* SL range must have upper bound dominating lower bound */
+ if (!bldominates(&max_sl, &min_sl)) {
+ *errp = LTSNET_ILL_RANGE;
+ return (B_FALSE);
+ }
+
+ if (mask & RTSA_MINSL)
+ sp->rtsa_slrange.lower_bound = min_sl;
+ if (mask & RTSA_MAXSL)
+ sp->rtsa_slrange.upper_bound = max_sl;
+ if (mask & RTSA_DOI)
+ sp->rtsa_doi = doi;
+ sp->rtsa_mask = mask;
+
+ return (B_TRUE);
+}
+
+/* Keep in sync with libtsnet.h */
+static const char *tsol_errlist[] = {
+ "No error",
+ "System error",
+ "Empty string or end of list",
+ "Entry is malformed",
+ "Missing name",
+ "Missing attributes",
+ "Illegal name",
+ "Illegal keyword delimiter",
+ "Unknown keyword",
+ "Duplicate keyword",
+ "Illegal value delimiter",
+ "Missing host type",
+ "Illegal host type",
+ "Missing label",
+ "Illegal label",
+ "Missing label range",
+ "Illegal label range",
+ "No lower bound in range",
+ "Illegal lower bound in range",
+ "No upper bound in range",
+ "Illegal upper bound in range",
+ "Missing DOI",
+ "Illegal DOI",
+ "Too many entries in set",
+ "Missing address/network",
+ "Illegal address/network",
+ "Illegal flag",
+ "Illegal MLP specification",
+ "Unacceptable keyword for type"
+};
+static const int tsol_nerr = sizeof (tsol_errlist) / sizeof (*tsol_errlist);
+
+const char *
+tsol_strerror(int libtserr, int errnoval)
+{
+ if (libtserr == LTSNET_SYSERR)
+ return (strerror(errnoval));
+ if (libtserr >= 0 && libtserr < tsol_nerr)
+ return (gettext(tsol_errlist[libtserr]));
+ return (gettext("Unknown error"));
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/common/synonyms.h Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,52 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * From "synonyms.h 7.2 99/06/21 SMI; TSOL 2.x"
+ */
+
+#ifndef _SYNONYMS_H
+#define _SYNONYMS_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__STDC__)
+
+/* external data */
+
+/* functions */
+#define tnrh _tnrh
+#define tnrhtp _tnrhtp
+#define tnmlp _tnmlp
+
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYNONYMS_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/common/tnmlp.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,49 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "synonyms.h"
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <libtsnet.h>
+#include <sys/tsol/tsyscall.h>
+
+/*
+ * tnmlp(2TSOL) - manipulate kernel trusted network multilevel port
+ * entries
+ *
+ * This is the library interface to the system call.
+ */
+
+#ifdef __STDC__
+#pragma weak tnmlp = _tnmlp
+#endif
+
+int
+tnmlp(int cmd, tsol_mlpent_t *buf)
+{
+ return (syscall(SYS_labelsys, TSOL_TNMLP, cmd, buf));
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/common/tnrh.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,48 @@
+/*
+ * 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 "synonyms.h"
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <libtsnet.h>
+#include <sys/tsol/tsyscall.h>
+
+/*
+ * tnrh(2TSOL) - manipulate kernel trusted network remote hosts cache
+ *
+ * This is the library interface to the system call.
+ */
+
+#ifdef __STDC__
+#pragma weak tnrh = _tnrh
+#endif
+
+int
+tnrh(int cmd, tsol_rhent_t *buf)
+{
+ return (syscall(SYS_labelsys, TSOL_TNRH, cmd, buf));
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/common/tnrhtp.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,49 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "synonyms.h"
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <libtsnet.h>
+#include <sys/tsol/tsyscall.h>
+
+/*
+ * tnrhtp(2TSOL) - manipulate kernel trusted network remote host
+ * templates cache
+ *
+ * This is the library interface to the system call.
+ */
+
+#ifdef __STDC__
+#pragma weak tnrhtp = _tnrhtp
+#endif
+
+int
+tnrhtp(int cmd, tsol_tpent_t *buf)
+{
+ return (syscall(SYS_labelsys, TSOL_TNRHTP, cmd, buf));
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/common/tsol_getrhent.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,257 @@
+/*
+ * 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.
+ *
+ * From "tsol_getrhent.c 7.6 00/09/22 SMI; TSOL 2.x"
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <nss_dbdefs.h>
+#include <libtsnet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <secdb.h>
+#include <nss.h>
+#include <libtsnet.h>
+#include <libintl.h>
+
+extern void _nss_XbyY_fgets(FILE *, nss_XbyY_args_t *); /* from lib.c */
+
+static int tsol_rh_stayopen; /* Unsynchronized, but it affects only */
+ /* efficiency, not correctness */
+static DEFINE_NSS_DB_ROOT(db_root);
+static DEFINE_NSS_GETENT(context);
+
+static void
+_nss_initf_tsol_rh(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_TSOL_RH;
+ p->default_config = NSS_DEFCONF_TSOL_RH;
+}
+
+tsol_rhent_t *
+tsol_getrhbyaddr(const void *addrp, size_t len, int af)
+{
+ int err = 0;
+ char *errstr = NULL;
+ char buf[NSS_BUFLEN_TSOL_RH];
+ tsol_rhstr_t result;
+ tsol_rhstr_t *rhstrp = NULL;
+ nss_XbyY_args_t arg;
+
+ NSS_XbyY_INIT(&arg, &result, buf, sizeof (buf), str_to_rhstr);
+
+ arg.key.hostaddr.addr = (const char *)addrp;
+ arg.key.hostaddr.len = len;
+ arg.key.hostaddr.type = af;
+ arg.stayopen = tsol_rh_stayopen;
+ arg.h_errno = TSOL_NOT_FOUND;
+ arg.status = nss_search(&db_root, _nss_initf_tsol_rh,
+ NSS_DBOP_TSOL_RH_BYADDR, &arg);
+ rhstrp = (tsol_rhstr_t *)NSS_XbyY_FINI(&arg);
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "tsol_getrhbyaddr %s: %s\n",
+ (char *)addrp, rhstrp ? rhstrp->template : "NULL");
+#endif /* DEBUG */
+
+ if (rhstrp == NULL)
+ return (NULL);
+
+ return (rhstr_to_ent(rhstrp, &err, &errstr));
+}
+
+void
+tsol_setrhent(int stay)
+{
+ tsol_rh_stayopen |= stay;
+ nss_setent(&db_root, _nss_initf_tsol_rh, &context);
+}
+
+void
+tsol_endrhent(void)
+{
+ tsol_rh_stayopen = 0;
+ nss_endent(&db_root, _nss_initf_tsol_rh, &context);
+ nss_delete(&db_root);
+}
+
+tsol_rhent_t *
+tsol_getrhent(void)
+{
+ int err = 0;
+ char *errstr = NULL;
+ char buf[NSS_BUFLEN_TSOL_RH];
+ tsol_rhstr_t result;
+ tsol_rhstr_t *rhstrp = NULL;
+ nss_XbyY_args_t arg;
+
+ NSS_XbyY_INIT(&arg, &result, buf, sizeof (buf), str_to_rhstr);
+ /* No key, no stayopen */
+ arg.status = nss_getent(&db_root, _nss_initf_tsol_rh, &context, &arg);
+ rhstrp = (tsol_rhstr_t *)NSS_XbyY_FINI(&arg);
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "tsol_getrhent: %s\n",
+ rhstrp ? rhstrp->template : "NULL");
+#endif /* DEBUG */
+
+ if (rhstrp == NULL)
+ return (NULL);
+
+ return (rhstr_to_ent(rhstrp, &err, &errstr));
+}
+
+tsol_rhent_t *
+tsol_fgetrhent(FILE *f)
+{
+ int err = 0;
+ char *errstr = NULL;
+ char buf[NSS_BUFLEN_TSOL_RH];
+ tsol_rhstr_t result;
+ tsol_rhstr_t *rhstrp = NULL;
+ tsol_rhent_t *rhentp = NULL;
+ nss_XbyY_args_t arg;
+
+ NSS_XbyY_INIT(&arg, &result, buf, sizeof (buf), str_to_rhstr);
+ _nss_XbyY_fgets(f, &arg);
+ rhstrp = (tsol_rhstr_t *)NSS_XbyY_FINI(&arg);
+ if (rhstrp == NULL)
+ return (NULL);
+ rhentp = rhstr_to_ent(rhstrp, &err, &errstr);
+ while (rhentp == NULL) {
+ /*
+ * Loop until we find a non-blank, non-comment line, or
+ * until EOF. No need to log blank lines, comments.
+ */
+ if (err != LTSNET_EMPTY)
+ (void) fprintf(stderr, "%s: %.32s%s: %s\n",
+ gettext("Error parsing tnrhdb file"), errstr,
+ (strlen(errstr) > 32)? "...": "",
+ (char *)tsol_strerror(err, errno));
+ _nss_XbyY_fgets(f, &arg);
+ rhstrp = (tsol_rhstr_t *)NSS_XbyY_FINI(&arg);
+ if (rhstrp == NULL) /* EOF */
+ return (NULL);
+ rhentp = rhstr_to_ent(rhstrp, &err, &errstr);
+ }
+ return (rhentp);
+}
+
+/*
+ * This is the callback routine for nss.
+ */
+int
+str_to_rhstr(const char *instr, int lenstr, void *entp, char *buffer,
+ int buflen)
+{
+ int len;
+ char *str = NULL;
+ char *last = NULL;
+ char *sep = KV_TOKEN_DELIMIT;
+ tsol_rhstr_t *rhstrp = (tsol_rhstr_t *)entp;
+
+ if ((instr >= buffer && (buffer + buflen) > instr) ||
+ (buffer >= instr && (instr + lenstr) > buffer))
+ return (NSS_STR_PARSE_PARSE);
+ if (lenstr >= buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ (void) strncpy(buffer, instr, buflen);
+ str = _strtok_escape(buffer, sep, &last);
+ rhstrp->address = _do_unescape(str);
+ /*
+ * _do_unesape uses isspace() which removes "\n".
+ * we keep "\n" as we use it in checking for
+ * blank lines.
+ */
+ if (strcmp(instr, "\n") == 0)
+ rhstrp->address = "\n";
+ rhstrp->template = _strtok_escape(NULL, sep, &last);
+ if (rhstrp->template != NULL) {
+ len = strlen(rhstrp->template);
+ if (rhstrp->template[len - 1] == '\n')
+ rhstrp->template[len - 1] = '\0';
+ }
+ if (rhstrp->address == NULL)
+ rhstrp->family = 0;
+ else if (strchr(rhstrp->address, ':') == NULL)
+ rhstrp->family = AF_INET;
+ else
+ rhstrp->family = AF_INET6;
+
+#ifdef DEBUG
+ (void) fprintf(stdout,
+ "str_to_rhstr:str - %s\taddress - %s\n\ttemplate - %s\n",
+ instr, rhstrp->address ? rhstrp->address : "NULL",
+ rhstrp->template ? rhstrp->template : "NULL");
+#endif /* DEBUG */
+
+ return (NSS_STR_PARSE_SUCCESS);
+}
+
+tsol_host_type_t
+tsol_getrhtype(char *rhost) {
+ int herr;
+ struct hostent *hp;
+ in6_addr_t in6;
+ char abuf[INET6_ADDRSTRLEN];
+ tsol_rhent_t rhent;
+ tsol_tpent_t tp;
+
+ if ((hp = getipnodebyname(rhost, AF_INET6,
+ AI_ALL | AI_ADDRCONFIG | AI_V4MAPPED, &herr)) == NULL) {
+ return (UNLABELED);
+ }
+
+ (void) memset(&rhent, 0, sizeof (rhent));
+ (void) memcpy(&in6, hp->h_addr, hp->h_length);
+
+ if (IN6_IS_ADDR_V4MAPPED(&in6)) {
+ rhent.rh_address.ta_family = AF_INET;
+ IN6_V4MAPPED_TO_INADDR(&in6, &rhent.rh_address.ta_addr_v4);
+ (void) inet_ntop(AF_INET, &rhent.rh_address.ta_addr_v4, abuf,
+ sizeof (abuf));
+ } else {
+ rhent.rh_address.ta_family = AF_INET6;
+ rhent.rh_address.ta_addr_v6 = in6;
+ (void) inet_ntop(AF_INET6, &in6, abuf, sizeof (abuf));
+ }
+
+ if (tnrh(TNDB_GET, &rhent) != 0)
+ return (UNLABELED);
+
+ if (rhent.rh_template[0] == '\0')
+ return (UNLABELED);
+
+ (void) strlcpy(tp.name, rhent.rh_template, sizeof (tp.name));
+
+ if (tnrhtp(TNDB_GET, &tp) != 0)
+ return (UNLABELED);
+
+ return (tp.host_type);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/common/tsol_gettpent.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,195 @@
+/*
+ * 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.
+ *
+ * From "tsol_gettpent.c 7.13 00/10/13 SMI; TSOL 2.x"
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+#include <nss_dbdefs.h>
+#include <libtsnet.h>
+#include <secdb.h>
+#include <nss.h>
+#include <libintl.h>
+
+extern void _nss_XbyY_fgets(FILE *, nss_XbyY_args_t *); /* from lib.c */
+
+static int tsol_tp_stayopen; /* Unsynchronized, but it affects only */
+ /* efficiency, not correctness */
+static DEFINE_NSS_DB_ROOT(db_root);
+static DEFINE_NSS_GETENT(context);
+
+
+static void
+_nss_initf_tsol_tp(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_TSOL_TP;
+ p->default_config = NSS_DEFCONF_TSOL_TP;
+}
+
+tsol_tpent_t *
+tsol_gettpbyname(const char *name)
+{
+ int err = 0;
+ char *errstr = NULL;
+ char buf[NSS_BUFLEN_TSOL_TP];
+ tsol_tpstr_t result;
+ tsol_tpstr_t *tpstrp = NULL;
+ nss_XbyY_args_t arg;
+
+ NSS_XbyY_INIT(&arg, &result, buf, sizeof (buf), str_to_tpstr);
+
+ arg.key.name = name;
+ arg.stayopen = tsol_tp_stayopen;
+ arg.h_errno = TSOL_NOT_FOUND;
+ arg.status = nss_search(&db_root, _nss_initf_tsol_tp,
+ NSS_DBOP_TSOL_TP_BYNAME, &arg);
+ tpstrp = (tsol_tpstr_t *)NSS_XbyY_FINI(&arg);
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "tsol_gettpbyname %s: %s\n",
+ name, tpstrp ? tpstrp->template : "NULL");
+#endif /* DEBUG */
+
+ if (tpstrp == NULL)
+ return (NULL);
+
+ return (tpstr_to_ent(tpstrp, &err, &errstr));
+}
+
+void
+tsol_settpent(int stay)
+{
+ tsol_tp_stayopen |= stay;
+ nss_setent(&db_root, _nss_initf_tsol_tp, &context);
+}
+
+void
+tsol_endtpent(void)
+{
+ tsol_tp_stayopen = 0;
+ nss_endent(&db_root, _nss_initf_tsol_tp, &context);
+ nss_delete(&db_root);
+}
+
+tsol_tpent_t *
+tsol_gettpent(void)
+{
+ int err = 0;
+ char *errstr = NULL;
+ char buf[NSS_BUFLEN_TSOL_TP];
+ tsol_tpstr_t result;
+ tsol_tpstr_t *tpstrp = NULL;
+ nss_XbyY_args_t arg;
+
+ NSS_XbyY_INIT(&arg, &result, buf, sizeof (buf), str_to_tpstr);
+ /* No key, no stayopen */
+ arg.status = nss_getent(&db_root, _nss_initf_tsol_tp, &context, &arg);
+ tpstrp = (tsol_tpstr_t *)NSS_XbyY_FINI(&arg);
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "tsol_gettpent: %s\n",
+ tpstrp ? tpstrp->template : "NULL");
+#endif /* DEBUG */
+
+ if (tpstrp == NULL)
+ return (NULL);
+
+ return (tpstr_to_ent(tpstrp, &err, &errstr));
+}
+
+tsol_tpent_t *
+tsol_fgettpent(FILE *f)
+{
+ int err = 0;
+ char *errstr = NULL;
+ char buf[NSS_BUFLEN_TSOL_TP];
+ tsol_tpstr_t result;
+ tsol_tpstr_t *tpstrp = NULL;
+ tsol_tpent_t *tpentp = NULL;
+ nss_XbyY_args_t arg;
+
+ NSS_XbyY_INIT(&arg, &result, buf, sizeof (buf), str_to_tpstr);
+ _nss_XbyY_fgets(f, &arg);
+ tpstrp = (tsol_tpstr_t *)NSS_XbyY_FINI(&arg);
+ if (tpstrp == NULL)
+ return (NULL);
+ tpentp = tpstr_to_ent(tpstrp, &err, &errstr);
+ while (tpentp == NULL) {
+ /*
+ * Loop until we find a non-blank, non-comment line, or
+ * until EOF. No need to log blank lines, comments.
+ */
+ if (err != LTSNET_EMPTY)
+ (void) fprintf(stderr, "%s: %.32s%s: %s\n",
+ gettext("Error parsing tnrhtp file"), errstr,
+ (strlen(errstr) > 32)? "...": "",
+ (char *)tsol_strerror(err, errno));
+ _nss_XbyY_fgets(f, &arg);
+ tpstrp = (tsol_tpstr_t *)NSS_XbyY_FINI(&arg);
+ if (tpstrp == NULL) /* EOF */
+ return (NULL);
+ tpentp = tpstr_to_ent(tpstrp, &err, &errstr);
+ }
+ return (tpentp);
+}
+
+/*
+ * This is the callback routine for nss. It just wraps the tsol_sgettpent
+ * parser.
+ */
+int
+str_to_tpstr(const char *instr, int lenstr, void *entp, char *buffer,
+ int buflen)
+{
+ int len;
+ char *last = NULL;
+ char *sep = KV_TOKEN_DELIMIT;
+ tsol_tpstr_t *tpstrp = (tsol_tpstr_t *)entp;
+
+ if ((instr >= buffer && (buffer + buflen) > instr) ||
+ (buffer >= instr && (instr + lenstr) > buffer))
+ return (NSS_STR_PARSE_PARSE);
+ if (lenstr >= buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ (void) strncpy(buffer, instr, buflen);
+ tpstrp->template = _strtok_escape(buffer, sep, &last);
+ tpstrp->attrs = _strtok_escape(NULL, sep, &last);
+ if (tpstrp->attrs != NULL) {
+ len = strlen(tpstrp->attrs);
+ if (tpstrp->attrs[len - 1] == '\n')
+ tpstrp->attrs[len - 1] = '\0';
+ }
+
+#ifdef DEBUG
+ (void) fprintf(stdout,
+ "str_to_tpstr:\nstr - %s\n\ttemplate - %s\n\tattrs - %s\n",
+ instr, tpstrp->template ? tpstrp->template : "NULL",
+ tpstrp->attrs ? tpstrp->attrs : "NULL");
+#endif /* DEBUG */
+
+ return (NSS_STR_PARSE_SUCCESS);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/common/tsol_getzcent.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,141 @@
+/*
+ * 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 <ctype.h>
+#include <nss_dbdefs.h>
+#include <libtsnet.h>
+
+static int tsol_zc_stayopen; /* Unsynchronized, but it affects only */
+ /* efficiency, not correctness */
+static DEFINE_NSS_DB_ROOT(db_root);
+static DEFINE_NSS_GETENT(context);
+
+struct zc_args {
+ tsol_zcent_t *zc;
+ int err;
+ char *errstr;
+ int errno_val;
+};
+
+static int str2tsol_zcent(const char *, int, void *, char *, int);
+
+static void
+_nss_initf_tsol_zc(nss_db_params_t *p)
+{
+ p->name = NSS_DBNAM_TSOL_ZC;
+ p->default_config = NSS_DEFCONF_TSOL_ZC;
+}
+
+/*
+ * This is just a placeholder. The system doesn't currently lookup tnzonecfg
+ * entries via name services.
+ */
+/* ARGSUSED */
+static void
+switch_callback(void *res, const char *zonename, const char *label,
+ const char *flags, const char *privmlp, const char *globalmlp)
+{
+}
+
+tsol_zcent_t *
+tsol_getzcbyname(const char *name)
+{
+ nss_XbyY_args_t arg;
+ struct zc_args zcargs;
+
+ zcargs.zc = NULL;
+ NSS_XbyY_INIT(&arg, &zcargs, (char *)switch_callback, 1,
+ str2tsol_zcent);
+ arg.key.name = name;
+ arg.stayopen = tsol_zc_stayopen;
+ arg.h_errno = TSOL_NOT_FOUND;
+ arg.status = nss_search(&db_root, _nss_initf_tsol_zc,
+ NSS_DBOP_TSOL_ZC_BYNAME, &arg);
+ (void) NSS_XbyY_FINI(&arg);
+ if (arg.status != 0) {
+ tsol_freezcent(zcargs.zc);
+ zcargs.zc = NULL;
+ }
+ return (zcargs.zc);
+}
+
+void
+tsol_setzcent(int stay)
+{
+ tsol_zc_stayopen |= stay;
+ nss_setent(&db_root, _nss_initf_tsol_zc, &context);
+}
+
+void
+tsol_endzcent(void)
+{
+ tsol_zc_stayopen = 0;
+ nss_endent(&db_root, _nss_initf_tsol_zc, &context);
+ nss_delete(&db_root);
+}
+
+struct tsol_zcent *
+tsol_getzcent(void)
+{
+ nss_XbyY_args_t arg;
+ struct zc_args zcargs;
+
+ zcargs.zc = NULL;
+ zcargs.errno_val = errno;
+ NSS_XbyY_INIT(&arg, &zcargs, (char *)switch_callback, 1,
+ str2tsol_zcent);
+ /* No key, no stayopen */
+ arg.status = nss_getent(&db_root, _nss_initf_tsol_zc, &context, &arg);
+ (void) NSS_XbyY_FINI(&arg);
+ if (arg.status != 0) {
+ tsol_freezcent(zcargs.zc);
+ zcargs.zc = NULL;
+ }
+ if (zcargs.zc == NULL && zcargs.err == LTSNET_SYSERR)
+ errno = zcargs.errno_val;
+ return (zcargs.zc);
+}
+
+/*
+ * This is the callback routine for nss. It just wraps the tsol_sgetzcent
+ * parser.
+ */
+/* ARGSUSED */
+static int
+str2tsol_zcent(const char *instr, int lenstr, void *entp, char *buffer,
+ int buflen)
+{
+ struct zc_args *zcargs = entp;
+
+ if (zcargs->zc != NULL)
+ tsol_freezcent(zcargs->zc);
+ zcargs->zc = tsol_sgetzcent(instr, &zcargs->err, &zcargs->errstr);
+ zcargs->errno_val = errno;
+
+ return (zcargs->zc == NULL ? NSS_STR_PARSE_PARSE :
+ NSS_STR_PARSE_SUCCESS);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/common/tsol_sgetrhent.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,272 @@
+/*
+ * 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.
+ *
+ * From "tsol_tndb_parser.c 7.24 01/09/05 SMI; TSOL 2.x"
+ *
+ * These functions parse entries in the "thrhdb" (remote host database) file.
+ * Each entry in the file has two fields, separated by a colon. The first
+ * field is the IP host or network address. The second is the name of the
+ * template to use (from tnrhtp).
+ *
+ * In order to help preserve sanity, we do not allow more than one unescaped
+ * colon in a line.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <strings.h>
+#include <libtsnet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <inet/ip.h>
+#include <arpa/inet.h>
+#include <nss.h>
+#include <errno.h>
+
+/*
+ * This routine deals with old pre-CIDR subnet address specifications. In the
+ * bad old days, a subnet was represented as:
+ *
+ * Expression Implied Prefix
+ * 10.1.1.0 /24
+ * 10.1.0.0 /16
+ * 10.0.0.0 /8
+ * 0.0.0.0 /0
+ */
+static int
+get_classful_prefix(in_addr_t addr)
+{
+ int bits;
+
+ if (addr == 0)
+ return (0);
+ addr = ntohl(addr);
+ for (bits = IP_ABITS; bits > 0 && (addr & 0xFF) == 0; bits -= 8)
+ addr >>= 8;
+
+ return (bits);
+}
+
+/*
+ * This routine deals with old pre-CIDR network address specifications. In the
+ * bad old days, a network was represented as:
+ *
+ * Expression Implied Prefix
+ * 10.1.1 /24
+ * 10.1 /16
+ * 10 /8
+ *
+ * This routine must compute the mask and left-align the address.
+ */
+static int
+get_network_prefix(in_addr_t *addrp)
+{
+ int bits;
+ in_addr_t addr;
+
+ addr = ntohl(*addrp);
+ for (bits = IP_ABITS; bits > 0 && addr < 0x01000000; bits -= 8)
+ addr <<= 8;
+ *addrp = htonl(addr);
+
+ return (bits);
+}
+
+static boolean_t
+parse_address(tsol_rhent_t *rh, const char *addrbuf)
+{
+ int upper_lim;
+ int len;
+ const uchar_t *aptr;
+
+ if (strchr(addrbuf, ':') == NULL) {
+ /* IPv4 address */
+ rh->rh_address.ta_family = AF_INET;
+ if (inet_pton(AF_INET, addrbuf,
+ &rh->rh_address.ta_addr_v4) > 0) {
+ if (rh->rh_prefix == -1)
+ rh->rh_prefix = get_classful_prefix(rh->
+ rh_address.ta_addr_v4.s_addr);
+ } else if ((rh->rh_address.ta_addr_v4.s_addr =
+ inet_network(addrbuf)) != (in_addr_t)-1) {
+ len = get_network_prefix(&rh->rh_address.ta_addr_v4.
+ s_addr);
+ if (rh->rh_prefix == -1)
+ rh->rh_prefix = len;
+ } else {
+ return (B_FALSE);
+ }
+ upper_lim = IP_ABITS;
+ aptr = (const uchar_t *)&rh->rh_address.ta_addr_v4;
+ } else {
+ /* IPv6 address */
+ rh->rh_address.ta_family = AF_INET6;
+ if (inet_pton(AF_INET6, addrbuf,
+ &rh->rh_address.ta_addr_v6) <= 0)
+ return (B_FALSE);
+ if (rh->rh_prefix == -1)
+ rh->rh_prefix = IPV6_ABITS;
+ upper_lim = IPV6_ABITS;
+ aptr = (const uchar_t *)&rh->rh_address.ta_addr_v6;
+ }
+
+ if (rh->rh_prefix < 0 || rh->rh_prefix > upper_lim)
+ return (B_FALSE);
+
+ /*
+ * Verify that there are no bits set in the "host" portion of the
+ * IP address.
+ */
+ len = rh->rh_prefix;
+ aptr += len / 8;
+ if ((len & 7) != 0) {
+ if ((*aptr++ & (0xff >> (len & 7))) != 0)
+ return (B_FALSE);
+ len = (len + 7) & ~7;
+ }
+ while (len < upper_lim) {
+ if (*aptr++ != 0)
+ return (B_FALSE);
+ len += 8;
+ }
+
+ return (B_TRUE);
+}
+
+tsol_rhent_t *
+rhstr_to_ent(tsol_rhstr_t *rhstrp, int *errp, char **errstrp)
+{
+ int len;
+ int err = 0;
+ char *cp, *cp2, *errstr;
+ char *address = rhstrp->address;
+ char *template = rhstrp->template;
+ char addrbuf[1024];
+ tsol_rhent_t *rhentp = NULL;
+
+ /*
+ * The user can specify NULL pointers for these. Make sure that we
+ * don't have to deal with checking for NULL everywhere by just
+ * pointing to our own variables if the user gives NULL.
+ */
+ if (errp == NULL)
+ errp = &err;
+ if (errstrp == NULL)
+ errstrp = &errstr;
+ /* The default, unless we find a more specific error locus. */
+ *errstrp = address;
+
+ if (address == NULL || *address == '#' || *address == '\n') {
+ *errp = LTSNET_EMPTY;
+ if (template && *template != '\0' && *template != '#' &&
+ *template != '\n')
+ *errstrp = template;
+ else if (address == NULL)
+ *errstrp = " ";
+ goto err_ret;
+ }
+ if (*address == '\0') {
+ *errp = LTSNET_NO_ADDR;
+ if (template && *template != '\0' && *template != '#' &&
+ *template != '\n')
+ *errstrp = template;
+ goto err_ret;
+ }
+ if (template == NULL || *template == '#' || *template == '\n' ||
+ *template == '\0') {
+ *errp = LTSNET_NO_HOSTTYPE;
+ goto err_ret;
+ }
+ if ((rhentp = calloc(1, sizeof (*rhentp))) == NULL) {
+ *errp = LTSNET_SYSERR;
+ return (NULL);
+ }
+ if ((cp = strrchr(address, '/')) != NULL) {
+ len = cp - address;
+ if (len >= sizeof (addrbuf)) {
+ *errp = LTSNET_ILL_ADDR;
+ goto err_ret;
+ }
+ (void) memset(addrbuf, '\0', sizeof (addrbuf));
+ (void) memcpy(addrbuf, address, len);
+ cp++;
+ errno = 0;
+ rhentp->rh_prefix = strtol(cp, &cp2, 0);
+ if (errno != 0) {
+ *errp = LTSNET_SYSERR;
+ *errstrp = cp2;
+ goto err_ret;
+ }
+ if ((isdigit(*cp) == 0)) {
+ *errp = LTSNET_ILL_ADDR;
+ *errstrp = address;
+ goto err_ret;
+ }
+ } else {
+ rhentp->rh_prefix = -1;
+ (void) strlcpy(addrbuf, address, sizeof (addrbuf));
+ }
+ if (strlcpy(rhentp->rh_template, template,
+ sizeof (rhentp->rh_template)) >= sizeof (rhentp->rh_template)) {
+ *errstrp = template;
+ *errp = LTSNET_ILL_NAME;
+ goto err_ret;
+ }
+ if (!parse_address(rhentp, addrbuf)) {
+ *errp = LTSNET_ILL_ADDR;
+ *errstrp = address;
+ goto err_ret;
+ }
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "rhstr_to_ent: %s:%s\n",
+ address, rhentp->rh_template);
+#endif /* DEBUG */
+
+ return (rhentp);
+
+err_ret:
+ err = errno;
+ tsol_freerhent(rhentp);
+ errno = err;
+#ifdef DEBUG
+ (void) fprintf(stderr, "\nrhstr_to_ent: %s: %s\n",
+ *errstrp, (char *)tsol_strerror(*errp, errno));
+#endif /* DEBUG */
+
+ return (NULL);
+}
+
+void
+tsol_freerhent(tsol_rhent_t *rh)
+{
+ if (rh != NULL)
+ free(rh);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/common/tsol_sgettpent.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,301 @@
+/*
+ * 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.
+ *
+ * From "tsol_tndb_parser.c 7.24 01/09/05 SMI; TSOL 2.x"
+ *
+ * These functions parse entries in the "tnrhtp" (remote host template) file.
+ * Each entry in this file has two fields, separated by a colon. The first
+ * field is the template name. The second is a list of "key=value" attributes,
+ * separated by semicolons.
+ *
+ * In order to help preserve sanity, we do not allow more than one unescaped
+ * colon in a line, nor any unescaped '=' or ';' characters in the template
+ * name. Such things are indicative of typing errors, not intentional
+ * configuration.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <strings.h>
+#include <libtsnet.h>
+#include <tsol/label.h>
+#include <sys/types.h>
+#include <nss.h>
+#include <secdb.h>
+#include <errno.h>
+
+static int
+get_tn_doi(tsol_tpent_t *tpentp, kva_t *kv)
+{
+ char *cp;
+ char *val = NULL;
+
+ val = kva_match(kv, TP_DOI);
+ if (val == NULL)
+ return (LTSNET_NO_DOI);
+
+ errno = 0;
+ tpentp->tp_doi = strtol(val, &cp, 0);
+ if (errno != 0)
+ return (LTSNET_SYSERR);
+ if (*cp != '\0')
+ return (LTSNET_ILL_DOI);
+
+ return (0);
+}
+
+static int
+get_tn_sl_range(brange_t *range, char *min, char *max)
+{
+ int err = 0;
+
+ if (min == NULL && max == NULL)
+ return (LTSNET_NO_RANGE);
+ if (min == NULL)
+ return (LTSNET_NO_LOWERBOUND);
+ if (max == NULL)
+ return (LTSNET_NO_UPPERBOUND);
+
+ if (stobsl(min, &range->lower_bound, NO_CORRECTION, &err) == 0)
+ return (LTSNET_ILL_LOWERBOUND);
+ if (stobsl(max, &range->upper_bound, NO_CORRECTION, &err) == 0)
+ return (LTSNET_ILL_UPPERBOUND);
+ if (!bldominates(&range->upper_bound, &range->lower_bound))
+ return (LTSNET_ILL_RANGE);
+
+ return (0);
+}
+
+static int
+get_tn_sl_set(blset_t *labelset, char *setstr)
+{
+ int sc, err;
+ char *tokp, *finally;
+ bslabel_t *labels;
+
+ (void) memset(labelset, 0, sizeof (blset_t));
+ labels = (bslabel_t *)labelset;
+ tokp = strtok_r(setstr, TNDB_COMMA, &finally);
+ for (sc = 0; tokp != NULL && sc < NSLS_MAX; sc++) {
+ if (stobsl(tokp, &labels[sc], NO_CORRECTION, &err) == 0)
+ return (LTSNET_ILL_LABEL);
+ tokp = strtok_r(NULL, TNDB_COMMA, &finally);
+ }
+ if (tokp != NULL && sc >= NSLS_MAX)
+ return (LTSNET_SET_TOO_BIG);
+
+ return (0);
+}
+
+static int
+parse_remainder(tsol_tpent_t *tpentp, kva_t *kv)
+{
+ int err = 0;
+ char *val = NULL;
+ char *val2 = NULL;
+
+ val = kva_match(kv, TP_HOSTTYPE);
+
+ if (val == NULL)
+ return (LTSNET_NO_HOSTTYPE);
+ if (strcasecmp(val, TP_UNLABELED) == 0)
+ tpentp->host_type = UNLABELED;
+ else if (strcasecmp(val, TP_CIPSO) == 0)
+ tpentp->host_type = SUN_CIPSO;
+ else
+ return (LTSNET_ILL_HOSTTYPE);
+
+ /*
+ * parse fields by host type -
+ * add on to the following if statement for each new host type.
+ */
+ if (tpentp->host_type == UNLABELED) {
+ tpentp->tp_mask_unl = 0;
+ /*
+ * doi
+ */
+ if ((err = get_tn_doi(tpentp, kv)) != 0)
+ return (err);
+ tpentp->tp_mask_unl |= TSOL_MSK_CIPSO_DOI;
+ /*
+ * default label
+ */
+ val = kva_match(kv, TP_DEFLABEL);
+ if (val == NULL)
+ return (LTSNET_NO_LABEL);
+ if (stobsl(val, &tpentp->tp_def_label, NO_CORRECTION,
+ &err) == 0)
+ return (LTSNET_ILL_LABEL);
+ tpentp->tp_mask_unl |= TSOL_MSK_DEF_LABEL;
+ /*
+ * check label range
+ */
+ val = kva_match(kv, TP_MINLABEL);
+ val2 = kva_match(kv, TP_MAXLABEL);
+ if (val == NULL && val2 == NULL) {
+ /*
+ * This is the old format. Use ADMIN_LOW to SL of the
+ * default label as the gw_sl_range.
+ */
+ bsllow(&tpentp->tp_gw_sl_range.lower_bound);
+ tpentp->tp_gw_sl_range.upper_bound =
+ tpentp->tp_def_label;
+ } else {
+ err = get_tn_sl_range(&tpentp->tp_gw_sl_range, val,
+ val2);
+ if (err != 0)
+ return (err);
+ }
+ tpentp->tp_mask_unl |= TSOL_MSK_SL_RANGE_TSOL;
+
+ /*
+ * also label set, if present. (optional)
+ */
+ val = kva_match(kv, TP_SET);
+ if (val != NULL) {
+ err = get_tn_sl_set(&tpentp->tp_gw_sl_set, val);
+ if (err != 0)
+ return (err);
+ tpentp->tp_mask_cipso |= TSOL_MSK_SL_RANGE_TSOL;
+ }
+ } else {
+ tpentp->tp_mask_cipso = 0;
+ /*
+ * doi
+ */
+ if ((err = get_tn_doi(tpentp, kv)) != 0)
+ return (err);
+ tpentp->tp_mask_cipso |= TSOL_MSK_CIPSO_DOI;
+ /*
+ * label range
+ */
+ val = kva_match(kv, TP_MINLABEL);
+ val2 = kva_match(kv, TP_MAXLABEL);
+ err = get_tn_sl_range(&tpentp->tp_sl_range_cipso, val, val2);
+ if (err != 0)
+ return (err);
+ tpentp->tp_mask_cipso |= TSOL_MSK_SL_RANGE_TSOL;
+ /*
+ * also label set, if present. (optional)
+ */
+ val = kva_match(kv, TP_SET);
+ if (val != NULL) {
+ err = get_tn_sl_set(&tpentp->tp_sl_set_cipso, val);
+ if (err != 0)
+ return (err);
+ tpentp->tp_mask_cipso |= TSOL_MSK_SL_RANGE_TSOL;
+ }
+
+ /* CIPSO entries don't support default labels */
+ val = kva_match(kv, TP_DEFLABEL);
+ if (val != NULL)
+ return (LTSNET_BAD_TYPE);
+ }
+
+ return (0);
+}
+
+tsol_tpent_t *
+tpstr_to_ent(tsol_tpstr_t *tpstrp, int *errp, char **errstrp)
+{
+ int err = 0;
+ char *errstr;
+ char *template = tpstrp->template;
+ char *attrs = tpstrp->attrs;
+ kva_t *kv;
+ tsol_tpent_t *tpentp = NULL;
+
+ /*
+ * The user can specify NULL pointers for these. Make sure that we
+ * don't have to deal with checking for NULL everywhere by just
+ * pointing to our own variables if the user gives NULL.
+ */
+ if (errp == NULL)
+ errp = &err;
+ if (errstrp == NULL)
+ errstrp = &errstr;
+ /* The default, unless we find a more specific error locus. */
+ *errstrp = template;
+
+ if (template == NULL || *template == '#' || *template == '\n') {
+ *errp = LTSNET_EMPTY;
+ if (attrs && *attrs != '\0' && *attrs != '#' && *attrs != '\n')
+ *errstrp = attrs;
+ else if (template == NULL)
+ *errstrp = " ";
+ goto err_ret;
+ }
+ if (*template == '\0') {
+ *errp = LTSNET_NO_NAME;
+ if (attrs && *attrs != '\0' && *attrs != '#' && *attrs != '\n')
+ *errstrp = attrs;
+ goto err_ret;
+ }
+ if (attrs == NULL || *attrs == '\0' || *attrs == '#' ||
+ *attrs == '\n') {
+ *errp = LTSNET_NO_ATTRS;
+ goto err_ret;
+ }
+ if ((tpentp = calloc(1, sizeof (*tpentp))) == NULL) {
+ *errp = LTSNET_SYSERR;
+ return (NULL);
+ }
+ if (strlcpy(tpentp->name, template, sizeof (tpentp->name)) >=
+ sizeof (tpentp->name))
+ goto err_ret;
+ kv = _str2kva(attrs, KV_ASSIGN, KV_DELIMITER);
+ *errp = parse_remainder(tpentp, kv);
+ _kva_free(kv);
+ if (*errp == 0) {
+#ifdef DEBUG
+ (void) fprintf(stdout, "tpstr_to_ent: %s:%s\n", tpentp->name,
+ attrs);
+#endif /* DEBUG */
+
+ return (tpentp);
+ }
+
+err_ret:
+ err = errno;
+ tsol_freetpent(tpentp);
+ errno = err;
+#ifdef DEBUG
+ (void) fprintf(stderr, "\ntpstr_to_ent: %s:%s\n",
+ *errstrp, (char *)tsol_strerror(*errp, errno));
+#endif /* DEBUG */
+
+ return (NULL);
+}
+
+void
+tsol_freetpent(tsol_tpent_t *tp)
+{
+ if (tp != NULL)
+ free(tp);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/common/tsol_sgetzcent.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,285 @@
+/*
+ * 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.
+ *
+ * From "tsol_tndb_parser.c 7.24 01/09/05 SMI; TSOL 2.x"
+ *
+ * These functions parse entries in the "tnzonecfg" (zone configuration) file.
+ * Each entry in this file has five fields, separated by a colon. These fields
+ * are:
+ *
+ * zone name : label : flags : zone-specific MLPs : global MLPs
+ *
+ * The fourth and fifth fields contain subfields consisting of MLP entries
+ * separated by semicolons. The MLP entries are of the form:
+ *
+ * port[-port]/protocol
+ *
+ * In order to help preserve sanity, we do not allow more than four unescaped
+ * colons in a line, nor any unescaped ';' characters in the non-MLP fields.
+ * Such things are indicative of typing errors, not intentional configuration.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <strings.h>
+#include <libtsnet.h>
+#include <tsol/label.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <nss.h>
+#include <errno.h>
+#include <secdb.h>
+
+/*
+ * Parse an MLP specification in port1-port2/proto or port/proto form.
+ */
+static int
+str_to_mlp(char *mlp_str, tsol_mlp_t *zone_mlp)
+{
+ char *fieldp;
+ char *lasts, *cp;
+ int i;
+ ulong_t ulv;
+ struct protoent proto;
+ char gbuf[1024];
+
+ (void) memset(zone_mlp, 0, sizeof (tsol_mlp_t));
+
+ fieldp = strtok_r(mlp_str, KV_DELIMITER, &lasts);
+ if (fieldp == NULL)
+ return (-1);
+
+ errno = 0;
+ for (i = 0; fieldp != NULL && i < NMLP_MAX; i++) {
+ ulv = strtoul(fieldp, &cp, 0);
+ zone_mlp[i].mlp_port = (uint16_t)ulv;
+ zone_mlp[i].mlp_port_upper = 0;
+ if (errno != 0 || ulv > 65535)
+ return (-1);
+ if (*cp == '-') {
+ ulv = strtol(cp + 1, &cp, 0);
+ zone_mlp[i].mlp_port_upper = (uint16_t)ulv;
+ if (errno != 0 || ulv > 65535)
+ return (-1);
+ }
+ if (*cp != '/')
+ return (-1);
+ fieldp = cp + 1;
+ ulv = strtol(fieldp, &cp, 0);
+ if (errno == 0 && ulv <= 255 && *cp == '\0')
+ zone_mlp->mlp_ipp = (uint8_t)ulv;
+ else if (getprotobyname_r(fieldp, &proto, gbuf,
+ sizeof (gbuf)) != NULL)
+ zone_mlp->mlp_ipp = proto.p_proto;
+ else
+ return (-1);
+ fieldp = strtok_r(NULL, KV_DELIMITER, &lasts);
+ }
+ return (0);
+}
+
+static boolean_t
+parse_mlp_list(tsol_mlp_t **list, char *str, int *errp, char **errstrp)
+{
+ int mmax;
+ tsol_mlp_t *mlp;
+ char *tokp, *finally;
+ int mc;
+
+ mmax = 0;
+ if ((mlp = *list) != NULL) {
+ while (!TSOL_MLP_END(mlp)) {
+ mmax++;
+ mlp++;
+ }
+ mmax++;
+ }
+ mlp = *list;
+ tokp = strtok_r(str, KV_DELIMITER, &finally);
+ for (mc = 0; tokp != NULL; mc++) {
+ if (mc >= mmax) {
+ mmax += 8;
+ mlp = realloc(mlp, mmax * sizeof (*mlp));
+ if (mlp == NULL) {
+ *errp = LTSNET_SYSERR;
+ *errstrp = tokp;
+ return (B_FALSE);
+ }
+ *list = mlp;
+ }
+ if (str_to_mlp(tokp, mlp + mc) == -1) {
+ *errp = LTSNET_ILL_MLP;
+ *errstrp = tokp;
+ return (B_FALSE);
+ }
+ tokp = strtok_r(NULL, KV_DELIMITER, &finally);
+ }
+ if (mc >= mmax) {
+ mlp = realloc(mlp, (mmax + 1) * sizeof (*mlp));
+ if (mlp == NULL) {
+ *errp = LTSNET_SYSERR;
+ *errstrp = finally;
+ return (B_FALSE);
+ }
+ *list = mlp;
+ }
+ (void) memset(mlp + mc, 0, sizeof (*mlp));
+ return (B_TRUE);
+}
+
+tsol_zcent_t *
+tsol_sgetzcent(const char *instr, int *errp, char **errstrp)
+{
+ int err;
+ char *errstr;
+ tsol_zcent_t *zc;
+ const char *nextf;
+ char *cp;
+ char fieldbuf[1024];
+
+ /*
+ * The user can specify NULL pointers for these. Make sure that we
+ * don't have to deal with checking for NULL everywhere by just
+ * pointing to our own variables if the user gives NULL.
+ */
+ if (errp == NULL)
+ errp = &err;
+ if (errstrp == NULL)
+ errstrp = &errstr;
+
+ /* The default, unless we find a more specific error locus. */
+ *errstrp = (char *)instr;
+
+ if ((zc = calloc(1, sizeof (*zc))) == NULL) {
+ *errp = LTSNET_SYSERR;
+ return (NULL);
+ }
+
+ /* First, parse off the zone name. */
+ instr = parse_entry(zc->zc_name, sizeof (zc->zc_name), instr, "#;:\n");
+ if (zc->zc_name[0] == '\0') {
+ *errstrp = (char *)instr;
+ if (*instr == '\0' || *instr == '#' || *instr == '\n')
+ *errp = LTSNET_EMPTY;
+ else if (*instr == ':')
+ *errp = LTSNET_NO_NAME;
+ else
+ *errp = LTSNET_ILL_NAME;
+ goto err_ret;
+ }
+ if (*instr != ':') {
+ *errstrp = (char *)instr;
+ if (*instr == '=' || *instr == ';')
+ *errp = LTSNET_ILL_NAME;
+ else
+ *errp = LTSNET_ILL_ENTRY;
+ goto err_ret;
+ }
+ instr++;
+
+ /* Field two: parse off the label. */
+ nextf = parse_entry(fieldbuf, sizeof (fieldbuf), instr, "#;:\n");
+ if (*nextf != ':') {
+ *errstrp = (char *)nextf;
+ *errp = LTSNET_ILL_ENTRY;
+ goto err_ret;
+ }
+ if (fieldbuf[0] == '\0') {
+ *errstrp = (char *)instr;
+ *errp = LTSNET_NO_LABEL;
+ goto err_ret;
+ }
+ if (stobsl(fieldbuf, &zc->zc_label, NO_CORRECTION, &err) == 0) {
+ *errstrp = (char *)instr;
+ *errp = LTSNET_ILL_LABEL;
+ goto err_ret;
+ }
+ instr = nextf + 1;
+
+ /* Not in the entry, but should be */
+ zc->zc_doi = 1;
+
+ /* Field three: get match flag */
+ errno = 0;
+ zc->zc_match = (uchar_t)strtol(instr, &cp, 0);
+ if (errno != 0 || (*cp != ':' && *cp != '\0')) {
+ *errp = LTSNET_ILL_FLAG;
+ *errstrp = (char *)instr;
+ goto err_ret;
+ }
+ if (*cp != ':') {
+ *errp = LTSNET_ILL_VALDELIM;
+ *errstrp = cp;
+ goto err_ret;
+ }
+ instr = cp + 1;
+
+ /* Field four: get zone-specific MLP list. */
+ nextf = parse_entry(fieldbuf, sizeof (fieldbuf), instr, "#:\n");
+ if (*nextf != ':') {
+ *errstrp = (char *)nextf;
+ *errp = LTSNET_ILL_ENTRY;
+ goto err_ret;
+ }
+ if (!parse_mlp_list(&zc->zc_private_mlp, fieldbuf, errp, errstrp)) {
+ *errstrp = (char *)instr + (*errstrp - fieldbuf);
+ goto err_ret;
+ }
+ instr = nextf + 1;
+
+ /* Field five: get global MLP list. */
+ nextf = parse_entry(fieldbuf, sizeof (fieldbuf), instr, "#:\n");
+ if (*nextf != '\0' && *nextf != '#' && !isspace(*nextf)) {
+ *errstrp = (char *)nextf;
+ *errp = LTSNET_ILL_ENTRY;
+ goto err_ret;
+ }
+ if (!parse_mlp_list(&zc->zc_shared_mlp, fieldbuf, errp, errstrp)) {
+ *errstrp = (char *)instr + (*errstrp - fieldbuf);
+ goto err_ret;
+ }
+
+ return (zc);
+
+err_ret:
+ err = errno;
+ tsol_freezcent(zc);
+ errno = err;
+ return (NULL);
+}
+
+void
+tsol_freezcent(tsol_zcent_t *zc)
+{
+ if (zc != NULL) {
+ free(zc->zc_private_mlp);
+ free(zc->zc_shared_mlp);
+ free(zc);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/i386/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,35 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+
+MAPDIR= ../spec/i386
+include ../Makefile.com
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/sparc/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,32 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/sparcv9/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,31 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/spec/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,30 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libtsnet/spec/Makefile
+#
+
+include $(SRC)/lib/Makefile.spec.arch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/spec/Makefile.targ Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,35 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libtsnet/spec/Makefile.targ
+#
+
+LIBRARY= libtsnet.a
+VERS= .1
+
+OBJECTS= tsnet.o
+
+SPECCPP += -I../../
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/spec/amd64/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+include $(SRC)/lib/Makefile.spec
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/spec/i386/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libtsnet/spec/i386/Makefile
+#
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.spec
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/spec/sparc/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libtsnet/spec/sparc/Makefile
+#
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.spec
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/spec/sparcv9/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+include $(SRC)/lib/Makefile.spec
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/spec/tsnet.spec Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,206 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libtsnet/spec/tsnet.spec
+#
+
+function tsol_gettpbyname
+include <libtsnet.h>
+declaration tsol_tpent_t *tsol_gettpbyname(const char *name);
+version SUNWprivate_1.1
+exception $return == 0
+end
+
+function tsol_gettpent
+include <libtsnet.h>
+declaration tsol_tpent_t *tsol_gettpent(void);
+version SUNWprivate_1.1
+exception $return == 0
+end
+
+function tsol_fgettpent
+include <libtsnet.h>
+declaration tsol_tpent_t *tsol_gettpent(FILE *);
+version SUNWprivate_1.1
+exception $return == 0
+end
+
+function tsol_freetpent
+include <libtsnet.h>
+declaration void tsol_freetpent(tsol_tpent_t *);
+version SUNWprivate_1.1
+exception $return == 0
+end
+
+function tsol_settpent
+include <libtsnet.h>
+declaration void tsol_settpent(int stay);
+version SUNWprivate_1.1
+end
+
+function tsol_endtpent
+include <libtsnet.h>
+declaration void tsol_endtpent(void);
+version SUNWprivate_1.1
+end
+
+function str_to_tpstr
+include <libtsnet.h>
+declaration int str_to_tpstr(const char *, int, void *, char *, int);
+version SUNWprivate_1.1
+end
+
+function tpstr_to_ent
+include <libtsnet.h>
+declaration tsol_tpent_t *tpstr_to_ent(tsol_tpstr_t *, int *, char **);
+version SUNWprivate_1.1
+end
+
+function tsol_getrhbyaddr
+include <libtsnet.h>
+declaration tsol_rhent_t *tsol_getrhbyaddr(const void *addr, size_t len, \
+ int type);
+version SUNWprivate_1.1
+exception $return == 0
+end
+
+function tsol_getrhent
+include <libtsnet.h>
+declaration tsol_rhent_t *tsol_getrhent(void);
+version SUNWprivate_1.1
+exception $return == 0
+end
+
+function tsol_fgetrhent
+include <libtsnet.h>
+declaration tsol_rhent_t *tsol_getrhent(FILE *);
+version SUNWprivate_1.1
+exception $return == 0
+end
+
+function tsol_freerhent
+include <libtsnet.h>
+declaration void tsol_freerhent(tsol_rhent_t *);
+version SUNWprivate_1.1
+exception $return == 0
+end
+
+function tsol_setrhent
+include <libtsnet.h>
+declaration void tsol_setrhent(int stay);
+version SUNWprivate_1.1
+end
+
+function tsol_endrhent
+include <libtsnet.h>
+declaration void tsol_endrhent(void);
+version SUNWprivate_1.1
+end
+
+function str_to_rhstr
+include <libtsnet.h>
+declaration int str_to_rhstr(const char *, int, void *, char *, int);
+version SUNWprivate_1.1
+end
+
+function rhstr_to_ent
+include <libtsnet.h>
+declaration tsol_rhent_t *rhstr_to_ent(tsol_rhstr_t *, int *, char **);
+version SUNWprivate_1.1
+end
+
+function tsol_getrhtype
+include <libtsnet.h>
+declaration tsol_host_type_t tsol_getrhtype(char *);
+version SUNWprivate_1.1
+end
+
+function tsol_sgetzcent
+include <libtsnet.h>
+declaration tsol_zcent_t *tsol_sgetzcent(const char *instr, int *errp, \
+ char **errstrp);
+version SUNWprivate_1.1
+exception $return == 0
+end
+
+function tsol_freezcent
+include <libtsnet.h>
+declaration void tsol_freezcent(tsol_zcent_t *);
+version SUNWprivate_1.1
+exception $return == 0
+end
+
+function sl_to_str
+include <libtsnet.h>
+declaration const char *sl_to_str(const bslabel_t *sl);
+version SUNWprivate_1.1
+end
+
+function rtsa_to_str
+include <libtsnet.h>
+declaration const char *rtsa_to_str(const struct rtsa_s *rtsa, \
+ char *line, size_t len);
+version SUNWprivate_1.1
+exception $return == 0
+end
+
+function rtsa_keyword
+include <libtsnet.h>
+declaration boolean_t rtsa_keyword(const char *opt, struct rtsa_s *rtsa, \
+ int *errp, char **errstr);
+version SUNWprivate_1.1
+exception $return == 0
+end
+
+function tsol_strerror
+include <libtsnet.h>
+declaration const char *tsol_strerror(int libtserr, int errnoval);
+version SUNWprivate_1.1
+end
+
+function tnrhtp
+include <libtsnet.h>
+declaration int tnrhtp(int cmd, tsol_tpent_t *buf);
+version SUNWprivate_1.1
+errno ENOSYS EFAULT EINVAL ENOENT EOPNOTSUPP EPERM
+exception $return == -1
+end
+
+function tnrh
+include <libtsnet.h>
+declaration int tnrh(int cmd, tsol_rhent_t *buf);
+version SUNWprivate_1.1
+errno ENOSYS EFAULT EINVAL ENOENT EOPNOTSUPP EPERM ENOMEM
+exception $return == -1
+end
+
+function tnmlp
+include <libtsnet.h>
+declaration int tnmlp(int cmd, tsol_mlpent_t *buf);
+version SUNWprivate_1.1
+errno ENOSYS EFAULT EINVAL ENOENT EEXIST EOPNOTSUPP EPERM
+exception $return == -1
+end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsnet/spec/versions Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,35 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libtsnet/spec/versions
+#
+
+sparc {
+ SUNWprivate_1.1;
+}
+i386 {
+ SUNWprivate_1.1;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,73 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#ident "%Z%%M% %I% %E% SMI"
+
+#
+# lib/libtsol/Makefile
+#
+
+include ../Makefile.lib
+
+HDRS = label.h
+HDRDIR = common
+SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+POFILE = libtsol.po
+MSGFILES = common/btos.c common/private.c common/stob.c
+XGETFLAGS = -a
+
+all := TARGET = all
+clean := TARGET = clean
+clobber := TARGET = clobber
+install := TARGET = install
+lint := TARGET = lint
+
+.KEEP_STATE:
+
+# Override so that label.h gets installed where expected.
+ROOTHDRDIR= $(ROOT)/usr/include/tsol
+
+all clean clobber install: spec .WAIT $(SUBDIRS)
+
+lint: $(SUBDIRS)
+
+install_h: $(ROOTHDRS)
+
+check: $(CHECKHDRS)
+
+$(POFILE): $(MSGFILES)
+ $(BUILDPO.msgfiles)
+
+_msg: $(MSGDOMAINPOFILE)
+
+$(SUBDIRS) spec: FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include $(SRC)/Makefile.msg.targ
+include $(SRC)/lib/Makefile.targ
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/Makefile.com Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,74 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#ident "%Z%%M% %I% %E% SMI"
+
+#
+# lib/libtsol/Makefile.com
+#
+
+LIBRARY = libtsol.a
+VERS = .2
+
+OBJECTS = \
+ blabel.o btohex.o btos.o call_labeld.o \
+ getlabel.o getplabel.o hextob.o \
+ ltos.o misc.o getpathbylabel.o private.o privlib.o \
+ setflabel.o stob.o stol.o zone.o
+
+include ../../Makefile.lib
+
+# install this library in the root filesystem
+include ../../Makefile.rootfs
+
+LIBS = $(DYNLIB) $(LINTLIB)
+$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC)
+LDLIBS += -lsecdb -lc
+
+NONCOMMON = $(OBJECTS:blabel.o=)
+lint:= SRCS = $(NONCOMMON:%.o=$(SRCDIR)/%.c) $(COMMONDIR)/blabel.c
+
+SRCDIR = ../common
+MAPDIR = ../spec/$(TRANSMACH)
+SPECMAPFILE = $(MAPDIR)/mapfile
+
+COMMONDIR= $(SRC)/common/tsol
+
+CFLAGS += $(CCVERBOSE)
+CPPFLAGS += -D_REENTRANT -I$(SRCDIR) -I$(COMMONDIR)
+
+LINTFLAGS64 += -Xarch=v9
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+objs/%.o pic_profs/%.o pics/%.o: $(COMMONDIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+include ../../Makefile.targ
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/amd64/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,31 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/common/btohex.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,200 @@
+/*
+ * 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"
+
+/*
+ * btohex.c - Binary to Hexadecimal string conversion.
+ *
+ * These routines convert binary labels into canonical
+ * hexadecimal representations of the binary form.
+ */
+
+#include <stdlib.h>
+#include <strings.h>
+#include <tsol/label.h>
+#include <sys/tsol/label_macro.h>
+
+/* 0x + Classification + '-' + ll + '-' + Compartments + end of string */
+#define _HEX_SIZE 2+(sizeof (Classification_t)*2)+4+\
+ (sizeof (Compartments_t)*2)+1
+
+static char hex_buf[_HEX_SIZE];
+
+/*
+ * h_alloc - Allocate data storage for a Hexadecimal label string.
+ *
+ * Entry id = Type of label to allocate storage for.
+ * SUN_SL_ID - Sensitivity Label.
+ * SUN_CLR_ID - Clearance.
+ *
+ * Returns NULL, If unable to allocate storage.
+ * Address of buffer.
+ *
+ * Calls malloc;
+ */
+
+char *
+h_alloc(unsigned char id)
+{
+ size_t size;
+
+ switch (id) {
+
+ case SUN_SL_ID:
+ size = _HEX_SIZE;
+ break;
+
+ case SUN_CLR_ID:
+ size = _HEX_SIZE;
+ break;
+
+ default:
+ return (NULL);
+ }
+
+ return ((char *)malloc(size));
+}
+
+
+/*
+ * h_free - Free a Hexadecimal label string.
+ *
+ * Entry hex = Hexadecimal label string.
+ *
+ * Returns none.
+ *
+ * Calls free.
+ */
+
+void
+h_free(char *hex)
+{
+
+ if (hex == NULL)
+ return;
+
+ free(hex);
+}
+
+
+/*
+ * bsltoh_r - Convert a Sensitivity Label into a Hexadecimal label string.
+ *
+ * Entry label = Sensitivity Label to be translated.
+ * hex = Buffer to place converted label.
+ * len = Length of buffer.
+ *
+ * Returns NULL, If invalid label type.
+ * Address of buffer.
+ *
+ * Calls label_to_str, strncpy.
+ */
+
+char *
+bsltoh_r(const m_label_t *label, char *hex)
+{
+ char *h;
+
+ if (label_to_str(label, &h, M_INTERNAL, DEF_NAMES) != 0) {
+ free(h);
+ return (NULL);
+ }
+
+ (void) strncpy(hex, (const char *)h, _HEX_SIZE);
+ free(h);
+ return (hex);
+}
+
+
+/*
+ * bsltoh - Convert a Sensitivity Label into a Hexadecimal label string.
+ *
+ * Entry label = Sensitivity Label to be translated.
+ *
+ * Returns NULL, If invalid label type.
+ * Address of statically allocated hex label string.
+ *
+ * Calls bsltoh_r.
+ *
+ * Uses hex_buf.
+ */
+
+char *
+bsltoh(const m_label_t *label)
+{
+
+ return (bsltoh_r(label, hex_buf));
+}
+
+
+/*
+ * bcleartoh_r - Convert a Clearance into a Hexadecimal label string.
+ *
+ * Entry clearance = Clearance to be translated.
+ * hex = Buffer to place converted label.
+ * len = Length of buffer.
+ *
+ * Returns NULL, If invalid label type.
+ * Address of buffer.
+ *
+ * Calls label_to_str, strncpy.
+ */
+
+char *
+bcleartoh_r(const m_label_t *clearance, char *hex)
+{
+ char *h;
+
+ if (label_to_str(clearance, &h, M_INTERNAL, DEF_NAMES) != 0) {
+ free(h);
+ return (NULL);
+ }
+
+ (void) strncpy(hex, (const char *)h, _HEX_SIZE);
+ free(h);
+ return (hex);
+}
+
+
+/*
+ * bcleartoh - Convert a Clearance into a Hexadecimal label string.
+ *
+ * Entry clearance = Clearance to be translated.
+ *
+ * Returns NULL, If invalid label type.
+ * Address of statically allocated hex label string.
+ *
+ * Calls bcleartoh_r.
+ *
+ * Uses hex_buf.
+ */
+
+char *
+bcleartoh(const m_label_t *clearance)
+{
+
+ return (bcleartoh_r(clearance, hex_buf));
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/common/btos.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,485 @@
+/*
+ * 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"
+
+/*
+ * Binary label to label string translations.
+ */
+
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <wchar.h>
+
+#include <sys/mman.h>
+
+#include <tsol/label.h>
+
+#include "clnt.h"
+#include "labeld.h"
+#include <sys/tsol/label_macro.h>
+
+#if !defined(TEXT_DOMAIN) /* should be defined by Makefiles */
+#define TEXT_DOMAIN "SYS_TEST"
+#endif /* TEXT_DOMAIN */
+
+static bslabel_t slow; /* static admin_low high sensitivity label */
+static bslabel_t shigh; /* static admin_high sensitivity label */
+static bclear_t clrlow, clrhigh; /* static admin_low and admin_high Clearance */
+
+static char *sstring; /* return string for sb*tos */
+static size_t ssize; /* current size of return string */
+
+static int
+return_string(char **string, int str_len, char *val)
+{
+ char *cpyptr;
+ size_t val_len = strlen(val) + 1;
+
+ if (*string == NULL) {
+ if ((*string = malloc(val_len)) == NULL)
+ return (0);
+ } else if (val_len > str_len) {
+ **string = '\0';
+ return (0);
+ }
+
+ cpyptr = *string;
+ bcopy(val, cpyptr, val_len);
+
+ return (val_len);
+}
+
+void
+set_label_view(uint_t *callflags, uint_t flags)
+{
+ if (flags&VIEW_INTERNAL) {
+ *callflags |= LABELS_VIEW_INTERNAL;
+ } else if (flags&VIEW_EXTERNAL) {
+ *callflags |= LABELS_VIEW_EXTERNAL;
+ }
+}
+
+int
+alloc_string(char **string, size_t size, char val)
+{
+ if (*string == NULL) {
+ if ((*string = malloc(ALLOC_CHUNK)) == NULL)
+ return (0);
+ } else {
+ if ((*string = realloc(*string, size + ALLOC_CHUNK)) == NULL) {
+ **string = val;
+ return (0);
+ }
+ }
+ **string = val;
+ return (ALLOC_CHUNK);
+}
+
+#define slcall callp->param.acall.cargs.bsltos_arg
+#define slret callp->param.aret.rvals.bsltos_ret
+/*
+ * bsltos - Convert Binary Sensitivity Label to Sensitivity Label string.
+ *
+ * Entry label = Binary Sensitivity Label to be converted.
+ * string = NULL ((char *) 0), if memory to be allocated,
+ * otherwise, pointer to preallocated memory.
+ * str_len = Length of preallocated memory, else ignored.
+ * flags = Logical sum of:
+ * LONG_CLASSIFICATION or SHORT_CLASSIFICATION,
+ * LONG_WORDS or SHORT_WORDS,
+ * VIEW_INTERNAL or VIEW_EXTERNAL, and
+ * NO_CLASSIFICATION.
+ * LONG_CLASSIFICATION, use long classification names.
+ * SHORT_CLASSIFICATION, use short classification
+ * names (default).
+ * NO_CLASSIFICATION, don't translate classification.
+ * LONG_WORDS, use the long form of words (default).
+ * SHORTWORDS, use the short form of words where available.
+ * VIEW_INTERNAL, don't promote/demote admin low/high.
+ * VIEW_EXTERNAL, promote/demote admin low/high.
+ *
+ * Exit string = Sensitivity Label string, or empty string if
+ * not enough preallocated memory.
+ *
+ * Returns -1, If unable to access label encodings database.
+ * 0, If unable to allocate string,
+ * or allocated string to short
+ * (and **string = '\0').
+ * length (including null) of Sensitivity Label string,
+ * If successful.
+ *
+ * Calls RPC - LABELS_BSLTOS, BCLHIGH, BCLLOW, BCLTOSL, BLEQUAL,
+ * BLTYPE, SETBSLABEL, UCLNT, memcpy, clnt_call,
+ * clnt_perror, malloc, strcat, strlen.
+ *
+ * Uses ADMIN_HIGH, ADMIN_LOW, shigh, slow.
+ */
+
+ssize_t
+bsltos(const bslabel_t *label, char **string, size_t str_len,
+ int flags)
+{
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize = CALL_SIZE(bsltos_call_t, 0);
+ int rval;
+
+ if (!BLTYPE(label, SUN_SL_ID)) {
+ return (-1);
+ }
+
+ call.callop = BSLTOS;
+ slcall.label = *label;
+ slcall.flags = (flags&NO_CLASSIFICATION) ? LABELS_NO_CLASS : 0;
+ slcall.flags |= (flags&SHORT_CLASSIFICATION ||
+ !(flags&LONG_CLASSIFICATION)) ? LABELS_SHORT_CLASS : 0;
+ slcall.flags |= (flags&SHORT_WORDS && !(flags&LONG_WORDS)) ?
+ LABELS_SHORT_WORDS : 0;
+ set_label_view(&slcall.flags, flags);
+
+ if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == SUCCESS) {
+
+ if (callp->reterr != 0)
+ return (-1);
+
+ /* unpack Sensitivity Label */
+
+ rval = return_string(string, str_len, slret.slabel);
+
+ if (callp != &call)
+ (void) munmap((void *)callp, bufsize);
+ return (rval);
+ } else if (rval == NOSERVER) {
+ /* server not present */
+ /* special case admin_high and admin_low */
+
+ if (!BLTYPE(&slow, SUN_SL_ID)) {
+ /* initialize static labels */
+
+ BSLLOW(&slow);
+ BSLHIGH(&shigh);
+ }
+
+ if (BLEQUAL(label, &slow)) {
+ return (return_string(string, str_len, ADMIN_LOW));
+ } else if (BLEQUAL(label, &shigh)) {
+ return (return_string(string, str_len, ADMIN_HIGH));
+ }
+ }
+ return (-1);
+} /* bsltos */
+#undef slcall
+#undef slret
+
+#define clrcall callp->param.acall.cargs.bcleartos_arg
+#define clrret callp->param.aret.rvals.bcleartos_ret
+/*
+ * bcleartos - Convert Binary Clearance to Clearance string.
+ *
+ * Entry clearance = Binary Clearance to be converted.
+ * string = NULL ((char *) 0), if memory to be allocated,
+ * otherwise, pointer to preallocated memory.
+ * str_len = Length of preallocated memory, else ignored.
+ * flags = Logical sum of:
+ * LONG_CLASSIFICATION or SHORT_CLASSIFICATION,
+ * LONG_WORDS or SHORT_WORDS,
+ * VIEW_INTERNAL or VIEW_EXTERNAL.
+ * LONG_CLASSIFICATION, use long classification names.
+ * SHORT_CLASSIFICATION, use short classification
+ * names (default).
+ * LONG_WORDS, use the long form of words (default).
+ * SHORTWORDS, use the short form of words where available.
+ * VIEW_INTERNAL, don't promote/demote admin low/high.
+ * VIEW_EXTERNAL, promote/demote admin low/high.
+ *
+ * Exit string = Clearance string, or empty string if not
+ * enough preallocated memory.
+ *
+ * Returns -1, If unable to access label encodings database.
+ * 0, If unable to allocate string,
+ * or allocated string to short
+ * (and **string = '\0').
+ * length (including null) of Clearance string,
+ * If successful.
+ *
+ * Calls RPC - LABELS_BSLTOS, BCLHIGH, BCLLOW, BCLTOSL, BLEQUAL,
+ * BLTYPE, SETBSLABEL, UCLNT, memcpy, clnt_call,
+ * clnt_perror, malloc, strcat, strlen.
+ *
+ * Uses ADMIN_HIGH, ADMIN_LOW, clrhigh, clrlow.
+ */
+
+ssize_t
+bcleartos(const bclear_t *clearance, char **string, size_t str_len,
+ int flags)
+{
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize = CALL_SIZE(bcleartos_call_t, 0);
+ int rval;
+
+ if (!BLTYPE(clearance, SUN_CLR_ID)) {
+ return (-1);
+ }
+
+ call.callop = BCLEARTOS;
+ clrcall.clear = *clearance;
+ clrcall.flags = (flags&SHORT_CLASSIFICATION ||
+ !(flags&LONG_CLASSIFICATION)) ? LABELS_SHORT_CLASS : 0;
+ clrcall.flags |= (flags&SHORT_WORDS && !(flags&LONG_WORDS)) ?
+ LABELS_SHORT_WORDS : 0;
+ set_label_view(&clrcall.flags, flags);
+
+ if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == SUCCESS) {
+
+ if (callp->reterr != 0)
+ return (-1);
+
+ /* unpack Clearance */
+
+ rval = return_string(string, str_len, clrret.cslabel);
+
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (rval);
+ } else if (rval == NOSERVER) {
+ /* server not present */
+ /* special case admin_high and admin_low */
+
+ if (!BLTYPE(&clrlow, SUN_CLR_ID)) {
+ /* initialize static labels */
+
+ BCLEARLOW(&clrlow);
+ BCLEARHIGH(&clrhigh);
+ }
+ if (BLEQUAL(clearance, &clrlow)) {
+ return (return_string(string, str_len, ADMIN_LOW));
+ } else if (BLEQUAL(clearance, &clrhigh)) {
+ return (return_string(string, str_len, ADMIN_HIGH));
+ }
+ }
+ return (-1);
+} /* bcleartos */
+#undef clrcall
+#undef clrret
+
+/*
+ * sbsltos - Convert Sensitivity Label to canonical clipped form.
+ *
+ * Entry label = Sensitivity Label to be converted.
+ * len = Maximum length of translated string, excluding NULL.
+ * 0, full string.
+ * sstring = address of string to translate into.
+ * ssize = size of memory currently allocated to sstring.
+ *
+ * Exit sstring = Newly translated string.
+ * ssize = Updated if more memory pre-allocated.
+ *
+ * Returns NULL, If error, len too small, unable to translate, or get
+ * memory for string.
+ * Address of string containing converted value.
+ *
+ * Calls alloc_string, bsltos, strcpy.
+ *
+ * Uses ssize, sstring.
+ */
+
+char *
+sbsltos(const bslabel_t *label, size_t len)
+{
+ ssize_t slen; /* length including NULL */
+ wchar_t *wstring;
+ int wccount;
+
+ if (ssize == 0) {
+ /* Allocate string memory. */
+ if ((ssize = alloc_string(&sstring, ssize, 's')) == 0)
+ /* can't get initial memory for string */
+ return (NULL);
+ }
+
+again:
+ if ((slen = bsltos(label, &sstring, ssize,
+ (SHORT_CLASSIFICATION | LONG_WORDS))) <= 0) {
+ /* error in translation */
+ if (slen == 0) {
+ if (*sstring == '\0') {
+ int newsize;
+ /* sstring not long enough */
+ if ((newsize = alloc_string(&sstring, ssize,
+ 's')) == 0) {
+ /* Can't get more memory */
+ return (NULL);
+ }
+ ssize += newsize;
+ goto again;
+ }
+ }
+ return (NULL);
+ }
+ if (len == 0) {
+ return (sstring);
+ } else if (len < MIN_SL_LEN) {
+ return (NULL);
+ }
+ if ((wstring = malloc(slen * sizeof (wchar_t))) == NULL)
+ return (NULL);
+ if ((wccount = mbstowcs(wstring, sstring, slen - 1)) == -1) {
+ free(wstring);
+ return (NULL);
+ }
+ if (wccount > len) {
+ wchar_t *clipp = wstring + (len - 2);
+
+ /* Adjust string size to desired length */
+
+ clipp[0] = L'<';
+ clipp[1] = L'-';
+ clipp[2] = L'\0';
+
+ while (wcstombs(NULL, wstring, 0) >= ssize) {
+ int newsize;
+
+ /* sstring not long enough */
+ if ((newsize = alloc_string(&sstring, ssize, 's')) ==
+ 0) {
+ /* Can't get more memory */
+ return (NULL);
+ }
+ ssize += newsize;
+ }
+
+ if ((wccount = wcstombs(sstring, wstring, ssize)) == -1) {
+ free(wstring);
+ return (NULL);
+ }
+ }
+ free(wstring);
+
+ return (sstring);
+} /* sbsltos */
+
+/*
+ * sbcleartos - Convert Clearance to canonical clipped form.
+ *
+ * Entry clearance = Clearance to be converted.
+ * len = Maximum length of translated string, excluding NULL.
+ * 0, full string.
+ * sstring = address of string to translate into.
+ * ssize = size of memory currently allocated to sstring.
+ *
+ * Exit sstring = Newly translated string.
+ * ssize = Updated if more memory pre-allocated.
+ *
+ * Returns NULL, If error, len too small, unable to translate, or get
+ * memory for string.
+ * Address of string containing converted value.
+ *
+ * Calls alloc_string, bcleartos, strcpy.
+ *
+ * Uses ssize, sstring.
+ */
+
+char *
+sbcleartos(const bclear_t *clearance, size_t len)
+{
+ ssize_t slen; /* length including NULL */
+ wchar_t *wstring;
+ int wccount;
+
+ if (ssize == 0) {
+ /* Allocate string memory. */
+ if ((ssize = alloc_string(&sstring, ssize, 'c')) == 0)
+ /* can't get initial memory for string */
+ return (NULL);
+ }
+
+again:
+ if ((slen = bcleartos(clearance, &sstring, ssize,
+ (SHORT_CLASSIFICATION | LONG_WORDS))) <= 0) {
+ /* error in translation */
+ if (slen == 0) {
+ if (*sstring == '\0') {
+ int newsize;
+ /* sstring not long enough */
+ if ((newsize = alloc_string(&sstring, ssize,
+ 'c')) == 0) {
+ /* Can't get more memory */
+ return (NULL);
+ }
+ ssize += newsize;
+ goto again;
+ }
+ }
+ return (NULL);
+ }
+ if (len == 0) {
+ return (sstring);
+ } else if (len < MIN_CLR_LEN) {
+ return (NULL);
+ }
+ if ((wstring = malloc(slen * sizeof (wchar_t))) == NULL)
+ return (NULL);
+ if ((wccount = mbstowcs(wstring, sstring, slen - 1)) == -1) {
+ free(wstring);
+ return (NULL);
+ }
+ if (wccount > len) {
+ wchar_t *clipp = wstring + (len - 2);
+
+ /* Adjust string size to desired length */
+
+ clipp[0] = L'<';
+ clipp[1] = L'-';
+ clipp[2] = L'\0';
+
+ while (wcstombs(NULL, wstring, 0) >= ssize) {
+ int newsize;
+
+ /* sstring not long enough */
+ if ((newsize = alloc_string(&sstring, ssize, 'c')) ==
+ 0) {
+ /* Can't get more memory */
+ free(wstring);
+ return (NULL);
+ }
+ ssize += newsize;
+ }
+ if ((wccount = wcstombs(sstring, wstring, ssize)) == -1) {
+ free(wstring);
+ return (NULL);
+ }
+ }
+ free(wstring);
+
+ return (sstring);
+} /* sbcleartos */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/common/call_labeld.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,308 @@
+/*
+ * 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 <door.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <synch.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "labeld.h"
+
+#ifndef DEBUG
+#define perror(e)
+#endif /* !DEBUG */
+
+/*
+ * Library prototypes to get away from lots of static build problems.
+ */
+
+extern int __nanosleep(const struct timespec *, struct timespec *);
+
+/*
+ * This is cloned from _nsc_trydoorcall used by the nscd client.
+ *
+ * Routine that actually performs the door call.
+ * Note that we cache a file descriptor. We do
+ * the following to prevent disasters:
+ *
+ * 1) Never use 0, 1 or 2; if we get this from the open
+ * we dup it upwards.
+ *
+ * 2) Set the close on exec flags so descriptor remains available
+ * to child processes.
+ *
+ * 3) Verify that the door is still the same one we had before
+ * by using door_info on the client side.
+ *
+ * Note that we never close the file descriptor if it isn't one
+ * we allocated; we check this with door info. The rather tricky
+ * logic is designed to be fast in the normal case (fd is already
+ * allocated and is ok) while handling the case where the application
+ * closed it underneath us or where the nscd dies or re-execs itself
+ * and we're a multi-threaded application. Note that we cannot protect
+ * the application if it closes the fd and it is multi-threaded.
+ *
+ * int __call_labeld(label_door_op **dptr, int *ndata, int *adata);
+ *
+ * *dptr IN: points to arg buffer OUT: points to results buffer
+ * *ndata IN: overall size of buffer OUT: overall size of buffer
+ * *adata IN: size of call data OUT: size of return data
+ *
+ * Note that *dptr may change if provided space as defined by *bufsize is
+ * inadequate. In this case the door call mmaps more space and places
+ * the answer there and sets dptr to contain a pointer to the space, which
+ * should be freed with munmap.
+ *
+ * Returns 0 if the door call reached the server, -1 if contact was not made.
+ *
+ */
+
+
+static mutex_t _door_lock = DEFAULTMUTEX;
+
+int
+__call_labeld(labeld_data_t **dptr, size_t *ndata, size_t *adata)
+{
+ static int doorfd = -1;
+ static door_info_t real_door;
+ struct stat st;
+ door_info_t my_door;
+ door_arg_t param;
+ char door_name[MAXPATHLEN];
+ struct timespec ts;
+ int busy = 0; /* number of busy loops */
+
+#ifdef DEBUG
+ labeld_data_t *callptr = *dptr;
+ int buf_size = *ndata;
+ int return_size = *adata;
+#endif /* DEBUG */
+
+ /*
+ * the first time in we try and open and validate the door.
+ * the validations are that the door must have been
+ * created with the label service door cookie and
+ * that it has the same door ID. If any of these
+ * validations fail we refuse to use the door.
+ */
+ ts.tv_sec = 0; /* initialize nanosecond retry timer */
+ ts.tv_nsec = 100;
+ (void) mutex_lock(&_door_lock);
+
+try_again:
+ if (doorfd == -1) {
+ int tbc[3];
+ int i;
+
+ (void) snprintf(door_name, sizeof (door_name), "%s%s",
+ DOOR_PATH, DOOR_NAME);
+ if ((doorfd = open64(door_name, O_RDONLY, 0)) < 0) {
+ (void) mutex_unlock(&_door_lock);
+ perror("server door open");
+ return (NOSERVER);
+ }
+
+ /*
+ * dup up the file descriptor if we have 0 - 2
+ * to avoid problems with shells stdin/out/err
+ */
+ i = 0;
+ while (doorfd < 3) { /* we have a reserved fd */
+ tbc[i++] = doorfd;
+ if ((doorfd = dup(doorfd)) < 0) {
+ perror("couldn't dup");
+ while (i--)
+ (void) close(tbc[i]);
+ doorfd = -1;
+ (void) mutex_unlock(&_door_lock);
+ return (NOSERVER);
+ }
+ }
+ while (i--)
+ (void) close(tbc[i]);
+
+ /*
+ * mark this door descriptor as close on exec
+ */
+ (void) fcntl(doorfd, F_SETFD, FD_CLOEXEC);
+ if (door_info(doorfd, &real_door) < 0) {
+ /*
+ * we should close doorfd because we just opened it
+ */
+ perror("real door door_info");
+ (void) close(doorfd);
+ doorfd = -1;
+ (void) mutex_unlock(&_door_lock);
+ return (NOSERVER);
+ }
+ if (fstat(doorfd, &st) < 0) {
+ perror("real door fstat");
+ return (NOSERVER);
+ }
+#ifdef DEBUG
+ (void) printf("\treal door %s\n", door_name);
+ (void) printf("\t\tuid = %d, gid = %d, mode = %o\n", st.st_uid,
+ st.st_gid, st.st_mode);
+ (void) printf("\t\toutstanding requests = %d\n", st.st_nlink-1);
+ (void) printf("\t\t pid = %d\n", real_door.di_target);
+ (void) printf("\t\t procedure = %llx\n", real_door.di_proc);
+ (void) printf("\t\t cookie = %llx\n", real_door.di_data);
+ (void) printf("\t\t attributes = %x\n",
+ real_door.di_attributes);
+ if (real_door.di_attributes & DOOR_UNREF)
+ (void) printf("\t\t\t UNREF\n");
+ if (real_door.di_attributes & DOOR_PRIVATE)
+ (void) printf("\t\t\t PRIVATE\n");
+ if (real_door.di_attributes & DOOR_LOCAL)
+ (void) printf("\t\t\t LOCAL\n");
+ if (real_door.di_attributes & DOOR_REVOKED)
+ (void) printf("\t\t\t REVOKED\n");
+ if (real_door.di_attributes & DOOR_DESCRIPTOR)
+ (void) printf("\t\t\t DESCRIPTOR\n");
+ if (real_door.di_attributes & DOOR_RELEASE)
+ (void) printf("\t\t\t RELEASE\n");
+ if (real_door.di_attributes & DOOR_DELAY)
+ (void) printf("\t\t\t DELAY\n");
+ (void) printf("\t\t id = %llx\n", real_door.di_uniquifier);
+#endif /* DEBUG */
+ if ((real_door.di_attributes & DOOR_REVOKED) ||
+ (real_door.di_data != (door_ptr_t)COOKIE)) {
+#ifdef DEBUG
+ (void) printf("real door revoked\n");
+#endif /* DEBUG */
+ (void) close(doorfd);
+ doorfd = -1;
+ (void) mutex_unlock(&_door_lock);
+ return (NOSERVER);
+ }
+ } else {
+ if ((door_info(doorfd, &my_door) < 0) ||
+ (my_door.di_data != (door_ptr_t)COOKIE) ||
+ (my_door.di_uniquifier != real_door.di_uniquifier)) {
+ perror("my door door_info");
+ /*
+ * don't close it - someone else has clobbered fd
+ */
+ doorfd = -1;
+ goto try_again;
+ }
+ if (fstat(doorfd, &st) < 0) {
+ perror("my door fstat");
+ goto try_again;
+ }
+#ifdef DEBUG
+ (void) sprintf(door_name, "%s%s", DOOR_PATH, DOOR_NAME);
+ (void) printf("\tmy door %s\n", door_name);
+ (void) printf("\t\tuid = %d, gid = %d, mode = %o\n", st.st_uid,
+ st.st_gid, st.st_mode);
+ (void) printf("\t\toutstanding requests = %d\n", st.st_nlink-1);
+ (void) printf("\t\t pid = %d\n", my_door.di_target);
+ (void) printf("\t\t procedure = %llx\n", my_door.di_proc);
+ (void) printf("\t\t cookie = %llx\n", my_door.di_data);
+ (void) printf("\t\t attributes = %x\n", my_door.di_attributes);
+ if (my_door.di_attributes & DOOR_UNREF)
+ (void) printf("\t\t\t UNREF\n");
+ if (my_door.di_attributes & DOOR_PRIVATE)
+ (void) printf("\t\t\t PRIVATE\n");
+ if (my_door.di_attributes & DOOR_LOCAL)
+ (void) printf("\t\t\t LOCAL\n");
+ if (my_door.di_attributes & DOOR_REVOKED)
+ (void) printf("\t\t\t REVOKED\n");
+ if (my_door.di_attributes & DOOR_DESCRIPTOR)
+ (void) printf("\t\t\t DESCRIPTOR\n");
+ if (my_door.di_attributes & DOOR_RELEASE)
+ (void) printf("\t\t\t RELEASE\n");
+ if (my_door.di_attributes & DOOR_DELAY)
+ (void) printf("\t\t\t DELAY\n");
+ (void) printf("\t\t id = %llx\n", my_door.di_uniquifier);
+#endif /* DEBUG */
+ if (my_door.di_attributes & DOOR_REVOKED) {
+#ifdef DEBUG
+ (void) printf("my door revoked\n");
+#endif /* DEBUG */
+ (void) close(doorfd); /* labeld exited .... */
+ doorfd = -1; /* try and restart connection */
+ goto try_again;
+ }
+ }
+ (void) mutex_unlock(&_door_lock);
+
+ param.data_ptr = (char *)*dptr;
+ param.data_size = *adata;
+ param.desc_ptr = NULL;
+ param.desc_num = 0;
+ param.rbuf = (char *)*dptr;
+ param.rsize = *ndata;
+
+ if (door_call(doorfd, ¶m) < 0) {
+ if (errno == EAGAIN && busy++ < 10) {
+ /* adjust backoff */
+ if ((ts.tv_nsec *= 10) >= NANOSEC) {
+ ts.tv_sec++;
+ ts.tv_nsec = 100;
+ }
+ (void) __nanosleep(&ts, NULL);
+#ifdef DEBUG
+ (void) printf("door_call failed EAGAIN # %d\n", busy);
+#endif /* DEBUG */
+ (void) mutex_lock(&_door_lock);
+ goto try_again;
+ }
+ perror("door call");
+ return (NOSERVER);
+ }
+
+ *adata = (int)param.data_size;
+ *ndata = (int)param.rsize;
+ /*LINTED*/
+ *dptr = (labeld_data_t *)param.data_ptr;
+
+ if (*adata == 0 || *dptr == NULL) {
+#ifdef DEBUG
+ (void) printf("\tNo data returned, size = %lu, dptr = %p\n",
+ (unsigned long)*adata, (void *)*dptr);
+#endif /* DEBUG */
+ return (NOSERVER);
+ }
+#ifdef DEBUG
+ (void) printf("call buf = %x, buf size = %d, call size = %d\n",
+ callptr, buf_size, return_size);
+ (void) printf("retn buf = %x, buf size = %d, retn size = %d\n",
+ *dptr, *ndata, *adata);
+ (void) printf("\treply status = %d\n", (*dptr)->param.aret.ret);
+#endif /* DEBUG */
+ return ((*dptr)->param.aret.ret);
+
+} /* __call_labeld */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/common/clnt.h Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,49 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _CLNT_H
+#define _CLNT_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAXCOLOR 256 /* Max size of a static color string */
+#define MIN_CMW_LEN 8 /* minimum length of clipped CMW Label */
+#define MIN_SL_LEN 3 /* minimum length of clipped SL */
+#define MIN_IL_LEN 3 /* minimum length of clipped IL */
+#define MIN_CLR_LEN 3 /* minimum length of clipped Clearance */
+
+#define ALLOC_CHUNK 1024 /* size of chunk for sb*tos allocs */
+
+extern int alloc_string(char **, size_t, char);
+extern void set_label_view(uint_t *, uint_t);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CLNT_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/common/getlabel.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,66 @@
+/*
+ * 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"
+
+/*
+ * String to binary label translations.
+ */
+
+#include <ctype.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <tsol/label.h>
+#include <sys/tsol/label_macro.h>
+
+#include <sys/syscall.h>
+#include <sys/tsol/tsyscall.h>
+
+#include <sys/types.h>
+
+/*
+ * getlabel(3TSOL) - get file label
+ *
+ * This is the library interface to the system call.
+ */
+
+int
+getlabel(const char *path, bslabel_t *label)
+{
+ return (syscall(SYS_labelsys, TSOL_GETLABEL, path, label));
+}
+
+/*
+ * fgetlabel(3TSOL) - get file label
+ *
+ * This is the library interface to the system call.
+ */
+int
+fgetlabel(int fd, bslabel_t *label)
+{
+ return (syscall(SYS_labelsys, TSOL_FGETLABEL, fd, label));
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/common/getpathbylabel.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,503 @@
+/*
+ * 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"
+
+
+/*
+ * Name: getpathbylabel.c
+ *
+ * Description: Returns the global zone pathname corresponding
+ * to the specified label. The pathname does
+ * not need to match an existing file system object.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <tsol/label.h>
+#include <stdlib.h>
+#include <zone.h>
+#include <sys/mntent.h>
+#include <sys/mnttab.h>
+#include <stdarg.h>
+
+/*
+ * This structure is used to chain mntent structures into a list
+ * and to cache stat information for each member of the list.
+ */
+struct mntlist {
+ struct mnttab *mntl_mnt;
+ struct mntlist *mntl_next;
+};
+
+
+/*
+ * Return a pointer to the trailing suffix of full that follows the prefix
+ * given by pref. If pref isn't a prefix of full, return NULL. Apply
+ * pathname semantics to the prefix test, so that pref must match at a
+ * component boundary.
+ */
+static char *
+pathsuffix(char *full, char *pref)
+{
+ int preflen;
+
+ if (full == NULL || pref == NULL)
+ return (NULL);
+
+ preflen = strlen(pref);
+ if (strncmp(pref, full, preflen) != 0)
+ return (NULL);
+
+ /*
+ * pref is a substring of full. To be a subpath, it cannot cover a
+ * partial component of full. The last clause of the test handles the
+ * special case of the root.
+ */
+ if (full[preflen] != '\0' && full[preflen] != '/' && preflen > 1)
+ return (NULL);
+
+ if (preflen == 1 && full[0] == '/')
+ return (full);
+ else
+ return (full + preflen);
+}
+
+/*
+ * Return zero iff the path named by sub is a leading subpath
+ * of the path named by full.
+ *
+ * Treat null paths as matching nothing.
+ */
+static int
+subpath(char *full, char *sub)
+{
+ return (pathsuffix(full, sub) == NULL);
+}
+
+static void
+tsol_mnt_free(struct mnttab *mnt)
+{
+ if (mnt->mnt_special)
+ free(mnt->mnt_special);
+ if (mnt->mnt_mountp)
+ free(mnt->mnt_mountp);
+ if (mnt->mnt_fstype)
+ free(mnt->mnt_fstype);
+ if (mnt->mnt_mntopts)
+ free(mnt->mnt_mntopts);
+ free(mnt);
+}
+
+static void
+tsol_mlist_free(struct mntlist *mlist)
+{
+ struct mntlist *mlp;
+
+ for (mlp = mlist; mlp; mlp = mlp->mntl_next) {
+ struct mnttab *mnt = mlp->mntl_mnt;
+
+ if (mnt)
+ tsol_mnt_free(mnt);
+ free(mlp);
+ }
+}
+
+static struct mnttab *
+mntdup(struct mnttab *mnt)
+{
+ struct mnttab *new;
+
+ new = (struct mnttab *)malloc(sizeof (*new));
+ if (new == NULL)
+ return (NULL);
+
+ new->mnt_special = NULL;
+ new->mnt_mountp = NULL;
+ new->mnt_fstype = NULL;
+ new->mnt_mntopts = NULL;
+
+ new->mnt_special = strdup(mnt->mnt_special);
+ if (new->mnt_special == NULL) {
+ tsol_mnt_free(new);
+ return (NULL);
+ }
+ new->mnt_mountp = strdup(mnt->mnt_mountp);
+ if (new->mnt_mountp == NULL) {
+ tsol_mnt_free(new);
+ return (NULL);
+ }
+ new->mnt_fstype = strdup(mnt->mnt_fstype);
+ if (new->mnt_fstype == NULL) {
+ tsol_mnt_free(new);
+ return (NULL);
+ }
+ new->mnt_mntopts = strdup(mnt->mnt_mntopts);
+ if (new->mnt_mntopts == NULL) {
+ tsol_mnt_free(new);
+ return (NULL);
+ }
+ return (new);
+}
+
+static struct mntlist *
+tsol_mkmntlist(void)
+{
+ FILE *mounted;
+ struct mntlist *mntl;
+ struct mntlist *mntst = NULL;
+ struct mnttab mnt;
+
+ if ((mounted = fopen(MNTTAB, "r")) == NULL) {
+ perror(MNTTAB);
+ return (NULL);
+ }
+ resetmnttab(mounted);
+ while (getmntent(mounted, &mnt) == NULL) {
+ mntl = (struct mntlist *)malloc(sizeof (*mntl));
+ if (mntl == NULL) {
+ tsol_mlist_free(mntst);
+ mntst = NULL;
+ break;
+ }
+ mntl->mntl_mnt = mntdup((struct mnttab *)(&mnt));
+ if (mntl->mntl_mnt == NULL) {
+ tsol_mlist_free(mntst);
+ mntst = NULL;
+ break;
+ }
+ mntl->mntl_next = mntst;
+ mntst = mntl;
+ }
+ (void) fclose(mounted);
+ return (mntst);
+}
+
+/*
+ * This function attempts to convert local zone NFS mounted pathnames
+ * into equivalent global zone NFS mounted pathnames. At present
+ * it only works for automounted filesystems. It depends on the
+ * assumption that both the local and global zone automounters
+ * share the same nameservices. It also assumes that any automount
+ * map used by a local zone is available to the global zone automounter.
+ *
+ * The algorithm used consists of three phases.
+ *
+ * 1. The local zone's mnttab is searched to find the automount map
+ * with the closest matching mountpath.
+ *
+ * 2. The matching autmount map name is looked up in the global zone's
+ * mnttab to determine the path where it should be mounted in the
+ * global zone.
+ *
+ * 3. A pathname covered by an appropiate autofs trigger mount in
+ * the global zone is generated as the resolved pathname
+ *
+ * Among the things that can go wrong is that global zone doesn't have
+ * a matching automount map or the mount was not done via the automounter.
+ * Either of these cases return a NULL path.
+ */
+#define ZONE_OPT "zone="
+static int
+getnfspathbyautofs(struct mntlist *mlist, zoneid_t zoneid,
+ struct mnttab *autofs_mnt, char *globalpath, char *zonepath, int global_len)
+{
+ struct mntlist *mlp;
+ char zonematch[ZONENAME_MAX + 20];
+ char zonename[ZONENAME_MAX];
+ int longestmatch;
+ struct mnttab *mountmatch;
+
+ if (autofs_mnt) {
+ mountmatch = autofs_mnt;
+ longestmatch = strlen(mountmatch->mnt_mountp);
+ } else {
+ /*
+ * First we need to get the zonename to look for
+ */
+ if (zone_getattr(zoneid, ZONE_ATTR_NAME, zonename,
+ ZONENAME_MAX) == -1) {
+ return (0);
+ }
+
+ (void) strncpy(zonematch, ZONE_OPT, sizeof (zonematch));
+ (void) strlcat(zonematch, zonename, sizeof (zonematch));
+
+ /*
+ * Find the best match for an automount map that
+ * corresponds to the local zone's pathname
+ */
+ longestmatch = 0;
+ for (mlp = mlist; mlp; mlp = mlp->mntl_next) {
+ struct mnttab *mnt = mlp->mntl_mnt;
+ int len;
+ int matchfound;
+ char *token;
+ char *lasts;
+ char mntopts[MAXPATHLEN];
+
+ if (subpath(globalpath, mnt->mnt_mountp) != 0)
+ continue;
+ if (strcmp(mnt->mnt_fstype, MNTTYPE_AUTOFS))
+ continue;
+
+ matchfound = 0;
+ (void) strncpy(mntopts, mnt->mnt_mntopts, MAXPATHLEN);
+ if ((token = strtok_r(mntopts, ",", &lasts)) != NULL) {
+ if (strcmp(token, zonematch) == 0) {
+ matchfound = 1;
+ } else while ((token = strtok_r(NULL, ",",
+ &lasts)) != NULL) {
+ if (strcmp(token, zonematch) == 0) {
+ matchfound = 1;
+ break;
+ }
+ }
+ }
+ if (matchfound) {
+ len = strlen(mnt->mnt_mountp);
+ if (len > longestmatch) {
+ mountmatch = mnt;
+ longestmatch = len;
+ }
+ }
+ }
+ }
+ if (longestmatch == 0) {
+ return (0);
+ } else {
+ /*
+ * Now we may have found the corresponding autofs mount
+ * Try to find the matching global zone autofs entry
+ */
+
+ for (mlp = mlist; mlp; mlp = mlp->mntl_next) {
+ char p[MAXPATHLEN];
+ size_t zp_len;
+ size_t mp_len;
+
+ struct mnttab *mnt = mlp->mntl_mnt;
+
+ if (strcmp(mountmatch->mnt_special,
+ mnt->mnt_special) != 0)
+ continue;
+ if (strcmp(mnt->mnt_fstype, MNTTYPE_AUTOFS))
+ continue;
+ if (strstr(mnt->mnt_mntopts, ZONE_OPT) != NULL)
+ continue;
+ /*
+ * OK, we have a matching global zone automap
+ * so adjust the path for the global zone.
+ */
+ zp_len = strlen(zonepath);
+ mp_len = strlen(mnt->mnt_mountp);
+ (void) strncpy(p, globalpath + zp_len, MAXPATHLEN);
+ /*
+ * If both global zone and zone-relative
+ * mountpoint match, just use the same pathname
+ */
+ if (strncmp(mnt->mnt_mountp, p, mp_len) == 0) {
+ (void) strncpy(globalpath, p, global_len);
+ return (1);
+ } else {
+ (void) strncpy(p, globalpath, MAXPATHLEN);
+ (void) strncpy(globalpath, mnt->mnt_mountp,
+ global_len);
+ (void) strlcat(globalpath,
+ p + strlen(mountmatch->mnt_mountp),
+ global_len);
+ return (1);
+ }
+ }
+ return (0);
+ }
+}
+
+ /*
+ * Find the pathname for the entry in mlist that corresponds to the
+ * file named by path (i.e., that names a mount table entry for the
+ * file system in which path lies).
+ *
+ * Return 0 is there an error.
+ */
+ static int
+ getglobalpath(const char *path, zoneid_t zoneid, struct mntlist *mlist,
+ char *globalpath)
+ {
+ struct mntlist *mlp;
+ char lofspath[MAXPATHLEN];
+ char zonepath[MAXPATHLEN];
+ int longestmatch;
+ struct mnttab *mountmatch;
+
+ if (zoneid != GLOBAL_ZONEID) {
+ char *prefix;
+
+ if ((prefix = getzonerootbyid(zoneid)) == NULL) {
+ return (0);
+ }
+ (void) strncpy(zonepath, prefix, MAXPATHLEN);
+ (void) strlcpy(globalpath, prefix, MAXPATHLEN);
+ (void) strlcat(globalpath, path, MAXPATHLEN);
+ free(prefix);
+ } else {
+ (void) strlcpy(globalpath, path, MAXPATHLEN);
+ }
+
+ for (;;) {
+ longestmatch = 0;
+ for (mlp = mlist; mlp; mlp = mlp->mntl_next) {
+ struct mnttab *mnt = mlp->mntl_mnt;
+ int len;
+
+ if (subpath(globalpath, mnt->mnt_mountp) != 0)
+ continue;
+ len = strlen(mnt->mnt_mountp);
+ if (len > longestmatch) {
+ mountmatch = mnt;
+ longestmatch = len;
+ }
+ }
+ /*
+ * Handle interesting mounts.
+ */
+ if ((strcmp(mountmatch->mnt_fstype, MNTTYPE_NFS) == 0) ||
+ (strcmp(mountmatch->mnt_fstype, MNTTYPE_AUTOFS) == 0)) {
+ if (zoneid > GLOBAL_ZONEID) {
+ struct mnttab *m = NULL;
+
+ if (strcmp(mountmatch->mnt_fstype,
+ MNTTYPE_AUTOFS) == 0)
+ m = mountmatch;
+ if (getnfspathbyautofs(mlist, zoneid, m,
+ globalpath, zonepath, MAXPATHLEN) == 0) {
+ return (0);
+ }
+ }
+ break;
+ } else if (strcmp(mountmatch->mnt_fstype, MNTTYPE_LOFS) == 0) {
+ /*
+ * count up what's left
+ */
+ int remainder;
+
+ remainder = strlen(globalpath) - longestmatch;
+ if (remainder > 0) {
+ path = pathsuffix(globalpath,
+ mountmatch->mnt_mountp);
+ (void) strlcpy(lofspath, path, MAXPATHLEN);
+ }
+ (void) strlcpy(globalpath, mountmatch->mnt_special,
+ MAXPATHLEN);
+ if (remainder > 0) {
+ (void) strlcat(globalpath, lofspath,
+ MAXPATHLEN);
+ }
+ } else {
+ if ((zoneid > GLOBAL_ZONEID) &&
+ (strncmp(path, "/home/", strlen("/home/")) == 0)) {
+ char zonename[ZONENAME_MAX];
+
+ /*
+ * If this is a cross-zone reference to
+ * a home directory, it must be corrected.
+ * We should only get here if the zone's
+ * automounter hasn't yet mounted its
+ * autofs trigger on /home.
+ *
+ * Since it is likely to do so in the
+ * future, we will assume that the global
+ * zone already has an equivalent autofs
+ * mount established. By convention,
+ * this should be mounted at the
+ * /zone/<zonename>
+ */
+
+ if (zone_getattr(zoneid, ZONE_ATTR_NAME,
+ zonename, ZONENAME_MAX) == -1) {
+ return (0);
+ } else {
+ (void) snprintf(globalpath, MAXPATHLEN,
+ "/zone/%s%s", zonename, path);
+ }
+ }
+ break;
+ }
+ }
+ return (1);
+}
+
+
+/*
+ * This function is only useful for global zone callers
+ * It uses the global zone mnttab to translate local zone pathnames
+ * into global zone pathnames.
+ */
+char *
+getpathbylabel(const char *path_name, char *resolved_path, size_t bufsize,
+ const bslabel_t *sl) {
+ char ret_path[MAXPATHLEN]; /* pathname to return */
+ zoneid_t zoneid;
+ struct mntlist *mlist;
+
+ if (getzoneid() != GLOBAL_ZONEID) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if (path_name[0] != '/') { /* need absolute pathname */
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if (resolved_path == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if ((zoneid = getzoneidbylabel(sl)) == -1)
+ return (NULL);
+
+ /*
+ * Construct the list of mounted file systems.
+ */
+
+ if ((mlist = tsol_mkmntlist()) == NULL) {
+ return (NULL);
+ }
+ if (getglobalpath(path_name, zoneid, mlist, ret_path) == 0) {
+ tsol_mlist_free(mlist);
+ return (NULL);
+ }
+ tsol_mlist_free(mlist);
+ if (strlen(ret_path) >= bufsize) {
+ errno = EFAULT;
+ return (NULL);
+ }
+ return (strcpy(resolved_path, ret_path));
+} /* end getpathbylabel() */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/common/getplabel.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,59 @@
+/*
+ * 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 <stdlib.h>
+#include <zone.h>
+#include <tsol/label.h>
+#include <sys/tsol/label_macro.h>
+#include <sys/types.h>
+#include <sys/zone.h>
+
+/*
+ * getplabel(2TSOL) - get process sensitivity label
+ */
+
+int
+getplabel(bslabel_t *label_p)
+{
+ zoneid_t zoneid;
+
+ zoneid = (int)getzoneid();
+ if (zoneid == GLOBAL_ZONEID) {
+ bslhigh(label_p);
+ } else {
+ bslabel_t *sl;
+
+ sl = getzonelabelbyid(zoneid);
+ if (sl == NULL) {
+ return (-1);
+ } else {
+ *label_p = *sl;
+ free(sl);
+ }
+ }
+ return (0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/common/hextob.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,97 @@
+/*
+ * 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"
+
+/*
+ * hextob.c - Hexadecimal string to binary label conversion.
+ *
+ * These routines convert canonical hexadecimal representations
+ * of internal labels into binary form.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <tsol/label.h>
+#include <sys/tsol/label_macro.h>
+
+/*
+ * htobsl - Convert a Hexadecimal label string to a Sensitivity Label.
+ *
+ * Entry s = Hexadecimal label string to be converted.
+ *
+ * Exit label = Sensitivity Label converted, if successful.
+ * Unchanged, if not successful.
+ *
+ * Returns 1, If successful.
+ * 0, Otherwise.
+ *
+ * Calls str_to_label, m_label_free.
+ */
+
+int
+htobsl(const char *s, m_label_t *label)
+{
+ m_label_t *l = NULL;
+
+ if (str_to_label(s, &l, MAC_LABEL, L_NO_CORRECTION, NULL) == -1) {
+ m_label_free(l);
+ return (0);
+ }
+ *label = *l;
+ m_label_free(l);
+ return (1);
+}
+
+/*
+ * htobclear - Convert a Hexadecimal label string to a Clearance.
+ *
+ * Entry s = Hexadecimal label string to be converted.
+ *
+ * Exit clearance = Clearnace converted, if successful.
+ * Unchanged, if not successful.
+ *
+ * Returns 1, If successful.
+ * 0, Otherwise.
+ *
+ * Calls str_to_label, m_label_free.
+ */
+
+int
+htobclear(const char *s, m_label_t *clearance)
+{
+ m_label_t *c = NULL;
+
+ if (str_to_label(s, &c, USER_CLEAR, L_NO_CORRECTION, NULL) == -1) {
+ m_label_free(c);
+ return (0);
+ }
+ *clearance = *c;
+ m_label_free(c);
+ return (1);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/common/label.h Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,242 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _TSOL_LABEL_H
+#define _TSOL_LABEL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/tsol/label.h>
+#include <priv.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Procedural Interface Structure Definitions */
+
+struct label_info { /* structure returned by label_info */
+ short ilabel_len; /* max Information Label length */
+ short slabel_len; /* max Sensitivity Label length */
+ short clabel_len; /* max CMW Label length */
+ short clear_len; /* max Clearance Label length */
+ short vers_len; /* version string length */
+ short header_len; /* max len of banner page header */
+ short protect_as_len; /* max len of banner page protect as */
+ short caveats_len; /* max len of banner page caveats */
+ short channels_len; /* max len of banner page channels */
+};
+
+typedef struct label_set_identifier { /* valid label set identifier */
+ int type; /* type of the set */
+ char *name; /* name of the set if needed */
+} set_id;
+
+struct name_fields { /* names for label builder fields */
+ char *class_name; /* Classifications field name */
+ char *comps_name; /* Compartments field name */
+ char *marks_name; /* Markings field name */
+};
+
+/* Label Set Identifier Types */
+
+/*
+ * The accreditation ranges as specified in the label encodings file.
+ * The name parameter is ignored.
+ *
+ * System Accreditation Range is all valid labels plus Admin High and Low.
+ *
+ * User Accreditation Range is valid user labels as defined in the
+ * ACCREDITATION RANGE: section of the label encodings file.
+ */
+
+#define SYSTEM_ACCREDITATION_RANGE 1
+#define USER_ACCREDITATION_RANGE 2
+
+
+/* System Call Interface Definitions */
+
+extern int getlabel(const char *, m_label_t *);
+extern int fgetlabel(int, m_label_t *);
+
+extern int getplabel(m_label_t *);
+extern int setflabel(const char *, m_label_t *);
+extern char *getpathbylabel(const char *, char *, size_t,
+ const m_label_t *sl);
+extern m_label_t *getzonelabelbyid(zoneid_t);
+extern m_label_t *getzonelabelbyname(const char *);
+extern zoneid_t getzoneidbylabel(const m_label_t *);
+extern char *getzonenamebylabel(const m_label_t *);
+extern char *getzonerootbyid(zoneid_t);
+extern char *getzonerootbyname(const char *);
+extern char *getzonerootbylabel(const m_label_t *);
+extern m_label_t *getlabelbypath(const char *);
+
+
+/* Flag word values */
+
+#define ALL_ENTRIES 0x00000000
+#define ACCESS_RELATED 0x00000001
+#define ACCESS_MASK 0x0000FFFF
+#define ACCESS_SHIFT 0
+
+#define LONG_WORDS 0x00010000 /* use long names */
+#define SHORT_WORDS 0x00020000 /* use short names if present */
+#define LONG_CLASSIFICATION 0x00040000 /* use long classification */
+#define SHORT_CLASSIFICATION 0x00080000 /* use short classification */
+#define NO_CLASSIFICATION 0x00100000 /* don't translate the class */
+#define VIEW_INTERNAL 0x00200000 /* don't promote/demote */
+#define VIEW_EXTERNAL 0x00400000 /* promote/demote label */
+
+#define NEW_LABEL 0x00000001 /* create a full new label */
+#define NO_CORRECTION 0x00000002 /* don't correct label errors */
+ /* implies NEW_LABEL */
+
+#define CVT_DIM 0x01 /* display word dimmed */
+#define CVT_SET 0x02 /* display word currently set */
+
+/* Procedure Interface Definitions available to user */
+
+/* APIs shared with the kernel are in <sys/tsol/label.h */
+
+extern m_label_t *blabel_alloc(void);
+extern void blabel_free(m_label_t *);
+extern size_t blabel_size(void);
+extern char *bsltoh(const m_label_t *);
+extern char *bcleartoh(const m_label_t *);
+
+extern char *bsltoh_r(const m_label_t *, char *);
+extern char *bcleartoh_r(const m_label_t *, char *);
+extern char *h_alloc(uint8_t);
+extern void h_free(char *);
+
+extern int htobsl(const char *, m_label_t *);
+extern int htobclear(const char *, m_label_t *);
+
+extern m_range_t *getuserrange(const char *);
+extern m_range_t *getdevicerange(const char *);
+
+extern int set_effective_priv(priv_op_t, int, ...);
+extern int set_inheritable_priv(priv_op_t, int, ...);
+extern int set_permitted_priv(priv_op_t, int, ...);
+extern int is_system_labeled(void);
+
+/* Procedures needed for multi-level printing */
+
+extern int tsol_check_admin_auth(uid_t uid);
+
+/* APIs implemented via labeld */
+
+extern int blinset(const m_label_t *, const set_id *);
+extern int labelinfo(struct label_info *);
+extern ssize_t labelvers(char **, size_t);
+extern char *bltocolor(const m_label_t *);
+extern char *bltocolor_r(const m_label_t *, size_t, char *);
+
+extern ssize_t bsltos(const m_label_t *, char **, size_t, int);
+extern ssize_t bcleartos(const m_label_t *, char **, size_t, int);
+
+
+extern char *sbsltos(const m_label_t *, size_t);
+extern char *sbcleartos(const m_label_t *, size_t);
+
+
+extern int stobsl(const char *, m_label_t *, int, int *);
+extern int stobclear(const char *, m_label_t *, int, int *);
+extern int bslvalid(const m_label_t *);
+extern int bclearvalid(const m_label_t *);
+
+/* Manifest human readable label names */
+
+#define ADMIN_LOW "ADMIN_LOW"
+#define ADMIN_HIGH "ADMIN_HIGH"
+
+/* DIA label conversion and parsing */
+
+/* Conversion types */
+
+typedef enum _m_label_str {
+ M_LABEL = 1, /* process or user clearance */
+ M_INTERNAL = 2, /* internal form for use in public databases */
+ M_COLOR = 3, /* process label color */
+ PRINTER_TOP_BOTTOM = 4, /* DIA banner page top/bottom */
+ PRINTER_LABEL = 5, /* DIA banner page label */
+ PRINTER_CAVEATS = 6, /* DIA banner page caveats */
+ PRINTER_CHANNELS = 7 /* DIA banner page handling channels */
+} m_label_str_t;
+
+/* Flags for conversion, not all flags apply to all types */
+#define DEF_NAMES 0x1
+#define SHORT_NAMES 0x3 /* short names are prefered where defined */
+#define LONG_NAMES 0x4 /* long names are prefered where defined */
+
+extern int label_to_str(const m_label_t *, char **, const m_label_str_t,
+ uint_t);
+
+/* Parsing types */
+typedef enum _m_label_type {
+ MAC_LABEL = 1, /* process or object label */
+ USER_CLEAR = 2 /* user's clearance (LUB) */
+} m_label_type_t;
+
+/* Flags for parsing */
+
+#define L_DEFAULT 0x0
+#define L_MODIFY_EXISTING 0x1 /* start parsing with existing label */
+#define L_NO_CORRECTION 0x2 /* must be correct by l_e rules */
+
+/* EINVAL sub codes */
+
+#define M_BAD_STRING -3 /* DIA L_BAD_LABEL */
+ /* bad requested label type, bad previous label type */
+#define M_BAD_LABEL -2 /* DIA L_BAD_CLASSIFICATION, */
+
+extern int str_to_label(const char *, m_label_t **, const m_label_type_t,
+ uint_t, int *);
+
+extern m_label_t *m_label_alloc(const m_label_type_t);
+
+extern int m_label_dup(m_label_t **, const m_label_t *);
+
+extern void m_label_free(m_label_t *);
+
+/* Contract Private interfaces with the label builder GUIs */
+
+extern int bslcvtfull(const m_label_t *, const m_range_t *, int,
+ char **, char **[], char **[], char *[], int *, int *);
+extern int bslcvt(const m_label_t *, int, char **, char *[]);
+extern int bclearcvtfull(const m_label_t *, const m_range_t *, int,
+ char **, char **[], char **[], char *[], int *, int *);
+extern int bclearcvt(const m_label_t *, int, char **, char *[]);
+
+extern int labelfields(struct name_fields *);
+extern int userdefs(m_label_t *, m_label_t *);
+extern int zonecopy(m_label_t *, char *, char *, char *, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_TSOL_LABEL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/common/labeld.h Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,473 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _LABELD_H
+#define _LABELD_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <tsol/label.h>
+#include <sys/tsol/label_macro.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Definitions for the call parameters for the door-based label
+ * translation service.
+ */
+
+#define BUFSIZE 4096
+
+#define DOOR_PATH "/var/tsol/doors/"
+#define DOOR_NAME "labeld"
+#define COOKIE (void *)0x6c616264 /* "labd" */
+
+/* Op codes */
+
+/* Labeld Commands */
+
+#define LABELDNULL 1
+
+/* Miscellaneous */
+
+#define BLINSET 10
+#define BSLVALID 11
+#define BILVALID 12
+#define BCLEARVALID 13
+#define LABELINFO 14
+#define LABELVERS 15
+#define BLTOCOLOR 16
+
+/* Binary to String Label Translation */
+
+#define BSLTOS 23
+#define BCLEARTOS 25
+
+/* String to Binary Label Translation */
+
+#define STOBSL 31
+#define STOBCLEAR 33
+
+/*
+ * Dimming List Routines
+ * Contract private for label builders
+ */
+
+#define BSLCVT 40
+#define BCLEARCVT 42
+#define LABELFIELDS 43
+#define UDEFS 44
+
+#define GETFLABEL 45
+#define SETFLABEL 46
+#define ZCOPY 47
+
+/* NEW LABELS */
+/* DIA printer banner labels */
+
+#define PR_CAVEATS 101
+#define PR_CHANNELS 102
+#define PR_LABEL 103
+#define PR_TOP 104
+
+/* DIA label to string */
+
+#define LTOS 105
+
+/* DIA string to label */
+
+#define STOL 106
+
+/* Structures */
+
+typedef uint_t bufp_t; /* offset into buf[] in/out string buffer */
+
+/* Null call */
+
+typedef struct {
+ int null;
+} null_call_t;
+
+typedef struct {
+ int null;
+} null_ret_t;
+
+/* Miscellaneous interfaces */
+
+typedef struct {
+ bslabel_t label;
+ int type;
+} inset_call_t;
+
+typedef struct {
+ int inset;
+} inset_ret_t;
+
+typedef struct {
+ bslabel_t label;
+} slvalid_call_t;
+
+typedef struct {
+ int valid;
+} slvalid_ret_t;
+
+typedef struct {
+ bclear_t clear;
+} clrvalid_call_t;
+
+typedef struct {
+ int valid;
+} clrvalid_ret_t;
+
+typedef struct {
+ int null;
+} info_call_t;
+
+typedef struct {
+ struct label_info info;
+} info_ret_t;
+
+typedef struct {
+ int null;
+} vers_call_t;
+
+typedef struct {
+ char vers[BUFSIZE];
+} vers_ret_t;
+
+typedef struct {
+ blevel_t label;
+} color_call_t;
+
+typedef struct {
+ char color[BUFSIZE];
+} color_ret_t;
+
+/* Binary Label to String interfaces */
+
+typedef struct {
+ bslabel_t label;
+ uint_t flags;
+} bsltos_call_t;
+
+typedef struct {
+ char slabel[BUFSIZE];
+} bsltos_ret_t;
+
+typedef struct {
+ bclear_t clear;
+ uint_t flags;
+} bcleartos_call_t;
+
+typedef struct {
+ char cslabel[BUFSIZE];
+} bcleartos_ret_t;
+
+/* String to Binary Label interfaces */
+
+typedef struct {
+ bslabel_t label;
+ uint_t flags;
+ char string[BUFSIZE];
+} stobsl_call_t;
+
+typedef struct {
+ bslabel_t label;
+} stobsl_ret_t;
+
+typedef struct {
+ bclear_t clear;
+ uint_t flags;
+ char string[BUFSIZE];
+} stobclear_call_t;
+
+typedef struct {
+ bclear_t clear;
+} stobclear_ret_t;
+
+/*
+ * The following Dimming List and Miscellaneous interfaces
+ * implement contract private interfaces for the label builder
+ * interfaces.
+ */
+
+/* Dimming List interfaces */
+
+typedef struct {
+ bslabel_t label;
+ brange_t bounds;
+ uint_t flags;
+} bslcvt_call_t;
+
+typedef struct {
+ bufp_t string;
+ bufp_t dim;
+ bufp_t lwords;
+ bufp_t swords;
+ size_t d_len;
+ size_t l_len;
+ size_t s_len;
+ int first_comp;
+ int first_mark;
+ char buf[BUFSIZE];
+} cvt_ret_t;
+
+typedef cvt_ret_t bslcvt_ret_t;
+
+typedef struct {
+ bclear_t clear;
+ brange_t bounds;
+ uint_t flags;
+} bclearcvt_call_t;
+
+typedef cvt_ret_t bclearcvt_ret_t;
+
+/* Miscellaneous interfaces */
+
+typedef struct {
+ int null;
+} fields_call_t;
+
+typedef struct {
+ bufp_t classi;
+ bufp_t compsi;
+ bufp_t marksi;
+ char buf[BUFSIZE];
+} fields_ret_t;
+
+typedef struct {
+ int null;
+} udefs_call_t;
+
+typedef struct {
+ bslabel_t sl;
+ bclear_t clear;
+} udefs_ret_t;
+
+typedef struct {
+ bslabel_t sl;
+ char pathname[BUFSIZE];
+} setfbcl_call_t;
+
+typedef struct {
+ int status;
+} setfbcl_ret_t;
+
+typedef struct {
+ bslabel_t src_win_sl;
+ int transfer_mode;
+ bufp_t remote_dir;
+ bufp_t filename;
+ bufp_t local_dir;
+ bufp_t display;
+ char buf[BUFSIZE];
+} zcopy_call_t;
+
+typedef struct {
+ int status;
+} zcopy_ret_t;
+
+typedef struct {
+ m_label_t label;
+ uint_t flags;
+} pr_call_t;
+
+typedef struct {
+ char buf[BUFSIZE];
+} pr_ret_t;
+
+typedef struct {
+ m_label_t label;
+ uint_t flags;
+} ls_call_t;
+
+typedef struct {
+ char buf[BUFSIZE];
+} ls_ret_t;
+
+typedef struct {
+ m_label_t label;
+ uint_t flags;
+ char string[BUFSIZE];
+} sl_call_t;
+
+typedef struct {
+ m_label_t label;
+} sl_ret_t;
+
+/* Labeld operation call structure */
+
+typedef struct {
+ uint_t op;
+ union {
+ null_call_t null_arg;
+
+ inset_call_t inset_arg;
+ slvalid_call_t slvalid_arg;
+ clrvalid_call_t clrvalid_arg;
+ info_call_t info_arg;
+ vers_call_t vers_arg;
+ color_call_t color_arg;
+
+ bsltos_call_t bsltos_arg;
+ bcleartos_call_t bcleartos_arg;
+
+ stobsl_call_t stobsl_arg;
+ stobclear_call_t stobclear_arg;
+
+ bslcvt_call_t bslcvt_arg;
+ bclearcvt_call_t bclearcvt_arg;
+ fields_call_t fields_arg;
+ udefs_call_t udefs_arg;
+ setfbcl_call_t setfbcl_arg;
+ zcopy_call_t zcopy_arg;
+ pr_call_t pr_arg;
+ ls_call_t ls_arg;
+ sl_call_t sl_arg;
+ } cargs;
+} labeld_call_t;
+
+/* Labeld operation return structure */
+
+typedef struct {
+ int ret; /* labeld return codes */
+ int err; /* function error codes */
+ union {
+ null_ret_t null_ret;
+
+ inset_ret_t inset_ret;
+ slvalid_ret_t slvalid_ret;
+ clrvalid_ret_t clrvalid_ret;
+ info_ret_t info_ret;
+ vers_ret_t vers_ret;
+ color_ret_t color_ret;
+
+ bsltos_ret_t bsltos_ret;
+ bcleartos_ret_t bcleartos_ret;
+
+ stobsl_ret_t stobsl_ret;
+ stobclear_ret_t stobclear_ret;
+
+ bslcvt_ret_t bslcvt_ret;
+ bclearcvt_ret_t bclearcvt_ret;
+ fields_ret_t fields_ret;
+ udefs_ret_t udefs_ret;
+ setfbcl_ret_t setfbcl_ret;
+ zcopy_ret_t zcopy_ret;
+ pr_ret_t pr_ret;
+ ls_ret_t ls_ret;
+ sl_ret_t sl_ret;
+ } rvals;
+} labeld_ret_t;
+
+/* Labeld call/return structure */
+
+typedef struct {
+ union {
+ labeld_call_t acall;
+ labeld_ret_t aret;
+ } param;
+} labeld_data_t;
+
+#define callop param.acall.op
+#define retret param.aret.ret
+#define reterr param.aret.err
+
+#define CALL_SIZE(type, buf) (size_t)(sizeof (type) + sizeof (int) + (buf))
+#define RET_SIZE(type, buf) (size_t)(sizeof (type) + 2*sizeof (int) + (buf))
+
+/* Labeld common client call function */
+
+int
+__call_labeld(labeld_data_t **dptr, size_t *ndata, size_t *adata);
+
+/* Return Codes */
+
+#define SUCCESS 1 /* Call OK */
+#define NOTFOUND -1 /* Function not found */
+#define SERVERFAULT -2 /* Internal labeld error */
+#define NOSERVER -3 /* No server thread available, try later */
+
+/* Flag Translation Values */
+
+#define L_NEW_LABEL 0x10000000
+
+/* GFI FLAGS */
+
+#define GFI_FLAG_MASK 0x0000FFFF
+#define GFI_ACCESS_RELATED 0x00000001
+
+/* binary to ASCII */
+
+#define LABELS_NO_CLASS 0x00010000
+#define LABELS_SHORT_CLASS 0x00020000
+#define LABELS_SHORT_WORDS 0x00040000
+
+/* Label view */
+
+#define LABELS_VIEW_INTERNAL 0x00100000
+#define LABELS_VIEW_EXTERNAL 0x00200000
+
+/* Dimming list (convert -- b*cvt* ) */
+
+#define LABELS_FULL_CONVERT 0x00010000
+
+/* ASCII to binary */
+
+#define LABELS_NEW_LABEL 0x00010000
+#define LABELS_FULL_PARSE 0x00020000
+#define LABELS_ONLY_INFO_LABEL 0x00040000
+
+#define MOVE_FILE 0
+#define COPY_FILE 1
+#define LINK_FILE 2
+
+#define PIPEMSG_FILEOP_ERROR 1
+#define PIPEMSG_EXIST_ERROR 2
+#define PIPEMSG_DONE 7
+#define PIPEMSG_PATH_ERROR 20
+#define PIPEMSG_ZONE_ERROR 21
+#define PIPEMSG_LABEL_ERROR 22
+#define PIPEMSG_READ_ERROR 23
+#define PIPEMSG_READONLY_ERROR 24
+#define PIPEMSG_WRITE_ERROR 25
+#define PIPEMSG_CREATE_ERROR 26
+#define PIPEMSG_DELETE_ERROR 27
+#define PIPEMSG_CANCEL 101
+#define PIPEMSG_PROCEED 102
+#define PIPEMSG_MERGE 103
+#define PIPEMSG_REPLACE_BUFFER 104
+#define PIPEMSG_RENAME_BUFFER 105
+#define PIPEMSG_MULTI_PROCEED 106
+#define PIPEMSG_RENAME_FILE 107
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LABELD_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/common/llib-ltsol Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,35 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* LINTLIBRARY */
+/* PROTOLIB1 */
+
+#include <tsol/label.h>
+#include <sys/tsol/label.h>
+#include <sys/tsol/priv.h>
+#include <sys/tsol/label_macro.h>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/common/ltos.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,283 @@
+/*
+ * 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 <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/tsol/label_macro.h>
+
+#include <tsol/label.h>
+
+#include "clnt.h"
+#include "labeld.h"
+
+static _mac_label_impl_t low;
+static _mac_label_impl_t high;
+static int inited = 0;
+
+/* 0x + Classification + '-' + ll + '-' + Compartments + end of string */
+#define _HEX_SIZE 2+(sizeof (Classification_t)*2)+4+\
+ (sizeof (Compartments_t)*2)+1
+
+/* 0x + Classification + '-' + ll + '-' + end of string */
+#define _MIN_HEX (2 + (sizeof (Classification_t)*2) + 4 + 1)
+
+static char digits[] = "0123456789abcdef";
+
+#define HEX(h, i, l, s) \
+ for (; i < s; /* */) {\
+ h[i++] = digits[(unsigned int)(*l >> 4)];\
+ h[i++] = digits[(unsigned int)(*l++&0xF)]; }
+
+static int
+__hex(char **s, const m_label_t *l)
+{
+ char *hex;
+ int i = 0;
+ uchar_t *hl;
+ int hex_len;
+ uchar_t *len;
+
+ hl = (uchar_t *)&(((_mac_label_impl_t *)l)->_c_len);
+ len = hl;
+
+ if (*len == 0) {
+ /* old binary label */
+ hex_len = _HEX_SIZE;
+ } else {
+ hex_len = _MIN_HEX + (*len * sizeof (uint32_t) * 2);
+ }
+
+ if ((hex = malloc(hex_len)) == NULL) {
+ return (-1);
+ }
+
+ /* header */
+
+ hex[i++] = '0';
+ hex[i++] = 'x';
+
+ /* classification */
+
+ hl++; /* start at classification */
+ HEX(hex, i, hl, 6);
+
+ /* Add compartments length */
+ hex[i++] = '-';
+ HEX(hex, i, len, 9);
+ hex[i++] = '-';
+
+ /* compartments */
+ HEX(hex, i, hl, hex_len-1);
+ hex[i] = '\0';
+
+ /* truncate trailing zeros */
+
+ while (hex[i-1] == '0' && hex[i-2] == '0') {
+ i -= 2;
+ }
+ hex[i] = '\0';
+
+ if ((*s = strdup(hex)) == NULL) {
+ free(hex);
+ return (-1);
+ }
+
+ free(hex);
+ return (0);
+
+}
+
+/*
+ * label_to_str -- convert a label to the requested type of string.
+ *
+ * Entry l = label to convert;
+ * t = type of conversion;
+ * f = flags for conversion type;
+ *
+ * Exit *s = allocated converted string;
+ * Caller must call free() to free.
+ *
+ * Returns 0, success.
+ * -1, error, errno set; *s = NULL.
+ *
+ * Calls labeld
+ */
+
+int
+label_to_str(const m_label_t *l, char **s, const m_label_str_t t, uint_t f)
+{
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize;
+ int err;
+
+ if (inited == 0) {
+ inited = 1;
+ _BSLLOW(&low);
+ _BSLHIGH(&high);
+ }
+
+#define lscall callp->param.acall.cargs.ls_arg
+#define lsret callp->param.aret.rvals.ls_ret
+ switch (t) {
+ case M_LABEL:
+ call.callop = LTOS;
+ lscall.label = *l;
+ lscall.flags = f;
+ datasize = CALL_SIZE(ls_call_t, 0);
+ if ((err = __call_labeld(&callp, &bufsize, &datasize)) ==
+ SUCCESS) {
+ if (callp->reterr != 0) {
+ errno = EINVAL;
+ *s = NULL;
+ return (-1);
+ }
+ if ((*s = strdup(lsret.buf)) == NULL) {
+ return (-1);
+ }
+ if (callp != &call) {
+ /* release returned buffer */
+ (void) munmap((void *)callp, bufsize);
+ }
+ return (0);
+ }
+ switch (err) {
+ case NOSERVER:
+ /* server not present */
+ /* special case admin_low and admin_high */
+
+ if (_MEQUAL(&low, (_mac_label_impl_t *)l)) {
+ if ((*s = strdup(ADMIN_LOW)) == NULL) {
+ return (-1);
+ }
+ return (0);
+ } else if (_MEQUAL(&high, (_mac_label_impl_t *)l)) {
+ if ((*s = strdup(ADMIN_HIGH)) == NULL) {
+ return (-1);
+ }
+ return (0);
+ }
+ errno = ENOTSUP;
+ break;
+ default:
+ errno = EINVAL;
+ break;
+ }
+ *s = NULL;
+ return (-1);
+#undef lscall
+#undef lsret
+
+ case M_INTERNAL: {
+ if (!(_MTYPE(l, SUN_MAC_ID) ||
+ _MTYPE(l, SUN_UCLR_ID))) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (_MEQUAL(&low, (_mac_label_impl_t *)l)) {
+ if ((*s = strdup(ADMIN_LOW)) == NULL) {
+ return (-1);
+ }
+ return (0);
+ }
+ if (_MEQUAL(&high, (_mac_label_impl_t *)l)) {
+ if ((*s = strdup(ADMIN_HIGH)) == NULL) {
+ return (-1);
+ }
+ return (0);
+ }
+
+ return (__hex(s, l));
+ }
+
+#define ccall callp->param.acall.cargs.color_arg
+#define cret callp->param.aret.rvals.color_ret
+ case M_COLOR:
+ datasize = CALL_SIZE(color_call_t, 0);
+ call.callop = BLTOCOLOR;
+ ccall.label = *l;
+
+ if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) {
+ errno = ENOTSUP;
+ *s = NULL;
+ return (-1);
+ } if (callp->reterr != 0) {
+ errno = EINVAL;
+ *s = NULL;
+ return (-1);
+ }
+ if ((*s = strdup(cret.color)) == NULL) {
+ return (-1);
+ }
+ return (0);
+#undef ccall
+#undef cret
+
+#define prcall callp->param.acall.cargs.pr_arg
+#define prret callp->param.aret.rvals.pr_ret
+ case PRINTER_TOP_BOTTOM:
+ call.callop = PR_TOP;
+ break;
+ case PRINTER_LABEL:
+ call.callop = PR_LABEL;
+ break;
+ case PRINTER_CAVEATS:
+ call.callop = PR_CAVEATS;
+ break;
+ case PRINTER_CHANNELS:
+ call.callop = PR_CHANNELS;
+ break;
+ default:
+ errno = EINVAL;
+ *s = NULL;
+ return (-1);
+ }
+ /* do the common printer calls */
+ datasize = CALL_SIZE(pr_call_t, 0);
+ prcall.label = *l;
+ prcall.flags = f;
+ if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) {
+ errno = ENOTSUP;
+ *s = NULL;
+ return (-1);
+ } if (callp->reterr != 0) {
+ errno = EINVAL;
+ *s = NULL;
+ return (-1);
+ }
+ if ((*s = strdup(prret.buf)) == NULL) {
+ return (-1);
+ }
+ return (0);
+#undef prcall
+#undef prret
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/common/misc.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,476 @@
+/*
+ * 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"
+
+
+/*
+ * Miscellaneous user interfaces to trusted label functions.
+ *
+ */
+
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include <sys/mman.h>
+
+#include <tsol/label.h>
+
+#include "labeld.h"
+#include "clnt.h"
+#include <sys/tsol/label_macro.h>
+#include <secdb.h>
+#include <user_attr.h>
+
+static bslabel_t slow, shigh; /* static Admin Low and High SLs */
+static bclear_t clow, chigh; /* static Admin Low and High CLRs */
+
+static char color[MAXCOLOR];
+
+
+#define incall callp->param.acall.cargs.inset_arg
+#define inret callp->param.aret.rvals.inset_ret
+/*
+ * blinset - Check in a label set.
+ *
+ * Entry label = Sensitivity Label to check.
+ * id = Label set identifier of set to check.
+ *
+ * Exit None.
+ *
+ * Returns -1, If label set unavailable, or server failure.
+ * 0, If label not in label set.
+ * 1, If label is in the label set.
+ *
+ * Calls __call_labeld(BLINSET), BLTYPE, BSLLOW, BSLHIGH.
+ *
+ * Uses slow, shigh.
+ */
+
+int
+blinset(const bslabel_t *label, const set_id *id)
+{
+ if (id->type == SYSTEM_ACCREDITATION_RANGE) {
+ if (!BLTYPE(&slow, SUN_SL_ID)) {
+ /* initialize static labels. */
+
+ BSLLOW(&slow);
+ BSLHIGH(&shigh);
+ }
+
+ if (BLTYPE(label, SUN_SL_ID) &&
+ (BLEQUAL(label, &slow) || BLEQUAL(label, &shigh)))
+
+ return (1);
+ }
+ if (id->type == USER_ACCREDITATION_RANGE ||
+ id->type == SYSTEM_ACCREDITATION_RANGE) {
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize = CALL_SIZE(inset_call_t, 0);
+
+ call.callop = BLINSET;
+ incall.label = *label;
+ incall.type = id->type;
+
+ if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) {
+ /* process error */
+
+ return (-1);
+ }
+ return (inret.inset);
+ } else {
+ /*
+ * Only System and User Accreditation Ranges presently
+ * implemented.
+ */
+ return (-1);
+ }
+}
+#undef incall
+#undef inret
+
+#define slvcall callp->param.acall.cargs.slvalid_arg
+#define slvret callp->param.aret.rvals.slvalid_ret
+/*
+ * bslvalid - Check Sensitivity Label for validity.
+ *
+ * Entry label = Sensitivity Label to check.
+ *
+ * Exit None.
+ *
+ * Returns -1, If unable to access label encodings file, or server failure.
+ * 0, If label not valid.
+ * 1, If label is valid.
+ *
+ * Calls __call_labeld(BSLVALID), BLTYPE, BSLLOW, BSLHIGH.
+ *
+ * Uses slow, shigh.
+ *
+ */
+
+int
+bslvalid(const bslabel_t *label)
+{
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize = CALL_SIZE(slvalid_call_t, 0);
+
+ if (!BLTYPE(&slow, SUN_SL_ID)) {
+ /* initialize static labels. */
+
+ BSLLOW(&slow);
+ BSLHIGH(&shigh);
+ }
+
+ if (BLTYPE(label, SUN_SL_ID) &&
+ (BLEQUAL(label, &slow) || BLEQUAL(label, &shigh))) {
+
+ return (1);
+ }
+
+ call.callop = BSLVALID;
+ slvcall.label = *label;
+
+ if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) {
+ /* process error */
+
+ return (-1);
+ }
+ return (slvret.valid);
+}
+#undef slvcall
+#undef slvret
+
+#define clrvcall callp->param.acall.cargs.clrvalid_arg
+#define clrvret callp->param.aret.rvals.clrvalid_ret
+/*
+ * bclearvalid - Check Clearance for validity.
+ *
+ * Entry clearance = Clearance to check.
+ *
+ * Exit None.
+ *
+ * Returns -1, If unable to access label encodings file, or server failure.
+ * 0, If label not valid.
+ * 1, If label is valid.
+ *
+ * Calls __call_labeld(BCLEARVALID), BLTYPE, BCLEARLOW, BCLEARHIGH.
+ *
+ * Uses clow, chigh.
+ *
+ */
+
+int
+bclearvalid(const bclear_t *clearance)
+{
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize = CALL_SIZE(clrvalid_call_t, 0);
+
+ if (!BLTYPE(&clow, SUN_CLR_ID)) {
+ /* initialize static labels. */
+
+ BCLEARLOW(&clow);
+ BCLEARHIGH(&chigh);
+ }
+
+ if (BLTYPE(clearance, SUN_CLR_ID) &&
+ (BLEQUAL(clearance, &clow) || BLEQUAL(clearance, &chigh))) {
+
+ return (1);
+ }
+
+ call.callop = BCLEARVALID;
+ clrvcall.clear = *clearance;
+
+ if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) {
+ /* process error */
+
+ return (-1);
+ }
+ return (clrvret.valid);
+}
+#undef clrvcall
+#undef clrvret
+
+#define inforet callp->param.aret.rvals.info_ret
+/*
+ * labelinfo - Get information about the label encodings file.
+ *
+ * Entry info = Address of label_info structure to update.
+ *
+ * Exit info = Updated.
+ *
+ * Returns -1, If unable to access label encodings file, or server failure.
+ * 1, If successful.
+ *
+ * Calls __call_labeld(LABELINFO).
+ */
+
+int
+labelinfo(struct label_info *info)
+{
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize = CALL_SIZE(info_call_t, 0);
+ int rval;
+
+ call.callop = LABELINFO;
+
+ if ((rval = __call_labeld(&callp, &bufsize, &datasize)) != SUCCESS) {
+ /* process error */
+
+ return (-1);
+ }
+ *info = inforet.info;
+ return (rval);
+}
+#undef inforet
+
+#define lvret callp->param.aret.rvals.vers_ret
+/*
+ * labelvers - Get version string of the label encodings file.
+ *
+ * Entry version = Address of string pointer to return.
+ * len = Length of string if pre-allocated.
+ *
+ * Exit version = Updated.
+ *
+ * Returns -1, If unable to access label encodings file, or server failure.
+ * 0, If unable to allocate version string,
+ * or pre-allocated version string to short
+ * (and **version = '\0').
+ * length (including null) of version string, If successful.
+ *
+ * Calls __call_labeld(LABELVERS)
+ * malloc, strlen.
+ */
+
+ssize_t
+labelvers(char **version, size_t len)
+{
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize = CALL_SIZE(vers_call_t, 0);
+ size_t ver_len;
+
+ call.callop = LABELVERS;
+
+ if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) {
+
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (-1);
+ }
+
+ /* unpack length */
+
+ ver_len = strlen(lvret.vers) + 1;
+ if (*version == NULL) {
+ if ((*version = malloc(ver_len)) == NULL) {
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (0);
+ }
+ } else if (ver_len > len) {
+ **version = '\0';
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (0);
+ }
+ (void) strcpy(*version, lvret.vers);
+
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (ver_len);
+} /* labelvers */
+#undef lvret
+
+#define ccall callp->param.acall.cargs.color_arg
+#define cret callp->param.aret.rvals.color_ret
+/*
+ * bltocolor - get ASCII color name of label.
+ *
+ * Entry label = Sensitivity Level of color to get.
+ * size = Size of the color_name array.
+ * color_name = Storage for ASCII color name string to be returned.
+ *
+ * Exit None.
+ *
+ * Returns NULL, If error (label encodings file not accessible,
+ * invalid label, no color for this label).
+ * Address of color_name parameter containing ASCII color name
+ * defined for the label.
+ *
+ * Calls __call_labeld(BLTOCOLOR), strlen.
+ */
+
+char *
+bltocolor_r(const blevel_t *label, size_t size, char *color_name)
+{
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize = CALL_SIZE(color_call_t, 0);
+ char *colorp;
+
+ call.callop = BLTOCOLOR;
+ ccall.label = *label;
+
+ if ((__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) ||
+ (callp->reterr != 0) ||
+ (strlen(cret.color) >= size)) {
+
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (NULL);
+ }
+
+ colorp = strcpy(color_name, cret.color);
+
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (colorp);
+} /* bltocolor_r */
+#undef ccall
+#undef cret
+
+/*
+ * bltocolor - get ASCII color name of label.
+ *
+ * Entry label = Sensitivity Level of color to get.
+ *
+ * Exit None.
+ *
+ * Returns NULL, If error (label encodings file not accessible,
+ * invalid label, no color for this label).
+ * Address of statically allocated string containing ASCII
+ * color name defined for the classification contained
+ * in label.
+ *
+ * Uses color.
+ *
+ * Calls bltocolor_r.
+ */
+
+char *
+bltocolor(const blevel_t *label)
+{
+ return (bltocolor_r(label, sizeof (color), color));
+} /* bltocolor */
+
+blevel_t *
+blabel_alloc(void)
+{
+ return (m_label_alloc(MAC_LABEL));
+}
+
+void
+blabel_free(blevel_t *label_p)
+{
+ free(label_p);
+}
+
+size_t
+blabel_size(void)
+{
+ return (sizeof (blevel_t));
+}
+
+/*
+ * getuserrange - get label range for user
+ *
+ * Entry username of user
+ *
+ * Exit None.
+ *
+ * Returns NULL, If memory allocation failure or userdefs failure.
+ * otherwise returns the allocates m_range_t with the
+ * user's min and max labels set.
+ */
+
+m_range_t *
+getuserrange(const char *username)
+{
+ char *kv_str = NULL;
+ userattr_t *userp = NULL;
+ m_range_t *range;
+ int err;
+
+ /*
+ * Get some memory
+ */
+
+ if ((range = malloc(sizeof (m_range_t))) == NULL) {
+ return (NULL);
+ }
+ if ((range->lower_bound = m_label_alloc(MAC_LABEL)) == NULL) {
+ free(range);
+ return (NULL);
+ }
+ if ((range->upper_bound = m_label_alloc(USER_CLEAR)) == NULL) {
+ m_label_free(range->lower_bound);
+ free(range);
+ return (NULL);
+ }
+ /*
+ * Since user_attr entries are optional, start with
+ * the system default values
+ */
+ if ((userdefs(range->lower_bound, range->upper_bound)) == -1) {
+ m_label_free(range->lower_bound);
+ m_label_free(range->upper_bound);
+ free(range);
+ return (NULL);
+ }
+ /*
+ * If the user has an explicit min_label or clearance,
+ * then use it instead.
+ */
+ if ((userp = getusernam(username)) == NULL) {
+ return (range);
+ }
+ if ((kv_str = kva_match(userp->attr, USERATTR_MINLABEL)) != NULL)
+ (void) stobsl(kv_str, range->lower_bound, NO_CORRECTION, &err);
+ if ((kv_str = kva_match(userp->attr, USERATTR_CLEARANCE)) != NULL)
+ (void) stobclear(kv_str, range->upper_bound, NO_CORRECTION,
+ &err);
+ free_userattr(userp);
+ return (range);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/common/private.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,660 @@
+/*
+ * 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"
+
+/*
+ * Label library contract private interfaces.
+ *
+ * Binary labels to String labels with dimming word lists.
+ * Dimming word list titles.
+ * Default user labels.
+ */
+
+#include <locale.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <strings.h>
+
+#include <sys/mman.h>
+
+#include <tsol/label.h>
+
+#include "clnt.h"
+#include "labeld.h"
+
+/*
+ * cvt memory:
+ *
+ * cvt: char *long_words[display_size]; Pointers to long words
+ * char *short_words[display_size]; Pointers to short words
+ * dim: char display[display_size]; Dim | Set
+ *
+ * strings associated with long and short words.
+ *
+ */
+
+/*
+ * Sensitivity Label words.
+ */
+
+static char *slcvt = NULL;
+static int slcvtsize = 0;
+static char *sldim;
+
+static char *slstring = NULL;
+static int slstringsize = 0;
+static brange_t sbounds;
+
+/*
+ * Clearance words.
+ */
+
+static char *clrcvt = NULL;
+static int clrcvtsize = 0;
+static char *clrdim;
+
+static char *clrstring = NULL;
+static int clrstringsize = 0;
+static brange_t cbounds;
+
+static
+int
+alloc_words(char **words, const size_t size)
+{
+ if (*words == NULL) {
+ if ((*words = malloc(size)) == NULL)
+ return (0);
+ } else {
+ if ((*words = realloc(*words, size)) == NULL) {
+ return (0);
+ }
+ }
+ return (1);
+}
+
+/*
+ * build_strings - Build the static strings and dimming list for a
+ * converted label.
+ *
+ * Entry new_string = Newly converted string.
+ * new_words_size = Size of words associated with newly converted
+ * label.
+ * number_of_words = Number of words associated with newly
+ * converted label.
+ * full = 1, if static words lists to be updated.
+ * 0, if only string and dimming list to be updated.
+ *
+ * Exit static_string_size = Updated if needed.
+ * static_string = Updated to new label string.
+ * static_words_size = Updated if needed.
+ * static_words = Updated to new words list, if needed.
+ * static_dimming = Updated to new dimming state.
+ * long_words = Updated to new long words pointers, if needed.
+ * short_words = Updated to new short words pointers, if needed.
+ *
+ *
+ * Returns 0, If unable to allocate memory.
+ * 1, If successful.
+ *
+ * Calls alloc_string, alloc_words, memcpy, strcpy, strlen.
+ */
+
+static
+int
+build_strings(int *static_string_size, char **static_string, char *new_string,
+ int *static_words_size, int new_words_size, char **static_words,
+ char **static_dimming, int number_of_words, char *long_words,
+ char *short_words, char *dimming_list, int full)
+{
+ char **l;
+ char **s;
+ char *w;
+ char *l_w = long_words;
+ char *s_w = short_words;
+ int i;
+ int len;
+ int newsize;
+
+ if (*static_string_size == 0) { /* Allocate string memory. */
+ if ((*static_string_size = alloc_string(static_string,
+ *static_string_size, 'C')) == 0)
+ /* can't get string memory for string */
+ return (0);
+ }
+
+again:
+ if (*static_string_size < (int)strlen(new_string)+1) {
+ /* need longer string */
+ if ((newsize = alloc_string(static_string, *static_string_size,
+ 'C')) == 0)
+ /* can't get more string memory */
+ return (0);
+
+ *static_string_size += newsize;
+ goto again;
+ }
+ bcopy(new_string, *static_string, strlen(new_string) + 1);
+
+ if (full) {
+ if (*static_words_size < new_words_size &&
+ !alloc_words(static_words, new_words_size)) {
+ /* can't get more words memory */
+ return (0);
+ } else {
+ *static_words_size = new_words_size;
+ }
+ /*LINTED*/
+ l = (char **)*static_words;
+ s = l + number_of_words;
+ *static_dimming = (char *)(s + number_of_words);
+ w = *static_dimming + number_of_words;
+ for (i = 0; i < number_of_words; i++) {
+ *l = w;
+ (void) strcpy(w, l_w);
+ w += (len = strlen(l_w) + 1);
+ l_w += len;
+ if (*s_w == '\000') {
+ *s = NULL;
+ s_w++;
+ } else {
+ *s = w;
+ (void) strcpy(w, s_w);
+ w += (len = strlen(s_w) + 1);
+ s_w += len;
+ }
+
+ l++;
+ s++;
+ } /* for each word entry */
+ } /* if (full) */
+
+ bcopy(dimming_list, *static_dimming, number_of_words);
+ return (1);
+} /* build_strings */
+
+#define bsfcall callp->param.acall.cargs.bslcvt_arg
+#define bsfret callp->param.aret.rvals.bslcvt_ret
+/*
+ * bslcvtfull - Convert Sensitivity Label and initialize static
+ * information.
+ *
+ * Entry label = Sensitivity Label to convert and get dimming list.
+ * This label should lie within the bounds or the
+ * results may not be meaningful.
+ * bounds = Lower and upper bounds for words lists. Must be
+ * dominated by clearance.
+ * flags = VIEW_INTERNAL, don't promote/demote admin low/high.
+ * VIEW_EXTERNAL, promote/demote admin low/high.
+ *
+ * Exit string = ASCII coded Sensitivity Label.
+ * long_words = Array of pointers to visible long word names.
+ * short_words = Array of pointers to visible short word names.
+ * display = Array of indicators as to whether the word is present
+ * in the converted label (CVT_SET), and/or changeable
+ * (CVT_DIM).
+ * first_compartment = Zero based index of first compartment.
+ * display_size = Number of entries in the display/words lists.
+ *
+ * Returns -1, If unable to access label encodings database, or
+ * invalid label.
+ * 0, If unable to allocate static memory.
+ * 1, If successful.
+ *
+ * Calls RPC - LABELS_BSLCONVERT, STTBLEVEL, SETBSLABEL, TCLNT,
+ * build_strings, clnt_call, clnt_perror.
+ *
+ * Uses sbounds, slrcvt, slrcvtsize, slrdim, slrstring,
+ * slrstringsize.
+ */
+
+int
+bslcvtfull(const bslabel_t *label, const blrange_t *bounds, int flags,
+ char **string, char **long_words[], char **short_words[], char *display[],
+ int *first_compartment, int *display_size)
+{
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize = CALL_SIZE(bslcvt_call_t, 0);
+ int new_words_size;
+ int rval;
+
+ call.callop = BSLCVT;
+ bsfcall.label = *label;
+ bsfcall.bounds.upper_bound = *bounds->upper_bound;
+ bsfcall.bounds.lower_bound = *bounds->lower_bound;
+ bsfcall.flags = LABELS_FULL_CONVERT;
+ set_label_view(&bsfcall.flags, flags);
+
+ if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == NOSERVER) {
+#ifdef DEBUG
+ (void) fprintf(stderr, "No label server.\n");
+#endif /* DEBUG */
+ return (-1);
+ } else if (rval != SUCCESS) {
+ return (-1);
+ } else {
+ if (callp->reterr != 0)
+ return (-1);
+ }
+
+ *first_compartment = bsfret.first_comp;
+ *display_size = bsfret.d_len;
+
+ new_words_size = bsfret.l_len + bsfret.s_len + bsfret.d_len +
+ (2 * sizeof (char *)) * bsfret.d_len;
+
+ if (build_strings(&slstringsize, &slstring, &bsfret.buf[bsfret.string],
+ &slcvtsize, new_words_size, &slcvt, &sldim, bsfret.d_len,
+ &bsfret.buf[bsfret.lwords], &bsfret.buf[bsfret.swords],
+ &bsfret.buf[bsfret.dim], 1) != 1) {
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (0);
+ }
+
+ /* save for bslcvt call */
+ sbounds.upper_bound = *bounds->upper_bound;
+ sbounds.lower_bound = *bounds->lower_bound;
+
+ *string = slstring;
+ *display = sldim;
+ /*LINTED*/
+ *long_words = (char **)slcvt;
+ /*LINTED*/
+ *short_words = (char **)(slcvt + *display_size * sizeof (char *));
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (1);
+} /* bslcvtfull */
+#undef bsfcall
+#undef bsfret
+
+#define bsccall callp->param.acall.cargs.bslcvt_arg
+#define bscret callp->param.aret.rvals.bslcvt_ret
+/*
+ * bslcvt - Convert Sensitivity Label and update dimming information.
+ *
+ * Entry label = Sensitivity Label to convert and get dimming list.
+ * This label should lie within the bounds of the
+ * corresponding bslcvtfull call or the results may
+ * not be meaningful.
+ * flags = VIEW_INTERNAL, don't promote/demote admin low/high.
+ * VIEW_EXTERNAL, promote/demote admin low/high.
+ *
+ * Exit string = ASCII coded Sensitivity Label.
+ * display = Array of indicators as to whether the word is present
+ * in the converted label (CVT_SET), and/or changeable
+ * (CVT_DIM).
+ *
+ * Returns -1, If unable to access label encodings database, or
+ * invalid label.
+ * 0, If unable to allocate static memory.
+ * 1, If successful.
+ *
+ * Calls RPC - LABELS_BSLCONVERT, SETBLEVEL, SETBSLABEL, build_strings
+ * clnt_call, clnt_perror.
+ *
+ * Uses sbounds, slrdim, slrstring.
+ */
+
+int
+bslcvt(const bslabel_t *label, int flags, char **string, char *display[])
+{
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize = CALL_SIZE(bslcvt_call_t, 0);
+ int rval;
+
+ if (slcvt == NULL)
+ return (-1); /* conversion not initialized */
+
+ call.callop = BSLCVT;
+ bsccall.label = *label;
+ bsccall.bounds = sbounds; /* save from last bslcvtfull() call */
+ bsccall.flags = 0;
+ set_label_view(&bsccall.flags, flags);
+
+ if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == NOSERVER) {
+#ifdef DEBUG
+ (void) fprintf(stderr, "No label server.\n");
+#endif /* DEBUG */
+ return (-1);
+ } else if (rval != SUCCESS) {
+ return (-1);
+ } else {
+ if (callp->reterr != 0)
+ return (-1);
+ }
+
+ if (build_strings(&slstringsize, &slstring, &bscret.buf[bscret.string],
+ &slcvtsize, 0, &slcvt, &sldim, bscret.d_len,
+ &bscret.buf[bscret.lwords], &bscret.buf[bscret.swords],
+ &bscret.buf[bscret.dim], 0) != 1) {
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (0);
+ }
+
+ *string = slstring;
+ *display = sldim;
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (1);
+} /* bslcvt */
+#undef bsccall
+#undef bscret
+
+#define bcfcall callp->param.acall.cargs.bclearcvt_arg
+#define bcfret callp->param.aret.rvals.bclearcvt_ret
+/*
+ * bclearcvtfull - Convert Clearance and initialize static information.
+ *
+ * Entry clearance = Clearance to convert and get dimming list.
+ * This clearance should lie within the bounds or
+ * the results may not be meaningful.
+ * bounds = Lower and upper bounds for words lists. Must be
+ * dominated by clearance.
+ * flags = VIEW_INTERNAL, don't promote/demote admin low/high.
+ * VIEW_EXTERNAL, promote/demote admin low/high.
+ *
+ * Exit string = ASCII coded Clearance.
+ * long_words = Array of pointers to visible long word names.
+ * short_words = Array of pointers to visible short word names.
+ * display = Array of indicators as to whether the word is present
+ * in the converted label (CVT_SET), and/or changeable
+ * (CVT_DIM).
+ * first_compartment = Zero based index of first compartment.
+ * display_size = Number of entries in the display/words lists.
+ *
+ * Returns -1, If unable to access label encodings database, or
+ * invalid label.
+ * 0, If unable to allocate static memory.
+ * 1, If successful.
+ *
+ * Calls RPC - LABELS_BCLEARCONVERT, SETBCLEAR, SETBLEVEL, TCLNT,
+ * build_strings, clnt_call, clnt_perror.
+ *
+ * Uses cbounds, clrcvt, clrcvtsize, clrdim, clrstring,
+ * clrstringsize.
+ */
+
+int
+bclearcvtfull(const bclear_t *clearance, const blrange_t *bounds,
+ int flags, char **string, char **long_words[], char **short_words[],
+ char *display[], int *first_compartment, int *display_size)
+{
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize = CALL_SIZE(bclearcvt_call_t, 0);
+ int new_words_size;
+ int rval;
+
+ call.callop = BCLEARCVT;
+ bcfcall.clear = *clearance;
+ bcfcall.bounds.upper_bound = *bounds->upper_bound;
+ bcfcall.bounds.lower_bound = *bounds->lower_bound;
+ bcfcall.flags = LABELS_FULL_CONVERT;
+ set_label_view(&bcfcall.flags, flags);
+
+ if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == NOSERVER) {
+#ifdef DEBUG
+ (void) fprintf(stderr, "No label server.\n");
+#endif /* DEBUG */
+ return (-1);
+ } else if (rval != SUCCESS) {
+ return (-1);
+ } else {
+ if (callp->reterr != 0)
+ return (-1);
+ }
+
+ *first_compartment = bcfret.first_comp;
+ *display_size = bcfret.d_len;
+
+ new_words_size = bcfret.l_len + bcfret.s_len + bcfret.d_len +
+ (2 * sizeof (char *)) * bcfret.d_len;
+
+ if (build_strings(&clrstringsize, &clrstring,
+ &bcfret.buf[bcfret.string],
+ &clrcvtsize, new_words_size, &clrcvt,
+ &clrdim, bcfret.d_len,
+ &bcfret.buf[bcfret.lwords], &bcfret.buf[bcfret.swords],
+ &bcfret.buf[bcfret.dim], 1) != 1) {
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (0);
+ }
+
+ /* save for bclearcvt call */
+ cbounds.upper_bound = *bounds->upper_bound;
+ cbounds.lower_bound = *bounds->lower_bound;
+
+ *string = clrstring;
+ *display = clrdim;
+ /*LINTED*/
+ *long_words = (char **)clrcvt;
+ /*LINTED*/
+ *short_words = (char **)(clrcvt + *display_size * sizeof (char *));
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (1);
+} /* bclearcvtfull */
+#undef bcfcall
+#undef bcfret
+
+#define bcccall callp->param.acall.cargs.bclearcvt_arg
+#define bccret callp->param.aret.rvals.bclearcvt_ret
+/*
+ * bclearcvt - Convert Clearance and update dimming inforamtion.
+ *
+ * Entry clearance = Clearance to convert and get dimming list.
+ * This clearance should lie within the bounds of the
+ * corresponding bclearcvtfull call or the results may
+ * not be meaningful.
+ * flags = VIEW_INTERNAL, don't promote/demote admin low/high.
+ * VIEW_EXTERNAL, promote/demote admin low/high.
+ *
+ * Exit string = ASCII coded Clearance.
+ * display = Array of indicators as to whether the word is present
+ * in the converted label (CVT_SET), and/or changeable
+ * (CVT_DIM).
+ *
+ * Returns -1, If unable to access label encodings database, or
+ * invalid label.
+ * 0, If unable to allocate static memory.
+ * 1, If successful.
+ *
+ * Calls RPC - LABELS_BCLEARCONVERT, SETBCLEAR, SETBLEVEL, build_strings,
+ * clnt_call, clnt_perror.
+ *
+ * Uses cbounds, clrdim, clrstring.
+ */
+
+int
+bclearcvt(const bclear_t *clearance, int flags, char **string,
+ char *display[])
+{
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize = CALL_SIZE(bclearcvt_call_t, 0);
+ int rval;
+
+ if (clrcvt == NULL)
+ return (-1); /* conversion not initialized */
+
+ call.callop = BCLEARCVT;
+ bcccall.clear = *clearance;
+ bcccall.bounds = cbounds; /* save from last bslcvtfull() call */
+ bcccall.flags = 0;
+ set_label_view(&bcccall.flags, flags);
+
+ if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == NOSERVER) {
+#ifdef DEBUG
+ (void) fprintf(stderr, "No label server.\n");
+#endif /* DEBUG */
+ return (-1);
+ } else if (rval != SUCCESS) {
+ return (-1);
+ } else {
+ if (callp->reterr != 0)
+ return (-1);
+ }
+
+ if (build_strings(&clrstringsize, &clrstring,
+ &bccret.buf[bccret.string],
+ &clrcvtsize, 0, &clrcvt, &clrdim, bccret.d_len,
+ &bccret.buf[bccret.lwords], &bccret.buf[bccret.swords],
+ &bccret.buf[bccret.dim], 0) != 1) {
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (0);
+ }
+
+ *string = clrstring;
+ *display = clrdim;
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (1);
+} /* bclearcvt */
+#undef bcccall
+#undef bccret
+
+#define lfret callp->param.aret.rvals.fields_ret
+/*
+ * labelfields - Return names for the label fields.
+ *
+ * Entry None
+ *
+ * Exit fields = Updated.
+ *
+ * Returns -1, If unable to access label encodings file, or
+ * labels server failure.
+ * 0, If unable to allocate memory.
+ * 1, If successful.
+ *
+ * Calls __call_labeld(LABELFIELDS).
+ */
+
+int
+labelfields(struct name_fields *fields)
+{
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize = CALL_SIZE(fields_call_t, 0);
+ int rval;
+
+ call.callop = LABELFIELDS;
+
+ if ((rval = __call_labeld(&callp, &bufsize, &datasize)) != SUCCESS) {
+
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (-1);
+ }
+
+ /* unpack results */
+
+ if ((fields->class_name = strdup(&lfret.buf[lfret.classi])) == NULL) {
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (0);
+ }
+ if ((fields->comps_name = strdup(&lfret.buf[lfret.compsi])) == NULL) {
+ free(fields->class_name);
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (0);
+ }
+ if ((fields->marks_name = strdup(&lfret.buf[lfret.marksi])) == NULL) {
+ free(fields->class_name);
+ free(fields->comps_name);
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (0);
+ }
+
+ if (callp != &call)
+ /* release return buffer */
+ (void) munmap((void *)callp, bufsize);
+ return (rval);
+} /* labelfields */
+#undef lfret
+
+#define udret callp->param.aret.rvals.udefs_ret
+/*
+ * userdefs - Get default user Sensitivity Label and Clearance.
+ *
+ * Entry None.
+ *
+ * Exit sl = default user Sensitivity Label.
+ * clear = default user Clearance.
+ *
+ * Returns -1, If unable to access label encodings file, or
+ * labels server failure.
+ * 1, If successful.
+ *
+ * Calls __call_labeld(UDEFS).
+ */
+
+int
+userdefs(bslabel_t *sl, bclear_t *clear)
+{
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize = CALL_SIZE(udefs_call_t, 0);
+ int rval;
+
+ call.callop = UDEFS;
+
+ if ((rval = __call_labeld(&callp, &bufsize, &datasize)) != SUCCESS) {
+ /* process error */
+
+ return (-1);
+ }
+
+ *sl = udret.sl;
+ *clear = udret.clear;
+ return (rval);
+} /* userdefs */
+#undef udret
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/common/privlib.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,179 @@
+/*
+ * 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 <errno.h>
+#include <priv.h>
+#include <sys/tsol/priv.h>
+#include <sys/varargs.h>
+
+/*
+ * set_effective_priv(op, num_priv, priv_id1, priv_id2, ... )
+ *
+ * Library routine to enable a user process to set its effective
+ * privilege set appropriately using a single call. User is
+ * required to specify the number of privilege ids that follow as
+ * arguments, rather than depending on the compiler to terminate
+ * the argument list with a NULL, which may be compiler-dependent.
+ */
+int
+set_effective_priv(priv_op_t op, int num_priv, ...)
+{
+ priv_set_t *priv_set;
+ priv_t priv_id;
+ va_list ap;
+ int status;
+
+ priv_set = priv_allocset();
+ PRIV_EMPTY(priv_set);
+
+ va_start(ap, num_priv);
+ while (num_priv--) {
+ char *priv_name;
+ /*
+ * Do sanity checking on priv_id's here to assure
+ * valid inputs to privilege macros. This checks
+ * num_priv argument as well.
+ */
+ priv_id = va_arg(ap, priv_t);
+ priv_name = (char *)priv_getbynum((int)(uintptr_t)priv_id);
+ if (priv_name == NULL) {
+ errno = EINVAL;
+ priv_freeset(priv_set);
+ return (-1);
+ }
+ (void) priv_addset(priv_set, priv_name);
+ }
+ va_end(ap);
+
+ /*
+ * Depend on system call to do sanity checking on "op"
+ */
+ status = setppriv(op, PRIV_EFFECTIVE, priv_set);
+ priv_freeset(priv_set);
+ return (status);
+
+} /* set_effective_priv() */
+
+
+
+
+/*
+ * set_inheritable_priv(op, num_priv, priv_id1, priv_id2, ... )
+ *
+ * Library routine to enable a user process to set its inheritable
+ * privilege set appropriately using a single call. User is
+ * required to specify the number of privilege ids that follow as
+ * arguments, rather than depending on the compiler to terminate
+ * the argument list with a NULL, which may be compiler-dependent.
+ */
+int
+set_inheritable_priv(priv_op_t op, int num_priv, ...)
+{
+ priv_set_t *priv_set;
+ priv_t priv_id;
+ va_list ap;
+ int status;
+
+ priv_set = priv_allocset();
+
+ PRIV_EMPTY(priv_set);
+
+ va_start(ap, num_priv);
+ while (num_priv--) {
+ /*
+ * Do sanity checking on priv_id's here to assure
+ * valid inputs to privilege macros. This checks
+ * num_priv argument as well.
+ */
+ priv_id = va_arg(ap, priv_t);
+ if ((char *)priv_getbynum((int)(uintptr_t)priv_id) == NULL) {
+ errno = EINVAL;
+ priv_freeset(priv_set);
+ return (-1);
+ }
+ (void) PRIV_ASSERT(priv_set, priv_id);
+ }
+ va_end(ap);
+
+ /*
+ * Depend on system call to do sanity checking on "op"
+ */
+ status = setppriv(op, PRIV_INHERITABLE, priv_set);
+ priv_freeset(priv_set);
+ return (status);
+
+} /* set_inheritable_priv() */
+
+
+
+
+/*
+ * set_permitted_priv(op, num_priv, priv_id1, priv_id2, ... )
+ *
+ * Library routine to enable a user process to set its permitted
+ * privilege set appropriately using a single call. User is
+ * required to specify the number of privilege ids that follow as
+ * arguments, rather than depending on the compiler to terminate
+ * the argument list with a NULL, which may be compiler-dependent.
+ */
+int
+set_permitted_priv(priv_op_t op, int num_priv, ...)
+{
+ priv_set_t *priv_set;
+ priv_t priv_id;
+ va_list ap;
+ int status;
+
+ priv_set = priv_allocset();
+
+ PRIV_EMPTY(priv_set);
+
+ va_start(ap, num_priv);
+ while (num_priv--) {
+ /*
+ * Do sanity checking on priv_id's here to assure
+ * valid inputs to privilege macros. This checks
+ * num_priv argument as well.
+ */
+ priv_id = va_arg(ap, priv_t);
+ if ((char *)priv_getbynum((int)(uintptr_t)priv_id) == NULL) {
+ errno = EINVAL;
+ priv_freeset(priv_set);
+ return (-1);
+ }
+ (void) PRIV_ASSERT(priv_set, priv_id);
+ }
+ va_end(ap);
+
+ /*
+ * Depend on system call to do sanity checking on "op"
+ */
+ status = setppriv(op, PRIV_PERMITTED, priv_set);
+ priv_freeset(priv_set);
+ return (status);
+
+} /* set_permitted_priv() */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/common/setflabel.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,309 @@
+/*
+ * 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"
+
+/*
+ * Change the label of a file
+ */
+
+#include <ctype.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <errno.h>
+
+#include <tsol/label.h>
+
+#include "labeld.h"
+#include <sys/tsol/label_macro.h>
+
+#include <sys/types.h>
+
+#include <zone.h>
+#include <sys/zone.h>
+#include <sys/param.h>
+#include <string.h>
+
+static int abspath(char *, const char *, char *);
+
+/*
+ * setflabel(3TSOL) - set file label
+ *
+ * This is the library interface to the door call.
+ */
+
+#define clcall callp->param.acall.cargs.setfbcl_arg
+#define clret callp->param.aret.rvals.setfbcl_ret
+/*
+ *
+ * Exit error = If error reported, the error indicator,
+ * -1, Unable to access label encodings file;
+ * 0, Invalid binary label passed;
+ * >0, Position after the first character in
+ * string of error, 1 indicates entire string.
+ * Otherwise, unchanged.
+ *
+ * Returns 0, If error.
+ * 1, If successful.
+ *
+ * Calls __call_labeld(SETFLABEL)
+ *
+ */
+
+int
+setflabel(const char *path, m_label_t *label)
+{
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize;
+ size_t path_len;
+ static char cwd[MAXPATHLEN];
+ char canon[MAXPATHLEN];
+
+
+ /*
+ * If path is relative and we haven't already determined the current
+ * working directory, do so now. Calculating the working directory
+ * here lets us do the work once, instead of (potentially) repeatedly
+ * in realpath().
+ */
+ if (*path != '/' && cwd[0] == '\0') {
+ if (getcwd(cwd, MAXPATHLEN) == NULL) {
+ cwd[0] = '\0';
+ return (-1);
+ }
+ }
+ /*
+ * Find an absolute pathname in the native file system name space that
+ * corresponds to path, stuffing it into canon.
+ */
+ if (abspath(cwd, path, canon) < 0)
+ return (-1);
+
+ path_len = strlen(canon) + 1;
+
+ datasize = CALL_SIZE(setfbcl_call_t, path_len - BUFSIZE);
+ datasize += 2; /* PAD */
+
+ if (datasize > bufsize) {
+ if ((callp = (labeld_data_t *)malloc(datasize)) == NULL) {
+ return (-1);
+ }
+ bufsize = datasize;
+ }
+
+ callp->callop = SETFLABEL;
+
+ clcall.sl = *label;
+ (void) strcpy(clcall.pathname, canon);
+
+ if (__call_labeld(&callp, &bufsize, &datasize) == SUCCESS) {
+ int err = callp->reterr;
+
+ if (callp != &call) {
+ /* free allocated buffer */
+ free(callp);
+ }
+ /*
+ * reterr == 0, OK,
+ * reterr < 0, invalid binary label,
+ */
+ if (err == 0) {
+ if (clret.status > 0) {
+ errno = clret.status;
+ return (-1);
+ } else {
+ return (0);
+ }
+ } else if (err < 0) {
+ err = 0;
+ }
+ errno = ECONNREFUSED;
+ return (-1);
+ } else {
+ if (callp != &call) {
+ /* free allocated buffer */
+ free(callp);
+ }
+ /* server not present */
+ errno = ECONNREFUSED;
+ return (-1);
+ }
+} /* setflabel */
+
+#undef clcall
+#undef clret
+
+#define clcall callp->param.acall.cargs.zcopy_arg
+#define clret callp->param.aret.rvals.zcopy_ret
+/*
+ *
+ * Exit status = result of zone copy request
+ * -1, Copy not confirmed
+ * Otherwise, unchanged.
+ *
+ * Returns 0, If error.
+ * 1, If successful.
+ *
+ * Calls __call_labeld(ZCOPY)
+ *
+ */
+int
+zonecopy(m_label_t *src_win_sl, char *remote_dir, char *filename,
+ char *local_dir, int transfer_mode)
+{
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize;
+ size_t strings;
+ size_t remote_dir_len;
+ size_t filename_len;
+ size_t local_dir_len;
+ size_t display_len;
+ char *display;
+
+ remote_dir_len = strlen(remote_dir) + 1;
+ filename_len = strlen(filename) + 1;
+ local_dir_len = strlen(local_dir) + 1;
+
+ if ((display = getenv("DISPLAY")) == NULL)
+ display = "";
+ display_len = strlen(display) + 1;
+
+ strings = remote_dir_len + filename_len + local_dir_len + display_len;
+
+ datasize = CALL_SIZE(zcopy_call_t, strings - BUFSIZE);
+
+ datasize += 4; /* PAD */
+
+ if (datasize > bufsize) {
+ if ((callp = (labeld_data_t *)malloc(datasize)) == NULL) {
+ return (NULL);
+ }
+ bufsize = datasize;
+ }
+
+ strings = 0;
+ callp->callop = ZCOPY;
+
+ clcall.src_win_sl = *src_win_sl;
+ clcall.transfer_mode = transfer_mode;
+ clcall.remote_dir = strings;
+ strings += remote_dir_len;
+ clcall.filename = strings;
+ strings += filename_len;
+ clcall.local_dir = strings;
+ strings += local_dir_len;
+ clcall.display = strings;
+
+ (void) strcpy(&clcall.buf[clcall.remote_dir], remote_dir);
+ (void) strcpy(&clcall.buf[clcall.filename], filename);
+ (void) strcpy(&clcall.buf[clcall.local_dir], local_dir);
+ (void) strcpy(&clcall.buf[clcall.display], display);
+
+ if (__call_labeld(&callp, &bufsize, &datasize) == SUCCESS) {
+ int err = callp->reterr;
+
+ if (callp != &call) {
+ /* free allocated buffer */
+ free(callp);
+ }
+ /*
+ * reterr == 0, OK,
+ * reterr < 0, transer not confirmed
+ */
+ if (err == 0) {
+ return (clret.status);
+ } else if (err < 0) {
+ err = 0;
+ }
+ return (PIPEMSG_CANCEL);
+ } else {
+ if (callp != &call) {
+ /* free allocated buffer */
+ free(callp);
+ }
+ /* server not present */
+ return (PIPEMSG_CANCEL);
+ }
+}
+
+/*
+ * Convert the path given in raw to canonical, absolute, symlink-free
+ * form, storing the result in the buffer named by canon, which must be
+ * at least MAXPATHLEN bytes long. If wd is non-NULL, assume that it
+ * points to a path for the current working directory and use it instead
+ * of invoking getcwd; accepting this value as an argument lets our caller
+ * cache the value, so that realpath (called from this routine) doesn't have
+ * to recalculate it each time it's given a relative pathname.
+ *
+ * Return 0 on success, -1 on failure.
+ */
+int
+abspath(char *wd, const char *raw, char *canon)
+{
+ char absbuf[MAXPATHLEN];
+
+ /*
+ * Preliminary sanity check.
+ */
+ if (raw == NULL || canon == NULL)
+ return (-1);
+
+ /*
+ * If the path is relative, convert it to absolute form,
+ * using wd if it's been supplied.
+ */
+ if (raw[0] != '/') {
+ char *limit = absbuf + sizeof (absbuf);
+ char *d;
+
+ /* Fill in working directory. */
+ if (wd != NULL)
+ (void) strncpy(absbuf, wd, sizeof (absbuf));
+ else if (getcwd(absbuf, strlen(absbuf)) == NULL)
+ return (-1);
+
+ /* Add separating slash. */
+ d = absbuf + strlen(absbuf);
+ if (d < limit)
+ *d++ = '/';
+
+ /* Glue on the relative part of the path. */
+ while (d < limit && (*d++ = *raw++))
+ continue;
+
+ raw = absbuf;
+ }
+
+ /*
+ * Call realpath to canonicalize and resolve symlinks.
+ */
+ return (realpath(raw, canon) == NULL ? -1 : 0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/common/stob.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,312 @@
+/*
+ * 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"
+
+/*
+ * String to binary label translations.
+ */
+
+#include <ctype.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include <tsol/label.h>
+
+#include "labeld.h"
+#include <sys/tsol/label_macro.h>
+
+#undef CALL_SIZE
+#define CALL_SIZE(type, buf) (size_t)(sizeof (type) - BUFSIZE + sizeof (int)\
+ + (buf))
+
+#if !defined(TEXT_DOMAIN) /* should be defined by Makefiles */
+#define TEXT_DOMAIN "SYS_TEST"
+#endif /* TEXT_DOMAIN */
+
+/* short hands */
+
+#define IS_ADMIN_LOW(sl) \
+ ((strncasecmp(sl, ADMIN_LOW, (sizeof (ADMIN_LOW) - 1)) == 0))
+
+#define IS_ADMIN_HIGH(sh) \
+ ((strncasecmp(sh, ADMIN_HIGH, (sizeof (ADMIN_HIGH) - 1)) == 0))
+
+#define ISHEX(f, s) \
+ (((((f) & NEW_LABEL) == ((f) | NEW_LABEL)) || \
+ (((f) & NO_CORRECTION) == ((f) | NO_CORRECTION))) && \
+ (((s)[0] == '0') && (((s)[1] == 'x') || ((s)[1] == 'X'))))
+
+#define slcall callp->param.acall.cargs.stobsl_arg
+#define slret callp->param.aret.rvals.stobsl_ret
+/*
+ * stobsl - Translate Sensitivity Label string to a Binary Sensitivity
+ * Label.
+ *
+ * Entry string = Sensitivity Label string to be translated.
+ * label = Address of Binary Sensitivity Label to be initialized or
+ * updated.
+ * flags = Flags to control translation:
+ * NO_CORRECTION implies NEW_LABEL.
+ * NEW_LABEL, Initialize the label to a valid empty
+ * Sensitivity Label structure.
+ * NO_CORRECTION, Initialize the label to a valid
+ * empty Sensitivity Label structure.
+ * Prohibit correction to the Sensitivity Label.
+ * Other, pass existing Sensitivity Label through for
+ * modification.
+ *
+ * Exit label = Translated (updated) Binary Sensitivity Label.
+ * error = If error reported, the error indicator,
+ * -1, Unable to access label encodings file;
+ * 0, Invalid binary label passed;
+ * >0, Position after the first character in
+ * string of error, 1 indicates entire string.
+ * Otherwise, unchanged.
+ *
+ * Returns 0, If error.
+ * 1, If successful.
+ *
+ * Calls __call_labeld(STOBSL), ISHEX, htobsl, strlen,
+ * isspace,
+ * strncasecmp.
+ *
+ * Uses ADMIN_HIGH, ADMIN_LOW.
+ */
+
+int
+stobsl(const char *string, bslabel_t *label, int flags, int *error)
+{
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize = CALL_SIZE(stobsl_call_t, strlen(string) + 1);
+ int rval;
+ char *s = (char *)string;
+
+ while (isspace(*s))
+ s++;
+ /* accept a leading '[' */
+ if (*s == '[') {
+ s++;
+ while (isspace(*s))
+ s++;
+ }
+ if (ISHEX(flags, s)) {
+ if (htobsl(s, label)) {
+ return (1);
+ } else {
+ if (error != NULL)
+ *error = 1;
+ return (0);
+ }
+ }
+
+ if (datasize > bufsize) {
+ if ((callp = malloc(datasize)) == NULL) {
+ if (error != NULL)
+ *error = -1;
+ return (0);
+ }
+ bufsize = datasize;
+ }
+ callp->callop = STOBSL;
+ slcall.flags = (flags&NEW_LABEL) ? LABELS_NEW_LABEL : 0;
+ slcall.flags |= (flags&NO_CORRECTION) ? LABELS_FULL_PARSE : 0;
+ slcall.label = *label;
+ (void) strcpy(slcall.string, string);
+
+ if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == SUCCESS) {
+ int err = callp->reterr;
+
+ if (callp != &call) {
+ /* free allocated buffer */
+ free(callp);
+ }
+ /*
+ * reterr == 0, OK,
+ * reterr < 0, invalid binary label,
+ * reterr > 0 error position, 1 == whole string
+ */
+ if (err == 0) {
+ *label = slret.label;
+ return (1);
+ } else if (err < 0) {
+ err = 0;
+ }
+ if (error != NULL)
+ *error = err;
+ return (0);
+ } else if (rval == NOSERVER) {
+ if (callp != &call) {
+ /* free allocated buffer */
+ free(callp);
+ }
+ /* server not present */
+ /* special case Admin High and Admin Low */
+ if (IS_ADMIN_LOW(s)) {
+ BSLLOW(label);
+ } else if (IS_ADMIN_HIGH(s)) {
+ BSLHIGH(label);
+ } else {
+ goto err1;
+ }
+ return (1);
+ }
+ if (callp != &call) {
+ /* free allocated buffer */
+ free(callp);
+ }
+err1:
+ if (error != NULL)
+ *error = -1;
+ return (0);
+} /* stobsl */
+#undef slcall
+#undef slret
+
+#define clrcall callp->param.acall.cargs.stobclear_arg
+#define clrret callp->param.aret.rvals.stobclear_ret
+/*
+ * stobclear - Translate Clearance string to a Binary Clearance.
+ *
+ * Entry string = Clearance string to be translated.
+ * clearance = Address of Binary Clearance to be initialized or
+ * updated.
+ * flags = Flags to control translation:
+ * NO_CORRECTION implies NEW_LABEL.
+ * NEW_LABEL, Initialize the label to a valid empty
+ * Sensitivity Label structure.
+ * NO_CORRECTION, Initialize the label to a valid
+ * empty Sensitivity Label structure.
+ * Prohibit correction to the Sensitivity Label.
+ * Other, pass existing Sensitivity Label through for
+ * modification.
+ *
+ * Exit clearance = Translated (updated) Binary Clearance.
+ * error = If error reported, the error indicator,
+ * -1, Unable to access label encodings file;
+ * 0, Invalid binary label passed;
+ * >0, Position after the first character in
+ * string of error, 1 indicates entire string.
+ * Otherwise, unchanged.
+ *
+ * Returns 0, If error.
+ * 1, If successful.
+ *
+ * Calls __call_labeld(STOBCLEAR), ISHEX, htobsl, strlen,
+ * isspace,
+ * strncasecmp.
+ *
+ * Uses ADMIN_HIGH, ADMIN_LOW.
+ */
+
+int
+stobclear(const char *string, bclear_t *clearance, int flags, int *error)
+{
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize = CALL_SIZE(callp->param.acall, strlen(string) + 1);
+ int rval;
+
+ if (ISHEX(flags, string)) {
+ if (htobclear(string, clearance)) {
+ return (1);
+ } else {
+ if (error != NULL)
+ *error = 1;
+ return (0);
+ }
+ }
+
+ if (datasize > bufsize) {
+ if ((callp = malloc(datasize)) == NULL) {
+ if (error != NULL)
+ *error = -1;
+ return (0);
+ }
+ bufsize = datasize;
+ }
+ callp->callop = STOBCLEAR;
+ clrcall.flags = (flags&NEW_LABEL) ? LABELS_NEW_LABEL : 0;
+ clrcall.flags |= (flags&NO_CORRECTION) ? LABELS_FULL_PARSE : 0;
+ clrcall.clear = *clearance;
+ (void) strcpy(clrcall.string, string);
+
+ if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == SUCCESS) {
+ int err = callp->reterr;
+
+ if (callp != &call) {
+ /* free allocated buffer */
+ free(callp);
+ }
+ /*
+ * reterr == 0, OK,
+ * reterr < 0, invalid binary label,
+ * reterr > 0 error position, 1 == whole string
+ */
+ if (err == 0) {
+ *clearance = clrret.clear;
+ return (1);
+ } else if (err < 0) {
+ err = 0;
+ }
+ if (error != NULL)
+ *error = err;
+ return (0);
+ } else if (rval == NOSERVER) {
+ char *s = (char *)string;
+
+ if (callp != &call) {
+ /* free allocated buffer */
+ free(callp);
+ }
+ /* server not present */
+ /* special case Admin High and Admin Low */
+ while (isspace(*s))
+ s++;
+ if (IS_ADMIN_LOW(s)) {
+ BCLEARLOW(clearance);
+ } else if (IS_ADMIN_HIGH(s)) {
+ BCLEARHIGH(clearance);
+ } else {
+ goto err1;
+ }
+ return (1);
+ }
+ if (callp != &call) {
+ /* free allocated buffer */
+ free(callp);
+ }
+err1:
+ if (error != NULL)
+ *error = -1;
+ return (0);
+} /* stobclear */
+#undef clrcall
+#undef clrret
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/common/stol.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,394 @@
+/*
+ * 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 <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+#include <sys/mman.h>
+#include <sys/tsol/label_macro.h>
+
+#include <tsol/label.h>
+
+#include "clnt.h"
+#include "labeld.h"
+
+#define IS_LOW(s) \
+ ((strncasecmp(s, ADMIN_LOW, (sizeof (ADMIN_LOW) - 1)) == 0) && \
+ (s[sizeof (ADMIN_LOW) - 1] == '\0'))
+#define IS_HIGH(s) \
+ ((strncasecmp(s, ADMIN_HIGH, (sizeof (ADMIN_HIGH) - 1)) == 0) && \
+ (s[sizeof (ADMIN_HIGH) - 1] == '\0'))
+#define IS_HEX(f, s) \
+ (((((f) == L_NO_CORRECTION)) || ((f) == L_DEFAULT)) && \
+ (((s)[0] == '0') && (((s)[1] == 'x') || ((s)[1] == 'X'))))
+
+static boolean_t
+unhex(char **h, uchar_t *l, int len)
+{
+ char *hx = *h;
+ char ch;
+ uchar_t byte;
+
+ for (; len--; ) {
+ ch = *hx++;
+ if (!isxdigit(ch))
+ return (B_FALSE);
+ if (isdigit(ch))
+ byte = ch - '0';
+ else
+ byte = ch - (isupper(ch) ? 'A' - 10 : 'a' - 10);
+ byte <<= 4;
+ ch = *hx++;
+ if (isdigit(ch))
+ byte |= ch - '0';
+ else
+ byte |= ch - (isupper(ch) ? 'A' - 10 : 'a' - 10);
+ *l++ = byte;
+ }
+ *h = hx;
+ return (B_TRUE);
+}
+
+/*
+ * Formats accepted:
+ * 0x + 4 class + 64 comps + end of string
+ * 0x + 4 class + '-' + ll + '-' + comps + end of string
+ * ll = number of words to fill out the entire comps field
+ * presumes trailing zero for comps
+ *
+ * So in the case of 256 comps (i.e., 8 compartment words):
+ * 0x0006-08-7ff3f
+ * 0x + Classification + Compartments + end of string
+ * 0[xX]hhh...
+ */
+
+static int
+htol(char *s, m_label_t *l)
+{
+ char *h = &s[2]; /* skip 0[xX] */
+ uchar_t *lp = (uchar_t *)&(((_mac_label_impl_t *)l)->_lclass);
+ size_t len = sizeof (_mac_label_impl_t) - 4;
+ int bytes;
+
+ /* unpack classification */
+ if (!unhex(&h, lp, 2)) {
+ goto error;
+ }
+ lp = (uchar_t *)&(((_mac_label_impl_t *)l)->_comps);
+ if (LCLASS(l) < LOW_CLASS ||
+ LCLASS(l) > HIGH_CLASS) {
+ goto error;
+ }
+ if (h[0] == '-' && h[3] == '-') {
+ uchar_t size;
+
+ /* length specified of internal text label */
+ h++; /* skip '-' */
+ if (!unhex(&h, &size, 1)) {
+ goto error;
+ }
+ size *= sizeof (uint32_t); /* words to bytes */
+ if (size > len) {
+ /*
+ * internal label greater than will fit in current
+ * binary.
+ */
+ goto error;
+ }
+ bzero(lp, len);
+ h++; /* skip '-' */
+ bytes = strlen(h)/2;
+ } else {
+ bytes = (strlen(h) + 1)/2;
+ }
+ if ((bytes > len) || !unhex(&h, lp, bytes)) {
+ goto error;
+ }
+ return (0);
+error:
+ errno = EINVAL;
+ return (-1);
+}
+
+static int
+convert_id(m_label_type_t t)
+{
+ switch (t) {
+ case MAC_LABEL:
+ return (SUN_MAC_ID);
+ case USER_CLEAR:
+ return (SUN_UCLR_ID);
+ default:
+ return (-1);
+ }
+}
+
+/*
+ * str_to_label -- parse a string into the requested label type.
+ *
+ * Entry s = string to parse.
+ * l = label to create or modify.
+ * t = label type (MAC_LABEL, USER_CLEAR).
+ * f = flags
+ * L_DEFAULT,
+ * L_MODIFY_EXISTING, use the existing label as a basis for
+ * the parse string.
+ * L_NO_CORRECTION, s must be correct and full by the
+ * label_encoding rules.
+ *
+ * Exit l = parsed label value.
+ * e = index into string of error.
+ * = M_BAD_STRING (-1) or could be zero, indicates entire string,
+ * e = M_BAD_LABEL (-3), problems with l
+ *
+ * Returns 0, success.
+ * -1, failure
+ * errno = ENOTSUP, the underlying label mechanism
+ * does not support label parsing.
+ * ENOMEM, unable to allocate memory for l.
+ * EINVAL, invalid argument, l != NULL or
+ * invalid label type for the underlying
+ * label mechanism.
+ */
+#define _M_GOOD_LABEL -1 /* gfi L_GOOD_LABEL */
+int
+str_to_label(const char *str, m_label_t **l, const m_label_type_t t, uint_t f,
+ int *e)
+{
+ char *s = (char *)str;
+ char *p;
+ labeld_data_t call;
+ labeld_data_t *callp = &call;
+ size_t bufsize = sizeof (labeld_data_t);
+ size_t datasize;
+ int err;
+ int id = convert_id(t);
+ boolean_t new = B_FALSE;
+
+ if (*l == NULL) {
+ if ((*l = m_label_alloc(t)) == NULL) {
+ return (-1);
+ }
+ if (id == -1) {
+ goto badlabel;
+ }
+ _LOW_LABEL(*l, id);
+ new = B_TRUE;
+ } else if (_MTYPE(*l, SUN_INVALID_ID) &&
+ ((f == L_NO_CORRECTION) || (f == L_DEFAULT))) {
+ _LOW_LABEL(*l, id);
+ new = B_TRUE;
+ } else if (!(_MTYPE(*l, SUN_MAC_ID) || _MTYPE(*l, SUN_CLR_ID))) {
+ goto badlabel;
+ }
+
+ if (new == B_FALSE && id == -1) {
+ goto badlabel;
+ }
+
+ /* get to the beginning of the string to parse */
+ while (isspace(*s)) {
+ s++;
+ }
+
+ /* accept a leading '[' and trailing ']' for old times sake */
+ if (*s == '[') {
+ s++;
+ while (isspace(*s)) {
+ s++;
+ }
+ }
+ p = s;
+ while (*p != '\0' && *p != ']') {
+ p++;
+ }
+
+ /* strip trailing spaces */
+ while (p != s && isspace(*(p-1))) {
+ --p;
+ }
+ *p = '\0'; /* end of string */
+
+ /* translate hex, admin_low and admin_high */
+ id = _MGETTYPE(*l);
+ if (IS_LOW(s)) {
+ _LOW_LABEL(*l, id);
+ return (0);
+ } else if (IS_HIGH(s)) {
+ _HIGH_LABEL(*l, id);
+ return (0);
+ } else if (IS_HEX(f, s)) {
+ int herr;
+
+ herr = htol(s, *l);
+ return (herr);
+ }
+#define slcall callp->param.acall.cargs.sl_arg
+#define slret callp->param.aret.rvals.sl_ret
+ /* now try label server */
+
+ datasize = CALL_SIZE(sl_call_t, strlen(str) + 1);
+ if (datasize > bufsize) {
+ if ((callp = malloc(datasize)) == NULL) {
+ return (-1);
+ }
+ bufsize = datasize;
+ }
+ callp->callop = STOL;
+ slcall.label = **l;
+ slcall.flags = f;
+ if (new)
+ slcall.flags |= L_NEW_LABEL;
+ (void) strcpy(slcall.string, str);
+ /*
+ * callp->reterr = L_GOOD_LABEL (-1) == OK;
+ * L_BAD_CLASSIFICATION (-2) == bad input
+ * classification: class
+ * L_BAD_LABEL (-3) == either sring or input label bad
+ * O'E == offset in string 0 == entire string.
+ */
+ if (__call_labeld(&callp, &bufsize, &datasize) == SUCCESS) {
+
+ err = callp->reterr;
+ if (callp != &call) {
+ /* free allocated buffer */
+ (void) free(callp);
+ }
+ switch (err) {
+ case _M_GOOD_LABEL: /* L_GOOD_LABEL */
+ **l = slret.label;
+ return (0);
+ case M_BAD_LABEL: /* L_BAD_CLASSIFICATION */
+ case M_BAD_STRING: /* L_BAD_LABEL */
+ default:
+ errno = EINVAL;
+ if (e != NULL)
+ *e = err;
+ return (-1);
+ }
+ }
+ switch (callp->reterr) {
+ case NOSERVER:
+ errno = ENOTSUP;
+ break;
+ default:
+ errno = EINVAL;
+ break;
+ }
+ return (-1);
+
+badlabel:
+ errno = EINVAL;
+ if (e != NULL)
+ *e = M_BAD_LABEL;
+ return (-1);
+}
+#undef slcall
+#undef slret
+
+/*
+ * m_label_alloc -- allocate a label structure
+ *
+ * Entry t = label type (MAC_LABEL, USER_CLEAR).
+ *
+ * Exit If error, NULL, errno set to ENOMEM
+ * Otherwise, pointer to m_label_t memory
+ */
+
+/* ARGUSED */
+m_label_t *
+m_label_alloc(const m_label_type_t t)
+{
+ m_label_t *l;
+
+ switch (t) {
+ case MAC_LABEL:
+ case USER_CLEAR:
+ if ((l = malloc(sizeof (_mac_label_impl_t))) == NULL) {
+ return (NULL);
+ }
+ _MSETTYPE(l, SUN_INVALID_ID);
+ break;
+ default:
+ errno = EINVAL;
+ return (NULL);
+ }
+ return (l);
+}
+
+/*
+ * m_label_dup -- make a duplicate copy of the given label.
+ *
+ * Entry l = label to duplicate.
+ *
+ * Exit d = duplicate copy of l.
+ *
+ * Returns 0, success
+ * -1, if error.
+ * errno = ENOTSUP, the underlying label mechanism
+ * does not support label duplication.
+ * ENOMEM, unable to allocate memory for d.
+ * EINVAL, invalid argument, l == NULL or
+ * invalid label type for the underlying
+ * label mechanism.
+ */
+
+int
+m_label_dup(m_label_t **d, const m_label_t *l)
+{
+ if (d == NULL || *d != NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if ((*d = malloc(sizeof (_mac_label_impl_t))) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ (void) memcpy(*d, l, sizeof (_mac_label_impl_t));
+ return (0);
+}
+
+/*
+ * m_label_free -- free label structure
+ *
+ * Entry l = label to free.
+ *
+ * Exit memory freed.
+ *
+ */
+
+void
+m_label_free(m_label_t *l)
+{
+ if (l)
+ free(l);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/common/zone.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,272 @@
+/*
+ * 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 <stdlib.h>
+#include <strings.h>
+#include <zone.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/tsol/label_macro.h>
+
+/*
+ * Get label from zone name
+ */
+m_label_t *
+getzonelabelbyname(const char *zone)
+{
+ zoneid_t zoneid;
+
+ if ((zoneid = getzoneidbyname(zone)) == -1) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ return (getzonelabelbyid(zoneid));
+}
+
+/*
+ * Get label from zone id
+ */
+m_label_t *
+getzonelabelbyid(zoneid_t zoneid)
+{
+ m_label_t *slabel;
+
+ if ((slabel = m_label_alloc(MAC_LABEL)) == NULL)
+ return (NULL);
+
+ if (zone_getattr(zoneid, ZONE_ATTR_SLBL, slabel,
+ sizeof (m_label_t)) < 0) {
+ m_label_free(slabel);
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ return (slabel);
+}
+
+/*
+ * Get zone id from label
+ */
+
+zoneid_t
+getzoneidbylabel(const m_label_t *label)
+{
+ m_label_t admin_low;
+ m_label_t admin_high;
+ zoneid_t zoneid;
+ zoneid_t *zids;
+ uint_t nzents;
+ uint_t nzents_saved;
+ int i;
+
+ bsllow(&admin_low);
+ bslhigh(&admin_high);
+
+ /* Check for admin_low or admin_high; both are global zone */
+ if (blequal(label, &admin_low) || blequal(label, &admin_high))
+ return (GLOBAL_ZONEID);
+
+ nzents = 0;
+ if (zone_list(NULL, &nzents) != 0)
+ return (-1);
+
+again:
+ if (nzents == 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /*
+ * Add a small amount of padding here to avoid spinning in a tight loop
+ * if there's a process running somewhere that's creating lots of zones
+ * all at once.
+ */
+ nzents += 8;
+ if ((zids = malloc(nzents * sizeof (zoneid_t))) == NULL)
+ return (-1);
+ nzents_saved = nzents;
+
+ if (zone_list(zids, &nzents) != 0) {
+ free(zids);
+ return (-1);
+ }
+ if (nzents > nzents_saved) {
+ /* list changed, try again */
+ free(zids);
+ goto again;
+ }
+
+ for (i = 0; i < nzents; i++) {
+ m_label_t test_sl;
+
+ if (zids[i] == GLOBAL_ZONEID)
+ continue;
+
+ if (zone_getattr(zids[i], ZONE_ATTR_SLBL, &test_sl,
+ sizeof (m_label_t)) < 0)
+ continue; /* Badly configured zone info */
+
+ if (blequal(label, &test_sl) != 0) {
+ zoneid = zids[i];
+ free(zids);
+ return (zoneid);
+ }
+ }
+ free(zids);
+ errno = EINVAL;
+ return (-1);
+}
+
+/*
+ * Get zoneroot for a zoneid
+ */
+
+char *
+getzonerootbyid(zoneid_t zoneid)
+{
+ char zoneroot[MAXPATHLEN];
+
+ if (zone_getattr(zoneid, ZONE_ATTR_ROOT, zoneroot,
+ sizeof (zoneroot)) == -1) {
+ return (NULL);
+ }
+
+ return (strdup(zoneroot));
+}
+
+/*
+ * Get zoneroot for a zonename
+ */
+
+char *
+getzonerootbyname(const char *zone)
+{
+ zoneid_t zoneid;
+
+ if ((zoneid = getzoneidbyname(zone)) == -1)
+ return (NULL);
+ return (getzonerootbyid(zoneid));
+}
+
+/*
+ * Get zoneroot for a label
+ */
+
+char *
+getzonerootbylabel(const m_label_t *label)
+{
+ zoneid_t zoneid;
+
+ if ((zoneid = getzoneidbylabel(label)) == -1)
+ return (NULL);
+ return (getzonerootbyid(zoneid));
+}
+
+/*
+ * Get label of path relative to global zone
+ *
+ * This function must be called from the global zone
+ */
+
+m_label_t *
+getlabelbypath(const char *path)
+{
+ m_label_t *slabel;
+ zoneid_t *zids;
+ uint_t nzents;
+ uint_t nzents_saved;
+ int i;
+
+ if (getzoneid() != GLOBAL_ZONEID) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ nzents = 0;
+ if (zone_list(NULL, &nzents) != 0)
+ return (NULL);
+
+again:
+ /* Add a small amount of padding to avoid loops */
+ nzents += 8;
+ zids = malloc(nzents * sizeof (zoneid_t));
+ if (zids == NULL)
+ return (NULL);
+
+ nzents_saved = nzents;
+
+ if (zone_list(zids, &nzents) != 0) {
+ free(zids);
+ return (NULL);
+ }
+ if (nzents > nzents_saved) {
+ /* list changed, try again */
+ free(zids);
+ goto again;
+ }
+
+ slabel = m_label_alloc(MAC_LABEL);
+ if (slabel == NULL) {
+ free(zids);
+ return (NULL);
+ }
+
+ for (i = 0; i < nzents; i++) {
+ char zoneroot[MAXPATHLEN];
+ int zonerootlen;
+
+ if (zids[i] == GLOBAL_ZONEID)
+ continue;
+
+ if (zone_getattr(zids[i], ZONE_ATTR_ROOT, zoneroot,
+ sizeof (zoneroot)) == -1)
+ continue; /* Badly configured zone info */
+
+ /*
+ * Need to handle the case for the /dev directory which is
+ * parallel to the zone's root directory. So we back up
+ * 4 bytes - the strlen of "root".
+ */
+ if ((zonerootlen = strlen(zoneroot)) <= 4)
+ continue; /* Badly configured zone info */
+ if (strncmp(path, zoneroot, zonerootlen - 4) == 0) {
+ /*
+ * If we get a match, the file is in a labeled zone.
+ * Return the label of that zone.
+ */
+ if (zone_getattr(zids[i], ZONE_ATTR_SLBL, slabel,
+ sizeof (m_label_t)) < 0)
+ continue; /* Badly configured zone info */
+
+ free(zids);
+ return (slabel);
+ }
+ }
+ free(zids);
+ bsllow(slabel);
+ return (slabel);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/i386/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,30 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#/
+
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/sparc/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,30 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/sparcv9/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,31 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/spec/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,28 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include $(SRC)/lib/Makefile.spec.arch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/spec/Makefile.targ Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+LIBRARY = libtsol.a
+VERS = .2
+OBJECTS = obsolete.o \
+ private.o \
+ tsol.o
+SPECCPP = -I../../common
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/spec/amd64/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+include $(SRC)/lib/Makefile.spec
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/spec/i386/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,32 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.spec
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/spec/obsolete.spec Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,122 @@
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Obsolete interfaces to be removed from a future release.
+# Retained to aid 3rd party initial porting from TS8.
+#
+# 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
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+function bcleartoh_r
+include <tsol/label.h>
+declaration char *bcleartoh_r(const bclear_t *clearance, char *hex);
+version SUNWprivate_1.1
+end
+
+function bcleartoh
+include <tsol/label.h>
+declaration char *bcleartoh(const bclear_t *clearance);
+version SUNWprivate_1.1
+end
+
+function bltocolor
+include <tsol/label.h>
+declaration char *bltocolor(const blevel_t *label);
+version SUNWprivate_1.1
+end
+
+function bltocolor_r
+include <tsol/label.h>
+declaration char *bltocolor_r(const blevel_t *label, int size, \
+ char *color_name);
+version SUNWprivate_1.1
+end
+
+function bsltoh
+include <tsol/label.h>
+declaration char *bsltoh(const bslabel_t *label);
+version SUNWprivate_1.1
+end
+
+function bsltoh_r
+include <tsol/label.h>
+declaration char *bsltoh_r(const bslabel_t *label, char *hex);
+version SUNWprivate_1.1
+end
+
+function bsltos
+include <tsol/label.h>
+declaration ssize_t bsltos(const bslabel_t *label, char **string, \
+ size_t str_len, int flags);
+version SUNWprivate_1.1
+end
+
+function h_alloc
+include <tsol/label.h>
+declaration char *h_alloc(unsigned char id);
+version SUNWprivate_1.1
+end
+
+function h_free
+include <tsol/label.h>
+declaration void h_free(char *hex);
+version SUNWprivate_1.1
+end
+
+function htobclear
+include <tsol/label.h>
+declaration int htobclear(const char *s, bclear_t *clearance);
+version SUNWprivate_1.1
+end
+
+function htobsl
+include <tsol/label.h>
+declaration int htobsl(const char *s, bslabel_t *label);
+version SUNWprivate_1.1
+end
+
+function sbcleartos
+include <tsol/label.h>
+declaration char *sbcleartos(const bclear_t *clearance, int len);
+version SUNWprivate_1.1
+end
+
+function sbsltos
+include <tsol/label.h>
+declaration char *sbsltos(const bslabel_t *label, int len);
+version SUNWprivate_1.1
+end
+
+function stobclear
+include <tsol/label.h>
+declaration int stobclear(const char *string, bclear_t *clearance, \
+ int flags, int *error);
+version SUNWprivate_1.1
+end
+
+function stobsl
+include <tsol/label.h>
+declaration int stobsl(const char *string, bslabel_t *label, int flags, \
+ int *error);
+version SUNWprivate_1.1
+end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/spec/private.spec Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,239 @@
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Project Private to the Trusted eXtensions project.
+# Not for public consumption or to be documented.
+#
+# 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
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+function bclearhigh
+include <tsol/label.h>
+declaration void bclearhigh(bclear_t *clearance);
+version SUNWprivate_1.1
+end
+
+function bclearlow
+include <tsol/label.h>
+declaration void bclearlow(bclear_t *clearance);
+version SUNWprivate_1.1
+end
+
+function bcleartos
+include <tsol/label.h>
+declaration ssize_t bcleartos(const bclear_t *clearance, char **string, \
+ size_t str_len, int flags);
+version SUNWprivate_1.1
+end
+
+function bclearundef
+include <tsol/label.h>
+declaration void bclearundef(bclear_t *clearance);
+version SUNWprivate_1.1
+end
+
+function bclearvalid
+include <tsol/label.h>
+declaration int bclearvalid(const bclear_t *clearance);
+version SUNWprivate_1.1
+end
+
+function bclearcvtfull
+include <tsol/label.h>
+declaration int bclearcvtfull(const bclear_t *clearance, \
+ const blrange_t *bounds, int flags, char **string, \
+ char **long_words[], char **short_words[], \
+ char *display[], int *first_compartment, \
+ int *display_size);
+version SUNWprivate_1.1
+end
+
+function bclearcvt
+include <tsol/label.h>
+declaration int bclearcvt(const bclear_t *clearance, int flags, \
+ char **string, char *display[]);
+version SUNWprivate_1.1
+end
+
+function blinrange
+include <tsol/label.h>
+declaration int blinrange(const blevel_t *label, const blrange_t *range);
+version SUNWprivate_1.1
+end
+
+function blinset
+include <tsol/label.h>
+declaration int blinset(const bslabel_t *label, const set_id *id);
+version SUNWprivate_1.1
+end
+
+function blmaximum
+include <tsol/label.h>
+declaration void blmaximum(blevel_t *label1, const blevel_t *label2);
+version SUNWprivate_1.1
+end
+
+function blminimum
+include <tsol/label.h>
+declaration void blminimum(blevel_t *label1, const blevel_t *label2);
+version SUNWprivate_1.1
+end
+
+function bltype
+include <tsol/label.h>
+declaration int bltype(const void *label, uint8_t type);
+version SUNWprivate_1.1
+end
+
+function bslcvtfull
+include <tsol/label.h>
+declaration int bslcvtfull(const bslabel_t *label,
+ const blrange_t *bounds, \
+ int flags, char **string, char **long_words[], \
+ char **short_words[], char *display[], \
+ int *first_compartment, int *display_size);
+version SUNWprivate_1.1
+end
+
+function bslcvt
+include <tsol/label.h>
+declaration int bslcvt(const bslabel_t *label, int flags, char **string, \
+ char *display[]);
+version SUNWprivate_1.1
+end
+
+function bslhigh
+include <tsol/label.h>
+declaration void bslhigh(bslabel_t *label);
+version SUNWprivate_1.1
+end
+
+function bsllow
+include <tsol/label.h>
+declaration void bsllow(bslabel_t *label);
+version SUNWprivate_1.1
+end
+
+function bslundef
+include <tsol/label.h>
+declaration void bslundef(bslabel_t *label);
+version SUNWprivate_1.1
+end
+
+function bslvalid
+include <tsol/label.h>
+declaration int bslvalid(const bslabel_t *label);
+version SUNWprivate_1.1
+end
+
+function labelinfo
+include <tsol/label.h>
+declaration int labelinfo(struct label_info *info);
+version SUNWprivate_1.1
+end
+
+function labelfields
+include <tsol/label.h>
+declaration int labelfields(struct name_fields *fields);
+version SUNWprivate_1.1
+end
+
+function labelvers
+include <tsol/label.h>
+declaration ssize_t labelvers(char **version, int len);
+version SUNWprivate_1.1
+end
+
+function getpathbylabel
+include <tsol/label.h>
+declaration char *getpathbylabel(const char *path_name, \
+ char *resolved_path, size_t bufsize, const bslabel_t *sl);
+version SUNWprivate_1.1
+end
+
+function getlabelbypath
+include <tsol/label.h>
+declaration m_label_t *getlabelbypath(char *path);
+version SUNWprivate_1.1
+end
+
+function blabel_alloc
+include <tsol/label.h>
+declaration blevel_t *blabel_alloc(void);
+version SUNWprivate_1.1
+end
+
+function blabel_free
+include <tsol/label.h>
+declaration void blabel_free(blevel_t *label_p);
+version SUNWprivate_1.1
+end
+
+function blabel_size
+include <tsol/label.h>
+declaration size_t blabel_size(void);
+version SUNWprivate_1.1
+end
+
+function setbltype
+include <tsol/label.h>
+declaration void setbltype(void *label, uint8_t type);
+version SUNWprivate_1.1
+end
+
+function bisinvalid
+include <tsol/label.h>
+declaration boolean_t bisinvalid(const void *label);
+version SUNWprivate_1.1
+end
+
+function set_effective_priv
+include <tsol/label.h>
+declaration int set_effective_priv(priv_op_t op, int num_priv, ...);
+version SUNWprivate_1.1
+end
+
+function set_inheritable_priv
+include <tsol/label.h>
+declaration int set_inheritable_priv(priv_op_t op, int num_priv, ...);
+version SUNWprivate_1.1
+end
+
+function set_permitted_priv
+include <tsol/label.h>
+declaration int set_permitted_priv(priv_op_t op, int num_priv, ...);
+version SUNWprivate_1.1
+end
+
+function userdefs
+include <tsol/label.h>
+declaration int userdefs(bslabel_t *sl, bclear_t *clear);
+version SUNWprivate_1.1
+end
+
+function zonecopy
+include <tsol/label.h>
+declaration int zonecopy(bslabel_t *src_win_sl, char *remote_dir, \
+ char *filename, char *local_dir, int transfer_mode);
+version SUNWprivate_1.1
+end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/spec/sparc/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,32 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.spec
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/spec/sparcv9/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+include $(SRC)/lib/Makefile.spec
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/spec/tsol.spec Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,143 @@
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# 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
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+
+function label_to_str
+include <tsol/label.h>
+declaration int label_to_str(const m_label_t *label, char **string, \
+ const m_label_str_t conversion_type, uint_t flags);
+version SUNW_2.1
+end
+
+function m_label_alloc
+include <tsol/label.h>
+declaration m_label_t m_label_dup(const m_label_type_t *type);
+version SUNW_2.1
+end
+
+function m_label_dup
+include <tsol/label.h>
+declaration int m_label_dup(m_label_t **dst, const m_label_t *src);
+version SUNW_2.1
+end
+
+function m_label_free
+include <tsol/label.h>
+declaration void m_label_free(m_label_t *label);
+version SUNW_2.1
+end
+
+function str_to_label
+include <tsol/label.h>
+declaration int str_to_label(const char *str, m_label_t **label, \
+ const m_label_type_t type, unit_t flags, int *error);
+version SUNW_2.1
+end
+
+function bldominates
+include <tsol/label.h>
+declaration int bldominates(const m_label_t *label1, \
+ const m_label_t *label2);
+version SUNW_2.1
+end
+
+function blequal
+include <tsol/label.h>
+declaration int blequal(const m_label_t *label1, const m_label_t *label2);
+version SUNW_2.1
+end
+
+function blstrictdom
+include <tsol/label.h>
+declaration int blstrictdom(const m_label_t *label1, \
+ const m_label_t *label2);
+version SUNW_2.1
+end
+
+function getlabel
+include <tsol/label.h>
+declaration int getlabel(const char *path, m_label_t *label);
+version SUNW_2.1
+end
+
+function fgetlabel
+include <tsol/label.h>
+declaration int fgetlabel(int fd, m_label_t *label);
+version SUNW_2.1
+end
+
+function getplabel
+include <tsol/label.h>
+declaration int getplabel(m_label_t *label_p);
+version SUNW_2.1
+end
+
+function getzoneidbylabel
+include <tsol/label.h>
+declaration zoneid_t getzoneidbylabel(const m_label_t *label);
+version SUNW_2.1
+end
+
+function getzonelabelbyid
+include <tsol/label.h>
+declaration m_label_t *getzonelabelbyid(zoneid_t zoneid);
+version SUNW_2.1
+end
+
+function getzonelabelbyname
+include <tsol/label.h>
+declaration m_label_t *getzonelabelbyname(char *zone);
+version SUNW_2.1
+end
+
+function getzonerootbyid
+include <tsol/label.h>
+declaration char *getzonerootbyid(zoneid_t zoneid);
+version SUNW_2.1
+end
+
+function getzonerootbylabel
+include <tsol/label.h>
+declaration char *getzonerootbylabel(m_label_t *label);
+version SUNW_2.1
+end
+
+function getzonerootbyname
+include <tsol/label.h>
+declaration char *getzonerootbyname(char *zone);
+version SUNW_2.1
+end
+
+function setflabel
+include <tsol/label.h>
+declaration int setflabel(const char *path, m_label_t *label);
+version SUNW_2.1
+end
+
+function getuserrange
+include <tsol/label.h>
+declaration m_range_t *getuserrange(const char *username);
+version SUNW_2.1
+end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libtsol/spec/versions Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,45 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# vers file for libtsol
+#
+
+sparc {
+ SUNW_2.1;
+ SUNWprivate_1.1;
+}
+i386 {
+ SUNW_2.1;
+ SUNWprivate_1.1;
+}
+sparcv9 {
+ SUNW_2.1;
+ SUNWprivate_1.1;
+}
+amd64 {
+ SUNW_2.1;
+ SUNWprivate_1.1;
+}
--- a/usr/src/lib/libzonecfg/common/libzonecfg.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/libzonecfg/common/libzonecfg.c Fri Mar 24 12:29:20 2006 -0800
@@ -49,8 +49,6 @@
#include <arpa/inet.h>
#include <netdb.h>
-#include <priv.h>
-
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
@@ -125,8 +123,8 @@
#define ATTACH_FORCED "SUNWattached.xml"
#define PKG_PATH "/var/sadm/pkg"
#define CONTENTS_FILE "/var/sadm/install/contents"
-#define ALL_ZONES "SUNW_PKG_ALLZONES=true\n"
-#define THIS_ZONE "SUNW_PKG_THISZONE=true\n"
+#define SUNW_PKG_ALL_ZONES "SUNW_PKG_ALLZONES=true\n"
+#define SUNW_PKG_THIS_ZONE "SUNW_PKG_THISZONE=true\n"
#define VERSION "VERSION="
#define PATCHLIST "PATCHLIST="
#define PATCHINFO "PATCH_INFO_"
@@ -3417,7 +3415,9 @@
PRIV_IPC_DAC_READ,
PRIV_IPC_DAC_WRITE,
PRIV_IPC_OWNER,
+ PRIV_NET_BINDMLP,
PRIV_NET_ICMPACCESS,
+ PRIV_NET_MAC_AWARE,
PRIV_NET_PRIVADDR,
PRIV_PROC_CHROOT,
PRIV_SYS_AUDIT,
@@ -5294,10 +5294,10 @@
len = strlen(infop->zpi_version);
*(infop->zpi_version + len - 1) = 0;
- } else if (strcmp(buf, ALL_ZONES) == 0) {
+ } else if (strcmp(buf, SUNW_PKG_ALL_ZONES) == 0) {
infop->zpi_all_zones = B_TRUE;
- } else if (strcmp(buf, THIS_ZONE) == 0) {
+ } else if (strcmp(buf, SUNW_PKG_THIS_ZONE) == 0) {
infop->zpi_this_zone = B_TRUE;
} else if (strncmp(buf, PATCHINFO, sizeof (PATCHINFO) - 1)
--- a/usr/src/lib/nsswitch/files/Makefile.com Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/nsswitch/files/Makefile.com Fri Mar 24 12:29:20 2006 -0800
@@ -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,6 +17,8 @@
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
+
+
#
#
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
@@ -49,7 +50,9 @@
getexecattr.o \
getuserattr.o \
getauuser.o \
- netmasks.o
+ netmasks.o \
+ tsol_getrhent.o \
+ tsol_gettpent.o
# include common nsswitch library definitions.
include ../../Makefile.com
--- a/usr/src/lib/nsswitch/files/common/mapfile-vers Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/nsswitch/files/common/mapfile-vers Fri Mar 24 12:29:20 2006 -0800
@@ -1,15 +1,14 @@
#
#ident "%Z%%M% %I% %E% SMI"
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# 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.
@@ -59,6 +58,8 @@
_nss_files_services_constr;
_nss_files_shadow_constr;
_nss_files_user_attr_constr;
+ _nss_files_tnrhdb_constr;
+ _nss_files_tnrhtp_constr;
local:
*;
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/nsswitch/files/common/tsol_getrhent.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,73 @@
+/*
+ * 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 "files_common.h"
+#include <string.h>
+#include <libtsnet.h>
+
+/*
+ * files/tsol_getrhent.c --
+ * "files" backend for nsswitch "tnrhdb" database
+ */
+static int
+check_addr(nss_XbyY_args_t *args)
+{
+ tsol_rhstr_t *rhstrp = (tsol_rhstr_t *)args->returnval;
+
+ if ((args->key.hostaddr.type == rhstrp->family) &&
+ (strcmp(args->key.hostaddr.addr, rhstrp->address) == 0))
+ return (1);
+
+ return (0);
+}
+
+static nss_status_t
+getbyaddr(files_backend_ptr_t be, void *a)
+{
+ nss_XbyY_args_t *argp = a;
+
+ return (_nss_files_XY_all(be, argp, 1,
+ argp->key.hostaddr.addr, check_addr));
+}
+
+static files_backend_op_t tsol_rh_ops[] = {
+ _nss_files_destr,
+ _nss_files_endent,
+ _nss_files_setent,
+ _nss_files_getent_netdb,
+ getbyaddr
+};
+
+/* ARGSUSED */
+nss_backend_t *
+_nss_files_tnrhdb_constr(const char *dummy1, const char *dummy2,
+ const char *dummy3)
+{
+ return (_nss_files_constr(tsol_rh_ops,
+ sizeof (tsol_rh_ops) / sizeof (tsol_rh_ops[0]), TNRHDB_PATH,
+ NSS_LINELEN_TSOL_RH, NULL));
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/nsswitch/files/common/tsol_gettpent.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,75 @@
+/*
+ * 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 "files_common.h"
+#include <sys/tsol/tndb.h>
+#include <string.h>
+
+/*
+ * files/tsol_gettpent.c --
+ * "files" backend for nsswitch "tnrhtp" database
+ */
+static int
+check_name(nss_XbyY_args_t *args)
+{
+ tsol_tpstr_t *tpstrp = (tsol_tpstr_t *)args->returnval;
+ const char *name = args->key.name;
+
+ if (strcmp(tpstrp->template, name) == 0)
+ return (1);
+
+ return (0);
+}
+
+static nss_status_t
+getbyname(be, a)
+ files_backend_ptr_t be;
+ void *a;
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+
+ return (_nss_files_XY_all(be, argp, 1, argp->key.name, check_name));
+}
+
+static files_backend_op_t tsol_tp_ops[] = {
+ _nss_files_destr,
+ _nss_files_endent,
+ _nss_files_setent,
+ _nss_files_getent_netdb,
+ getbyname
+};
+
+nss_backend_t *
+_nss_files_tnrhtp_constr(dummy1, dummy2, dummy3)
+ const char *dummy1, *dummy2, *dummy3;
+{
+ return (_nss_files_constr(tsol_tp_ops,
+ sizeof (tsol_tp_ops) / sizeof (tsol_tp_ops[0]),
+ "/etc/security/tsol/tnrhtp",
+ NSS_LINELEN_TSOL_TP,
+ NULL));
+}
--- a/usr/src/lib/nsswitch/ldap/Makefile.com Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/nsswitch/ldap/Makefile.com Fri Mar 24 12:29:20 2006 -0800
@@ -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,12 +17,14 @@
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
+
+
#
#
#ident "%Z%%M% %I% %E% SMI"
#
-# Copyright (c) 1999-2001 by Sun Microsystems, Inc.
-# All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
#
# lib/nsswitch/ldap/Makefile.com
@@ -51,6 +52,8 @@
getservent.o \
getspent.o \
getuserattr.o \
+ tsol_getrhent.o \
+ tsol_gettpent.o \
ldap_common.o \
ldap_utils.o
--- a/usr/src/lib/nsswitch/ldap/common/ldap_common.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/nsswitch/ldap/common/ldap_common.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -55,6 +54,9 @@
#define _F_GETSPENT "(objectclass=shadowAccount)"
#define _F_GETUSERNAME "(objectClass=SolarisUserAttr)"
#define _F_GETPROJENT "(objectClass=SolarisProject)"
+#define _F_GETTNRHDB "(objectClass=ipTnetHost)"
+#define _F_GETTNRHTP "(&(objectClass=ipTnetTemplate)"\
+ "(SolarisAttrKeyValue=*))"
#define _F_GETENT_SSD "(%s)"
static struct gettablefilter {
@@ -77,6 +79,8 @@
{(char *)_USERATTR, (char *)_F_GETUSERNAME},
{(char *)_PROJECT, (char *)_F_GETPROJENT},
{(char *)_PRINTERS, (char *)_F_GETPRINTERENT},
+ {(char *)_TNRHDB, (char *)_F_GETTNRHDB},
+ {(char *)_TNRHTP, (char *)_F_GETTNRHTP},
{(char *)NULL, (char *)NULL}
};
--- a/usr/src/lib/nsswitch/ldap/common/ldap_common.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/nsswitch/ldap/common/ldap_common.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -68,6 +67,8 @@
#define _SERVICES "services"
#define _SHADOW "shadow"
#define _USERATTR "user_attr"
+#define _TNRHDB "tnrhdb"
+#define _TNRHTP "tnrhtp"
#define NSS_STR_PARSE_NO_ADDR (NSS_STR_PARSE_ERANGE + 100)
--- a/usr/src/lib/nsswitch/ldap/common/mapfile-vers Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/lib/nsswitch/ldap/common/mapfile-vers Fri Mar 24 12:29:20 2006 -0800
@@ -1,15 +1,14 @@
#
#ident "%Z%%M% %I% %E% SMI"
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# 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.
@@ -61,6 +60,8 @@
_nss_ldap_shadow_constr;
_nss_ldap_publickey_constr;
_nss_ldap_user_attr_constr;
+ _nss_ldap_tnrhdb_constr;
+ _nss_ldap_tnrhtp_constr;
local:
*;
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/nsswitch/ldap/common/tsol_getrhent.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,183 @@
+/*
+ * 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 <netdb.h>
+#include "ldap_common.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/tsol/tndb.h>
+
+/* tnrhdb attributes filters */
+#define _TNRHDB_ADDR "ipTnetNumber"
+#define _TNRHDB_TNAME "ipTnetTemplateName"
+#define _F_GETTNDBBYADDR "(&(objectClass=ipTnetHost)(ipTnetNumber=%s))"
+#define _F_GETTNDBBYADDR_SSD "(&(%%s)(ipTnetNumber=%s))"
+
+static const char *tnrhdb_attrs[] = {
+ _TNRHDB_ADDR,
+ _TNRHDB_TNAME,
+ NULL
+};
+
+static int
+_nss_ldap_tnrhdb2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i, nss_result;
+ int len = 0;
+ int buflen = 0;
+ char *buffer = NULL;
+ char *ceiling = NULL;
+ ns_ldap_attr_t *attrptr;
+ ns_ldap_result_t *result = be->result;
+ tsol_rhstr_t *rhstrp;
+
+ buffer = argp->buf.buffer;
+ buflen = argp->buf.buflen;
+ if (argp->buf.result == NULL) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_tnrhdb2ent;
+ }
+ rhstrp = (tsol_rhstr_t *)(argp->buf.result);
+ rhstrp->family = 0;
+ rhstrp->address = rhstrp->template = NULL;
+ ceiling = buffer + buflen;
+ (void) memset(argp->buf.buffer, 0, buflen);
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_tnrhdb2ent;
+ }
+ for (i = 0; i < result->entry->attr_count; i++) {
+ attrptr = getattr(result, i);
+ if (attrptr == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_tnrhdb2ent;
+ }
+ if (strcasecmp(attrptr->attrname, _TNRHDB_ADDR) == 0) {
+ len = strlen(attrptr->attrvalue[0]);
+ if (len < 1 || (attrptr->attrvalue[0] == '\0')) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_tnrhdb2ent;
+ }
+ rhstrp->address = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_tnrhdb2ent;
+ }
+ (void) strcpy(rhstrp->address, attrptr->attrvalue[0]);
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _TNRHDB_TNAME) == 0) {
+ len = strlen(attrptr->attrvalue[0]);
+ if (len < 1 || (attrptr->attrvalue[0] == '\0')) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_tnrhdb2ent;
+ }
+ rhstrp->template = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_tnrhdb2ent;
+ }
+ (void) strcpy(rhstrp->template, attrptr->attrvalue[0]);
+ continue;
+ }
+ }
+ nss_result = NSS_STR_PARSE_SUCCESS;
+
+#ifdef DEBUG
+ (void) printf("\n[tsol_getrhent.c: _nss_ldap_tnrhdb2ent]\n");
+ (void) printf(" address: [%s]\n",
+ rhstrp->address ? rhstrp->address : "NULL");
+ (void) printf("template: [%s]\n",
+ rhstrp->template ? rhstrp->template : "NULL");
+#endif /* DEBUG */
+
+result_tnrhdb2ent:
+ (void) __ns_ldap_freeResult(&be->result);
+ return (nss_result);
+}
+
+
+static nss_status_t
+getbyaddr(ldap_backend_ptr be, void *a)
+{
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ struct in_addr addr;
+ char buf[18];
+ extern char *inet_ntoa_r();
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[tsol_getrhent.c: getbyaddr]\n");
+#endif /* DEBUG */
+
+ (void) memcpy(&addr, argp->key.hostaddr.addr, sizeof (addr));
+ (void) inet_ntoa_r(addr, buf);
+
+ if (snprintf(searchfilter, sizeof (searchfilter), _F_GETTNDBBYADDR,
+ buf) < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ if (snprintf(userdata, sizeof (userdata), _F_GETTNDBBYADDR_SSD,
+ buf) < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return (_nss_ldap_lookup(be, argp, _TNRHDB, searchfilter, NULL,
+ _merge_SSD_filter, userdata));
+}
+
+
+static ldap_backend_op_t tnrhdb_ops[] = {
+ _nss_ldap_destr,
+ _nss_ldap_endent,
+ _nss_ldap_setent,
+ _nss_ldap_getent,
+ getbyaddr
+};
+
+
+/* ARGSUSED */
+nss_backend_t *
+_nss_ldap_tnrhdb_constr(const char *dummy1,
+ const char *dummy2,
+ const char *dummy3,
+ const char *dummy4,
+ const char *dummy5)
+{
+#ifdef DEBUG
+ (void) fprintf(stdout,
+ "\n[tsol_getrhent.c: _nss_ldap_tnrhdb_constr]\n");
+#endif
+ return ((nss_backend_t *)_nss_ldap_constr(tnrhdb_ops,
+ sizeof (tnrhdb_ops)/sizeof (tnrhdb_ops[0]), _TNRHDB,
+ tnrhdb_attrs, _nss_ldap_tnrhdb2ent));
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/nsswitch/ldap/common/tsol_gettpent.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,182 @@
+/*
+ * 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 "ldap_common.h"
+#include <sys/tsol/tndb.h>
+
+/* tnrhtp attributes filters */
+#define _TNRHTP_NAME "ipTnetTemplateName"
+#define _TNRHTP_ATTRS "SolarisAttrKeyValue"
+#define _F_GETTNTPBYNAME "(&(objectClass=ipTnetTemplate)"\
+ "(ipTnetTemplateName=%s))"
+#define _F_GETTNTPBYNAME_SSD "(&(%%s)(ipTnetTemplateName=%s))"
+
+static const char *tnrhtp_attrs[] = {
+ _TNRHTP_NAME,
+ _TNRHTP_ATTRS,
+ NULL
+};
+
+static int
+_nss_ldap_tnrhtp2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i, nss_result;
+ int len = 0;
+ int buflen = 0;
+ char *buffer = NULL;
+ char *ceiling = NULL;
+ ns_ldap_attr_t *attrptr;
+ ns_ldap_result_t *result = be->result;
+ tsol_tpstr_t *tpstrp;
+
+ buffer = argp->buf.buffer;
+ buflen = argp->buf.buflen;
+ if (argp->buf.result == NULL) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_tnrhtp2ent;
+ }
+ tpstrp = (tsol_tpstr_t *)(argp->buf.result);
+ tpstrp->template = tpstrp->attrs = NULL;
+ ceiling = buffer + buflen;
+ (void) memset(argp->buf.buffer, 0, buflen);
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_tnrhtp2ent;
+ }
+ for (i = 0; i < result->entry->attr_count; i++) {
+ attrptr = getattr(result, i);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_tnrhtp2ent;
+ }
+#ifdef DEBUG
+ (void) fprintf(stdout,
+ "\n[tsol_gettpent.c: _nss_ldap_tnrhtp2ent %d]\n", i);
+ (void) fprintf(stdout, " entry value count %d: %s:%s\n",
+ attrptr->value_count,
+ attrptr->attrname ? attrptr->attrname : "NULL",
+ attrptr->attrvalue[0] ? attrptr->attrvalue[0] : "NULL");
+#endif /* DEBUG */
+ if (strcasecmp(attrptr->attrname, _TNRHTP_NAME) == 0) {
+ len = strlen(attrptr->attrvalue[0]);
+ if (len < 1 || (attrptr->attrvalue[0] == '\0')) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_tnrhtp2ent;
+ }
+ tpstrp->template = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_tnrhtp2ent;
+ }
+ (void) strcpy(tpstrp->template, attrptr->attrvalue[0]);
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _TNRHTP_ATTRS) == 0) {
+ len = strlen(attrptr->attrvalue[0]);
+ if (len < 1 || (attrptr->attrvalue[0] == '\0')) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_tnrhtp2ent;
+ }
+ tpstrp->attrs = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_tnrhtp2ent;
+ }
+ (void) strcpy(tpstrp->attrs, attrptr->attrvalue[0]);
+ continue;
+ }
+ }
+ if (tpstrp->attrs == NULL)
+ nss_result = NSS_STR_PARSE_PARSE;
+ else
+ nss_result = NSS_STR_PARSE_SUCCESS;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[tsol_gettpent.c: _nss_ldap_tnrhtp2ent]\n");
+ (void) fprintf(stdout, " template: [%s]\n",
+ tpstrp->template ? tpstrp->template : "NULL");
+ (void) fprintf(stdout, " attrs: [%s]\n",
+ tpstrp->attrs ? tpstrp->attrs : "NULL");
+#endif /* DEBUG */
+
+result_tnrhtp2ent:
+ (void) __ns_ldap_freeResult(&be->result);
+ return (nss_result);
+}
+
+
+static nss_status_t
+getbyname(ldap_backend_ptr be, void *a)
+{
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[tsol_gettpent.c: getbyname]\n");
+#endif /* DEBUG */
+
+ if (snprintf(searchfilter, SEARCHFILTERLEN, _F_GETTNTPBYNAME,
+ argp->key.name) < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ if (snprintf(userdata, sizeof (userdata), _F_GETTNTPBYNAME_SSD,
+ argp->key.name) < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return (_nss_ldap_lookup(be, argp, _TNRHTP, searchfilter, NULL,
+ _merge_SSD_filter, userdata));
+}
+
+
+static ldap_backend_op_t tnrhtp_ops[] = {
+ _nss_ldap_destr,
+ _nss_ldap_endent,
+ _nss_ldap_setent,
+ _nss_ldap_getent,
+ getbyname
+};
+
+
+nss_backend_t *
+_nss_ldap_tnrhtp_constr(const char *dummy1,
+ const char *dummy2,
+ const char *dummy3,
+ const char *dummy4,
+ const char *dummy5)
+{
+#ifdef DEBUG
+ (void) fprintf(stdout,
+ "\n[gettnrhtpattr.c: _nss_ldap_tnrhtp_constr]\n");
+#endif
+ return ((nss_backend_t *)_nss_ldap_constr(tnrhtp_ops,
+ sizeof (tnrhtp_ops)/sizeof (tnrhtp_ops[0]), _TNRHTP,
+ tnrhtp_attrs, _nss_ldap_tnrhtp2ent));
+}
--- a/usr/src/pkgdefs/SUNWarc/prototype_com Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/pkgdefs/SUNWarc/prototype_com Fri Mar 24 12:29:20 2006 -0800
@@ -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"
@@ -182,6 +183,8 @@
f none usr/lib/llib-lssasnmp.ln 644 root bin
s none usr/lib/llib-lsysevent=../../lib/llib-lsysevent
s none usr/lib/llib-lsysevent.ln=../../lib/llib-lsysevent.ln
+s none usr/lib/llib-ltsnet.ln=../../lib/llib-ltsnet.ln
+s none usr/lib/llib-ltsol.ln=../../lib/llib-ltsol.ln
s none usr/lib/llib-lumem=../../lib/llib-lumem
s none usr/lib/llib-lumem.ln=../../lib/llib-lumem.ln
s none usr/lib/llib-luuid=../../lib/llib-luuid
--- a/usr/src/pkgdefs/SUNWarc/prototype_i386 Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/pkgdefs/SUNWarc/prototype_i386 Fri Mar 24 12:29:20 2006 -0800
@@ -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"
@@ -137,6 +138,8 @@
s none usr/lib/amd64/llib-ltermlib.ln=../../../lib/amd64/llib-lcurses.ln
s none usr/lib/amd64/llib-lthread.ln=../../../lib/amd64/llib-lthread.ln
s none usr/lib/amd64/llib-lthread_db.ln=../../../lib/amd64/llib-lc_db.ln
+s none usr/lib/amd64/llib-ltsnet.ln=../../../lib/amd64/llib-ltsnet.ln
+s none usr/lib/amd64/llib-ltsol.ln=../../../lib/amd64/llib-ltsol.ln
s none usr/lib/amd64/llib-lumem.ln=../../../lib/amd64/llib-lumem.ln
s none usr/lib/amd64/llib-luuid.ln=../../../lib/amd64/llib-luuid.ln
f none usr/lib/amd64/llib-lvolmgt.ln 644 root bin
--- a/usr/src/pkgdefs/SUNWarc/prototype_sparc Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/pkgdefs/SUNWarc/prototype_sparc Fri Mar 24 12:29:20 2006 -0800
@@ -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"
@@ -132,6 +133,8 @@
s none usr/lib/sparcv9/llib-ltermlib.ln=../../../lib/sparcv9/llib-lcurses.ln
s none usr/lib/sparcv9/llib-lthread.ln=../../../lib/sparcv9/llib-lthread.ln
s none usr/lib/sparcv9/llib-lthread_db.ln=../../../lib/sparcv9/llib-lc_db.ln
+s none usr/lib/sparcv9/llib-ltsnet.ln=../../../lib/sparcv9/llib-ltsnet.ln
+s none usr/lib/sparcv9/llib-ltsol.ln=../../../lib/sparcv9/llib-ltsol.ln
s none usr/lib/sparcv9/llib-lumem.ln=../../../lib/sparcv9/llib-lumem.ln
s none usr/lib/sparcv9/llib-luuid.ln=../../../lib/sparcv9/llib-luuid.ln
f none usr/lib/sparcv9/llib-lvolmgt.ln 644 root bin
--- a/usr/src/pkgdefs/SUNWarcr/prototype_com Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/pkgdefs/SUNWarcr/prototype_com Fri Mar 24 12:29:20 2006 -0800
@@ -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"
@@ -121,6 +122,10 @@
s none lib/llib-ltermlib=./llib-lcurses
f none lib/llib-lthread 644 root bin
f none lib/llib-lthread.ln 644 root bin
+f none lib/llib-ltsnet 644 root bin
+f none lib/llib-ltsnet.ln 644 root bin
+f none lib/llib-ltsol 644 root bin
+f none lib/llib-ltsol.ln 644 root bin
f none lib/llib-lumem 0644 root bin
f none lib/llib-lumem.ln 0644 root bin
f none lib/llib-luuid 644 root bin
--- a/usr/src/pkgdefs/SUNWarcr/prototype_i386 Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/pkgdefs/SUNWarcr/prototype_i386 Fri Mar 24 12:29:20 2006 -0800
@@ -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"
@@ -90,6 +91,8 @@
s none lib/amd64/llib-ltermlib.ln=./llib-lcurses.ln
s none lib/amd64/llib-ltermlib=./llib-lcurses
f none lib/amd64/llib-lthread.ln 644 root bin
+f none lib/amd64/llib-ltsnet.ln 644 root bin
+f none lib/amd64/llib-ltsol.ln 644 root bin
f none lib/amd64/llib-lumem.ln 644 root bin
f none lib/amd64/llib-luuid.ln 644 root bin
f none lib/amd64/llib-luutil.ln 644 root bin
--- a/usr/src/pkgdefs/SUNWarcr/prototype_sparc Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/pkgdefs/SUNWarcr/prototype_sparc Fri Mar 24 12:29:20 2006 -0800
@@ -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"
@@ -90,6 +91,8 @@
s none lib/sparcv9/llib-ltermlib.ln=./llib-lcurses.ln
s none lib/sparcv9/llib-ltermlib=./llib-lcurses
f none lib/sparcv9/llib-lthread.ln 644 root bin
+f none lib/sparcv9/llib-ltsnet.ln 644 root bin
+f none lib/sparcv9/llib-ltsol.ln 644 root bin
f none lib/sparcv9/llib-lumem.ln 0644 root bin
f none lib/sparcv9/llib-luuid.ln 644 root bin
f none lib/sparcv9/llib-lxnet.ln 644 root bin
--- a/usr/src/pkgdefs/SUNWcsl/prototype_com Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/pkgdefs/SUNWcsl/prototype_com Fri Mar 24 12:29:20 2006 -0800
@@ -17,6 +17,8 @@
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
+
+
#
#
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
@@ -245,6 +247,10 @@
s none usr/lib/libthread.so.1=../../lib/libthread.so.1
s none usr/lib/libthread_db.so=../../lib/libc_db.so.1
s none usr/lib/libthread_db.so.1=../../lib/libc_db.so.1
+s none usr/lib/libtsnet.so.1=../../lib/libtsnet.so.1
+s none usr/lib/libtsnet.so=../../lib/libtsnet.so.1
+s none usr/lib/libtsol.so.2=../../lib/libtsol.so.2
+s none usr/lib/libtsol.so=../../lib/libtsol.so.2
s none usr/lib/libumem.so=../../lib/libumem.so.1
s none usr/lib/libumem.so.1=../../lib/libumem.so.1
s none usr/lib/libuuid.so=../../lib/libuuid.so.1
--- a/usr/src/pkgdefs/SUNWcsl/prototype_i386 Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/pkgdefs/SUNWcsl/prototype_i386 Fri Mar 24 12:29:20 2006 -0800
@@ -197,6 +197,10 @@
s none usr/lib/amd64/lib450.so=./lib450.so.1
s none usr/lib/amd64/libthread_db.so.1=../../../lib/amd64/libc_db.so.1
s none usr/lib/amd64/libthread_db.so=../../../lib/amd64/libc_db.so.1
+s none usr/lib/amd64/libtsnet.so.1=../../../lib/amd64/libtsnet.so.1
+s none usr/lib/amd64/libtsnet.so=../../../lib/amd64/libtsnet.so.1
+s none usr/lib/amd64/libtsol.so.2=../../../lib/amd64/libtsol.so.2
+s none usr/lib/amd64/libtsol.so=../../../lib/amd64/libtsol.so.2
s none usr/lib/amd64/libuuid.so.1=../../../lib/amd64/libuuid.so.1
s none usr/lib/amd64/libuuid.so=../../../lib/amd64/libuuid.so.1
f none usr/lib/amd64/libvt0.so.1 755 root bin
--- a/usr/src/pkgdefs/SUNWcsl/prototype_sparc Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/pkgdefs/SUNWcsl/prototype_sparc Fri Mar 24 12:29:20 2006 -0800
@@ -17,6 +17,8 @@
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
+
+
#
#
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
@@ -288,6 +290,10 @@
s none usr/lib/sparcv9/libtermlib.so.1=../../../lib/sparcv9/libcurses.so.1
s none usr/lib/sparcv9/libthread.so.1=../../../lib/sparcv9/libthread.so.1
s none usr/lib/sparcv9/libthread.so=../../../lib/sparcv9/libthread.so.1
+s none usr/lib/sparcv9/libtsnet.so.1=../../../lib/sparcv9/libtsnet.so.1
+s none usr/lib/sparcv9/libtsnet.so=../../../lib/sparcv9/libtsnet.so.1
+s none usr/lib/sparcv9/libtsol.so.2=../../../lib/sparcv9/libtsol.so.2
+s none usr/lib/sparcv9/libtsol.so=../../../lib/sparcv9/libtsol.so.2
s none usr/lib/sparcv9/libumem.so=../../../lib/sparcv9/libumem.so.1
s none usr/lib/sparcv9/libumem.so.1=../../../lib/sparcv9/libumem.so.1
s none usr/lib/sparcv9/libuutil.so.1=../../../lib/sparcv9/libuutil.so.1
--- a/usr/src/pkgdefs/SUNWcslr/prototype_com Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/pkgdefs/SUNWcslr/prototype_com Fri Mar 24 12:29:20 2006 -0800
@@ -17,6 +17,8 @@
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
+
+
#
#
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
@@ -144,6 +146,9 @@
s none lib/libthread.so=libthread.so.1
s none lib/libthread_db.so.1=libc_db.so.1
s none lib/libthread_db.so=libc_db.so.1
+f none lib/libtsnet.so.1 755 root bin
+f none lib/libtsol.so.2 755 root bin
+s none lib/libtsol.so=libtsol.so.2
s none lib/libw.so=libw.so.1
f none lib/libw.so.1 755 root bin
s none lib/libumem.so=libumem.so.1
--- a/usr/src/pkgdefs/SUNWcslr/prototype_i386 Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/pkgdefs/SUNWcslr/prototype_i386 Fri Mar 24 12:29:20 2006 -0800
@@ -17,6 +17,8 @@
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
+
+
#
#
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
@@ -140,6 +142,10 @@
f none lib/amd64/libthread.so.1 755 root bin
s none lib/amd64/libthread_db.so=libc_db.so.1
s none lib/amd64/libthread_db.so.1=libc_db.so.1
+s none lib/amd64/libtsnet.so=libtsnet.so.1
+f none lib/amd64/libtsnet.so.1 755 root bin
+s none lib/amd64/libtsol.so=libtsol.so.2
+f none lib/amd64/libtsol.so.2 755 root bin
s none lib/amd64/libumem.so=libumem.so.1
f none lib/amd64/libumem.so.1 755 root bin
s none lib/amd64/libuuid.so=libuuid.so.1
--- a/usr/src/pkgdefs/SUNWcslr/prototype_sparc Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/pkgdefs/SUNWcslr/prototype_sparc Fri Mar 24 12:29:20 2006 -0800
@@ -17,6 +17,8 @@
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
+
+
#
#
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
@@ -142,6 +144,10 @@
f none lib/sparcv9/libthread.so.1 755 root bin
s none lib/sparcv9/libthread_db.so=libc_db.so.1
s none lib/sparcv9/libthread_db.so.1=libc_db.so.1
+s none lib/sparcv9/libtsnet.so=libtsnet.so.1
+f none lib/sparcv9/libtsnet.so.1 755 root bin
+s none lib/sparcv9/libtsol.so=libtsol.so.2
+f none lib/sparcv9/libtsol.so.2 755 root bin
s none lib/sparcv9/libumem.so=libumem.so.1
f none lib/sparcv9/libumem.so.1 0755 root bin
s none lib/sparcv9/libuuid.so=libuuid.so.1
--- a/usr/src/pkgdefs/SUNWcsr/prototype_com Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/pkgdefs/SUNWcsr/prototype_com Fri Mar 24 12:29:20 2006 -0800
@@ -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"
@@ -272,10 +272,10 @@
f none etc/security/dev/st0 400 root bin
f none etc/security/dev/st1 400 root bin
d none etc/security/lib 755 root sys
-f none etc/security/lib/audio_clean 751 root sys
-f none etc/security/lib/fd_clean 751 root sys
-f none etc/security/lib/sr_clean 751 root sys
-f none etc/security/lib/st_clean 751 root sys
+f none etc/security/lib/audio_clean 555 root sys
+f none etc/security/lib/fd_clean 555 root sys
+f none etc/security/lib/sr_clean 555 root sys
+f none etc/security/lib/st_clean 555 root sys
e rbac etc/security/auth_attr 644 root sys
e rbac etc/security/exec_attr 644 root sys
e rbac etc/security/prof_attr 644 root sys
--- a/usr/src/pkgdefs/SUNWcsu/prototype_com Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/pkgdefs/SUNWcsu/prototype_com Fri Mar 24 12:29:20 2006 -0800
@@ -685,7 +685,7 @@
f none usr/sbin/6to4relay 555 root bin
f none usr/sbin/acctadm 555 root bin
l none usr/sbin/add_drv=../../usr/lib/isaexec
-f none usr/sbin/allocate 4755 root bin
+f none usr/sbin/allocate 4555 root bin
f none usr/sbin/arp 555 root bin
f none usr/sbin/audit 555 root bin
f none usr/sbin/auditconfig 555 root bin
@@ -699,7 +699,7 @@
f none usr/sbin/clear_locks 555 root bin
f none usr/sbin/cryptoadm 555 root bin
l none usr/sbin/deallocate=../../usr/sbin/allocate
-f none usr/sbin/dminfo 755 root bin
+f none usr/sbin/dminfo 555 root bin
s none usr/sbin/fdisk=../../sbin/fdisk
f none usr/sbin/ikeadm 555 root bin
f none usr/sbin/ikecert 555 root bin
@@ -708,8 +708,8 @@
f none usr/sbin/ipsecconf 555 root bin
f none usr/sbin/ipseckey 555 root bin
l none usr/sbin/list_devices=../../usr/sbin/allocate
-f none usr/sbin/mkdevalloc 755 root bin
-f none usr/sbin/mkdevmaps 755 root bin
+f none usr/sbin/mkdevalloc 555 root bin
+l none usr/sbin/mkdevmaps=../../usr/sbin/mkdevalloc
f none usr/sbin/praudit 555 root bin
l none usr/sbin/audlinks=./devfsadm
s none usr/sbin/autopush=../../sbin/autopush
@@ -1562,4 +1562,3 @@
d none usr/xpg4 755 root bin
d none usr/xpg4/bin 755 root bin
f none usr/xpg4/bin/sh 555 root bin
-
--- a/usr/src/pkgdefs/SUNWhea/prototype_com Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/pkgdefs/SUNWhea/prototype_com Fri Mar 24 12:29:20 2006 -0800
@@ -189,6 +189,7 @@
f none usr/include/libsysevent.h 644 root bin
f none usr/include/libsysevent_impl.h 644 root bin
f none usr/include/libsvm.h 644 root bin
+f none usr/include/libtsnet.h 644 root bin
f none usr/include/libw.h 644 root bin
f none usr/include/libzfs.h 644 root bin
f none usr/include/libzoneinfo.h 644 root bin
@@ -1110,6 +1111,12 @@
f none usr/include/sys/tpicommon.h 0644 root bin
f none usr/include/sys/trap.h 644 root bin
f none usr/include/sys/ts.h 644 root bin
+d none usr/include/sys/tsol 755 root bin
+f none usr/include/sys/tsol/label.h 644 root bin
+f none usr/include/sys/tsol/label_macro.h 644 root bin
+f none usr/include/sys/tsol/priv.h 644 root bin
+f none usr/include/sys/tsol/tndb.h 644 root bin
+f none usr/include/sys/tsol/tsyscall.h 644 root bin
f none usr/include/sys/tspriocntl.h 644 root bin
f none usr/include/sys/ttcompat.h 644 root bin
f none usr/include/sys/ttold.h 644 root bin
@@ -1173,6 +1180,8 @@
f none usr/include/thread_db.h 644 root bin
f none usr/include/time.h 644 root bin
f none usr/include/tiuser.h 644 root bin
+d none usr/include/tsol 755 root bin
+f none usr/include/tsol/label.h 644 root bin
f none usr/include/tzfile.h 644 root bin
f none usr/include/ucontext.h 644 root bin
f none usr/include/ucred.h 644 root bin
--- a/usr/src/pkgdefs/common_files/i.nsswitch Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/pkgdefs/common_files/i.nsswitch Fri Mar 24 12:29:20 2006 -0800
@@ -3,9 +3,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,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.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -302,6 +300,28 @@
sed -e '/^sendmailvars:/d' $dest > /tmp/d.$$
cp /tmp/d.$$ $dest
rm -f /tmp/d.$$
+
+ # If the file doesn't have Trusted Extensions networking
+ # database (TNdb) entries, add appropriate entries. Default
+ # to everything if we can't figure out what is appropriate.
+ for DB in tnrhtp tnrhdb
+ do
+ grep $DB: $dest > /dev/null 2>&1
+ if [ $? != 0 ]; then
+ ATTR="files ldap"
+ egrep '/etc/nsswitch\.(dns|files)' $dest >\
+ /dev/null 2>&1
+ if [ $? = 0 ] ; then
+ ATTR="files"
+ fi
+ grep '/etc/nsswitch.ldap' $dest >/dev/null \
+ 2>&1
+ if [ $? = 0 ] ; then
+ ATTR="files ldap"
+ fi
+ echo "${DB}: ${ATTR}" >> $dest
+ fi
+ done
fi
done
--- a/usr/src/pkgdefs/etc/exception_list_i386 Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/pkgdefs/etc/exception_list_i386 Fri Mar 24 12:29:20 2006 -0800
@@ -52,6 +52,7 @@
usr/include/priv_utils.h i386
usr/include/bsm/audit_door_infc.h i386
usr/include/bsm/audit_private.h i386
+usr/include/bsm/devalloc.h i386
usr/include/sys/ieeefp.h i386
usr/include/sys/winlockio.h i386
usr/include/security/pam_impl.h i386
@@ -782,3 +783,15 @@
#
usr/lib/libstanddisasm.so i386
usr/lib/amd64/libstanddisasm.so i386
+
+#
+# TSol: tsol doesn't ship lint source, and tsnet isn't for customers at all.
+lib/libtsnet.so i386
+lib/llib-ltsnet i386
+usr/lib/llib-ltsnet i386
+usr/lib/llib-ltsol i386
+lib/llib-ltsol i386
+
+#
+# nss interfaces shared between libnsl and other ON libraries.
+usr/include/nss.h i386
--- a/usr/src/pkgdefs/etc/exception_list_sparc Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/pkgdefs/etc/exception_list_sparc Fri Mar 24 12:29:20 2006 -0800
@@ -43,6 +43,7 @@
usr/include/priv_utils.h sparc
usr/include/bsm/audit_door_infc.h sparc
usr/include/bsm/audit_private.h sparc
+usr/include/bsm/devalloc.h sparc
usr/include/security/pam_impl.h sparc
usr/include/passwdutil.h sparc
#
@@ -847,3 +848,15 @@
# only used when building the KMDB disasm module.
#
usr/lib/sparcv9/libstanddisasm.so sparc
+
+#
+# TSol: tsol doesn't ship lint source, and tsnet isn't for customers at all.
+lib/libtsnet.so sparc
+lib/llib-ltsnet sparc
+usr/lib/llib-ltsnet sparc
+usr/lib/llib-ltsol sparc
+lib/llib-ltsol sparc
+
+#
+# nss interfaces shared between libnsl and other ON libraries.
+usr/include/nss.h sparc
--- a/usr/src/tools/abi/etc/exceptions Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/tools/abi/etc/exceptions Fri Mar 24 12:29:20 2006 -0800
@@ -1,13 +1,12 @@
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# 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.
@@ -366,6 +365,13 @@
4947729: RULE W3: usr/lib/pool/libjpool.so.1
4947729: RULE W3: usr/lib/pool/libjsyslog.so.1
4940032: RULE W3: usr/lib/print/psm-lpsched.so.1
+PSARC 2002/762: RULE W3: lib/libtsnet.so.1
+PSARC 2002/762: RULE W3: usr/lib/libtsol.so.2
+PSARC 2002/762: RULE W3: usr/lib/sparcv9/libtsol.so.2
+PSARC 2002/762: RULE W3: usr/lib/amd64/libtsol.so.2
+PSARC 2002/762: RULE W3: lib/libtsol.so.2
+PSARC 2002/762: RULE W3: lib/sparcv9/libtsol.so.2
+PSARC 2002/762: RULE W3: lib/amd64/libtsol.so.2
6289029: RULE W3: lib/libdlpi.so.1
#############################################
--- a/usr/src/uts/common/Makefile.files Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/Makefile.files Fri Mar 24 12:29:20 2006 -0800
@@ -77,6 +77,7 @@
bdev_dsort.o \
bio.o \
bitmap.o \
+ blabel.o \
callb.o \
callout.o \
chdir.o \
@@ -162,6 +163,7 @@
kmem.o \
ksyms_snapshot.o \
l_strplumb.o \
+ labelsys.o \
link.o \
list.o \
lockstat_subr.o \
@@ -297,6 +299,7 @@
times.o \
timers.o \
thread.o \
+ tlabel.o \
tnf_res.o \
turnstile.o \
tty_common.o \
@@ -426,7 +429,7 @@
sctp_param.o sctp_shutdown.o sctp_common.o \
sctp_timer.o sctp_heartbeat.o sctp_hash.o \
sctp_ioc.o sctp_bind.o sctp_notify.o sctp_asconf.o \
- sctp_addr.o
+ sctp_addr.o tn_ipopt.o tnet.o
IP_OBJS += igmp.o ip.o ip6.o ip6_asp.o ip6_if.o ip6_ire.o ip6_rts.o \
ip_cksum.o ip_if.o ip_ire.o ip_listutils.o ip_mroute.o \
--- a/usr/src/uts/common/Makefile.rules Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/Makefile.rules Fri Mar 24 12:29:20 2006 -0800
@@ -828,6 +828,10 @@
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
+$(OBJS_DIR)/%.o: $(COMMONBASE)/tsol/%.c
+ $(COMPILE.c) -o $@ $<
+ $(CTFCONVERT_O)
+
$(OBJS_DIR)/%.o: $(COMMONBASE)/util/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
@@ -1467,6 +1471,9 @@
$(LINTS_DIR)/%.ln: $(UTSBASE)/common/tnf/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
+$(LINTS_DIR)/%.ln: $(COMMONBASE)/tsol/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+
$(LINTS_DIR)/%.ln: $(COMMONBASE)/util/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
--- a/usr/src/uts/common/c2/audit.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/c2/audit.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -64,6 +63,7 @@
#include <sys/devpolicy.h>
#include <sys/crypto/ioctladmin.h>
#include <inet/kssl/kssl.h>
+#include <sys/tsol/label.h>
static void add_return_token(caddr_t *, unsigned int scid, int err, int rval);
@@ -300,6 +300,8 @@
return (0);
}
+ tad->tad_ctrl |= PAD_NOPATH; /* prevent possible reentry */
+
audit_pathbuild(pnp);
tad->tad_vn = vp;
@@ -348,6 +350,7 @@
if (tad->tad_ctrl & PAD_MLD)
tad->tad_ctrl |= PAD_PATHFND;
+ tad->tad_ctrl &= ~PAD_NOPATH; /* restore */
return (0);
}
@@ -703,6 +706,7 @@
tad->tad_ctrl |= PAD_NOAUDIT;
} else {
au_uwrite(au_to_attr(&attr));
+ audit_sec_attributes(&(u_ad), vp);
}
}
}
@@ -920,6 +924,10 @@
/* Add an optional group token */
AUDIT_SETGROUP(&(u_ad), cr, kctx);
+ /* Add slabel token */
+ if (is_system_labeled())
+ au_write(&(u_ad), au_to_label(CR_SL(cr)));
+
/* Add a return token (should use f argument) */
add_return_token((caddr_t *)&(u_ad), tad->tad_scid, 0, 0);
@@ -1124,6 +1132,7 @@
if (getattr_ret == 0) {
au_write((caddr_t *)&(ad), au_to_attr(&attr));
+ audit_sec_attributes((caddr_t *)&(ad), vp);
}
/* Add a subject token */
@@ -1132,6 +1141,10 @@
/* add an optional group token */
AUDIT_SETGROUP((caddr_t *)&(ad), cr, kctx);
+ /* add slabel token */
+ if (is_system_labeled())
+ au_write((caddr_t *)&(ad), au_to_label(CR_SL(cr)));
+
/* add a return token */
add_return_token((caddr_t *)&(ad), tad->tad_scid, 0, 0);
@@ -1325,6 +1338,10 @@
/* add an optional group token */
AUDIT_SETGROUP(&(u_ad), cr, kctx);
+ /* add slabel token */
+ if (is_system_labeled())
+ au_uwrite(au_to_label(CR_SL(cr)));
+
/* add a return token */
add_return_token((caddr_t *)&(u_ad), tad->tad_scid, 0, 0);
@@ -2158,6 +2175,10 @@
/* add an optional group token */
AUDIT_SETGROUP((caddr_t *)&(ad), cr, kctx);
+ /* add slabel token */
+ if (is_system_labeled())
+ au_write((caddr_t *)&ad, au_to_label(CR_SL(cr)));
+
switch (cmd) {
case CRYPTO_LOAD_DEV_DISABLED:
if (error == 0 && rv == CRYPTO_SUCCESS) {
@@ -2307,6 +2328,10 @@
/* add an optional group token */
AUDIT_SETGROUP((caddr_t *)&ad, cr, kctx);
+ /* Add slabel token */
+ if (is_system_labeled())
+ au_write(&(u_ad), au_to_label(CR_SL(cr)));
+
switch (cmd) {
case KSSL_ADD_ENTRY: {
char buf[32];
@@ -2349,3 +2374,35 @@
au_close(kctx, (caddr_t *)&ad, AU_OK, AUE_CONFIGKSSL, 0);
}
+
+/*
+ * ROUTINE: AUDIT_SEC_ATTRIBUTES
+ * PURPOSE: Add security attributes
+ * CALLBY: AUDIT_ATTRIBUTES
+ * AUDIT_CLOSEF
+ * AUS_CLOSE
+ * NOTE:
+ * TODO:
+ * QUESTION:
+ */
+
+void
+audit_sec_attributes(caddr_t *ad, struct vnode *vp)
+{
+ /* Dump the SL */
+ if (is_system_labeled()) {
+ ts_label_t *tsl;
+ bslabel_t *bsl;
+
+ tsl = getflabel(vp);
+ if (tsl == NULL)
+ return; /* nothing else to do */
+
+ bsl = label2bslabel(tsl);
+ if (bsl == NULL)
+ return; /* nothing else to do */
+ au_write(ad, au_to_label(bsl));
+ label_rele(tsl);
+ }
+
+} /* AUDIT_SEC_ATTRIBUTES */
--- a/usr/src/uts/common/c2/audit.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/c2/audit.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -271,12 +270,21 @@
#define AUDIT_WINDATA 0x0040 /* include interwindow moved data */
#define AUDIT_USER 0x0080 /* make audituser(2) un-privileged */
#define AUDIT_GROUP 0x0100 /* include group attribute with each record */
-#define AUDIT_TRAIL 0X0200 /* include trailer token */
+#define AUDIT_TRAIL 0x0200 /* include trailer token */
#define AUDIT_PATH 0x0400 /* allow multiple paths per event */
#define AUDIT_SCNT 0x0800 /* sleep user events but not kernel events */
#define AUDIT_PUBLIC 0x1000 /* audit even "public" files */
#define AUDIT_ZONENAME 0x2000 /* emit zonename token */
#define AUDIT_PERZONE 0x4000 /* auditd and audit queue for each zone */
+
+/*
+ * These next (WINDATA*) are used by TSOL. Although per-zone audit is not
+ * used with TSOL, these policies still make sense to be categorized as
+ * "local".
+ */
+#define AUDIT_WINDATA_DOWN 0x00010000 /* include downgraded data */
+#define AUDIT_WINDATA_UP 0x00020000 /* include upgraded data */
+
/*
* If AUDIT_GLOBAL changes, corresponding changes are required in
* audit_syscalls.c's setpolicy().
@@ -285,7 +293,8 @@
#define AUDIT_LOCAL (AUDIT_CNT | AUDIT_ARGV | AUDIT_ARGE |\
AUDIT_PASSWD | AUDIT_SEQ | AUDIT_WINDATA |\
AUDIT_USER | AUDIT_GROUP | AUDIT_TRAIL | AUDIT_PATH |\
- AUDIT_PUBLIC | AUDIT_SCNT | AUDIT_ZONENAME)
+ AUDIT_PUBLIC | AUDIT_SCNT | AUDIT_ZONENAME |\
+ AUDIT_WINDATA_DOWN | AUDIT_WINDATA_UP)
/*
* Kernel audit queue control parameters
@@ -580,6 +589,7 @@
void audit_devpolicy(int, const struct devplcysys *);
void audit_update_context(proc_t *, cred_t *);
void audit_kssl(int, void *, int);
+void audit_sec_attributes(caddr_t *, struct vnode *);
#endif
--- a/usr/src/uts/common/c2/audit_event.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/c2/audit_event.c Fri Mar 24 12:29:20 2006 -0800
@@ -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 @@
#include <sys/kmem.h>
#include <sys/file.h> /* for accept */
#include <sys/utssys.h> /* for fuser */
+#include <sys/tsol/label.h>
#include <c2/audit.h>
#include <c2/audit_kernel.h>
#include <c2/audit_kevents.h>
@@ -1432,6 +1432,10 @@
rgid = crgetrgid(cr);
au_uwrite(au_to_process(uid, gid, ruid, rgid, pid,
ainfo->ai_auid, ainfo->ai_asid, &ainfo->ai_termid));
+
+ if (is_system_labeled())
+ au_uwrite(au_to_label(CR_SL(cr)));
+
crfree(cr);
}
else
@@ -1865,7 +1869,6 @@
if ((vp = fp->f_vnode) != NULL) {
attr.va_mask = AT_ALL;
if (VOP_GETATTR(vp, &attr, 0, CRED()) == 0) {
- au_uwrite(au_to_attr(&attr));
/*
* When write was not used and the file can be
* considered public, skip the audit.
@@ -1879,6 +1882,8 @@
releasef(fd);
return;
}
+ au_uwrite(au_to_attr(&attr));
+ audit_sec_attributes(&(u_ad), vp);
}
}
}
--- a/usr/src/uts/common/c2/audit_kevents.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/c2/audit_kevents.h Fri Mar 24 12:29:20 2006 -0800
@@ -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,7 @@
*
* 0 Reserved as an invalid event number.
* 1 - 511 Allocated for Solaris kernel
- * 512 - 1023 Allocated for Trusted Solaris kernel
+ * 512 - 1023 Allocated for Trusted Solaris/Trusted Extensions kernel
* 1024 - 2047 (reserved but not allocated)
* 2048 - 32767 Reserved for the Solaris TCB application.
* 32768 - 65535 Available for other Trusted applications.
@@ -165,11 +164,9 @@
#define AUE_ASYNC_DAEMON_EXIT 114 /* =no async_daemon(2) exited */
#define AUE_NFSSVC_EXIT 115 /* =no nfssvc(2) exited */
/*
- * 116 - 127 are available for future growth (old SunOS_CMW events
+ * 116 - 129 are available for future growth (old SunOS_CMW events
* that had no libbsm or praudit support or references)
*/
-#define AUE_WRITEL 128 /* =no writel(2) */
-#define AUE_WRITEVL 129 /* =no writevl(2) */
#define AUE_GETAUID 130 /* =aa getauid(2) */
#define AUE_SETAUID 131 /* =aa setauid(2) */
#define AUE_GETAUDIT 132 /* =aa getaudit(2) */
@@ -219,10 +216,10 @@
#define AUE_MSGSNDL 176 /* =no msgsndl(2) */
#define AUE_SEMGETL 177 /* =no semgetl(2) */
#define AUE_SHMGETL 178 /* =no shmgetl(2) */
-#define AUE_GETMLDADORN 179 /* =no getmldadorn(2) */
-#define AUE_GETSLDNAME 180 /* =no getsldname(2) */
-#define AUE_MLDLSTAT 181 /* =no mldlstat(2) */
-#define AUE_MLDSTAT 182 /* =no mldstat(2) */
+/* 179 OBSOLETE */
+/* 180 OBSOLETE */
+/* 181 OBSOLETE */
+/* 182 OBSOLETE */
#define AUE_SOCKET 183 /* =nt socket(2) */
#define AUE_SENDTO 184 /* =nt sendto(2) */
#define AUE_PIPE 185 /* =no pipe(2) */
@@ -336,12 +333,17 @@
#define AUE_CONFIGKSSL 293 /* =as kernel SSL */
/*
+ * Trusted Solaris/Trusted Extensions kernel audit events
+ * 512 - 1023 allocated for Trusted Solaris/Trusted Extensions
+ */
+
+/*
* Maximum number of kernel events in the event to class table
* leave a couple extra ones just incase somebody wants to load a new
* driver with build in auditing
*/
-#define MAX_KEVENTS 512
+#define MAX_KEVENTS 580
#ifdef __cplusplus
}
--- a/usr/src/uts/common/c2/audit_record.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/c2/audit_record.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -37,9 +36,7 @@
#include <sys/socket.h>
#include <sys/acl.h>
-#if defined(TSOL) && defined(_KERNEL)
#include <sys/tsol/label.h>
-#endif /* TSOL && _KERNEL */
#ifdef __cplusplus
extern "C" {
@@ -303,15 +300,7 @@
token_t *au_to_sock_inet(struct sockaddr_in *);
token_t *au_to_exec_args(const char *, ssize_t);
token_t *au_to_exec_env(const char *, ssize_t);
-
-#ifdef TSOL
-token_t *au_to_clearance(bclear_t *);
-token_t *au_to_host(void);
-token_t *au_to_ilabel(bilabel_t *);
-token_t *au_to_priv(priv_t, int);
-token_t *au_to_privilege(priv_set_t *, char);
-token_t *au_to_slabel(bslabel_t *);
-#endif /* TSOL */
+token_t *au_to_label(bslabel_t *);
token_t *au_to_privset(const char *, const priv_set_t *, char, int);
void au_uwrite();
@@ -735,6 +724,7 @@
extern token_t *au_to_ipc_perm(struct ipc_perm *);
extern token_t *au_to_iport(ushort_t);
extern token_t *au_to_me(void);
+extern token_t *au_to_mylabel(void);
extern token_t *au_to_opaque(char *, short);
extern token_t *au_to_path(char *);
extern token_t *au_to_privset(const char *, const priv_set_t *);
@@ -745,6 +735,7 @@
extern token_t *au_to_return32(char, uint32_t);
extern token_t *au_to_return64(char, uint64_t);
extern token_t *au_to_seq(int);
+extern token_t *au_to_label(bslabel_t *);
extern token_t *au_to_socket(struct oldsocket *);
extern token_t *au_to_socket_ex(short, short,
struct sockaddr *, struct sockaddr *);
--- a/usr/src/uts/common/c2/audit_start.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/c2/audit_start.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -44,6 +43,7 @@
#include <sys/debug.h>
#include <sys/cred_impl.h>
#include <sys/zone.h>
+#include <sys/tsol/label.h>
#include <c2/audit.h>
#include <c2/audit_kernel.h>
#include <c2/audit_kevents.h>
@@ -428,6 +428,10 @@
/* Add an optional group token */
AUDIT_SETGROUP(&(u_ad), cr, kctx);
+ /* Add token for process SL */
+ if (is_system_labeled())
+ au_write(&(u_ad), au_to_label(CR_SL(cr)));
+
if (tad->tad_evmod & PAD_SPRIVUSE)
au_write(&(u_ad),
au_to_privset("", &tad->tad_sprivs,
--- a/usr/src/uts/common/c2/audit_token.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/c2/audit_token.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -54,6 +53,7 @@
#include <sys/vfs.h> /* for sonode */
#include <sys/socketvar.h> /* for sonode */
#include <sys/zone.h>
+#include <sys/tsol/label.h>
/*
* These are the control tokens
@@ -928,33 +928,6 @@
return (m);
}
-#ifdef NOTYET
-/*
- * au_to_label
- * returns:
- * pointer to au_membuf chain containing a label token.
- */
-token_t *
-au_to_label(bilabel_t *label)
-{
- token_t *m; /* local au_membuf */
- adr_t adr; /* adr memory stream header */
- char data_header = AUT_LABEL; /* header for this token */
- short bs = sizeof (bilabel_t);
-
- m = au_getclr();
-
- adr_start(&adr, memtod(m, char *));
- adr_char(&adr, &data_header, 1);
- adr_short(&adr, &bs, 1);
- adr_char(&adr, (char *)label, bs);
-
- m->len = adr_count(&adr);
-
- return (m);
-}
-#endif /* NOTYET */
-
token_t *
au_to_groups(const gid_t *crgroups, uint_t crngroups)
{
@@ -1144,3 +1117,25 @@
return (token);
}
+
+/*
+ * au_to_label
+ * returns:
+ * pointer to au_membuf chain containing a sensitivity label token.
+ */
+token_t *
+au_to_label(bslabel_t *label)
+{
+ token_t *m; /* local au_membuf */
+ adr_t adr; /* adr memory stream header */
+ char data_header = AUT_LABEL; /* header for this token */
+
+ m = au_getclr();
+
+ adr_start(&adr, memtod(m, char *));
+ adr_char(&adr, &data_header, 1);
+ adr_char(&adr, (char *)label, sizeof (bslabel_t));
+ m->len = adr_count(&adr);
+
+ return (m);
+}
--- a/usr/src/uts/common/disp/thread.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/disp/thread.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
@@ -67,6 +66,8 @@
#include <sys/rctl.h>
#include <sys/pool.h>
#include <sys/zone.h>
+#include <sys/tsol/label.h>
+#include <sys/tsol/tndb.h>
#include <sys/cpc_impl.h>
#include <sys/sdt.h>
#include <sys/reboot.h>
@@ -178,12 +179,14 @@
sizeof (turnstile_t), 0,
turnstile_constructor, turnstile_destructor, NULL, NULL, NULL, 0);
+ label_init();
cred_init();
rctl_init();
project_init();
zone_init();
task_init();
+ tcache_init();
pool_init();
curthread->t_ts = kmem_cache_alloc(turnstile_cache, KM_SLEEP);
--- a/usr/src/uts/common/fs/autofs/auto_vfsops.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/fs/autofs/auto_vfsops.c Fri Mar 24 12:29:20 2006 -0800
@@ -39,18 +39,15 @@
#include <sys/tiuser.h>
#include <sys/cmn_err.h>
#include <sys/debug.h>
-#include <sys/mkdev.h>
#include <sys/systm.h>
#include <sys/sysmacros.h>
#include <sys/pathname.h>
#include <rpc/types.h>
#include <rpc/auth.h>
#include <rpc/clnt.h>
-#include <sys/dnlc.h>
#include <fs/fs_subr.h>
#include <sys/fs/autofs.h>
#include <rpcsvc/autofs_prot.h>
-#include <sys/note.h>
#include <sys/modctl.h>
#include <sys/mntent.h>
#include <sys/policy.h>
--- a/usr/src/uts/common/fs/doorfs/door_vnops.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/fs/doorfs/door_vnops.c Fri Mar 24 12:29:20 2006 -0800
@@ -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,7 +33,8 @@
#include <sys/debug.h>
#include <sys/cmn_err.h>
#include <fs/fs_subr.h>
-
+#include <sys/zone.h>
+#include <sys/tsol/label.h>
kmutex_t door_knob;
static int door_open(struct vnode **vpp, int flag, struct cred *cr);
@@ -71,6 +71,27 @@
static int
door_open(struct vnode **vpp, int flag, struct cred *cr)
{
+ /*
+ * MAC policy for doors. Restrict cross-zone open()s so that only
+ * door servers in the global zone can have clients from other zones.
+ * For other zones, client must be within the same zone as server.
+ */
+ if (is_system_labeled()) {
+ zone_t *server_zone, *client_zone;
+ door_node_t *dp = VTOD((*vpp));
+
+ mutex_enter(&door_knob);
+ if (DOOR_INVALID(dp)) {
+ mutex_exit(&door_knob);
+ return (0);
+ }
+ client_zone = curproc->p_zone;
+ server_zone = dp->door_target->p_zone;
+ mutex_exit(&door_knob);
+ if (server_zone != global_zone &&
+ server_zone != client_zone)
+ return (EACCES);
+ }
return (0);
}
--- a/usr/src/uts/common/fs/lofs/lofs_vfsops.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/fs/lofs/lofs_vfsops.c Fri Mar 24 12:29:20 2006 -0800
@@ -39,10 +39,12 @@
#include <sys/mount.h>
#include <sys/mntent.h>
#include <sys/mkdev.h>
+#include <sys/priv.h>
#include <sys/sysmacros.h>
#include <sys/systm.h>
#include <sys/cmn_err.h>
#include <sys/policy.h>
+#include <sys/tsol/label.h>
#include "fs/fs_subr.h"
/*
@@ -118,8 +120,9 @@
/*
* This is the module initialization routine.
*/
+
int
-_init()
+_init(void)
{
int status;
@@ -139,8 +142,9 @@
* Don't allow the lofs module to be unloaded for now.
* There is a memory leak if it gets unloaded.
*/
+
int
-_fini()
+_fini(void)
{
return (EBUSY);
}
@@ -203,7 +207,7 @@
mutex_enter(&vp->v_lock);
if (!(uap->flags & MS_OVERLAY) &&
- (vp->v_count != 1 || (vp->v_flag & VROOT))) {
+ (vp->v_count != 1 || (vp->v_flag & VROOT))) {
mutex_exit(&vp->v_lock);
return (EBUSY);
}
@@ -218,6 +222,95 @@
return (error);
/*
+ * Enforce MAC policy if needed.
+ *
+ * Loopback mounts must not allow writing up. The dominance test
+ * is intended to prevent a global zone caller from accidentally
+ * creating write-up conditions between two labeled zones.
+ * Local zones can't violate MAC on their own without help from
+ * the global zone because they can't name a pathname that
+ * they don't already have.
+ *
+ * The special case check for the NET_MAC_AWARE process flag is
+ * to support the case of the automounter in the global zone. We
+ * permit automounting of local zone directories such as home
+ * directories, into the global zone as required by setlabel,
+ * zonecopy, and saving of desktop sessions. Such mounts are
+ * trusted not to expose the contents of one zone's directories
+ * to another by leaking them through the global zone.
+ */
+ if (is_system_labeled() && crgetzoneid(cr) == GLOBAL_ZONEID) {
+ void *specname;
+ zone_t *from_zptr;
+ zone_t *to_zptr;
+
+ if (uap->flags & MS_SYSSPACE) {
+ specname = uap->spec;
+ } else {
+ specname = kmem_alloc(MAXPATHLEN, KM_SLEEP);
+ error = copyinstr(uap->spec, specname, MAXPATHLEN,
+ NULL);
+ if (error) {
+ kmem_free(specname, MAXPATHLEN);
+ return (error);
+ }
+ }
+ from_zptr = zone_find_by_path(specname);
+ if (!(uap->flags & MS_SYSSPACE))
+ kmem_free(specname, MAXPATHLEN);
+
+ to_zptr = zone_find_by_path(refstr_value(vfsp->vfs_mntpt));
+
+ /*
+ * Special case for zone devfs: the zone for /dev will
+ * incorrectly appear as the global zone since it's not
+ * under the zone rootpath. So for zone devfs check allow
+ * read-write mounts.
+ */
+
+ if (from_zptr != to_zptr && !is_zonedevfs) {
+ /*
+ * We know at this point that the labels aren't equal
+ * because the zone pointers aren't equal, and zones
+ * can't share a label.
+ *
+ * If the source is the global zone then making
+ * it available to a local zone must be done in
+ * read-only mode as the label will become admin_low.
+ *
+ * If it is a mount between local zones then if
+ * the current process is in the global zone and has
+ * the NET_MAC_AWARE flag, then regular read-write
+ * access is allowed. If it's in some other zone, but
+ * the label on the mount point dominates the original
+ * source, then allow the mount as read-only
+ * ("read-down").
+ */
+ if (from_zptr->zone_id == GLOBAL_ZONEID) {
+ /* make the mount read-only */
+ vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0);
+ } else { /* cross-zone mount */
+ if (to_zptr->zone_id == GLOBAL_ZONEID &&
+ /* LINTED: no consequent */
+ getpflags(NET_MAC_AWARE, cr) != 0) {
+ /* Allow the mount as read-write */
+ } else if (bldominates(
+ label2bslabel(to_zptr->zone_slabel),
+ label2bslabel(from_zptr->zone_slabel))) {
+ /* make the mount read-only */
+ vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0);
+ } else {
+ zone_rele(to_zptr);
+ zone_rele(from_zptr);
+ return (EACCES);
+ }
+ }
+ }
+ zone_rele(to_zptr);
+ zone_rele(from_zptr);
+ }
+
+ /*
* realrootvp may be an AUTOFS node, in which case we
* perform a VOP_ACCESS() to trigger the mount of the
* intended filesystem, so we loopback mount the intended
--- a/usr/src/uts/common/fs/nfs/nfs3_vfsops.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs3_vfsops.c Fri Mar 24 12:29:20 2006 -0800
@@ -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,6 +56,7 @@
#include <sys/class.h>
#include <sys/socket.h>
#include <sys/netconfig.h>
+#include <sys/tsol/tnet.h>
#include <rpc/types.h>
#include <rpc/auth.h>
@@ -222,6 +222,7 @@
int flags, addr_type;
char *p, *pf;
zone_t *zone = nfs_zone();
+ zone_t *mntzone = NULL;
if ((error = secpolicy_fs_mount(cr, mvp, vfsp)) != 0)
return (EPERM);
@@ -680,22 +681,34 @@
/*
* Determine the zone we're being mounted into.
*/
+ zone_hold(mntzone = zone); /* start with this assumption */
if (getzoneid() == GLOBAL_ZONEID) {
- zone_t *mntzone;
-
+ zone_rele(mntzone);
mntzone = zone_find_by_path(refstr_value(vfsp->vfs_mntpt));
ASSERT(mntzone != NULL);
- zone_rele(mntzone);
if (mntzone != zone) {
error = EBUSY;
goto errout;
}
}
+ if (is_system_labeled()) {
+ error = nfs_mount_label_policy(vfsp, &svp->sv_addr,
+ svp->sv_knconf, cr);
+
+ if (error > 0)
+ goto errout;
+
+ if (error == -1) {
+ /* change mount to read-only to prevent write-down */
+ vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0);
+ }
+ }
+
/*
* Stop the mount from going any further if the zone is going away.
*/
- if (zone_status_get(curproc->p_zone) >= ZONE_IS_SHUTTING_DOWN) {
+ if (zone_status_get(mntzone) >= ZONE_IS_SHUTTING_DOWN) {
error = EBUSY;
goto errout;
}
@@ -704,7 +717,7 @@
* Get root vnode.
*/
proceed:
- error = nfs3rootvp(&rtvp, vfsp, svp_head, flags, cr, zone);
+ error = nfs3rootvp(&rtvp, vfsp, svp_head, flags, cr, mntzone);
if (error)
goto errout;
@@ -745,6 +758,9 @@
if (rtvp != NULL)
VN_RELE(rtvp);
+ if (mntzone != NULL)
+ zone_rele(mntzone);
+
return (error);
}
--- a/usr/src/uts/common/fs/nfs/nfs4_srv.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -54,6 +53,7 @@
#include <sys/atomic.h>
#include <sys/policy.h>
#include <sys/fem.h>
+#include <sys/sdt.h>
#include <rpc/types.h>
#include <rpc/auth.h>
@@ -72,6 +72,9 @@
#include <inet/ip.h>
#include <inet/ip6.h>
+#include <sys/tsol/label.h>
+#include <sys/tsol/tndb.h>
+
#define RFS4_MAXLOCK_TRIES 4 /* Try to get the lock this many times */
static int rfs4_maxlock_tries = RFS4_MAXLOCK_TRIES;
#define RFS4_LOCK_DELAY 10 /* Milliseconds */
@@ -135,6 +138,12 @@
#define DIRENT64_TO_DIRCOUNT(dp) \
(3 * BYTES_PER_XDR_UNIT + DIRENT64_NAMELEN((dp)->d_reclen))
+/*
+ * types of label comparison
+ */
+#define EQUALITY_CHECK 0
+#define DOMINANCE_CHECK 1
+
time_t rfs4_start_time; /* Initialized in rfs4_srvrinit */
static sysid_t lockt_sysid; /* dummy sysid for all LOCKT calls */
@@ -1164,6 +1173,32 @@
resp->SECINFO4resok_val = NULL;
}
+/*
+ * do label check on client label and server's file lable.
+ */
+static boolean_t
+do_rfs4_label_check(bslabel_t *clabel, vnode_t *vp, int flag)
+{
+ bslabel_t *slabel;
+ ts_label_t *tslabel;
+ boolean_t result;
+
+ if ((tslabel = nfs4_getflabel(vp)) == NULL) {
+ return (B_FALSE);
+ }
+ slabel = label2bslabel(tslabel);
+ DTRACE_PROBE4(tx__rfs4__log__info__labelcheck, char *,
+ "comparing server's file label(1) with client label(2) (vp(3))",
+ bslabel_t *, slabel, bslabel_t *, clabel, vnode_t *, vp);
+
+ if (flag == EQUALITY_CHECK)
+ result = blequal(clabel, slabel);
+ else
+ result = bldominates(clabel, slabel);
+ label_rele(tslabel);
+ return (result);
+}
+
/* ARGSUSED */
static void
rfs4_op_access(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
@@ -1176,6 +1211,9 @@
struct vattr va;
int checkwriteperm;
cred_t *cr = cs->cr;
+ bslabel_t *clabel, *slabel;
+ ts_label_t *tslabel;
+ boolean_t admin_low_client;
#if 0 /* XXX allow access even if !cs->access. Eventually only pseudo fs */
if (cs->access == CS_ACCESS_DENIED) {
@@ -1217,26 +1255,51 @@
*cs->statusp = resp->status = puterrno4(error);
return;
}
-
resp->access = 0;
resp->supported = 0;
+ if (is_system_labeled()) {
+ ASSERT(req->rq_label != NULL);
+ clabel = req->rq_label;
+ DTRACE_PROBE2(tx__rfs4__log__info__opaccess__clabel, char *,
+ "got client label from request(1)",
+ struct svc_req *, req);
+ if (!blequal(&l_admin_low->tsl_label, clabel)) {
+ if ((tslabel = nfs4_getflabel(vp)) == NULL) {
+ *cs->statusp = resp->status = puterrno4(EACCES);
+ return;
+ }
+ slabel = label2bslabel(tslabel);
+ DTRACE_PROBE3(tx__rfs4__log__info__opaccess__slabel,
+ char *, "got server label(1) for vp(2)",
+ bslabel_t *, slabel, vnode_t *, vp);
+
+ admin_low_client = B_FALSE;
+ } else
+ admin_low_client = B_TRUE;
+ }
+
if (args->access & ACCESS4_READ) {
error = VOP_ACCESS(vp, VREAD, 0, cr);
- if (!error && !MANDLOCK(vp, va.va_mode))
+ if (!error && !MANDLOCK(vp, va.va_mode) &&
+ (!is_system_labeled() || admin_low_client ||
+ bldominates(clabel, slabel)))
resp->access |= ACCESS4_READ;
resp->supported |= ACCESS4_READ;
}
if ((args->access & ACCESS4_LOOKUP) && vp->v_type == VDIR) {
error = VOP_ACCESS(vp, VEXEC, 0, cr);
- if (!error)
+ if (!error && (!is_system_labeled() || admin_low_client ||
+ bldominates(clabel, slabel)))
resp->access |= ACCESS4_LOOKUP;
resp->supported |= ACCESS4_LOOKUP;
}
if (checkwriteperm &&
(args->access & (ACCESS4_MODIFY|ACCESS4_EXTEND))) {
error = VOP_ACCESS(vp, VWRITE, 0, cr);
- if (!error && !MANDLOCK(vp, va.va_mode))
+ if (!error && !MANDLOCK(vp, va.va_mode) &&
+ (!is_system_labeled() || admin_low_client ||
+ blequal(clabel, slabel)))
resp->access |=
(args->access & (ACCESS4_MODIFY|ACCESS4_EXTEND));
resp->supported |= (ACCESS4_MODIFY|ACCESS4_EXTEND);
@@ -1245,17 +1308,23 @@
if (checkwriteperm &&
(args->access & ACCESS4_DELETE) && vp->v_type == VDIR) {
error = VOP_ACCESS(vp, VWRITE, 0, cr);
- if (!error)
+ if (!error && (!is_system_labeled() || admin_low_client ||
+ blequal(clabel, slabel)))
resp->access |= ACCESS4_DELETE;
resp->supported |= ACCESS4_DELETE;
}
if (args->access & ACCESS4_EXECUTE && vp->v_type != VDIR) {
error = VOP_ACCESS(vp, VEXEC, 0, cr);
- if (!error && !MANDLOCK(vp, va.va_mode))
+ if (!error && !MANDLOCK(vp, va.va_mode) &&
+ (!is_system_labeled() || admin_low_client ||
+ bldominates(clabel, slabel)))
resp->access |= ACCESS4_EXECUTE;
resp->supported |= ACCESS4_EXECUTE;
}
+ if (is_system_labeled() && !admin_low_client)
+ label_rele(tslabel);
+
*cs->statusp = resp->status = NFS4_OK;
}
@@ -2541,8 +2610,62 @@
}
}
+ /*
+ * After various NFS checks, do a label check on the path
+ * component. The label on this path should either be the
+ * global zone's label or a zone's label. We are only
+ * interested in the zone's label because exported files
+ * in global zone is accessible (though read-only) to
+ * clients. The exportability/visibility check is already
+ * done before reaching this code.
+ */
+ if (is_system_labeled()) {
+ bslabel_t *clabel;
+
+ ASSERT(req->rq_label != NULL);
+ clabel = req->rq_label;
+ DTRACE_PROBE2(tx__rfs4__log__info__oplookup__clabel, char *,
+ "got client label from request(1)", struct svc_req *, req);
+
+ if (!blequal(&l_admin_low->tsl_label, clabel)) {
+ if (!do_rfs4_label_check(clabel, vp, DOMINANCE_CHECK)) {
+ error = EACCES;
+ goto err_out;
+ }
+ } else {
+ /*
+ * We grant access to admin_low label clients
+ * only if the client is trusted, i.e. also
+ * running Solaris Trusted Extension.
+ */
+ struct sockaddr *ca;
+ int addr_type;
+ void *ipaddr;
+ tsol_tpc_t *tp;
+
+ ca = (struct sockaddr *)svc_getrpccaller(
+ req->rq_xprt)->buf;
+ if (ca->sa_family == AF_INET) {
+ addr_type = IPV4_VERSION;
+ ipaddr = &((struct sockaddr_in *)ca)->sin_addr;
+ } else if (ca->sa_family == AF_INET6) {
+ addr_type = IPV6_VERSION;
+ ipaddr = &((struct sockaddr_in6 *)
+ ca)->sin6_addr;
+ }
+ tp = find_tpc(ipaddr, addr_type, B_FALSE);
+ if (tp == NULL || tp->tpc_tp.tp_doi !=
+ l_admin_low->tsl_doi || tp->tpc_tp.host_type !=
+ SUN_CIPSO) {
+ error = EACCES;
+ goto err_out;
+ }
+ }
+ }
+
error = makefh4(&cs->fh, vp, cs->exi);
+err_out:
if (error) {
if (is_newvp) {
VN_RELE(cs->vp);
@@ -3575,6 +3698,7 @@
uint_t len;
rfs4_file_t *fp;
int in_crit = 0;
+ bslabel_t *clabel;
/* CURRENT_FH: directory */
dvp = cs->vp;
@@ -3669,6 +3793,29 @@
}
}
+ /* check label before allowing removal */
+ if (is_system_labeled()) {
+ ASSERT(req->rq_label != NULL);
+ clabel = req->rq_label;
+ DTRACE_PROBE2(tx__rfs4__log__info__opremove__clabel, char *,
+ "got client label from request(1)",
+ struct svc_req *, req);
+ if (!blequal(&l_admin_low->tsl_label, clabel)) {
+ if (!do_rfs4_label_check(clabel, vp, EQUALITY_CHECK)) {
+ *cs->statusp = resp->status = NFS4ERR_ACCESS;
+ kmem_free(nm, len);
+ if (in_crit)
+ nbl_end_crit(vp);
+ VN_RELE(vp);
+ if (fp) {
+ rfs4_clear_dont_grant(fp);
+ rfs4_file_rele(fp);
+ }
+ return;
+ }
+ }
+ }
+
/* Get dir "before" change value */
bdva.va_mask = AT_CTIME|AT_SEQ;
error = VOP_GETATTR(dvp, &bdva, 0, cs->cr);
@@ -3809,6 +3956,7 @@
rfs4_file_t *fp, *sfp;
int in_crit_src, in_crit_targ;
int fp_rele_grant_hold, sfp_rele_grant_hold;
+ bslabel_t *clabel;
fp = sfp = NULL;
srcvp = targvp = NULL;
@@ -3900,6 +4048,22 @@
return;
}
+ /* check label of the target dir */
+ if (is_system_labeled()) {
+ ASSERT(req->rq_label != NULL);
+ clabel = req->rq_label;
+ DTRACE_PROBE2(tx__rfs4__log__info__oprename__clabel, char *,
+ "got client label from request(1)",
+ struct svc_req *, req);
+ if (!blequal(&l_admin_low->tsl_label, clabel)) {
+ if (!do_rfs4_label_check(clabel, ndvp,
+ EQUALITY_CHECK)) {
+ *cs->statusp = resp->status = NFS4ERR_ACCESS;
+ return;
+ }
+ }
+ }
+
/*
* Is the source a file and have a delegation?
* We don't need to acquire va_seq before these lookups, if
@@ -4712,6 +4876,7 @@
{
SETATTR4args *args = &argop->nfs_argop4_u.opsetattr;
SETATTR4res *resp = &resop->nfs_resop4_u.opsetattr;
+ bslabel_t *clabel;
if (cs->vp == NULL) {
*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
@@ -4734,6 +4899,22 @@
return;
}
+ /* check label before setting attributes */
+ if (is_system_labeled()) {
+ ASSERT(req->rq_label != NULL);
+ clabel = req->rq_label;
+ DTRACE_PROBE2(tx__rfs4__log__info__opsetattr__clabel, char *,
+ "got client label from request(1)",
+ struct svc_req *, req);
+ if (!blequal(&l_admin_low->tsl_label, clabel)) {
+ if (!do_rfs4_label_check(clabel, cs->vp,
+ EQUALITY_CHECK)) {
+ *cs->statusp = resp->status = NFS4ERR_ACCESS;
+ return;
+ }
+ }
+ }
+
*cs->statusp = resp->status =
do_rfs4_op_setattr(&resp->attrsset, &args->obj_attributes, cs,
&args->stateid);
@@ -5187,6 +5368,14 @@
crfree(cs.basecr);
if (cs.cr)
crfree(cs.cr);
+ /*
+ * done with this compound request, free the label
+ */
+
+ if (req->rq_label != NULL) {
+ kmem_free(req->rq_label, sizeof (bslabel_t));
+ req->rq_label = NULL;
+ }
}
/*
@@ -5577,6 +5766,7 @@
bool_t trunc;
caller_context_t ct;
component4 *component;
+ bslabel_t *clabel;
sarg.sbp = &sb;
@@ -5586,6 +5776,20 @@
if (rdonly4(cs->exi, dvp, req))
return (NFS4ERR_ROFS);
+ /* check the label of including directory */
+ if (is_system_labeled()) {
+ ASSERT(req->rq_label != NULL);
+ clabel = req->rq_label;
+ DTRACE_PROBE2(tx__rfs4__log__info__opremove__clabel, char *,
+ "got client label from request(1)",
+ struct svc_req *, req);
+ if (!blequal(&l_admin_low->tsl_label, clabel)) {
+ if (!do_rfs4_label_check(clabel, dvp, EQUALITY_CHECK)) {
+ return (NFS4ERR_ACCESS);
+ }
+ }
+ }
+
/*
* Get the last component of path name in nm. cs will reference
* the including directory on success.
--- a/usr/src/uts/common/fs/nfs/nfs4_subr.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs4_subr.c Fri Mar 24 12:29:20 2006 -0800
@@ -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,9 +38,10 @@
#include <sys/session.h>
#include <sys/thread.h>
#include <sys/dnlc.h>
-#include <sys/cred.h>
+#include <sys/cred_impl.h>
#include <sys/list.h>
#include <sys/sdt.h>
+#include <sys/policy.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
@@ -1208,17 +1208,19 @@
static int
nfs4_rfscall(mntinfo4_t *mi, rpcproc_t which, xdrproc_t xdrargs, caddr_t argsp,
- xdrproc_t xdrres, caddr_t resp, cred_t *cr, int *doqueue,
+ xdrproc_t xdrres, caddr_t resp, cred_t *icr, int *doqueue,
enum clnt_stat *rpc_statusp, int flags, struct nfs4_clnt *nfscl)
{
CLIENT *client;
struct chtab *ch;
+ cred_t *cr = icr;
struct rpc_err rpcerr;
enum clnt_stat status;
int error;
struct timeval wait;
int timeo; /* in units of hz */
bool_t tryagain, is_recov;
+ bool_t cred_cloned = FALSE;
k_sigset_t smask;
servinfo4_t *svp;
#ifdef DEBUG
@@ -1239,6 +1241,13 @@
}
mutex_exit(&mi->mi_lock);
+ /* For TSOL, use a new cred which has net_mac_aware flag */
+ if (!cred_cloned && is_system_labeled()) {
+ cred_cloned = TRUE;
+ cr = crdup(icr);
+ (void) setpflags(NET_MAC_AWARE, 1, cr);
+ }
+
/*
* clget() calls clnt_tli_kinit() which clears the xid, so we
* are guaranteed to reprocess the retry as a new request.
@@ -1281,6 +1290,8 @@
if (mi->mi_flags & MI4_SHUTDOWN) {
mutex_exit(&mi->mi_lock);
clfree4(client, ch, nfscl);
+ if (cred_cloned)
+ crfree(cr);
return (EIO);
}
mutex_exit(&mi->mi_lock);
@@ -1288,6 +1299,8 @@
if ((mi->mi_vfsp->vfs_flag & VFS_UNMOUNTED) &&
(!is_recov || !firstcall)) {
clfree4(client, ch, nfscl);
+ if (cred_cloned)
+ crfree(cr);
return (EIO);
}
@@ -1297,6 +1310,8 @@
!is_recov || !firstcall) {
mutex_exit(&mi->mi_lock);
clfree4(client, ch, nfscl);
+ if (cred_cloned)
+ crfree(cr);
return (EIO);
}
mutex_exit(&mi->mi_lock);
@@ -1391,6 +1406,8 @@
mi->mi_flags |= MI4_TIMEDOUT;
mutex_exit(&mi->mi_lock);
clfree4(client, ch, nfscl);
+ if (cred_cloned)
+ crfree(cr);
return (EIO);
}
@@ -1404,6 +1421,8 @@
if (mi->mi_vers == 4 && FAILOVER_MOUNT4(mi) &&
(error = try_failover(status)) != 0) {
clfree4(client, ch, nfscl);
+ if (cred_cloned)
+ crfree(cr);
*rpc_statusp = status;
return (error);
}
@@ -1526,6 +1545,8 @@
}
clfree4(client, ch, nfscl);
+ if (cred_cloned)
+ crfree(cr);
ASSERT(rpcerr.re_status == RPC_SUCCESS || rpcerr.re_errno != 0);
--- a/usr/src/uts/common/fs/nfs/nfs4_vfsops.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs4_vfsops.c Fri Mar 24 12:29:20 2006 -0800
@@ -57,6 +57,8 @@
#include <sys/netconfig.h>
#include <sys/dnlc.h>
#include <sys/list.h>
+#include <sys/mntent.h>
+#include <sys/tsol/label.h>
#include <rpc/types.h>
#include <rpc/auth.h>
@@ -332,6 +334,7 @@
char *userbufptr;
zone_t *zone = nfs_zone();
nfs4_error_t n4e;
+ zone_t *mntzone = NULL;
if (secpolicy_fs_mount(cr, mvp, vfsp) != 0)
return (EPERM);
@@ -725,22 +728,34 @@
/*
* Determine the zone we're being mounted into.
*/
+ zone_hold(mntzone = zone); /* start with this assumption */
if (getzoneid() == GLOBAL_ZONEID) {
- zone_t *mntzone;
-
+ zone_rele(mntzone);
mntzone = zone_find_by_path(refstr_value(vfsp->vfs_mntpt));
ASSERT(mntzone != NULL);
- zone_rele(mntzone);
if (mntzone != zone) {
error = EBUSY;
goto errout;
}
}
+ if (is_system_labeled()) {
+ error = nfs_mount_label_policy(vfsp, &svp->sv_addr,
+ svp->sv_knconf, cr);
+
+ if (error > 0)
+ goto errout;
+
+ if (error == -1) {
+ /* change mount to read-only to prevent write-down */
+ vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0);
+ }
+ }
+
/*
* Stop the mount from going any further if the zone is going away.
*/
- if (zone_status_get(curproc->p_zone) >= ZONE_IS_SHUTTING_DOWN) {
+ if (zone_status_get(mntzone) >= ZONE_IS_SHUTTING_DOWN) {
error = EBUSY;
goto errout;
}
@@ -749,7 +764,7 @@
* Get root vnode.
*/
proceed:
- error = nfs4rootvp(&rtvp, vfsp, svp_head, flags, cr, zone);
+ error = nfs4rootvp(&rtvp, vfsp, svp_head, flags, cr, mntzone);
if (error)
goto errout;
@@ -792,10 +807,12 @@
/*
* In this error path we need to sfh4_rele() before
* we free the mntinfo4_t as sfh4_rele() has a
- * dependancy on mi_fh_lock.
+ * dependency on mi_fh_lock.
*/
- if (rtvp != NULL)
+ if (rtvp != NULL) {
VN_RELE(rtvp);
+ rtvp = NULL;
+ }
if (mi->mi_io_kstats) {
kstat_delete(mi->mi_io_kstats);
mi->mi_io_kstats = NULL;
@@ -809,6 +826,8 @@
mi->mi_recov_ksp = NULL;
}
nfs_free_mi4(mi);
+ if (mntzone != NULL)
+ zone_rele(mntzone);
return (error);
}
sv4_free(svp_head);
@@ -817,6 +836,9 @@
if (rtvp != NULL)
VN_RELE(rtvp);
+ if (mntzone != NULL)
+ zone_rele(mntzone);
+
return (error);
}
--- a/usr/src/uts/common/fs/nfs/nfs_subr.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs_subr.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*
* Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T.
@@ -32,7 +31,7 @@
#include <sys/param.h>
#include <sys/types.h>
#include <sys/systm.h>
-#include <sys/cred.h>
+#include <sys/cred_impl.h>
#include <sys/proc.h>
#include <sys/user.h>
#include <sys/time.h>
@@ -61,6 +60,10 @@
#include <sys/callb.h>
#include <sys/atomic.h>
#include <sys/list.h>
+#include <sys/tsol/tnet.h>
+#include <sys/priv.h>
+
+#include <inet/ip6.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
@@ -279,6 +282,11 @@
extern void sec_clnt_freeinfo(struct sec_data *);
/*
+ * used in mount policy
+ */
+extern ts_label_t *getflabel_cipso(vfs_t *);
+
+/*
* EIO or EINTR are not recoverable errors.
*/
#define IS_RECOVERABLE_ERROR(error) !((error == EINTR) || (error == EIO))
@@ -914,17 +922,19 @@
static int
rfscall(mntinfo_t *mi, rpcproc_t which, xdrproc_t xdrargs, caddr_t argsp,
- xdrproc_t xdrres, caddr_t resp, cred_t *cr, int *douprintf,
+ xdrproc_t xdrres, caddr_t resp, cred_t *icr, int *douprintf,
enum clnt_stat *rpc_status, int flags, failinfo_t *fi)
{
CLIENT *client;
struct chtab *ch;
+ cred_t *cr = icr;
enum clnt_stat status;
struct rpc_err rpcerr;
struct timeval wait;
int timeo; /* in units of hz */
int my_rsize, my_wsize;
bool_t tryagain;
+ bool_t cred_cloned = FALSE;
k_sigset_t smask;
servinfo_t *svp;
struct nfs_clnt *nfscl;
@@ -1026,6 +1036,13 @@
}
}
+ /* For TSOL, use a new cred which has net_mac_aware flag */
+ if (!cred_cloned && is_system_labeled()) {
+ cred_cloned = TRUE;
+ cr = crdup(icr);
+ (void) setpflags(NET_MAC_AWARE, 1, cr);
+ }
+
/*
* clget() calls clnt_tli_kinit() which clears the xid, so we
* are guaranteed to reprocess the retry as a new request.
@@ -1252,6 +1269,8 @@
* the transfer size changed.
*/
clfree_impl(client, ch, nfscl);
+ if (cred_cloned)
+ crfree(cr);
return (ENFS_TRYAGAIN);
}
}
@@ -1348,6 +1367,8 @@
}
clfree_impl(client, ch, nfscl);
+ if (cred_cloned)
+ crfree(cr);
ASSERT(rpcerr.re_status == RPC_SUCCESS || rpcerr.re_errno != 0);
@@ -1449,11 +1470,13 @@
static int
aclcall(mntinfo_t *mi, rpcproc_t which, xdrproc_t xdrargs, caddr_t argsp,
- xdrproc_t xdrres, caddr_t resp, cred_t *cr, int *douprintf,
+ xdrproc_t xdrres, caddr_t resp, cred_t *icr, int *douprintf,
int flags, failinfo_t *fi)
{
CLIENT *client;
struct chtab *ch;
+ cred_t *cr = icr;
+ bool_t cred_cloned = FALSE;
enum clnt_stat status;
struct rpc_err rpcerr;
struct timeval wait;
@@ -1562,6 +1585,13 @@
}
}
+ /* For TSOL, use a new cred which has net_mac_aware flag */
+ if (!cred_cloned && is_system_labeled()) {
+ cred_cloned = TRUE;
+ cr = crdup(icr);
+ (void) setpflags(NET_MAC_AWARE, 1, cr);
+ }
+
/*
* acl_clget() calls clnt_tli_kinit() which clears the xid, so we
* are guaranteed to reprocess the retry as a new request.
@@ -1581,8 +1611,11 @@
goto failoverretry;
}
}
- if (rpcerr.re_errno != 0)
+ if (rpcerr.re_errno != 0) {
+ if (cred_cloned)
+ crfree(cr);
return (rpcerr.re_errno);
+ }
if (svp->sv_knconf->knc_semantics == NC_TPI_COTS_ORD ||
svp->sv_knconf->knc_semantics == NC_TPI_COTS) {
@@ -1823,6 +1856,8 @@
* the transfer size changed.
*/
clfree_impl(client, ch, nfscl);
+ if (cred_cloned)
+ crfree(cr);
return (ENFS_TRYAGAIN);
}
#endif
@@ -1921,6 +1956,8 @@
}
clfree_impl(client, ch, nfscl);
+ if (cred_cloned)
+ crfree(cr);
ASSERT(rpcerr.re_status == RPC_SUCCESS || rpcerr.re_errno != 0);
@@ -4972,3 +5009,111 @@
{
return (nfs_global_client_only != 0 ? GLOBAL_ZONEID : getzoneid());
}
+
+/*
+ * nfs_mount_label_policy:
+ * Determine whether the mount is allowed according to MAC check,
+ * by comparing (where appropriate) label of the remote server
+ * against the label of the zone being mounted into.
+ *
+ * Returns:
+ * 0 : access allowed
+ * -1 : read-only access allowed (i.e., read-down)
+ * >0 : error code, such as EACCES
+ */
+int
+nfs_mount_label_policy(vfs_t *vfsp, struct netbuf *addr,
+ struct knetconfig *knconf, cred_t *cr)
+{
+ int addr_type;
+ void *ipaddr;
+ bslabel_t *server_sl, *mntlabel;
+ zone_t *mntzone = NULL;
+ ts_label_t *zlabel;
+ tsol_tpc_t *tp;
+ ts_label_t *tsl = NULL;
+ int retv;
+
+ /*
+ * Get the zone's label. Each zone on a labeled system has a label.
+ */
+ mntzone = zone_find_by_any_path(refstr_value(vfsp->vfs_mntpt), B_FALSE);
+ zlabel = mntzone->zone_slabel;
+ ASSERT(zlabel != NULL);
+ label_hold(zlabel);
+
+ if (strcmp(knconf->knc_protofmly, NC_INET) == 0) {
+ addr_type = IPV4_VERSION;
+ ipaddr = &((struct sockaddr_in *)addr->buf)->sin_addr;
+ } else if (strcmp(knconf->knc_protofmly, NC_INET6) == 0) {
+ addr_type = IPV6_VERSION;
+ ipaddr = &((struct sockaddr_in6 *)addr->buf)->sin6_addr;
+ } else {
+ retv = 0;
+ goto out;
+ }
+
+ retv = EACCES; /* assume the worst */
+
+ /*
+ * Next, get the assigned label of the remote server.
+ */
+ tp = find_tpc(ipaddr, addr_type, B_FALSE);
+ if (tp == NULL)
+ goto out; /* error getting host entry */
+
+ if (tp->tpc_tp.tp_doi != zlabel->tsl_doi)
+ goto rel_tpc; /* invalid domain */
+ if ((tp->tpc_tp.host_type != SUN_CIPSO) &&
+ (tp->tpc_tp.host_type != UNLABELED))
+ goto rel_tpc; /* invalid hosttype */
+
+ if (tp->tpc_tp.host_type == SUN_CIPSO) {
+ tsl = getflabel_cipso(vfsp);
+ if (tsl == NULL)
+ goto rel_tpc; /* error getting server lbl */
+
+ server_sl = label2bslabel(tsl);
+ } else { /* UNLABELED */
+ server_sl = &tp->tpc_tp.tp_def_label;
+ }
+
+ mntlabel = label2bslabel(zlabel);
+
+ /*
+ * Now compare labels to complete the MAC check. If the labels
+ * are equal or if the requestor is in the global zone and has
+ * NET_MAC_AWARE, then allow read-write access. (Except for
+ * mounts into the global zone itself; restrict these to
+ * read-only.)
+ *
+ * If the requestor is in some other zone, but his label
+ * dominates the server, then allow read-down.
+ *
+ * Otherwise, access is denied.
+ */
+ if (blequal(mntlabel, server_sl) ||
+ (crgetzoneid(cr) == GLOBAL_ZONEID &&
+ getpflags(NET_MAC_AWARE, cr) != 0)) {
+ if ((mntzone == global_zone) ||
+ !blequal(mntlabel, server_sl))
+ retv = -1; /* read-only */
+ else
+ retv = 0; /* access OK */
+ } else if (bldominates(mntlabel, server_sl)) {
+ retv = -1; /* read-only */
+ } else {
+ retv = EACCES;
+ }
+
+ if (tsl != NULL)
+ label_rele(tsl);
+
+rel_tpc:
+ TPC_RELE(tp);
+out:
+ if (mntzone)
+ zone_rele(mntzone);
+ label_rele(zlabel);
+ return (retv);
+}
--- a/usr/src/uts/common/fs/nfs/nfs_vfsops.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs_vfsops.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*
* Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T.
@@ -55,6 +54,8 @@
#include <sys/class.h>
#include <sys/socket.h>
#include <sys/netconfig.h>
+#include <sys/mntent.h>
+#include <sys/tsol/label.h>
#include <rpc/types.h>
#include <rpc/auth.h>
@@ -223,6 +224,7 @@
int flags, addr_type;
char *p, *pf;
zone_t *zone = nfs_zone();
+ zone_t *mntzone = NULL;
if ((error = secpolicy_fs_mount(cr, mvp, vfsp)) != 0)
return (error);
@@ -670,22 +672,34 @@
/*
* Determine the zone we're being mounted into.
*/
+ zone_hold(mntzone = zone); /* start with this assumption */
if (getzoneid() == GLOBAL_ZONEID) {
- zone_t *mntzone;
-
+ zone_rele(mntzone);
mntzone = zone_find_by_path(refstr_value(vfsp->vfs_mntpt));
ASSERT(mntzone != NULL);
- zone_rele(mntzone);
if (mntzone != zone) {
error = EBUSY;
goto errout;
}
}
+ if (is_system_labeled()) {
+ error = nfs_mount_label_policy(vfsp, &svp->sv_addr,
+ svp->sv_knconf, cr);
+
+ if (error > 0)
+ goto errout;
+
+ if (error == -1) {
+ /* change mount to read-only to prevent write-down */
+ vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0);
+ }
+ }
+
/*
* Stop the mount from going any further if the zone is going away.
*/
- if (zone_status_get(curproc->p_zone) >= ZONE_IS_SHUTTING_DOWN) {
+ if (zone_status_get(mntzone) >= ZONE_IS_SHUTTING_DOWN) {
error = EBUSY;
goto errout;
}
@@ -694,7 +708,7 @@
* Get root vnode.
*/
proceed:
- error = nfsrootvp(&rtvp, vfsp, svp_head, flags, cr, zone);
+ error = nfsrootvp(&rtvp, vfsp, svp_head, flags, cr, mntzone);
if (error)
goto errout;
@@ -739,6 +753,9 @@
if (rtvp != NULL)
VN_RELE(rtvp);
+ if (mntzone != NULL)
+ zone_rele(mntzone);
+
return (error);
}
--- a/usr/src/uts/common/fs/sockfs/socksyscalls.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/fs/sockfs/socksyscalls.c Fri Mar 24 12:29:20 2006 -0800
@@ -41,9 +41,7 @@
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/file.h>
-#include <sys/open.h>
#include <sys/user.h>
-#include <sys/termios.h>
#include <sys/stream.h>
#include <sys/strsubr.h>
#include <sys/strsun.h>
@@ -56,15 +54,11 @@
#include <sys/socket.h>
#include <sys/socketvar.h>
-#include <netinet/in.h>
-#include <sys/un.h>
-#include <inet/nca/ncadoorhdr.h>
#include <sys/isa_defs.h>
#include <sys/inttypes.h>
#include <sys/systm.h>
#include <sys/cpuvar.h>
-#include <sys/atomic.h>
#include <sys/filio.h>
#include <sys/sendfile.h>
#include <sys/ddi.h>
--- a/usr/src/uts/common/inet/ip.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip.h Fri Mar 24 12:29:20 2006 -0800
@@ -51,6 +51,7 @@
#include <sys/avl.h>
#include <sys/vmem.h>
#include <sys/squeue.h>
+#include <net/route.h>
#include <sys/systm.h>
#include <sys/multidata.h>
@@ -124,6 +125,8 @@
#define IP_SIMPLE_HDR_LENGTH 20
#define IP_MAX_HDR_LENGTH 60
+#define IP_MAX_OPT_LENGTH (IP_MAX_HDR_LENGTH-IP_SIMPLE_HDR_LENGTH)
+
#define IP_MIN_MTU (IP_MAX_HDR_LENGTH + 8) /* 68 bytes */
/*
@@ -134,6 +137,8 @@
#define IP_SIMPLE_HDR_VERSION \
((IP_VERSION << 4) | IP_SIMPLE_HDR_LENGTH_IN_WORDS)
+#define UDPH_SIZE 8
+
/*
* Constants and type definitions to support IP IOCTL commands
*/
@@ -2074,6 +2079,104 @@
} ipndp_t;
/*
+ * The kernel stores security attributes of all gateways in a database made
+ * up of one or more tsol_gcdb_t elements. Each tsol_gcdb_t contains the
+ * security-related credentials of the gateway. More than one gateways may
+ * share entries in the database.
+ *
+ * The tsol_gc_t structure represents the gateway to credential association,
+ * and refers to an entry in the database. One or more tsol_gc_t entities are
+ * grouped together to form one or more tsol_gcgrp_t, each representing the
+ * list of security attributes specific to the gateway. A gateway may be
+ * associated with at most one credentials group.
+ */
+struct tsol_gcgrp_s;
+
+extern uchar_t ip6opt_ls; /* TX IPv6 enabler */
+
+/*
+ * Gateway security credential record.
+ */
+typedef struct tsol_gcdb_s {
+ uint_t gcdb_refcnt; /* reference count */
+ struct rtsa_s gcdb_attr; /* security attributes */
+#define gcdb_mask gcdb_attr.rtsa_mask
+#define gcdb_doi gcdb_attr.rtsa_doi
+#define gcdb_slrange gcdb_attr.rtsa_slrange
+} tsol_gcdb_t;
+
+/*
+ * Gateway to credential association.
+ */
+typedef struct tsol_gc_s {
+ uint_t gc_refcnt; /* reference count */
+ struct tsol_gcgrp_s *gc_grp; /* pointer to group */
+ struct tsol_gc_s *gc_prev; /* previous in list */
+ struct tsol_gc_s *gc_next; /* next in list */
+ tsol_gcdb_t *gc_db; /* pointer to actual credentials */
+} tsol_gc_t;
+
+/*
+ * Gateway credentials group address.
+ */
+typedef struct tsol_gcgrp_addr_s {
+ int ga_af; /* address family */
+ in6_addr_t ga_addr; /* IPv4 mapped or IPv6 address */
+} tsol_gcgrp_addr_t;
+
+/*
+ * Gateway credentials group.
+ */
+typedef struct tsol_gcgrp_s {
+ uint_t gcgrp_refcnt; /* reference count */
+ krwlock_t gcgrp_rwlock; /* lock to protect following */
+ uint_t gcgrp_count; /* number of credentials */
+ tsol_gc_t *gcgrp_head; /* first credential in list */
+ tsol_gc_t *gcgrp_tail; /* last credential in list */
+ tsol_gcgrp_addr_t gcgrp_addr; /* next-hop gateway address */
+} tsol_gcgrp_t;
+
+extern kmutex_t gcgrp_lock;
+
+#define GC_REFRELE(p) { \
+ ASSERT((p)->gc_grp != NULL); \
+ rw_enter(&(p)->gc_grp->gcgrp_rwlock, RW_WRITER); \
+ ASSERT((p)->gc_refcnt > 0); \
+ if (--((p)->gc_refcnt) == 0) \
+ gc_inactive(p); \
+ else \
+ rw_exit(&(p)->gc_grp->gcgrp_rwlock); \
+}
+
+#define GCGRP_REFHOLD(p) { \
+ mutex_enter(&gcgrp_lock); \
+ ++((p)->gcgrp_refcnt); \
+ ASSERT((p)->gcgrp_refcnt != 0); \
+ mutex_exit(&gcgrp_lock); \
+}
+
+#define GCGRP_REFRELE(p) { \
+ mutex_enter(&gcgrp_lock); \
+ ASSERT((p)->gcgrp_refcnt > 0); \
+ if (--((p)->gcgrp_refcnt) == 0) \
+ gcgrp_inactive(p); \
+ ASSERT(MUTEX_HELD(&gcgrp_lock)); \
+ mutex_exit(&gcgrp_lock); \
+}
+
+/*
+ * IRE gateway security attributes structure, pointed to by tsol_ire_gw_secattr
+ */
+struct tsol_tnrhc;
+
+typedef struct tsol_ire_gw_secattr_s {
+ kmutex_t igsa_lock; /* lock to protect following */
+ struct tsol_tnrhc *igsa_rhc; /* host entry for gateway */
+ tsol_gc_t *igsa_gc; /* for prefix IREs */
+ tsol_gcgrp_t *igsa_gcgrp; /* for cache IREs */
+} tsol_ire_gw_secattr_t;
+
+/*
* Following are the macros to increment/decrement the reference
* count of the IREs and IRBs (ire bucket).
*
@@ -2306,6 +2409,7 @@
clock_t ire_last_used_time; /* Last used time */
struct ire_s *ire_fastpath; /* Pointer to next ire in fastpath */
zoneid_t ire_zoneid; /* for local address discrimination */
+ tsol_ire_gw_secattr_t *ire_gw_secattr; /* gateway security attributes */
#ifdef IRE_DEBUG
th_trace_t *ire_trace[IP_TR_HASH_MAX];
boolean_t ire_trace_disable; /* True when alloc fails */
@@ -2433,6 +2537,8 @@
};
typedef struct ip6_pkt_s ip6_pkt_t;
+extern void ip6_pkt_free(ip6_pkt_t *); /* free storage inside ip6_pkt_t */
+
/*
* This structure is used to convey information from IP and the ULP.
* Currently used for the IP_RECVSLLA and IP_RECVIF options. The
@@ -2447,7 +2553,7 @@
} in_pktinfo_t;
/*
- * flags to tell UDP what IP is sending
+ * flags to tell UDP what IP is sending; in_pkt_flags
*/
#define IPF_RECVIF 0x01 /* inbound interface index */
#define IPF_RECVSLLA 0x02 /* source link layer address */
@@ -2832,6 +2938,7 @@
extern uint8_t ipoptp_next(ipoptp_t *);
extern uint8_t ipoptp_first(ipoptp_t *, ipha_t *);
+extern int ip_opt_get_user(const ipha_t *, uchar_t *);
extern ill_t *ip_grab_attach_ill(ill_t *, mblk_t *, int, boolean_t);
extern ire_t *conn_set_outgoing_ill(conn_t *, ire_t *, ill_t **);
extern int ipsec_req_from_conn(conn_t *, ipsec_req_t *, int);
@@ -2844,6 +2951,12 @@
extern void ip_ioctl_finish(queue_t *, mblk_t *, int, int, ipif_t *,
ipsq_t *);
+extern boolean_t ip_cmpbuf(const void *, uint_t, boolean_t, const void *,
+ uint_t);
+extern boolean_t ip_allocbuf(void **, uint_t *, boolean_t, const void *,
+ uint_t);
+extern void ip_savebuf(void **, uint_t *, boolean_t, const void *, uint_t);
+
extern boolean_t ipsq_pending_mp_cleanup(ill_t *, conn_t *);
extern void conn_ioctl_cleanup(conn_t *);
extern ill_t *conn_get_held_ill(conn_t *, ill_t **, int *);
@@ -2862,6 +2975,9 @@
uint_t);
extern mblk_t *ip_unbind(queue_t *, mblk_t *);
+extern void tnet_init(void);
+extern void tnet_fini(void);
+
/* Hooks for CGTP (multirt routes) filtering module */
#define CGTP_FILTER_REV_1 1
#define CGTP_FILTER_REV_2 2
@@ -3004,6 +3120,17 @@
};
/*
+ * This message is sent by an upper-layer protocol to tell IP that it knows all
+ * about labels and will construct them itself. IP takes the slow path and
+ * recomputes the label on every packet when this isn't true.
+ */
+#define IP_ULP_OUT_LABELED (('O' << 8) + 'L')
+typedef struct out_labeled_s {
+ uint32_t out_labeled_type; /* OUT_LABELED */
+ queue_t *out_qnext; /* intermediate detection */
+} out_labeled_t;
+
+/*
* IP squeues exports
*/
extern int ip_squeue_profile;
--- a/usr/src/uts/common/inet/ip/icmp.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip/icmp.c Fri Mar 24 12:29:20 2006 -0800
@@ -37,10 +37,12 @@
#include <sys/timod.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
+#include <sys/strsubr.h>
#include <sys/cmn_err.h>
#include <sys/debug.h>
#include <sys/kmem.h>
#include <sys/policy.h>
+#include <sys/priv.h>
#include <sys/zone.h>
#include <sys/time.h>
@@ -58,7 +60,6 @@
#include <inet/common.h>
#include <inet/ip.h>
#include <inet/ip6.h>
-#include <inet/ip_ire.h>
#include <inet/mi.h>
#include <inet/nd.h>
#include <inet/optcom.h>
@@ -72,6 +73,9 @@
#include <inet/ipsec_info.h>
#include <inet/ipclassifier.h>
+#include <sys/tsol/label.h>
+#include <sys/tsol/tnet.h>
+
#define ICMP6 "icmp6"
major_t ICMP6_MAJ;
@@ -133,8 +137,6 @@
static boolean_t icmp_param_register(icmpparam_t *icmppa, int cnt);
static int icmp_param_set(queue_t *q, mblk_t *mp, char *value,
caddr_t cp, cred_t *cr);
-static int icmp_pkt_set(uchar_t *invalp, uint_t inlen, boolean_t sticky,
- uchar_t **optbufp, uint_t *optlenp);
static void icmp_rput(queue_t *q, mblk_t *mp);
static void icmp_rput_bind_ack(queue_t *q, mblk_t *mp);
static int icmp_snmp_get(queue_t *q, mblk_t *mpctl);
@@ -614,6 +616,7 @@
linkb(mp1, mp);
linkb(mp1, mp2);
+ mblk_setcred(mp1, icmp->icmp_credp);
putnext(q, mp1);
}
@@ -623,6 +626,10 @@
icmp_t *icmp = (icmp_t *)q->q_ptr;
int i1;
+ /* tell IP that if we're not here, he can't trust labels */
+ if (is_system_labeled())
+ putnext(WR(q), icmp->icmp_delabel);
+
qprocsoff(q);
/* If there are any options associated with the stream, free them. */
@@ -639,28 +646,8 @@
icmp->icmp_sticky_hdrs = NULL;
icmp->icmp_sticky_hdrs_len = 0;
}
- if (icmp->icmp_sticky_ipp.ipp_fields & IPPF_HOPOPTS) {
- kmem_free(icmp->icmp_sticky_ipp.ipp_hopopts,
- icmp->icmp_sticky_ipp.ipp_hopoptslen);
- }
- if (icmp->icmp_sticky_ipp.ipp_fields & IPPF_RTDSTOPTS) {
- kmem_free(icmp->icmp_sticky_ipp.ipp_rtdstopts,
- icmp->icmp_sticky_ipp.ipp_rtdstoptslen);
- }
- if (icmp->icmp_sticky_ipp.ipp_fields & IPPF_RTHDR) {
- kmem_free(icmp->icmp_sticky_ipp.ipp_rthdr,
- icmp->icmp_sticky_ipp.ipp_rthdrlen);
- }
- if (icmp->icmp_sticky_ipp.ipp_fields & IPPF_DSTOPTS) {
- kmem_free(icmp->icmp_sticky_ipp.ipp_dstopts,
- icmp->icmp_sticky_ipp.ipp_dstoptslen);
- }
- if (icmp->icmp_sticky_ipp.ipp_fields & IPPF_PATHMTU) {
- kmem_free(icmp->icmp_sticky_ipp.ipp_pathmtu,
- icmp->icmp_sticky_ipp.ipp_pathmtulen);
- }
- icmp->icmp_sticky_ipp.ipp_fields &=
- ~(IPPF_HOPOPTS|IPPF_RTDSTOPTS|IPPF_RTHDR|IPPF_DSTOPTS);
+
+ ip6_pkt_free(&icmp->icmp_sticky_ipp);
crfree(icmp->icmp_credp);
@@ -1295,6 +1282,37 @@
return (mp);
}
+/* ARGSUSED */
+static void
+dummy_func(void *arg)
+{
+}
+
+static mblk_t *
+alloc_wait(queue_t *q, size_t len, int pri, int *errp)
+{
+ mblk_t *mp;
+ bufcall_id_t id;
+ int retv;
+
+ while ((mp = allocb(len, pri)) == NULL) {
+ id = qbufcall(q, len, pri, dummy_func, NULL);
+ if (id == 0) {
+ *errp = ENOMEM;
+ break;
+ }
+ retv = qwait_sig(q);
+ qunbufcall(q, id);
+ if (retv == 0) {
+ *errp = EINTR;
+ break;
+ }
+ }
+ if (mp != NULL)
+ mp->b_wptr += len;
+ return (mp);
+}
+
/*
* This is the open routine for icmp. It allocates a icmp_t structure for
* the stream and, on the first open of the module, creates an ND table.
@@ -1304,6 +1322,8 @@
{
int err;
icmp_t *icmp;
+ mblk_t *mp;
+ out_labeled_t *olp;
/* If the stream is already open, return immediately. */
if (q->q_ptr != NULL)
@@ -1326,7 +1346,7 @@
*/
err = mi_open_comm(&icmp_g_head, sizeof (icmp_t), q, devp,
flag, sflag, credp);
- if (err)
+ if (err != 0)
return (err);
/*
@@ -1345,6 +1365,13 @@
icmp->icmp_credp = credp;
crhold(credp);
+ /*
+ * If the caller has the process-wide flag set, then default to MAC
+ * exempt mode. This allows read-down to unlabeled hosts.
+ */
+ if (getpflags(NET_MAC_AWARE, credp) != 0)
+ icmp->icmp_mac_exempt = B_TRUE;
+
icmp->icmp_zoneid = getzoneid();
if (getmajor(*devp) == (major_t)ICMP6_MAJ) {
@@ -1386,19 +1413,43 @@
if (icmp->icmp_family == AF_INET6) {
/* Build initial header template for transmit */
- int error;
-
- error = icmp_build_hdrs(q, icmp);
- if (error != 0) {
- (void) icmp_close(q);
- return (error);
- }
+ err = icmp_build_hdrs(q, icmp);
+ if (err != 0)
+ goto open_error;
}
/* Set the Stream head write offset. */
(void) mi_set_sth_wroff(q, icmp->icmp_max_hdr_len + icmp_wroff_extra);
(void) mi_set_sth_hiwat(q, q->q_hiwat);
+ if (is_system_labeled()) {
+ /* notify IP that we know about labeling */
+ mp = alloc_wait(q, sizeof (*olp), BPRI_MED, &err);
+ if (mp == NULL)
+ goto open_error;
+ mp->b_datap->db_type = M_CTL;
+ olp = (out_labeled_t *)mp->b_rptr;
+ olp->out_labeled_type = IP_ULP_OUT_LABELED;
+ olp->out_qnext = WR(q)->q_next;
+ putnext(WR(q), mp);
+
+ /* save off a copy for closing */
+ mp = alloc_wait(q, sizeof (*olp), BPRI_MED, &err);
+ if (mp == NULL)
+ goto open_error;
+ mp->b_datap->db_type = M_CTL;
+ olp = (out_labeled_t *)mp->b_rptr;
+ olp->out_labeled_type = IP_ULP_OUT_LABELED;
+ olp->out_qnext = NULL;
+ icmp->icmp_delabel = mp;
+ }
+
return (0);
+
+open_error:
+ qprocsoff(q);
+ crfree(credp);
+ (void) mi_close_comm(&icmp_g_head, q);
+ return (err);
}
/*
@@ -1512,6 +1563,9 @@
case SO_TIMESTAMP:
*i1 = icmp->icmp_timestamp;
break;
+ case SO_MAC_EXEMPT:
+ *i1 = icmp->icmp_mac_exempt;
+ break;
/*
* Following three not meaningful for icmp
* Action is same as "default" to which we fallthrough
@@ -1711,8 +1765,17 @@
case IPV6_HOPOPTS:
if (!(ipp->ipp_fields & IPPF_HOPOPTS))
return (0);
- bcopy(ipp->ipp_hopopts, ptr, ipp->ipp_hopoptslen);
- return (ipp->ipp_hopoptslen);
+ if (ipp->ipp_hopoptslen <= icmp->icmp_label_len_v6)
+ return (0);
+ bcopy((char *)ipp->ipp_hopopts +
+ icmp->icmp_label_len_v6, ptr,
+ ipp->ipp_hopoptslen - icmp->icmp_label_len_v6);
+ if (icmp->icmp_label_len_v6 > 0) {
+ ptr[0] = ((char *)ipp->ipp_hopopts)[0];
+ ptr[1] = (ipp->ipp_hopoptslen -
+ icmp->icmp_label_len_v6 + 7) / 8 - 1;
+ }
+ return (ipp->ipp_hopoptslen - icmp->icmp_label_len_v6);
case IPV6_RTHDRDSTOPTS:
if (!(ipp->ipp_fields & IPPF_RTDSTOPTS))
return (0);
@@ -1966,6 +2029,13 @@
icmp->icmp_timestamp = onoff;
}
break;
+ case SO_MAC_EXEMPT:
+ if (secpolicy_net_mac_aware(cr) != 0 ||
+ icmp->icmp_state != TS_UNBND)
+ return (EACCES);
+ if (!checkonly)
+ icmp->icmp_mac_exempt = onoff;
+ break;
/*
* Following three not meaningful for icmp
* Action is same as "default" so we keep them
@@ -1991,27 +2061,21 @@
case IP_OPTIONS:
case T_IP_OPTIONS:
/* Save options for use by IP. */
- if (inlen & 0x3) {
+ if ((inlen & 0x3) ||
+ inlen + icmp->icmp_label_len > IP_MAX_OPT_LENGTH) {
*outlenp = 0;
return (EINVAL);
}
if (checkonly)
break;
- if (icmp->icmp_ip_snd_options) {
- mi_free((char *)icmp->icmp_ip_snd_options);
- icmp->icmp_ip_snd_options_len = 0;
- icmp->icmp_ip_snd_options = NULL;
+ if (!tsol_option_set(&icmp->icmp_ip_snd_options,
+ &icmp->icmp_ip_snd_options_len,
+ icmp->icmp_label_len, invalp, inlen)) {
+ *outlenp = 0;
+ return (ENOMEM);
}
- if (inlen) {
- icmp->icmp_ip_snd_options =
- (uchar_t *)mi_alloc(inlen, BPRI_HI);
- if (icmp->icmp_ip_snd_options) {
- bcopy(invalp,
- icmp->icmp_ip_snd_options, inlen);
- icmp->icmp_ip_snd_options_len = inlen;
- }
- }
+
icmp->icmp_max_hdr_len = IP_SIMPLE_HDR_LENGTH +
icmp->icmp_ip_snd_options_len;
(void) mi_set_sth_wroff(RD(q), icmp->icmp_max_hdr_len +
@@ -2417,22 +2481,16 @@
if (checkonly)
break;
- if (inlen == 0) {
- if (sticky &&
- (ipp->ipp_fields & IPPF_HOPOPTS) != 0) {
- kmem_free(ipp->ipp_hopopts,
- ipp->ipp_hopoptslen);
- ipp->ipp_hopopts = NULL;
- ipp->ipp_hopoptslen = 0;
- }
+ error = optcom_pkt_set(invalp, inlen, sticky,
+ (uchar_t **)&ipp->ipp_hopopts,
+ &ipp->ipp_hopoptslen,
+ sticky ? icmp->icmp_label_len_v6 : 0);
+ if (error != 0)
+ return (error);
+ if (ipp->ipp_hopoptslen == 0) {
ipp->ipp_fields &= ~IPPF_HOPOPTS;
ipp->ipp_sticky_ignored |= IPPF_HOPOPTS;
} else {
- error = icmp_pkt_set(invalp, inlen, sticky,
- (uchar_t **)&ipp->ipp_hopopts,
- &ipp->ipp_hopoptslen);
- if (error != 0)
- return (error);
ipp->ipp_fields |= IPPF_HOPOPTS;
}
if (sticky) {
@@ -2467,9 +2525,9 @@
ipp->ipp_fields &= ~IPPF_RTDSTOPTS;
ipp->ipp_sticky_ignored |= IPPF_RTDSTOPTS;
} else {
- error = icmp_pkt_set(invalp, inlen, sticky,
+ error = optcom_pkt_set(invalp, inlen, sticky,
(uchar_t **)&ipp->ipp_rtdstopts,
- &ipp->ipp_rtdstoptslen);
+ &ipp->ipp_rtdstoptslen, 0);
if (error != 0)
return (error);
ipp->ipp_fields |= IPPF_RTDSTOPTS;
@@ -2506,9 +2564,9 @@
ipp->ipp_fields &= ~IPPF_DSTOPTS;
ipp->ipp_sticky_ignored |= IPPF_DSTOPTS;
} else {
- error = icmp_pkt_set(invalp, inlen, sticky,
+ error = optcom_pkt_set(invalp, inlen, sticky,
(uchar_t **)&ipp->ipp_dstopts,
- &ipp->ipp_dstoptslen);
+ &ipp->ipp_dstoptslen, 0);
if (error != 0)
return (error);
ipp->ipp_fields |= IPPF_DSTOPTS;
@@ -2545,9 +2603,9 @@
ipp->ipp_fields &= ~IPPF_RTHDR;
ipp->ipp_sticky_ignored |= IPPF_RTHDR;
} else {
- error = icmp_pkt_set(invalp, inlen, sticky,
+ error = optcom_pkt_set(invalp, inlen, sticky,
(uchar_t **)&ipp->ipp_rthdr,
- &ipp->ipp_rthdrlen);
+ &ipp->ipp_rthdrlen, 0);
if (error != 0)
return (error);
ipp->ipp_fields |= IPPF_RTHDR;
@@ -2733,46 +2791,6 @@
}
/*
- * Set optbuf and optlen for the option.
- * If sticky is set allocate memory (if not already present).
- * Otherwise just point optbuf and optlen at invalp and inlen.
- * Returns failure if memory can not be allocated.
- */
-static int
-icmp_pkt_set(uchar_t *invalp, uint_t inlen, boolean_t sticky,
- uchar_t **optbufp, uint_t *optlenp)
-{
- uchar_t *optbuf;
-
- if (!sticky) {
- *optbufp = invalp;
- *optlenp = inlen;
- return (0);
- }
- if (inlen == *optlenp) {
- /* Unchanged length - no need to realocate */
- bcopy(invalp, *optbufp, inlen);
- return (0);
- }
- if (inlen != 0) {
- /* Allocate new buffer before free */
- optbuf = kmem_alloc(inlen, KM_NOSLEEP);
- if (optbuf == NULL)
- return (ENOMEM);
- } else {
- optbuf = NULL;
- }
- /* Free old buffer */
- if (*optlenp != 0)
- kmem_free(*optbufp, *optlenp);
-
- bcopy(invalp, optbuf, inlen);
- *optbufp = optbuf;
- *optlenp = inlen;
- return (0);
-}
-
-/*
* This routine retrieves the value of an ND variable in a icmpparam_t
* structure. It is called through nd_getset when a user reads the
* variable.
@@ -2857,6 +2875,7 @@
mblk_t *options_mp = NULL;
uint_t icmp_opt = 0;
boolean_t icmp_ipv6_recvhoplimit = B_FALSE;
+ uint_t hopstrip;
icmp = (icmp_t *)q->q_ptr;
if (icmp->icmp_restricted) {
@@ -3186,6 +3205,7 @@
/* Initialize */
ipp.ipp_fields = 0;
+ hopstrip = 0;
ip6h = (ip6_t *)rptr;
/*
@@ -3214,6 +3234,52 @@
ip6h = (ip6_t *)rptr;
}
hdr_len = ip_find_hdr_v6(mp, ip6h, &ipp, &nexthdr);
+
+ /*
+ * We need to lie a bit to the user because users inside
+ * labeled compartments should not see their own labels. We
+ * assume that in all other respects IP has checked the label,
+ * and that the label is always first among the options. (If
+ * it's not first, then this code won't see it, and the option
+ * will be passed along to the user.)
+ *
+ * If we had multilevel ICMP sockets, then the following code
+ * should be skipped for them to allow the user to see the
+ * label.
+ *
+ * Alignment restrictions in the definition of IP options
+ * (namely, the requirement that the 4-octet DOI goes on a
+ * 4-octet boundary) mean that we know exactly where the option
+ * should start, but we're lenient for other hosts.
+ *
+ * Note that there are no multilevel ICMP or raw IP sockets
+ * yet, thus nobody ever sees the IP6OPT_LS option.
+ */
+ if ((ipp.ipp_fields & IPPF_HOPOPTS) &&
+ ipp.ipp_hopoptslen > 5 && is_system_labeled()) {
+ const uchar_t *ucp =
+ (const uchar_t *)ipp.ipp_hopopts + 2;
+ int remlen = ipp.ipp_hopoptslen - 2;
+
+ while (remlen > 0) {
+ if (*ucp == IP6OPT_PAD1) {
+ remlen--;
+ ucp++;
+ } else if (*ucp == IP6OPT_PADN) {
+ remlen -= ucp[1] + 2;
+ ucp += ucp[1] + 2;
+ } else if (*ucp == ip6opt_ls) {
+ hopstrip = (ucp -
+ (const uchar_t *)ipp.ipp_hopopts) +
+ ucp[1] + 2;
+ hopstrip = (hopstrip + 7) & ~7;
+ break;
+ } else {
+ /* label option must be first */
+ break;
+ }
+ }
+ }
} else {
hdr_len = IPV6_HDR_LEN;
ip6i = NULL;
@@ -3293,9 +3359,10 @@
if (ipp.ipp_fields & (IPPF_HOPOPTS|IPPF_DSTOPTS|IPPF_RTDSTOPTS|
IPPF_RTHDR|IPPF_IFINDEX)) {
if (icmp->icmp_ipv6_recvhopopts &&
- (ipp.ipp_fields & IPPF_HOPOPTS)) {
+ (ipp.ipp_fields & IPPF_HOPOPTS) &&
+ ipp.ipp_hopoptslen > hopstrip) {
udi_size += sizeof (struct T_opthdr) +
- ipp.ipp_hopoptslen;
+ ipp.ipp_hopoptslen - hopstrip;
icmp_opt |= IPPF_HOPOPTS;
}
if ((icmp->icmp_ipv6_recvdstopts ||
@@ -3425,12 +3492,18 @@
toh->level = IPPROTO_IPV6;
toh->name = IPV6_HOPOPTS;
toh->len = sizeof (struct T_opthdr) +
- ipp.ipp_hopoptslen;
+ ipp.ipp_hopoptslen - hopstrip;
toh->status = 0;
dstopt += sizeof (struct T_opthdr);
- bcopy(ipp.ipp_hopopts, dstopt,
- ipp.ipp_hopoptslen);
- dstopt += ipp.ipp_hopoptslen;
+ bcopy((char *)ipp.ipp_hopopts + hopstrip, dstopt,
+ ipp.ipp_hopoptslen - hopstrip);
+ if (hopstrip > 0) {
+ /* copy next header value and fake length */
+ dstopt[0] = ((uchar_t *)ipp.ipp_hopopts)[0];
+ dstopt[1] = ((uchar_t *)ipp.ipp_hopopts)[1] -
+ hopstrip / 8;
+ }
+ dstopt += ipp.ipp_hopoptslen - hopstrip;
udi_size -= toh->len;
}
if (icmp_opt & IPPF_RTDSTOPTS) {
@@ -3850,9 +3923,36 @@
*/
(void) ip_massage_options(ipha);
}
+ mblk_setcred(mp, icmp->icmp_credp);
putnext(q, mp);
}
+static boolean_t
+icmp_update_label(queue_t *q, icmp_t *icmp, mblk_t *mp, ipaddr_t dst)
+{
+ int err;
+ uchar_t opt_storage[IP_MAX_OPT_LENGTH];
+
+ err = tsol_compute_label(DB_CREDDEF(mp, icmp->icmp_credp), dst,
+ opt_storage, icmp->icmp_mac_exempt);
+ if (err == 0) {
+ err = tsol_update_options(&icmp->icmp_ip_snd_options,
+ &icmp->icmp_ip_snd_options_len, &icmp->icmp_label_len,
+ opt_storage);
+ }
+ if (err != 0) {
+ BUMP_MIB(&rawip_mib, rawipOutErrors);
+ DTRACE_PROBE4(
+ tx__ip__log__drop__updatelabel__icmp,
+ char *, "queue(1) failed to update options(2) on mp(3)",
+ queue_t *, q, char *, opt_storage, mblk_t *, mp);
+ icmp_ud_err(q, mp, err);
+ return (B_FALSE);
+ }
+ IN6_IPADDR_TO_V4MAPPED(dst, &icmp->icmp_v6lastdst);
+ return (B_TRUE);
+}
+
/*
* This routine handles all messages passed downstream. It either
* consumes the message or passes it downstream; it never queues a
@@ -3882,6 +3982,27 @@
case M_DATA:
if (icmp->icmp_hdrincl) {
ASSERT(icmp->icmp_ipversion == IPV4_VERSION);
+ ipha = (ipha_t *)mp->b_rptr;
+ if (mp->b_wptr - mp->b_rptr < IP_SIMPLE_HDR_LENGTH) {
+ if (!pullupmsg(mp, IP_SIMPLE_HDR_LENGTH)) {
+ BUMP_MIB(&rawip_mib, rawipOutErrors);
+ freemsg(mp);
+ return;
+ }
+ ipha = (ipha_t *)mp->b_rptr;
+ }
+ /*
+ * If this connection was used for v6 (inconceivable!)
+ * or if we have a new destination, then it's time to
+ * figure a new label.
+ */
+ if (is_system_labeled() &&
+ (!IN6_IS_ADDR_V4MAPPED(&icmp->icmp_v6lastdst) ||
+ V4_PART_OF_V6(icmp->icmp_v6lastdst) !=
+ ipha->ipha_dst) &&
+ !icmp_update_label(q, icmp, mp, ipha->ipha_dst)) {
+ return;
+ }
icmp_wput_hdrincl(q, mp, icmp);
return;
}
@@ -3960,6 +4081,9 @@
/* Extract and ipaddr */
v4dst = sin->sin_addr.s_addr;
break;
+
+ default:
+ ASSERT(0);
}
/*
@@ -3983,12 +4107,24 @@
*/
}
+ if (v4dst == INADDR_ANY)
+ v4dst = htonl(INADDR_LOOPBACK);
+
+ /* Check if our saved options are valid; update if not */
+ if (is_system_labeled() &&
+ (!IN6_IS_ADDR_V4MAPPED(&icmp->icmp_v6lastdst) ||
+ V4_PART_OF_V6(icmp->icmp_v6lastdst) != v4dst) &&
+ !icmp_update_label(q, icmp, mp, v4dst)) {
+ return;
+ }
+
/* Protocol 255 contains full IP headers */
if (icmp->icmp_hdrincl) {
freeb(mp);
icmp_wput_hdrincl(q, mp1, icmp);
return;
}
+
/* Add an IP header */
ip_hdr_length = IP_SIMPLE_HDR_LENGTH + icmp->icmp_ip_snd_options_len;
ipha = (ipha_t *)&mp1->b_rptr[-ip_hdr_length];
@@ -4059,10 +4195,7 @@
* Copy in the destination address from the T_UNITDATA
* request
*/
- if (v4dst == INADDR_ANY)
- ipha->ipha_dst = htonl(INADDR_LOOPBACK);
- else
- ipha->ipha_dst = v4dst;
+ ipha->ipha_dst = v4dst;
/*
* Set ttl based on IP_MULTICAST_TTL to match IPv6 logic.
@@ -4082,15 +4215,42 @@
}
freeb(mp);
BUMP_MIB(&rawip_mib, rawipOutDatagrams);
+ mblk_setcred(mp1, icmp->icmp_credp);
putnext(q, mp1);
#undef ipha
#undef tudr
}
+static boolean_t
+icmp_update_label_v6(queue_t *wq, icmp_t *icmp, mblk_t *mp, in6_addr_t *dst)
+{
+ int err;
+ uchar_t opt_storage[TSOL_MAX_IPV6_OPTION];
+
+ err = tsol_compute_label_v6(DB_CREDDEF(mp, icmp->icmp_credp), dst,
+ opt_storage, icmp->icmp_mac_exempt);
+ if (err == 0) {
+ err = tsol_update_sticky(&icmp->icmp_sticky_ipp,
+ &icmp->icmp_label_len_v6, opt_storage);
+ }
+ if (err != 0) {
+ BUMP_MIB(&rawip_mib, rawipOutErrors);
+ DTRACE_PROBE4(
+ tx__ip__log__drop__updatelabel__icmp6,
+ char *, "queue(1) failed to update options(2) on mp(3)",
+ queue_t *, wq, char *, opt_storage, mblk_t *, mp);
+ icmp_ud_err(wq, mp, err);
+ return (B_FALSE);
+ }
+
+ icmp->icmp_v6lastdst = *dst;
+ return (B_TRUE);
+}
+
/*
* icmp_wput_ipv6():
* Assumes that icmp_wput did some sanity checking on the destination
- * address.
+ * address, but that the label may not yet be correct.
*/
void
icmp_wput_ipv6(queue_t *q, mblk_t *mp, sin6_t *sin6, t_scalar_t tudr_optlen)
@@ -4109,6 +4269,7 @@
uint_t option_exists = 0, is_sticky = 0;
uint8_t *cp;
uint8_t *nxthdr_ptr;
+ in6_addr_t ip6_dst;
icmp = (icmp_t *)q->q_ptr;
@@ -4155,6 +4316,34 @@
option_exists |= IPPF_SCOPE_ID;
}
+ /*
+ * Compute the destination address
+ */
+ ip6_dst = sin6->sin6_addr;
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
+ ip6_dst = ipv6_loopback;
+
+ /*
+ * If we're not going to the same destination as last time, then
+ * recompute the label required. This is done in a separate routine to
+ * avoid blowing up our stack here.
+ */
+ if (is_system_labeled() &&
+ !IN6_ARE_ADDR_EQUAL(&icmp->icmp_v6lastdst, &ip6_dst) &&
+ !icmp_update_label_v6(q, icmp, mp, &ip6_dst)) {
+ return;
+ }
+
+ /*
+ * If there's a security label here, then we ignore any options the
+ * user may try to set. We keep the peer's label as a hidden sticky
+ * option.
+ */
+ if (icmp->icmp_label_len_v6 > 0) {
+ ignore &= ~IPPF_HOPOPTS;
+ ipp->ipp_fields &= ~IPPF_HOPOPTS;
+ }
+
if ((icmp->icmp_sticky_ipp.ipp_fields == 0) &&
(ipp->ipp_fields == 0)) {
/* No sticky options nor ancillary data. */
@@ -4497,10 +4686,7 @@
/*
* Copy in the destination address
*/
- if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
- ip6h->ip6_dst = ipv6_loopback;
- else
- ip6h->ip6_dst = sin6->sin6_addr;
+ ip6h->ip6_dst = ip6_dst;
ip6h->ip6_vcf =
(IPV6_DEFAULT_VERS_AND_FLOW & IPV6_VERS_AND_FLOW_MASK) |
@@ -4622,6 +4808,7 @@
/* We're done. Pass the packet to IP */
BUMP_MIB(&rawip_mib, rawipOutDatagrams);
+ mblk_setcred(mp1, icmp->icmp_credp);
putnext(q, mp1);
}
--- a/usr/src/uts/common/inet/ip/icmp_opt_data.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip/icmp_opt_data.c Fri Mar 24 12:29:20 2006 -0800
@@ -87,6 +87,8 @@
0 },
{ SO_TIMESTAMP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0
},
+{ SO_MAC_EXEMPT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int),
+ 0 },
{ IP_OPTIONS, IPPROTO_IP, OA_RW, OA_RW, OP_NP,
(OP_PASSNEXT|OP_VARLEN|OP_NODEFAULT),
--- a/usr/src/uts/common/inet/ip/igmp.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip/igmp.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
@@ -38,10 +37,8 @@
* MULTICAST 3.5.1.1
*/
-
#include <sys/types.h>
#include <sys/stream.h>
-#include <sys/dlpi.h>
#include <sys/stropts.h>
#include <sys/strlog.h>
#include <sys/strsun.h>
@@ -54,12 +51,8 @@
#include <sys/param.h>
#include <sys/socket.h>
-#define _SUN_TPI_VERSION 2
-#include <sys/tihdr.h>
#include <inet/ipclassifier.h>
#include <net/if.h>
-#include <net/if_arp.h>
-#include <sys/sockio.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/igmp_var.h>
@@ -69,7 +62,6 @@
#include <inet/common.h>
#include <inet/mi.h>
#include <inet/nd.h>
-#include <inet/arp.h>
#include <inet/ip.h>
#include <inet/ip6.h>
#include <inet/ip_multi.h>
@@ -1871,6 +1863,7 @@
ill_t *ill = ipif->ipif_ill; /* Will be the "lower" ill */
mblk_t *first_mp;
ipsec_out_t *io;
+ zoneid_t zoneid;
/*
* We need to make sure this packet goes out on an ipif. If
@@ -1907,7 +1900,9 @@
io->ipsec_out_attach_if = B_TRUE;
io->ipsec_out_multicast_loop = B_FALSE;
io->ipsec_out_dontroute = B_TRUE;
- io->ipsec_out_zoneid = ilm->ilm_zoneid;
+ if ((zoneid = ilm->ilm_zoneid) == ALL_ZONES)
+ zoneid = GLOBAL_ZONEID;
+ io->ipsec_out_zoneid = zoneid;
mp = allocb(size, BPRI_HI);
if (mp == NULL) {
@@ -1986,6 +1981,7 @@
mrec_t *rp, *cur_reclist;
mrec_t *next_reclist = reclist;
boolean_t morepkts;
+ zoneid_t zoneid;
/* if there aren't any records, there's nothing to send */
if (reclist == NULL)
@@ -2077,7 +2073,9 @@
io->ipsec_out_attach_if = B_TRUE;
io->ipsec_out_multicast_loop = B_FALSE;
io->ipsec_out_dontroute = B_TRUE;
- io->ipsec_out_zoneid = ipif->ipif_zoneid;
+ if ((zoneid = ipif->ipif_zoneid) == ALL_ZONES)
+ zoneid = GLOBAL_ZONEID;
+ io->ipsec_out_zoneid = zoneid;
mp = allocb(size, BPRI_HI);
if (mp == NULL) {
--- a/usr/src/uts/common/inet/ip/ip.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip/ip.c Fri Mar 24 12:29:20 2006 -0800
@@ -46,6 +46,7 @@
#include <sys/modctl.h>
#include <sys/atomic.h>
#include <sys/policy.h>
+#include <sys/priv.h>
#include <sys/systm.h>
#include <sys/param.h>
@@ -113,6 +114,11 @@
#include <inet/sctp_ip.h>
#include <inet/udp_impl.h>
+#include <sys/tsol/label.h>
+#include <sys/tsol/tnet.h>
+
+#include <rpc/pmap_prot.h>
+
/*
* Values for squeue switch:
* IP_SQUEUE_ENTER_NODRAIN: squeue_enter_nodrain
@@ -252,6 +258,17 @@
typedef struct listptr_s listptr_t;
/*
+ * This is used by ip_snmp_get_mib2_ip_route_media and
+ * ip_snmp_get_mib2_ip6_route_media to carry the lists of return data.
+ */
+typedef struct iproutedata_s {
+ uint_t ird_idx;
+ listptr_t ird_route; /* ipRouteEntryTable */
+ listptr_t ird_netmedia; /* ipNetToMediaEntryTable */
+ listptr_t ird_attrs; /* ipRouteAttributeTable */
+} iproutedata_t;
+
+/*
* Cluster specific hooks. These should be NULL when booted as a non-cluster
*/
@@ -423,18 +440,31 @@
* ill_g_lock -> ndp_g_lock -> ill_lock -> nce_lock
* ill_g_lock -> ip_addr_avail_lock
* conn_lock -> irb_lock -> ill_lock -> ire_lock
- * ipsa_lock -> ill_g_lock -> ill_lock
* ill_g_lock -> ip_g_nd_lock
- * irb_lock -> ill_lock -> ire_mrtun_lock
- * irb_lock -> ill_lock -> ire_srcif_table_lock
- * ipsec_capab_ills_lock -> ill_g_lock -> ill_lock
- * ipsec_capab_ills_lock -> ipsa_lock
- * ill_g_usesrc_lock -> ill_g_lock -> ill_lock
*
* When more than 1 ill lock is needed to be held, all ill lock addresses
* are sorted on address and locked starting from highest addressed lock
* downward.
*
+ * Mobile-IP scenarios
+ *
+ * irb_lock -> ill_lock -> ire_mrtun_lock
+ * irb_lock -> ill_lock -> ire_srcif_table_lock
+ *
+ * IPsec scenarios
+ *
+ * ipsa_lock -> ill_g_lock -> ill_lock
+ * ipsec_capab_ills_lock -> ill_g_lock -> ill_lock
+ * ipsec_capab_ills_lock -> ipsa_lock
+ * ill_g_usesrc_lock -> ill_g_lock -> ill_lock
+ *
+ * Trusted Solaris scenarios
+ *
+ * igsa_lock -> gcgrp_rwlock -> gcgrp_lock
+ * igsa_lock -> gcdb_lock
+ * gcgrp_rwlock -> ire_lock
+ * gcgrp_rwlock -> gcdb_lock
+ *
* IPSEC notes :
*
* IP interacts with the IPSEC code (AH/ESP) by tagging a M_CTL message
@@ -700,9 +730,9 @@
static mblk_t *ip_snmp_get_mib2_multi_rtable(queue_t *, mblk_t *);
static mblk_t *ip_snmp_get_mib2_ip_route_media(queue_t *, mblk_t *);
static mblk_t *ip_snmp_get_mib2_ip6_route_media(queue_t *, mblk_t *);
-static void ip_snmp_get2_v4(ire_t *, listptr_t []);
-static void ip_snmp_get2_v6_route(ire_t *, listptr_t *);
-static int ip_snmp_get2_v6_media(nce_t *, listptr_t *);
+static void ip_snmp_get2_v4(ire_t *, iproutedata_t *);
+static void ip_snmp_get2_v6_route(ire_t *, iproutedata_t *);
+static int ip_snmp_get2_v6_media(nce_t *, iproutedata_t *);
int ip_snmp_set(queue_t *, int, int, uchar_t *, int);
static boolean_t ip_source_routed(ipha_t *);
static boolean_t ip_source_route_included(ipha_t *);
@@ -1666,6 +1696,23 @@
if (first_mp == NULL)
return;
}
+
+ /*
+ * On a labeled system, we have to check whether the zone itself is
+ * permitted to receive raw traffic.
+ */
+ if (is_system_labeled()) {
+ if (zoneid == ALL_ZONES)
+ zoneid = tsol_packet_to_zoneid(mp);
+ if (!tsol_can_accept_raw(mp, B_FALSE)) {
+ ip1dbg(("icmp_inbound: zone %d can't receive raw",
+ zoneid));
+ BUMP_MIB(&icmp_mib, icmpInErrors);
+ freemsg(first_mp);
+ return;
+ }
+ }
+
/*
* We have accepted the ICMP message. It means that we will
* respond to the packet if needed. It may not be delivered
@@ -2037,7 +2084,7 @@
* accept packets for them afterwards.
*/
src_ire = ire_ctable_lookup(ipha->ipha_dst, 0, IRE_LOCAL,
- NULL, ALL_ZONES, MATCH_IRE_TYPE);
+ NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (src_ire == NULL) {
ipif = ipif_get_next_ipif(NULL, ill);
if (ipif == NULL) {
@@ -2047,7 +2094,7 @@
}
src_ire = ire_ftable_lookup(ipha->ipha_dst, 0, 0,
IRE_INTERFACE, ipif, NULL, ALL_ZONES, 0,
- MATCH_IRE_ILL | MATCH_IRE_TYPE);
+ NULL, MATCH_IRE_ILL | MATCH_IRE_TYPE);
ipif_refrele(ipif);
if (src_ire != NULL) {
onlink = B_TRUE;
@@ -2091,6 +2138,7 @@
ii = (ipsec_in_t *)first_mp->b_rptr;
}
ii->ipsec_in_zoneid = zoneid;
+ ASSERT(zoneid != ALL_ZONES);
if (!ipsec_in_to_out(first_mp, ipha, NULL)) {
BUMP_MIB(&ip_mib, ipInDiscards);
return;
@@ -2124,7 +2172,7 @@
hdr_length = IPH_HDR_LENGTH(ipha);
first_ire = ire_ctable_lookup(ipha->ipha_dst, 0, IRE_CACHE, NULL,
- ALL_ZONES, MATCH_IRE_TYPE);
+ ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (!first_ire) {
ip1dbg(("icmp_inbound_too_big: no route for 0x%x\n",
@@ -2144,8 +2192,9 @@
mutex_enter(&ire->ire_lock);
if (icmph->icmph_du_zero == 0 && mtu > 68) {
/* Reduce the IRE max frag value as advised. */
+ ip1dbg(("Received mtu from router: %d (was %d)\n",
+ mtu, ire->ire_max_frag));
ire->ire_max_frag = MIN(ire->ire_max_frag, mtu);
- ip1dbg(("Received mtu from router: %d\n", mtu));
} else {
uint32_t length;
int i;
@@ -2761,6 +2810,93 @@
}
/*
+ * Use the outgoing IP header to create an IP_OPTIONS option the way
+ * it was passed down from the application.
+ */
+int
+ip_opt_get_user(const ipha_t *ipha, uchar_t *buf)
+{
+ ipoptp_t opts;
+ const uchar_t *opt;
+ uint8_t optval;
+ uint8_t optlen;
+ uint32_t len = 0;
+ uchar_t *buf1 = buf;
+
+ buf += IP_ADDR_LEN; /* Leave room for final destination */
+ len += IP_ADDR_LEN;
+ bzero(buf1, IP_ADDR_LEN);
+
+ /*
+ * OK to cast away const here, as we don't store through the returned
+ * opts.ipoptp_cur pointer.
+ */
+ for (optval = ipoptp_first(&opts, (ipha_t *)ipha);
+ optval != IPOPT_EOL;
+ optval = ipoptp_next(&opts)) {
+ int off;
+
+ opt = opts.ipoptp_cur;
+ optlen = opts.ipoptp_len;
+ switch (optval) {
+ case IPOPT_SSRR:
+ case IPOPT_LSRR:
+
+ /*
+ * Insert ipha_dst as the first entry in the source
+ * route and move down the entries on step.
+ * The last entry gets placed at buf1.
+ */
+ buf[IPOPT_OPTVAL] = optval;
+ buf[IPOPT_OLEN] = optlen;
+ buf[IPOPT_OFFSET] = optlen;
+
+ off = optlen - IP_ADDR_LEN;
+ if (off < 0) {
+ /* No entries in source route */
+ break;
+ }
+ /* Last entry in source route */
+ bcopy(opt + off, buf1, IP_ADDR_LEN);
+ off -= IP_ADDR_LEN;
+
+ while (off > 0) {
+ bcopy(opt + off,
+ buf + off + IP_ADDR_LEN,
+ IP_ADDR_LEN);
+ off -= IP_ADDR_LEN;
+ }
+ /* ipha_dst into first slot */
+ bcopy(&ipha->ipha_dst,
+ buf + off + IP_ADDR_LEN,
+ IP_ADDR_LEN);
+ buf += optlen;
+ len += optlen;
+ break;
+
+ case IPOPT_COMSEC:
+ case IPOPT_SECURITY:
+ /* if passing up a label is not ok, then remove */
+ if (is_system_labeled())
+ break;
+ /* FALLTHROUGH */
+ default:
+ bcopy(opt, buf, optlen);
+ buf += optlen;
+ len += optlen;
+ break;
+ }
+ }
+done:
+ /* Pad the resulting options */
+ while (len & 0x3) {
+ *buf++ = IPOPT_EOL;
+ len++;
+ }
+ return (len);
+}
+
+/*
* Update any record route or timestamp options to include this host.
* Reverse any source route option.
* This routine assumes that the options are well formed i.e. that they
@@ -2856,14 +2992,14 @@
gateway = icmph->icmph_rd_gateway;
/* Make sure the new gateway is reachable somehow. */
ire = ire_route_lookup(gateway, 0, 0, IRE_INTERFACE, NULL, NULL,
- ALL_ZONES, MATCH_IRE_TYPE);
+ ALL_ZONES, NULL, MATCH_IRE_TYPE);
/*
* Make sure we had a route for the dest in question and that
* that route was pointing to the old gateway (the source of the
* redirect packet.)
*/
prev_ire = ire_route_lookup(dst, 0, src, 0, NULL, NULL, ALL_ZONES,
- MATCH_IRE_GW);
+ NULL, MATCH_IRE_GW);
/*
* Check that
* the redirect was not from ourselves
@@ -2903,7 +3039,7 @@
ire_t *sire;
tmp_ire = ire_ftable_lookup(dst, 0, gateway, 0, NULL, &sire,
- ALL_ZONES, 0,
+ ALL_ZONES, 0, NULL,
(MATCH_IRE_RECURSIVE | MATCH_IRE_GW | MATCH_IRE_DEFAULT));
if (sire != NULL) {
bcopy(&sire->ire_uinfo, &ulp_info, sizeof (iulp_t));
@@ -2963,7 +3099,9 @@
0,
0,
(RTF_DYNAMIC | RTF_GATEWAY | RTF_HOST),
- &ulp_info);
+ &ulp_info,
+ NULL,
+ NULL);
if (ire == NULL) {
freemsg(mp);
@@ -2986,7 +3124,7 @@
* modifying an existing redirect.
*/
prev_ire = ire_ftable_lookup(dst, 0, src, IRE_HOST_REDIRECT, NULL, NULL,
- ALL_ZONES, 0, (MATCH_IRE_GW | MATCH_IRE_TYPE));
+ ALL_ZONES, 0, NULL, (MATCH_IRE_GW | MATCH_IRE_TYPE));
if (prev_ire) {
ire_delete(prev_ire);
ire_refrele(prev_ire);
@@ -3120,6 +3258,7 @@
zoneid = GLOBAL_ZONEID;
}
ii->ipsec_in_zoneid = zoneid;
+ ASSERT(zoneid != ALL_ZONES);
ipsec_mp->b_cont = mp;
ipha = (ipha_t *)mp->b_rptr;
/*
@@ -3136,13 +3275,14 @@
dst = ipha->ipha_src;
ire = ire_route_lookup(ipha->ipha_dst, 0, 0, (IRE_LOCAL|IRE_LOOPBACK),
- NULL, NULL, zoneid, MATCH_IRE_TYPE);
- if (ire != NULL && ire->ire_zoneid == zoneid) {
+ NULL, NULL, zoneid, NULL, MATCH_IRE_TYPE);
+ if (ire != NULL &&
+ (ire->ire_zoneid == zoneid || ire->ire_zoneid == ALL_ZONES)) {
src = ipha->ipha_dst;
} else if (!xmit_if_on) {
if (ire != NULL)
ire_refrele(ire);
- ire = ire_route_lookup(dst, 0, 0, 0, NULL, NULL, zoneid,
+ ire = ire_route_lookup(dst, 0, 0, 0, NULL, NULL, zoneid, NULL,
(MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE|MATCH_IRE_ZONEONLY));
if (ire == NULL) {
BUMP_MIB(&ip_mib, ipOutNoRoutes);
@@ -3187,18 +3327,29 @@
* Check if we can send back more then 8 bytes in addition
* to the IP header. We will include as much as 64 bytes.
*/
- len_needed = IPH_HDR_LENGTH(ipha) + ip_icmp_return;
+ len_needed = IPH_HDR_LENGTH(ipha);
+ if (ipha->ipha_protocol == IPPROTO_ENCAP &&
+ (uchar_t *)ipha + len_needed + 1 <= mp->b_wptr) {
+ len_needed += IPH_HDR_LENGTH(((uchar_t *)ipha + len_needed));
+ }
+ len_needed += ip_icmp_return;
msg_len = msgdsize(mp);
if (msg_len > len_needed) {
(void) adjmsg(mp, len_needed - msg_len);
msg_len = len_needed;
}
mp1 = allocb(sizeof (icmp_ipha) + len, BPRI_HI);
- if (!mp1) {
+ if (mp1 == NULL) {
BUMP_MIB(&icmp_mib, icmpOutErrors);
freemsg(ipsec_mp);
return;
}
+ /*
+ * On an unlabeled system, dblks don't necessarily have creds.
+ */
+ ASSERT(!is_system_labeled() || DB_CRED(mp) != NULL);
+ if (DB_CRED(mp) != NULL)
+ mblk_setcred(mp1, DB_CRED(mp));
mp1->b_cont = mp;
mp = mp1;
ASSERT(ipsec_mp->b_datap->db_type == M_CTL &&
@@ -3314,9 +3465,9 @@
return (NULL);
}
src_ire = ire_ctable_lookup(ipha->ipha_dst, 0, IRE_BROADCAST,
- NULL, ALL_ZONES, MATCH_IRE_TYPE);
+ NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE);
dst_ire = ire_ctable_lookup(ipha->ipha_src, 0, IRE_BROADCAST,
- NULL, ALL_ZONES, MATCH_IRE_TYPE);
+ NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (src_ire != NULL || dst_ire != NULL ||
CLASSD(ipha->ipha_dst) ||
CLASSD(ipha->ipha_src) ||
@@ -3359,6 +3510,16 @@
break;
}
}
+ /*
+ * If this is a labeled system, then check to see if we're allowed to
+ * send a response to this particular sender. If not, then just drop.
+ */
+ if (is_system_labeled() && !tsol_can_reply_error(mp)) {
+ ip2dbg(("icmp_pkt_err_ok: can't respond to packet\n"));
+ BUMP_MIB(&icmp_mib, icmpOutDrops);
+ freemsg(mp);
+ return (NULL);
+ }
if (icmp_err_rate_limit()) {
/*
* Only send ICMP error packets every so often.
@@ -3515,9 +3676,9 @@
cp1[-1] = '\0';
(void) ip_dot_addr(src, sbuf);
if (isv6)
- ire = ire_cache_lookup_v6(&v6src, ALL_ZONES);
+ ire = ire_cache_lookup_v6(&v6src, ALL_ZONES, NULL);
else
- ire = ire_cache_lookup(src, ALL_ZONES);
+ ire = ire_cache_lookup(src, ALL_ZONES, NULL);
if (ire != NULL && IRE_IS_LOCAL(ire)) {
cmn_err(CE_WARN,
@@ -3579,7 +3740,7 @@
*/
if ((ip_ire_clookup_and_delete(src, NULL) ||
(ire = ire_ftable_lookup(src, 0, 0, 0, NULL, NULL, NULL,
- 0, MATCH_IRE_DSTONLY)) != NULL) && src != 0) {
+ 0, NULL, MATCH_IRE_DSTONLY)) != NULL) && src != 0) {
ire_walk_v4(ire_delete_cache_gw, (char *)&src,
ALL_ZONES);
}
@@ -3766,6 +3927,18 @@
goto bad_addr;
}
+ /*
+ *
+ * The udp module never sends down a zero-length address,
+ * and allowing this on a labeled system will break MLP
+ * functionality.
+ */
+ if (is_system_labeled() && protocol == IPPROTO_UDP)
+ goto bad_addr;
+
+ if (connp->conn_mac_exempt)
+ goto bad_addr;
+
/* No hash here really. The table is big enough. */
connp->conn_srcv6 = ipv6_all_zeros;
@@ -3904,6 +4077,8 @@
* In all the above cases, the bound address must be valid in the current zone.
* When the address is loopback, multicast or broadcast, there might be many
* matching IREs so bind has to look up based on the zone.
+ *
+ * Note: lport is in network byte order.
*/
int
ip_bind_laddr(conn_t *connp, mblk_t *mp, ipaddr_t src_addr, uint16_t lport,
@@ -3933,7 +4108,7 @@
if (src_addr) {
src_ire = ire_route_lookup(src_addr, 0, 0, 0,
- NULL, NULL, zoneid, MATCH_IRE_ZONEONLY);
+ NULL, NULL, zoneid, NULL, MATCH_IRE_ZONEONLY);
/*
* If an address other than 0.0.0.0 is requested,
* we verify that it is a valid address for bind
@@ -3984,7 +4159,7 @@
*/
src_ire = ire_ctable_lookup(
INADDR_BROADCAST, INADDR_ANY,
- IRE_BROADCAST, NULL, zoneid,
+ IRE_BROADCAST, NULL, zoneid, NULL,
(MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY));
if (src_ire == NULL || !ire_requested)
error = EADDRNOTAVAIL;
@@ -4033,7 +4208,7 @@
*/
error = ipcl_bind_insert(connp, *mp->b_wptr, src_addr, lport);
}
-done:
+
if (error == 0) {
if (ire_requested) {
if (!ip_bind_insert_ire(mp, src_ire, NULL)) {
@@ -4048,6 +4223,14 @@
}
}
bad_addr:
+ if (error != 0) {
+ if (connp->conn_anon_port) {
+ (void) tsol_mlp_anon(crgetzone(connp->conn_cred),
+ connp->conn_mlp_type, connp->conn_ulp, ntohs(lport),
+ B_FALSE);
+ }
+ connp->conn_mlp_type = mlptSingle;
+ }
if (src_ire != NULL)
IRE_REFRELE(src_ire);
if (ipsec_policy_set) {
@@ -4075,6 +4258,8 @@
* Returns zero if ok.
* On error: returns -1 to mean TBADADDR otherwise returns an errno
* (for use with TSYSERR reply).
+ *
+ * Note: lport and fport are in network byte order.
*/
int
ip_bind_connected(conn_t *connp, mblk_t *mp, ipaddr_t *src_addrp,
@@ -4110,8 +4295,10 @@
if (CLASSD(dst_addr)) {
/* Pick up an IRE_BROADCAST */
dst_ire = ire_route_lookup(ip_g_all_ones, 0, 0, 0, NULL,
- NULL, zoneid, (MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT |
- MATCH_IRE_RJ_BHOLE));
+ NULL, zoneid, MBLK_GETLABEL(mp),
+ (MATCH_IRE_RECURSIVE |
+ MATCH_IRE_DEFAULT | MATCH_IRE_RJ_BHOLE |
+ MATCH_IRE_SECATTR));
} else {
/*
* If conn_dontroute is set or if conn_nexthop_set is set,
@@ -4131,12 +4318,14 @@
if (connp->conn_nexthop_set) {
dst_ire = ire_route_lookup(connp->conn_nexthop_v4, 0,
- 0, 0, NULL, NULL, zoneid, 0);
+ 0, 0, NULL, NULL, zoneid, MBLK_GETLABEL(mp),
+ MATCH_IRE_SECATTR);
} else {
dst_ire = ire_route_lookup(dst_addr, 0, 0, 0, NULL,
- &sire, zoneid,
+ &sire, zoneid, MBLK_GETLABEL(mp),
(MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT |
- MATCH_IRE_PARENT | MATCH_IRE_RJ_BHOLE));
+ MATCH_IRE_PARENT | MATCH_IRE_RJ_BHOLE |
+ MATCH_IRE_SECATTR));
}
}
/*
@@ -4175,6 +4364,34 @@
goto bad_addr;
}
}
+
+ /*
+ * We now know that routing will allow us to reach the destination.
+ * Check whether Trusted Solaris policy allows communication with this
+ * host, and pretend that the destination is unreachable if not.
+ *
+ * This is never a problem for TCP, since that transport is known to
+ * compute the label properly as part of the tcp_rput_other T_BIND_ACK
+ * handling. If the remote is unreachable, it will be detected at that
+ * point, so there's no reason to check it here.
+ *
+ * Note that for sendto (and other datagram-oriented friends), this
+ * check is done as part of the data path label computation instead.
+ * The check here is just to make non-TCP connect() report the right
+ * error.
+ */
+ if (dst_ire != NULL && is_system_labeled() &&
+ !IPCL_IS_TCP(connp) &&
+ tsol_compute_label(DB_CREDDEF(mp, connp->conn_cred), dst_addr, NULL,
+ connp->conn_mac_exempt) != 0) {
+ error = EHOSTUNREACH;
+ if (ip_debug > 2) {
+ pr_addr_dbg("ip_bind_connected: no label for dst %s\n",
+ AF_INET, &dst_addr);
+ }
+ goto bad_addr;
+ }
+
/*
* If the app does a connect(), it means that it will most likely
* send more than 1 packet to the destination. It makes sense
@@ -4212,14 +4429,14 @@
if (dst_ire != NULL &&
dst_ire->ire_type == IRE_LOCAL &&
- dst_ire->ire_zoneid != zoneid) {
+ dst_ire->ire_zoneid != zoneid && dst_ire->ire_zoneid != ALL_ZONES) {
/*
* If the IRE belongs to a different zone, look for a matching
* route in the forwarding table and use the source address from
* that route.
*/
src_ire = ire_ftable_lookup(dst_addr, 0, 0, 0, NULL, NULL,
- zoneid, 0,
+ zoneid, 0, NULL,
MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT |
MATCH_IRE_RJ_BHOLE);
if (src_ire == NULL) {
@@ -4271,11 +4488,12 @@
* group, then try selecting a source address from
* the usesrc ILL.
*/
- if (!(dst_ire->ire_type & IRE_BROADCAST) &&
+ if ((dst_ire->ire_zoneid != zoneid &&
+ dst_ire->ire_zoneid != ALL_ZONES) ||
+ (!(dst_ire->ire_type & IRE_BROADCAST) &&
((dst_ill->ill_group != NULL) ||
- (dst_ire->ire_ipif->ipif_flags &
- IPIF_DEPRECATED) ||
- (dst_ill->ill_usesrc_ifindex != 0))) {
+ (dst_ire->ire_ipif->ipif_flags & IPIF_DEPRECATED) ||
+ (dst_ill->ill_usesrc_ifindex != 0)))) {
/*
* If the destination is reachable via a
* given gateway, the selected source address
@@ -4335,7 +4553,7 @@
*/
ASSERT(src_ire == NULL);
src_ire = ire_route_lookup(src_addr, 0, 0, 0, NULL,
- NULL, zoneid, MATCH_IRE_ZONEONLY);
+ NULL, zoneid, NULL, MATCH_IRE_ZONEONLY);
/* src_ire must be a local|loopback */
if (!IRE_IS_LOCAL(src_ire)) {
if (ip_debug > 2) {
@@ -4785,6 +5003,14 @@
if (conn_ioctl_cleanup_reqd)
conn_ioctl_cleanup(connp);
+ if (is_system_labeled() && connp->conn_anon_port) {
+ (void) tsol_mlp_anon(crgetzone(connp->conn_cred),
+ connp->conn_mlp_type, connp->conn_ulp,
+ ntohs(connp->conn_lport), B_FALSE);
+ connp->conn_anon_port = 0;
+ }
+ connp->conn_mlp_type = mlptSingle;
+
/*
* Remove this conn from any fanout list it is on.
* and then wait for any threads currently operating
@@ -4877,10 +5103,6 @@
freemsg(connp->conn_ipsec_opt_mp);
connp->conn_ipsec_opt_mp = NULL;
}
- if (connp->conn_cred != NULL) {
- crfree(connp->conn_cred);
- connp->conn_cred = NULL;
- }
inet_minor_free(ip_minor_arena, connp->conn_dev);
@@ -4998,6 +5220,7 @@
void
ip_ddi_destroy(void)
{
+ tnet_fini();
tcp_ddi_destroy();
sctp_ddi_destroy();
ipsec_loader_destroy();
@@ -5088,8 +5311,8 @@
ip_kstat_init();
ip6_kstat_init();
icmp_kstat_init();
-
ipsec_loader_start();
+ tnet_init();
}
/*
@@ -5299,30 +5522,6 @@
return (B_TRUE);
}
-#ifdef DEBUG
-/*
- * Copy the header into the IPSEC_IN message.
- */
-static void
-ipsec_inbound_debug_tag(mblk_t *ipsec_mp)
-{
- mblk_t *data_mp = ipsec_mp->b_cont;
- ipsec_in_t *ii = (ipsec_in_t *)ipsec_mp->b_rptr;
- ipha_t *ipha;
-
- if (ii->ipsec_in_type != IPSEC_IN)
- return;
- ASSERT(data_mp != NULL);
-
- ipha = (ipha_t *)data_mp->b_rptr;
- bcopy(ipha, ii->ipsec_in_saved_hdr,
- (IPH_HDR_VERSION(ipha) == IP_VERSION) ?
- sizeof (ipha_t) : sizeof (ip6_t));
-}
-#else
-#define ipsec_inbound_debug_tag(x) /* NOP */
-#endif /* DEBUG */
-
/*
* Used to send an ICMP error message when a packet is received for
* a protocol that is not supported. The mblk passed as argument
@@ -5442,6 +5641,7 @@
uint32_t ill_index;
conn_t *connp, *first_connp, *next_connp;
connf_t *connfp;
+ boolean_t shared_addr;
if (mctl_present) {
mp = first_mp->b_cont;
@@ -5458,12 +5658,25 @@
one_only = ((protocol == IPPROTO_ENCAP || protocol == IPPROTO_IPV6) &&
!CLASSD(dst));
+ shared_addr = (zoneid == ALL_ZONES);
+ if (shared_addr) {
+ /*
+ * We don't allow multilevel ports for raw IP, so no need to
+ * check for that here.
+ */
+ zoneid = tsol_packet_to_zoneid(mp);
+ }
+
connfp = &ipcl_proto_fanout[protocol];
mutex_enter(&connfp->connf_lock);
connp = connfp->connf_head;
for (connp = connfp->connf_head; connp != NULL;
connp = connp->conn_next) {
- if (IPCL_PROTO_MATCH(connp, protocol, ipha, ill, flags, zoneid))
+ if (IPCL_PROTO_MATCH(connp, protocol, ipha, ill, flags,
+ zoneid) &&
+ (!is_system_labeled() ||
+ tsol_receive_local(mp, &dst, IPV4_VERSION, shared_addr,
+ connp)))
break;
}
@@ -5518,7 +5731,10 @@
for (;;) {
while (connp != NULL) {
if (IPCL_PROTO_MATCH(connp, protocol, ipha, ill,
- flags, zoneid))
+ flags, zoneid) &&
+ (!is_system_labeled() ||
+ tsol_receive_local(mp, &dst, IPV4_VERSION,
+ shared_addr, connp)))
break;
connp = connp->conn_next;
}
@@ -5704,6 +5920,8 @@
return;
}
BUMP_MIB(&ip_mib, ipInDelivers);
+ ip2dbg(("ip_fanout_tcp: no listener; send reset to zone %d\n",
+ zoneid));
tcp_xmit_listeners_reset(first_mp, ip_hdr_len);
return;
}
@@ -5956,6 +6174,7 @@
ipaddr_t src;
zoneid_t last_zoneid;
boolean_t reuseaddr;
+ boolean_t shared_addr;
first_mp = mp;
if (mctl_present) {
@@ -5974,6 +6193,13 @@
dst = ipha->ipha_dst;
src = ipha->ipha_src;
+ shared_addr = (zoneid == ALL_ZONES);
+ if (shared_addr) {
+ zoneid = tsol_mlp_findzone(IPPROTO_UDP, dstport);
+ if (zoneid == ALL_ZONES)
+ zoneid = tsol_packet_to_zoneid(mp);
+ }
+
connfp = &ipcl_udp_fanout[IPCL_UDP_HASH(dstport)];
mutex_enter(&connfp->connf_lock);
connp = connfp->connf_head;
@@ -5992,6 +6218,12 @@
if (connp == NULL || connp->conn_upq == NULL)
goto notfound;
+
+ if (is_system_labeled() &&
+ !tsol_receive_local(mp, &dst, IPV4_VERSION, shared_addr,
+ connp))
+ goto notfound;
+
CONN_INC_REF(connp);
mutex_exit(&connfp->connf_lock);
ip_fanout_udp_conn(connp, first_mp, mp, secure, ipha, flags,
@@ -6012,7 +6244,10 @@
while (connp != NULL) {
if ((IPCL_UDP_MATCH(connp, dstport, dst, srcport, src)) &&
- conn_wantpacket(connp, ill, ipha, flags, zoneid))
+ conn_wantpacket(connp, ill, ipha, flags, zoneid) &&
+ (!is_system_labeled() ||
+ tsol_receive_local(mp, &dst, IPV4_VERSION, shared_addr,
+ connp)))
break;
connp = connp->conn_next;
}
@@ -6034,7 +6269,10 @@
while (connp != NULL) {
if (IPCL_UDP_MATCH(connp, dstport, dst, srcport, src) &&
(reuseaddr || connp->conn_zoneid != last_zoneid) &&
- conn_wantpacket(connp, ill, ipha, flags, zoneid))
+ conn_wantpacket(connp, ill, ipha, flags, zoneid) &&
+ (!is_system_labeled() ||
+ tsol_receive_local(mp, &dst, IPV4_VERSION,
+ shared_addr, connp)))
break;
connp = connp->conn_next;
}
@@ -6127,6 +6365,11 @@
connp = connp->conn_next;
}
+ if (connp != NULL && is_system_labeled() &&
+ !tsol_receive_local(mp, &dst, IPV4_VERSION, shared_addr,
+ connp))
+ connp = NULL;
+
if (connp == NULL || connp->conn_upq == NULL) {
/*
* No one bound to this port. Is
@@ -6153,6 +6396,7 @@
}
return;
}
+
CONN_INC_REF(connp);
mutex_exit(&connfp->connf_lock);
ip_fanout_udp_conn(connp, first_mp, mp, secure, ipha, flags,
@@ -6172,7 +6416,10 @@
while (connp != NULL) {
if (IPCL_UDP_MATCH_V6(connp, dstport, ipv6_all_zeros,
srcport, v6src) &&
- conn_wantpacket(connp, ill, ipha, flags, zoneid))
+ conn_wantpacket(connp, ill, ipha, flags, zoneid) &&
+ (!is_system_labeled() ||
+ tsol_receive_local(mp, &dst, IPV4_VERSION, shared_addr,
+ connp)))
break;
connp = connp->conn_next;
}
@@ -6214,7 +6461,10 @@
while (connp != NULL) {
if (IPCL_UDP_MATCH_V6(connp, dstport,
ipv6_all_zeros, srcport, v6src) &&
- conn_wantpacket(connp, ill, ipha, flags, zoneid))
+ conn_wantpacket(connp, ill, ipha, flags, zoneid) &&
+ (!is_system_labeled() ||
+ tsol_receive_local(mp, &dst, IPV4_VERSION,
+ shared_addr, connp)))
break;
connp = connp->conn_next;
}
@@ -6378,7 +6628,7 @@
* for source route?
*/
ire = ire_ctable_lookup(dst, 0, IRE_LOCAL, NULL,
- ALL_ZONES, MATCH_IRE_TYPE);
+ ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (ire != NULL) {
ire_refrele(ire);
off += IP_ADDR_LEN;
@@ -6746,6 +6996,9 @@
boolean_t do_attach_ill = B_FALSE;
boolean_t ip_nexthop = B_FALSE;
zoneid_t zoneid;
+ tsol_ire_gw_secattr_t *attrp = NULL;
+ tsol_gcgrp_t *gcgrp = NULL;
+ tsol_gcgrp_addr_t ga;
if (ip_debug > 2) {
/* ip1dbg */
@@ -6835,23 +7088,26 @@
* nexthop address and create an IRE_CACHE entry for the
* destination address via the specified nexthop.
*/
- ire = ire_cache_lookup(nexthop_addr, zoneid);
+ ire = ire_cache_lookup(nexthop_addr, zoneid,
+ MBLK_GETLABEL(mp));
if (ire != NULL) {
gw = nexthop_addr;
ire_marks |= IRE_MARK_PRIVATE_ADDR;
} else {
ire = ire_ftable_lookup(nexthop_addr, 0, 0,
IRE_INTERFACE, NULL, NULL, zoneid, 0,
- MATCH_IRE_TYPE);
+ MBLK_GETLABEL(mp),
+ MATCH_IRE_TYPE | MATCH_IRE_SECATTR);
if (ire != NULL) {
dst = nexthop_addr;
}
}
} else if (attach_ill == NULL) {
ire = ire_ftable_lookup(dst, 0, 0, 0,
- NULL, &sire, zoneid, 0,
+ NULL, &sire, zoneid, 0, MBLK_GETLABEL(mp),
MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT |
- MATCH_IRE_RJ_BHOLE | MATCH_IRE_PARENT);
+ MATCH_IRE_RJ_BHOLE | MATCH_IRE_PARENT |
+ MATCH_IRE_SECATTR);
} else {
/*
* attach_ill is set only for communicating with
@@ -6865,8 +7121,9 @@
goto icmp_err_ret;
}
ire = ire_ftable_lookup(dst, 0, 0, 0, attach_ipif,
- &sire, zoneid, 0,
- MATCH_IRE_RJ_BHOLE | MATCH_IRE_ILL);
+ &sire, zoneid, 0, MBLK_GETLABEL(mp),
+ MATCH_IRE_RJ_BHOLE | MATCH_IRE_ILL |
+ MATCH_IRE_SECATTR);
ipif_refrele(attach_ipif);
}
ip3dbg(("ip_newroute: ire_ftable_lookup() "
@@ -6906,7 +7163,8 @@
ASSERT(sire != NULL);
multirt_is_resolvable =
- ire_multirt_lookup(&ire, &sire, multirt_flags);
+ ire_multirt_lookup(&ire, &sire, multirt_flags,
+ MBLK_GETLABEL(mp));
ip3dbg(("ip_newroute: multirt_is_resolvable %d, "
"ire %p, sire %p\n",
@@ -7152,7 +7410,8 @@
ire_marks |= IRE_MARK_USESRC_CHECK;
if ((dst_ill->ill_group != NULL) ||
(ire->ire_ipif->ipif_flags & IPIF_DEPRECATED) ||
- (connp != NULL && ire->ire_zoneid != zoneid) ||
+ (connp != NULL && ire->ire_zoneid != zoneid &&
+ ire->ire_zoneid != ALL_ZONES) ||
(dst_ill->ill_usesrc_ifindex != 0)) {
/*
* If the destination is reachable via a
@@ -7338,6 +7597,18 @@
if (save_ire->ire_stq == dst_ill->ill_wq)
ire_fp_mp = save_ire->ire_fp_mp;
+ /*
+ * Check cached gateway IRE for any security
+ * attributes; if found, associate the gateway
+ * credentials group to the destination IRE.
+ */
+ if ((attrp = save_ire->ire_gw_secattr) != NULL) {
+ mutex_enter(&attrp->igsa_lock);
+ if ((gcgrp = attrp->igsa_gcgrp) != NULL)
+ GCGRP_REFHOLD(gcgrp);
+ mutex_exit(&attrp->igsa_lock);
+ }
+
ire = ire_create(
(uchar_t *)&dst, /* dest address */
(uchar_t *)&ip_g_all_ones, /* mask */
@@ -7360,13 +7631,23 @@
(sire != NULL) ? (sire->ire_flags &
(RTF_SETSRC | RTF_MULTIRT)) : 0, /* flags */
(sire != NULL) ?
- &(sire->ire_uinfo) : &(save_ire->ire_uinfo));
+ &(sire->ire_uinfo) : &(save_ire->ire_uinfo),
+ NULL,
+ gcgrp);
if (ire == NULL) {
+ if (gcgrp != NULL) {
+ GCGRP_REFRELE(gcgrp);
+ gcgrp = NULL;
+ }
ire_refrele(ipif_ire);
ire_refrele(save_ire);
break;
}
+
+ /* reference now held by IRE */
+ gcgrp = NULL;
+
ire->ire_marks |= ire_marks;
/*
@@ -7475,6 +7756,23 @@
break;
}
+ /*
+ * TSol note: We are creating the ire cache for the
+ * destination 'dst'. If 'dst' is offlink, going
+ * through the first hop 'gw', the security attributes
+ * of 'dst' must be set to point to the gateway
+ * credentials of gateway 'gw'. If 'dst' is onlink, it
+ * is possible that 'dst' is a potential gateway that is
+ * referenced by some route that has some security
+ * attributes. Thus in the former case, we need to do a
+ * gcgrp_lookup of 'gw' while in the latter case we
+ * need to do gcgrp_lookup of 'dst' itself.
+ */
+ ga.ga_af = AF_INET;
+ IN6_IPADDR_TO_V4MAPPED(gw != INADDR_ANY ? gw : dst,
+ &ga.ga_addr);
+ gcgrp = gcgrp_lookup(&ga, B_FALSE);
+
ire = ire_create(
(uchar_t *)&dst, /* dest address */
(uchar_t *)&ip_g_all_ones, /* mask */
@@ -7495,16 +7793,25 @@
save_ire->ire_ihandle, /* Interface handle */
(sire != NULL) ? sire->ire_flags &
(RTF_SETSRC | RTF_MULTIRT) : 0, /* flags */
- &(save_ire->ire_uinfo));
+ &(save_ire->ire_uinfo),
+ NULL,
+ gcgrp);
if (dst_ill->ill_phys_addr_length == IP_ADDR_LEN)
freeb(dlureq_mp);
if (ire == NULL) {
+ if (gcgrp != NULL) {
+ GCGRP_REFRELE(gcgrp);
+ gcgrp = NULL;
+ }
ire_refrele(save_ire);
break;
}
+ /* reference now held by IRE */
+ gcgrp = NULL;
+
ire->ire_marks |= ire_marks;
/* Prevent save_ire from getting deleted */
@@ -7587,6 +7894,7 @@
res_mp = dst_ill->ill_resolver_mp;
if (!OK_RESOLVER_MP(res_mp))
break;
+
/*
* To be at this point in the code with a non-zero gw
* means that dst is reachable through a gateway that
@@ -7626,6 +7934,15 @@
dst = gw;
gw = INADDR_ANY;
}
+
+ /*
+ * TSol note: Please see the corresponding note
+ * of the IRE_IF_NORESOLVER case
+ */
+ ga.ga_af = AF_INET;
+ IN6_IPADDR_TO_V4MAPPED(dst, &ga.ga_addr);
+ gcgrp = gcgrp_lookup(&ga, B_FALSE);
+
/*
* We obtain a partial IRE_CACHE which we will pass
* along with the resolver query. When the response
@@ -7651,12 +7968,21 @@
0,
save_ire->ire_ihandle, /* Interface handle */
0, /* flags if any */
- &(save_ire->ire_uinfo));
+ &(save_ire->ire_uinfo),
+ NULL,
+ gcgrp);
if (ire == NULL) {
ire_refrele(save_ire);
- break;
- }
+ if (gcgrp != NULL) {
+ GCGRP_REFRELE(gcgrp);
+ gcgrp = NULL;
+ }
+ break;
+ }
+
+ /* reference now held by IRE */
+ gcgrp = NULL;
if ((sire != NULL) &&
(sire->ire_flags & RTF_MULTIRT)) {
@@ -8065,7 +8391,8 @@
zoneid, NULL, NULL, NULL, NULL);
}
if (((ipif->ipif_flags & IPIF_DEPRECATED) ||
- (connp != NULL && ipif->ipif_zoneid != zoneid)) &&
+ (connp != NULL && ipif->ipif_zoneid != zoneid &&
+ ipif->ipif_zoneid != ALL_ZONES)) &&
(src_ipif == NULL)) {
src_ipif = ipif_select_source(dst_ill, dst, zoneid);
if (src_ipif == NULL) {
@@ -8221,7 +8548,9 @@
(fire->ire_flags &
(RTF_SETSRC | RTF_MULTIRT)) : 0,
(save_ire == NULL ? &ire_uinfo_null :
- &save_ire->ire_uinfo));
+ &save_ire->ire_uinfo),
+ NULL,
+ NULL);
freeb(dlureq_mp);
@@ -8278,7 +8607,8 @@
*/
if ((flags & RTF_MULTIRT) && (copy_mp != NULL)) {
boolean_t need_resolve =
- ire_multirt_need_resolve(ipha_dst);
+ ire_multirt_need_resolve(ipha_dst,
+ MBLK_GETLABEL(copy_mp));
if (!need_resolve) {
MULTIRT_DEBUG_UNTAG(copy_mp);
freemsg(copy_mp);
@@ -8361,7 +8691,9 @@
(fire->ire_flags &
(RTF_SETSRC | RTF_MULTIRT)) : 0,
(save_ire == NULL ? &ire_uinfo_null :
- &save_ire->ire_uinfo));
+ &save_ire->ire_uinfo),
+ NULL,
+ NULL);
if (save_ire != NULL) {
ire_refrele(save_ire);
@@ -8442,7 +8774,8 @@
*/
if ((flags & RTF_MULTIRT) && (copy_mp != NULL)) {
boolean_t need_resolve =
- ire_multirt_need_resolve(ipha_dst);
+ ire_multirt_need_resolve(ipha_dst,
+ MBLK_GETLABEL(copy_mp));
if (!need_resolve) {
MULTIRT_DEBUG_UNTAG(copy_mp);
freemsg(copy_mp);
@@ -8703,11 +9036,18 @@
*devp = makedevice(maj, (minor_t)connp->conn_dev);
/*
- * connp->conn_cred is crfree()ed in ip_close().
+ * connp->conn_cred is crfree()ed in ipcl_conn_destroy()
*/
connp->conn_cred = credp;
crhold(connp->conn_cred);
+ /*
+ * If the caller has the process-wide flag set, then default to MAC
+ * exempt mode. This allows read-down to unlabeled hosts.
+ */
+ if (getpflags(NET_MAC_AWARE, credp) != 0)
+ connp->conn_mac_exempt = B_TRUE;
+
connp->conn_zoneid = getzoneid();
/*
@@ -9576,6 +9916,23 @@
mutex_exit(&connp->conn_lock);
}
break; /* goto sizeof (int) option return */
+ case SO_ANON_MLP:
+ if (!checkonly) {
+ mutex_enter(&connp->conn_lock);
+ connp->conn_anon_mlp = *i1 != 0 ? 1 : 0;
+ mutex_exit(&connp->conn_lock);
+ }
+ break; /* goto sizeof (int) option return */
+ case SO_MAC_EXEMPT:
+ if (secpolicy_net_mac_aware(cr) != 0 ||
+ IPCL_IS_BOUND(connp))
+ return (EACCES);
+ if (!checkonly) {
+ mutex_enter(&connp->conn_lock);
+ connp->conn_mac_exempt = *i1 != 0 ? 1 : 0;
+ mutex_exit(&connp->conn_lock);
+ }
+ break; /* goto sizeof (int) option return */
default:
/*
* "soft" error (negative)
@@ -9674,7 +10031,7 @@
* operation succeeds on at least one interface.
*/
ire = ire_ftable_lookup(group, IP_HOST_MASK, 0,
- IRE_HOST, NULL, NULL, ALL_ZONES, 0,
+ IRE_HOST, NULL, NULL, ALL_ZONES, 0, NULL,
MATCH_IRE_MASK | MATCH_IRE_TYPE);
if (ire != NULL) {
if (ire->ire_flags & RTF_MULTIRT) {
@@ -9782,7 +10139,7 @@
* the request as noted in the mcast cases above.
*/
ire = ire_ftable_lookup(grp, IP_HOST_MASK, 0,
- IRE_HOST, NULL, NULL, ALL_ZONES, 0,
+ IRE_HOST, NULL, NULL, ALL_ZONES, 0, NULL,
MATCH_IRE_MASK | MATCH_IRE_TYPE);
if (ire != NULL) {
if (ire->ire_flags & RTF_MULTIRT) {
@@ -10008,7 +10365,7 @@
* the operation succeeds on at least one interface.
*/
ire = ire_ftable_lookup_v6(&groupv6, &ipv6_all_ones, 0,
- IRE_HOST, NULL, NULL, ALL_ZONES, 0,
+ IRE_HOST, NULL, NULL, ALL_ZONES, 0, NULL,
MATCH_IRE_MASK | MATCH_IRE_TYPE);
if (ire != NULL) {
if (ire->ire_flags & RTF_MULTIRT) {
@@ -10094,7 +10451,7 @@
* the request as noted in the mcast cases above.
*/
ire = ire_ftable_lookup_v6(&v6grp, &ipv6_all_ones, 0,
- IRE_HOST, NULL, NULL, ALL_ZONES, 0,
+ IRE_HOST, NULL, NULL, ALL_ZONES, 0, NULL,
MATCH_IRE_MASK | MATCH_IRE_TYPE);
if (ire != NULL) {
if (ire->ire_flags & RTF_MULTIRT) {
@@ -10218,7 +10575,7 @@
sin6 = (struct sockaddr_in6 *)invalp;
ire = ire_route_lookup_v6(&sin6->sin6_addr,
0, 0, 0, NULL, NULL, connp->conn_zoneid,
- MATCH_IRE_DEFAULT);
+ NULL, MATCH_IRE_DEFAULT);
if (ire == NULL) {
*outlenp = 0;
@@ -10353,7 +10710,7 @@
mtuinfo->ip6m_addr.sin6_port = port;
mtuinfo->ip6m_addr.sin6_addr = *in6;
- ire = ire_cache_lookup_v6(in6, ALL_ZONES);
+ ire = ire_cache_lookup_v6(in6, ALL_ZONES, NULL);
if (ire != NULL) {
mtuinfo->ip6m_mtu = ire->ire_max_frag;
ire_refrele(ire);
@@ -12053,7 +12410,6 @@
first_mp = mp;
}
-tcp_slow:
/* Now we have a complete datagram, destined for this machine. */
u1 = ip_hdr_len = IPH_HDR_LENGTH(ipha);
@@ -12253,8 +12609,8 @@
IRE_REFRELE(ire);
IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &map_dst);
IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &map_src);
- if ((connp = sctp_find_conn(&map_src, &map_dst, ports, ipif_seqid,
- zoneid)) == NULL) {
+ if ((connp = sctp_fanout(&map_src, &map_dst, ports, ipif_seqid, zoneid,
+ mp)) == NULL) {
/* Check for raw socket or OOTB handling */
goto no_conn;
}
@@ -12632,7 +12988,7 @@
src = ipha->ipha_src;
src_ire = ire_ftable_lookup(src, 0, 0,
IRE_INTERFACE, ire->ire_ipif, NULL, ALL_ZONES,
- 0, MATCH_IRE_IPIF | MATCH_IRE_TYPE);
+ 0, NULL, MATCH_IRE_IPIF | MATCH_IRE_TYPE);
if (src_ire != NULL) {
/*
@@ -12723,7 +13079,7 @@
return (B_TRUE);
}
new_ire = ire_ctable_lookup(dst, 0, 0,
- ipif, ALL_ZONES, MATCH_IRE_ILL);
+ ipif, ALL_ZONES, NULL, MATCH_IRE_ILL);
ipif_refrele(ipif);
if (new_ire != NULL) {
@@ -13398,6 +13754,16 @@
continue;
}
+ /*
+ * Attach any necessary label information to this packet.
+ */
+ if (is_system_labeled() &&
+ !tsol_get_pkt_label(mp, IPV4_VERSION)) {
+ BUMP_MIB(&ip_mib, ipInDiscards);
+ freemsg(mp);
+ continue;
+ }
+
opt_len = ipha->ipha_version_and_hdr_length -
IP_SIMPLE_HDR_VERSION;
/* IP version bad or there are IP options */
@@ -13461,8 +13827,10 @@
}
}
- if (ire == NULL)
- ire = ire_cache_lookup(dst, ALL_ZONES);
+ if (ire == NULL) {
+ ire = ire_cache_lookup(dst, ALL_ZONES,
+ MBLK_GETLABEL(mp));
+ }
/*
* If mipagent is running and reverse tunnel is created as per
@@ -14927,6 +15295,19 @@
/* Get the ill_index of the outgoing ILL */
ill_index = ire->ire_ipif->ipif_ill->ill_phyint->phyint_ifindex;
+ if (is_system_labeled()) {
+ mblk_t *mp1;
+
+ if ((mp1 = tsol_ip_forward(ire, mp)) == NULL) {
+ BUMP_MIB(&ip_mib, ipForwProhibits);
+ goto drop_pkt;
+ }
+ /* Size may have changed */
+ mp = mp1;
+ ipha = (ipha_t *)mp->b_rptr;
+ pkt_len = ntohs(ipha->ipha_length);
+ }
+
/* Check if there are options to update */
if (!IS_SIMPLE_IPH(ipha)) {
if (ip_csum_hdr(ipha)) {
@@ -14999,9 +15380,9 @@
*/
if (ipif->ipif_flags & IPIF_POINTOPOINT)
dst = ipif->ipif_pp_dst_addr;
- ire = ire_ctable_lookup(dst, 0, 0, ipif, ALL_ZONES,
- MATCH_IRE_ILL_GROUP);
- if (!ire) {
+ ire = ire_ctable_lookup(dst, 0, 0, ipif, ALL_ZONES, MBLK_GETLABEL(mp),
+ MATCH_IRE_ILL_GROUP | MATCH_IRE_SECATTR);
+ if (ire == NULL) {
/*
* Mark this packet to make it be delivered to
* ip_rput_forward after the new ire has been
@@ -15060,7 +15441,7 @@
}
dst_ire = ire_ctable_lookup(dst, 0, IRE_LOCAL,
- NULL, ALL_ZONES, MATCH_IRE_TYPE);
+ NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (dst_ire == NULL) {
/*
* Must be partial since ip_rput_options
@@ -15090,7 +15471,7 @@
* once as consecutive hops in source route.
*/
tmp_ire = ire_ctable_lookup(dst, 0, IRE_LOCAL,
- NULL, ALL_ZONES, MATCH_IRE_TYPE);
+ NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (tmp_ire != NULL) {
ire_refrele(tmp_ire);
off += IP_ADDR_LEN;
@@ -15127,7 +15508,9 @@
off = opt[IPOPT_OFFSET] - 1;
bcopy((char *)opt + off, &dst, IP_ADDR_LEN);
dst_ire = ire_ctable_lookup(dst, 0,
- IRE_LOCAL, NULL, ALL_ZONES, MATCH_IRE_TYPE);
+ IRE_LOCAL, NULL, ALL_ZONES, NULL,
+ MATCH_IRE_TYPE);
+
if (dst_ire == NULL) {
/* Not for us */
break;
@@ -15304,7 +15687,8 @@
}
if (ire == NULL) {
- ire = ire_cache_lookup(dst, ii->ipsec_in_zoneid);
+ ire = ire_cache_lookup(dst, ii->ipsec_in_zoneid,
+ MBLK_GETLABEL(mp));
if (ire == NULL) {
if (ill_need_rele)
ill_refrele(ill);
@@ -15621,6 +16005,7 @@
ipha->ipha_dst != ilm->ilm_addr ||
ilm->ilm_zoneid == last_zoneid ||
ilm->ilm_zoneid == ire->ire_zoneid ||
+ ilm->ilm_zoneid == ALL_ZONES ||
!(ilm->ilm_ipif->ipif_flags & IPIF_UP))
continue;
mp1 = ip_copymsg(first_mp);
@@ -15676,6 +16061,12 @@
if (first_mp == NULL)
return;
}
+ if (is_system_labeled() && !tsol_can_accept_raw(mp, B_TRUE)) {
+ freemsg(first_mp);
+ ip1dbg(("ip_proto_input: zone all cannot accept raw"));
+ BUMP_MIB(&ip_mib, ipInDiscards);
+ return;
+ }
if (igmp_input(q, mp, ill)) {
/* Bad packet - discarded by igmp_input */
TRACE_2(TR_FAC_IP, TR_IP_RPUT_LOCL_END,
@@ -15706,6 +16097,12 @@
if (first_mp == NULL)
return;
}
+ if (is_system_labeled() && !tsol_can_accept_raw(mp, B_TRUE)) {
+ freemsg(first_mp);
+ ip1dbg(("ip_proto_input: zone all cannot accept PIM"));
+ BUMP_MIB(&ip_mib, ipInDiscards);
+ return;
+ }
if (pim_input(q, mp) != 0) {
/* Bad packet - discarded by pim_input */
TRACE_2(TR_FAC_IP, TR_IP_RPUT_LOCL_END,
@@ -15916,6 +16313,11 @@
default:
break;
}
+ if (is_system_labeled() && !tsol_can_accept_raw(mp, B_FALSE)) {
+ ip1dbg(("ip_proto_input: zone %d cannot accept raw IP",
+ ire->ire_zoneid));
+ goto drop_pkt;
+ }
/*
* Handle protocols with which IP is less intimate. There
* can be more than one stream bound to a particular
@@ -16027,7 +16429,7 @@
off = opt[IPOPT_OFFSET] - 1;
bcopy((char *)opt + off, &dst, IP_ADDR_LEN);
dst_ire = ire_ctable_lookup(dst, 0, IRE_LOCAL,
- NULL, ALL_ZONES, MATCH_IRE_TYPE);
+ NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (dst_ire == NULL) {
/* Not for us */
break;
@@ -16123,7 +16525,7 @@
case IPOPT_SSRR:
case IPOPT_LSRR:
ire = ire_ctable_lookup(dst, 0, IRE_LOCAL, NULL,
- ALL_ZONES, MATCH_IRE_TYPE);
+ ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (ire == NULL) {
if (optval == IPOPT_SSRR) {
ip1dbg(("ip_rput_options: not next"
@@ -16167,7 +16569,7 @@
* for source route?
*/
ire = ire_ctable_lookup(dst, 0, IRE_LOCAL, NULL,
- ALL_ZONES, MATCH_IRE_TYPE);
+ ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (ire != NULL) {
ire_refrele(ire);
@@ -16187,7 +16589,8 @@
if (optval == IPOPT_SSRR) {
ire = ire_ftable_lookup(dst, 0, 0,
IRE_INTERFACE, NULL, NULL, ALL_ZONES, 0,
- MATCH_IRE_TYPE);
+ MBLK_GETLABEL(mp),
+ MATCH_IRE_TYPE | MATCH_IRE_SECATTR);
if (ire == NULL) {
ip1dbg(("ip_rput_options: SSRR not "
"directly reachable: 0x%x\n",
@@ -16283,6 +16686,7 @@
* - ipAddrEntryTable (ip 20) all IPv4 ipifs
* - ipRouteEntryTable (ip 21) all IPv4 IREs
* - ipNetToMediaEntryTable (ip 22) IPv4 IREs for on-link destinations
+ * - ipRouteAttributeTable (ip 102) labeled routes
* - ip multicast membership (ip_member_t)
* - ip multicast source filtering (ip_grpsrc_t)
* - igmp fixed part (struct igmpstat)
@@ -16294,6 +16698,7 @@
* - icmp6 fixed part (mib2_ipv6IfIcmpEntry_t)
* One per ill plus one generic
* - ipv6RouteEntry all IPv6 IREs
+ * - ipv6RouteAttributeTable (ip6 102) labeled routes
* - ipv6NetToMediaEntry all Neighbor Cache entries
* - ipv6AddrEntry all IPv6 ipifs
* - ipv6 multicast membership (ipv6_member_t)
@@ -16301,8 +16706,8 @@
*
* IP_ROUTE and IP_MEDIA are augmented in arp to include arp cache entries not
* already present.
- * NOTE: original mpctl is copied for msg's 2..N, since its ctl part
- * already filled in by caller.
+ * NOTE: original mpctl is copied for msg's 2..N, since its ctl part is
+ * already filled in by the caller.
* Return value of 0 indicates that no messages were sent and caller
* should free mpctl.
*/
@@ -16416,6 +16821,8 @@
sizeof (mib2_ipNetToMediaEntry_t));
SET_MIB(ip_mib.ipMemberEntrySize, sizeof (ip_member_t));
SET_MIB(ip_mib.ipGroupSourceEntrySize, sizeof (ip_grpsrc_t));
+ SET_MIB(ip_mib.ipRouteAttributeSize, sizeof (mib2_ipAttributeEntry_t));
+ SET_MIB(ip_mib.transportMLPSize, sizeof (mib2_transportMLPEntry_t));
if (!snmp_append_data(mpctl->b_cont, (char *)&ip_mib,
(int)sizeof (ip_mib))) {
ip1dbg(("ip_snmp_get_mib2_ip: failed to allocate %u bytes\n",
@@ -16539,7 +16946,8 @@
for (; ill != NULL; ill = ill_next(&ctx, ill)) {
for (ipif = ill->ill_ipif; ipif != NULL;
ipif = ipif->ipif_next) {
- if (ipif->ipif_zoneid != zoneid)
+ if (ipif->ipif_zoneid != zoneid &&
+ ipif->ipif_zoneid != ALL_ZONES)
continue;
mae.ipAdEntInfo.ae_ibcnt = ipif->ipif_ib_pkt_count;
mae.ipAdEntInfo.ae_obcnt = ipif->ipif_ob_pkt_count;
@@ -16618,7 +17026,8 @@
ill = ILL_START_WALK_V6(&ctx);
for (; ill != NULL; ill = ill_next(&ctx, ill)) {
for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
- if (ipif->ipif_zoneid != zoneid)
+ if (ipif->ipif_zoneid != zoneid &&
+ ipif->ipif_zoneid != ALL_ZONES)
continue;
mae6.ipv6AddrInfo.ae_ibcnt = ipif->ipif_ib_pkt_count;
mae6.ipv6AddrInfo.ae_obcnt = ipif->ipif_ob_pkt_count;
@@ -16714,7 +17123,8 @@
ILM_WALKER_HOLD(ill);
for (ipif = ill->ill_ipif; ipif != NULL;
ipif = ipif->ipif_next) {
- if (ipif->ipif_zoneid != zoneid)
+ if (ipif->ipif_zoneid != zoneid &&
+ ipif->ipif_zoneid != ALL_ZONES)
continue; /* not this zone */
(void) ipif_get_name(ipif,
ipm.ipGroupMemberIfIndex.o_bytes,
@@ -16989,60 +17399,60 @@
}
/*
- * Return both ipRouteEntryTable, and ipNetToMediaEntryTable
+ * Return ipRouteEntryTable, ipNetToMediaEntryTable, and ipRouteAttributeTable
* in one IRE walk.
*/
static mblk_t *
ip_snmp_get_mib2_ip_route_media(queue_t *q, mblk_t *mpctl)
{
- struct opthdr *optp;
- mblk_t *mp2ctl; /* Returned */
- mblk_t *mp3ctl; /* nettomedia */
- /*
- * We need two listptrs, for ipRouteEntryTable and
- * ipNetToMediaEntryTable to pass to ip_snmp_get2_v4()
- */
- listptr_t re_ntme_v4[2];
- zoneid_t zoneid;
-
- /*
- * make a copy of the original message
+ struct opthdr *optp;
+ mblk_t *mp2ctl; /* Returned */
+ mblk_t *mp3ctl; /* nettomedia */
+ mblk_t *mp4ctl; /* routeattrs */
+ iproutedata_t ird;
+ zoneid_t zoneid;
+
+ /*
+ * make copies of the original message
+ * - mp2ctl is returned unchanged to the caller for his use
+ * - mpctl is sent upstream as ipRouteEntryTable
+ * - mp3ctl is sent upstream as ipNetToMediaEntryTable
+ * - mp4ctl is sent upstream as ipRouteAttributeTable
*/
mp2ctl = copymsg(mpctl);
mp3ctl = copymsg(mpctl);
- if (mp3ctl == NULL) {
+ mp4ctl = copymsg(mpctl);
+ if (mp3ctl == NULL || mp4ctl == NULL) {
+ freemsg(mp4ctl);
+ freemsg(mp3ctl);
freemsg(mp2ctl);
freemsg(mpctl);
return (NULL);
}
- re_ntme_v4[0].lp_head = mpctl->b_cont; /* ipRouteEntryTable */
- re_ntme_v4[1].lp_head = mp3ctl->b_cont; /* ipNetToMediaEntryTable */
- /*
- * We assign NULL to tail ptrs as snmp_append_data2() will assign
- * proper values when called.
- */
- re_ntme_v4[0].lp_tail = NULL;
- re_ntme_v4[1].lp_tail = NULL;
+ bzero(&ird, sizeof (ird));
+
+ ird.ird_route.lp_head = mpctl->b_cont;
+ ird.ird_netmedia.lp_head = mp3ctl->b_cont;
+ ird.ird_attrs.lp_head = mp4ctl->b_cont;
zoneid = Q_TO_CONN(q)->conn_zoneid;
- ire_walk_v4(ip_snmp_get2_v4, (char *)re_ntme_v4, zoneid);
+ ire_walk_v4(ip_snmp_get2_v4, &ird, zoneid);
if (zoneid == GLOBAL_ZONEID) {
/*
* Those IREs are used by Mobile-IP; since mipagent(1M) requires
* the sys_net_config privilege, it can only run in the global
* zone, so we don't display these IREs in the other zones.
*/
- ire_walk_srcif_table_v4(ip_snmp_get2_v4, (char *)re_ntme_v4);
- ire_walk_ill_mrtun(0, 0, ip_snmp_get2_v4, (char *)re_ntme_v4,
- NULL);
+ ire_walk_srcif_table_v4(ip_snmp_get2_v4, &ird);
+ ire_walk_ill_mrtun(0, 0, ip_snmp_get2_v4, &ird, NULL);
}
/* ipRouteEntryTable in mpctl */
optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)];
optp->level = MIB2_IP;
optp->name = MIB2_IP_ROUTE;
- optp->len = (t_uscalar_t)msgdsize(re_ntme_v4[0].lp_head);
+ optp->len = msgdsize(ird.ird_route.lp_head);
ip3dbg(("ip_snmp_get_mib2_ip_route_media: level %d, name %d, len %d\n",
(int)optp->level, (int)optp->name, (int)optp->len));
qreply(q, mpctl);
@@ -17051,67 +17461,98 @@
optp = (struct opthdr *)&mp3ctl->b_rptr[sizeof (struct T_optmgmt_ack)];
optp->level = MIB2_IP;
optp->name = MIB2_IP_MEDIA;
- optp->len = (t_uscalar_t)msgdsize(re_ntme_v4[1].lp_head);
+ optp->len = msgdsize(ird.ird_netmedia.lp_head);
ip3dbg(("ip_snmp_get_mib2_ip_route_media: level %d, name %d, len %d\n",
(int)optp->level, (int)optp->name, (int)optp->len));
qreply(q, mp3ctl);
+
+ /* ipRouteAttributeTable in mp4ctl */
+ optp = (struct opthdr *)&mp4ctl->b_rptr[sizeof (struct T_optmgmt_ack)];
+ optp->level = MIB2_IP;
+ optp->name = EXPER_IP_RTATTR;
+ optp->len = msgdsize(ird.ird_attrs.lp_head);
+ ip3dbg(("ip_snmp_get_mib2_ip_route_media: level %d, name %d, len %d\n",
+ (int)optp->level, (int)optp->name, (int)optp->len));
+ if (optp->len == 0)
+ freemsg(mp4ctl);
+ else
+ qreply(q, mp4ctl);
+
return (mp2ctl);
}
/*
- * Return both ipv6RouteEntryTable, and ipv6NetToMediaEntryTable
- * in one IRE walk.
+ * Return ipv6RouteEntryTable and ipv6RouteAttributeTable in one IRE walk, and
+ * ipv6NetToMediaEntryTable in an NDP walk.
*/
static mblk_t *
ip_snmp_get_mib2_ip6_route_media(queue_t *q, mblk_t *mpctl)
{
- struct opthdr *optp;
- mblk_t *mp2ctl; /* Returned */
- mblk_t *mp3ctl; /* nettomedia */
- listptr_t re_ntme_v6;
- zoneid_t zoneid;
-
- /*
- * make a copy of the original message
+ struct opthdr *optp;
+ mblk_t *mp2ctl; /* Returned */
+ mblk_t *mp3ctl; /* nettomedia */
+ mblk_t *mp4ctl; /* routeattrs */
+ iproutedata_t ird;
+ zoneid_t zoneid;
+
+ /*
+ * make copies of the original message
+ * - mp2ctl is returned unchanged to the caller for his use
+ * - mpctl is sent upstream as ipv6RouteEntryTable
+ * - mp3ctl is sent upstream as ipv6NetToMediaEntryTable
+ * - mp4ctl is sent upstream as ipv6RouteAttributeTable
*/
mp2ctl = copymsg(mpctl);
mp3ctl = copymsg(mpctl);
- if (mp3ctl == NULL) {
+ mp4ctl = copymsg(mpctl);
+ if (mp3ctl == NULL || mp4ctl == NULL) {
+ freemsg(mp4ctl);
+ freemsg(mp3ctl);
freemsg(mp2ctl);
freemsg(mpctl);
return (NULL);
}
- /*
- * We assign NULL to tail ptrs as snmp_append_data2() will assign
- * proper values when called. ipv6RouteEntryTable in is placed
- * in mpctl.
- */
- re_ntme_v6.lp_head = mpctl->b_cont; /* ip6RouteEntryTable */
- re_ntme_v6.lp_tail = NULL;
+ bzero(&ird, sizeof (ird));
+
+ ird.ird_route.lp_head = mpctl->b_cont;
+ ird.ird_netmedia.lp_head = mp3ctl->b_cont;
+ ird.ird_attrs.lp_head = mp4ctl->b_cont;
+
zoneid = Q_TO_CONN(q)->conn_zoneid;
- ire_walk_v6(ip_snmp_get2_v6_route, (char *)&re_ntme_v6, zoneid);
+ ire_walk_v6(ip_snmp_get2_v6_route, &ird, zoneid);
optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)];
optp->level = MIB2_IP6;
optp->name = MIB2_IP6_ROUTE;
- optp->len = (t_uscalar_t)msgdsize(re_ntme_v6.lp_head);
+ optp->len = msgdsize(ird.ird_route.lp_head);
ip3dbg(("ip_snmp_get_mib2_ip6_route_media: level %d, name %d, len %d\n",
(int)optp->level, (int)optp->name, (int)optp->len));
qreply(q, mpctl);
/* ipv6NetToMediaEntryTable in mp3ctl */
- re_ntme_v6.lp_head = mp3ctl->b_cont; /* ip6NetToMediaEntryTable */
- re_ntme_v6.lp_tail = NULL;
- ndp_walk(NULL, ip_snmp_get2_v6_media, (uchar_t *)&re_ntme_v6);
+ ndp_walk(NULL, ip_snmp_get2_v6_media, &ird);
optp = (struct opthdr *)&mp3ctl->b_rptr[sizeof (struct T_optmgmt_ack)];
optp->level = MIB2_IP6;
optp->name = MIB2_IP6_MEDIA;
- optp->len = (t_uscalar_t)msgdsize(re_ntme_v6.lp_head);
+ optp->len = msgdsize(ird.ird_netmedia.lp_head);
ip3dbg(("ip_snmp_get_mib2_ip6_route_media: level %d, name %d, len %d\n",
(int)optp->level, (int)optp->name, (int)optp->len));
qreply(q, mp3ctl);
+
+ /* ipv6RouteAttributeTable in mp4ctl */
+ optp = (struct opthdr *)&mp4ctl->b_rptr[sizeof (struct T_optmgmt_ack)];
+ optp->level = MIB2_IP6;
+ optp->name = EXPER_IP_RTATTR;
+ optp->len = msgdsize(ird.ird_attrs.lp_head);
+ ip3dbg(("ip_snmp_get_mib2_ip6_route_media: level %d, name %d, len %d\n",
+ (int)optp->level, (int)optp->name, (int)optp->len));
+ if (optp->len == 0)
+ freemsg(mp4ctl);
+ else
+ qreply(q, mp4ctl);
+
return (mp2ctl);
}
@@ -17251,85 +17692,144 @@
* ipNetToMediaEntryTable in one IRE walk
*/
static void
-ip_snmp_get2_v4(ire_t *ire, listptr_t re_ntme[])
+ip_snmp_get2_v4(ire_t *ire, iproutedata_t *ird)
{
ill_t *ill;
ipif_t *ipif;
mblk_t *llmp;
dl_unitdata_req_t *dlup;
- mib2_ipRouteEntry_t re;
+ mib2_ipRouteEntry_t *re;
mib2_ipNetToMediaEntry_t ntme;
+ mib2_ipAttributeEntry_t *iae, *iaeptr;
ipaddr_t gw_addr;
+ tsol_ire_gw_secattr_t *attrp;
+ tsol_gc_t *gc = NULL;
+ tsol_gcgrp_t *gcgrp = NULL;
+ uint_t sacnt = 0;
+ int i;
ASSERT(ire->ire_ipversion == IPV4_VERSION);
+ if ((re = kmem_zalloc(sizeof (*re), KM_NOSLEEP)) == NULL)
+ return;
+
+ if ((attrp = ire->ire_gw_secattr) != NULL) {
+ mutex_enter(&attrp->igsa_lock);
+ if ((gc = attrp->igsa_gc) != NULL) {
+ gcgrp = gc->gc_grp;
+ ASSERT(gcgrp != NULL);
+ rw_enter(&gcgrp->gcgrp_rwlock, RW_READER);
+ sacnt = 1;
+ } else if ((gcgrp = attrp->igsa_gcgrp) != NULL) {
+ rw_enter(&gcgrp->gcgrp_rwlock, RW_READER);
+ gc = gcgrp->gcgrp_head;
+ sacnt = gcgrp->gcgrp_count;
+ }
+ mutex_exit(&attrp->igsa_lock);
+
+ /* do nothing if there's no gc to report */
+ if (gc == NULL) {
+ ASSERT(sacnt == 0);
+ if (gcgrp != NULL) {
+ /* we might as well drop the lock now */
+ rw_exit(&gcgrp->gcgrp_rwlock);
+ gcgrp = NULL;
+ }
+ attrp = NULL;
+ }
+
+ ASSERT(gc == NULL || (gcgrp != NULL &&
+ RW_LOCK_HELD(&gcgrp->gcgrp_rwlock)));
+ }
+ ASSERT(sacnt == 0 || gc != NULL);
+
+ if (sacnt != 0 &&
+ (iae = kmem_alloc(sacnt * sizeof (*iae), KM_NOSLEEP)) == NULL) {
+ kmem_free(re, sizeof (*re));
+ rw_exit(&gcgrp->gcgrp_rwlock);
+ return;
+ }
+
/*
* Return all IRE types for route table... let caller pick and choose
*/
- re.ipRouteDest = ire->ire_addr;
+ re->ipRouteDest = ire->ire_addr;
ipif = ire->ire_ipif;
- re.ipRouteIfIndex.o_length = 0;
+ re->ipRouteIfIndex.o_length = 0;
if (ire->ire_type == IRE_CACHE) {
ill = (ill_t *)ire->ire_stq->q_ptr;
- re.ipRouteIfIndex.o_length =
+ re->ipRouteIfIndex.o_length =
ill->ill_name_length == 0 ? 0 :
MIN(OCTET_LENGTH, ill->ill_name_length - 1);
- bcopy(ill->ill_name, re.ipRouteIfIndex.o_bytes,
- re.ipRouteIfIndex.o_length);
+ bcopy(ill->ill_name, re->ipRouteIfIndex.o_bytes,
+ re->ipRouteIfIndex.o_length);
} else if (ipif != NULL) {
- (void) ipif_get_name(ipif, re.ipRouteIfIndex.o_bytes,
+ (void) ipif_get_name(ipif, re->ipRouteIfIndex.o_bytes,
OCTET_LENGTH);
- re.ipRouteIfIndex.o_length =
- mi_strlen(re.ipRouteIfIndex.o_bytes);
- }
- re.ipRouteMetric1 = -1;
- re.ipRouteMetric2 = -1;
- re.ipRouteMetric3 = -1;
- re.ipRouteMetric4 = -1;
+ re->ipRouteIfIndex.o_length =
+ mi_strlen(re->ipRouteIfIndex.o_bytes);
+ }
+ re->ipRouteMetric1 = -1;
+ re->ipRouteMetric2 = -1;
+ re->ipRouteMetric3 = -1;
+ re->ipRouteMetric4 = -1;
gw_addr = ire->ire_gateway_addr;
if (ire->ire_type & (IRE_INTERFACE|IRE_LOOPBACK|IRE_BROADCAST))
- re.ipRouteNextHop = ire->ire_src_addr;
+ re->ipRouteNextHop = ire->ire_src_addr;
else
- re.ipRouteNextHop = gw_addr;
+ re->ipRouteNextHop = gw_addr;
/* indirect(4), direct(3), or invalid(2) */
if (ire->ire_flags & (RTF_REJECT | RTF_BLACKHOLE))
- re.ipRouteType = 2;
+ re->ipRouteType = 2;
else
- re.ipRouteType = (gw_addr != 0) ? 4 : 3;
- re.ipRouteProto = -1;
- re.ipRouteAge = gethrestime_sec() - ire->ire_create_time;
- re.ipRouteMask = ire->ire_mask;
- re.ipRouteMetric5 = -1;
- re.ipRouteInfo.re_max_frag = ire->ire_max_frag;
- re.ipRouteInfo.re_frag_flag = ire->ire_frag_flag;
- re.ipRouteInfo.re_rtt = ire->ire_uinfo.iulp_rtt;
+ re->ipRouteType = (gw_addr != 0) ? 4 : 3;
+ re->ipRouteProto = -1;
+ re->ipRouteAge = gethrestime_sec() - ire->ire_create_time;
+ re->ipRouteMask = ire->ire_mask;
+ re->ipRouteMetric5 = -1;
+ re->ipRouteInfo.re_max_frag = ire->ire_max_frag;
+ re->ipRouteInfo.re_frag_flag = ire->ire_frag_flag;
+ re->ipRouteInfo.re_rtt = ire->ire_uinfo.iulp_rtt;
llmp = ire->ire_dlureq_mp;
- re.ipRouteInfo.re_ref = ire->ire_refcnt;
- re.ipRouteInfo.re_src_addr = ire->ire_src_addr;
- re.ipRouteInfo.re_ire_type = ire->ire_type;
- re.ipRouteInfo.re_obpkt = ire->ire_ob_pkt_count;
- re.ipRouteInfo.re_ibpkt = ire->ire_ib_pkt_count;
- re.ipRouteInfo.re_flags = ire->ire_flags;
- re.ipRouteInfo.re_in_ill.o_length = 0;
+ re->ipRouteInfo.re_ref = ire->ire_refcnt;
+ re->ipRouteInfo.re_src_addr = ire->ire_src_addr;
+ re->ipRouteInfo.re_ire_type = ire->ire_type;
+ re->ipRouteInfo.re_obpkt = ire->ire_ob_pkt_count;
+ re->ipRouteInfo.re_ibpkt = ire->ire_ib_pkt_count;
+ re->ipRouteInfo.re_flags = ire->ire_flags;
+ re->ipRouteInfo.re_in_ill.o_length = 0;
if (ire->ire_in_ill != NULL) {
- re.ipRouteInfo.re_in_ill.o_length =
+ re->ipRouteInfo.re_in_ill.o_length =
ire->ire_in_ill->ill_name_length == 0 ? 0 :
MIN(OCTET_LENGTH, ire->ire_in_ill->ill_name_length - 1);
bcopy(ire->ire_in_ill->ill_name,
- re.ipRouteInfo.re_in_ill.o_bytes,
- re.ipRouteInfo.re_in_ill.o_length);
- }
- re.ipRouteInfo.re_in_src_addr = ire->ire_in_src_addr;
- if (!snmp_append_data2(re_ntme[0].lp_head, &(re_ntme[0].lp_tail),
- (char *)&re, (int)sizeof (re))) {
+ re->ipRouteInfo.re_in_ill.o_bytes,
+ re->ipRouteInfo.re_in_ill.o_length);
+ }
+ re->ipRouteInfo.re_in_src_addr = ire->ire_in_src_addr;
+
+ if (!snmp_append_data2(ird->ird_route.lp_head, &ird->ird_route.lp_tail,
+ (char *)re, (int)sizeof (*re))) {
ip1dbg(("ip_snmp_get2_v4: failed to allocate %u bytes\n",
- (uint_t)sizeof (re)));
+ (uint_t)sizeof (*re)));
+ }
+
+ for (iaeptr = iae, i = 0; i < sacnt; i++, iaeptr++, gc = gc->gc_next) {
+ iaeptr->iae_routeidx = ird->ird_idx;
+ iaeptr->iae_doi = gc->gc_db->gcdb_doi;
+ iaeptr->iae_slrange = gc->gc_db->gcdb_slrange;
+ }
+
+ if (!snmp_append_data2(ird->ird_attrs.lp_head, &ird->ird_attrs.lp_tail,
+ (char *)iae, sacnt * sizeof (*iae))) {
+ ip1dbg(("ip_snmp_get2_v4: failed to allocate %u bytes\n",
+ (unsigned)(sacnt * sizeof (*iae))));
}
if (ire->ire_type != IRE_CACHE || gw_addr != 0)
- return;
+ goto done;
/*
* only IRE_CACHE entries that are for a directly connected subnet
* get appended to net -> phys addr table
@@ -17368,46 +17868,102 @@
bcopy(&ire->ire_mask, ntme.ipNetToMediaInfo.ntm_mask.o_bytes,
ntme.ipNetToMediaInfo.ntm_mask.o_length);
ntme.ipNetToMediaInfo.ntm_flags = ACE_F_RESOLVED;
- if (!snmp_append_data2(re_ntme[1].lp_head, &(re_ntme[1].lp_tail),
- (char *)&ntme, (int)sizeof (ntme))) {
+ if (!snmp_append_data2(ird->ird_netmedia.lp_head,
+ &ird->ird_netmedia.lp_tail, (char *)&ntme, sizeof (ntme))) {
ip1dbg(("ip_snmp_get2_v4: failed to allocate %u bytes\n",
(uint_t)sizeof (ntme)));
}
-}
-
-/*
- * ire_walk routine to create ipv6RouteEntryTable.
- */
-static void
-ip_snmp_get2_v6_route(ire_t *ire, listptr_t *re_ntme)
+done:
+ /* bump route index for next pass */
+ ird->ird_idx++;
+
+ kmem_free(re, sizeof (*re));
+ if (sacnt != 0)
+ kmem_free(iae, sacnt * sizeof (*iae));
+
+ if (gcgrp != NULL)
+ rw_exit(&gcgrp->gcgrp_rwlock);
+}
+
+/*
+ * ire_walk routine to create ipv6RouteEntryTable and ipRouteEntryTable.
+ */
+static void
+ip_snmp_get2_v6_route(ire_t *ire, iproutedata_t *ird)
{
ill_t *ill;
ipif_t *ipif;
- mib2_ipv6RouteEntry_t re;
+ mib2_ipv6RouteEntry_t *re;
+ mib2_ipAttributeEntry_t *iae, *iaeptr;
in6_addr_t gw_addr_v6;
+ tsol_ire_gw_secattr_t *attrp;
+ tsol_gc_t *gc = NULL;
+ tsol_gcgrp_t *gcgrp = NULL;
+ uint_t sacnt = 0;
+ int i;
ASSERT(ire->ire_ipversion == IPV6_VERSION);
+ if ((re = kmem_zalloc(sizeof (*re), KM_NOSLEEP)) == NULL)
+ return;
+
+ if ((attrp = ire->ire_gw_secattr) != NULL) {
+ mutex_enter(&attrp->igsa_lock);
+ if ((gc = attrp->igsa_gc) != NULL) {
+ gcgrp = gc->gc_grp;
+ ASSERT(gcgrp != NULL);
+ rw_enter(&gcgrp->gcgrp_rwlock, RW_READER);
+ sacnt = 1;
+ } else if ((gcgrp = attrp->igsa_gcgrp) != NULL) {
+ rw_enter(&gcgrp->gcgrp_rwlock, RW_READER);
+ gc = gcgrp->gcgrp_head;
+ sacnt = gcgrp->gcgrp_count;
+ }
+ mutex_exit(&attrp->igsa_lock);
+
+ /* do nothing if there's no gc to report */
+ if (gc == NULL) {
+ ASSERT(sacnt == 0);
+ if (gcgrp != NULL) {
+ /* we might as well drop the lock now */
+ rw_exit(&gcgrp->gcgrp_rwlock);
+ gcgrp = NULL;
+ }
+ attrp = NULL;
+ }
+
+ ASSERT(gc == NULL || (gcgrp != NULL &&
+ RW_LOCK_HELD(&gcgrp->gcgrp_rwlock)));
+ }
+ ASSERT(sacnt == 0 || gc != NULL);
+
+ if (sacnt != 0 &&
+ (iae = kmem_alloc(sacnt * sizeof (*iae), KM_NOSLEEP)) == NULL) {
+ kmem_free(re, sizeof (*re));
+ rw_exit(&gcgrp->gcgrp_rwlock);
+ return;
+ }
+
/*
* Return all IRE types for route table... let caller pick and choose
*/
- re.ipv6RouteDest = ire->ire_addr_v6;
- re.ipv6RoutePfxLength = ip_mask_to_plen_v6(&ire->ire_mask_v6);
- re.ipv6RouteIndex = 0; /* Unique when multiple with same dest/plen */
- re.ipv6RouteIfIndex.o_length = 0;
+ re->ipv6RouteDest = ire->ire_addr_v6;
+ re->ipv6RoutePfxLength = ip_mask_to_plen_v6(&ire->ire_mask_v6);
+ re->ipv6RouteIndex = 0; /* Unique when multiple with same dest/plen */
+ re->ipv6RouteIfIndex.o_length = 0;
ipif = ire->ire_ipif;
if (ire->ire_type == IRE_CACHE) {
ill = (ill_t *)ire->ire_stq->q_ptr;
- re.ipv6RouteIfIndex.o_length =
+ re->ipv6RouteIfIndex.o_length =
ill->ill_name_length == 0 ? 0 :
MIN(OCTET_LENGTH, ill->ill_name_length - 1);
- bcopy(ill->ill_name, re.ipv6RouteIfIndex.o_bytes,
- re.ipv6RouteIfIndex.o_length);
+ bcopy(ill->ill_name, re->ipv6RouteIfIndex.o_bytes,
+ re->ipv6RouteIfIndex.o_length);
} else if (ipif != NULL) {
- (void) ipif_get_name(ipif, re.ipv6RouteIfIndex.o_bytes,
+ (void) ipif_get_name(ipif, re->ipv6RouteIfIndex.o_bytes,
OCTET_LENGTH);
- re.ipv6RouteIfIndex.o_length =
- mi_strlen(re.ipv6RouteIfIndex.o_bytes);
+ re->ipv6RouteIfIndex.o_length =
+ mi_strlen(re->ipv6RouteIfIndex.o_bytes);
}
ASSERT(!(ire->ire_type & IRE_BROADCAST));
@@ -17417,46 +17973,68 @@
mutex_exit(&ire->ire_lock);
if (ire->ire_type & (IRE_INTERFACE|IRE_LOOPBACK))
- re.ipv6RouteNextHop = ire->ire_src_addr_v6;
+ re->ipv6RouteNextHop = ire->ire_src_addr_v6;
else
- re.ipv6RouteNextHop = gw_addr_v6;
+ re->ipv6RouteNextHop = gw_addr_v6;
/* remote(4), local(3), or discard(2) */
if (ire->ire_flags & (RTF_REJECT | RTF_BLACKHOLE))
- re.ipv6RouteType = 2;
+ re->ipv6RouteType = 2;
else if (IN6_IS_ADDR_UNSPECIFIED(&gw_addr_v6))
- re.ipv6RouteType = 3;
+ re->ipv6RouteType = 3;
else
- re.ipv6RouteType = 4;
-
- re.ipv6RouteProtocol = -1;
- re.ipv6RoutePolicy = 0;
- re.ipv6RouteAge = gethrestime_sec() - ire->ire_create_time;
- re.ipv6RouteNextHopRDI = 0;
- re.ipv6RouteWeight = 0;
- re.ipv6RouteMetric = 0;
- re.ipv6RouteInfo.re_max_frag = ire->ire_max_frag;
- re.ipv6RouteInfo.re_frag_flag = ire->ire_frag_flag;
- re.ipv6RouteInfo.re_rtt = ire->ire_uinfo.iulp_rtt;
- re.ipv6RouteInfo.re_src_addr = ire->ire_src_addr_v6;
- re.ipv6RouteInfo.re_ire_type = ire->ire_type;
- re.ipv6RouteInfo.re_obpkt = ire->ire_ob_pkt_count;
- re.ipv6RouteInfo.re_ibpkt = ire->ire_ib_pkt_count;
- re.ipv6RouteInfo.re_ref = ire->ire_refcnt;
- re.ipv6RouteInfo.re_flags = ire->ire_flags;
-
- if (!snmp_append_data2(re_ntme->lp_head, &(re_ntme->lp_tail),
- (char *)&re, (int)sizeof (re))) {
+ re->ipv6RouteType = 4;
+
+ re->ipv6RouteProtocol = -1;
+ re->ipv6RoutePolicy = 0;
+ re->ipv6RouteAge = gethrestime_sec() - ire->ire_create_time;
+ re->ipv6RouteNextHopRDI = 0;
+ re->ipv6RouteWeight = 0;
+ re->ipv6RouteMetric = 0;
+ re->ipv6RouteInfo.re_max_frag = ire->ire_max_frag;
+ re->ipv6RouteInfo.re_frag_flag = ire->ire_frag_flag;
+ re->ipv6RouteInfo.re_rtt = ire->ire_uinfo.iulp_rtt;
+ re->ipv6RouteInfo.re_src_addr = ire->ire_src_addr_v6;
+ re->ipv6RouteInfo.re_ire_type = ire->ire_type;
+ re->ipv6RouteInfo.re_obpkt = ire->ire_ob_pkt_count;
+ re->ipv6RouteInfo.re_ibpkt = ire->ire_ib_pkt_count;
+ re->ipv6RouteInfo.re_ref = ire->ire_refcnt;
+ re->ipv6RouteInfo.re_flags = ire->ire_flags;
+
+ if (!snmp_append_data2(ird->ird_route.lp_head, &ird->ird_route.lp_tail,
+ (char *)re, (int)sizeof (*re))) {
ip1dbg(("ip_snmp_get2_v6: failed to allocate %u bytes\n",
- (uint_t)sizeof (re)));
- }
+ (uint_t)sizeof (*re)));
+ }
+
+ for (iaeptr = iae, i = 0; i < sacnt; i++, iaeptr++, gc = gc->gc_next) {
+ iaeptr->iae_routeidx = ird->ird_idx;
+ iaeptr->iae_doi = gc->gc_db->gcdb_doi;
+ iaeptr->iae_slrange = gc->gc_db->gcdb_slrange;
+ }
+
+ if (!snmp_append_data2(ird->ird_attrs.lp_head, &ird->ird_attrs.lp_tail,
+ (char *)iae, sacnt * sizeof (*iae))) {
+ ip1dbg(("ip_snmp_get2_v6: failed to allocate %u bytes\n",
+ (unsigned)(sacnt * sizeof (*iae))));
+ }
+
+ /* bump route index for next pass */
+ ird->ird_idx++;
+
+ kmem_free(re, sizeof (*re));
+ if (sacnt != 0)
+ kmem_free(iae, sacnt * sizeof (*iae));
+
+ if (gcgrp != NULL)
+ rw_exit(&gcgrp->gcgrp_rwlock);
}
/*
* ndp_walk routine to create ipv6NetToMediaEntryTable
*/
static int
-ip_snmp_get2_v6_media(nce_t *nce, listptr_t *re_ntme)
+ip_snmp_get2_v6_media(nce_t *nce, iproutedata_t *ird)
{
ill_t *ill;
mib2_ipv6NetToMediaEntry_t ntme;
@@ -17506,8 +18084,8 @@
ntme.ipv6NetToMediaType = 2;
}
- if (!snmp_append_data2(re_ntme->lp_head,
- &(re_ntme->lp_tail), (char *)&ntme, (int)sizeof (ntme))) {
+ if (!snmp_append_data2(ird->ird_netmedia.lp_head,
+ &ird->ird_netmedia.lp_tail, (char *)&ntme, sizeof (ntme))) {
ip1dbg(("ip_snmp_get2_v6_media: failed to allocate %u bytes\n",
(uint_t)sizeof (ntme)));
}
@@ -17572,7 +18150,7 @@
* entries left in the source route return (true).
*/
ire = ire_ctable_lookup(dst, 0, IRE_LOCAL, NULL,
- ALL_ZONES, MATCH_IRE_TYPE);
+ ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (ire == NULL) {
ip2dbg(("ip_source_routed: not next"
" source route 0x%x\n",
@@ -17820,6 +18398,14 @@
ASSERT(!MUTEX_HELD(&connp->conn_lock));
+ if (is_system_labeled() && connp->conn_anon_port) {
+ (void) tsol_mlp_anon(crgetzone(connp->conn_cred),
+ connp->conn_mlp_type, connp->conn_ulp,
+ ntohs(connp->conn_lport), B_FALSE);
+ connp->conn_anon_port = 0;
+ }
+ connp->conn_mlp_type = mlptSingle;
+
ipcl_hash_remove(connp);
ASSERT(mp->b_cont == NULL);
@@ -17873,6 +18459,8 @@
mblk_t *copy_mp = NULL;
int err;
zoneid_t zoneid;
+ int adjust;
+ uint16_t iplen;
boolean_t need_decref = B_FALSE;
boolean_t ignore_dontroute = B_FALSE;
boolean_t ignore_nexthop = B_FALSE;
@@ -17919,6 +18507,7 @@
return;
} else if (DB_TYPE(mp) != M_DATA)
goto notdata;
+
if (mp->b_flag & MSGHASREF) {
ASSERT(connp->conn_ulp == IPPROTO_SCTP);
mp->b_flag &= ~MSGHASREF;
@@ -17934,6 +18523,34 @@
goto hdrtoosmall;
#endif
+ ASSERT(OK_32PTR(ipha));
+
+ /*
+ * This function assumes that mp points to an IPv4 packet. If it's the
+ * wrong version, we'll catch it again in ip_output_v6.
+ *
+ * Note that this is *only* locally-generated output here, and never
+ * forwarded data, and that we need to deal only with transports that
+ * don't know how to label. (TCP, UDP, and ICMP/raw-IP all know how to
+ * label.)
+ */
+ if (is_system_labeled() &&
+ (ipha->ipha_version_and_hdr_length & 0xf0) == (IPV4_VERSION << 4) &&
+ !connp->conn_ulp_labeled) {
+ err = tsol_check_label(BEST_CRED(mp, connp), &mp, &adjust,
+ connp->conn_mac_exempt);
+ ipha = (ipha_t *)mp->b_rptr;
+ if (err != 0) {
+ first_mp = mp;
+ if (err == EINVAL)
+ goto icmp_parameter_problem;
+ ip2dbg(("ip_wput: label check failed (%d)\n", err));
+ goto drop_pkt;
+ }
+ iplen = ntohs(ipha->ipha_length) + adjust;
+ ipha->ipha_length = htons(iplen);
+ }
+
/*
* If there is a policy, try to attach an ipsec_out in
* the front. At the end, first_mp either points to a
@@ -17989,7 +18606,7 @@
* destination only SO_DONTROUTE and IP_NEXTHOP go through
* the standard path not IP_XMIT_IF.
*/
- ire = ire_cache_lookup(dst, zoneid);
+ ire = ire_cache_lookup(dst, zoneid, MBLK_GETLABEL(mp));
if ((ire == NULL) || ((ire->ire_type != IRE_BROADCAST) &&
(ire->ire_type != IRE_LOOPBACK))) {
if ((connp->conn_dontroute ||
@@ -18055,7 +18672,7 @@
*/
if (IP_FLOW_CONTROLLED_ULP(connp->conn_ulp) &&
!connp->conn_fully_bound) {
- ire = ire_cache_lookup(dst, zoneid);
+ ire = ire_cache_lookup(dst, zoneid, MBLK_GETLABEL(mp));
if (ire == NULL)
goto noirefound;
TRACE_2(TR_FAC_IP, TR_IP_WPUT_END,
@@ -18091,7 +18708,8 @@
* to initiate additional route resolutions.
*/
multirt_need_resolve =
- ire_multirt_need_resolve(ire->ire_addr);
+ ire_multirt_need_resolve(ire->ire_addr,
+ MBLK_GETLABEL(first_mp));
ip2dbg(("ip_wput[TCP]: ire %p, "
"multirt_need_resolve %d, first_mp %p\n",
(void *)ire, multirt_need_resolve,
@@ -18161,7 +18779,7 @@
if (ire != NULL && sctp_ire == NULL)
IRE_REFRELE_NOTR(ire);
- ire = (ire_t *)ire_cache_lookup(dst, zoneid);
+ ire = ire_cache_lookup(dst, zoneid, MBLK_GETLABEL(mp));
if (ire == NULL)
goto noirefound;
IRE_REFHOLD_NOTR(ire);
@@ -18220,7 +18838,8 @@
* of the current message. It will be used
* to initiate additional route resolutions.
*/
- multirt_need_resolve = ire_multirt_need_resolve(ire->ire_addr);
+ multirt_need_resolve = ire_multirt_need_resolve(ire->ire_addr,
+ MBLK_GETLABEL(first_mp));
ip2dbg(("ip_wput[not TCP]: ire %p, "
"multirt_need_resolve %d, first_mp %p\n",
(void *)ire, multirt_need_resolve, (void *)first_mp));
@@ -18330,7 +18949,7 @@
return;
} else {
/*
- * This must be ARP.
+ * This must be ARP or special TSOL signaling.
*/
ip_wput_nondata(NULL, q, mp, NULL);
TRACE_2(TR_FAC_IP, TR_IP_WPUT_END,
@@ -18452,6 +19071,29 @@
first_mp = mp;
goto drop_pkt;
}
+
+ /* This function assumes that mp points to an IPv4 packet. */
+ if (is_system_labeled() && q->q_next == NULL &&
+ (*mp->b_rptr & 0xf0) == (IPV4_VERSION << 4) &&
+ !connp->conn_ulp_labeled) {
+ err = tsol_check_label(BEST_CRED(mp, connp), &mp,
+ &adjust, connp->conn_mac_exempt);
+ ipha = (ipha_t *)mp->b_rptr;
+ if (first_mp != NULL)
+ first_mp->b_cont = mp;
+ if (err != 0) {
+ if (first_mp == NULL)
+ first_mp = mp;
+ if (err == EINVAL)
+ goto icmp_parameter_problem;
+ ip2dbg(("ip_wput: label check failed (%d)\n",
+ err));
+ goto drop_pkt;
+ }
+ iplen = ntohs(ipha->ipha_length) + adjust;
+ ipha->ipha_length = htons(iplen);
+ }
+
ipha = (ipha_t *)mp->b_rptr;
if (first_mp == NULL) {
ASSERT(attach_ill == NULL && xmit_ill == NULL);
@@ -18717,7 +19359,7 @@
}
if (attach_ill != NULL) {
ASSERT(attach_ill == ipif->ipif_ill);
- match_flags = MATCH_IRE_ILL;
+ match_flags = MATCH_IRE_ILL | MATCH_IRE_SECATTR;
/*
* Check if we need an ire that will not be
@@ -18730,7 +19372,7 @@
attach_ill->ill_phyint->phyint_ifindex;
io->ipsec_out_attach_if = B_TRUE;
} else {
- match_flags = MATCH_IRE_ILL_GROUP;
+ match_flags = MATCH_IRE_ILL_GROUP | MATCH_IRE_SECATTR;
io->ipsec_out_ill_index =
ipif->ipif_ill->ill_phyint->phyint_ifindex;
}
@@ -18791,7 +19433,7 @@
ire = NULL;
if (xmit_ill == NULL) {
ire = ire_ctable_lookup(dst, 0, 0, ipif,
- zoneid, match_flags);
+ zoneid, MBLK_GETLABEL(mp), match_flags);
}
/*
@@ -18860,7 +19502,7 @@
}
}
} else {
- ire = ire_cache_lookup(dst, zoneid);
+ ire = ire_cache_lookup(dst, zoneid, MBLK_GETLABEL(mp));
if ((ire != NULL) && (ire->ire_type &
(IRE_BROADCAST | IRE_LOCAL | IRE_LOOPBACK))) {
ignore_dontroute = B_TRUE;
@@ -18939,7 +19581,7 @@
if (attach_ill != NULL) {
ipif_t *attach_ipif;
- match_flags = MATCH_IRE_ILL;
+ match_flags = MATCH_IRE_ILL | MATCH_IRE_SECATTR;
/*
* Check if we need an ire that will not be
@@ -18955,7 +19597,7 @@
goto drop_pkt;
}
ire = ire_ctable_lookup(dst, 0, 0, attach_ipif,
- zoneid, match_flags);
+ zoneid, MBLK_GETLABEL(mp), match_flags);
ipif_refrele(attach_ipif);
} else if (xmit_ill != NULL || (connp != NULL &&
connp->conn_xmit_if_ill != NULL)) {
@@ -19016,9 +19658,9 @@
match_flags = MATCH_IRE_MARK_PRIVATE_ADDR |
MATCH_IRE_GW;
ire = ire_ctable_lookup(dst, nexthop_addr, 0,
- NULL, zoneid, match_flags);
- } else {
- ire = ire_cache_lookup(dst, zoneid);
+ NULL, zoneid, MBLK_GETLABEL(mp), match_flags);
+ } else {
+ ire = ire_cache_lookup(dst, zoneid, MBLK_GETLABEL(mp));
}
if (!ire) {
/*
@@ -19121,7 +19763,8 @@
* of the current message. It will be used
* to initiate additional route resolutions.
*/
- multirt_need_resolve = ire_multirt_need_resolve(ire->ire_addr);
+ multirt_need_resolve = ire_multirt_need_resolve(ire->ire_addr,
+ MBLK_GETLABEL(first_mp));
ip2dbg(("ip_wput[noirefound]: ire %p, "
"multirt_need_resolve %d, first_mp %p\n",
(void *)ire, multirt_need_resolve, (void *)first_mp));
@@ -19166,6 +19809,16 @@
CONN_DEC_REF(connp);
return;
+icmp_parameter_problem:
+ /* could not have originated externally */
+ ASSERT(mp->b_prev == NULL);
+ if (ip_hdr_complete(ipha, zoneid) == 0) {
+ BUMP_MIB(&ip_mib, ipOutNoRoutes);
+ /* it's the IP header length that's in trouble */
+ icmp_param_problem(q, first_mp, 0);
+ first_mp = NULL;
+ }
+
drop_pkt:
ip1dbg(("ip_wput: dropped packet\n"));
if (ire != NULL)
@@ -19808,7 +20461,8 @@
}
}
- if (ire->ire_type == IRE_LOCAL && ire->ire_zoneid != zoneid) {
+ if (ire->ire_type == IRE_LOCAL && ire->ire_zoneid != zoneid &&
+ ire->ire_zoneid != ALL_ZONES) {
/*
* When a zone sends a packet to another zone, we try to deliver
* the packet under the same conditions as if the destination
@@ -19818,7 +20472,7 @@
* ip_newroute() does.
*/
ire_t *src_ire = ire_ftable_lookup(ipha->ipha_dst, 0, 0, 0,
- NULL, NULL, zoneid, 0, (MATCH_IRE_RECURSIVE |
+ NULL, NULL, zoneid, 0, NULL, (MATCH_IRE_RECURSIVE |
MATCH_IRE_DEFAULT | MATCH_IRE_RJ_BHOLE));
if (src_ire != NULL &&
!(src_ire->ire_flags & (RTF_REJECT | RTF_BLACKHOLE))) {
@@ -19980,7 +20634,7 @@
if (ire->ire_type == IRE_BROADCAST &&
ire->ire_zoneid != zoneid) {
ire_t *src_ire = ire_ctable_lookup(dst, 0,
- IRE_BROADCAST, ire->ire_ipif, zoneid,
+ IRE_BROADCAST, ire->ire_ipif, zoneid, NULL,
(MATCH_IRE_TYPE | MATCH_IRE_ILL_GROUP));
if (src_ire != NULL) {
src = src_ire->ire_src_addr;
@@ -20786,7 +21440,6 @@
}
}
- noprepend:
ASSERT(ipsec_len == 0);
mp1 = ip_wput_attach_llhdr(mp, ire,
IPP_LOCAL_OUT, ill_index);
@@ -21619,6 +22272,8 @@
"couldn't copy hdr");
return;
}
+ if (DB_CRED(mp) != NULL)
+ mblk_setcred(hdr_mp, DB_CRED(mp));
/* Store the starting offset, with the MoreFrags flag. */
i1 = offset | IPH_MF | frag_flag;
@@ -21824,6 +22479,8 @@
return;
} else {
xmit_mp->b_cont = mp;
+ if (DB_CRED(mp) != NULL)
+ mblk_setcred(xmit_mp, DB_CRED(mp));
/* Get priority marking, if any. */
if (DB_TYPE(xmit_mp) == M_DATA)
xmit_mp->b_band = mp->b_band;
@@ -22073,6 +22730,8 @@
xmit_mp = mp;
} else if ((xmit_mp = copyb(ll_hdr_mp)) != NULL) {
xmit_mp->b_cont = mp;
+ if (DB_CRED(mp) != NULL)
+ mblk_setcred(xmit_mp, DB_CRED(mp));
/* Get priority marking, if any. */
if (DB_TYPE(xmit_mp) == M_DATA)
xmit_mp->b_band = mp->b_band;
@@ -22428,6 +23087,7 @@
if ((ushort_t)ire_type == IRE_BROADCAST) {
freemsg(first_mp);
BUMP_MIB(&ip_mib, ipInDiscards);
+ ip2dbg(("ip_wput_local: discard broadcast\n"));
return;
}
@@ -22560,7 +23220,7 @@
off = opt[IPOPT_OFFSET] - 1;
bcopy((char *)opt + off, &dst, IP_ADDR_LEN);
ire = ire_ctable_lookup(dst, 0, IRE_LOCAL,
- NULL, ALL_ZONES, MATCH_IRE_TYPE);
+ NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (ire == NULL) {
/* Not for us */
break;
@@ -22656,7 +23316,8 @@
* ipsec_out_attach_if so that this will not be load spread in
* ip_newroute_ipif.
*/
- ire = ire_ctable_lookup(dst, 0, 0, ipif, ALL_ZONES, MATCH_IRE_ILL);
+ ire = ire_ctable_lookup(dst, 0, 0, ipif, ALL_ZONES, NULL,
+ MATCH_IRE_ILL);
if (!ire) {
/*
* Mark this packet to make it be delivered to
@@ -22751,6 +23412,15 @@
mp1->b_band = mp->b_band;
mp1->b_cont = mp;
/*
+ * certain system generated traffic may not
+ * have cred/label in ip header block. This
+ * is true even for a labeled system. But for
+ * labeled traffic, inherit the label in the
+ * new header.
+ */
+ if (DB_CRED(mp) != NULL)
+ mblk_setcred(mp1, DB_CRED(mp));
+ /*
* XXX disable ICK_VALID and compute checksum
* here; can happen if ire_fp_mp changes and
* it can't be copied now due to insufficient
@@ -22770,6 +23440,15 @@
}
UNLOCK_IRE_FP_MP(ire);
mp1->b_cont = mp;
+ /*
+ * certain system generated traffic may not
+ * have cred/label in ip header block. This
+ * is true even for a labeled system. But for
+ * labeled traffic, inherit the label in the
+ * new header.
+ */
+ if (DB_CRED(mp) != NULL)
+ mblk_setcred(mp1, DB_CRED(mp));
if (!qos_done && (proc != 0) && IPP_ENABLED(proc)) {
ip_process(proc, &mp1, ill_index);
if (mp1 == NULL)
@@ -22812,7 +23491,7 @@
hwaccel = io->ipsec_out_accelerated;
zoneid = io->ipsec_out_zoneid;
ASSERT(zoneid != ALL_ZONES);
- match_flags = MATCH_IRE_ILL_GROUP;
+ match_flags = MATCH_IRE_ILL_GROUP | MATCH_IRE_SECATTR;
/* Multicast addresses should have non-zero ill_index. */
v6dstp = &ip6h->ip6_dst;
ASSERT(ip6h->ip6_nxt != IPPROTO_RAW);
@@ -22867,7 +23546,7 @@
ire = ire_arg;
} else {
ire = ire_ctable_lookup_v6(v6dstp, 0, 0, ipif,
- zoneid, match_flags);
+ zoneid, MBLK_GETLABEL(mp), match_flags);
ire_need_rele = B_TRUE;
}
if (ire != NULL) {
@@ -22909,14 +23588,14 @@
return;
}
ire = ire_ctable_lookup_v6(v6dstp, 0, 0, ipif,
- zoneid, match_flags);
+ zoneid, MBLK_GETLABEL(mp), match_flags);
ire_need_rele = B_TRUE;
ipif_refrele(ipif);
} else {
if (ire_arg != NULL) {
ire = ire_arg;
} else {
- ire = ire_cache_lookup_v6(v6dstp, zoneid);
+ ire = ire_cache_lookup_v6(v6dstp, zoneid, NULL);
ire_need_rele = B_TRUE;
}
}
@@ -23103,7 +23782,7 @@
attach_if = io->ipsec_out_attach_if;
zoneid = io->ipsec_out_zoneid;
ASSERT(zoneid != ALL_ZONES);
- match_flags = MATCH_IRE_ILL_GROUP;
+ match_flags = MATCH_IRE_ILL_GROUP | MATCH_IRE_SECATTR;
if (ill_index != 0) {
if (ill == NULL) {
ill = ip_grab_attach_ill(NULL, ipsec_mp,
@@ -23120,7 +23799,7 @@
* honor it.
*/
if (attach_if) {
- match_flags = MATCH_IRE_ILL;
+ match_flags = MATCH_IRE_ILL | MATCH_IRE_SECATTR;
/*
* Check if we need an ire that will not be
@@ -23154,7 +23833,8 @@
* value of the ipif in ip_wput. All we need now is
* an ire to send this downstream.
*/
- ire = ire_ctable_lookup(dst, 0, 0, ipif, zoneid, match_flags);
+ ire = ire_ctable_lookup(dst, 0, 0, ipif, zoneid,
+ MBLK_GETLABEL(mp), match_flags);
if (ire != NULL) {
ill_t *ill1;
/*
@@ -23199,13 +23879,14 @@
} else {
if (attach_if) {
ire = ire_ctable_lookup(dst, 0, 0, ill->ill_ipif,
- zoneid, match_flags);
+ zoneid, MBLK_GETLABEL(mp), match_flags);
} else {
if (ire_arg != NULL) {
ire = ire_arg;
ire_need_rele = B_FALSE;
} else {
- ire = ire_cache_lookup(dst, zoneid);
+ ire = ire_cache_lookup(dst, zoneid,
+ MBLK_GETLABEL(mp));
}
}
if (ire != NULL) {
@@ -24497,6 +25178,21 @@
ip_ire_req(q, mp);
return;
case M_CTL:
+ if (mp->b_wptr - mp->b_rptr < sizeof (uint32_t))
+ break;
+
+ if (connp != NULL && *(uint32_t *)mp->b_rptr ==
+ IP_ULP_OUT_LABELED) {
+ out_labeled_t *olp;
+
+ if (mp->b_wptr - mp->b_rptr != sizeof (*olp))
+ break;
+ olp = (out_labeled_t *)mp->b_rptr;
+ connp->conn_ulp_labeled = olp->out_qnext == q;
+ freemsg(mp);
+ return;
+ }
+
/* M_CTL messages are used by ARP to tell us things. */
if ((mp->b_wptr - mp->b_rptr) < sizeof (arc_t))
break;
@@ -24921,7 +25617,8 @@
if (optval == IPOPT_SSRR) {
ire = ire_ftable_lookup(dst, 0, 0,
IRE_INTERFACE, NULL, NULL, ALL_ZONES, 0,
- MATCH_IRE_TYPE);
+ MBLK_GETLABEL(mp),
+ MATCH_IRE_TYPE | MATCH_IRE_SECATTR);
if (ire == NULL) {
ip1dbg(("ip_wput_options: SSRR not"
" directly reachable: 0x%x\n",
@@ -25557,7 +26254,8 @@
if (ipif == NULL)
return (B_FALSE);
ire = ire_ctable_lookup(dst, 0, IRE_BROADCAST, ipif,
- connp->conn_zoneid, (MATCH_IRE_TYPE | MATCH_IRE_ILL_GROUP));
+ connp->conn_zoneid, NULL,
+ (MATCH_IRE_TYPE | MATCH_IRE_ILL_GROUP));
ipif_refrele(ipif);
if (ire != NULL) {
ire_refrele(ire);
@@ -25812,7 +26510,7 @@
continue;
ire_gw = ire_ftable_lookup(ire->ire_gateway_addr, 0, 0,
- IRE_INTERFACE, NULL, NULL, ALL_ZONES, 0,
+ IRE_INTERFACE, NULL, NULL, ALL_ZONES, 0, NULL,
MATCH_IRE_RECURSIVE | MATCH_IRE_TYPE);
/* No resolver exists for the gateway; skip this ire. */
if (ire_gw == NULL)
@@ -26303,7 +27001,7 @@
}
ip6h = (isv4) ? NULL : (ip6_t *)ipha;
- connp = ipcl_classify_raw(IPPROTO_SCTP, zoneid, ports, ipha);
+ connp = ipcl_classify_raw(mp, IPPROTO_SCTP, zoneid, ports, ipha);
if (connp == NULL) {
sctp_ootb_input(first_mp, recv_ill, ipif_seqid, zoneid,
mctl_present);
@@ -26400,7 +27098,7 @@
goto dont_forward;
src_ire = ire_ctable_lookup(ipha->ipha_src, 0, IRE_BROADCAST, NULL,
- ALL_ZONES, MATCH_IRE_TYPE);
+ ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (src_ire != NULL) {
ire_refrele(src_ire);
goto dont_forward;
@@ -26449,3 +27147,100 @@
}
return (B_FALSE);
}
+
+/*
+ * Return B_TRUE if the buffers differ in length or content.
+ * This is used for comparing extension header buffers.
+ * Note that an extension header would be declared different
+ * even if all that changed was the next header value in that header i.e.
+ * what really changed is the next extension header.
+ */
+boolean_t
+ip_cmpbuf(const void *abuf, uint_t alen, boolean_t b_valid, const void *bbuf,
+ uint_t blen)
+{
+ if (!b_valid)
+ blen = 0;
+
+ if (alen != blen)
+ return (B_TRUE);
+ if (alen == 0)
+ return (B_FALSE); /* Both zero length */
+ return (bcmp(abuf, bbuf, alen));
+}
+
+/*
+ * Preallocate memory for ip_savebuf(). Returns B_TRUE if ok.
+ * Return B_FALSE if memory allocation fails - don't change any state!
+ */
+boolean_t
+ip_allocbuf(void **dstp, uint_t *dstlenp, boolean_t src_valid,
+ const void *src, uint_t srclen)
+{
+ void *dst;
+
+ if (!src_valid)
+ srclen = 0;
+
+ ASSERT(*dstlenp == 0);
+ if (src != NULL && srclen != 0) {
+ dst = mi_alloc(srclen, BPRI_MED);
+ if (dst == NULL)
+ return (B_FALSE);
+ } else {
+ dst = NULL;
+ }
+ if (*dstp != NULL)
+ mi_free(*dstp);
+ *dstp = dst;
+ *dstlenp = dst == NULL ? 0 : srclen;
+ return (B_TRUE);
+}
+
+/*
+ * Replace what is in *dst, *dstlen with the source.
+ * Assumes ip_allocbuf has already been called.
+ */
+void
+ip_savebuf(void **dstp, uint_t *dstlenp, boolean_t src_valid,
+ const void *src, uint_t srclen)
+{
+ if (!src_valid)
+ srclen = 0;
+
+ ASSERT(*dstlenp == srclen);
+ if (src != NULL && srclen != 0)
+ bcopy(src, *dstp, srclen);
+}
+
+/*
+ * Free the storage pointed to by the members of an ip6_pkt_t.
+ */
+void
+ip6_pkt_free(ip6_pkt_t *ipp)
+{
+ ASSERT(ipp->ipp_pathmtu == NULL && !(ipp->ipp_fields & IPPF_PATHMTU));
+
+ if (ipp->ipp_fields & IPPF_HOPOPTS) {
+ kmem_free(ipp->ipp_hopopts, ipp->ipp_hopoptslen);
+ ipp->ipp_hopopts = NULL;
+ ipp->ipp_hopoptslen = 0;
+ }
+ if (ipp->ipp_fields & IPPF_RTDSTOPTS) {
+ kmem_free(ipp->ipp_rtdstopts, ipp->ipp_rtdstoptslen);
+ ipp->ipp_rtdstopts = NULL;
+ ipp->ipp_rtdstoptslen = 0;
+ }
+ if (ipp->ipp_fields & IPPF_DSTOPTS) {
+ kmem_free(ipp->ipp_dstopts, ipp->ipp_dstoptslen);
+ ipp->ipp_dstopts = NULL;
+ ipp->ipp_dstoptslen = 0;
+ }
+ if (ipp->ipp_fields & IPPF_RTHDR) {
+ kmem_free(ipp->ipp_rthdr, ipp->ipp_rthdrlen);
+ ipp->ipp_rthdr = NULL;
+ ipp->ipp_rthdrlen = 0;
+ }
+ ipp->ipp_fields &= ~(IPPF_HOPOPTS | IPPF_RTDSTOPTS | IPPF_DSTOPTS |
+ IPPF_RTHDR);
+}
--- a/usr/src/uts/common/inet/ip/ip6.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip/ip6.c Fri Mar 24 12:29:20 2006 -0800
@@ -38,7 +38,6 @@
#include <sys/strsubr.h>
#define _SUN_TPI_VERSION 2
#include <sys/tihdr.h>
-#include <sys/tiuser.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/cmn_err.h>
@@ -56,7 +55,6 @@
#include <sys/iphada.h>
#include <sys/policy.h>
#include <net/if.h>
-#include <net/if_arp.h>
#include <net/if_types.h>
#include <net/route.h>
#include <net/if_dl.h>
@@ -71,7 +69,6 @@
#include <inet/mib2.h>
#include <inet/nd.h>
#include <inet/arp.h>
-#include <inet/snmpcom.h>
#include <inet/ip.h>
#include <inet/ip_impl.h>
@@ -94,13 +91,17 @@
#include <inet/ipsec_impl.h>
#include <inet/tun.h>
#include <inet/sctp_ip.h>
-#include <sys/multidata.h>
#include <sys/pattr.h>
#include <inet/ipclassifier.h>
#include <inet/ipsecah.h>
#include <inet/udp_impl.h>
#include <sys/squeue.h>
+#include <sys/tsol/label.h>
+#include <sys/tsol/tnet.h>
+
+#include <rpc/pmap_prot.h>
+
extern squeue_func_t ip_input_proc;
/*
@@ -179,6 +180,14 @@
mib2_ipv6IfStatsEntry_t ip6_mib;
mib2_ipv6IfIcmpEntry_t icmp6_mib;
+/*
+ * ip6opt_ls is used to enable IPv6 (via /etc/system on TX systems).
+ * We need to do this because we didn't obtain the IP6OPT_LS (0x0a)
+ * from IANA. This mechanism will remain in effect until an official
+ * number is obtained.
+ */
+uchar_t ip6opt_ls;
+
uint_t ipv6_ire_default_count; /* Number of IPv6 IRE_DEFAULT entries */
uint_t ipv6_ire_default_index; /* Walking IPv6 index used to mod in */
@@ -358,6 +367,22 @@
return;
}
+ /*
+ * On a labeled system, we have to check whether the zone itself is
+ * permitted to receive raw traffic.
+ */
+ if (is_system_labeled()) {
+ if (zoneid == ALL_ZONES)
+ zoneid = tsol_packet_to_zoneid(mp);
+ if (!tsol_can_accept_raw(mp, B_FALSE)) {
+ ip1dbg(("icmp_inbound_v6: zone %d can't receive raw",
+ zoneid));
+ BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInErrors);
+ freemsg(first_mp);
+ return;
+ }
+ }
+
icmp6 = (icmp6_t *)(&mp->b_rptr[hdr_length]);
ip2dbg(("icmp_inbound_v6: type %d code %d\n", icmp6->icmp6_type,
icmp6->icmp6_code));
@@ -507,7 +532,8 @@
* we do this, we will try to forward all packets
* meant to our LOCAL address.
*/
- ire = ire_cache_lookup_v6(&ip6h->ip6_dst, ALL_ZONES);
+ ire = ire_cache_lookup_v6(&ip6h->ip6_dst, ALL_ZONES,
+ NULL);
if (ire == NULL || ire->ire_type != IRE_LOCAL) {
mp = ip_add_info_v6(mp, NULL, &ip6h->ip6_dst);
if (mp == NULL) {
@@ -552,6 +578,7 @@
first_mp->b_cont = mp;
}
ii->ipsec_in_zoneid = zoneid;
+ ASSERT(zoneid != ALL_ZONES);
if (!ipsec_in_to_out(first_mp, NULL, ip6h)) {
BUMP_MIB(ill->ill_ip6_mib, ipv6InDiscards);
return;
@@ -708,8 +735,8 @@
if (IN6_IS_ADDR_LINKLOCAL(&inner_ip6h->ip6_dst)) {
first_ire = ire_ctable_lookup_v6(&inner_ip6h->ip6_dst, NULL,
- IRE_CACHE, ill->ill_ipif, ALL_ZONES,
- MATCH_IRE_TYPE | MATCH_IRE_ILL_GROUP);
+ IRE_CACHE, ill->ill_ipif, ALL_ZONES, NULL,
+ MATCH_IRE_TYPE | MATCH_IRE_ILL_GROUP);
if (first_ire == NULL) {
if (ip_debug > 2) {
@@ -764,7 +791,7 @@
* for non-link local destinations we match only on the IRE type
*/
ire = ire_ctable_lookup_v6(&inner_ip6h->ip6_dst, NULL,
- IRE_CACHE, ill->ill_ipif, ALL_ZONES, MATCH_IRE_TYPE);
+ IRE_CACHE, ill->ill_ipif, ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (ire == NULL) {
if (ip_debug > 2) {
/* ip1dbg */
@@ -1224,7 +1251,7 @@
* router goes away between now and then.
*/
ire = ire_route_lookup_v6(&rd->nd_rd_dst, 0,
- &ip6h->ip6_src, 0, ill->ill_ipif, NULL, ALL_ZONES,
+ &ip6h->ip6_src, 0, ill->ill_ipif, NULL, ALL_ZONES, NULL,
MATCH_IRE_GW | MATCH_IRE_ILL_GROUP);
if (ire == NULL)
return (B_FALSE);
@@ -1288,7 +1315,7 @@
return;
}
prev_ire = ire_route_lookup_v6(dst, 0, src, 0, ipif, NULL,
- ALL_ZONES, MATCH_IRE_GW | MATCH_IRE_ILL_GROUP);
+ ALL_ZONES, NULL, MATCH_IRE_GW | MATCH_IRE_ILL_GROUP);
ipif_refrele(ipif);
/*
* Check that
@@ -1331,7 +1358,7 @@
ire_t *sire;
tmp_ire = ire_ftable_lookup_v6(dst, 0, gateway, 0, NULL, &sire,
- ALL_ZONES, 0,
+ ALL_ZONES, 0, NULL,
(MATCH_IRE_RECURSIVE | MATCH_IRE_GW | MATCH_IRE_DEFAULT));
if (sire != NULL) {
bcopy(&sire->ire_uinfo, &ulp_info, sizeof (iulp_t));
@@ -1400,7 +1427,9 @@
0,
0,
(RTF_DYNAMIC | RTF_GATEWAY | RTF_HOST),
- &ulp_info);
+ &ulp_info,
+ NULL,
+ NULL);
} else {
/*
* Just create an on link entry, may or may not be a router
@@ -1423,7 +1452,9 @@
0,
0,
0,
- &ulp_info);
+ &ulp_info,
+ NULL,
+ NULL);
}
if (ire == NULL)
goto fail_redirect;
@@ -1450,7 +1481,7 @@
* modifying an existing redirect.
*/
redir_ire = ire_ftable_lookup_v6(dst, 0, src, IRE_HOST_REDIRECT,
- ire->ire_ipif, NULL, ALL_ZONES, 0,
+ ire->ire_ipif, NULL, ALL_ZONES, 0, NULL,
(MATCH_IRE_GW | MATCH_IRE_TYPE | MATCH_IRE_ILL_GROUP));
ire_refrele(ire); /* Held in ire_add_v6 */
@@ -1521,7 +1552,7 @@
}
ire = ire_route_lookup_v6(origdst, 0, 0, (IRE_LOCAL|IRE_LOOPBACK),
- NULL, NULL, zoneid, (MATCH_IRE_TYPE|MATCH_IRE_ZONEONLY));
+ NULL, NULL, zoneid, NULL, (MATCH_IRE_TYPE|MATCH_IRE_ZONEONLY));
if (ire != NULL) {
/* Destined to one of our addresses */
*src = *origdst;
@@ -1535,7 +1566,7 @@
if (ill == NULL) {
/* What is the route back to the original source? */
ire = ire_route_lookup_v6(origsrc, 0, 0, 0,
- NULL, NULL, zoneid,
+ NULL, NULL, zoneid, NULL,
(MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE));
if (ire == NULL) {
BUMP_MIB(&ip6_mib, ipv6OutNoRoutes);
@@ -1561,7 +1592,8 @@
* original source. Use what in the route to the source.
*/
ire = ire_route_lookup_v6(origsrc, 0, 0, 0,
- NULL, NULL, zoneid, (MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE));
+ NULL, NULL, zoneid, NULL,
+ (MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE));
if (ire == NULL) {
BUMP_MIB(&ip6_mib, ipv6OutNoRoutes);
return (NULL);
@@ -2176,6 +2208,20 @@
goto bad_addr;
}
+ /*
+ *
+ * The udp module never sends down a zero-length address,
+ * and allowing this on a labeled system will break MLP
+ * functionality.
+ */
+ if (is_system_labeled() && protocol == IPPROTO_UDP)
+ goto bad_addr;
+
+ /* Allow ipsec plumbing */
+ if (connp->conn_mac_exempt && protocol != IPPROTO_AH &&
+ protocol != IPPROTO_ESP)
+ goto bad_addr;
+
connp->conn_srcv6 = ipv6_all_zeros;
ipcl_proto_insert_v6(connp, protocol);
@@ -2420,7 +2466,7 @@
if (!IN6_IS_ADDR_UNSPECIFIED(v6src)) {
src_ire = ire_route_lookup_v6(v6src, 0, 0,
- 0, NULL, NULL, zoneid, MATCH_IRE_ZONEONLY);
+ 0, NULL, NULL, zoneid, NULL, MATCH_IRE_ZONEONLY);
/*
* If an address other than in6addr_any is requested,
* we verify that it is a valid address for bind
@@ -2428,7 +2474,6 @@
* readability compared to a condition check.
*/
ASSERT(src_ire == NULL || !(src_ire->ire_type & IRE_BROADCAST));
- /* LINTED - statement has no consequent */
if (IRE_IS_LOCAL(src_ire)) {
/*
* (2) Bind to address of local UP interface
@@ -2463,10 +2508,8 @@
mutex_exit(&connp->conn_lock);
save_ire = src_ire;
src_ire = NULL;
- if (multi_ipif == NULL ||
- !ire_requested || (src_ire =
- ipif_to_ire_v6(multi_ipif)) ==
- NULL) {
+ if (multi_ipif == NULL || !ire_requested ||
+ (src_ire = ipif_to_ire_v6(multi_ipif)) == NULL) {
src_ire = save_ire;
error = EADDRNOTAVAIL;
} else {
@@ -2545,6 +2588,15 @@
}
}
bad_addr:
+ if (error != 0) {
+ if (connp->conn_anon_port) {
+ (void) tsol_mlp_anon(crgetzone(connp->conn_cred),
+ connp->conn_mlp_type, connp->conn_ulp, ntohs(lport),
+ B_FALSE);
+ }
+ connp->conn_mlp_type = mlptSingle;
+ }
+
if (src_ire != NULL)
ire_refrele(src_ire);
@@ -2683,9 +2735,9 @@
ipif_refrele(ipif);
} else {
dst_ire = ire_route_lookup_v6(v6dst, NULL, NULL, 0,
- NULL, &sire, zoneid,
+ NULL, &sire, zoneid, MBLK_GETLABEL(mp),
MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT |
- MATCH_IRE_PARENT | MATCH_IRE_RJ_BHOLE);
+ MATCH_IRE_PARENT | MATCH_IRE_RJ_BHOLE | MATCH_IRE_SECATTR);
/*
* We also prevent ire's with src address INADDR_ANY to
* be used, which are created temporarily for
@@ -2722,6 +2774,33 @@
}
/*
+ * We now know that routing will allow us to reach the destination.
+ * Check whether Trusted Solaris policy allows communication with this
+ * host, and pretend that the destination is unreachable if not.
+ *
+ * This is never a problem for TCP, since that transport is known to
+ * compute the label properly as part of the tcp_rput_other T_BIND_ACK
+ * handling. If the remote is unreachable, it will be detected at that
+ * point, so there's no reason to check it here.
+ *
+ * Note that for sendto (and other datagram-oriented friends), this
+ * check is done as part of the data path label computation instead.
+ * The check here is just to make non-TCP connect() report the right
+ * error.
+ */
+ if (dst_ire != NULL && is_system_labeled() &&
+ !IPCL_IS_TCP(connp) &&
+ tsol_compute_label_v6(DB_CREDDEF(mp, connp->conn_cred), v6dst, NULL,
+ connp->conn_mac_exempt) != 0) {
+ error = EHOSTUNREACH;
+ if (ip_debug > 2) {
+ pr_addr_dbg("ip_bind_connected: no label for dst %s\n",
+ AF_INET6, v6dst);
+ }
+ goto bad_addr;
+ }
+
+ /*
* If the app does a connect(), it means that it will most likely
* send more than 1 packet to the destination. It makes sense
* to clear the temporary flag.
@@ -2760,9 +2839,10 @@
if (dst_ire != NULL &&
dst_ire->ire_type == IRE_LOCAL &&
- dst_ire->ire_zoneid != zoneid) {
+ dst_ire->ire_zoneid != zoneid &&
+ dst_ire->ire_zoneid != ALL_ZONES) {
src_ire = ire_ftable_lookup_v6(v6dst, 0, 0, 0, NULL, NULL,
- zoneid, 0,
+ zoneid, 0, NULL,
MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT |
MATCH_IRE_RJ_BHOLE);
if (src_ire == NULL) {
@@ -2790,7 +2870,8 @@
sire = NULL;
} else if (dst_ire->ire_type == IRE_CACHE &&
(dst_ire->ire_flags & RTF_SETSRC)) {
- ASSERT(dst_ire->ire_zoneid == zoneid);
+ ASSERT(dst_ire->ire_zoneid == zoneid ||
+ dst_ire->ire_zoneid == ALL_ZONES);
*v6src = dst_ire->ire_src_addr_v6;
} else {
/*
@@ -2866,7 +2947,7 @@
* UP interface for hard binding.
*/
src_ire = ire_route_lookup_v6(v6src, 0, 0, 0, NULL,
- NULL, zoneid, MATCH_IRE_ZONEONLY);
+ NULL, zoneid, NULL, MATCH_IRE_ZONEONLY);
/* src_ire must be a local|loopback */
if (!IRE_IS_LOCAL(src_ire)) {
@@ -3130,7 +3211,7 @@
in6_addr_t src = ip6h->ip6_src;
boolean_t one_only;
mblk_t *first_mp = mp;
- boolean_t secure;
+ boolean_t secure, shared_addr;
conn_t *connp, *first_connp, *next_connp;
connf_t *connfp;
@@ -3149,13 +3230,25 @@
one_only = ((nexthdr == IPPROTO_ENCAP || nexthdr == IPPROTO_IPV6) &&
!IN6_IS_ADDR_MULTICAST(&dst));
+ shared_addr = (zoneid == ALL_ZONES);
+ if (shared_addr) {
+ /*
+ * We don't allow multilevel ports for raw IP, so no need to
+ * check for that here.
+ */
+ zoneid = tsol_packet_to_zoneid(mp);
+ }
+
connfp = &ipcl_proto_fanout_v6[nexthdr];
mutex_enter(&connfp->connf_lock);
connp = connfp->connf_head;
for (connp = connfp->connf_head; connp != NULL;
connp = connp->conn_next) {
if (IPCL_PROTO_MATCH_V6(connp, nexthdr, ip6h, ill, flags,
- zoneid))
+ zoneid) &&
+ (!is_system_labeled() ||
+ tsol_receive_local(mp, &dst, IPV6_VERSION, shared_addr,
+ connp)))
break;
}
@@ -3195,7 +3288,10 @@
for (;;) {
while (connp != NULL) {
if (IPCL_PROTO_MATCH_V6(connp, nexthdr, ip6h, ill,
- flags, zoneid))
+ flags, zoneid) &&
+ (!is_system_labeled() ||
+ tsol_receive_local(mp, &dst, IPV6_VERSION,
+ shared_addr, connp)))
break;
connp = connp->conn_next;
}
@@ -3630,6 +3726,7 @@
conn_t *next_conn;
mblk_t *mp1, *first_mp1;
in6_addr_t src;
+ boolean_t shared_addr;
first_mp = mp;
if (mctl_present) {
@@ -3646,6 +3743,20 @@
dst = ip6h->ip6_dst;
src = ip6h->ip6_src;
+ shared_addr = (zoneid == ALL_ZONES);
+ if (shared_addr) {
+ zoneid = tsol_mlp_findzone(IPPROTO_UDP, dstport);
+ /*
+ * If no shared MLP is found, tsol_mlp_findzone returns
+ * ALL_ZONES. In that case, we assume it's SLP, and
+ * search for the zone based on the packet label.
+ * That will also return ALL_ZONES on failure, but
+ * we never allow conn_zoneid to be set to ALL_ZONES.
+ */
+ if (zoneid == ALL_ZONES)
+ zoneid = tsol_packet_to_zoneid(mp);
+ }
+
/* Attempt to find a client stream based on destination port. */
connfp = &ipcl_udp_fanout[IPCL_UDP_HASH(dstport)];
mutex_enter(&connfp->connf_lock);
@@ -3666,13 +3777,17 @@
if (connp == NULL || connp->conn_upq == NULL)
goto notfound;
+ if (is_system_labeled() &&
+ !tsol_receive_local(mp, &dst, IPV6_VERSION, shared_addr,
+ connp))
+ goto notfound;
+
/* Found a client */
CONN_INC_REF(connp);
mutex_exit(&connfp->connf_lock);
if (CONN_UDP_FLOWCTLD(connp)) {
freemsg(first_mp);
- BUMP_MIB(ill->ill_ip6_mib, udpInOverflows);
CONN_DEC_REF(connp);
return;
}
@@ -3733,15 +3848,12 @@
return;
}
- /*
- * The code is fine but we shouldn't be walking the conn_next
- * list in IPv6 (its a classifier private data struct). Maybe create
- * a classifier API to put a REF_HOLD on all matching conn in the
- * list and return an array.
- */
while (connp != NULL) {
if ((IPCL_UDP_MATCH_V6(connp, dstport, dst, srcport, src)) &&
- conn_wantpacket_v6(connp, ill, ip6h, flags, zoneid))
+ conn_wantpacket_v6(connp, ill, ip6h, flags, zoneid) &&
+ (!is_system_labeled() ||
+ tsol_receive_local(mp, &dst, IPV6_VERSION, shared_addr,
+ connp)))
break;
connp = connp->conn_next;
}
@@ -3757,7 +3869,10 @@
while (connp != NULL) {
if (IPCL_UDP_MATCH_V6(connp, dstport, dst, srcport,
src) && conn_wantpacket_v6(connp, ill, ip6h,
- flags, zoneid))
+ flags, zoneid) &&
+ (!is_system_labeled() ||
+ tsol_receive_local(mp, &dst, IPV6_VERSION,
+ shared_addr, connp)))
break;
connp = connp->conn_next;
}
@@ -3791,13 +3906,20 @@
/* Add header */
mp1 = ip_add_info_v6(mp1, inill, &dst);
}
+ /* mp1 could have changed */
+ if (mctl_present)
+ first_mp1->b_cont = mp1;
+ else
+ first_mp1 = mp1;
if (mp1 == NULL) {
+ if (mctl_present)
+ freeb(first_mp1);
BUMP_MIB(ill->ill_ip6_mib, ipv6InDiscards);
goto next_one;
}
if (CONN_UDP_FLOWCTLD(connp)) {
BUMP_MIB(ill->ill_ip6_mib, udpInOverflows);
- freemsg(mp1);
+ freemsg(first_mp1);
goto next_one;
}
@@ -4261,6 +4383,9 @@
boolean_t need_rele = B_FALSE;
boolean_t do_attach_ill = B_FALSE;
boolean_t ip6_asp_table_held = B_FALSE;
+ tsol_ire_gw_secattr_t *attrp = NULL;
+ tsol_gcgrp_t *gcgrp = NULL;
+ tsol_gcgrp_addr_t ga;
ASSERT(!IN6_IS_ADDR_MULTICAST(v6dstp));
@@ -4329,9 +4454,10 @@
if (ill == NULL) {
match_flags = MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT |
- MATCH_IRE_PARENT | MATCH_IRE_RJ_BHOLE;
+ MATCH_IRE_PARENT | MATCH_IRE_RJ_BHOLE | MATCH_IRE_SECATTR;
ire = ire_ftable_lookup_v6(v6dstp, 0, 0, 0,
- NULL, &sire, zoneid, 0, match_flags);
+ NULL, &sire, zoneid, 0, MBLK_GETLABEL(mp),
+ match_flags);
/*
* ire_add_then_send -> ip_newroute_v6 in the CGTP case passes
* in a NULL ill, but the packet could be a neighbor
@@ -4355,9 +4481,9 @@
match_flags = MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT |
MATCH_IRE_RJ_BHOLE | MATCH_IRE_ILL_GROUP;
}
- match_flags |= MATCH_IRE_PARENT;
- ire = ire_ftable_lookup_v6(v6dstp, 0, 0, 0, ill->ill_ipif,
- &sire, zoneid, 0, match_flags);
+ match_flags |= MATCH_IRE_PARENT | MATCH_IRE_SECATTR;
+ ire = ire_ftable_lookup_v6(v6dstp, NULL, NULL, 0, ill->ill_ipif,
+ &sire, zoneid, 0, MBLK_GETLABEL(mp), match_flags);
}
ip3dbg(("ip_newroute_v6: ire_ftable_lookup_v6() "
@@ -4403,8 +4529,8 @@
* We check if there are trailing unresolved routes for
* the destination contained in sire.
*/
- multirt_is_resolvable =
- ire_multirt_lookup_v6(&ire, &sire, multirt_flags);
+ multirt_is_resolvable = ire_multirt_lookup_v6(&ire,
+ &sire, multirt_flags, MBLK_GETLABEL(mp));
ip3dbg(("ip_newroute_v6: multirt_is_resolvable %d, "
"ire %p, sire %p\n",
@@ -4755,6 +4881,19 @@
* and RTF_MULTIRT to propagate these flags from prefix
* to cache.
*/
+
+ /*
+ * Check cached gateway IRE for any security
+ * attributes; if found, associate the gateway
+ * credentials group to the destination IRE.
+ */
+ if ((attrp = save_ire->ire_gw_secattr) != NULL) {
+ mutex_enter(&attrp->igsa_lock);
+ if ((gcgrp = attrp->igsa_gcgrp) != NULL)
+ GCGRP_REFHOLD(gcgrp);
+ mutex_exit(&attrp->igsa_lock);
+ }
+
ire = ire_create_v6(
v6dstp, /* dest address */
&ipv6_all_ones, /* mask */
@@ -4772,13 +4911,23 @@
ipif_ire->ire_ihandle, /* Interface handle */
sire->ire_flags & /* flags if any */
(RTF_SETSRC | RTF_MULTIRT),
- &(sire->ire_uinfo));
+ &(sire->ire_uinfo),
+ NULL,
+ gcgrp);
if (ire == NULL) {
+ if (gcgrp != NULL) {
+ GCGRP_REFRELE(gcgrp);
+ gcgrp = NULL;
+ }
ire_refrele(save_ire);
ire_refrele(ipif_ire);
break;
}
+
+ /* reference now held by IRE */
+ gcgrp = NULL;
+
ire->ire_marks |= ire_marks;
/*
@@ -4871,6 +5020,24 @@
}
if (dlureq_mp == NULL)
break;
+ /*
+ * TSol note: We are creating the ire cache for the
+ * destination 'dst'. If 'dst' is offlink, going
+ * through the first hop 'gw', the security attributes
+ * of 'dst' must be set to point to the gateway
+ * credentials of gateway 'gw'. If 'dst' is onlink, it
+ * is possible that 'dst' is a potential gateway that is
+ * referenced by some route that has some security
+ * attributes. Thus in the former case, we need to do a
+ * gcgrp_lookup of 'gw' while in the latter case we
+ * need to do gcgrp_lookup of 'dst' itself.
+ */
+ ga.ga_af = AF_INET6;
+ if (!IN6_IS_ADDR_UNSPECIFIED(&v6gw))
+ ga.ga_addr = v6gw;
+ else
+ ga.ga_addr = *v6dstp;
+ gcgrp = gcgrp_lookup(&ga, B_FALSE);
/*
* Note: the new ire inherits sire flags RTF_SETSRC
@@ -4896,16 +5063,25 @@
(sire != NULL) ? /* flags if any */
sire->ire_flags &
(RTF_SETSRC | RTF_MULTIRT) : 0,
- &(save_ire->ire_uinfo));
+ &(save_ire->ire_uinfo),
+ NULL,
+ gcgrp);
if (dst_ill->ill_phys_addr_length == IPV6_ADDR_LEN)
freeb(dlureq_mp);
if (ire == NULL) {
+ if (gcgrp != NULL) {
+ GCGRP_REFRELE(gcgrp);
+ gcgrp = NULL;
+ }
ire_refrele(save_ire);
break;
}
+ /* reference now held by IRE */
+ gcgrp = NULL;
+
ire->ire_marks |= ire_marks;
if (!IN6_IS_ADDR_UNSPECIFIED(&v6gw))
@@ -4997,6 +5173,7 @@
* found a resolver that can help.
*/
dst = *v6dstp;
+
/*
* To be at this point in the code with a non-zero gw
* means that dst is reachable through a gateway that
@@ -5012,6 +5189,13 @@
dst = v6gw;
v6gw = ipv6_all_zeros;
}
+ /*
+ * TSol note: Please see the note above the
+ * IRE_IF_NORESOLVER case.
+ */
+ ga.ga_af = AF_INET6;
+ ga.ga_addr = dst;
+ gcgrp = gcgrp_lookup(&ga, B_FALSE);
if (dst_ill->ill_flags & ILLF_XRESOLV) {
/*
* Ask the external resolver to do its thing.
@@ -5046,14 +5230,24 @@
save_ire->ire_ihandle,
/* Interface handle */
0, /* flags if any */
- &(save_ire->ire_uinfo));
+ &(save_ire->ire_uinfo),
+ NULL,
+ gcgrp);
ire_refrele(save_ire);
if (ire == NULL) {
+ if (gcgrp != NULL) {
+ GCGRP_REFRELE(gcgrp);
+ gcgrp = NULL;
+ }
ip1dbg(("ip_newroute_v6:"
"ire is NULL\n"));
break;
}
+
+ /* reference now held by IRE */
+ gcgrp = NULL;
+
if ((sire != NULL) &&
(sire->ire_flags & RTF_MULTIRT)) {
/*
@@ -5225,13 +5419,22 @@
0,
save_ire->ire_ihandle, /* Interface handle */
0, /* flags if any */
- &(save_ire->ire_uinfo));
+ &(save_ire->ire_uinfo),
+ NULL,
+ gcgrp);
if (ire == NULL) {
+ if (gcgrp != NULL) {
+ GCGRP_REFRELE(gcgrp);
+ gcgrp = NULL;
+ }
ire_refrele(save_ire);
break;
}
+ /* reference now held by IRE */
+ gcgrp = NULL;
+
if ((sire != NULL) &&
(sire->ire_flags & RTF_MULTIRT)) {
copy_mp = copymsg(first_mp);
@@ -5818,7 +6021,9 @@
(fire != NULL) ?
(fire->ire_flags & (RTF_SETSRC | RTF_MULTIRT)) :
0,
- &ire_uinfo_null);
+ &ire_uinfo_null,
+ NULL,
+ NULL);
if (dst_ill->ill_phys_addr_length == IPV6_ADDR_LEN)
freeb(dlureq_mp);
@@ -5866,7 +6071,8 @@
*/
if (copy_mp != NULL) {
boolean_t need_resolve =
- ire_multirt_need_resolve_v6(v6dstp);
+ ire_multirt_need_resolve_v6(v6dstp,
+ MBLK_GETLABEL(copy_mp));
if (!need_resolve) {
MULTIRT_DEBUG_UNTAG(copy_mp);
freemsg(copy_mp);
@@ -5948,7 +6154,9 @@
(fire != NULL) ?
(fire->ire_flags & (RTF_SETSRC | RTF_MULTIRT)) :
0,
- &ire_uinfo_null);
+ &ire_uinfo_null,
+ NULL,
+ NULL);
if (ire == NULL) {
ire_refrele(save_ire);
@@ -5994,7 +6202,8 @@
*/
if (copy_mp != NULL) {
boolean_t need_resolve =
- ire_multirt_need_resolve_v6(v6dstp);
+ ire_multirt_need_resolve_v6(v6dstp,
+ MBLK_GETLABEL(copy_mp));
if (!need_resolve) {
MULTIRT_DEBUG_UNTAG(copy_mp);
freemsg(copy_mp);
@@ -6071,7 +6280,8 @@
*/
if (copy_mp != NULL) {
boolean_t need_resolve =
- ire_multirt_need_resolve_v6(v6dstp);
+ ire_multirt_need_resolve_v6(v6dstp,
+ MBLK_GETLABEL(copy_mp));
if (!need_resolve) {
MULTIRT_DEBUG_UNTAG(copy_mp);
freemsg(copy_mp);
@@ -6195,6 +6405,7 @@
uint_t optused;
int ret = 0;
mblk_t *first_mp;
+ const char *errtype;
first_mp = mp;
if (mp->b_datap->db_type == M_CTL) {
@@ -6208,7 +6419,12 @@
} else {
if (optlen < 2)
goto bad_opt;
- switch (opt_type) {
+ errtype = "malformed";
+ if (opt_type == ip6opt_ls) {
+ optused = 2 + optptr[1];
+ if (optused > optlen)
+ goto bad_opt;
+ } else switch (opt_type) {
case IP6OPT_PADN:
/*
* Note:We don't verify that (N-2) pad octets
@@ -6324,16 +6540,22 @@
break;
default:
+ errtype = "unknown";
+ /* FALLTHROUGH */
opt_error:
- ip1dbg(("ip_process_options_v6: bad opt 0x%x\n",
- opt_type));
switch (IP6OPT_TYPE(opt_type)) {
case IP6OPT_TYPE_SKIP:
optused = 2 + optptr[1];
if (optused > optlen)
goto bad_opt;
+ ip1dbg(("ip_process_options_v6: %s "
+ "opt 0x%x skipped\n",
+ errtype, opt_type));
break;
case IP6OPT_TYPE_DISCARD:
+ ip1dbg(("ip_process_options_v6: %s "
+ "opt 0x%x; packet dropped\n",
+ errtype, opt_type));
freemsg(first_mp);
return (-1);
case IP6OPT_TYPE_ICMP:
@@ -6350,6 +6572,8 @@
(uint8_t *)ip6h),
B_FALSE, B_TRUE);
return (-1);
+ default:
+ ASSERT(0);
}
}
}
@@ -7014,6 +7238,18 @@
}
/*
+ * Attach any necessary label information to this packet.
+ */
+ if (is_system_labeled() && !tsol_get_pkt_label(mp, IPV6_VERSION)) {
+ if (ip6opt_ls != 0)
+ ip0dbg(("tsol_get_pkt_label v6 failed\n"));
+ BUMP_MIB(ill->ill_ip6_mib, ipv6InHdrErrors);
+ freemsg(hada_mp);
+ freemsg(first_mp);
+ return;
+ }
+
+ /*
* On incoming v6 multicast packets we will bypass the ire table,
* and assume that the read queue corresponds to the targetted
* interface.
@@ -7084,10 +7320,11 @@
*/
if (IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_dst)) {
ire = ire_ctable_lookup_v6(&ip6h->ip6_dst, NULL,
- IRE_CACHE|IRE_LOCAL, ill->ill_ipif, ALL_ZONES,
+ IRE_CACHE|IRE_LOCAL, ill->ill_ipif, ALL_ZONES, NULL,
MATCH_IRE_TYPE | MATCH_IRE_ILL_GROUP);
} else {
- ire = ire_cache_lookup_v6(&ip6h->ip6_dst, ALL_ZONES);
+ ire = ire_cache_lookup_v6(&ip6h->ip6_dst, ALL_ZONES,
+ MBLK_GETLABEL(mp));
}
if (ire == NULL) {
/*
@@ -7173,11 +7410,26 @@
*/
if (IN6_IS_ADDR_UNSPECIFIED(&ip6h->ip6_src)) {
BUMP_MIB(ill->ill_ip6_mib, ipv6ForwProhibits);
- freemsg(hada_mp);
freemsg(mp);
ire_refrele(ire);
return;
}
+
+ if (is_system_labeled()) {
+ mblk_t *mp1;
+
+ if ((mp1 = tsol_ip_forward(ire, mp)) == NULL) {
+ BUMP_MIB(ill->ill_ip6_mib, ipv6ForwProhibits);
+ freemsg(mp);
+ ire_refrele(ire);
+ return;
+ }
+ /* Size may have changed */
+ mp = mp1;
+ ip6h = (ip6_t *)mp->b_rptr;
+ pkt_len = msgdsize(mp);
+ }
+
if (pkt_len > ire->ire_max_frag) {
BUMP_MIB(ill->ill_ip6_mib, ipv6InTooBigErrors);
icmp_pkt2big_v6(WR(q), mp, ire->ire_max_frag,
@@ -7240,7 +7492,8 @@
src_ire_v6 = ire_ftable_lookup_v6(&ip6h->ip6_src,
NULL, NULL, IRE_INTERFACE, ire->ire_ipif, NULL,
- ALL_ZONES, 0, MATCH_IRE_IPIF | MATCH_IRE_TYPE);
+ ALL_ZONES, 0, NULL,
+ MATCH_IRE_IPIF | MATCH_IRE_TYPE);
if (src_ire_v6 != NULL) {
/*
@@ -7495,8 +7748,8 @@
}
sctph->sh_chksum = pktsum;
ports = *(uint32_t *)(mp->b_rptr + hdr_len);
- if ((connp = sctp_find_conn(&ip6h->ip6_src,
- &ip6h->ip6_dst, ports, ipif_id, zoneid)) == NULL) {
+ if ((connp = sctp_fanout(&ip6h->ip6_src, &ip6h->ip6_dst,
+ ports, ipif_id, zoneid, mp)) == NULL) {
ip_fanout_sctp_raw(first_mp, ill,
(ipha_t *)ip6h, B_FALSE, ports,
mctl_present,
@@ -8797,7 +9050,8 @@
addrptr += (numaddr - (rthdr->ip6r0_segleft + 1));
if (addrptr != NULL) {
ire = ire_ctable_lookup_v6(addrptr, NULL,
- IRE_LOCAL, NULL, ALL_ZONES, MATCH_IRE_TYPE);
+ IRE_LOCAL, NULL, ALL_ZONES, NULL,
+ MATCH_IRE_TYPE);
if (ire != NULL) {
ire_refrele(ire);
return (B_TRUE);
@@ -9213,7 +9467,7 @@
if (secpolicy_net_rawaccess(cr) != 0) {
ire = ire_route_lookup_v6(&ip6h->ip6_src,
0, 0, (IRE_LOCAL|IRE_LOOPBACK), NULL,
- NULL, zoneid,
+ NULL, zoneid, NULL,
MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY);
if (ire == NULL) {
if (do_outrequests)
@@ -9415,7 +9669,7 @@
* as it does not really have a real destination to
* talk to.
*/
- ire = ire_cache_lookup_v6(v6dstp, zoneid);
+ ire = ire_cache_lookup_v6(v6dstp, zoneid, MBLK_GETLABEL(mp));
} else {
/*
* IRE_MARK_CONDEMNED is marked in ire_delete. We don't
@@ -9441,7 +9695,8 @@
if (ire != NULL && sctp_ire == NULL)
IRE_REFRELE_NOTR(ire);
- ire = (ire_t *)ire_cache_lookup_v6(v6dstp, zoneid);
+ ire = ire_cache_lookup_v6(v6dstp, zoneid,
+ MBLK_GETLABEL(mp));
if (ire != NULL) {
IRE_REFHOLD_NOTR(ire);
@@ -9519,7 +9774,8 @@
* to initiate additional route resolutions.
*/
multirt_need_resolve =
- ire_multirt_need_resolve_v6(&ire->ire_addr_v6);
+ ire_multirt_need_resolve_v6(&ire->ire_addr_v6,
+ MBLK_GETLABEL(first_mp));
ip2dbg(("ip_wput_v6: ire %p, "
"multirt_need_resolve %d, first_mp %p\n",
(void *)ire, multirt_need_resolve,
@@ -9895,7 +10151,7 @@
* It is used only when ire_cache_lookup is used above.
*/
ire = ire_ctable_lookup_v6(v6dstp, 0, 0, ill->ill_ipif,
- zoneid, match_flags);
+ zoneid, MBLK_GETLABEL(mp), match_flags);
if (ire != NULL) {
/*
* Check if the ire has the RTF_MULTIRT flag, inherited
@@ -9933,7 +10189,8 @@
* to initiate additional route resolutions.
*/
multirt_need_resolve =
- ire_multirt_need_resolve_v6(&ire->ire_addr_v6);
+ ire_multirt_need_resolve_v6(&ire->ire_addr_v6,
+ MBLK_GETLABEL(first_mp));
ip2dbg(("ip_wput_v6[send_from_ill]: ire %p, "
"multirt_need_resolve %d, first_mp %p\n",
(void *)ire, multirt_need_resolve,
@@ -10413,7 +10670,8 @@
ip6h->ip6_hops = ill->ill_max_hops;
}
- if (ire->ire_type == IRE_LOCAL && ire->ire_zoneid != zoneid) {
+ if (ire->ire_type == IRE_LOCAL && ire->ire_zoneid != zoneid &&
+ ire->ire_zoneid != ALL_ZONES) {
/*
* When a zone sends a packet to another zone, we try to deliver
* the packet under the same conditions as if the destination
@@ -10423,7 +10681,7 @@
* ip_newroute_v6() does.
*/
ire_t *src_ire = ire_ftable_lookup_v6(&ip6h->ip6_dst, 0, 0, 0,
- NULL, NULL, zoneid, 0, (MATCH_IRE_RECURSIVE |
+ NULL, NULL, zoneid, 0, NULL, (MATCH_IRE_RECURSIVE |
MATCH_IRE_DEFAULT | MATCH_IRE_RJ_BHOLE));
if (src_ire != NULL &&
!(src_ire->ire_flags & (RTF_REJECT | RTF_BLACKHOLE))) {
@@ -11422,11 +11680,11 @@
* Unicast case: we match the conn only if it's in the specified
* zone.
*/
- return (connp->conn_zoneid == zoneid);
+ return (connp->conn_zoneid == zoneid || zoneid == ALL_ZONES);
}
if ((fanout_flags & IP_FF_NO_MCAST_LOOP) &&
- connp->conn_zoneid == zoneid) {
+ (connp->conn_zoneid == zoneid || zoneid == ALL_ZONES)) {
/*
* Loopback case: the sending endpoint has IP_MULTICAST_LOOP
* disabled, therefore we don't dispatch the multicast packet to
@@ -11436,7 +11694,7 @@
}
if ((ill->ill_phyint->phyint_flags & PHYI_LOOPBACK) &&
- connp->conn_zoneid != zoneid) {
+ connp->conn_zoneid != zoneid && zoneid != ALL_ZONES) {
/*
* Multicast packet on the loopback interface: we only match
* conns who joined the group in the specified zone.
@@ -12409,7 +12667,7 @@
continue;
ire_gw = ire_ftable_lookup_v6(&ire->ire_gateway_addr_v6, 0, 0,
- IRE_INTERFACE, NULL, NULL, ALL_ZONES, 0,
+ IRE_INTERFACE, NULL, NULL, ALL_ZONES, 0, NULL,
MATCH_IRE_RECURSIVE | MATCH_IRE_TYPE);
/* No resolver exists for the gateway; skip this ire. */
if (ire_gw == NULL)
@@ -12546,7 +12804,7 @@
secpolicy_net_rawaccess(cr) != 0) {
ire = ire_route_lookup_v6(&pkti->ipi6_addr, 0, 0,
(IRE_LOCAL|IRE_LOOPBACK), NULL, NULL,
- connp->conn_zoneid, MATCH_IRE_TYPE);
+ connp->conn_zoneid, NULL, MATCH_IRE_TYPE);
if (ire != NULL)
ire_refrele(ire);
else
--- a/usr/src/uts/common/inet/ip/ip6_if.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip/ip6_if.c Fri Mar 24 12:29:20 2006 -0800
@@ -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,6 @@
#include <sys/stream.h>
#include <sys/dlpi.h>
#include <sys/stropts.h>
-#include <sys/strlog.h>
#include <sys/ddi.h>
#include <sys/cmn_err.h>
#include <sys/kstat.h>
@@ -48,14 +46,10 @@
#include <sys/systm.h>
#include <sys/param.h>
#include <sys/socket.h>
-#define _SUN_TPI_VERSION 2
-#include <sys/tihdr.h>
#include <sys/isa_defs.h>
#include <net/if.h>
-#include <net/if_types.h>
#include <net/if_dl.h>
#include <net/route.h>
-#include <sys/sockio.h>
#include <netinet/in.h>
#include <netinet/igmp_var.h>
#include <netinet/ip6.h>
@@ -63,10 +57,8 @@
#include <netinet/in.h>
#include <inet/common.h>
-#include <inet/mi.h>
#include <inet/nd.h>
#include <inet/mib2.h>
-#include <inet/arp.h>
#include <inet/ip.h>
#include <inet/ip6.h>
#include <inet/ip_multi.h>
@@ -79,8 +71,8 @@
#include <inet/ipclassifier.h>
#include <inet/sctp_ip.h>
-#include <netinet/igmp.h>
-#include <netinet/ip_mroute.h>
+#include <sys/tsol/tndb.h>
+#include <sys/tsol/tnet.h>
static in6_addr_t ipv6_ll_template =
{(uint32_t)V6_LINKLOCAL, 0x0, 0x0, 0x0};
@@ -225,7 +217,9 @@
GRAB_CONN_LOCK(q);
mutex_enter(&ill->ill_lock);
for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
- if (zoneid != ALL_ZONES && ipif->ipif_zoneid != zoneid)
+ if (zoneid != ALL_ZONES &&
+ ipif->ipif_zoneid != zoneid &&
+ ipif->ipif_zoneid != ALL_ZONES)
continue;
/* Allow the ipif to be down */
if ((!ptp && (IN6_ARE_ADDR_EQUAL(
@@ -332,7 +326,8 @@
int
ip_rt_add_v6(const in6_addr_t *dst_addr, const in6_addr_t *mask,
const in6_addr_t *gw_addr, const in6_addr_t *src_addr, int flags,
- ipif_t *ipif_arg, ire_t **ire_arg, queue_t *q, mblk_t *mp, ipsq_func_t func)
+ ipif_t *ipif_arg, ire_t **ire_arg, queue_t *q, mblk_t *mp, ipsq_func_t func,
+ struct rtsa_s *sp)
{
ire_t *ire;
ire_t *gw_ire = NULL;
@@ -341,6 +336,9 @@
uint_t type;
int match_flags = MATCH_IRE_TYPE;
int error;
+ tsol_gc_t *gc = NULL;
+ tsol_gcgrp_t *gcgrp = NULL;
+ boolean_t gcgrp_xtraref = B_FALSE;
if (ire_arg != NULL)
*ire_arg = NULL;
@@ -433,6 +431,14 @@
if (!(flags & RTF_GATEWAY)) {
queue_t *stq;
+ if (sp != NULL) {
+ ip2dbg(("ip_rt_add_v6: gateway security attributes "
+ "cannot be set with interface route\n"));
+ if (ipif_refheld)
+ ipif_refrele(ipif);
+ return (EINVAL);
+ }
+
/*
* As the interface index specified with the RTA_IFP sockaddr is
* the same for all ipif's off of an ill, the matching logic
@@ -470,7 +476,7 @@
*/
match_flags |= MATCH_IRE_MASK;
ire = ire_ftable_lookup_v6(dst_addr, mask, 0, IRE_INTERFACE,
- ipif, NULL, ALL_ZONES, 0, match_flags);
+ ipif, NULL, ALL_ZONES, 0, NULL, match_flags);
if (ire != NULL) {
ire_refrele(ire);
if (ipif_refheld)
@@ -501,7 +507,9 @@
0,
0,
flags,
- &ire_uinfo_null);
+ &ire_uinfo_null,
+ NULL,
+ NULL);
if (ire == NULL) {
if (ipif_refheld)
ipif_refrele(ipif);
@@ -551,7 +559,7 @@
if (ipif_arg != NULL)
match_flags |= MATCH_IRE_ILL;
gw_ire = ire_ftable_lookup_v6(gw_addr, 0, 0, IRE_INTERFACE, ipif_arg,
- NULL, ALL_ZONES, 0, match_flags);
+ NULL, ALL_ZONES, 0, NULL, match_flags);
if (gw_ire == NULL)
return (ENETUNREACH);
@@ -572,13 +580,45 @@
/* check for a duplicate entry */
ire = ire_ftable_lookup_v6(dst_addr, mask, gw_addr, type, ipif_arg,
- NULL, ALL_ZONES, 0, match_flags | MATCH_IRE_MASK | MATCH_IRE_GW);
+ NULL, ALL_ZONES, 0, NULL,
+ match_flags | MATCH_IRE_MASK | MATCH_IRE_GW);
if (ire != NULL) {
ire_refrele(gw_ire);
ire_refrele(ire);
return (EEXIST);
}
+ /* Security attribute exists */
+ if (sp != NULL) {
+ tsol_gcgrp_addr_t ga;
+
+ /* find or create the gateway credentials group */
+ ga.ga_af = AF_INET6;
+ ga.ga_addr = *gw_addr;
+
+ /* we hold reference to it upon success */
+ gcgrp = gcgrp_lookup(&ga, B_TRUE);
+ if (gcgrp == NULL) {
+ ire_refrele(gw_ire);
+ return (ENOMEM);
+ }
+
+ /*
+ * Create and add the security attribute to the group; a
+ * reference to the group is made upon allocating a new
+ * entry successfully. If it finds an already-existing
+ * entry for the security attribute in the group, it simply
+ * returns it and no new reference is made to the group.
+ */
+ gc = gc_create(sp, gcgrp, &gcgrp_xtraref);
+ if (gc == NULL) {
+ /* release reference held by gcgrp_lookup */
+ GCGRP_REFRELE(gcgrp);
+ ire_refrele(gw_ire);
+ return (ENOMEM);
+ }
+ }
+
/* Create the IRE. */
ire = ire_create_v6(
dst_addr, /* dest address */
@@ -598,8 +638,19 @@
0,
0,
flags,
- &gw_ire->ire_uinfo); /* Inherit ULP info from gw */
+ &gw_ire->ire_uinfo, /* Inherit ULP info from gw */
+ gc, /* security attribute */
+ NULL);
+ /*
+ * The ire holds a reference to the 'gc' and the 'gc' holds a
+ * reference to the 'gcgrp'. We can now release the extra reference
+ * the 'gcgrp' acquired in the gcgrp_lookup, if it was not used.
+ */
+ if (gcgrp_xtraref)
+ GCGRP_REFRELE(gcgrp);
if (ire == NULL) {
+ if (gc != NULL)
+ GC_REFRELE(gc);
ire_refrele(gw_ire);
return (ENOMEM);
}
@@ -646,6 +697,17 @@
}
}
+ /*
+ * Now that the prefix IRE entry has been created, delete any
+ * existing gateway IRE cache entries as well as any IRE caches
+ * using the gateway, and force them to be created through
+ * ip_newroute_v6.
+ */
+ if (gc != NULL) {
+ ASSERT(gcgrp != NULL);
+ ire_clookup_delete_cache_gw_v6(gw_addr, ALL_ZONES);
+ }
+
save_ire:
if (gw_ire != NULL) {
ire_refrele(gw_ire);
@@ -768,10 +830,10 @@
if (ipif->ipif_ire_type == IRE_LOOPBACK)
ire = ire_ctable_lookup_v6(dst_addr, 0, IRE_LOOPBACK,
- ipif, ALL_ZONES, match_flags);
+ ipif, ALL_ZONES, NULL, match_flags);
if (ire == NULL)
ire = ire_ftable_lookup_v6(dst_addr, mask, 0,
- IRE_INTERFACE, ipif, NULL, ALL_ZONES, 0,
+ IRE_INTERFACE, ipif, NULL, ALL_ZONES, 0, NULL,
match_flags);
} else if (err == EINPROGRESS) {
return (err);
@@ -802,11 +864,11 @@
else
type = IRE_PREFIX;
ire = ire_ftable_lookup_v6(dst_addr, mask, gw_addr, type,
- ipif_arg, NULL, ALL_ZONES, 0, match_flags);
+ ipif_arg, NULL, ALL_ZONES, 0, NULL, match_flags);
if (ire == NULL && type == IRE_HOST) {
ire = ire_ftable_lookup_v6(dst_addr, mask, gw_addr,
IRE_HOST_REDIRECT, ipif_arg, NULL, ALL_ZONES, 0,
- match_flags);
+ NULL, match_flags);
}
}
@@ -1419,7 +1481,9 @@
0,
0,
ifrt->ifrt_flags,
- &ifrt->ifrt_iulp_info);
+ &ifrt->ifrt_iulp_info,
+ NULL,
+ NULL);
if (ire == NULL) {
mutex_exit(&ipif->ipif_saved_ire_lock);
kmem_free(ipif_saved_irep,
@@ -1528,6 +1592,7 @@
#define cand_srcaddr cand_ipif->ipif_v6lcl_addr
#define cand_flags cand_ipif->ipif_flags
#define cand_ill cand_ipif->ipif_ill
+#define cand_zoneid cand_ipif->ipif_zoneid
/* information about the destination for source address selection */
typedef struct dstinfo {
@@ -1787,6 +1852,23 @@
}
/*
+ * Prefer to use zone-specific addresses when possible instead of all-zones
+ * addresses.
+ */
+/* ARGSUSED2 */
+static rule_res_t
+rule_zone_specific(cand_t *bc, cand_t *cc, const dstinfo_t *dstinfo)
+{
+ if ((bc->cand_zoneid == ALL_ZONES) ==
+ (cc->cand_zoneid == ALL_ZONES))
+ return (CAND_TIE);
+ else if (cc->cand_zoneid == ALL_ZONES)
+ return (CAND_AVOID);
+ else
+ return (CAND_PREFER);
+}
+
+/*
* Determine the best source address given a destination address and a
* destination ill. If no suitable source address is found, it returns
* NULL. If there is a usable address pointed to by the usesrc
@@ -1828,6 +1910,7 @@
boolean_t first_candidate = B_TRUE;
rule_res_t rule_result;
phyint_t *phyi;
+ tsol_tpc_t *src_rhtp, *dst_rhtp;
/*
* The list of ordering rules. They are applied in the order they
@@ -1845,6 +1928,7 @@
rule_label,
rule_temporary,
rule_prefix,
+ rule_zone_specific,
NULL
};
@@ -1868,6 +1952,26 @@
dstinfo.dst_ill = dstill;
}
+ /*
+ * If we're dealing with an unlabeled destination on a labeled system,
+ * make sure that we ignore source addresses that are incompatible with
+ * the destination's default label. That destination's default label
+ * must dominate the minimum label on the source address.
+ *
+ * (Note that this has to do with Trusted Solaris. It's not related to
+ * the labels described by ip6_asp_lookup.)
+ */
+ dst_rhtp = NULL;
+ if (is_system_labeled()) {
+ dst_rhtp = find_tpc(dst, IPV6_VERSION, B_FALSE);
+ if (dst_rhtp == NULL)
+ return (NULL);
+ if (dst_rhtp->tpc_tp.host_type != UNLABELED) {
+ TPC_RELE(dst_rhtp);
+ dst_rhtp = NULL;
+ }
+ }
+
dstinfo.dst_addr = dst;
dstinfo.dst_scope = ip_addr_scope_v6(dst);
dstinfo.dst_label = ip6_asp_lookup(dst, NULL);
@@ -1936,9 +2040,37 @@
if (!IPIF_VALID_IPV6_SOURCE(ipif))
continue;
- if (zoneid != ALL_ZONES && ipif->ipif_zoneid != zoneid)
+ if (zoneid != ALL_ZONES &&
+ ipif->ipif_zoneid != zoneid &&
+ ipif->ipif_zoneid != ALL_ZONES)
continue;
+ /*
+ * Check compatibility of local address for
+ * destination's default label if we're on a labeled
+ * system. Incompatible addresses can't be used at
+ * all and must be skipped over.
+ */
+ if (dst_rhtp != NULL) {
+ boolean_t incompat;
+
+ src_rhtp = find_tpc(&ipif->ipif_v6lcl_addr,
+ IPV6_VERSION, B_FALSE);
+ if (src_rhtp == NULL)
+ continue;
+ incompat =
+ src_rhtp->tpc_tp.host_type != SUN_CIPSO ||
+ src_rhtp->tpc_tp.tp_doi !=
+ dst_rhtp->tpc_tp.tp_doi ||
+ (!_blinrange(&dst_rhtp->tpc_tp.tp_def_label,
+ &src_rhtp->tpc_tp.tp_sl_range_cipso) &&
+ !blinlset(&dst_rhtp->tpc_tp.tp_def_label,
+ src_rhtp->tpc_tp.tp_sl_set_cipso));
+ TPC_RELE(src_rhtp);
+ if (incompat)
+ continue;
+ }
+
if (first_candidate) {
/*
* This is first valid address in the list.
@@ -2014,6 +2146,9 @@
if (usesrc_ill != NULL)
ill_refrele(usesrc_ill);
+ if (dst_rhtp != NULL)
+ TPC_RELE(dst_rhtp);
+
if (ipif == NULL) {
rw_exit(&ill_g_lock);
return (NULL);
@@ -2152,7 +2287,9 @@
0,
0,
0,
- &ire_uinfo_null);
+ &ire_uinfo_null,
+ NULL,
+ NULL);
if (ire != NULL) {
ire_t *ret_ire;
@@ -2505,6 +2642,22 @@
if (!IN6_IS_ADDR_UNSPECIFIED(&ipif->ipif_v6lcl_addr) &&
!(ipif->ipif_flags & IPIF_NOLOCAL)) {
+
+ /*
+ * If we're on a labeled system then make sure that zone-
+ * private addresses have proper remote host database entries.
+ */
+ if (is_system_labeled() &&
+ ipif->ipif_ire_type != IRE_LOOPBACK) {
+ if (ip6opt_ls == 0) {
+ cmn_err(CE_WARN, "IPv6 not enabled "
+ "via /etc/system");
+ return (EINVAL);
+ }
+ if (!tsol_check_interface_address(ipif))
+ return (EINVAL);
+ }
+
/* Register the source address for __sin6_src_id */
err = ip_srcid_insert(&ipif->ipif_v6lcl_addr,
ipif->ipif_zoneid);
@@ -2541,7 +2694,9 @@
0,
0,
(ipif->ipif_flags & IPIF_PRIVATE) ? RTF_PRIVATE : 0,
- &ire_uinfo_null);
+ &ire_uinfo_null,
+ NULL,
+ NULL);
}
/*
@@ -2581,7 +2736,9 @@
0,
0,
(ipif->ipif_flags & IPIF_PRIVATE) ? RTF_PRIVATE : 0,
- &ire_uinfo_null);
+ &ire_uinfo_null,
+ NULL,
+ NULL);
}
/*
@@ -2608,7 +2765,7 @@
* this tunnel interface.
*/
isdup = ire_ftable_lookup_v6(first_addr, &prefix_mask, 0,
- IRE_IF_NORESOLVER, ill->ill_ipif, NULL, ALL_ZONES, 0,
+ IRE_IF_NORESOLVER, ill->ill_ipif, NULL, ALL_ZONES, 0, NULL,
(MATCH_IRE_SRC | MATCH_IRE_MASK));
if (isdup == NULL) {
@@ -2632,7 +2789,9 @@
0,
0,
RTF_UP,
- &ire_uinfo_null);
+ &ire_uinfo_null,
+ NULL,
+ NULL);
} else {
ire_refrele(isdup);
}
--- a/usr/src/uts/common/inet/ip/ip6_ire.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip/ip6_ire.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
/*
@@ -35,8 +34,6 @@
#include <sys/types.h>
#include <sys/stream.h>
#include <sys/stropts.h>
-#include <sys/strlog.h>
-#include <sys/dlpi.h>
#include <sys/ddi.h>
#include <sys/cmn_err.h>
@@ -54,16 +51,17 @@
#include <inet/mi.h>
#include <inet/ip.h>
#include <inet/ip6.h>
-#include <inet/arp.h>
#include <inet/ip_ndp.h>
#include <inet/ip_if.h>
#include <inet/ip_ire.h>
-#include <inet/ip_rts.h>
#include <inet/ipclassifier.h>
#include <inet/nd.h>
#include <sys/kmem.h>
#include <sys/zone.h>
+#include <sys/tsol/label.h>
+#include <sys/tsol/tnet.h>
+
irb_t *ip_forwarding_table_v6[IP6_MASK_TABLE_SIZE];
/* This is dynamically allocated in ip_ire_init */
irb_t *ip_cache_table_v6;
@@ -77,8 +75,9 @@
static void ire_report_ftable_v6(ire_t *ire, char *mp);
static void ire_report_ctable_v6(ire_t *ire, char *mp);
static boolean_t ire_match_args_v6(ire_t *ire, const in6_addr_t *addr,
- const in6_addr_t *mask, const in6_addr_t *gateway, int type, ipif_t *ipif,
- zoneid_t zoneid, uint32_t ihandle, int match_flags);
+ const in6_addr_t *mask, const in6_addr_t *gateway, int type,
+ const ipif_t *ipif, zoneid_t zoneid, uint32_t ihandle,
+ const ts_label_t *tsl, int match_flags);
/*
* Named Dispatch routine to produce a formatted report on all IREs.
@@ -270,8 +269,16 @@
const in6_addr_t *v6gateway, uint_t *max_fragp,
mblk_t *fp_mp, queue_t *rfq, queue_t *stq, ushort_t type,
mblk_t *dlureq_mp, ipif_t *ipif, const in6_addr_t *v6cmask,
- uint32_t phandle, uint32_t ihandle, uint_t flags, const iulp_t *ulp_info)
+ uint32_t phandle, uint32_t ihandle, uint_t flags, const iulp_t *ulp_info,
+ tsol_gc_t *gc, tsol_gcgrp_t *gcgrp)
{
+ /*
+ * Reject IRE security attribute creation/initialization
+ * if system is not running in Trusted mode.
+ */
+ if ((gc != NULL || gcgrp != NULL) && !is_system_labeled())
+ return (NULL);
+
if (fp_mp != NULL) {
/*
* We can't dupb() here as multiple threads could be
@@ -321,8 +328,11 @@
ire->ire_frag_flag = IPH_FRAG_HDR;
}
- ire_init_common(ire, max_fragp, fp_mp, rfq, stq, type, dlureq_mp,
- ipif, NULL, phandle, ihandle, flags, IPV6_VERSION, ulp_info);
+ /* ire_init_common will free the mblks upon encountering any failure */
+ if (!ire_init_common(ire, max_fragp, fp_mp, rfq, stq, type, dlureq_mp,
+ ipif, NULL, phandle, ihandle, flags, IPV6_VERSION, ulp_info,
+ gc, gcgrp))
+ return (NULL);
return (ire);
}
@@ -337,7 +347,8 @@
const in6_addr_t *v6src_addr, const in6_addr_t *v6gateway,
mblk_t *fp_mp, queue_t *rfq, queue_t *stq, ushort_t type,
mblk_t *dlureq_mp, ipif_t *ipif, const in6_addr_t *v6cmask,
- uint32_t phandle, uint32_t ihandle, uint_t flags, const iulp_t *ulp_info)
+ uint32_t phandle, uint32_t ihandle, uint_t flags, const iulp_t *ulp_info,
+ tsol_gc_t *gc, tsol_gcgrp_t *gcgrp)
{
ire_t *ire;
ire_t *ret_ire;
@@ -362,7 +373,7 @@
ret_ire = ire_init_v6(ire, v6addr, v6mask, v6src_addr, v6gateway,
NULL, fp_mp, rfq, stq, type, dlureq_mp, ipif, v6cmask, phandle,
- ihandle, flags, ulp_info);
+ ihandle, flags, ulp_info, gc, gcgrp);
if (ret_ire == NULL) {
freeb(ire->ire_mp);
@@ -382,7 +393,8 @@
const in6_addr_t *v6src_addr, const in6_addr_t *v6gateway,
uint_t *max_fragp, mblk_t *fp_mp, queue_t *rfq, queue_t *stq, ushort_t type,
mblk_t *dlureq_mp, ipif_t *ipif, const in6_addr_t *v6cmask,
- uint32_t phandle, uint32_t ihandle, uint_t flags, const iulp_t *ulp_info)
+ uint32_t phandle, uint32_t ihandle, uint_t flags, const iulp_t *ulp_info,
+ tsol_gc_t *gc, tsol_gcgrp_t *gcgrp)
{
ire_t *ire;
ire_t *ret_ire;
@@ -398,7 +410,7 @@
ret_ire = ire_init_v6(ire, v6addr, v6mask, v6src_addr, v6gateway,
max_fragp, fp_mp, rfq, stq, type, dlureq_mp, ipif, v6cmask, phandle,
- ihandle, flags, ulp_info);
+ ihandle, flags, ulp_info, gc, gcgrp);
if (ret_ire == NULL) {
kmem_cache_free(ire_cache, ire);
@@ -427,7 +439,7 @@
in6_addr_t gw_addr_v6;
ire = ire_ftable_lookup_v6(group, 0, 0, 0, NULL, NULL,
- zoneid, 0, MATCH_IRE_DEFAULT);
+ zoneid, 0, NULL, MATCH_IRE_DEFAULT);
/* We search a resolvable ire in case of multirouting. */
if ((ire != NULL) && (ire->ire_flags & RTF_MULTIRT)) {
@@ -437,7 +449,8 @@
* may be changed here. In that case, ire_multirt_lookup()
* IRE_REFRELE the original ire and change it.
*/
- (void) ire_multirt_lookup_v6(&cire, &ire, MULTIRT_CACHEGW);
+ (void) ire_multirt_lookup_v6(&cire, &ire, MULTIRT_CACHEGW,
+ NULL);
if (cire != NULL)
ire_refrele(cire);
}
@@ -466,7 +479,7 @@
ire_refrele(ire);
ire = ire_ftable_lookup_v6(&gw_addr_v6, 0, 0,
IRE_INTERFACE, ipif, NULL, zoneid, 0,
- match_flags);
+ NULL, match_flags);
return (ire);
case IRE_IF_NORESOLVER:
case IRE_IF_RESOLVER:
@@ -497,7 +510,8 @@
rw_enter(&irb->irb_lock, RW_READER);
for (ire = irb->irb_ire; ire; ire = ire->ire_next) {
if ((ire->ire_marks & IRE_MARK_CONDEMNED) ||
- ire->ire_zoneid != zoneid)
+ ire->ire_zoneid != zoneid &&
+ ire->ire_zoneid != ALL_ZONES)
continue;
switch (ire->ire_type) {
case IRE_LOOPBACK:
@@ -847,7 +861,8 @@
continue;
if (ire_match_args_v6(ire1, &ire->ire_addr_v6,
&ire->ire_mask_v6, &ire->ire_gateway_addr_v6,
- ire->ire_type, ire->ire_ipif, ire->ire_zoneid, 0, flags)) {
+ ire->ire_type, ire->ire_ipif, ire->ire_zoneid, 0, NULL,
+ flags)) {
/*
* Return the old ire after doing a REFHOLD.
* As most of the callers continue to use the IRE
@@ -1066,7 +1081,7 @@
if (ip_mask_to_plen_v6(&ire->ire_mask_v6) == IPV6_ABITS) {
ire_t *lire;
lire = ire_ctable_lookup_v6(&ire->ire_addr_v6, NULL,
- IRE_CACHE, NULL, ALL_ZONES, MATCH_IRE_TYPE);
+ IRE_CACHE, NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (lire != NULL) {
ire_refrele(lire);
ire_flush_cache_v6(ire, IRE_FLUSH_ADD);
@@ -1385,8 +1400,8 @@
*/
static boolean_t
ire_match_args_v6(ire_t *ire, const in6_addr_t *addr, const in6_addr_t *mask,
- const in6_addr_t *gateway, int type, ipif_t *ipif, zoneid_t zoneid,
- uint32_t ihandle, int match_flags)
+ const in6_addr_t *gateway, int type, const ipif_t *ipif, zoneid_t zoneid,
+ uint32_t ihandle, const ts_label_t *tsl, int match_flags)
{
in6_addr_t masked_addr;
in6_addr_t gw_addr_v6;
@@ -1416,7 +1431,8 @@
(ire->ire_marks & IRE_MARK_HIDDEN))
return (B_FALSE);
- if (zoneid != ALL_ZONES && zoneid != ire->ire_zoneid) {
+ if (zoneid != ALL_ZONES && zoneid != ire->ire_zoneid &&
+ ire->ire_zoneid != ALL_ZONES) {
/*
* If MATCH_IRE_ZONEONLY has been set and the supplied zoneid is
* valid and does not match that of ire_zoneid, a failure to
@@ -1486,7 +1502,8 @@
tipif != NULL; tipif = tipif->ipif_next) {
if (IPIF_CAN_LOOKUP(tipif) &&
(tipif->ipif_flags & IPIF_UP) &&
- (tipif->ipif_zoneid == zoneid))
+ (tipif->ipif_zoneid == zoneid ||
+ tipif->ipif_zoneid == ALL_ZONES))
break;
}
mutex_exit(&ire->ire_ipif->ipif_ill->ill_lock);
@@ -1541,7 +1558,10 @@
((!(match_flags & MATCH_IRE_ILL_GROUP)) ||
(ire_ill == ipif_ill) ||
(ire_ill_group != NULL &&
- ire_ill_group == ipif_ill_group))) {
+ ire_ill_group == ipif_ill_group)) &&
+ ((!(match_flags & MATCH_IRE_SECATTR)) ||
+ (!is_system_labeled()) ||
+ (tsol_ire_match_gwattr(ire, tsl) == 0))) {
/* We found the matched IRE */
return (B_TRUE);
}
@@ -1553,8 +1573,8 @@
*/
ire_t *
ire_route_lookup_v6(const in6_addr_t *addr, const in6_addr_t *mask,
- const in6_addr_t *gateway, int type, ipif_t *ipif, ire_t **pire,
- zoneid_t zoneid, int flags)
+ const in6_addr_t *gateway, int type, const ipif_t *ipif, ire_t **pire,
+ zoneid_t zoneid, const ts_label_t *tsl, int flags)
{
ire_t *ire = NULL;
@@ -1576,13 +1596,13 @@
*/
if ((flags & MATCH_IRE_TYPE) == 0 || (type & IRE_CACHETABLE) != 0) {
ire = ire_ctable_lookup_v6(addr, gateway, type, ipif, zoneid,
- flags);
+ tsl, flags);
if (ire != NULL)
return (ire);
}
if ((flags & MATCH_IRE_TYPE) == 0 || (type & IRE_FORWARDTABLE) != 0) {
ire = ire_ftable_lookup_v6(addr, mask, gateway, type, ipif,
- pire, zoneid, 0, flags);
+ pire, zoneid, 0, tsl, flags);
}
return (ire);
}
@@ -1620,8 +1640,8 @@
*/
ire_t *
ire_ftable_lookup_v6(const in6_addr_t *addr, const in6_addr_t *mask,
- const in6_addr_t *gateway, int type, ipif_t *ipif, ire_t **pire,
- zoneid_t zoneid, uint32_t ihandle, int flags)
+ const in6_addr_t *gateway, int type, const ipif_t *ipif, ire_t **pire,
+ zoneid_t zoneid, uint32_t ihandle, const ts_label_t *tsl, int flags)
{
irb_t *irb_ptr;
ire_t *rire;
@@ -1671,7 +1691,7 @@
if (ire->ire_marks & IRE_MARK_CONDEMNED)
continue;
if (ire_match_args_v6(ire, addr, mask, gateway, type,
- ipif, zoneid, ihandle, flags))
+ ipif, zoneid, ihandle, tsl, flags))
goto found_ire;
}
rw_exit(&irb_ptr->irb_lock);
@@ -1697,7 +1717,7 @@
continue;
if (ire_match_args_v6(ire, addr,
&ire->ire_mask_v6, gateway, type, ipif,
- zoneid, ihandle, flags))
+ zoneid, ihandle, tsl, flags))
goto found_ire;
}
rw_exit(&irb_ptr->irb_lock);
@@ -1732,7 +1752,7 @@
if (ire_match_args_v6(ire, addr,
&ipv6_all_zeros, gateway, type, ipif,
- zoneid, ihandle, flags))
+ zoneid, ihandle, tsl, flags))
goto found_ire;
}
rw_exit(&irb_ptr->irb_lock);
@@ -1815,7 +1835,7 @@
if (ire_match_args_v6(ire, addr,
&ipv6_all_zeros, gateway, type, ipif,
- zoneid, ihandle, flags)) {
+ zoneid, ihandle, tsl, flags)) {
int match_flags;
/*
@@ -1831,9 +1851,10 @@
mutex_enter(&ire->ire_lock);
gw_addr_v6 = ire->ire_gateway_addr_v6;
mutex_exit(&ire->ire_lock);
- match_flags = MATCH_IRE_ILL_GROUP;
+ match_flags = MATCH_IRE_ILL_GROUP |
+ MATCH_IRE_SECATTR;
rire = ire_ctable_lookup_v6(&gw_addr_v6, NULL,
- 0, ire->ire_ipif, zoneid, match_flags);
+ 0, ire->ire_ipif, zoneid, tsl, match_flags);
if (rire != NULL) {
nce = rire->ire_nce;
if (nce != NULL &&
@@ -1867,7 +1888,7 @@
*/
rire = ire_route_lookup_v6(&gw_addr_v6,
NULL, NULL, 0, ire->ire_ipif, NULL,
- zoneid, match_flags);
+ zoneid, tsl, match_flags);
if (rire != NULL) {
ire_refrele(rire);
saved_ire = ire;
@@ -1903,7 +1924,7 @@
if (ire_match_args_v6(ire, addr,
&ipv6_all_zeros, gateway, type, ipif,
- zoneid, ihandle, flags)) {
+ zoneid, ihandle, tsl, flags)) {
IRE_REFHOLD(ire);
IRB_REFRELE(irb_ptr);
goto found_ire_held;
@@ -1937,7 +1958,7 @@
* of lookup is done.
*/
if (flags & MATCH_IRE_RECURSIVE) {
- ipif_t *gw_ipif;
+ const ipif_t *gw_ipif;
int match_flags = MATCH_IRE_DSTONLY;
if (ire->ire_type & IRE_INTERFACE)
@@ -1971,7 +1992,7 @@
mutex_exit(&ire->ire_lock);
ire = ire_route_lookup_v6(&gw_addr_v6, NULL, NULL, 0,
- ire->ire_ipif, NULL, zoneid, match_flags);
+ ire->ire_ipif, NULL, zoneid, tsl, match_flags);
if (ire == NULL) {
/*
* In this case we have to deal with the
@@ -2018,7 +2039,7 @@
ire_refrele(ire);
ire = ire_route_lookup_v6(&gw_addr_v6, NULL, NULL,
(IRE_CACHETABLE | IRE_INTERFACE), gw_ipif, NULL, zoneid,
- match_flags);
+ NULL, match_flags);
if (ire == NULL) {
/*
* In this case we have to deal with the
@@ -2061,6 +2082,34 @@
}
/*
+ * Delete the IRE cache for the gateway and all IRE caches whose
+ * ire_gateway_addr_v6 points to this gateway, and allow them to
+ * be created on demand by ip_newroute_v6.
+ */
+void
+ire_clookup_delete_cache_gw_v6(const in6_addr_t *addr, zoneid_t zoneid)
+{
+ irb_t *irb;
+ ire_t *ire;
+
+ irb = &ip_cache_table_v6[IRE_ADDR_HASH_V6(*addr, ip6_cache_table_size)];
+ IRB_REFHOLD(irb);
+ for (ire = irb->irb_ire; ire != NULL; ire = ire->ire_next) {
+ if (ire->ire_marks & IRE_MARK_CONDEMNED)
+ continue;
+
+ ASSERT(IN6_ARE_ADDR_EQUAL(&ire->ire_mask_v6, &ipv6_all_ones));
+ if (ire_match_args_v6(ire, addr, &ire->ire_mask_v6, 0,
+ IRE_CACHE, NULL, zoneid, 0, NULL, MATCH_IRE_TYPE)) {
+ ire_delete(ire);
+ }
+ }
+ IRB_REFRELE(irb);
+
+ ire_walk_v6(ire_delete_cache_gw_v6, (char *)addr, zoneid);
+}
+
+/*
* Looks up cache table for a route.
* specific lookup can be indicated by
* passing the MATCH_* flags and the
@@ -2068,7 +2117,8 @@
*/
ire_t *
ire_ctable_lookup_v6(const in6_addr_t *addr, const in6_addr_t *gateway,
- int type, ipif_t *ipif, zoneid_t zoneid, int flags)
+ int type, const ipif_t *ipif, zoneid_t zoneid, const ts_label_t *tsl,
+ int flags)
{
ire_t *ire;
irb_t *irb_ptr;
@@ -2092,7 +2142,7 @@
ASSERT(IN6_ARE_ADDR_EQUAL(&ire->ire_mask_v6, &ipv6_all_ones));
if (ire_match_args_v6(ire, addr, &ire->ire_mask_v6, gateway,
- type, ipif, zoneid, 0, flags)) {
+ type, ipif, zoneid, 0, tsl, flags)) {
IRE_REFHOLD(ire);
rw_exit(&irb_ptr->irb_lock);
return (ire);
@@ -2108,7 +2158,8 @@
* to the hidden ones.
*/
ire_t *
-ire_cache_lookup_v6(const in6_addr_t *addr, zoneid_t zoneid)
+ire_cache_lookup_v6(const in6_addr_t *addr, zoneid_t zoneid,
+ const ts_label_t *tsl)
{
irb_t *irb_ptr;
ire_t *ire;
@@ -2120,7 +2171,19 @@
if (ire->ire_marks & (IRE_MARK_CONDEMNED|IRE_MARK_HIDDEN))
continue;
if (IN6_ARE_ADDR_EQUAL(&ire->ire_addr_v6, addr)) {
+ /*
+ * Finally, check if the security policy has any
+ * restriction on using this route for the specified
+ * message.
+ */
+ if (tsl != NULL &&
+ ire->ire_gw_secattr != NULL &&
+ tsol_ire_match_gwattr(ire, tsl) != 0) {
+ continue;
+ }
+
if (zoneid == ALL_ZONES || ire->ire_zoneid == zoneid ||
+ ire->ire_zoneid == ALL_ZONES ||
ire->ire_type == IRE_LOCAL) {
IRE_REFHOLD(ire);
rw_exit(&irb_ptr->irb_lock);
@@ -2160,7 +2223,7 @@
*/
ire = ire_ftable_lookup_v6(&cire->ire_addr_v6, &cire->ire_cmask_v6,
NULL, IRE_INTERFACE, NULL, NULL, ALL_ZONES, cire->ire_ihandle,
- match_flags);
+ NULL, match_flags);
if (ire != NULL)
return (ire);
/*
@@ -2246,7 +2309,7 @@
*/
ire = ire_ftable_lookup_v6(&cire->ire_addr_v6, &cire->ire_cmask_v6, 0,
IRE_INTERFACE, pire->ire_ipif, NULL, ALL_ZONES, cire->ire_ihandle,
- match_flags);
+ NULL, match_flags);
if (ire != NULL)
return (ire);
/*
@@ -2281,7 +2344,7 @@
gw_addr = pire->ire_gateway_addr_v6;
mutex_exit(&pire->ire_lock);
ire = ire_ftable_lookup_v6(&gw_addr, 0, 0, IRE_OFFSUBNET,
- pire->ire_ipif, NULL, ALL_ZONES, 0, match_flags);
+ pire->ire_ipif, NULL, ALL_ZONES, 0, NULL, match_flags);
if (ire == NULL)
return (NULL);
/*
@@ -2296,7 +2359,8 @@
match_flags |= MATCH_IRE_IHANDLE;
ire = ire_ftable_lookup_v6(&gw_addr, 0, 0, IRE_INTERFACE,
- gw_ipif, NULL, ALL_ZONES, cire->ire_ihandle, match_flags);
+ gw_ipif, NULL, ALL_ZONES, cire->ire_ihandle,
+ NULL, match_flags);
return (ire);
}
@@ -2313,24 +2377,25 @@
* (Sometimes called as writer though not required by this function.)
*/
ire_t *
-ipif_to_ire_v6(ipif_t *ipif)
+ipif_to_ire_v6(const ipif_t *ipif)
{
ire_t *ire;
ASSERT(ipif->ipif_isv6);
if (ipif->ipif_ire_type == IRE_LOOPBACK) {
ire = ire_ctable_lookup_v6(&ipif->ipif_v6lcl_addr, NULL,
- IRE_LOOPBACK, ipif, ALL_ZONES,
+ IRE_LOOPBACK, ipif, ALL_ZONES, NULL,
(MATCH_IRE_TYPE | MATCH_IRE_IPIF));
} else if (ipif->ipif_flags & IPIF_POINTOPOINT) {
/* In this case we need to lookup destination address. */
ire = ire_ftable_lookup_v6(&ipif->ipif_v6pp_dst_addr,
&ipv6_all_ones, NULL, IRE_INTERFACE, ipif, NULL, ALL_ZONES,
- 0, (MATCH_IRE_TYPE | MATCH_IRE_IPIF | MATCH_IRE_MASK));
+ 0, NULL, (MATCH_IRE_TYPE | MATCH_IRE_IPIF |
+ MATCH_IRE_MASK));
} else {
ire = ire_ftable_lookup_v6(&ipif->ipif_v6subnet,
&ipif->ipif_v6net_mask, NULL, IRE_INTERFACE, ipif, NULL,
- ALL_ZONES, 0, (MATCH_IRE_TYPE | MATCH_IRE_IPIF |
+ ALL_ZONES, 0, NULL, (MATCH_IRE_TYPE | MATCH_IRE_IPIF |
MATCH_IRE_MASK));
}
return (ire);
@@ -2342,7 +2407,7 @@
* This only works in the global zone.
*/
boolean_t
-ire_multirt_need_resolve_v6(const in6_addr_t *v6dstp)
+ire_multirt_need_resolve_v6(const in6_addr_t *v6dstp, const ts_label_t *tsl)
{
ire_t *first_fire;
ire_t *first_cire;
@@ -2355,7 +2420,8 @@
/* Retrieve the first IRE_HOST that matches the destination */
first_fire = ire_ftable_lookup_v6(v6dstp, &ipv6_all_ones, 0, IRE_HOST,
- NULL, NULL, ALL_ZONES, 0, MATCH_IRE_MASK | MATCH_IRE_TYPE);
+ NULL, NULL, ALL_ZONES, 0, tsl, MATCH_IRE_MASK | MATCH_IRE_TYPE |
+ MATCH_IRE_SECATTR);
/* No route at all */
if (first_fire == NULL) {
@@ -2366,7 +2432,7 @@
ASSERT(firb);
/* Retrieve the first IRE_CACHE ire for that destination. */
- first_cire = ire_cache_lookup_v6(v6dstp, GLOBAL_ZONEID);
+ first_cire = ire_cache_lookup_v6(v6dstp, GLOBAL_ZONEID, tsl);
/* No resolved route. */
if (first_cire == NULL) {
@@ -2407,7 +2473,7 @@
/* At least one route is unresolved; search for a resolvable route. */
if (unres_cnt > 0)
resolvable = ire_multirt_lookup_v6(&first_cire, &first_fire,
- MULTIRT_USESTAMP|MULTIRT_CACHEGW);
+ MULTIRT_USESTAMP|MULTIRT_CACHEGW, tsl);
if (first_fire)
ire_refrele(first_fire);
@@ -2427,7 +2493,8 @@
* This only works in the global zone.
*/
boolean_t
-ire_multirt_lookup_v6(ire_t **ire_arg, ire_t **fire_arg, uint32_t flags)
+ire_multirt_lookup_v6(ire_t **ire_arg, ire_t **fire_arg, uint32_t flags,
+ const ts_label_t *tsl)
{
clock_t delta;
ire_t *best_fire = NULL;
@@ -2473,7 +2540,7 @@
* if we don't find one, no route for that dest is
* resolved yet.
*/
- first_cire = ire_cache_lookup_v6(&v6dst, GLOBAL_ZONEID);
+ first_cire = ire_cache_lookup_v6(&v6dst, GLOBAL_ZONEID, tsl);
if (first_cire) {
cirb = first_cire->ire_bucket;
}
@@ -2499,6 +2566,11 @@
if (!IN6_ARE_ADDR_EQUAL(&fire->ire_addr_v6, &v6dst))
continue;
+ if (fire->ire_gw_secattr != NULL &&
+ tsol_ire_match_gwattr(fire, tsl) != 0) {
+ continue;
+ }
+
mutex_enter(&fire->ire_lock);
v6gw = fire->ire_gateway_addr_v6;
mutex_exit(&fire->ire_lock);
@@ -2532,6 +2604,13 @@
(IRE_MARK_CONDEMNED|
IRE_MARK_HIDDEN))
continue;
+
+ if (cire->ire_gw_secattr != NULL &&
+ tsol_ire_match_gwattr(cire,
+ tsl) != 0) {
+ continue;
+ }
+
/*
* Check if the IRE_CACHE's gateway
* matches the IRE_HOST's gateway.
@@ -2562,7 +2641,8 @@
* for the gateway?
*/
gw_ire = ire_route_lookup_v6(&v6gw, 0, 0, 0, NULL, NULL,
- ALL_ZONES, MATCH_IRE_RECURSIVE);
+ ALL_ZONES, tsl, MATCH_IRE_RECURSIVE |
+ MATCH_IRE_SECATTR);
ip2dbg(("ire_multirt_lookup_v6: looked up gw_ire %p\n",
(void *)gw_ire));
@@ -2684,6 +2764,11 @@
if (!IN6_ARE_ADDR_EQUAL(&fire->ire_addr_v6, &v6dst))
continue;
+ if (fire->ire_gw_secattr != NULL &&
+ tsol_ire_match_gwattr(fire, tsl) != 0) {
+ continue;
+ }
+
already_resolved = B_FALSE;
mutex_enter(&fire->ire_lock);
@@ -2691,8 +2776,9 @@
mutex_exit(&fire->ire_lock);
gw_ire = ire_ftable_lookup_v6(&v6gw, 0, 0,
- IRE_INTERFACE, NULL, NULL, ALL_ZONES, 0,
- MATCH_IRE_RECURSIVE | MATCH_IRE_TYPE);
+ IRE_INTERFACE, NULL, NULL, ALL_ZONES, 0, tsl,
+ MATCH_IRE_RECURSIVE | MATCH_IRE_TYPE |
+ MATCH_IRE_SECATTR);
/* No resolver for the gateway; we skip this ire. */
if (gw_ire == NULL) {
@@ -2719,6 +2805,13 @@
(IRE_MARK_CONDEMNED|
IRE_MARK_HIDDEN))
continue;
+
+ if (cire->ire_gw_secattr != NULL &&
+ tsol_ire_match_gwattr(cire,
+ tsl) != 0) {
+ continue;
+ }
+
/*
* Cache entries are linked to the
* parent routes using the parent handle
@@ -2843,7 +2936,7 @@
int match_flags = MATCH_IRE_TYPE | MATCH_IRE_ILL;
ire = ire_ftable_lookup_v6(v6dstp, 0, 0, 0, NULL, NULL, ALL_ZONES, 0,
- MATCH_IRE_DEFAULT);
+ NULL, MATCH_IRE_DEFAULT);
if (ire == NULL)
return (NULL);
@@ -2855,7 +2948,8 @@
ire_refrele(ire);
for (ire = irb->irb_ire; ire != NULL; ire = ire->ire_next) {
if (!IN6_ARE_ADDR_EQUAL(&ire->ire_addr_v6, v6dstp) ||
- ipif->ipif_zoneid != ire->ire_zoneid) {
+ (ipif->ipif_zoneid != ire->ire_zoneid &&
+ ire->ire_zoneid != ALL_ZONES)) {
continue;
}
@@ -2868,7 +2962,7 @@
mutex_exit(&ire->ire_lock);
gw_ire = ire_ftable_lookup_v6(&v6gw, 0, 0,
IRE_INTERFACE, ipif, NULL, ALL_ZONES, 0,
- match_flags);
+ NULL, match_flags);
if (gw_ire != NULL) {
if (save_ire != NULL) {
--- a/usr/src/uts/common/inet/ip/ip6_rts.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip/ip6_rts.c Fri Mar 24 12:29:20 2006 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 1992-2002 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -72,6 +72,8 @@
#include <inet/ip_ire.h>
#include <inet/ip_rts.h>
#include <inet/ip_multi.h>
+#include <sys/tsol/tndb.h>
+#include <sys/tsol/tnet.h>
/*
* Fills the message with the given info.
@@ -80,7 +82,8 @@
rts_fill_msg_v6(int type, int rtm_addrs, const in6_addr_t *dst,
const in6_addr_t *mask, const in6_addr_t *gateway,
const in6_addr_t *src_addr, const in6_addr_t *brd_addr,
- const in6_addr_t *author, ipif_t *ipif, mblk_t *mp)
+ const in6_addr_t *author, const ipif_t *ipif, mblk_t *mp,
+ uint_t sacnt, const tsol_gc_t *gc)
{
rt_msghdr_t *rtm;
sin6_t *sin6;
@@ -89,6 +92,7 @@
int i;
ASSERT(mp != NULL);
+ ASSERT(sacnt == 0 || gc != NULL);
/*
* First find the type of the message
* and its length.
@@ -98,7 +102,7 @@
* Now find the size of the data
* that follows the message header.
*/
- data_size = rts_data_msg_size(rtm_addrs, AF_INET6);
+ data_size = rts_data_msg_size(rtm_addrs, AF_INET6, sacnt);
rtm = (rt_msghdr_t *)mp->b_rptr;
mp->b_wptr = &mp->b_rptr[header_size];
@@ -147,6 +151,32 @@
break;
}
}
+
+ if (gc != NULL) {
+ rtm_ext_t *rtm_ext;
+ struct rtsa_s *rp_dst;
+ tsol_rtsecattr_t *rsap;
+ int i;
+
+ ASSERT(gc->gc_grp != NULL);
+ ASSERT(RW_LOCK_HELD(&gc->gc_grp->gcgrp_rwlock));
+ ASSERT(sacnt > 0);
+
+ rtm_ext = (rtm_ext_t *)cp;
+ rtm_ext->rtmex_type = RTMEX_GATEWAY_SECATTR;
+ rtm_ext->rtmex_len = TSOL_RTSECATTR_SIZE(sacnt);
+
+ rsap = (tsol_rtsecattr_t *)(rtm_ext + 1);
+ rsap->rtsa_cnt = sacnt;
+ rp_dst = rsap->rtsa_attr;
+
+ for (i = 0; i < sacnt; i++, gc = gc->gc_next, rp_dst++) {
+ ASSERT(gc->gc_db != NULL);
+ bcopy(&gc->gc_db->gcdb_attr, rp_dst, sizeof (*rp_dst));
+ }
+ cp = (uchar_t *)rp_dst;
+ }
+
mp->b_wptr = cp;
mp->b_cont = NULL;
/*
@@ -176,11 +206,11 @@
if (rtm_addrs == 0)
return;
- mp = rts_alloc_msg(type, rtm_addrs, AF_INET6);
+ mp = rts_alloc_msg(type, rtm_addrs, AF_INET6, 0);
if (mp == NULL)
return;
rts_fill_msg_v6(type, rtm_addrs, dst_addr, net_mask, gw_addr, source,
- &ipv6_all_zeros, author, NULL, mp);
+ &ipv6_all_zeros, author, NULL, mp, 0, NULL);
rtm = (rt_msghdr_t *)mp->b_rptr;
rtm->rtm_flags = flags;
rtm->rtm_errno = error;
--- a/usr/src/uts/common/inet/ip/ip_if.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip/ip_if.c Fri Mar 24 12:29:20 2006 -0800
@@ -48,8 +48,6 @@
#include <sys/systm.h>
#include <sys/param.h>
#include <sys/socket.h>
-#define _SUN_TPI_VERSION 2
-#include <sys/tihdr.h>
#include <sys/isa_defs.h>
#include <net/if.h>
#include <net/if_arp.h>
@@ -92,13 +90,15 @@
#include <netinet/igmp.h>
#include <inet/ip_listutils.h>
-#include <netinet/ip_mroute.h>
#include <inet/ipclassifier.h>
#include <sys/mac.h>
#include <sys/systeminfo.h>
#include <sys/bootconf.h>
+#include <sys/tsol/tndb.h>
+#include <sys/tsol/tnet.h>
+
/* The character which tells where the ill_name ends */
#define IPIF_SEPARATOR_CHAR ':'
@@ -4553,7 +4553,7 @@
* creates datalink socket info from the device.
*/
int
-ill_dls_info(struct sockaddr_dl *sdl, ipif_t *ipif)
+ill_dls_info(struct sockaddr_dl *sdl, const ipif_t *ipif)
{
size_t length;
ill_t *ill = ipif->ipif_ill;
@@ -5096,7 +5096,8 @@
for (; ill != NULL; ill = ill_next(&ctx, ill)) {
for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
if (zoneid != GLOBAL_ZONEID &&
- zoneid != ipif->ipif_zoneid)
+ zoneid != ipif->ipif_zoneid &&
+ ipif->ipif_zoneid != ALL_ZONES)
continue;
(void) mi_mpprintf(mp,
MI_COL_PTRFMT_STR
@@ -5484,7 +5485,9 @@
mutex_enter(&ill->ill_lock);
for (ipif = ill->ill_ipif; ipif != NULL;
ipif = ipif->ipif_next) {
- if (zoneid != ALL_ZONES && zoneid != ipif->ipif_zoneid)
+ if (zoneid != ALL_ZONES &&
+ zoneid != ipif->ipif_zoneid &&
+ ipif->ipif_zoneid != ALL_ZONES)
continue;
/* Allow the ipif to be down */
if ((!ptp && (ipif->ipif_lcl_addr == addr) &&
@@ -5557,7 +5560,8 @@
for (ipif = ill->ill_ipif; ipif != NULL; ipif = ipif->ipif_next) {
if (!IPIF_CAN_LOOKUP(ipif))
continue;
- if (zoneid != ALL_ZONES && zoneid != ipif->ipif_zoneid)
+ if (zoneid != ALL_ZONES && zoneid != ipif->ipif_zoneid &&
+ ipif->ipif_zoneid != ALL_ZONES)
continue;
/* Allow the ipif to be down */
if (ipif->ipif_flags & IPIF_POINTOPOINT) {
@@ -5576,7 +5580,7 @@
}
mutex_exit(&ill->ill_lock);
ire = ire_route_lookup(addr, 0, 0, 0, NULL, NULL, zoneid,
- MATCH_IRE_RECURSIVE);
+ NULL, MATCH_IRE_RECURSIVE);
if (ire != NULL) {
/*
* The callers of this function wants to know the
@@ -6160,7 +6164,7 @@
ip_rt_add(ipaddr_t dst_addr, ipaddr_t mask, ipaddr_t gw_addr,
ipaddr_t src_addr, int flags, ipif_t *ipif_arg, ipif_t *src_ipif,
ire_t **ire_arg, boolean_t ioctl_msg, queue_t *q, mblk_t *mp,
- ipsq_func_t func)
+ ipsq_func_t func, struct rtsa_s *sp)
{
ire_t *ire;
ire_t *gw_ire = NULL;
@@ -6169,6 +6173,9 @@
uint_t type;
int match_flags = MATCH_IRE_TYPE;
int error;
+ tsol_gc_t *gc = NULL;
+ tsol_gcgrp_t *gcgrp = NULL;
+ boolean_t gcgrp_xtraref = B_FALSE;
ip1dbg(("ip_rt_add:"));
@@ -6280,6 +6287,14 @@
queue_t *rfq = NULL;
ill_t *in_ill = NULL;
+ if (sp != NULL) {
+ ip2dbg(("ip_rt_add: gateway security attributes "
+ "cannot be set with interface route\n"));
+ if (ipif_refheld)
+ ipif_refrele(ipif);
+ return (EINVAL);
+ }
+
/*
* As the interface index specified with the RTA_IFP sockaddr is
* the same for all ipif's off of an ill, the matching logic
@@ -6335,7 +6350,7 @@
} else {
ire = ire_ftable_lookup(dst_addr, mask, 0,
IRE_INTERFACE, ipif, NULL, ALL_ZONES, 0,
- match_flags);
+ NULL, match_flags);
}
if (ire != NULL) {
ire_refrele(ire);
@@ -6381,7 +6396,9 @@
0,
0,
flags,
- &ire_uinfo_null);
+ &ire_uinfo_null,
+ NULL,
+ NULL);
if (ire == NULL) {
if (ipif_refheld)
ipif_refrele(ipif);
@@ -6437,7 +6454,7 @@
if (ipif_arg != NULL)
match_flags |= MATCH_IRE_ILL;
gw_ire = ire_ftable_lookup(gw_addr, 0, 0, IRE_INTERFACE, ipif_arg, NULL,
- ALL_ZONES, 0, match_flags);
+ ALL_ZONES, 0, NULL, match_flags);
if (gw_ire == NULL)
return (ENETUNREACH);
@@ -6458,13 +6475,45 @@
/* check for a duplicate entry */
ire = ire_ftable_lookup(dst_addr, mask, gw_addr, type, ipif_arg,
- NULL, ALL_ZONES, 0, match_flags | MATCH_IRE_MASK | MATCH_IRE_GW);
+ NULL, ALL_ZONES, 0, NULL,
+ match_flags | MATCH_IRE_MASK | MATCH_IRE_GW);
if (ire != NULL) {
ire_refrele(gw_ire);
ire_refrele(ire);
return (EEXIST);
}
+ /* Security attribute exists */
+ if (sp != NULL) {
+ tsol_gcgrp_addr_t ga;
+
+ /* find or create the gateway credentials group */
+ ga.ga_af = AF_INET;
+ IN6_IPADDR_TO_V4MAPPED(gw_addr, &ga.ga_addr);
+
+ /* we hold reference to it upon success */
+ gcgrp = gcgrp_lookup(&ga, B_TRUE);
+ if (gcgrp == NULL) {
+ ire_refrele(gw_ire);
+ return (ENOMEM);
+ }
+
+ /*
+ * Create and add the security attribute to the group; a
+ * reference to the group is made upon allocating a new
+ * entry successfully. If it finds an already-existing
+ * entry for the security attribute in the group, it simply
+ * returns it and no new reference is made to the group.
+ */
+ gc = gc_create(sp, gcgrp, &gcgrp_xtraref);
+ if (gc == NULL) {
+ /* release reference held by gcgrp_lookup */
+ GCGRP_REFRELE(gcgrp);
+ ire_refrele(gw_ire);
+ return (ENOMEM);
+ }
+ }
+
/* Create the IRE. */
ire = ire_create(
(uchar_t *)&dst_addr, /* dest address */
@@ -6486,8 +6535,19 @@
0,
0,
flags,
- &gw_ire->ire_uinfo); /* Inherit ULP info from gw */
+ &gw_ire->ire_uinfo, /* Inherit ULP info from gw */
+ gc, /* security attribute */
+ NULL);
+ /*
+ * The ire holds a reference to the 'gc' and the 'gc' holds a
+ * reference to the 'gcgrp'. We can now release the extra reference
+ * the 'gcgrp' acquired in the gcgrp_lookup, if it was not used.
+ */
+ if (gcgrp_xtraref)
+ GCGRP_REFRELE(gcgrp);
if (ire == NULL) {
+ if (gc != NULL)
+ GC_REFRELE(gc);
ire_refrele(gw_ire);
return (ENOMEM);
}
@@ -6521,7 +6581,7 @@
* or a multicast.
*/
ire_t *ire_dst = ire_ctable_lookup(ire->ire_addr, 0,
- IRE_BROADCAST, NULL, NULL, MATCH_IRE_TYPE);
+ IRE_BROADCAST, NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (ire_dst != NULL) {
ip_cgtp_bcast_add(ire, ire_dst);
ire_refrele(ire_dst);
@@ -6541,6 +6601,17 @@
}
}
+ /*
+ * Now that the prefix IRE entry has been created, delete any
+ * existing gateway IRE cache entries as well as any IRE caches
+ * using the gateway, and force them to be created through
+ * ip_newroute.
+ */
+ if (gc != NULL) {
+ ASSERT(gcgrp != NULL);
+ ire_clookup_delete_cache_gw(gw_addr, ALL_ZONES);
+ }
+
save_ire:
if (gw_ire != NULL) {
ire_refrele(gw_ire);
@@ -6682,12 +6753,13 @@
} else {
if (ipif->ipif_ire_type == IRE_LOOPBACK) {
ire = ire_ctable_lookup(dst_addr, 0,
- IRE_LOOPBACK, ipif, ALL_ZONES, match_flags);
+ IRE_LOOPBACK, ipif, ALL_ZONES, NULL,
+ match_flags);
}
if (ire == NULL) {
ire = ire_ftable_lookup(dst_addr, mask, 0,
IRE_INTERFACE, ipif, NULL, ALL_ZONES, 0,
- match_flags);
+ NULL, match_flags);
}
}
}
@@ -6723,11 +6795,11 @@
else
type = IRE_PREFIX;
ire = ire_ftable_lookup(dst_addr, mask, gw_addr, type,
- ipif_arg, NULL, ALL_ZONES, 0, match_flags);
+ ipif_arg, NULL, ALL_ZONES, 0, NULL, match_flags);
if (ire == NULL && type == IRE_HOST) {
ire = ire_ftable_lookup(dst_addr, mask, gw_addr,
IRE_HOST_REDIRECT, ipif_arg, NULL,
- ALL_ZONES, 0, match_flags);
+ ALL_ZONES, 0, NULL, match_flags);
}
}
}
@@ -6810,8 +6882,8 @@
mask = ip_subnet_mask(dst_addr, &ipif);
}
- error = ip_rt_add(dst_addr, mask, gw_addr, 0, rt->rt_flags,
- NULL, NULL, NULL, B_TRUE, q, mp, ip_process_ioctl);
+ error = ip_rt_add(dst_addr, mask, gw_addr, 0, rt->rt_flags, NULL, NULL,
+ NULL, B_TRUE, q, mp, ip_process_ioctl, NULL);
if (ipif != NULL)
ipif_refrele(ipif);
return (error);
@@ -7791,7 +7863,8 @@
while (ill != NULL) {
for (ipif = ill->ill_ipif; ipif != NULL;
ipif = ipif->ipif_next) {
- if (ipif->ipif_zoneid == zoneid)
+ if (ipif->ipif_zoneid == zoneid ||
+ ipif->ipif_zoneid == ALL_ZONES)
numifs++;
}
ill = ill_next(&ctx, ill);
@@ -7840,6 +7913,7 @@
continue;
if (zoneid != ipif->ipif_zoneid &&
+ ipif->ipif_zoneid != ALL_ZONES &&
(zoneid != GLOBAL_ZONEID ||
!(lifn_flags & LIFC_ALLZONES)))
continue;
@@ -8027,7 +8101,8 @@
for (; ill != NULL; ill = ill_next(&ctx, ill)) {
for (ipif = ill->ill_ipif; ipif;
ipif = ipif->ipif_next) {
- if (zoneid != ipif->ipif_zoneid)
+ if (zoneid != ipif->ipif_zoneid &&
+ ipif->ipif_zoneid != ALL_ZONES)
continue;
if ((uchar_t *)&ifr[1] > mp1->b_wptr) {
if (iocp->ioc_cmd == O_SIOCGIFCONF) {
@@ -8313,6 +8388,7 @@
continue;
if (zoneid != ipif->ipif_zoneid &&
+ ipif->ipif_zoneid != ALL_ZONES &&
(zoneid != GLOBAL_ZONEID ||
!(flags & LIFC_ALLZONES)))
continue;
@@ -8529,10 +8605,10 @@
if (isipv4) {
IN6_V4MAPPED_TO_IPADDR(daddr, v4daddr);
ire = ire_ftable_lookup(v4daddr, NULL, NULL,
- 0, NULL, NULL, zoneid, 0, match_ire);
+ 0, NULL, NULL, zoneid, 0, NULL, match_ire);
} else {
ire = ire_ftable_lookup_v6(daddr, NULL, NULL,
- 0, NULL, NULL, zoneid, 0, match_ire);
+ 0, NULL, NULL, zoneid, 0, NULL, match_ire);
}
if (ire == NULL) {
dir->dir_dreachable = 0;
@@ -8622,14 +8698,14 @@
v4_addr);
ire = ire_ctable_lookup(v4_addr, 0,
IRE_LOCAL|IRE_LOOPBACK, NULL, zoneid,
- MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY);
+ NULL, MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY);
} else {
in6_addr_t v6addr;
v6addr = sin6->sin6_addr;
ire = ire_ctable_lookup_v6(&v6addr, 0,
IRE_LOCAL|IRE_LOOPBACK, NULL, zoneid,
- MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY);
+ NULL, MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY);
}
break;
}
@@ -8639,7 +8715,7 @@
v4addr = sin->sin_addr.s_addr;
ire = ire_ctable_lookup(v4addr, 0,
IRE_LOCAL|IRE_LOOPBACK, NULL, zoneid,
- MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY);
+ NULL, MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY);
break;
}
default:
@@ -8705,7 +8781,8 @@
v4_addr);
if (!CLASSD(v4_addr)) {
ire = ire_route_lookup(v4_addr, 0, 0, 0,
- NULL, NULL, zoneid, MATCH_IRE_GW);
+ NULL, NULL, zoneid, NULL,
+ MATCH_IRE_GW);
}
} else {
in6_addr_t v6addr;
@@ -8716,7 +8793,7 @@
if (!IN6_IS_ADDR_MULTICAST(&v6addr)) {
ire = ire_route_lookup_v6(&v6addr, 0,
&v6gw, 0, NULL, NULL, zoneid,
- MATCH_IRE_GW);
+ NULL, MATCH_IRE_GW);
}
}
break;
@@ -8727,7 +8804,8 @@
v4addr = sin->sin_addr.s_addr;
if (!CLASSD(v4addr)) {
ire = ire_route_lookup(v4addr, 0, 0, 0,
- NULL, NULL, zoneid, MATCH_IRE_GW);
+ NULL, NULL, zoneid, NULL,
+ MATCH_IRE_GW);
}
break;
}
@@ -9082,7 +9160,7 @@
* as an extended BSD ioctl. The kernel uses the IP address
* to figure out the network interface.
*/
- ire = ire_cache_lookup(sin->sin_addr.s_addr, ALL_ZONES);
+ ire = ire_cache_lookup(sin->sin_addr.s_addr, ALL_ZONES, NULL);
if ((ire == NULL) || (ire->ire_type == IRE_LOOPBACK) ||
((ill = ire_to_ill(ire)) == NULL) ||
(ill->ill_net_type != IRE_IF_RESOLVER)) {
@@ -9090,7 +9168,7 @@
ire_refrele(ire);
ire = ire_ftable_lookup(sin->sin_addr.s_addr,
0, 0, IRE_IF_RESOLVER, NULL, NULL, ALL_ZONES, 0,
- MATCH_IRE_TYPE);
+ NULL, MATCH_IRE_TYPE);
if ((ire == NULL) ||
((ill = ire_to_ill(ire)) == NULL)) {
if (ire != NULL)
@@ -9167,14 +9245,14 @@
* be rare enough since IRE cache entries have a longer
* life expectancy than ARP cache entries.
*/
- ire = ire_cache_lookup(sin->sin_addr.s_addr, ALL_ZONES);
+ ire = ire_cache_lookup(sin->sin_addr.s_addr, ALL_ZONES, NULL);
if ((ire == NULL) || (ire->ire_type == IRE_LOOPBACK) ||
((ill = ire_to_ill(ire)) == NULL)) {
if (ire != NULL)
ire_refrele(ire);
ire = ire_ftable_lookup(sin->sin_addr.s_addr,
0, 0, IRE_IF_RESOLVER, NULL, NULL, ALL_ZONES, 0,
- MATCH_IRE_TYPE);
+ NULL, MATCH_IRE_TYPE);
if ((ire == NULL) || ((ill = ire_to_ill(ire)) == NULL)) {
if (ire != NULL)
ire_refrele(ire);
@@ -9851,10 +9929,10 @@
ipsqill = ill;
ire = ire_ctable_lookup(addr, 0, IRE_CACHE,
ipsqill->ill_ipif, ALL_ZONES,
- MATCH_IRE_TYPE | MATCH_IRE_ILL);
+ NULL, MATCH_IRE_TYPE | MATCH_IRE_ILL);
} else {
ire = ire_ctable_lookup(addr, 0, IRE_CACHE,
- NULL, ALL_ZONES, MATCH_IRE_TYPE);
+ NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (ire != NULL)
ipsqill = ire_to_ill(ire);
}
@@ -11591,7 +11669,8 @@
* in the group has its own broadcast ire.
*/
ire = ire_ctable_lookup(addr, 0, IRE_BROADCAST,
- ipif, ALL_ZONES, (MATCH_IRE_ILL | MATCH_IRE_TYPE));
+ ipif, ALL_ZONES, NULL,
+ (MATCH_IRE_ILL | MATCH_IRE_TYPE));
if (ire == NULL) {
return (EINVAL);
} else {
@@ -13990,7 +14069,7 @@
*/
for (;;) {
ire = ire_ctable_lookup(addr, 0, IRE_BROADCAST, ill->ill_ipif,
- ALL_ZONES, MATCH_IRE_TYPE | MATCH_IRE_ILL);
+ ALL_ZONES, NULL, MATCH_IRE_TYPE | MATCH_IRE_ILL);
if (ire == NULL)
break;
@@ -14035,7 +14114,9 @@
ire->ire_phandle,
ire->ire_ihandle,
ire->ire_flags,
- &ire->ire_uinfo) == NULL) {
+ &ire->ire_uinfo,
+ NULL,
+ NULL) == NULL) {
cmn_err(CE_PANIC, "ire_init() failed");
}
ire_delete(ire);
@@ -14142,7 +14223,7 @@
ASSERT(ill->ill_group == NULL);
ire = ire_ctable_lookup(addr, 0, IRE_BROADCAST, ill->ill_ipif,
- ALL_ZONES, MATCH_IRE_TYPE | MATCH_IRE_ILL);
+ ALL_ZONES, NULL, MATCH_IRE_TYPE | MATCH_IRE_ILL);
if (ire != NULL) {
/*
@@ -14194,7 +14275,7 @@
boolean_t fallback = B_FALSE;
ire = ire_ctable_lookup(addr, 0, IRE_BROADCAST, NULL, ALL_ZONES,
- MATCH_IRE_TYPE);
+ NULL, MATCH_IRE_TYPE);
/*
* We may not be able to find some ires if a previous
* ire_create failed. This happens when an ipif goes
@@ -14337,7 +14418,9 @@
clear_ire->ire_phandle,
clear_ire->ire_ihandle,
clear_ire->ire_flags,
- &clear_ire->ire_uinfo) == NULL)
+ &clear_ire->ire_uinfo,
+ NULL,
+ NULL) == NULL)
cmn_err(CE_PANIC, "ire_init() failed");
if (clear_ire->ire_stq == NULL) {
ire_t *ire_next = clear_ire->ire_next;
@@ -14368,7 +14451,9 @@
clear_ire_stq->ire_phandle,
clear_ire_stq->ire_ihandle,
clear_ire_stq->ire_flags,
- &clear_ire_stq->ire_uinfo) == NULL)
+ &clear_ire_stq->ire_uinfo,
+ NULL,
+ NULL) == NULL)
cmn_err(CE_PANIC, "ire_init() failed");
}
}
@@ -17957,7 +18042,7 @@
* "ill_name" otherwise.
*/
char *
-ipif_get_name(ipif_t *ipif, char *buf, int len)
+ipif_get_name(const ipif_t *ipif, char *buf, int len)
{
char lbuf[32];
char *name;
@@ -18082,7 +18167,8 @@
for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
if (ipif->ipif_id == id) {
if (zoneid != ALL_ZONES &&
- zoneid != ipif->ipif_zoneid) {
+ zoneid != ipif->ipif_zoneid &&
+ ipif->ipif_zoneid != ALL_ZONES) {
mutex_exit(&ill->ill_lock);
RELEASE_CONN_LOCK(q);
ill_refrele(ill);
@@ -18489,7 +18575,9 @@
0,
0,
ifrt->ifrt_flags,
- &ifrt->ifrt_iulp_info);
+ &ifrt->ifrt_iulp_info,
+ NULL,
+ NULL);
if (ire == NULL) {
mutex_exit(&ipif->ipif_saved_ire_lock);
@@ -18631,6 +18719,7 @@
continue;
else if (new_ipif->ipif_zoneid !=
ipif->ipif_zoneid &&
+ ipif->ipif_zoneid != ALL_ZONES &&
(ill->ill_phyint->phyint_flags &
PHYI_LOOPBACK))
continue;
@@ -18963,6 +19052,16 @@
/* Create all the IREs associated with this interface */
if ((ipif->ipif_lcl_addr != INADDR_ANY) &&
!(ipif->ipif_flags & IPIF_NOLOCAL)) {
+
+ /*
+ * If we're on a labeled system then make sure that zone-
+ * private addresses have proper remote host database entries.
+ */
+ if (is_system_labeled() &&
+ ipif->ipif_ire_type != IRE_LOOPBACK &&
+ !tsol_check_interface_address(ipif))
+ return (EINVAL);
+
/* Register the source address for __sin6_src_id */
err = ip_srcid_insert(&ipif->ipif_v6lcl_addr,
ipif->ipif_zoneid);
@@ -18970,6 +19069,7 @@
ip0dbg(("ipif_up_done: srcid_insert %d\n", err));
return (err);
}
+
/* If the interface address is set, create the local IRE. */
ip1dbg(("ipif_up_done: 0x%p creating IRE 0x%x for 0x%x\n",
(void *)ipif,
@@ -18994,7 +19094,9 @@
0,
(ipif->ipif_flags & IPIF_PRIVATE) ?
RTF_PRIVATE : 0,
- &ire_uinfo_null);
+ &ire_uinfo_null,
+ NULL,
+ NULL);
} else {
ip1dbg((
"ipif_up_done: not creating IRE %d for 0x%x: flags 0x%x\n",
@@ -19057,7 +19159,9 @@
0,
0,
(ipif->ipif_flags & IPIF_PRIVATE) ? RTF_PRIVATE: 0,
- &ire_uinfo_null);
+ &ire_uinfo_null,
+ NULL,
+ NULL);
}
/*
@@ -19239,7 +19343,7 @@
ire = ire_ctable_lookup(ipif->ipif_brd_addr, 0,
IRE_BROADCAST, ipif, ALL_ZONES,
- (MATCH_IRE_TYPE | MATCH_IRE_ILL));
+ NULL, (MATCH_IRE_TYPE | MATCH_IRE_ILL));
if (ire == NULL) {
/*
@@ -19606,7 +19710,9 @@
boolean_t wrapped = B_FALSE;
boolean_t same_subnet_only = B_FALSE;
boolean_t ipif_same_found, ipif_other_found;
+ boolean_t specific_found;
ill_t *till, *usill = NULL;
+ tsol_tpc_t *src_rhtp, *dst_rhtp;
if (ill->ill_usesrc_ifindex != 0) {
usill = ill_lookup_on_ifindex(ill->ill_usesrc_ifindex, B_FALSE,
@@ -19618,6 +19724,23 @@
}
/*
+ * If we're dealing with an unlabeled destination on a labeled system,
+ * make sure that we ignore source addresses that are incompatible with
+ * the destination's default label. That destination's default label
+ * must dominate the minimum label on the source address.
+ */
+ dst_rhtp = NULL;
+ if (is_system_labeled()) {
+ dst_rhtp = find_tpc(&dst, IPV4_VERSION, B_FALSE);
+ if (dst_rhtp == NULL)
+ return (NULL);
+ if (dst_rhtp->tpc_tp.host_type != UNLABELED) {
+ TPC_RELE(dst_rhtp);
+ dst_rhtp = NULL;
+ }
+ }
+
+ /*
* Holds the ill_g_lock as reader. This makes sure that no ipif/ill
* can be deleted. But an ipif/ill can get CONDEMNED any time.
* After selecting the right ipif, under ill_lock make sure ipif is
@@ -19691,6 +19814,7 @@
* one we find that happens to be on the same subnet,
* otherwise the first one not in the same subnet.
*/
+ specific_found = B_FALSE;
for (; till != NULL; till = till->ill_group_next) {
ipif_same_found = B_FALSE;
ipif_other_found = B_FALSE;
@@ -19703,7 +19827,8 @@
continue;
if (!(ipif->ipif_flags & IPIF_UP))
continue;
- if (ipif->ipif_zoneid != zoneid)
+ if (ipif->ipif_zoneid != zoneid &&
+ ipif->ipif_zoneid != ALL_ZONES)
continue;
/*
* Interfaces with 0.0.0.0 address are allowed to be UP,
@@ -19711,6 +19836,51 @@
*/
if (ipif->ipif_lcl_addr == INADDR_ANY)
continue;
+
+ /*
+ * Check compatibility of local address for
+ * destination's default label if we're on a labeled
+ * system. Incompatible addresses can't be used at
+ * all.
+ */
+ if (dst_rhtp != NULL) {
+ boolean_t incompat;
+
+ src_rhtp = find_tpc(&ipif->ipif_lcl_addr,
+ IPV4_VERSION, B_FALSE);
+ if (src_rhtp == NULL)
+ continue;
+ incompat =
+ src_rhtp->tpc_tp.host_type != SUN_CIPSO ||
+ src_rhtp->tpc_tp.tp_doi !=
+ dst_rhtp->tpc_tp.tp_doi ||
+ (!_blinrange(&dst_rhtp->tpc_tp.tp_def_label,
+ &src_rhtp->tpc_tp.tp_sl_range_cipso) &&
+ !blinlset(&dst_rhtp->tpc_tp.tp_def_label,
+ src_rhtp->tpc_tp.tp_sl_set_cipso));
+ TPC_RELE(src_rhtp);
+ if (incompat)
+ continue;
+ }
+
+ /*
+ * We prefer not to use all all-zones addresses, if we
+ * can avoid it, as they pose problems with unlabeled
+ * destinations.
+ */
+ if (ipif->ipif_zoneid != ALL_ZONES) {
+ if (!specific_found &&
+ (!same_subnet_only ||
+ (ipif->ipif_net_mask & dst) ==
+ ipif->ipif_subnet)) {
+ index = 0;
+ specific_found = B_TRUE;
+ ipif_other_found = B_FALSE;
+ }
+ } else {
+ if (specific_found)
+ continue;
+ }
if (ipif->ipif_flags & IPIF_DEPRECATED) {
if (ipif_dep == NULL ||
(ipif->ipif_net_mask & dst) ==
@@ -19720,14 +19890,13 @@
}
if ((ipif->ipif_net_mask & dst) == ipif->ipif_subnet) {
/* found a source address in the same subnet */
- if (same_subnet_only == B_FALSE) {
+ if (!same_subnet_only) {
same_subnet_only = B_TRUE;
index = 0;
}
ipif_same_found = B_TRUE;
} else {
- if (same_subnet_only == B_TRUE ||
- ipif_other_found == B_TRUE)
+ if (same_subnet_only || ipif_other_found)
continue;
ipif_other_found = B_TRUE;
}
@@ -19736,7 +19905,7 @@
wrapped = B_TRUE;
index = 0;
}
- if (ipif_same_found == B_TRUE)
+ if (ipif_same_found)
break;
}
}
@@ -19763,6 +19932,8 @@
rw_exit(&ill_g_lock);
if (usill != NULL)
ill_refrele(usill);
+ if (dst_rhtp != NULL)
+ TPC_RELE(dst_rhtp);
#ifdef DEBUG
if (ipif == NULL) {
@@ -19896,7 +20067,9 @@
0,
0,
0,
- &ire_uinfo_null);
+ &ire_uinfo_null,
+ NULL,
+ NULL);
if (ire != NULL) {
ire_t *ret_ire;
@@ -20086,10 +20259,10 @@
return;
test_allzero_ire = ire_ctable_lookup(0, 0, IRE_BROADCAST,
- test_ipif, ALL_ZONES, (MATCH_IRE_TYPE | MATCH_IRE_IPIF));
+ test_ipif, ALL_ZONES, NULL, (MATCH_IRE_TYPE | MATCH_IRE_IPIF));
test_allone_ire = ire_ctable_lookup(INADDR_BROADCAST, 0, IRE_BROADCAST,
- test_ipif, ALL_ZONES, (MATCH_IRE_TYPE | MATCH_IRE_IPIF));
+ test_ipif, ALL_ZONES, NULL, (MATCH_IRE_TYPE | MATCH_IRE_IPIF));
test_net_mask = ip_net_mask(test_ipif->ipif_subnet);
test_subnet_mask = test_ipif->ipif_net_mask;
@@ -20105,14 +20278,14 @@
*/
test_net_addr = test_net_mask & test_ipif->ipif_subnet;
test_net_ire = ire_ctable_lookup(test_net_addr, 0, IRE_BROADCAST,
- test_ipif, ALL_ZONES, (MATCH_IRE_TYPE | MATCH_IRE_IPIF));
+ test_ipif, ALL_ZONES, NULL, (MATCH_IRE_TYPE | MATCH_IRE_IPIF));
/*
* Check if there is a subnet broadcast IRE associated with this ipif
*/
test_subnet_addr = test_subnet_mask & test_ipif->ipif_subnet;
test_subnet_ire = ire_ctable_lookup(test_subnet_addr, 0, IRE_BROADCAST,
- test_ipif, ALL_ZONES, (MATCH_IRE_TYPE | MATCH_IRE_IPIF));
+ test_ipif, ALL_ZONES, NULL, (MATCH_IRE_TYPE | MATCH_IRE_IPIF));
/*
* No broadcast ire's associated with this ipif.
@@ -20503,7 +20676,8 @@
ipif = ipif->ipif_next) {
if (IPIF_CAN_LOOKUP(ipif) &&
(zoneid == ALL_ZONES ||
- zoneid == ipif->ipif_zoneid)) {
+ zoneid == ipif->ipif_zoneid ||
+ ipif->ipif_zoneid == ALL_ZONES)) {
ipif_refhold_locked(ipif);
mutex_exit(&ill->ill_lock);
RELEASE_CONN_LOCK(q);
@@ -20756,13 +20930,17 @@
zone_status_t status;
zoneid_t zoneid;
+ ASSERT(ipip->ipi_cmd_type == LIF_CMD);
+ if ((zoneid = lifr->lifr_zoneid) == ALL_ZONES) {
+ if (!is_system_labeled())
+ return (ENOTSUP);
+ zoneid = GLOBAL_ZONEID;
+ }
+
/* cannot assign instance zero to a non-global zone */
- if (ipif->ipif_id == 0)
+ if (ipif->ipif_id == 0 && zoneid != GLOBAL_ZONEID)
return (ENOTSUP);
- ASSERT(ipip->ipi_cmd_type == LIF_CMD);
- zoneid = lifr->lifr_zoneid;
-
/*
* Cannot assign to a zone that doesn't exist or is shutting down. In
* the event of a race with the zone shutdown processing, since IP
@@ -20795,7 +20973,7 @@
need_up = B_TRUE;
}
- err = ip_sioctl_slifzone_tail(ipif, zoneid, q, mp, need_up);
+ err = ip_sioctl_slifzone_tail(ipif, lifr->lifr_zoneid, q, mp, need_up);
return (err);
}
@@ -20840,7 +21018,8 @@
ASSERT(ipif->ipif_id != 0);
ASSERT(ipip->ipi_cmd_type == LIF_CMD);
- zoneid = lifr->lifr_zoneid;
+ if ((zoneid = lifr->lifr_zoneid) == ALL_ZONES)
+ zoneid = GLOBAL_ZONEID;
ip1dbg(("ip_sioctl_slifzone_restart(%s:%u %p)\n",
ipif->ipif_ill->ill_name, ipif->ipif_id, (void *)ipif));
@@ -20877,7 +21056,8 @@
ipif_down_tail(ipif);
- return (ip_sioctl_slifzone_tail(ipif, zoneid, q, mp, B_TRUE));
+ return (ip_sioctl_slifzone_tail(ipif, lifr->lifr_zoneid, q, mp,
+ B_TRUE));
}
/* ARGSUSED */
@@ -21885,7 +22065,9 @@
0,
0,
flags,
- &ire_uinfo_null);
+ &ire_uinfo_null,
+ NULL,
+ NULL);
if (ire == NULL)
return (ENOMEM);
@@ -21977,7 +22159,8 @@
ipif = ipif->ipif_next) {
if (!IPIF_CAN_LOOKUP(ipif))
continue;
- if (ipif->ipif_zoneid != zoneid)
+ if (ipif->ipif_zoneid != zoneid &&
+ ipif->ipif_zoneid != ALL_ZONES)
continue;
/*
* Point-to-point case. Look for exact match with
@@ -22104,7 +22287,7 @@
ASSERT(ire_dst != NULL);
ire_prim = ire_ctable_lookup(ire->ire_gateway_addr, 0,
- IRE_BROADCAST, NULL, NULL, MATCH_IRE_TYPE);
+ IRE_BROADCAST, NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (ire_prim != NULL) {
/*
* We are in the special case of broadcasts for
@@ -22142,7 +22325,9 @@
0,
0,
ire->ire_flags,
- &ire_uinfo_null);
+ &ire_uinfo_null,
+ NULL,
+ NULL);
if (bcast_ire != NULL) {
@@ -22172,12 +22357,12 @@
ASSERT(ire != NULL);
ire_dst = ire_ctable_lookup(ire->ire_addr, 0, IRE_BROADCAST,
- NULL, NULL, MATCH_IRE_TYPE);
+ NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (ire_dst != NULL) {
ire_t *ire_prim;
ire_prim = ire_ctable_lookup(ire->ire_gateway_addr, 0,
- IRE_BROADCAST, NULL, NULL, MATCH_IRE_TYPE);
+ IRE_BROADCAST, NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (ire_prim != NULL) {
ipif_t *ipif_prim;
ire_t *bcast_ire;
@@ -22192,7 +22377,7 @@
bcast_ire = ire_ctable_lookup(ire->ire_addr,
ire->ire_gateway_addr,
IRE_BROADCAST,
- ipif_prim,
+ ipif_prim, ALL_ZONES,
NULL,
MATCH_IRE_TYPE | MATCH_IRE_GW | MATCH_IRE_IPIF |
MATCH_IRE_MASK);
@@ -22818,7 +23003,8 @@
for (ipif = ill->ill_ipif; ipif != NULL; ipif = ipif->ipif_next) {
if (!IPIF_CAN_LOOKUP(ipif))
continue;
- if (zoneid != ALL_ZONES && ipif->ipif_zoneid != zoneid)
+ if (zoneid != ALL_ZONES && ipif->ipif_zoneid != zoneid &&
+ ipif->ipif_zoneid != ALL_ZONES)
continue;
if ((ipif->ipif_flags & flags) != flags)
continue;
--- a/usr/src/uts/common/inet/ip/ip_ire.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip/ip_ire.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -35,8 +34,7 @@
#include <sys/types.h>
#include <sys/stream.h>
#include <sys/stropts.h>
-#include <sys/strlog.h>
-#include <sys/dlpi.h>
+#include <sys/strsun.h>
#include <sys/ddi.h>
#include <sys/cmn_err.h>
#include <sys/policy.h>
@@ -57,7 +55,6 @@
#include <inet/ip.h>
#include <inet/ip6.h>
#include <inet/ip_ndp.h>
-#include <inet/arp.h>
#include <inet/ip_if.h>
#include <inet/ip_ire.h>
#include <inet/ip_rts.h>
@@ -71,6 +68,9 @@
#include <inet/ipclassifier.h>
#include <sys/zone.h>
+#include <sys/tsol/label.h>
+#include <sys/tsol/tnet.h>
+
/*
* Synchronization notes:
*
@@ -396,18 +396,17 @@
static void ire_report_ctable(ire_t *ire, char *mp);
static void ire_report_mrtun_table(ire_t *ire, char *mp);
static void ire_report_srcif_table(ire_t *ire, char *mp);
-static void ire_walk_ipvers(pfv_t func, char *arg, uchar_t vers,
+static void ire_walk_ipvers(pfv_t func, void *arg, uchar_t vers,
zoneid_t zoneid);
static void ire_walk_ill_ipvers(uint_t match_flags, uint_t ire_type,
- pfv_t func, char *arg, uchar_t vers, ill_t *ill);
+ pfv_t func, void *arg, uchar_t vers, ill_t *ill);
static void ire_walk_ill_tables(uint_t match_flags, uint_t ire_type,
- pfv_t func, char *arg, size_t ftbl_sz, size_t htbl_sz,
- irb_t **ipftbl, size_t ctbl_sz, irb_t *ipctbl, ill_t *ill,
- zoneid_t zoneid);
+ pfv_t func, void *arg, size_t ftbl_sz, size_t htbl_sz, irb_t **ipftbl,
+ size_t ctbl_sz, irb_t *ipctbl, ill_t *ill, zoneid_t zoneid);
static void ire_delete_host_redirects(ipaddr_t gateway);
static boolean_t ire_match_args(ire_t *ire, ipaddr_t addr, ipaddr_t mask,
- ipaddr_t gateway, int type, ipif_t *ipif, zoneid_t zoneid,
- uint32_t ihandle, int match_flags);
+ ipaddr_t gateway, int type, const ipif_t *ipif, zoneid_t zoneid,
+ uint32_t ihandle, const ts_label_t *tsl, int match_flags);
static void ire_cache_cleanup(irb_t *irb, uint32_t threshold, int cnt);
extern void ill_unlock_ills(ill_t **list, int cnt);
static void ire_fastpath_list_add(ill_t *ill, ire_t *ire);
@@ -506,14 +505,14 @@
/* Extract the destination address. */
addr = *(ipaddr_t *)addr_ucp;
/* Find the corresponding IRE. */
- ire = ire_cache_lookup(addr, zoneid);
+ ire = ire_cache_lookup(addr, zoneid, NULL);
break;
}
case IPV6_ADDR_LEN: {
/* Extract the destination address. */
v6addr = *(in6_addr_t *)addr_ucp;
/* Find the corresponding IRE. */
- ire = ire_cache_lookup_v6(&v6addr, zoneid);
+ ire = ire_cache_lookup_v6(&v6addr, zoneid, NULL);
break;
}
default:
@@ -647,7 +646,7 @@
bcopy(addr_ucp, &addr, IP_ADDR_LEN);
/* Try to find the CACHED IRE. */
- ire = ire_cache_lookup(addr, zoneid);
+ ire = ire_cache_lookup(addr, zoneid, NULL);
/* Nail it. */
if (ire) {
@@ -726,7 +725,7 @@
}
/* Also look for an IRE_HOST_REDIRECT and remove it if present */
ire = ire_route_lookup(addr, 0, 0, IRE_HOST_REDIRECT, NULL, NULL,
- ALL_ZONES, MATCH_IRE_TYPE);
+ ALL_ZONES, NULL, MATCH_IRE_TYPE);
/* Nail it. */
if (ire) {
@@ -787,8 +786,8 @@
if (zoneid == GLOBAL_ZONEID)
zoneid = ALL_ZONES;
- ire_walk_v4(ire_report_ftable, (char *)mp->b_cont, zoneid);
- ire_walk_v4(ire_report_ctable, (char *)mp->b_cont, zoneid);
+ ire_walk_v4(ire_report_ftable, mp->b_cont, zoneid);
+ ire_walk_v4(ire_report_ctable, mp->b_cont, zoneid);
return (0);
}
@@ -922,7 +921,7 @@
"ref ");
/* 123 */
- ire_walk_ill_mrtun(0, 0, ire_report_mrtun_table, (char *)mp, NULL);
+ ire_walk_ill_mrtun(0, 0, ire_report_mrtun_table, mp, NULL);
return (0);
}
@@ -974,7 +973,7 @@
"type "
/* ABCDEFGH */
"in/out/forward");
- ire_walk_srcif_table_v4(ire_report_srcif_table, (char *)mp);
+ ire_walk_srcif_table_v4(ire_report_srcif_table, mp);
return (0);
}
@@ -1035,12 +1034,12 @@
*/
if (inire->ire_ipversion == IPV6_VERSION) {
ire = ire_route_lookup_v6(&inire->ire_addr_v6, 0, 0, 0,
- NULL, &sire, zoneid,
+ NULL, &sire, zoneid, NULL,
(MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT));
} else {
ASSERT(inire->ire_ipversion == IPV4_VERSION);
ire = ire_route_lookup(inire->ire_addr, 0, 0, 0,
- NULL, &sire, zoneid,
+ NULL, &sire, zoneid, NULL,
(MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT));
}
@@ -1516,7 +1515,7 @@
mp = first_mp;
dst_ire = ire_cache_lookup(ipha->ipha_dst,
- ire->ire_zoneid);
+ ire->ire_zoneid, MBLK_GETLABEL(mp));
} else {
/*
* Get a pointer to the beginning of the IPv6 header.
@@ -1530,7 +1529,7 @@
save_mp = mp;
mp = first_mp;
dst_ire = ire_cache_lookup_v6(&ip6h->ip6_dst,
- ire->ire_zoneid);
+ ire->ire_zoneid, MBLK_GETLABEL(mp));
}
if (dst_ire != NULL) {
if (dst_ire->ire_flags & RTF_MULTIRT) {
@@ -1663,8 +1662,15 @@
uchar_t *gateway, uchar_t *in_src_addr, uint_t *max_fragp, mblk_t *fp_mp,
queue_t *rfq, queue_t *stq, ushort_t type, mblk_t *dlureq_mp, ipif_t *ipif,
ill_t *in_ill, ipaddr_t cmask, uint32_t phandle, uint32_t ihandle,
- uint32_t flags, const iulp_t *ulp_info)
+ uint32_t flags, const iulp_t *ulp_info, tsol_gc_t *gc, tsol_gcgrp_t *gcgrp)
{
+ /*
+ * Reject IRE security attribute creation/initialization
+ * if system is not running in Trusted mode.
+ */
+ if ((gc != NULL || gcgrp != NULL) && !is_system_labeled())
+ return (NULL);
+
if (fp_mp != NULL) {
/*
* We can't dupb() here as multiple threads could be
@@ -1722,8 +1728,11 @@
if (type == IRE_CACHE)
ire->ire_cmask = cmask;
- ire_init_common(ire, max_fragp, fp_mp, rfq, stq, type, dlureq_mp,
- ipif, in_ill, phandle, ihandle, flags, IPV4_VERSION, ulp_info);
+ /* ire_init_common will free the mblks upon encountering any failure */
+ if (!ire_init_common(ire, max_fragp, fp_mp, rfq, stq, type, dlureq_mp,
+ ipif, in_ill, phandle, ihandle, flags, IPV4_VERSION, ulp_info,
+ gc, gcgrp))
+ return (NULL);
return (ire);
}
@@ -1738,7 +1747,7 @@
uchar_t *in_src_addr, uint_t max_frag, mblk_t *fp_mp, queue_t *rfq,
queue_t *stq, ushort_t type, mblk_t *dlureq_mp, ipif_t *ipif, ill_t *in_ill,
ipaddr_t cmask, uint32_t phandle, uint32_t ihandle, uint32_t flags,
- const iulp_t *ulp_info)
+ const iulp_t *ulp_info, tsol_gc_t *gc, tsol_gcgrp_t *gcgrp)
{
ire_t *ire;
ire_t *ret_ire;
@@ -1761,7 +1770,7 @@
ret_ire = ire_init(ire, addr, mask, src_addr, gateway, in_src_addr,
NULL, fp_mp, rfq, stq, type, dlureq_mp, ipif, in_ill, cmask,
- phandle, ihandle, flags, ulp_info);
+ phandle, ihandle, flags, ulp_info, gc, gcgrp);
if (ret_ire == NULL) {
freeb(ire->ire_mp);
@@ -1789,7 +1798,7 @@
uchar_t *in_src_addr, uint_t *max_fragp, mblk_t *fp_mp, queue_t *rfq,
queue_t *stq, ushort_t type, mblk_t *dlureq_mp, ipif_t *ipif, ill_t *in_ill,
ipaddr_t cmask, uint32_t phandle, uint32_t ihandle, uint32_t flags,
- const iulp_t *ulp_info)
+ const iulp_t *ulp_info, tsol_gc_t *gc, tsol_gcgrp_t *gcgrp)
{
ire_t *ire;
ire_t *ret_ire;
@@ -1803,7 +1812,7 @@
ret_ire = ire_init(ire, addr, mask, src_addr, gateway, in_src_addr,
max_fragp, fp_mp, rfq, stq, type, dlureq_mp, ipif, in_ill, cmask,
- phandle, ihandle, flags, ulp_info);
+ phandle, ihandle, flags, ulp_info, gc, gcgrp);
if (ret_ire == NULL) {
kmem_cache_free(ire_cache, ire);
@@ -1817,23 +1826,51 @@
/*
* Common to IPv4 and IPv6
*/
-void
+boolean_t
ire_init_common(ire_t *ire, uint_t *max_fragp, mblk_t *fp_mp,
queue_t *rfq, queue_t *stq, ushort_t type,
mblk_t *dlureq_mp, ipif_t *ipif, ill_t *in_ill, uint32_t phandle,
uint32_t ihandle, uint32_t flags, uchar_t ipversion,
- const iulp_t *ulp_info)
+ const iulp_t *ulp_info, tsol_gc_t *gc, tsol_gcgrp_t *gcgrp)
{
ire->ire_max_fragp = max_fragp;
ire->ire_frag_flag |= (ip_path_mtu_discovery) ? IPH_DF : 0;
ASSERT(fp_mp == NULL || fp_mp->b_datap->db_type == M_DATA);
- if (ipif) {
+#ifdef DEBUG
+ if (ipif != NULL) {
if (ipif->ipif_isv6)
ASSERT(ipversion == IPV6_VERSION);
else
ASSERT(ipversion == IPV4_VERSION);
}
+#endif /* DEBUG */
+
+ /*
+ * Create/initialize IRE security attribute only in Trusted mode;
+ * if the passed in gc/gcgrp is non-NULL, we expect that the caller
+ * has held a reference to it and will release it when this routine
+ * returns a failure, otherwise we own the reference. We do this
+ * prior to initializing the rest IRE fields.
+ */
+ if (is_system_labeled()) {
+ if ((type & (IRE_LOCAL | IRE_LOOPBACK | IRE_BROADCAST |
+ IRE_INTERFACE)) != 0) {
+ /* release references on behalf of caller */
+ if (gc != NULL)
+ GC_REFRELE(gc);
+ if (gcgrp != NULL)
+ GCGRP_REFRELE(gcgrp);
+ } else if (tsol_ire_init_gwattr(ire, ipversion,
+ gc, gcgrp) != 0) {
+ /* free any caller-allocated mblks upon failure */
+ if (fp_mp != NULL)
+ freeb(fp_mp);
+ if (dlureq_mp != NULL)
+ freeb(dlureq_mp);
+ return (B_FALSE);
+ }
+ }
ire->ire_fp_mp = fp_mp;
ire->ire_dlureq_mp = dlureq_mp;
@@ -1883,6 +1920,8 @@
#ifdef IRE_DEBUG
bzero(ire->ire_trace, sizeof (th_trace_t *) * IP_TR_HASH_MAX);
#endif
+
+ return (B_TRUE);
}
/*
@@ -1918,7 +1957,7 @@
/* If this would be a duplicate, don't bother. */
if ((ire = ire_ctable_lookup(addr, 0, IRE_BROADCAST, ipif,
- ipif->ipif_zoneid, match_flags)) != NULL) {
+ ipif->ipif_zoneid, NULL, match_flags)) != NULL) {
/*
* We look for non-deprecated (and non-anycast, non-nolocal)
* ipifs as the best choice. ipifs with check_flags matching
@@ -1976,7 +2015,9 @@
0,
0,
0,
- &ire_uinfo_null);
+ &ire_uinfo_null,
+ NULL,
+ NULL);
*irep++ = ire_create(
(uchar_t *)&addr, /* dest address */
@@ -1996,7 +2037,9 @@
0,
0,
0,
- &ire_uinfo_null);
+ &ire_uinfo_null,
+ NULL,
+ NULL);
return (irep);
}
@@ -2120,7 +2163,7 @@
return (B_TRUE);
ip2dbg(("ire_fastpath_update: trying\n"));
- mp = arg;
+ mp = (mblk_t *)arg;
up = mp->b_rptr;
cmplen = mp->b_wptr - up;
/* Serialize multiple fast path updates */
@@ -2352,7 +2395,7 @@
ipaddr_t gw_addr;
ire = ire_ftable_lookup(group, 0, 0, 0, NULL, NULL, zoneid,
- 0, MATCH_IRE_DEFAULT);
+ 0, NULL, MATCH_IRE_DEFAULT);
/* We search a resolvable ire in case of multirouting. */
if ((ire != NULL) && (ire->ire_flags & RTF_MULTIRT)) {
@@ -2362,7 +2405,7 @@
* may be changed here. In that case, ire_multirt_lookup()
* IRE_REFRELE the original ire and change it.
*/
- (void) ire_multirt_lookup(&cire, &ire, MULTIRT_CACHEGW);
+ (void) ire_multirt_lookup(&cire, &ire, MULTIRT_CACHEGW, NULL);
if (cire != NULL)
ire_refrele(cire);
}
@@ -2389,7 +2432,7 @@
ire_refrele(ire);
ire = ire_ftable_lookup(gw_addr, 0, 0,
IRE_INTERFACE, ipif, NULL, zoneid, 0,
- match_flags);
+ NULL, match_flags);
return (ire);
case IRE_IF_NORESOLVER:
case IRE_IF_RESOLVER:
@@ -2420,7 +2463,8 @@
rw_enter(&irb->irb_lock, RW_READER);
for (ire = irb->irb_ire; ire != NULL; ire = ire->ire_next) {
if ((ire->ire_marks & IRE_MARK_CONDEMNED) ||
- ire->ire_zoneid != zoneid)
+ (ire->ire_zoneid != zoneid &&
+ ire->ire_zoneid != ALL_ZONES))
continue;
switch (ire->ire_type) {
case IRE_LOOPBACK:
@@ -2452,7 +2496,7 @@
* if this ire is used.
*/
ill_t *
-ire_to_ill(ire_t *ire)
+ire_to_ill(const ire_t *ire)
{
ill_t *ill = NULL;
@@ -2501,19 +2545,19 @@
/* Arrange to call the specified function for every IRE in the world. */
void
-ire_walk(pfv_t func, char *arg)
+ire_walk(pfv_t func, void *arg)
{
ire_walk_ipvers(func, arg, 0, ALL_ZONES);
}
void
-ire_walk_v4(pfv_t func, char *arg, zoneid_t zoneid)
+ire_walk_v4(pfv_t func, void *arg, zoneid_t zoneid)
{
ire_walk_ipvers(func, arg, IPV4_VERSION, zoneid);
}
void
-ire_walk_v6(pfv_t func, char *arg, zoneid_t zoneid)
+ire_walk_v6(pfv_t func, void *arg, zoneid_t zoneid)
{
ire_walk_ipvers(func, arg, IPV6_VERSION, zoneid);
}
@@ -2522,7 +2566,7 @@
* Walk a particular version. version == 0 means both v4 and v6.
*/
static void
-ire_walk_ipvers(pfv_t func, char *arg, uchar_t vers, zoneid_t zoneid)
+ire_walk_ipvers(pfv_t func, void *arg, uchar_t vers, zoneid_t zoneid)
{
if (vers != IPV6_VERSION) {
ire_walk_ill_tables(0, 0, func, arg, IP_MASK_TABLE_SIZE,
@@ -2541,14 +2585,14 @@
* function for every IRE that matches the ill.
*/
void
-ire_walk_ill(uint_t match_flags, uint_t ire_type, pfv_t func, char *arg,
+ire_walk_ill(uint_t match_flags, uint_t ire_type, pfv_t func, void *arg,
ill_t *ill)
{
ire_walk_ill_ipvers(match_flags, ire_type, func, arg, 0, ill);
}
void
-ire_walk_ill_v4(uint_t match_flags, uint_t ire_type, pfv_t func, char *arg,
+ire_walk_ill_v4(uint_t match_flags, uint_t ire_type, pfv_t func, void *arg,
ill_t *ill)
{
ire_walk_ill_ipvers(match_flags, ire_type, func, arg, IPV4_VERSION,
@@ -2556,7 +2600,7 @@
}
void
-ire_walk_ill_v6(uint_t match_flags, uint_t ire_type, pfv_t func, char *arg,
+ire_walk_ill_v6(uint_t match_flags, uint_t ire_type, pfv_t func, void *arg,
ill_t *ill)
{
ire_walk_ill_ipvers(match_flags, ire_type, func, arg, IPV6_VERSION,
@@ -2568,7 +2612,7 @@
*/
static void
ire_walk_ill_ipvers(uint_t match_flags, uint_t ire_type, pfv_t func,
- char *arg, uchar_t vers, ill_t *ill)
+ void *arg, uchar_t vers, ill_t *ill)
{
if (vers != IPV6_VERSION) {
ire_walk_ill_tables(match_flags, ire_type, func, arg,
@@ -2639,7 +2683,7 @@
* routes that can be matched during lookup are also matched
* here.
*/
- if (zoneid != ire->ire_zoneid) {
+ if (zoneid != ire->ire_zoneid && ire->ire_zoneid != ALL_ZONES) {
/*
* Note, IRE_INTERFACE can have the stq as NULL. For
* example, if the default multicast route is tied to
@@ -2693,7 +2737,7 @@
}
if (ire->ire_ipversion == IPV4_VERSION) {
rire = ire_route_lookup(ire->ire_gateway_addr,
- 0, 0, 0, ire->ire_ipif, NULL, zoneid,
+ 0, 0, 0, ire->ire_ipif, NULL, zoneid, NULL,
ire_match_flags);
} else {
ASSERT(ire->ire_ipversion == IPV6_VERSION);
@@ -2702,7 +2746,7 @@
mutex_exit(&ire->ire_lock);
rire = ire_route_lookup_v6(&gw_addr_v6,
NULL, NULL, 0, ire->ire_ipif, NULL, zoneid,
- ire_match_flags);
+ NULL, ire_match_flags);
}
if (rire == NULL) {
return (B_FALSE);
@@ -2731,7 +2775,7 @@
*/
static void
ire_walk_ill_tables(uint_t match_flags, uint_t ire_type, pfv_t func,
- char *arg, size_t ftbl_sz, size_t htbl_sz, irb_t **ipftbl,
+ void *arg, size_t ftbl_sz, size_t htbl_sz, irb_t **ipftbl,
size_t ctbl_sz, irb_t *ipctbl, ill_t *ill, zoneid_t zoneid)
{
irb_t *irb_ptr;
@@ -2812,7 +2856,7 @@
* down/deleted or the 'ipv4_ire_srcif_status' report is printed.
*/
void
-ire_walk_srcif_table_v4(pfv_t func, char *arg)
+ire_walk_srcif_table_v4(pfv_t func, void *arg)
{
irb_t *irb;
ire_t *ire;
@@ -3154,7 +3198,7 @@
&ipif->ipif_v6src_addr)) ||
(!ipif->ipif_isv6 &&
ire->ire_src_addr != ipif->ipif_src_addr) ||
- (ire->ire_zoneid != ipif->ipif_zoneid)) {
+ ire->ire_zoneid != ipif->ipif_zoneid) {
if (ipif != NULL)
ipif_refrele(ipif);
@@ -3484,7 +3528,7 @@
continue;
if (ire_match_args(ire1, ire->ire_addr, ire->ire_mask,
ire->ire_gateway_addr, ire->ire_type, ire->ire_ipif,
- ire->ire_zoneid, 0, flags)) {
+ ire->ire_zoneid, 0, NULL, flags)) {
/*
* Return the old ire after doing a REFHOLD.
* As most of the callers continue to use the IRE
@@ -3683,7 +3727,7 @@
if (ire->ire_mask == IP_HOST_MASK) {
ire_t *lire;
lire = ire_ctable_lookup(ire->ire_addr, NULL, IRE_CACHE,
- NULL, ALL_ZONES, MATCH_IRE_TYPE);
+ NULL, ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (lire != NULL) {
ire_refrele(lire);
ire_flush_cache_v4(ire, IRE_FLUSH_ADD);
@@ -4187,6 +4231,10 @@
ire->ire_in_ill = NULL;
}
+ if (ire->ire_gw_secattr != NULL) {
+ ire_gw_secattr_free(ire->ire_gw_secattr);
+ ire->ire_gw_secattr = NULL;
+ }
#ifdef IRE_DEBUG
ire_trace_inactive(ire);
#endif
@@ -4368,7 +4416,8 @@
*/
static boolean_t
ire_match_args(ire_t *ire, ipaddr_t addr, ipaddr_t mask, ipaddr_t gateway,
- int type, ipif_t *ipif, zoneid_t zoneid, uint32_t ihandle, int match_flags)
+ int type, const ipif_t *ipif, zoneid_t zoneid, uint32_t ihandle,
+ const ts_label_t *tsl, int match_flags)
{
ill_t *ire_ill = NULL, *dst_ill;
ill_t *ipif_ill = NULL;
@@ -4405,7 +4454,8 @@
(ire->ire_marks & IRE_MARK_PRIVATE_ADDR))
return (B_FALSE);
- if (zoneid != ALL_ZONES && zoneid != ire->ire_zoneid) {
+ if (zoneid != ALL_ZONES && zoneid != ire->ire_zoneid &&
+ ire->ire_zoneid != ALL_ZONES) {
/*
* If MATCH_IRE_ZONEONLY has been set and the supplied zoneid is
* valid and does not match that of ire_zoneid, a failure to
@@ -4472,7 +4522,8 @@
tipif != NULL; tipif = tipif->ipif_next) {
if (IPIF_CAN_LOOKUP(tipif) &&
(tipif->ipif_flags & IPIF_UP) &&
- (tipif->ipif_zoneid == zoneid))
+ (tipif->ipif_zoneid == zoneid ||
+ tipif->ipif_zoneid == ALL_ZONES))
break;
}
mutex_exit(&ire->ire_ipif->ipif_ill->ill_lock);
@@ -4520,7 +4571,10 @@
((!(match_flags & MATCH_IRE_ILL_GROUP)) ||
(ire_ill == ipif_ill) ||
(ire_ill_group != NULL &&
- ire_ill_group == ipif_ill_group))) {
+ ire_ill_group == ipif_ill_group)) &&
+ ((!(match_flags & MATCH_IRE_SECATTR)) ||
+ (!is_system_labeled()) ||
+ (tsol_ire_match_gwattr(ire, tsl) == 0))) {
/* We found the matched IRE */
return (B_TRUE);
}
@@ -4533,7 +4587,8 @@
*/
ire_t *
ire_route_lookup(ipaddr_t addr, ipaddr_t mask, ipaddr_t gateway,
- int type, ipif_t *ipif, ire_t **pire, zoneid_t zoneid, int flags)
+ int type, const ipif_t *ipif, ire_t **pire, zoneid_t zoneid,
+ const ts_label_t *tsl, int flags)
{
ire_t *ire = NULL;
@@ -4555,13 +4610,13 @@
*/
if ((flags & MATCH_IRE_TYPE) == 0 || (type & IRE_CACHETABLE) != 0) {
ire = ire_ctable_lookup(addr, gateway, type, ipif, zoneid,
- flags);
+ tsl, flags);
if (ire != NULL)
return (ire);
}
if ((flags & MATCH_IRE_TYPE) == 0 || (type & IRE_FORWARDTABLE) != 0) {
ire = ire_ftable_lookup(addr, mask, gateway, type, ipif, pire,
- zoneid, 0, flags);
+ zoneid, 0, tsl, flags);
}
return (ire);
}
@@ -4599,8 +4654,8 @@
*/
ire_t *
ire_ftable_lookup(ipaddr_t addr, ipaddr_t mask, ipaddr_t gateway,
- int type, ipif_t *ipif, ire_t **pire, zoneid_t zoneid, uint32_t ihandle,
- int flags)
+ int type, const ipif_t *ipif, ire_t **pire, zoneid_t zoneid,
+ uint32_t ihandle, const ts_label_t *tsl, int flags)
{
irb_t *irb_ptr;
ire_t *ire = NULL;
@@ -4644,7 +4699,7 @@
if (ire->ire_marks & IRE_MARK_CONDEMNED)
continue;
if (ire_match_args(ire, addr, mask, gateway, type, ipif,
- zoneid, ihandle, flags))
+ zoneid, ihandle, tsl, flags))
goto found_ire;
}
rw_exit(&irb_ptr->irb_lock);
@@ -4670,7 +4725,7 @@
continue;
if (ire_match_args(ire, addr, ire->ire_mask,
gateway, type, ipif, zoneid, ihandle,
- flags))
+ tsl, flags))
goto found_ire;
}
rw_exit(&irb_ptr->irb_lock);
@@ -4701,7 +4756,7 @@
continue;
if (ire_match_args(ire, addr, (ipaddr_t)0,
gateway, type, ipif, zoneid, ihandle,
- flags))
+ tsl, flags))
goto found_ire;
}
rw_exit(&irb_ptr->irb_lock);
@@ -4780,7 +4835,7 @@
ire = ire_get_next_default_ire(ire, ire_origin)) {
if (ire_match_args(ire, addr, (ipaddr_t)0,
- gateway, type, ipif, zoneid, ihandle, flags)) {
+ gateway, type, ipif, zoneid, ihandle, tsl, flags)) {
int match_flags = 0;
ire_t *rire;
@@ -4804,7 +4859,7 @@
match_flags |= MATCH_IRE_ILL_GROUP;
}
rire = ire_route_lookup(ire->ire_gateway_addr,
- 0, 0, 0, ire->ire_ipif, NULL, zoneid,
+ 0, 0, 0, ire->ire_ipif, NULL, zoneid, tsl,
match_flags);
if (rire != NULL) {
ire_refrele(rire);
@@ -4830,7 +4885,8 @@
continue;
if (ire_match_args(ire, addr, (ipaddr_t)0,
- gateway, type, ipif, zoneid, ihandle, flags)) {
+ gateway, type, ipif, zoneid, ihandle, tsl,
+ flags)) {
IRE_REFHOLD(ire);
IRB_REFRELE(irb_ptr);
goto found_ire_held;
@@ -4862,7 +4918,7 @@
* of lookup is done.
*/
if (flags & MATCH_IRE_RECURSIVE) {
- ipif_t *gw_ipif;
+ const ipif_t *gw_ipif;
int match_flags = MATCH_IRE_DSTONLY;
ire_t *save_ire;
@@ -4893,7 +4949,7 @@
match_flags |= MATCH_IRE_ILL_GROUP;
ire = ire_route_lookup(ire->ire_gateway_addr, 0, 0, 0,
- ire->ire_ipif, NULL, zoneid, match_flags);
+ ire->ire_ipif, NULL, zoneid, tsl, match_flags);
if (ire == NULL) {
/*
* Do not release the parent ire if MATCH_IRE_PARENT
@@ -4932,7 +4988,7 @@
ire_refrele(ire);
ire = ire_route_lookup(gw_addr, 0, 0,
(IRE_CACHETABLE | IRE_INTERFACE), gw_ipif, NULL, zoneid,
- match_flags);
+ tsl, match_flags);
if (ire == NULL) {
/*
* Do not release the parent ire if MATCH_IRE_PARENT
@@ -4968,14 +5024,43 @@
}
/*
+ * Delete the IRE cache for the gateway and all IRE caches whose
+ * ire_gateway_addr points to this gateway, and allow them to
+ * be created on demand by ip_newroute.
+ */
+void
+ire_clookup_delete_cache_gw(ipaddr_t addr, zoneid_t zoneid)
+{
+ irb_t *irb;
+ ire_t *ire;
+
+ irb = &ip_cache_table[IRE_ADDR_HASH(addr, ip_cache_table_size)];
+ IRB_REFHOLD(irb);
+ for (ire = irb->irb_ire; ire != NULL; ire = ire->ire_next) {
+ if (ire->ire_marks & IRE_MARK_CONDEMNED)
+ continue;
+
+ ASSERT(ire->ire_mask == IP_HOST_MASK);
+ ASSERT(ire->ire_type != IRE_MIPRTUN && ire->ire_in_ill == NULL);
+ if (ire_match_args(ire, addr, ire->ire_mask, 0, IRE_CACHE,
+ NULL, zoneid, 0, NULL, MATCH_IRE_TYPE)) {
+ ire_delete(ire);
+ }
+ }
+ IRB_REFRELE(irb);
+
+ ire_walk_v4(ire_delete_cache_gw, &addr, zoneid);
+}
+
+/*
* Looks up cache table for a route.
* specific lookup can be indicated by
* passing the MATCH_* flags and the
* necessary parameters.
*/
ire_t *
-ire_ctable_lookup(ipaddr_t addr, ipaddr_t gateway, int type, ipif_t *ipif,
- zoneid_t zoneid, int flags)
+ire_ctable_lookup(ipaddr_t addr, ipaddr_t gateway, int type, const ipif_t *ipif,
+ zoneid_t zoneid, const ts_label_t *tsl, int flags)
{
irb_t *irb_ptr;
ire_t *ire;
@@ -4996,7 +5081,7 @@
ASSERT(ire->ire_mask == IP_HOST_MASK);
ASSERT(ire->ire_type != IRE_MIPRTUN && ire->ire_in_ill == NULL);
if (ire_match_args(ire, addr, ire->ire_mask, gateway, type,
- ipif, zoneid, 0, flags)) {
+ ipif, zoneid, 0, tsl, flags)) {
IRE_REFHOLD(ire);
rw_exit(&irb_ptr->irb_lock);
return (ire);
@@ -5012,7 +5097,7 @@
* to the hidden ones.
*/
ire_t *
-ire_cache_lookup(ipaddr_t addr, zoneid_t zoneid)
+ire_cache_lookup(ipaddr_t addr, zoneid_t zoneid, const ts_label_t *tsl)
{
irb_t *irb_ptr;
ire_t *ire;
@@ -5025,7 +5110,19 @@
continue;
}
if (ire->ire_addr == addr) {
+ /*
+ * Finally, check if the security policy has any
+ * restriction on using this route for the specified
+ * message.
+ */
+ if (tsl != NULL &&
+ ire->ire_gw_secattr != NULL &&
+ tsol_ire_match_gwattr(ire, tsl) != 0) {
+ continue;
+ }
+
if (zoneid == ALL_ZONES || ire->ire_zoneid == zoneid ||
+ ire->ire_zoneid == ALL_ZONES ||
ire->ire_type == IRE_LOCAL) {
IRE_REFHOLD(ire);
rw_exit(&irb_ptr->irb_lock);
@@ -5075,7 +5172,7 @@
*/
ire = ire_ftable_lookup(cire->ire_addr, cire->ire_cmask, 0,
IRE_INTERFACE, pire->ire_ipif, NULL, ALL_ZONES, cire->ire_ihandle,
- match_flags);
+ NULL, match_flags);
if (ire != NULL)
return (ire);
/*
@@ -5106,7 +5203,7 @@
if (pire->ire_ipif != NULL)
match_flags |= MATCH_IRE_ILL_GROUP;
ire = ire_ftable_lookup(pire->ire_gateway_addr, 0, 0, IRE_OFFSUBNET,
- pire->ire_ipif, NULL, ALL_ZONES, 0, match_flags);
+ pire->ire_ipif, NULL, ALL_ZONES, 0, NULL, match_flags);
if (ire == NULL)
return (NULL);
/*
@@ -5119,7 +5216,7 @@
match_flags |= MATCH_IRE_IHANDLE;
ire = ire_ftable_lookup(gw_addr, 0, 0, IRE_INTERFACE,
- gw_ipif, NULL, ALL_ZONES, cire->ire_ihandle, match_flags);
+ gw_ipif, NULL, ALL_ZONES, cire->ire_ihandle, NULL, match_flags);
return (ire);
}
@@ -5154,7 +5251,7 @@
*/
ire = ire_ftable_lookup(cire->ire_addr, cire->ire_cmask, 0,
IRE_INTERFACE, NULL, NULL, ALL_ZONES, cire->ire_ihandle,
- match_flags);
+ NULL, match_flags);
if (ire != NULL)
return (ire);
/*
@@ -5249,23 +5346,23 @@
* the ipif, this routine might return NULL.
*/
ire_t *
-ipif_to_ire(ipif_t *ipif)
+ipif_to_ire(const ipif_t *ipif)
{
ire_t *ire;
ASSERT(!ipif->ipif_isv6);
if (ipif->ipif_ire_type == IRE_LOOPBACK) {
ire = ire_ctable_lookup(ipif->ipif_lcl_addr, 0, IRE_LOOPBACK,
- ipif, ALL_ZONES, (MATCH_IRE_TYPE | MATCH_IRE_IPIF));
+ ipif, ALL_ZONES, NULL, (MATCH_IRE_TYPE | MATCH_IRE_IPIF));
} else if (ipif->ipif_flags & IPIF_POINTOPOINT) {
/* In this case we need to lookup destination address. */
ire = ire_ftable_lookup(ipif->ipif_pp_dst_addr, IP_HOST_MASK, 0,
- IRE_INTERFACE, ipif, NULL, ALL_ZONES, 0,
+ IRE_INTERFACE, ipif, NULL, ALL_ZONES, 0, NULL,
(MATCH_IRE_TYPE | MATCH_IRE_IPIF | MATCH_IRE_MASK));
} else {
ire = ire_ftable_lookup(ipif->ipif_subnet,
ipif->ipif_net_mask, 0, IRE_INTERFACE, ipif, NULL,
- ALL_ZONES, 0, (MATCH_IRE_TYPE | MATCH_IRE_IPIF |
+ ALL_ZONES, 0, NULL, (MATCH_IRE_TYPE | MATCH_IRE_IPIF |
MATCH_IRE_MASK));
}
return (ire);
@@ -5730,7 +5827,7 @@
if (ire->ire_marks & IRE_MARK_CONDEMNED)
continue;
if (ire_match_args(ire, dst_addr, ire->ire_mask, 0,
- ire_type, ipif, ire->ire_zoneid, 0, flags)) {
+ ire_type, ipif, ire->ire_zoneid, 0, NULL, flags)) {
IRE_REFHOLD(ire);
rw_exit(&irb_ptr->irb_lock);
return (ire);
@@ -5852,7 +5949,8 @@
continue;
/* Has anyone inserted route in the meanwhile ? */
if (ire_match_args(ire1, ire->ire_addr, ire->ire_mask, 0,
- ire->ire_type, ire->ire_ipif, ire->ire_zoneid, 0, flags)) {
+ ire->ire_type, ire->ire_ipif, ire->ire_zoneid, 0, NULL,
+ flags)) {
ip1dbg(("ire_add_srcif_v4 : Duplicate entry exists\n"));
IRE_REFHOLD(ire1);
ire_atomic_end(irb_ptr, ire);
@@ -5996,7 +6094,7 @@
* This only works in the global zone.
*/
boolean_t
-ire_multirt_need_resolve(ipaddr_t dst)
+ire_multirt_need_resolve(ipaddr_t dst, const ts_label_t *tsl)
{
ire_t *first_fire;
ire_t *first_cire;
@@ -6009,7 +6107,8 @@
/* Retrieve the first IRE_HOST that matches the destination */
first_fire = ire_ftable_lookup(dst, IP_HOST_MASK, 0, IRE_HOST, NULL,
- NULL, ALL_ZONES, 0, MATCH_IRE_MASK | MATCH_IRE_TYPE);
+ NULL, ALL_ZONES, 0, tsl,
+ MATCH_IRE_MASK | MATCH_IRE_TYPE | MATCH_IRE_SECATTR);
/* No route at all */
if (first_fire == NULL) {
@@ -6020,7 +6119,7 @@
ASSERT(firb != NULL);
/* Retrieve the first IRE_CACHE ire for that destination. */
- first_cire = ire_cache_lookup(dst, GLOBAL_ZONEID);
+ first_cire = ire_cache_lookup(dst, GLOBAL_ZONEID, tsl);
/* No resolved route. */
if (first_cire == NULL) {
@@ -6065,7 +6164,7 @@
/* At least one route is unresolved; search for a resolvable route. */
if (unres_cnt > 0)
resolvable = ire_multirt_lookup(&first_cire, &first_fire,
- MULTIRT_USESTAMP | MULTIRT_CACHEGW);
+ MULTIRT_USESTAMP | MULTIRT_CACHEGW, tsl);
if (first_fire != NULL)
ire_refrele(first_fire);
@@ -6128,7 +6227,8 @@
* This only works in the global zone.
*/
boolean_t
-ire_multirt_lookup(ire_t **ire_arg, ire_t **fire_arg, uint32_t flags)
+ire_multirt_lookup(ire_t **ire_arg, ire_t **fire_arg, uint32_t flags,
+ const ts_label_t *tsl)
{
clock_t delta;
ire_t *best_fire = NULL;
@@ -6170,7 +6270,7 @@
* if we don't find one, no route for that dest is
* resolved yet.
*/
- first_cire = ire_cache_lookup(dst, GLOBAL_ZONEID);
+ first_cire = ire_cache_lookup(dst, GLOBAL_ZONEID, tsl);
if (first_cire != NULL) {
cirb = first_cire->ire_bucket;
}
@@ -6196,6 +6296,11 @@
if (fire->ire_addr != dst)
continue;
+ if (fire->ire_gw_secattr != NULL &&
+ tsol_ire_match_gwattr(fire, tsl) != 0) {
+ continue;
+ }
+
gw = fire->ire_gateway_addr;
ip2dbg(("ire_multirt_lookup: fire %p, "
@@ -6224,6 +6329,13 @@
(IRE_MARK_CONDEMNED |
IRE_MARK_HIDDEN))
continue;
+
+ if (cire->ire_gw_secattr != NULL &&
+ tsol_ire_match_gwattr(cire,
+ tsl) != 0) {
+ continue;
+ }
+
/*
* Check if the IRE_CACHE's gateway
* matches the IRE_HOST's gateway.
@@ -6252,7 +6364,8 @@
* for the gateway?
*/
gw_ire = ire_route_lookup(gw, 0, 0, 0, NULL, NULL,
- ALL_ZONES, MATCH_IRE_RECURSIVE);
+ ALL_ZONES, tsl,
+ MATCH_IRE_RECURSIVE | MATCH_IRE_SECATTR);
ip2dbg(("ire_multirt_lookup: looked up gw_ire %p\n",
(void *)gw_ire));
@@ -6377,13 +6490,19 @@
if (fire->ire_addr != dst)
continue;
+ if (fire->ire_gw_secattr != NULL &&
+ tsol_ire_match_gwattr(fire, tsl) != 0) {
+ continue;
+ }
+
already_resolved = B_FALSE;
gw = fire->ire_gateway_addr;
gw_ire = ire_ftable_lookup(gw, 0, 0, IRE_INTERFACE,
- NULL, NULL, ALL_ZONES, 0,
- MATCH_IRE_RECURSIVE | MATCH_IRE_TYPE);
+ NULL, NULL, ALL_ZONES, 0, tsl,
+ MATCH_IRE_RECURSIVE | MATCH_IRE_TYPE |
+ MATCH_IRE_SECATTR);
/* No resolver for the gateway; we skip this ire. */
if (gw_ire == NULL) {
@@ -6410,6 +6529,12 @@
IRE_MARK_HIDDEN))
continue;
+ if (cire->ire_gw_secattr != NULL &&
+ tsol_ire_match_gwattr(cire,
+ tsl) != 0) {
+ continue;
+ }
+
/*
* Cache entries are linked to the
* parent routes using the parent handle
@@ -6535,7 +6660,7 @@
ASSERT(CLASSD(group));
ire = ire_ftable_lookup(group, 0, 0, 0, NULL, NULL, ALL_ZONES, 0,
- MATCH_IRE_DEFAULT);
+ NULL, MATCH_IRE_DEFAULT);
if (ire == NULL)
return (NULL);
@@ -6547,7 +6672,8 @@
ire_refrele(ire);
for (ire = irb->irb_ire; ire != NULL; ire = ire->ire_next) {
if (ire->ire_addr != group ||
- ipif->ipif_zoneid != ire->ire_zoneid) {
+ (ipif->ipif_zoneid != ire->ire_zoneid &&
+ ire->ire_zoneid != ALL_ZONES)) {
continue;
}
@@ -6557,7 +6683,7 @@
case IRE_HOST:
gw_addr = ire->ire_gateway_addr;
gw_ire = ire_ftable_lookup(gw_addr, 0, 0, IRE_INTERFACE,
- ipif, NULL, ALL_ZONES, 0, match_flags);
+ ipif, NULL, ALL_ZONES, 0, NULL, match_flags);
if (gw_ire != NULL) {
if (save_ire != NULL) {
@@ -6625,14 +6751,14 @@
dir = ire_route_lookup(
((struct sockaddr_in *)target)->sin_addr.s_addr,
0xffffffff,
- 0, 0, NULL, NULL, ALL_ZONES,
+ 0, 0, NULL, NULL, ALL_ZONES, NULL,
MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE);
break;
case AF_INET6:
dir = ire_route_lookup_v6(
&((struct sockaddr_in6 *)target)->sin6_addr,
NULL,
- 0, 0, NULL, NULL, ALL_ZONES,
+ 0, 0, NULL, NULL, ALL_ZONES, NULL,
MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE);
if ((dir != NULL) && (dir->ire_nce == NULL)) {
ire_refrele(dir);
@@ -6756,14 +6882,14 @@
dir = ire_route_lookup(
((struct sockaddr_in *)target)->sin_addr.s_addr,
0xffffffff,
- 0, 0, ill->ill_ipif, NULL, ALL_ZONES,
+ 0, 0, ill->ill_ipif, NULL, ALL_ZONES, NULL,
MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|
MATCH_IRE_RECURSIVE|MATCH_IRE_IPIF);
break;
case AF_INET6:
dir = ire_route_lookup_v6(
&((struct sockaddr_in6 *)target)->sin6_addr, NULL,
- 0, 0, ill->ill_ipif, NULL, ALL_ZONES,
+ 0, 0, ill->ill_ipif, NULL, ALL_ZONES, NULL,
MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|
MATCH_IRE_RECURSIVE|MATCH_IRE_IPIF);
if ((dir != NULL) && (dir->ire_nce == NULL)) {
--- a/usr/src/uts/common/inet/ip/ip_mroute.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip/ip_mroute.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
+ * Copyright 2006 Sun Microsystems, Inc.
* All rights reserved. Use is subject to license terms.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -48,7 +47,6 @@
#include <sys/types.h>
#include <sys/stream.h>
-#include <sys/dlpi.h>
#include <sys/stropts.h>
#include <sys/strlog.h>
#include <sys/systm.h>
@@ -58,21 +56,16 @@
#include <sys/param.h>
#include <sys/socket.h>
-#define _SUN_TPI_VERSION 2
-#include <sys/tihdr.h>
#include <sys/vtrace.h>
#include <sys/debug.h>
#include <net/if.h>
-#include <net/if_arp.h>
#include <sys/sockio.h>
-#include <net/route.h>
#include <netinet/in.h>
#include <net/if_dl.h>
#include <inet/common.h>
#include <inet/mi.h>
#include <inet/nd.h>
-#include <inet/arp.h>
#include <inet/mib2.h>
#include <netinet/ip6.h>
#include <inet/ip.h>
@@ -2992,7 +2985,7 @@
}
mp_loop = copymsg(mp);
ire = ire_ctable_lookup(~0, 0, IRE_BROADCAST, NULL,
- ALL_ZONES, MATCH_IRE_TYPE);
+ ALL_ZONES, NULL, MATCH_IRE_TYPE);
if (mp_loop != NULL && ire != NULL) {
IP_RPUT_LOCAL(ipif->ipif_rq, mp_loop,
--- a/usr/src/uts/common/inet/ip/ip_multi.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip/ip_multi.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -32,18 +31,14 @@
#include <sys/dlpi.h>
#include <sys/stropts.h>
#include <sys/strsun.h>
-#include <sys/strlog.h>
#include <sys/ddi.h>
#include <sys/cmn_err.h>
#include <sys/zone.h>
#include <sys/param.h>
#include <sys/socket.h>
-#define _SUN_TPI_VERSION 2
-#include <sys/tihdr.h>
+#include <sys/sockio.h>
#include <net/if.h>
-#include <net/if_arp.h>
-#include <sys/sockio.h>
#include <sys/systm.h>
#include <net/route.h>
#include <netinet/in.h>
@@ -58,7 +53,6 @@
#include <inet/ip.h>
#include <inet/ip6.h>
#include <inet/ip_if.h>
-#include <inet/ip_ire.h>
#include <inet/ip_ndp.h>
#include <inet/ip_multi.h>
#include <inet/ipclassifier.h>
@@ -67,8 +61,6 @@
#include <inet/ip_listutils.h>
#include <inet/udp_impl.h>
-#include <netinet/igmp.h>
-
/* igmpv3/mldv2 source filter manipulation */
static void ilm_bld_flists(conn_t *conn, void *arg);
static void ilm_gen_filter(ilm_t *ilm, mcast_record_t *fmode,
@@ -1706,6 +1698,7 @@
ilm->ilm_zoneid = zoneid;
ilm->ilm_timer = INFINITY;
ilm->ilm_rtx.rtx_timer = INFINITY;
+
/*
* IPv4 Multicast groups are joined using ipif.
* IPv6 Multicast groups are joined using ill.
--- a/usr/src/uts/common/inet/ip/ip_ndp.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip/ip_ndp.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -31,11 +30,7 @@
#include <sys/stropts.h>
#include <sys/sysmacros.h>
#include <sys/errno.h>
-#include <sys/strlog.h>
#include <sys/dlpi.h>
-#include <sys/sockio.h>
-#include <sys/tiuser.h>
-#include <sys/tihdr.h>
#include <sys/socket.h>
#include <sys/ddi.h>
#include <sys/cmn_err.h>
@@ -45,12 +40,9 @@
#include <sys/zone.h>
#include <net/if.h>
-#include <net/if_types.h>
#include <net/if_dl.h>
#include <net/route.h>
-#include <sys/sockio.h>
#include <netinet/in.h>
-#include <netinet/in_systm.h>
#include <netinet/ip6.h>
#include <netinet/icmp6.h>
@@ -58,9 +50,7 @@
#include <inet/mi.h>
#include <inet/mib2.h>
#include <inet/nd.h>
-#include <inet/arp.h>
#include <inet/ip.h>
-#include <inet/ip_multi.h>
#include <inet/ip_if.h>
#include <inet/ip_ire.h>
#include <inet/ip_rts.h>
@@ -762,7 +752,7 @@
*/
ire = ire_ftable_lookup_v6(&ipv6_all_zeros,
&ipv6_all_zeros, &nce->nce_addr, IRE_DEFAULT,
- nce->nce_ill->ill_ipif, NULL, ALL_ZONES, 0,
+ nce->nce_ill->ill_ipif, NULL, ALL_ZONES, 0, NULL,
MATCH_IRE_ILL | MATCH_IRE_TYPE | MATCH_IRE_GW |
MATCH_IRE_DEFAULT);
if (ire != NULL) {
@@ -781,7 +771,7 @@
* walking the hash list.
*/
void
-ndp_walk_impl(ill_t *ill, pfi_t pfi, uchar_t *arg1, boolean_t trace)
+ndp_walk_impl(ill_t *ill, pfi_t pfi, void *arg1, boolean_t trace)
{
nce_t *nce;
@@ -852,7 +842,7 @@
}
void
-ndp_walk(ill_t *ill, pfi_t pfi, uchar_t *arg1)
+ndp_walk(ill_t *ill, pfi_t pfi, void *arg1)
{
ndp_walk_impl(ill, pfi, arg1, B_TRUE);
}
@@ -869,6 +859,7 @@
mblk_t *first_mp;
ipsec_out_t *io;
+ ASSERT(zoneid != ALL_ZONES);
if (mp->b_datap->db_type == M_CTL) {
io = (ipsec_out_t *)mp->b_rptr;
ASSERT(io->ipsec_out_type == IPSEC_OUT);
--- a/usr/src/uts/common/inet/ip/ip_opt_data.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip/ip_opt_data.c Fri Mar 24 12:29:20 2006 -0800
@@ -37,7 +37,6 @@
#include <inet/ip.h>
#include <netinet/in.h>
-#include <netinet/tcp.h>
#include <netinet/ip_mroute.h>
#include <inet/optcom.h>
@@ -63,6 +62,9 @@
{ SO_BROADCAST, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0 },
{ SO_REUSEADDR, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0 },
{ SO_PROTOTYPE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0 },
+{ SO_ANON_MLP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0 },
+{ SO_MAC_EXEMPT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0
+ },
{ IP_OPTIONS, IPPROTO_IP, OA_RW, OA_RW, OP_NP,
(OP_PASSNEXT|OP_VARLEN|OP_NODEFAULT), 40, -1 /* not initialized */ },
--- a/usr/src/uts/common/inet/ip/ip_rts.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip/ip_rts.c Fri Mar 24 12:29:20 2006 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -47,8 +47,6 @@
#include <sys/types.h>
#include <sys/stream.h>
#include <sys/stropts.h>
-#include <sys/strlog.h>
-#include <sys/dlpi.h>
#include <sys/ddi.h>
#include <sys/cmn_err.h>
#include <sys/debug.h>
@@ -58,8 +56,6 @@
#include <sys/systm.h>
#include <sys/param.h>
#include <sys/socket.h>
-#define _SUN_TPI_VERSION 2
-#include <sys/tihdr.h>
#include <sys/strsun.h>
#include <net/if.h>
#include <net/route.h>
@@ -68,28 +64,30 @@
#include <netinet/ip6.h>
#include <inet/common.h>
-#include <inet/mi.h>
#include <inet/ip.h>
#include <inet/ip6.h>
#include <inet/ip_if.h>
#include <inet/ip_ire.h>
#include <inet/ip_rts.h>
-#include <inet/ip_multi.h>
#include <inet/ipclassifier.h>
-#define RTS_MSG_SIZE(type, rtm_addrs, af) \
- (rts_data_msg_size(rtm_addrs, af) + rts_header_msg_size(type))
+#include <sys/tsol/tndb.h>
+#include <sys/tsol/tnet.h>
+
+#define RTS_MSG_SIZE(type, rtm_addrs, af, sacnt) \
+ (rts_data_msg_size(rtm_addrs, af, sacnt) + rts_header_msg_size(type))
static size_t rts_copyfromsockaddr(struct sockaddr *sa, in6_addr_t *addrp);
static void rts_fill_msg(int type, int rtm_addrs, ipaddr_t dst,
ipaddr_t mask, ipaddr_t gateway, ipaddr_t src_addr, ipaddr_t brd_addr,
- ipaddr_t author, ipif_t *ipif, mblk_t *mp);
+ ipaddr_t author, const ipif_t *ipif, mblk_t *mp, uint_t, const tsol_gc_t *);
static int rts_getaddrs(rt_msghdr_t *rtm, in6_addr_t *dst_addrp,
in6_addr_t *gw_addrp, in6_addr_t *net_maskp, in6_addr_t *authorp,
in6_addr_t *if_addrp, in6_addr_t *src_addrp, ushort_t *indexp,
- ushort_t *src_indexp, sa_family_t *afp);
-static void rts_getifdata(if_data_t *if_data, ipif_t *ipif);
+ ushort_t *src_indexp, sa_family_t *afp, tsol_rtsecattr_t *rtsecattr,
+ int *error);
+static void rts_getifdata(if_data_t *if_data, const ipif_t *ipif);
static int rts_getmetrics(ire_t *ire, rt_metrics_t *metrics);
static mblk_t *rts_rtmget(mblk_t *mp, ire_t *ire, ire_t *sire,
sa_family_t af);
@@ -187,15 +185,16 @@
switch (ire->ire_ipversion) {
case IPV4_VERSION:
af = AF_INET;
- mp = rts_alloc_msg(type, rtm_addrs, af);
+ mp = rts_alloc_msg(type, rtm_addrs, af, 0);
if (mp == NULL)
return;
rts_fill_msg(type, rtm_addrs, ire->ire_addr, ire->ire_mask,
- ire->ire_gateway_addr, ire->ire_src_addr, 0, 0, NULL, mp);
+ ire->ire_gateway_addr, ire->ire_src_addr, 0, 0, NULL, mp,
+ 0, NULL);
break;
case IPV6_VERSION:
af = AF_INET6;
- mp = rts_alloc_msg(type, rtm_addrs, af);
+ mp = rts_alloc_msg(type, rtm_addrs, af, 0);
if (mp == NULL)
return;
mutex_enter(&ire->ire_lock);
@@ -204,7 +203,7 @@
rts_fill_msg_v6(type, rtm_addrs, &ire->ire_addr_v6,
&ire->ire_mask_v6, &gw_addr_v6,
&ire->ire_src_addr_v6, &ipv6_all_zeros, &ipv6_all_zeros,
- NULL, mp);
+ NULL, mp, 0, NULL);
break;
}
rtm = (rt_msghdr_t *)mp->b_rptr;
@@ -272,6 +271,12 @@
ipif_t *tmp_ipif = NULL;
IOCP iocp = (IOCP)mp->b_rptr;
conn_t *connp;
+ boolean_t gcgrp_xtraref = B_FALSE;
+ tsol_gcgrp_addr_t ga;
+ tsol_rtsecattr_t rtsecattr;
+ struct rtsa_s *rtsap = NULL;
+ tsol_gcgrp_t *gcgrp = NULL;
+ tsol_gc_t *gc = NULL;
ip1dbg(("ip_rts_request: mp is %x\n", DB_TYPE(mp)));
@@ -347,7 +352,12 @@
}
found_addrs = rts_getaddrs(rtm, &dst_addr_v6, &gw_addr_v6, &net_mask_v6,
- &author_v6, &if_addr_v6, &src_addr_v6, &index, &src_index, &af);
+ &author_v6, &if_addr_v6, &src_addr_v6, &index, &src_index, &af,
+ &rtsecattr, &error);
+
+ if (error != 0)
+ goto done;
+
if ((found_addrs & RTA_DST) == 0) {
error = EINVAL;
goto done;
@@ -471,6 +481,16 @@
if ((found_addrs & RTA_NETMASK) != 0)
match_flags |= MATCH_IRE_MASK;
+ /*
+ * We only process any passed-in route security attributes for
+ * either RTM_ADD or RTM_CHANGE message; ignore otherwise.
+ */
+ if (rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) {
+ ASSERT(rtsecattr.rtsa_cnt <= TSOL_RTSA_REQUEST_MAX);
+ if (rtsecattr.rtsa_cnt > 0)
+ rtsap = &rtsecattr.rtsa_attr[0];
+ }
+
switch (rtm->rtm_type) {
case RTM_ADD:
/* if we are adding a route, gateway is a must */
@@ -554,10 +574,10 @@
}
}
- error = ip_rt_add(dst_addr, net_mask,
- gw_addr, src_addr,
+ error = ip_rt_add(dst_addr, net_mask, gw_addr, src_addr,
rtm->rtm_flags, ipif, src_ipif, &ire, B_FALSE,
- CONNP_TO_WQ(connp), ioc_mp, ip_rts_request_retry);
+ CONNP_TO_WQ(connp), ioc_mp, ip_rts_request_retry,
+ rtsap);
if (ipif != NULL)
ASSERT(!MUTEX_HELD(&ipif->ipif_ill->ill_lock));
break;
@@ -605,7 +625,7 @@
error = ip_rt_add_v6(&dst_addr_v6, &net_mask_v6,
&gw_addr_v6, &src_addr_v6, rtm->rtm_flags,
ipif, &ire, CONNP_TO_WQ(connp), ioc_mp,
- ip_rts_request_retry);
+ ip_rts_request_retry, rtsap);
break;
}
/*
@@ -619,7 +639,7 @@
error = ip_rt_add_v6(&dst_addr_v6, &net_mask_v6,
&gw_addr_v6, NULL, rtm->rtm_flags,
ipif, &ire, CONNP_TO_WQ(connp), ioc_mp,
- ip_rts_request_retry);
+ ip_rts_request_retry, rtsap);
if (ipif != NULL)
ASSERT(!MUTEX_HELD(&ipif->ipif_ill->ill_lock));
break;
@@ -726,24 +746,25 @@
if (net_mask == IP_HOST_MASK) {
ire = ire_ctable_lookup(dst_addr, gw_addr,
IRE_LOCAL | IRE_LOOPBACK, NULL, ALL_ZONES,
- MATCH_IRE_TYPE | MATCH_IRE_GW);
+ NULL, MATCH_IRE_TYPE | MATCH_IRE_GW);
}
if (ire == NULL) {
ire = ire_ftable_lookup(dst_addr, net_mask,
gw_addr, 0, ipif, &sire, ALL_ZONES, 0,
- match_flags);
+ NULL, match_flags);
}
break;
case AF_INET6:
if (IN6_ARE_ADDR_EQUAL(&net_mask_v6, &ipv6_all_ones)) {
ire = ire_ctable_lookup_v6(&dst_addr_v6,
&gw_addr_v6, IRE_LOCAL | IRE_LOOPBACK, NULL,
- ALL_ZONES, MATCH_IRE_TYPE | MATCH_IRE_GW);
+ ALL_ZONES, NULL,
+ MATCH_IRE_TYPE | MATCH_IRE_GW);
}
if (ire == NULL) {
ire = ire_ftable_lookup_v6(&dst_addr_v6,
&net_mask_v6, &gw_addr_v6, 0, ipif, &sire,
- ALL_ZONES, 0, match_flags);
+ ALL_ZONES, 0, NULL, match_flags);
}
break;
}
@@ -790,6 +811,19 @@
(ire->ire_gateway_addr != gw_addr)) {
ire->ire_gateway_addr = gw_addr;
}
+
+ if (rtsap != NULL) {
+ ga.ga_af = AF_INET;
+ IN6_IPADDR_TO_V4MAPPED(
+ ire->ire_gateway_addr, &ga.ga_addr);
+
+ gcgrp = gcgrp_lookup(&ga, B_TRUE);
+ if (gcgrp == NULL) {
+ error = ENOMEM;
+ goto done;
+ }
+ }
+
if ((found_addrs & RTA_SRC) != 0 &&
(rtm->rtm_flags & RTF_SETSRC) != 0 &&
(ire->ire_src_addr != src_addr)) {
@@ -849,6 +883,18 @@
&ire->ire_gateway_addr_v6, &gw_addr_v6)) {
ire->ire_gateway_addr_v6 = gw_addr_v6;
}
+
+ if (rtsap != NULL) {
+ ga.ga_af = AF_INET6;
+ ga.ga_addr = ire->ire_gateway_addr_v6;
+
+ gcgrp = gcgrp_lookup(&ga, B_TRUE);
+ if (gcgrp == NULL) {
+ error = ENOMEM;
+ goto done;
+ }
+ }
+
if ((found_addrs & RTA_SRC) != 0 &&
(rtm->rtm_flags & RTF_SETSRC) != 0 &&
!IN6_ARE_ADDR_EQUAL(
@@ -910,6 +956,48 @@
mutex_exit(&ire->ire_lock);
break;
}
+
+ if (rtsap != NULL) {
+ in_addr_t ga_addr4;
+
+ ASSERT(gcgrp != NULL);
+
+ /*
+ * Create and add the security attribute to
+ * prefix IRE; it will add a reference to the
+ * group upon allocating a new entry. If it
+ * finds an already-existing entry for the
+ * security attribute, it simply returns it
+ * and no new group reference is made.
+ */
+ gc = gc_create(rtsap, gcgrp, &gcgrp_xtraref);
+ if (gc == NULL ||
+ (error = tsol_ire_init_gwattr(ire,
+ ire->ire_ipversion, gc, NULL)) != 0) {
+ if (gc != NULL) {
+ GC_REFRELE(gc);
+ } else {
+ /* gc_create failed */
+ error = ENOMEM;
+ }
+ goto done;
+ }
+
+ /*
+ * Now delete any existing gateway IRE caches
+ * as well as all caches using the gateway,
+ * and allow them to be created on demand
+ * through ip_newroute{_v6}.
+ */
+ IN6_V4MAPPED_TO_IPADDR(&ga.ga_addr, ga_addr4);
+ if (af == AF_INET) {
+ ire_clookup_delete_cache_gw(
+ ga_addr4, ALL_ZONES);
+ } else {
+ ire_clookup_delete_cache_gw_v6(
+ &ga.ga_addr, ALL_ZONES);
+ }
+ }
rts_setmetrics(ire, rtm->rtm_inits, &rtm->rtm_rmx);
break;
}
@@ -930,6 +1018,9 @@
if (tmp_ipif != NULL)
ipif_refrele(tmp_ipif);
+ if (gcgrp_xtraref)
+ GCGRP_REFRELE(gcgrp);
+
if (error == EINPROGRESS)
return (error);
if (rtm != NULL) {
@@ -964,7 +1055,7 @@
* Returns a pointer to a message block containing the reply if successful,
* otherwise NULL is returned.
*/
-mblk_t *
+static mblk_t *
rts_rtmget(mblk_t *mp, ire_t *ire, ire_t *sire, sa_family_t af)
{
rt_msghdr_t *rtm;
@@ -973,10 +1064,49 @@
int rtm_addrs;
int rtm_flags;
in6_addr_t gw_addr_v6;
+ tsol_ire_gw_secattr_t *attrp = NULL;
+ tsol_gc_t *gc = NULL;
+ tsol_gcgrp_t *gcgrp = NULL;
+ int sacnt = 0;
ASSERT(ire->ire_ipif != NULL);
rtm = (rt_msghdr_t *)mp->b_rptr;
+ if (sire != NULL && sire->ire_gw_secattr != NULL)
+ attrp = sire->ire_gw_secattr;
+ else if (ire->ire_gw_secattr != NULL)
+ attrp = ire->ire_gw_secattr;
+
+ if (attrp != NULL) {
+ mutex_enter(&attrp->igsa_lock);
+ if ((gc = attrp->igsa_gc) != NULL) {
+ gcgrp = gc->gc_grp;
+ ASSERT(gcgrp != NULL);
+ rw_enter(&gcgrp->gcgrp_rwlock, RW_READER);
+ sacnt = 1;
+ } else if ((gcgrp = attrp->igsa_gcgrp) != NULL) {
+ rw_enter(&gcgrp->gcgrp_rwlock, RW_READER);
+ gc = gcgrp->gcgrp_head;
+ sacnt = gcgrp->gcgrp_count;
+ }
+ mutex_exit(&attrp->igsa_lock);
+
+ /* do nothing if there's no gc to report */
+ if (gc == NULL) {
+ ASSERT(sacnt == 0);
+ if (gcgrp != NULL) {
+ /* we might as well drop the lock now */
+ rw_exit(&gcgrp->gcgrp_rwlock);
+ gcgrp = NULL;
+ }
+ attrp = NULL;
+ }
+
+ ASSERT(gc == NULL || (gcgrp != NULL &&
+ RW_LOCK_HELD(&gcgrp->gcgrp_rwlock)));
+ }
+ ASSERT(sacnt == 0 || gc != NULL);
+
/*
* Always return RTA_DST, RTA_GATEWAY and RTA_NETMASK.
*
@@ -992,9 +1122,12 @@
rtm_addrs |= RTA_BRD;
}
- new_mp = rts_alloc_msg(RTM_GET, rtm_addrs, af);
- if (new_mp == NULL)
+ new_mp = rts_alloc_msg(RTM_GET, rtm_addrs, af, sacnt);
+ if (new_mp == NULL) {
+ if (gcgrp != NULL)
+ rw_exit(&gcgrp->gcgrp_rwlock);
return (NULL);
+ }
/*
* We set the destination address, gateway address,
@@ -1013,7 +1146,7 @@
rts_fill_msg(RTM_GET, rtm_addrs, ire->ire_addr,
ire->ire_mask, ire->ire_src_addr, ire->ire_src_addr,
ire->ire_ipif->ipif_pp_dst_addr, 0, ire->ire_ipif,
- new_mp);
+ new_mp, sacnt, gc);
} else {
if (sire->ire_flags & RTF_SETSRC)
rtm_addrs |= RTA_SRC;
@@ -1024,7 +1157,7 @@
(sire->ire_flags & RTF_SETSRC) ?
sire->ire_src_addr : ire->ire_src_addr,
ire->ire_ipif->ipif_pp_dst_addr,
- 0, ire->ire_ipif, new_mp);
+ 0, ire->ire_ipif, new_mp, sacnt, gc);
}
break;
case AF_INET6:
@@ -1034,7 +1167,8 @@
&ire->ire_mask_v6, &ire->ire_src_addr_v6,
&ire->ire_src_addr_v6,
&ire->ire_ipif->ipif_v6pp_dst_addr,
- &ipv6_all_zeros, ire->ire_ipif, new_mp);
+ &ipv6_all_zeros, ire->ire_ipif, new_mp,
+ sacnt, gc);
} else {
if (sire->ire_flags & RTF_SETSRC)
rtm_addrs |= RTA_SRC;
@@ -1048,10 +1182,14 @@
(sire->ire_flags & RTF_SETSRC) ?
&sire->ire_src_addr_v6 : &ire->ire_src_addr_v6,
&ire->ire_ipif->ipif_v6pp_dst_addr, &ipv6_all_zeros,
- ire->ire_ipif, new_mp);
+ ire->ire_ipif, new_mp, sacnt, gc);
}
break;
}
+
+ if (gcgrp != NULL)
+ rw_exit(&gcgrp->gcgrp_rwlock);
+
new_rtm = (rt_msghdr_t *)new_mp->b_rptr;
/*
@@ -1079,6 +1217,7 @@
new_rtm->rtm_inits = rts_getmetrics(ire, &new_rtm->rtm_rmx);
else
new_rtm->rtm_inits = rts_getmetrics(sire, &new_rtm->rtm_rmx);
+
return (new_mp);
}
@@ -1086,7 +1225,7 @@
* Fill the given if_data_t with interface statistics.
*/
static void
-rts_getifdata(if_data_t *if_data, ipif_t *ipif)
+rts_getifdata(if_data_t *if_data, const ipif_t *ipif)
{
if_data->ifi_type = ipif->ipif_type; /* ethernet, tokenring, etc */
if_data->ifi_addrlen = 0; /* media address length */
@@ -1254,7 +1393,7 @@
rts_getaddrs(rt_msghdr_t *rtm, in6_addr_t *dst_addrp, in6_addr_t *gw_addrp,
in6_addr_t *net_maskp, in6_addr_t *authorp, in6_addr_t *if_addrp,
in6_addr_t *in_src_addrp, ushort_t *indexp, ushort_t *src_indexp,
- sa_family_t *afp)
+ sa_family_t *afp, tsol_rtsecattr_t *rtsecattr, int *error)
{
struct sockaddr *sa;
int i;
@@ -1274,6 +1413,8 @@
*indexp = 0;
*src_indexp = 0;
*afp = AF_UNSPEC;
+ rtsecattr->rtsa_cnt = 0;
+ *error = 0;
/*
* At present we handle only RTA_DST, RTA_GATEWAY, RTA_NETMASK, RTA_IFP,
@@ -1354,6 +1495,16 @@
cp += size;
found_addrs |= addr_bits;
}
+
+ /*
+ * Parse the routing message and look for any security-
+ * related attributes for the route. For each valid
+ * attribute, allocate/obtain the corresponding kernel
+ * route security attributes.
+ */
+ *error = tsol_rtsa_init(rtm, rtsecattr, cp);
+ ASSERT(rtsecattr->rtsa_cnt <= TSOL_RTSA_REQUEST_MAX);
+
return (found_addrs);
}
@@ -1363,7 +1514,7 @@
static void
rts_fill_msg(int type, int rtm_addrs, ipaddr_t dst, ipaddr_t mask,
ipaddr_t gateway, ipaddr_t src_addr, ipaddr_t brd_addr, ipaddr_t author,
- ipif_t *ipif, mblk_t *mp)
+ const ipif_t *ipif, mblk_t *mp, uint_t sacnt, const tsol_gc_t *gc)
{
rt_msghdr_t *rtm;
sin_t *sin;
@@ -1372,6 +1523,7 @@
int i;
ASSERT(mp != NULL);
+ ASSERT(sacnt == 0 || gc != NULL);
/*
* First find the type of the message
* and its length.
@@ -1381,7 +1533,7 @@
* Now find the size of the data
* that follows the message header.
*/
- data_size = rts_data_msg_size(rtm_addrs, AF_INET);
+ data_size = rts_data_msg_size(rtm_addrs, AF_INET, sacnt);
rtm = (rt_msghdr_t *)mp->b_rptr;
mp->b_wptr = &mp->b_rptr[header_size];
@@ -1436,6 +1588,32 @@
break;
}
}
+
+ if (gc != NULL) {
+ rtm_ext_t *rtm_ext;
+ struct rtsa_s *rp_dst;
+ tsol_rtsecattr_t *rsap;
+ int i;
+
+ ASSERT(gc->gc_grp != NULL);
+ ASSERT(RW_LOCK_HELD(&gc->gc_grp->gcgrp_rwlock));
+ ASSERT(sacnt > 0);
+
+ rtm_ext = (rtm_ext_t *)cp;
+ rtm_ext->rtmex_type = RTMEX_GATEWAY_SECATTR;
+ rtm_ext->rtmex_len = TSOL_RTSECATTR_SIZE(sacnt);
+
+ rsap = (tsol_rtsecattr_t *)(rtm_ext + 1);
+ rsap->rtsa_cnt = sacnt;
+ rp_dst = rsap->rtsa_attr;
+
+ for (i = 0; i < sacnt; i++, gc = gc->gc_next, rp_dst++) {
+ ASSERT(gc->gc_db != NULL);
+ bcopy(&gc->gc_db->gcdb_attr, rp_dst, sizeof (*rp_dst));
+ }
+ cp = (uchar_t *)rp_dst;
+ }
+
mp->b_wptr = cp;
mp->b_cont = NULL;
/*
@@ -1451,12 +1629,12 @@
* Allocates and initializes a routing socket message.
*/
mblk_t *
-rts_alloc_msg(int type, int rtm_addrs, sa_family_t af)
+rts_alloc_msg(int type, int rtm_addrs, sa_family_t af, uint_t sacnt)
{
size_t length;
mblk_t *mp;
- length = RTS_MSG_SIZE(type, rtm_addrs, af);
+ length = RTS_MSG_SIZE(type, rtm_addrs, af, sacnt);
mp = allocb(length, BPRI_MED);
if (mp == NULL)
return (mp);
@@ -1489,7 +1667,7 @@
* of the same family (currently either AF_INET or AF_INET6).
*/
size_t
-rts_data_msg_size(int rtm_addrs, sa_family_t af)
+rts_data_msg_size(int rtm_addrs, sa_family_t af, uint_t sacnt)
{
int i;
size_t length = 0;
@@ -1519,6 +1697,9 @@
break;
}
}
+ if (sacnt > 0)
+ length += sizeof (rtm_ext_t) + TSOL_RTSECATTR_SIZE(sacnt);
+
return (length);
}
@@ -1538,11 +1719,11 @@
if (rtm_addrs == 0)
return;
- mp = rts_alloc_msg(type, rtm_addrs, AF_INET);
+ mp = rts_alloc_msg(type, rtm_addrs, AF_INET, 0);
if (mp == NULL)
return;
rts_fill_msg(type, rtm_addrs, dst_addr, net_mask, gw_addr, source, 0,
- author, NULL, mp);
+ author, NULL, mp, 0, NULL);
rtm = (rt_msghdr_t *)mp->b_rptr;
rtm->rtm_flags = flags;
rtm->rtm_errno = error;
@@ -1557,7 +1738,7 @@
* Message type generated RTM_IFINFO.
*/
void
-ip_rts_ifmsg(ipif_t *ipif)
+ip_rts_ifmsg(const ipif_t *ipif)
{
if_msghdr_t *ifm;
mblk_t *mp;
@@ -1572,18 +1753,19 @@
return;
if (ipif->ipif_isv6) {
af = AF_INET6;
- mp = rts_alloc_msg(RTM_IFINFO, RTA_IFP, af);
+ mp = rts_alloc_msg(RTM_IFINFO, RTA_IFP, af, 0);
if (mp == NULL)
return;
rts_fill_msg_v6(RTM_IFINFO, RTA_IFP, &ipv6_all_zeros,
&ipv6_all_zeros, &ipv6_all_zeros, &ipv6_all_zeros,
- &ipv6_all_zeros, &ipv6_all_zeros, ipif, mp);
+ &ipv6_all_zeros, &ipv6_all_zeros, ipif, mp, 0, NULL);
} else {
af = AF_INET;
- mp = rts_alloc_msg(RTM_IFINFO, RTA_IFP, af);
+ mp = rts_alloc_msg(RTM_IFINFO, RTA_IFP, af, 0);
if (mp == NULL)
return;
- rts_fill_msg(RTM_IFINFO, RTA_IFP, 0, 0, 0, 0, 0, 0, ipif, mp);
+ rts_fill_msg(RTM_IFINFO, RTA_IFP, 0, 0, 0, 0, 0, 0, ipif, mp,
+ 0, NULL);
}
ifm = (if_msghdr_t *)mp->b_rptr;
ifm->ifm_index = ipif->ipif_ill->ill_phyint->phyint_ifindex;
@@ -1600,7 +1782,7 @@
* The structure of the code is based on the 4.4BSD-Lite2 <net/rtsock.c>.
*/
void
-ip_rts_newaddrmsg(int cmd, int error, ipif_t *ipif)
+ip_rts_newaddrmsg(int cmd, int error, const ipif_t *ipif)
{
int pass;
int ncmd;
@@ -1624,21 +1806,22 @@
ncmd = ((cmd == RTM_ADD) ? RTM_NEWADDR : RTM_DELADDR);
rtm_addrs = (RTA_IFA | RTA_NETMASK | RTA_BRD);
- mp = rts_alloc_msg(ncmd, rtm_addrs, af);
+ mp = rts_alloc_msg(ncmd, rtm_addrs, af, 0);
if (mp == NULL)
continue;
switch (af) {
case AF_INET:
rts_fill_msg(ncmd, rtm_addrs, 0,
ipif->ipif_net_mask, 0, ipif->ipif_lcl_addr,
- ipif->ipif_pp_dst_addr, 0, NULL, mp);
+ ipif->ipif_pp_dst_addr, 0, NULL, mp,
+ 0, NULL);
break;
case AF_INET6:
rts_fill_msg_v6(ncmd, rtm_addrs,
&ipv6_all_zeros, &ipif->ipif_v6net_mask,
&ipv6_all_zeros, &ipif->ipif_v6lcl_addr,
&ipif->ipif_v6pp_dst_addr, &ipv6_all_zeros,
- NULL, mp);
+ NULL, mp, 0, NULL);
break;
}
ifam = (ifa_msghdr_t *)mp->b_rptr;
@@ -1652,21 +1835,21 @@
if ((cmd == RTM_ADD && pass == 2) ||
(cmd == RTM_DELETE && pass == 1)) {
rtm_addrs = (RTA_DST | RTA_NETMASK);
- mp = rts_alloc_msg(cmd, rtm_addrs, af);
+ mp = rts_alloc_msg(cmd, rtm_addrs, af, 0);
if (mp == NULL)
continue;
switch (af) {
case AF_INET:
rts_fill_msg(cmd, rtm_addrs,
ipif->ipif_lcl_addr, ipif->ipif_net_mask, 0,
- 0, 0, 0, NULL, mp);
+ 0, 0, 0, NULL, mp, 0, NULL);
break;
case AF_INET6:
rts_fill_msg_v6(cmd, rtm_addrs,
&ipif->ipif_v6lcl_addr,
&ipif->ipif_v6net_mask, &ipv6_all_zeros,
&ipv6_all_zeros, &ipv6_all_zeros,
- &ipv6_all_zeros, NULL, mp);
+ &ipv6_all_zeros, NULL, mp, 0, NULL);
break;
}
rtm = (rt_msghdr_t *)mp->b_rptr;
--- a/usr/src/uts/common/inet/ip/ipclassifier.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip/ipclassifier.c Fri Mar 24 12:29:20 2006 -0800
@@ -25,7 +25,7 @@
#pragma ident "%Z%%M% %I% %E% SMI"
-const char ipclassifier_version[] = "@(#)ipclassifier.c 1.6 04/03/31 SMI";
+const char ipclassifier_version[] = "@(#)ipclassifier.c %I% %E% SMI";
/*
* IP PACKET CLASSIFIER
@@ -110,7 +110,9 @@
* hdr_len: The size of IP header. It is used to find TCP or UDP header in
* the packet.
*
- * zoneid: The zone in which the returned connection must be.
+ * zoneid: The zone in which the returned connection must be; the zoneid
+ * corresponding to the ire_zoneid on the IRE located for the
+ * packet's destination address.
*
* For TCP connections, the lookup order is as follows:
* 5-tuple {src, dst, protocol, local port, remote port}
@@ -123,6 +125,40 @@
* these interfaces do not handle cases where a packets belongs
* to multiple UDP clients, which is handled in IP itself.
*
+ * If the destination IRE is ALL_ZONES (indicated by zoneid), then we must
+ * determine which actual zone gets the segment. This is used only in a
+ * labeled environment. The matching rules are:
+ *
+ * - If it's not a multilevel port, then the label on the packet selects
+ * the zone. Unlabeled packets are delivered to the global zone.
+ *
+ * - If it's a multilevel port, then only the zone registered to receive
+ * packets on that port matches.
+ *
+ * Also, in a labeled environment, packet labels need to be checked. For fully
+ * bound TCP connections, we can assume that the packet label was checked
+ * during connection establishment, and doesn't need to be checked on each
+ * packet. For others, though, we need to check for strict equality or, for
+ * multilevel ports, membership in the range or set. This part currently does
+ * a tnrh lookup on each packet, but could be optimized to use cached results
+ * if that were necessary. (SCTP doesn't come through here, but if it did,
+ * we would apply the same rules as TCP.)
+ *
+ * An implication of the above is that fully-bound TCP sockets must always use
+ * distinct 4-tuples; they can't be discriminated by label alone.
+ *
+ * Note that we cannot trust labels on packets sent to fully-bound UDP sockets,
+ * as there's no connection set-up handshake and no shared state.
+ *
+ * Labels on looped-back packets within a single zone do not need to be
+ * checked, as all processes in the same zone have the same label.
+ *
+ * Finally, for unlabeled packets received by a labeled system, special rules
+ * apply. We consider only the MLP if there is one. Otherwise, we prefer a
+ * socket in the zone whose label matches the default label of the sender, if
+ * any. In any event, the receiving socket must have SO_MAC_EXEMPT set and the
+ * receiver's label must dominate the sender's default label.
+ *
* conn_t *ipcl_tcp_lookup_reversed_ipv4(ipha_t *, tcph_t *, int);
* conn_t *ipcl_tcp_lookup_reversed_ipv6(ip6_t *, tcpha_t *, int, uint_t);
*
@@ -203,11 +239,9 @@
#include <sys/types.h>
#include <sys/stream.h>
-#include <sys/dlpi.h>
#include <sys/stropts.h>
#include <sys/sysmacros.h>
#include <sys/strsubr.h>
-#include <sys/strlog.h>
#include <sys/strsun.h>
#define _SUN_TPI_VERSION 2
#include <sys/ddi.h>
@@ -225,24 +259,17 @@
#include <inet/ip.h>
#include <inet/ip6.h>
#include <inet/tcp.h>
-#include <inet/tcp_trace.h>
-#include <inet/ip_multi.h>
-#include <inet/ip_if.h>
-#include <inet/ip_ire.h>
-#include <inet/ip_rts.h>
-#include <inet/optcom.h>
#include <inet/ip_ndp.h>
#include <inet/udp_impl.h>
#include <inet/sctp_ip.h>
-#include <sys/ethernet.h>
-#include <net/if_types.h>
#include <sys/cpuvar.h>
-#include <inet/mi.h>
#include <inet/ipclassifier.h>
#include <inet/ipsec_impl.h>
+#include <sys/tsol/tnet.h>
+
#ifdef DEBUG
#define IPCL_DEBUG
#else
@@ -527,6 +554,16 @@
ASSERT(connp->conn_ref == 0);
ASSERT(connp->conn_ire_cache == NULL);
+ if (connp->conn_peercred != NULL &&
+ connp->conn_peercred != connp->conn_cred)
+ crfree(connp->conn_peercred);
+ connp->conn_peercred = NULL;
+
+ if (connp->conn_cred != NULL) {
+ crfree(connp->conn_cred);
+ connp->conn_cred = NULL;
+ }
+
ipcl_globalhash_remove(connp);
cv_destroy(&connp->conn_cv);
@@ -537,6 +574,7 @@
ASSERT(connp->conn_tcp != NULL);
tcp_free(tcp);
mp = tcp->tcp_timercache;
+ tcp->tcp_cred = NULL;
if (tcp->tcp_sack_info != NULL) {
bzero(tcp->tcp_sack_info, sizeof (tcp_sack_info_t));
@@ -763,6 +801,7 @@
void
ipcl_hash_insert_wildcard(connf_t *connfp, conn_t *connp)
{
+ ASSERT(!connp->conn_mac_exempt);
IPCL_HASH_INSERT_WILDCARD(connfp, connp);
}
@@ -772,6 +811,8 @@
connf_t *connfp;
ASSERT(connp != NULL);
+ ASSERT(!connp->conn_mac_exempt || protocol == IPPROTO_AH ||
+ protocol == IPPROTO_ESP);
connp->conn_ulp = protocol;
@@ -786,6 +827,8 @@
connf_t *connfp;
ASSERT(connp != NULL);
+ ASSERT(!connp->conn_mac_exempt || protocol == IPPROTO_AH ||
+ protocol == IPPROTO_ESP);
connp->conn_ulp = protocol;
@@ -844,6 +887,69 @@
}
/*
+ * Check for a MAC exemption conflict on a labeled system. Note that for
+ * protocols that use port numbers (UDP, TCP, SCTP), we do this check up in the
+ * transport layer. This check is for binding all other protocols.
+ *
+ * Returns true if there's a conflict.
+ */
+static boolean_t
+check_exempt_conflict_v4(conn_t *connp)
+{
+ connf_t *connfp;
+ conn_t *tconn;
+
+ connfp = &ipcl_proto_fanout[connp->conn_ulp];
+ mutex_enter(&connfp->connf_lock);
+ for (tconn = connfp->connf_head; tconn != NULL;
+ tconn = tconn->conn_next) {
+ /* We don't allow v4 fallback for v6 raw socket */
+ if (connp->conn_af_isv6 != tconn->conn_af_isv6)
+ continue;
+ /* If neither is exempt, then there's no conflict */
+ if (!connp->conn_mac_exempt && !tconn->conn_mac_exempt)
+ continue;
+ /* If both are bound to different specific addrs, ok */
+ if (connp->conn_src != INADDR_ANY &&
+ tconn->conn_src != INADDR_ANY &&
+ connp->conn_src != tconn->conn_src)
+ continue;
+ /* These two conflict; fail */
+ break;
+ }
+ mutex_exit(&connfp->connf_lock);
+ return (tconn != NULL);
+}
+
+static boolean_t
+check_exempt_conflict_v6(conn_t *connp)
+{
+ connf_t *connfp;
+ conn_t *tconn;
+
+ connfp = &ipcl_proto_fanout[connp->conn_ulp];
+ mutex_enter(&connfp->connf_lock);
+ for (tconn = connfp->connf_head; tconn != NULL;
+ tconn = tconn->conn_next) {
+ /* We don't allow v4 fallback for v6 raw socket */
+ if (connp->conn_af_isv6 != tconn->conn_af_isv6)
+ continue;
+ /* If neither is exempt, then there's no conflict */
+ if (!connp->conn_mac_exempt && !tconn->conn_mac_exempt)
+ continue;
+ /* If both are bound to different addrs, ok */
+ if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_srcv6) &&
+ !IN6_IS_ADDR_UNSPECIFIED(&tconn->conn_srcv6) &&
+ !IN6_ARE_ADDR_EQUAL(&connp->conn_srcv6, &tconn->conn_srcv6))
+ continue;
+ /* These two conflict; fail */
+ break;
+ }
+ mutex_exit(&connfp->connf_lock);
+ return (tconn != NULL);
+}
+
+/*
* (v4, v6) bind hash insertion routines
*/
int
@@ -865,8 +971,11 @@
connp->conn_lport = lport;
switch (protocol) {
+ default:
+ if (is_system_labeled() && check_exempt_conflict_v4(connp))
+ return (EADDRINUSE);
+ /* FALLTHROUGH */
case IPPROTO_UDP:
- default:
if (protocol == IPPROTO_UDP) {
IPCL_DEBUG_LVL(64,
("ipcl_bind_insert: connp %p - udp\n",
@@ -891,6 +1000,7 @@
case IPPROTO_TCP:
/* Insert it in the Bind Hash */
+ ASSERT(connp->conn_zoneid != ALL_ZONES);
connfp = &ipcl_bind_fanout[IPCL_BIND_HASH(lport)];
if (connp->conn_src != INADDR_ANY) {
IPCL_HASH_INSERT_BOUND(connfp, connp);
@@ -927,8 +1037,11 @@
connp->conn_lport = lport;
switch (protocol) {
+ default:
+ if (is_system_labeled() && check_exempt_conflict_v6(connp))
+ return (EADDRINUSE);
+ /* FALLTHROUGH */
case IPPROTO_UDP:
- default:
if (protocol == IPPROTO_UDP) {
IPCL_DEBUG_LVL(128,
("ipcl_bind_insert_v6: connp %p - udp\n",
@@ -954,6 +1067,7 @@
/* XXX - Need a separate table for IN6_IS_ADDR_UNSPECIFIED? */
/* Insert it in the Bind Hash */
+ ASSERT(connp->conn_zoneid != ALL_ZONES);
connfp = &ipcl_bind_fanout[IPCL_BIND_HASH(lport)];
if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_srcv6)) {
IPCL_HASH_INSERT_BOUND(connfp, connp);
@@ -1055,8 +1169,18 @@
ret = ipcl_sctp_hash_insert(connp, lport);
break;
+ default:
+ /*
+ * Check for conflicts among MAC exempt bindings. For
+ * transports with port numbers, this is done by the upper
+ * level per-transport binding logic. For all others, it's
+ * done here.
+ */
+ if (is_system_labeled() && check_exempt_conflict_v4(connp))
+ return (EADDRINUSE);
+ /* FALLTHROUGH */
+
case IPPROTO_UDP:
- default:
up = (uint16_t *)&ports;
IPCL_CONN_INIT(connp, protocol, src, rem, ports);
if (protocol == IPPROTO_UDP) {
@@ -1128,8 +1252,11 @@
ret = ipcl_sctp_hash_insert(connp, lport);
break;
+ default:
+ if (is_system_labeled() && check_exempt_conflict_v6(connp))
+ return (EADDRINUSE);
+ /* FALLTHROUGH */
case IPPROTO_UDP:
- default:
up = (uint16_t *)&ports;
IPCL_CONN_INIT_V6(connp, protocol, *src, *rem, ports);
if (protocol == IPPROTO_UDP) {
@@ -1155,6 +1282,11 @@
* v4 packet classifying function. looks up the fanout table to
* find the conn, the packet belongs to. returns the conn with
* the reference held, null otherwise.
+ *
+ * If zoneid is ALL_ZONES, then the search rules described in the "Connection
+ * Lookup" comment block are applied. Labels are also checked as described
+ * above. If the packet is from the inside (looped back), and is from the same
+ * zone, then label checks are omitted.
*/
conn_t *
ipcl_classify_v4(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid)
@@ -1166,6 +1298,8 @@
uint32_t ports;
conn_t *connp;
uint16_t *up;
+ boolean_t shared_addr;
+ boolean_t unlabeled;
ipha = (ipha_t *)mp->b_rptr;
up = (uint16_t *)((uchar_t *)ipha + hdr_len + TCP_PORTS_OFFSET);
@@ -1184,6 +1318,13 @@
}
if (connp != NULL) {
+ /*
+ * We have a fully-bound TCP connection.
+ *
+ * For labeled systems, there's no need to check the
+ * label here. It's known to be good as we checked
+ * before allowing the connection to become bound.
+ */
CONN_INC_REF(connp);
mutex_exit(&connfp->connf_lock);
return (connp);
@@ -1192,18 +1333,60 @@
mutex_exit(&connfp->connf_lock);
lport = up[1];
+ unlabeled = B_FALSE;
+ /* Cred cannot be null on IPv4 */
+ if (is_system_labeled())
+ unlabeled = (crgetlabel(DB_CRED(mp))->tsl_flags &
+ TSLF_UNLABELED) != 0;
+ shared_addr = (zoneid == ALL_ZONES);
+ if (shared_addr) {
+ zoneid = tsol_mlp_findzone(protocol, lport);
+ /*
+ * If no shared MLP is found, tsol_mlp_findzone returns
+ * ALL_ZONES. In that case, we assume it's SLP, and
+ * search for the zone based on the packet label.
+ *
+ * If there is such a zone, we prefer to find a
+ * connection in it. Otherwise, we look for a
+ * MAC-exempt connection in any zone whose label
+ * dominates the default label on the packet.
+ */
+ if (zoneid == ALL_ZONES)
+ zoneid = tsol_packet_to_zoneid(mp);
+ else
+ unlabeled = B_FALSE;
+ }
+
bind_connfp = &ipcl_bind_fanout[IPCL_BIND_HASH(lport)];
mutex_enter(&bind_connfp->connf_lock);
for (connp = bind_connfp->connf_head; connp != NULL;
connp = connp->conn_next) {
- if (IPCL_BIND_MATCH(connp, protocol,
- ipha->ipha_dst, lport) &&
- connp->conn_zoneid == zoneid)
+ if (IPCL_BIND_MATCH(connp, protocol, ipha->ipha_dst,
+ lport) &&
+ (connp->conn_zoneid == zoneid ||
+ (unlabeled && connp->conn_mac_exempt)))
break;
}
+ /*
+ * If the matching connection is SLP on a private address, then
+ * the label on the packet must match the local zone's label.
+ * Otherwise, it must be in the label range defined by tnrh.
+ * This is ensured by tsol_receive_label.
+ */
+ if (connp != NULL && is_system_labeled() &&
+ !tsol_receive_local(mp, &ipha->ipha_dst, IPV4_VERSION,
+ shared_addr, connp)) {
+ DTRACE_PROBE3(
+ tx__ip__log__info__classify__tcp,
+ char *,
+ "connp(1) could not receive mp(2)",
+ conn_t *, connp, mblk_t *, mp);
+ connp = NULL;
+ }
+
if (connp != NULL) {
- /* Have a listner at least */
+ /* Have a listener at least */
CONN_INC_REF(connp);
mutex_exit(&bind_connfp->connf_lock);
return (connp);
@@ -1218,6 +1401,29 @@
case IPPROTO_UDP:
lport = up[1];
+ unlabeled = B_FALSE;
+ /* Cred cannot be null on IPv4 */
+ if (is_system_labeled())
+ unlabeled = (crgetlabel(DB_CRED(mp))->tsl_flags &
+ TSLF_UNLABELED) != 0;
+ shared_addr = (zoneid == ALL_ZONES);
+ if (shared_addr) {
+ zoneid = tsol_mlp_findzone(protocol, lport);
+ /*
+ * If no shared MLP is found, tsol_mlp_findzone returns
+ * ALL_ZONES. In that case, we assume it's SLP, and
+ * search for the zone based on the packet label.
+ *
+ * If there is such a zone, we prefer to find a
+ * connection in it. Otherwise, we look for a
+ * MAC-exempt connection in any zone whose label
+ * dominates the default label on the packet.
+ */
+ if (zoneid == ALL_ZONES)
+ zoneid = tsol_packet_to_zoneid(mp);
+ else
+ unlabeled = B_FALSE;
+ }
fport = up[0];
IPCL_DEBUG_LVL(512, ("ipcl_udp_classify %x %x", lport, fport));
connfp = &ipcl_udp_fanout[IPCL_UDP_HASH(lport)];
@@ -1226,10 +1432,20 @@
connp = connp->conn_next) {
if (IPCL_UDP_MATCH(connp, lport, ipha->ipha_dst,
fport, ipha->ipha_src) &&
- connp->conn_zoneid == zoneid)
+ (connp->conn_zoneid == zoneid ||
+ (unlabeled && connp->conn_mac_exempt)))
break;
}
+ if (connp != NULL && is_system_labeled() &&
+ !tsol_receive_local(mp, &ipha->ipha_dst, IPV4_VERSION,
+ shared_addr, connp)) {
+ DTRACE_PROBE3(tx__ip__log__info__classify__udp,
+ char *, "connp(1) could not receive mp(2)",
+ conn_t *, connp, mblk_t *, mp);
+ connp = NULL;
+ }
+
if (connp != NULL) {
CONN_INC_REF(connp);
mutex_exit(&connfp->connf_lock);
@@ -1260,7 +1476,8 @@
uint32_t ports;
conn_t *connp;
uint16_t *up;
-
+ boolean_t shared_addr;
+ boolean_t unlabeled;
ip6h = (ip6_t *)mp->b_rptr;
@@ -1281,6 +1498,13 @@
}
if (connp != NULL) {
+ /*
+ * We have a fully-bound TCP connection.
+ *
+ * For labeled systems, there's no need to check the
+ * label here. It's known to be good as we checked
+ * before allowing the connection to become bound.
+ */
CONN_INC_REF(connp);
mutex_exit(&connfp->connf_lock);
return (connp);
@@ -1289,16 +1513,53 @@
mutex_exit(&connfp->connf_lock);
lport = up[1];
+ unlabeled = B_FALSE;
+ /* Cred can be null on IPv6 */
+ if (is_system_labeled()) {
+ cred_t *cr = DB_CRED(mp);
+
+ unlabeled = (cr != NULL &&
+ crgetlabel(cr)->tsl_flags & TSLF_UNLABELED) != 0;
+ }
+ shared_addr = (zoneid == ALL_ZONES);
+ if (shared_addr) {
+ zoneid = tsol_mlp_findzone(protocol, lport);
+ /*
+ * If no shared MLP is found, tsol_mlp_findzone returns
+ * ALL_ZONES. In that case, we assume it's SLP, and
+ * search for the zone based on the packet label.
+ *
+ * If there is such a zone, we prefer to find a
+ * connection in it. Otherwise, we look for a
+ * MAC-exempt connection in any zone whose label
+ * dominates the default label on the packet.
+ */
+ if (zoneid == ALL_ZONES)
+ zoneid = tsol_packet_to_zoneid(mp);
+ else
+ unlabeled = B_FALSE;
+ }
+
bind_connfp = &ipcl_bind_fanout[IPCL_BIND_HASH(lport)];
mutex_enter(&bind_connfp->connf_lock);
for (connp = bind_connfp->connf_head; connp != NULL;
connp = connp->conn_next) {
if (IPCL_BIND_MATCH_V6(connp, protocol,
ip6h->ip6_dst, lport) &&
- connp->conn_zoneid == zoneid)
+ (connp->conn_zoneid == zoneid ||
+ (unlabeled && connp->conn_mac_exempt)))
break;
}
+ if (connp != NULL && is_system_labeled() &&
+ !tsol_receive_local(mp, &ip6h->ip6_dst, IPV6_VERSION,
+ shared_addr, connp)) {
+ DTRACE_PROBE3(tx__ip__log__info__classify__tcp6,
+ char *, "connp(1) could not receive mp(2)",
+ conn_t *, connp, mblk_t *, mp);
+ connp = NULL;
+ }
+
if (connp != NULL) {
/* Have a listner at least */
CONN_INC_REF(connp);
@@ -1320,6 +1581,33 @@
case IPPROTO_UDP:
up = (uint16_t *)&mp->b_rptr[hdr_len];
lport = up[1];
+ unlabeled = B_FALSE;
+ /* Cred can be null on IPv6 */
+ if (is_system_labeled()) {
+ cred_t *cr = DB_CRED(mp);
+
+ unlabeled = (cr != NULL &&
+ crgetlabel(cr)->tsl_flags & TSLF_UNLABELED) != 0;
+ }
+ shared_addr = (zoneid == ALL_ZONES);
+ if (shared_addr) {
+ zoneid = tsol_mlp_findzone(protocol, lport);
+ /*
+ * If no shared MLP is found, tsol_mlp_findzone returns
+ * ALL_ZONES. In that case, we assume it's SLP, and
+ * search for the zone based on the packet label.
+ *
+ * If there is such a zone, we prefer to find a
+ * connection in it. Otherwise, we look for a
+ * MAC-exempt connection in any zone whose label
+ * dominates the default label on the packet.
+ */
+ if (zoneid == ALL_ZONES)
+ zoneid = tsol_packet_to_zoneid(mp);
+ else
+ unlabeled = B_FALSE;
+ }
+
fport = up[0];
IPCL_DEBUG_LVL(512, ("ipcl_udp_classify_v6 %x %x", lport,
fport));
@@ -1329,10 +1617,20 @@
connp = connp->conn_next) {
if (IPCL_UDP_MATCH_V6(connp, lport, ip6h->ip6_dst,
fport, ip6h->ip6_src) &&
- connp->conn_zoneid == zoneid)
+ (connp->conn_zoneid == zoneid ||
+ (unlabeled && connp->conn_mac_exempt)))
break;
}
+ if (connp != NULL && is_system_labeled() &&
+ !tsol_receive_local(mp, &ip6h->ip6_dst, IPV6_VERSION,
+ shared_addr, connp)) {
+ DTRACE_PROBE3(tx__ip__log__info__classify__udp6,
+ char *, "connp(1) could not receive mp(2)",
+ conn_t *, connp, mblk_t *, mp);
+ connp = NULL;
+ }
+
if (connp != NULL) {
CONN_INC_REF(connp);
mutex_exit(&connfp->connf_lock);
@@ -1349,7 +1647,6 @@
break;
}
-
return (NULL);
}
@@ -1384,52 +1681,96 @@
}
conn_t *
-ipcl_classify_raw(uint8_t protocol, zoneid_t zoneid, uint32_t ports,
- ipha_t *hdr)
+ipcl_classify_raw(mblk_t *mp, uint8_t protocol, zoneid_t zoneid,
+ uint32_t ports, ipha_t *hdr)
{
- struct connf_s *connfp;
+ connf_t *connfp;
conn_t *connp;
in_port_t lport;
int af;
+ boolean_t shared_addr;
+ boolean_t unlabeled;
+ const void *dst;
lport = ((uint16_t *)&ports)[1];
+
+ unlabeled = B_FALSE;
+ /* Cred can be null on IPv6 */
+ if (is_system_labeled()) {
+ cred_t *cr = DB_CRED(mp);
+
+ unlabeled = (cr != NULL &&
+ crgetlabel(cr)->tsl_flags & TSLF_UNLABELED) != 0;
+ }
+ shared_addr = (zoneid == ALL_ZONES);
+ if (shared_addr) {
+ zoneid = tsol_mlp_findzone(protocol, lport);
+ /*
+ * If no shared MLP is found, tsol_mlp_findzone returns
+ * ALL_ZONES. In that case, we assume it's SLP, and search for
+ * the zone based on the packet label.
+ *
+ * If there is such a zone, we prefer to find a connection in
+ * it. Otherwise, we look for a MAC-exempt connection in any
+ * zone whose label dominates the default label on the packet.
+ */
+ if (zoneid == ALL_ZONES)
+ zoneid = tsol_packet_to_zoneid(mp);
+ else
+ unlabeled = B_FALSE;
+ }
+
af = IPH_HDR_VERSION(hdr);
+ dst = af == IPV4_VERSION ? (const void *)&hdr->ipha_dst :
+ (const void *)&((ip6_t *)hdr)->ip6_dst;
connfp = &ipcl_raw_fanout[IPCL_RAW_HASH(ntohs(lport))];
mutex_enter(&connfp->connf_lock);
for (connp = connfp->connf_head; connp != NULL;
connp = connp->conn_next) {
/* We don't allow v4 fallback for v6 raw socket. */
- if ((af == (connp->conn_af_isv6 ? IPV4_VERSION :
- IPV6_VERSION)) || (connp->conn_zoneid != zoneid)) {
+ if (af == (connp->conn_af_isv6 ? IPV4_VERSION :
+ IPV6_VERSION))
continue;
- }
if (connp->conn_fully_bound) {
if (af == IPV4_VERSION) {
- if (IPCL_CONN_MATCH(connp, protocol,
- hdr->ipha_src, hdr->ipha_dst, ports)) {
- break;
- }
+ if (!IPCL_CONN_MATCH(connp, protocol,
+ hdr->ipha_src, hdr->ipha_dst, ports))
+ continue;
} else {
- if (IPCL_CONN_MATCH_V6(connp, protocol,
+ if (!IPCL_CONN_MATCH_V6(connp, protocol,
((ip6_t *)hdr)->ip6_src,
- ((ip6_t *)hdr)->ip6_dst, ports)) {
- break;
- }
+ ((ip6_t *)hdr)->ip6_dst, ports))
+ continue;
}
} else {
if (af == IPV4_VERSION) {
- if (IPCL_BIND_MATCH(connp, protocol,
- hdr->ipha_dst, lport)) {
- break;
- }
+ if (!IPCL_BIND_MATCH(connp, protocol,
+ hdr->ipha_dst, lport))
+ continue;
} else {
- if (IPCL_BIND_MATCH_V6(connp, protocol,
- ((ip6_t *)hdr)->ip6_dst, lport)) {
- break;
- }
+ if (!IPCL_BIND_MATCH_V6(connp, protocol,
+ ((ip6_t *)hdr)->ip6_dst, lport))
+ continue;
}
}
+
+ if (connp->conn_zoneid == zoneid ||
+ (unlabeled && connp->conn_mac_exempt))
+ break;
+ }
+ /*
+ * If the connection is fully-bound and connection-oriented (TCP or
+ * SCTP), then we've already validated the remote system's label.
+ * There's no need to do it again for every packet.
+ */
+ if (connp != NULL && is_system_labeled() && (!connp->conn_fully_bound ||
+ !(connp->conn_flags & (IPCL_TCP|IPCL_SCTPCONN))) &&
+ !tsol_receive_local(mp, dst, af, shared_addr, connp)) {
+ DTRACE_PROBE3(tx__ip__log__info__classify__rawip,
+ char *, "connp(1) could not receive mp(2)",
+ conn_t *, connp, mblk_t *, mp);
+ connp = NULL;
}
if (connp != NULL)
@@ -1797,7 +2138,8 @@
}
/*
- * To find a TCP listening connection matching the incoming segment.
+ * Finds a TCP/IPv4 listening connection; called by tcp_disconnect to locate
+ * a listener when changing state.
*/
conn_t *
ipcl_lookup_listener_v4(uint16_t lport, ipaddr_t laddr, zoneid_t zoneid)
@@ -1813,6 +2155,8 @@
if (laddr == 0)
return (NULL);
+ ASSERT(zoneid != ALL_ZONES);
+
bind_connfp = &ipcl_bind_fanout[IPCL_BIND_HASH(lport)];
mutex_enter(&bind_connfp->connf_lock);
for (connp = bind_connfp->connf_head; connp != NULL;
@@ -1830,7 +2174,10 @@
return (NULL);
}
-
+/*
+ * Finds a TCP/IPv6 listening connection; called by tcp_disconnect to locate
+ * a listener when changing state.
+ */
conn_t *
ipcl_lookup_listener_v6(uint16_t lport, in6_addr_t *laddr, uint_t ifindex,
zoneid_t zoneid)
@@ -1846,6 +2193,7 @@
if (IN6_IS_ADDR_UNSPECIFIED(laddr))
return (NULL);
+ ASSERT(zoneid != ALL_ZONES);
bind_connfp = &ipcl_bind_fanout[IPCL_BIND_HASH(lport)];
mutex_enter(&bind_connfp->connf_lock);
--- a/usr/src/uts/common/inet/ip/ipsecah.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip/ipsecah.c Fri Mar 24 12:29:20 2006 -0800
@@ -66,6 +66,7 @@
#include <sys/crypto/common.h>
#include <sys/crypto/api.h>
#include <sys/kstat.h>
+#include <sys/strsubr.h>
/* Packet dropper for AH drops. */
static ipdropper_t ah_dropper;
@@ -4080,6 +4081,12 @@
nip6h->ip6_plen = htons((uint16_t)length);
}
+ if (is_system_labeled()) {
+ /*
+ * inherit the label by setting it in the new ip header
+ */
+ mblk_setcred(phdr_mp, DB_CRED(mp));
+ }
return (IPSEC_STATUS_SUCCESS);
ah_in_discard:
@@ -4197,6 +4204,13 @@
nip6h->ip6_plen = htons((uint16_t)length);
}
+ if (is_system_labeled()) {
+ /*
+ * inherit the label by setting it in the new ip header
+ */
+ mblk_setcred(phdr_mp, DB_CRED(mp));
+ }
+
/* Skip the original IP header */
mp->b_rptr += hdrs_length;
if (mp->b_rptr == mp->b_wptr) {
--- a/usr/src/uts/common/inet/ip/nattymod.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip/nattymod.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -308,7 +307,7 @@
ni->ni_addr = addr;
- ire = ire_ctable_lookup(addr, 0, IRE_LOCAL, NULL, ALL_ZONES,
+ ire = ire_ctable_lookup(addr, 0, IRE_LOCAL, NULL, ALL_ZONES, NULL,
MATCH_IRE_TYPE);
if (ire == NULL)
goto bail;
--- a/usr/src/uts/common/inet/ip/spd.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip/spd.c Fri Mar 24 12:29:20 2006 -0800
@@ -3471,6 +3471,7 @@
attach_if = ii->ipsec_in_attach_if;
ifindex = ii->ipsec_in_ill_index;
zoneid = ii->ipsec_in_zoneid;
+ ASSERT(zoneid != ALL_ZONES);
v4 = ii->ipsec_in_v4;
ipsec_in_release_refs(ii);
@@ -4153,8 +4154,13 @@
* When conn is non-NULL, the zoneid is set by ipsec_init_ipsec_out().
* Otherwise set the zoneid based on the ire.
*/
- if (connp == NULL)
- io->ipsec_out_zoneid = ire->ire_zoneid;
+ if (connp == NULL) {
+ zoneid_t zoneid = ire->ire_zoneid;
+
+ if (zoneid == ALL_ZONES)
+ zoneid = GLOBAL_ZONEID;
+ io->ipsec_out_zoneid = zoneid;
+ }
return (ipsec_mp);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/inet/ip/tn_ipopt.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,1469 @@
+/*
+ * 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/systm.h>
+#include <sys/kmem.h>
+#include <sys/disp.h>
+#include <sys/stream.h>
+#include <sys/strsubr.h>
+#include <sys/strsun.h>
+#include <sys/policy.h>
+#include <sys/tsol/label_macro.h>
+#include <sys/tsol/tndb.h>
+#include <sys/tsol/tnet.h>
+#include <inet/ip.h>
+#include <inet/ip6.h>
+#include <inet/tcp.h>
+#include <inet/ipclassifier.h>
+#include <inet/ip_ire.h>
+
+/*
+ * This routine takes a sensitivity label as input and creates a CIPSO
+ * option in the specified buffer. It returns the size of the CIPSO option.
+ * If the sensitivity label is too large for the CIPSO option, then 0
+ * is returned.
+ *
+ * tsol2cipso_tt1 returns 0 for failure and greater than 0 for success
+ * (more accurately, success means a return value between 10 and 40).
+ */
+
+static int
+tsol2cipso_tt1(const bslabel_t *sl, unsigned char *cop, uint32_t doi)
+{
+ struct cipso_tag_type_1 *tt1;
+ const _bslabel_impl_t *bsl;
+ const uchar_t *ucp;
+ int i;
+
+ if (doi == 0)
+ return (0);
+
+ /* check for Admin High sensitivity label */
+ if (blequal(sl, label2bslabel(l_admin_high)))
+ return (0);
+
+ /* check whether classification will fit in one octet */
+ bsl = (const _bslabel_impl_t *)sl;
+ if (LCLASS(bsl) & 0xFF00)
+ return (0);
+
+ /*
+ * Check whether compartments will fit in 30 octets.
+ * Compartments 241 - 256 are not allowed.
+ */
+ if (ntohl(bsl->compartments.c8) & 0x0000FFFF)
+ return (0);
+
+ /*
+ * Compute option length and tag length.
+ * 'p' points to the last two bytes in the Sensitivity Label's
+ * compartments; these cannot be mapped into CIPSO compartments.
+ */
+ ucp = (const uchar_t *)&bsl->compartments.c8 + 2;
+ while (--ucp >= (const uchar_t *)&bsl->compartments.c1)
+ if (*ucp != 0)
+ break;
+
+ i = ucp - (const uchar_t *)&bsl->compartments.c1 + 1;
+
+ if (cop == NULL)
+ return (10 + i);
+
+ doi = htonl(doi);
+ ucp = (const uchar_t *)&doi;
+ cop[IPOPT_OPTVAL] = IPOPT_COMSEC;
+ cop[IPOPT_OLEN] = 10 + i;
+ cop[IPOPT_OLEN+1] = ucp[0];
+ cop[IPOPT_OLEN+2] = ucp[1];
+ cop[IPOPT_OLEN+3] = ucp[2];
+ cop[IPOPT_OLEN+4] = ucp[3];
+ tt1 = (struct cipso_tag_type_1 *)&cop[IPOPT_OLEN + 5];
+ tt1->tag_type = 1;
+ tt1->tag_align = 0;
+ tt1->tag_sl = LCLASS(bsl);
+ tt1->tag_length = 4 + i;
+
+ bcopy(&bsl->compartments.c1, tt1->tag_cat, i);
+
+ return (cop[IPOPT_OLEN]);
+}
+
+/*
+ * The following routine copies a datagram's option into the specified buffer
+ * (if buffer pointer is non-null), or returns a pointer to the label within
+ * the streams message (if buffer is null). In both cases, tsol_get_option
+ * returns the option's type.
+ *
+ * tsol_get_option assumes that the specified buffer is large enough to
+ * hold the largest valid CIPSO option. Since the total number of
+ * IP header options cannot exceed 40 bytes, a 40 byte buffer is a good choice.
+ */
+
+tsol_ip_label_t
+tsol_get_option(mblk_t *mp, uchar_t **buffer)
+{
+ ipha_t *ipha;
+ uchar_t *opt;
+ uint32_t totallen;
+ uint32_t optval;
+ uint32_t optlen;
+
+ ipha = (ipha_t *)mp->b_rptr;
+
+ /*
+ * Get length (in 4 byte octets) of IP header options.
+ * If header doesn't contain options, then return OPT_NONE.
+ */
+ totallen = ipha->ipha_version_and_hdr_length -
+ (uint8_t)((IP_VERSION << 4) + IP_SIMPLE_HDR_LENGTH_IN_WORDS);
+
+ if (totallen == 0)
+ return (OPT_NONE);
+
+ totallen <<= 2;
+
+ /*
+ * Search for CIPSO option.
+ * If no such option is present, then return OPT_NONE.
+ */
+ opt = (uchar_t *)&ipha[1];
+ while (totallen != 0) {
+ switch (optval = opt[IPOPT_OPTVAL]) {
+ case IPOPT_EOL:
+ return (OPT_NONE);
+ case IPOPT_NOP:
+ optlen = 1;
+ break;
+ default:
+ if (totallen <= IPOPT_OLEN)
+ return (OPT_NONE);
+ optlen = opt[IPOPT_OLEN];
+ if (optlen < 2)
+ return (OPT_NONE);
+ }
+ if (optlen > totallen)
+ return (OPT_NONE);
+ /*
+ * Copy pointer to option into '*buffer' and
+ * return the option type.
+ */
+ switch (optval) {
+ case IPOPT_COMSEC:
+ *buffer = opt;
+ if (TSOL_CIPSO_TAG_OFFSET < optlen &&
+ opt[TSOL_CIPSO_TAG_OFFSET] == 1)
+ return (OPT_CIPSO);
+ return (OPT_NONE);
+ }
+ totallen -= optlen;
+ opt += optlen;
+ }
+ return (OPT_NONE);
+}
+
+/*
+ * tsol_compute_label()
+ *
+ * This routine computes the IP label that should be on a packet based on the
+ * connection and destination information.
+ *
+ * Returns:
+ * 0 Fetched label
+ * EACCES The packet failed the remote host accreditation
+ * ENOMEM Memory allocation failure
+ * EINVAL Label cannot be computed
+ */
+int
+tsol_compute_label(const cred_t *credp, ipaddr_t dst, uchar_t *opt_storage,
+ boolean_t isexempt)
+{
+ uint_t sec_opt_len;
+ ts_label_t *tsl;
+ tsol_tpc_t *dst_rhtp;
+ ire_t *ire, *sire = NULL;
+ boolean_t compute_label = B_FALSE;
+ tsol_ire_gw_secattr_t *attrp;
+ zoneid_t zoneid;
+
+ if (opt_storage != NULL)
+ opt_storage[IPOPT_OLEN] = 0;
+
+ if ((tsl = crgetlabel(credp)) == NULL)
+ return (0);
+
+ /* always pass multicast */
+ if (CLASSD(dst))
+ return (0);
+
+ if ((dst_rhtp = find_tpc(&dst, IPV4_VERSION, B_FALSE)) == NULL) {
+ DTRACE_PROBE3(tx__tnopt__log__info__labeling__lookupdst__v4,
+ char *, "destination ip(1) not in database (with creds(2))",
+ ipaddr_t, dst, cred_t *, credp);
+ return (EINVAL);
+ }
+
+ zoneid = crgetzoneid(credp);
+
+ switch (dst_rhtp->tpc_tp.host_type) {
+ case UNLABELED:
+ /*
+ * Only add a label if the unlabeled destination is
+ * not broadcast/local/loopback address, that it is
+ * not on the same subnet, and that the next-hop
+ * gateway is labeled.
+ */
+ ire = ire_cache_lookup(dst, zoneid, tsl);
+
+ if (ire != NULL && (ire->ire_type & (IRE_BROADCAST | IRE_LOCAL |
+ IRE_LOOPBACK | IRE_INTERFACE)) != 0) {
+ IRE_REFRELE(ire);
+ TPC_RELE(dst_rhtp);
+ return (0);
+ } else if (ire == NULL) {
+ ire = ire_ftable_lookup(dst, 0, 0, 0, NULL, &sire,
+ zoneid, 0, tsl, (MATCH_IRE_RECURSIVE |
+ MATCH_IRE_DEFAULT | MATCH_IRE_SECATTR));
+ }
+
+ /* no route to destination */
+ if (ire == NULL) {
+ DTRACE_PROBE4(
+ tx__tnopt__log__info__labeling__routedst__v4,
+ char *, "No route to unlabeled dest ip(1)/tpc(2) "
+ "with creds(3).", ipaddr_t, dst, tsol_tpc_t *,
+ dst_rhtp, cred_t *, credp);
+ TPC_RELE(dst_rhtp);
+ return (EINVAL);
+ }
+
+ /*
+ * Prefix IRE from f-table lookup means that the destination
+ * is not directly connected; check the next-hop attributes.
+ */
+ if (sire != NULL) {
+ ASSERT(ire != NULL);
+ IRE_REFRELE(ire);
+ ire = sire;
+ }
+
+ attrp = ire->ire_gw_secattr;
+ if (attrp != NULL && attrp->igsa_rhc != NULL &&
+ attrp->igsa_rhc->rhc_tpc->tpc_tp.host_type != UNLABELED)
+ compute_label = B_TRUE;
+
+ /*
+ * Can talk to unlabeled hosts if
+ * (1) zone's label matches the default label, or
+ * (2) SO_MAC_EXEMPT is on and we dominate the peer's label
+ * (3) SO_MAC_EXEMPT is on and this is the global zone
+ */
+ if (dst_rhtp->tpc_tp.tp_doi != tsl->tsl_doi ||
+ (!blequal(&dst_rhtp->tpc_tp.tp_def_label,
+ &tsl->tsl_label) && (!isexempt ||
+ (zoneid != GLOBAL_ZONEID && !bldominates(&tsl->tsl_label,
+ &dst_rhtp->tpc_tp.tp_def_label))))) {
+ DTRACE_PROBE4(tx__tnopt__log__info__labeling__mac__v4,
+ char *, "unlabeled dest ip(1)/tpc(2) "
+ "non-matching creds(3).", ipaddr_t, dst,
+ tsol_tpc_t *, dst_rhtp, cred_t *, credp);
+ IRE_REFRELE(ire);
+ TPC_RELE(dst_rhtp);
+ return (EACCES);
+ }
+
+ IRE_REFRELE(ire);
+ break;
+
+ case SUN_CIPSO:
+ /*
+ * Can talk to labeled hosts if zone's label is within target's
+ * label range or set.
+ */
+ if (dst_rhtp->tpc_tp.tp_cipso_doi_cipso != tsl->tsl_doi ||
+ (!_blinrange(&tsl->tsl_label,
+ &dst_rhtp->tpc_tp.tp_sl_range_cipso) &&
+ !blinlset(&tsl->tsl_label,
+ dst_rhtp->tpc_tp.tp_sl_set_cipso))) {
+ DTRACE_PROBE4(tx__tnopt__log__info__labeling__mac__v4,
+ char *, "labeled dest ip(1)/tpc(2) "
+ "non-matching creds(3).", ipaddr_t, dst,
+ tsol_tpc_t *, dst_rhtp, cred_t *, credp);
+ TPC_RELE(dst_rhtp);
+ return (EACCES);
+ }
+ compute_label = B_TRUE;
+ break;
+
+ default:
+ TPC_RELE(dst_rhtp);
+ return (EACCES);
+ }
+
+ if (!compute_label) {
+ TPC_RELE(dst_rhtp);
+ return (0);
+ }
+
+ /* compute the CIPSO option */
+ if (dst_rhtp->tpc_tp.host_type != UNLABELED)
+ sec_opt_len = tsol2cipso_tt1(&tsl->tsl_label, opt_storage,
+ tsl->tsl_doi);
+ else
+ sec_opt_len = tsol2cipso_tt1(&dst_rhtp->tpc_tp.tp_def_label,
+ opt_storage, tsl->tsl_doi);
+ TPC_RELE(dst_rhtp);
+
+ if (sec_opt_len == 0) {
+ DTRACE_PROBE4(tx__tnopt__log__error__labeling__lostops__v4,
+ char *,
+ "options lack length for dest ip(1)/tpc(2) with creds(3).",
+ ipaddr_t, dst, tsol_tpc_t *, dst_rhtp, cred_t *, credp);
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+/*
+ * Remove any existing security option (CIPSO) from the given IP
+ * header, move the 'buflen' bytes back to fill the gap, and return the number
+ * of bytes removed (as zero or negative number). Assumes that the headers are
+ * sane.
+ */
+int
+tsol_remove_secopt(ipha_t *ipha, int buflen)
+{
+ int remlen, olen, oval, delta;
+ uchar_t *fptr, *tptr;
+ boolean_t noop_keep;
+
+ remlen = IPH_HDR_LENGTH(ipha) - IP_SIMPLE_HDR_LENGTH;
+ fptr = tptr = (uchar_t *)(ipha + 1);
+ noop_keep = B_TRUE;
+ while (remlen > 0) {
+ oval = fptr[IPOPT_OPTVAL];
+
+ /* terminate on end of list */
+ if (oval == IPOPT_EOL)
+ break;
+
+ /*
+ * Delete any no-ops following a deleted option, at least up
+ * to a 4 octet alignment; copy others.
+ */
+ if (oval == IPOPT_NOP) {
+ if (((fptr - (uchar_t *)ipha) & 3) == 0)
+ noop_keep = B_TRUE;
+ if (noop_keep)
+ *tptr++ = oval;
+ fptr++;
+ remlen--;
+ continue;
+ }
+
+ /* stop on corrupted list; just do nothing. */
+ if (remlen < 2)
+ return (0);
+ olen = fptr[IPOPT_OLEN];
+ if (olen < 2 || olen > remlen)
+ return (0);
+
+ /* skip over security options to delete them */
+ if (oval == IPOPT_COMSEC || oval == IPOPT_SECURITY) {
+ noop_keep = B_FALSE;
+ fptr += olen;
+ remlen -= olen;
+ continue;
+ }
+
+ /* copy the rest */
+ noop_keep = B_TRUE;
+ if (tptr != fptr)
+ ovbcopy(fptr, tptr, olen);
+ fptr += olen;
+ tptr += olen;
+ remlen -= olen;
+ }
+
+ fptr += remlen;
+
+ /* figure how much padding we'll need for header alignment */
+ olen = (tptr - (uchar_t *)ipha) & 3;
+ if (olen > 0) {
+ olen = 4 - olen;
+ /* pad with end-of-list */
+ bzero(tptr, olen);
+ tptr += olen;
+ }
+
+ /* slide back the headers that follow and update the IP header */
+ delta = fptr - tptr;
+ if (delta != 0) {
+ ovbcopy(fptr, tptr, ((uchar_t *)ipha + buflen) - fptr);
+ ipha->ipha_version_and_hdr_length -= delta / 4;
+ }
+ return (-delta);
+}
+
+/*
+ * Insert the option in 'optbuf' into the IP header pointed to by 'ipha', and
+ * move the data following the IP header (up to buflen) to accomodate the new
+ * option. Assumes that up to IP_MAX_OPT_LENGTH bytes are available (in total)
+ * for IP options. Returns the number of bytes actually inserted, or -1 if the
+ * option cannot be inserted. (Note that negative return values are possible
+ * when noops must be compressed, and that only -1 indicates error. Successful
+ * return value is always evenly divisible by 4, by definition.)
+ */
+int
+tsol_prepend_option(uchar_t *optbuf, ipha_t *ipha, int buflen)
+{
+ int remlen, padding, lastpad, totlen;
+ int oval, olen;
+ int delta;
+ uchar_t *optr;
+ uchar_t tempopt[IP_MAX_OPT_LENGTH], *toptr;
+
+ if (optbuf[IPOPT_OPTVAL] == IPOPT_EOL ||
+ optbuf[IPOPT_OPTVAL] == IPOPT_NOP ||
+ optbuf[IPOPT_OLEN] == 0)
+ return (0);
+
+ ASSERT(optbuf[IPOPT_OLEN] >= 2 &&
+ optbuf[IPOPT_OLEN] <= IP_MAX_OPT_LENGTH);
+
+ /* first find the real (unpadded) length of the existing options */
+ remlen = IPH_HDR_LENGTH(ipha) - IP_SIMPLE_HDR_LENGTH;
+ padding = totlen = lastpad = 0;
+ optr = (uchar_t *)(ipha + 1);
+ while (remlen > 0) {
+ oval = optr[IPOPT_OPTVAL];
+
+ /* stop at end of list */
+ if (oval == IPOPT_EOL)
+ break;
+
+ /* skip no-ops, noting that length byte isn't present */
+ if (oval == IPOPT_NOP) {
+ optr++;
+ padding++;
+ lastpad++;
+ totlen++;
+ remlen--;
+ continue;
+ }
+
+ /* give up on a corrupted list; report failure */
+ if (remlen < 2)
+ return (-1);
+ olen = optr[IPOPT_OLEN];
+ if (olen < 2 || olen > remlen)
+ return (-1);
+
+ lastpad = 0;
+ optr += olen;
+ totlen += olen;
+ remlen -= olen;
+ }
+
+ /* completely ignore any trailing padding */
+ totlen -= lastpad;
+ padding -= lastpad;
+
+ /*
+ * If some sort of inter-option alignment was present, try to preserve
+ * that alignment. If alignment pushes us out past the maximum, then
+ * discard it and try to compress to fit. (We just "assume" that any
+ * padding added was attempting to get 32 bit alignment. If that's
+ * wrong, that's just too bad.)
+ */
+ if (padding > 0) {
+ olen = (optbuf[IPOPT_OLEN] + 3) & ~3;
+ if (olen + totlen > IP_MAX_OPT_LENGTH) {
+ totlen -= padding;
+ if (olen + totlen > IP_MAX_OPT_LENGTH)
+ return (-1);
+ padding = 0;
+ }
+ }
+
+ /*
+ * Since we may need to compress or expand the option list, we write to
+ * a temporary buffer and then copy the results back to the IP header.
+ */
+ toptr = tempopt;
+
+ /* compute actual option to insert */
+ olen = optbuf[IPOPT_OLEN];
+ bcopy(optbuf, toptr, olen);
+ toptr += olen;
+ if (padding > 0) {
+ while ((olen & 3) != 0) {
+ *toptr++ = IPOPT_NOP;
+ olen++;
+ }
+ }
+
+ /* copy over the existing options */
+ optr = (uchar_t *)(ipha + 1);
+ while (totlen > 0) {
+ oval = optr[IPOPT_OPTVAL];
+
+ /* totlen doesn't include end-of-list marker */
+ ASSERT(oval != IPOPT_EOL);
+
+ /* handle no-ops; copy if desired, ignore otherwise */
+ if (oval == IPOPT_NOP) {
+ if (padding > 0) {
+ /* note: cannot overflow due to checks above */
+ ASSERT(toptr < tempopt + IP_MAX_OPT_LENGTH);
+ *toptr++ = oval;
+ }
+ optr++;
+ totlen--;
+ continue;
+ }
+
+ /* list cannot be corrupt at this point */
+ ASSERT(totlen >= 2);
+ olen = optr[IPOPT_OLEN];
+ ASSERT(olen >= 2 && olen <= totlen);
+
+ /* cannot run out of room due to tests above */
+ ASSERT(toptr + olen <= tempopt + IP_MAX_OPT_LENGTH);
+
+ bcopy(optr, toptr, olen);
+ optr += olen;
+ toptr += olen;
+ totlen -= olen;
+ }
+
+ /* figure how much padding we'll need for header alignment */
+ olen = (toptr - tempopt) & 3;
+ if (olen > 0) {
+ olen = 4 - olen;
+ ASSERT(toptr + olen <= tempopt + IP_MAX_OPT_LENGTH);
+ /* pad with end-of-list value */
+ bzero(toptr, olen);
+ toptr += olen;
+ }
+
+ /* move the headers as needed and update IP header */
+ olen = (toptr - tempopt) + IP_SIMPLE_HDR_LENGTH;
+ remlen = IPH_HDR_LENGTH(ipha);
+ delta = olen - remlen;
+ if (delta != 0) {
+ ovbcopy((uchar_t *)ipha + remlen, (uchar_t *)ipha + olen,
+ buflen - remlen);
+ ipha->ipha_version_and_hdr_length += delta / 4;
+ }
+
+ /* slap in the new options */
+ bcopy(tempopt, ipha + 1, olen - IP_SIMPLE_HDR_LENGTH);
+
+ return (delta);
+}
+
+/*
+ * tsol_check_label()
+ *
+ * This routine computes the IP label that should be on the packet based on the
+ * connection and destination information. If the label is there, it returns
+ * zero, so the caller knows that the label is syncronized, and further calls
+ * are not required. If the label isn't right, then the right one is inserted.
+ *
+ * The packet's header is clear, before entering IPSec's engine.
+ *
+ * Returns:
+ * 0 Label on packet (was|is now) correct
+ * EACCES The packet failed the remote host accreditation.
+ * ENOMEM Memory allocation failure.
+ * EINVAL Label cannot be computed
+ */
+int
+tsol_check_label(const cred_t *credp, mblk_t **mpp, int *addedp,
+ boolean_t isexempt)
+{
+ mblk_t *mp = *mpp;
+ ipha_t *ipha;
+ uchar_t opt_storage[IP_MAX_OPT_LENGTH];
+ uint_t hlen;
+ uint_t sec_opt_len;
+ uchar_t *optr;
+ int added;
+ int retv;
+
+ if (addedp != NULL)
+ *addedp = 0;
+
+ opt_storage[IPOPT_OPTVAL] = 0;
+
+ ipha = (ipha_t *)mp->b_rptr;
+
+ retv = tsol_compute_label(credp, ipha->ipha_dst, opt_storage, isexempt);
+ if (retv != 0)
+ return (retv);
+
+ optr = (uchar_t *)(ipha + 1);
+ hlen = IPH_HDR_LENGTH(ipha) - IP_SIMPLE_HDR_LENGTH;
+ sec_opt_len = opt_storage[IPOPT_OLEN];
+
+ if (hlen >= sec_opt_len) {
+ /* If no option is supposed to be there, make sure it's not */
+ if (sec_opt_len == 0 && hlen > 0 &&
+ optr[IPOPT_OPTVAL] != IPOPT_COMSEC &&
+ optr[IPOPT_OPTVAL] != IPOPT_SECURITY)
+ return (0);
+ /* if the option is there, it's always first */
+ if (sec_opt_len != 0 &&
+ bcmp(opt_storage, optr, sec_opt_len) == 0)
+ return (0);
+ }
+
+ /*
+ * If there is an option there, then it must be the wrong one; delete.
+ */
+ if (hlen > 0)
+ mp->b_wptr += tsol_remove_secopt(ipha, MBLKL(mp));
+
+ /* Make sure we have room for the worst-case addition */
+ hlen = IPH_HDR_LENGTH(ipha) + opt_storage[IPOPT_OLEN];
+ hlen = (hlen + 3) & ~3;
+ if (hlen > IP_MAX_HDR_LENGTH)
+ hlen = IP_MAX_HDR_LENGTH;
+ hlen -= IPH_HDR_LENGTH(ipha);
+ if (mp->b_wptr + hlen > mp->b_datap->db_lim) {
+ int copylen;
+ mblk_t *new_mp;
+
+ /* allocate enough to be meaningful, but not *too* much */
+ copylen = MBLKL(mp);
+ if (copylen > 256)
+ copylen = 256;
+ new_mp = allocb(hlen + copylen +
+ (mp->b_rptr - mp->b_datap->db_base), BPRI_HI);
+ if (new_mp == NULL)
+ return (ENOMEM);
+ mblk_setcred(new_mp, DB_CRED(mp));
+
+ /* keep the bias */
+ new_mp->b_rptr += mp->b_rptr - mp->b_datap->db_base;
+ new_mp->b_wptr = new_mp->b_rptr + copylen;
+ bcopy(mp->b_rptr, new_mp->b_rptr, copylen);
+ new_mp->b_cont = mp;
+ if ((mp->b_rptr += copylen) >= mp->b_wptr) {
+ new_mp->b_cont = mp->b_cont;
+ freeb(mp);
+ }
+ *mpp = mp = new_mp;
+ ipha = (ipha_t *)mp->b_rptr;
+ }
+
+ added = tsol_prepend_option(opt_storage, ipha, MBLKL(mp));
+ if (added == -1)
+ goto param_prob;
+
+ if (addedp != NULL)
+ *addedp = added;
+
+ ASSERT((mp->b_wptr + added) <= DB_LIM(mp));
+ mp->b_wptr += added;
+
+ return (0);
+
+param_prob:
+ return (EINVAL);
+}
+
+/*
+ * IPv6 HopOpt extension header for the label option layout:
+ * - One octet giving the type of the 'next extension header'
+ * - Header extension length in 8-byte words, not including the
+ * 1st 8 bytes, but including any pad bytes at the end.
+ * Eg. A value of 2 means 16 bytes not including the 1st 8 bytes.
+ * - Followed by TLV encoded IPv6 label option. Option layout is
+ * * One octet, IP6OPT_LS
+ * * One octet option length in bytes of the option data following
+ * the length, but not including any pad bytes at the end.
+ * * Four-octet DOI (IP6LS_DOI_V4)
+ * * One octet suboption, IP6LS_TT_V4
+ * * One octet suboption length in bytes of the suboption
+ * following the suboption length, including the suboption
+ * header length, but not including any pad bytes at the end.
+ * - Pad to make the extension header a multiple of 8 bytes.
+ *
+ * This function returns the contents of 'IPv6 option structure' in the above.
+ * i.e starting from the IP6OPT_LS but not including the pad at the end.
+ * The user must prepend two octets (either padding or next header / length)
+ * and append padding out to the next 8 octet boundary.
+ */
+int
+tsol_compute_label_v6(const cred_t *credp, const in6_addr_t *dst,
+ uchar_t *opt_storage, boolean_t isexempt)
+{
+ tsol_tpc_t *dst_rhtp;
+ ts_label_t *tsl;
+ uint_t sec_opt_len;
+ uint32_t doi;
+ zoneid_t zoneid;
+ ire_t *ire, *sire;
+ tsol_ire_gw_secattr_t *attrp;
+ boolean_t compute_label;
+
+ if (ip6opt_ls == 0)
+ return (EINVAL);
+
+ if (opt_storage != NULL)
+ opt_storage[IPOPT_OLEN] = 0;
+
+ if ((tsl = crgetlabel(credp)) == NULL)
+ return (0);
+
+ /* Always pass multicast */
+ if (IN6_IS_ADDR_MULTICAST(dst))
+ return (0);
+
+ if ((dst_rhtp = find_tpc(dst, IPV6_VERSION, B_FALSE)) == NULL) {
+ DTRACE_PROBE3(tx__tnopt__log__info__labeling__lookupdst__v6,
+ char *, "destination ip6(1) not in database with creds(2)",
+ in6_addr_t *, dst, cred_t *, credp);
+ return (EINVAL);
+ }
+
+ zoneid = crgetzoneid(credp);
+
+ /*
+ * Fill in a V6 label. If a new format is added here, make certain
+ * that the maximum size of this label is reflected in sys/tsol/tnet.h
+ * as TSOL_MAX_IPV6_OPTION.
+ */
+ compute_label = B_FALSE;
+ switch (dst_rhtp->tpc_tp.host_type) {
+ case UNLABELED:
+ /*
+ * Only add a label if the unlabeled destination is
+ * not local or loopback address, that it is
+ * not on the same subnet, and that the next-hop
+ * gateway is labeled.
+ */
+ sire = NULL;
+ ire = ire_cache_lookup_v6(dst, zoneid, tsl);
+
+ if (ire != NULL && (ire->ire_type & (IRE_LOCAL |
+ IRE_LOOPBACK | IRE_INTERFACE)) != 0) {
+ IRE_REFRELE(ire);
+ TPC_RELE(dst_rhtp);
+ return (0);
+ } else if (ire == NULL) {
+ ire = ire_ftable_lookup_v6(dst, NULL, NULL, 0, NULL,
+ &sire, zoneid, 0, tsl, (MATCH_IRE_RECURSIVE |
+ MATCH_IRE_DEFAULT | MATCH_IRE_SECATTR));
+ }
+
+ /* no route to destination */
+ if (ire == NULL) {
+ DTRACE_PROBE4(
+ tx__tnopt__log__info__labeling__routedst__v6,
+ char *, "No route to unlabeled dest ip6(1)/tpc(2) "
+ "with creds(3).", in6_addr_t *, dst, tsol_tpc_t *,
+ dst_rhtp, cred_t *, credp);
+ TPC_RELE(dst_rhtp);
+ return (EINVAL);
+ }
+
+ /*
+ * Prefix IRE from f-table lookup means that the destination
+ * is not directly connected; check the next-hop attributes.
+ */
+ if (sire != NULL) {
+ ASSERT(ire != NULL);
+ IRE_REFRELE(ire);
+ ire = sire;
+ }
+
+ attrp = ire->ire_gw_secattr;
+ if (attrp != NULL && attrp->igsa_rhc != NULL &&
+ attrp->igsa_rhc->rhc_tpc->tpc_tp.host_type != UNLABELED)
+ compute_label = B_TRUE;
+
+ if (dst_rhtp->tpc_tp.tp_doi != tsl->tsl_doi ||
+ (!blequal(&dst_rhtp->tpc_tp.tp_def_label,
+ &tsl->tsl_label) && (!isexempt ||
+ (zoneid != GLOBAL_ZONEID && !bldominates(&tsl->tsl_label,
+ &dst_rhtp->tpc_tp.tp_def_label))))) {
+ DTRACE_PROBE4(tx__tnopt__log__info__labeling__mac__v6,
+ char *, "unlabeled dest ip6(1)/tpc(2) "
+ "non-matching creds(3)", in6_addr_t *, dst,
+ tsol_tpc_t *, dst_rhtp, cred_t *, credp);
+ IRE_REFRELE(ire);
+ TPC_RELE(dst_rhtp);
+ return (EACCES);
+ }
+
+ IRE_REFRELE(ire);
+ break;
+
+ case SUN_CIPSO:
+ if (dst_rhtp->tpc_tp.tp_cipso_doi_cipso != tsl->tsl_doi ||
+ (!_blinrange(&tsl->tsl_label,
+ &dst_rhtp->tpc_tp.tp_sl_range_cipso) &&
+ !blinlset(&tsl->tsl_label,
+ dst_rhtp->tpc_tp.tp_sl_set_cipso))) {
+ DTRACE_PROBE4(tx__tnopt__log__info__labeling__mac__v6,
+ char *,
+ "labeled dest ip6(1)/tpc(2) non-matching creds(3).",
+ in6_addr_t *, dst, tsol_tpc_t *, dst_rhtp,
+ cred_t *, credp);
+ TPC_RELE(dst_rhtp);
+ return (EACCES);
+ }
+ compute_label = B_TRUE;
+ break;
+
+ default:
+ TPC_RELE(dst_rhtp);
+ return (EACCES);
+ }
+
+ if (!compute_label) {
+ TPC_RELE(dst_rhtp);
+ return (0);
+ }
+
+ /* compute the CIPSO option */
+ if (opt_storage != NULL)
+ opt_storage += 8;
+ if (dst_rhtp->tpc_tp.host_type != UNLABELED) {
+ sec_opt_len = tsol2cipso_tt1(&tsl->tsl_label, opt_storage,
+ tsl->tsl_doi);
+ } else {
+ sec_opt_len = tsol2cipso_tt1(&dst_rhtp->tpc_tp.tp_def_label,
+ opt_storage, tsl->tsl_doi);
+ }
+ TPC_RELE(dst_rhtp);
+
+ if (sec_opt_len == 0) {
+ DTRACE_PROBE4(tx__tnopt__log__error__labeling__lostops__v6,
+ char *,
+ "options lack length for dest ip6(1)/tpc(2) with creds(3).",
+ in6_addr_t *, dst, tsol_tpc_t *, dst_rhtp, cred_t *, credp);
+ return (EINVAL);
+ }
+
+ if (opt_storage == NULL)
+ return (0);
+
+ if (sec_opt_len < IP_MAX_OPT_LENGTH)
+ opt_storage[sec_opt_len] = IPOPT_EOL;
+
+ /*
+ * Just in case the option length is odd, round it up to the next even
+ * multiple. The IPv6 option definition doesn't like odd numbers for
+ * some reason.
+ *
+ * Length in the overall option header (IP6OPT_LS) does not include the
+ * option header itself, but the length in the suboption does include
+ * the suboption header. Thus, when there's just one suboption, the
+ * length in the option header is the suboption length plus 4 (for the
+ * DOI value).
+ */
+ opt_storage[-2] = IP6LS_TT_V4;
+ opt_storage[-1] = (sec_opt_len + 2 + 1) & ~1;
+ opt_storage[-8] = ip6opt_ls;
+ opt_storage[-7] = opt_storage[-1] + 4;
+ doi = htons(IP6LS_DOI_V4);
+ bcopy(&doi, opt_storage - 6, 4);
+
+ return (0);
+}
+
+/*
+ * Locate the start of the IP6OPT_LS label option and return it.
+ * Also return the start of the next non-pad option in after_secoptp.
+ * Usually the label option is the first option at least when packets
+ * are generated, but for generality we don't assume that on received packets.
+ */
+uchar_t *
+tsol_find_secopt_v6(
+ const uchar_t *ip6hbh, /* Start of the hop-by-hop extension header */
+ uint_t hbhlen, /* Length of the hop-by-hop extension header */
+ uchar_t **after_secoptp, /* Non-pad option following the label option */
+ boolean_t *hbh_needed) /* Is hop-by-hop hdr needed w/o label */
+{
+ uint_t optlen;
+ uint_t optused;
+ const uchar_t *optptr;
+ uchar_t opt_type;
+ const uchar_t *secopt = NULL;
+
+ *hbh_needed = B_FALSE;
+ *after_secoptp = NULL;
+ optlen = hbhlen - 2;
+ optptr = ip6hbh + 2;
+ while (optlen != 0) {
+ opt_type = *optptr;
+ if (opt_type == IP6OPT_PAD1) {
+ optptr++;
+ optlen--;
+ continue;
+ }
+ if (optlen == 1)
+ break;
+ optused = 2 + optptr[1];
+ if (optused > optlen)
+ break;
+ /*
+ * if we get here, ip6opt_ls can
+ * not be 0 because it will always
+ * match the IP6OPT_PAD1 above.
+ * Therefore ip6opt_ls == 0 forces
+ * this test to always fail here.
+ */
+ if (opt_type == ip6opt_ls)
+ secopt = optptr;
+ else switch (opt_type) {
+ case IP6OPT_PADN:
+ break;
+ default:
+ /*
+ * There is at least 1 option other than
+ * the label option. So the hop-by-hop header is needed
+ */
+ *hbh_needed = B_TRUE;
+ if (secopt != NULL) {
+ *after_secoptp = (uchar_t *)optptr;
+ return ((uchar_t *)secopt);
+ }
+ break;
+ }
+ optlen -= optused;
+ optptr += optused;
+ }
+ return ((uchar_t *)secopt);
+}
+
+/*
+ * Remove the label option from the hop-by-hop options header if it exists.
+ * 'buflen' is the total length of the packet typically b_wptr - b_rptr.
+ * Header and data following the label option that is deleted are copied
+ * (i.e. slid backward) to the right position.
+ */
+int
+tsol_remove_secopt_v6(ip6_t *ip6h, int buflen)
+{
+ uchar_t *ip6hbh; /* hop-by-hop header */
+ uint_t hbhlen; /* hop-by-hop extension header length */
+ uchar_t *secopt = NULL;
+ uchar_t *after_secopt;
+ uint_t pad;
+ uint_t delta;
+ boolean_t hbh_needed;
+
+ /*
+ * hop-by-hop extension header must appear first, if it does not
+ * exist, there is no label option.
+ */
+ if (ip6h->ip6_nxt != IPPROTO_HOPOPTS)
+ return (0);
+
+ ip6hbh = (uchar_t *)&ip6h[1];
+ hbhlen = (ip6hbh[1] + 1) << 3;
+ /*
+ * Locate the start of the label option if it exists and the end
+ * of the label option including pads if any.
+ */
+ secopt = tsol_find_secopt_v6(ip6hbh, hbhlen, &after_secopt,
+ &hbh_needed);
+ if (secopt == NULL)
+ return (0);
+ if (!hbh_needed) {
+ uchar_t next_hdr;
+ /*
+ * The label option was the only option in the hop-by-hop
+ * header. We don't need the hop-by-hop header itself any
+ * longer.
+ */
+ next_hdr = ip6hbh[0];
+ ovbcopy(ip6hbh + hbhlen, ip6hbh,
+ buflen - (IPV6_HDR_LEN + hbhlen));
+ ip6h->ip6_plen -= hbhlen;
+ ip6h->ip6_nxt = next_hdr;
+ return (hbhlen);
+ }
+
+ if (after_secopt == NULL) {
+ /* There is no option following the label option */
+ after_secopt = ip6hbh + hbhlen;
+ }
+
+ /*
+ * After deleting the label option, we need to slide the headers
+ * and data back, while still maintaining the same alignment (module 8)
+ * for the other options. So we slide the headers and data back only
+ * by an integral multiple of 8 bytes, and fill the remaining bytes
+ * with pads.
+ */
+ delta = after_secopt - secopt;
+ pad = delta % 8;
+ if (pad == 1) {
+ secopt[0] = IP6OPT_PAD1;
+ } else if (pad > 1) {
+ secopt[0] = IP6OPT_PADN;
+ secopt[1] = pad - 2;
+ if (pad > 2)
+ bzero(&secopt[2], pad - 2);
+ }
+ secopt += pad;
+ delta -= pad;
+ ovbcopy(after_secopt, secopt,
+ (uchar_t *)ip6h + buflen - after_secopt);
+ ip6hbh[1] -= delta/8;
+ ip6h->ip6_plen -= delta;
+
+ return (delta);
+}
+
+/*
+ * 'optbuf' contains a CIPSO label embedded in an IPv6 hop-by-hop option,
+ * starting with the IP6OPT_LS option type. The format of this hop-by-hop
+ * option is described in the block comment above tsol_compute_label_v6.
+ * This function prepends this hop-by-hop option before any other hop-by-hop
+ * options in the hop-by-hop header if one already exists, else a new
+ * hop-by-hop header is created and stuffed into the packet following
+ * the IPv6 header. 'buflen' is the total length of the packet i.e.
+ * b_wptr - b_rptr. The caller ensures that there is enough space for the
+ * extra option being added. Header and data following the position where
+ * the label option is inserted are copied (i.e. slid forward) to the right
+ * position.
+ */
+int
+tsol_prepend_option_v6(uchar_t *optbuf, ip6_t *ip6h, int buflen)
+{
+ /*
+ * rawlen is the length of the label option in bytes, not including
+ * any pads, starting from the IP6OPT_LS (option type) byte.
+ */
+ uint_t rawlen;
+
+ uint_t optlen; /* rawlen rounded to an 8 byte multiple */
+ uchar_t *ip6hbh; /* start of the hop-by-hop extension header */
+ uint_t hbhlen; /* Length of the hop-by-hop extension header */
+ uint_t pad_len;
+ uchar_t *pad_position;
+ int delta; /* Actual number of bytes inserted */
+
+ rawlen = optbuf[1] + 2; /* Add 2 for the option type, option length */
+ ip6hbh = (uchar_t *)&ip6h[1];
+ if (ip6h->ip6_nxt == IPPROTO_HOPOPTS) {
+ /*
+ * There is a hop-by-hop header present already. In order to
+ * preserve the alignment of the other options at the existing
+ * value (modulo 8) we need to pad the label option to a
+ * multiple of 8 bytes before prepending it to the other
+ * options. Slide the extension headers and data forward to
+ * accomodate the label option at the start of the hop-by-hop
+ * header
+ */
+ delta = optlen = (rawlen + 7) & ~7;
+ pad_len = optlen - rawlen;
+ pad_position = ip6hbh + 2 + rawlen;
+ ovbcopy(ip6hbh + 2, ip6hbh + 2 + optlen,
+ buflen - (IPV6_HDR_LEN + 2));
+ /*
+ * Bump up the hop-by-hop extension header length by
+ * the number of 8-byte words added
+ */
+ optlen >>= 3;
+ if (ip6hbh[1] + optlen > 255)
+ return (-1);
+ ip6hbh[1] += optlen;
+ } else {
+ /*
+ * There is no hop-by-hop header in the packet. Construct a
+ * new Hop-by-hop extension header (a multiple of 8 bytes).
+ * Slide any other extension headers and data forward to
+ * accomodate this hop-by-hop header
+ */
+ delta = hbhlen = (2 + rawlen + 7) & ~7; /* +2 for nxthdr, len */
+ pad_len = hbhlen - (2 + rawlen);
+ pad_position = ip6hbh + 2 + rawlen;
+ ovbcopy(ip6hbh, ip6hbh + hbhlen, buflen - IPV6_HDR_LEN);
+ ip6hbh[0] = ip6h->ip6_nxt;
+ /*
+ * hop-by-hop extension header length in 8-byte words, not
+ * including the 1st 8 bytes of the hop-by-hop header.
+ */
+ ip6hbh[1] = (hbhlen >> 3) - 1;
+ ip6h->ip6_nxt = IPPROTO_HOPOPTS;
+ }
+ /*
+ * Copy the label option into the hop-by-hop header and insert any
+ * needed pads
+ */
+ bcopy(optbuf, ip6hbh + 2, rawlen);
+ if (pad_len == 1) {
+ pad_position[0] = IP6OPT_PAD1;
+ } else if (pad_len > 1) {
+ pad_position[0] = IP6OPT_PADN;
+ pad_position[1] = pad_len - 2;
+ if (pad_len > 2)
+ bzero(pad_position + 2, pad_len - 2);
+ }
+ ip6h->ip6_plen += delta;
+ return (delta);
+}
+
+/*
+ * tsol_check_label_v6()
+ *
+ * This routine computes the IP label that should be on the packet based on the
+ * connection and destination information. It's called only by the IP
+ * forwarding logic, because all internal modules atop IP know how to generate
+ * their own labels.
+ *
+ * Returns:
+ * 0 Label on packet was already correct
+ * EACCESS The packet failed the remote host accreditation.
+ * ENOMEM Memory allocation failure.
+ */
+int
+tsol_check_label_v6(const cred_t *credp, mblk_t **mpp, int *addedp,
+ boolean_t isexempt)
+{
+ mblk_t *mp = *mpp;
+ ip6_t *ip6h;
+ /*
+ * Label option length is limited to IP_MAX_OPT_LENGTH for
+ * symmetry with IPv4. Can be relaxed if needed
+ */
+ uchar_t opt_storage[TSOL_MAX_IPV6_OPTION];
+ uint_t hlen;
+ uint_t sec_opt_len; /* label option length not including type, len */
+ int added;
+ int retv;
+ uchar_t *after_secopt;
+ uchar_t *secopt = NULL;
+ uchar_t *ip6hbh;
+ uint_t hbhlen;
+ boolean_t hbh_needed;
+
+ if (addedp != NULL)
+ *addedp = 0;
+
+ ip6h = (ip6_t *)mp->b_rptr;
+ retv = tsol_compute_label_v6(credp, &ip6h->ip6_dst, opt_storage,
+ isexempt);
+ if (retv != 0)
+ return (retv);
+
+ sec_opt_len = opt_storage[1];
+
+ if (ip6h->ip6_nxt == IPPROTO_HOPOPTS) {
+ ip6hbh = (uchar_t *)&ip6h[1];
+ hbhlen = (ip6hbh[1] + 1) << 3;
+ secopt = tsol_find_secopt_v6(ip6hbh, hbhlen, &after_secopt,
+ &hbh_needed);
+ }
+
+ if (sec_opt_len == 0 && secopt == NULL) {
+ /*
+ * The packet is not supposed to have a label, and it
+ * does not have one currently
+ */
+ return (0);
+ }
+ if (secopt != NULL && sec_opt_len != 0 &&
+ (bcmp(opt_storage, secopt, sec_opt_len + 2) == 0)) {
+ /* The packet has the correct label already */
+ return (0);
+ }
+
+ /*
+ * If there is an option there, then it must be the wrong one; delete.
+ */
+ if (secopt != NULL)
+ mp->b_wptr += tsol_remove_secopt_v6(ip6h, MBLKL(mp));
+
+ /*
+ * Make sure we have room for the worst-case addition. Add 2 bytes for
+ * the hop-by-hop ext header's next header and length fields. Add
+ * another 2 bytes for the label option type, len and then round
+ * up to the next 8-byte multiple.
+ */
+ hlen = (4 + sec_opt_len + 7) & ~7;
+ if (mp->b_wptr + hlen > mp->b_datap->db_lim) {
+ int copylen;
+ mblk_t *new_mp;
+ uint16_t hdr_len;
+
+ hdr_len = ip_hdr_length_v6(mp, ip6h);
+ /*
+ * Allocate enough to be meaningful, but not *too* much.
+ * Also all the IPv6 extension headers must be in the same mblk
+ */
+ copylen = MBLKL(mp);
+ if (copylen > 256)
+ copylen = 256;
+ if (copylen < hdr_len)
+ copylen = hdr_len;
+ new_mp = allocb(hlen + copylen +
+ (mp->b_rptr - mp->b_datap->db_base), BPRI_HI);
+ if (new_mp == NULL)
+ return (ENOMEM);
+
+ /* keep the bias */
+ new_mp->b_rptr += mp->b_rptr - mp->b_datap->db_base;
+ new_mp->b_wptr = new_mp->b_rptr + copylen;
+ bcopy(mp->b_rptr, new_mp->b_rptr, copylen);
+ new_mp->b_cont = mp;
+ if ((mp->b_rptr += copylen) >= mp->b_wptr) {
+ new_mp->b_cont = mp->b_cont;
+ freeb(mp);
+ }
+ *mpp = mp = new_mp;
+ ip6h = (ip6_t *)mp->b_rptr;
+ }
+
+ added = tsol_prepend_option_v6(opt_storage, ip6h, MBLKL(mp));
+ if (added == -1)
+ goto param_prob;
+
+ if (addedp != NULL)
+ *addedp = added;
+
+ ASSERT(mp->b_wptr + added <= DB_LIM(mp));
+ mp->b_wptr += added;
+
+ return (0);
+
+param_prob:
+ return (EINVAL);
+}
+
+/*
+ * Update the given IPv6 "sticky options" structure to contain the provided
+ * label, which is encoded as an IPv6 option. Existing label is removed if
+ * necessary, and storage is allocated/freed/resized.
+ *
+ * Returns 0 on success, errno on failure.
+ */
+int
+tsol_update_sticky(ip6_pkt_t *ipp, uint_t *labellen, const uchar_t *labelopt)
+{
+ int rawlen, optlen, newlen;
+ uchar_t *newopts;
+
+ /*
+ * rawlen is the size of the IPv6 label to be inserted from labelopt.
+ * optlen is the total length of that option, including any necessary
+ * headers and padding. newlen is the new size of the total hop-by-hop
+ * options buffer, including user options.
+ */
+ if ((rawlen = labelopt[1]) != 0) {
+ rawlen += 2; /* add in header size */
+ optlen = (2 + rawlen + 7) & ~7;
+ } else {
+ optlen = 0;
+ }
+ newlen = ipp->ipp_hopoptslen + optlen - *labellen;
+ if (optlen > *labellen) {
+ if (newlen > IP6_MAX_OPT_LENGTH)
+ return (EHOSTUNREACH);
+ /* If the label is bigger than last time, then reallocate */
+ newopts = kmem_alloc(newlen, KM_NOSLEEP);
+ if (newopts == NULL)
+ return (ENOMEM);
+ /*
+ * If the user has hop-by-hop stickyoptions set, then copy his
+ * options in after the security label.
+ */
+ if (ipp->ipp_hopoptslen > *labellen) {
+ bcopy(ipp->ipp_hopopts + *labellen, newopts + optlen,
+ ipp->ipp_hopoptslen - *labellen);
+ /*
+ * Stomp out any header gunk here - this was the
+ * previous next-header and option length field.
+ */
+ newopts[optlen] = IP6OPT_PADN;
+ newopts[optlen + 1] = 0;
+ }
+ if (ipp->ipp_hopopts != NULL)
+ kmem_free(ipp->ipp_hopopts, ipp->ipp_hopoptslen);
+ ipp->ipp_hopopts = (ip6_hbh_t *)newopts;
+ } else if (optlen < *labellen) {
+ /* If the label got smaller, then adjust downward. */
+ if (newlen == 0 && ipp->ipp_hopopts != NULL) {
+ kmem_free(ipp->ipp_hopopts, ipp->ipp_hopoptslen);
+ ipp->ipp_hopopts = NULL;
+ ipp->ipp_fields &= ~IPPF_HOPOPTS;
+ }
+ /* If the user still has options, move those back. */
+ if (ipp->ipp_hopoptslen > *labellen) {
+ ovbcopy(ipp->ipp_hopopts + *labellen,
+ ipp->ipp_hopopts + optlen,
+ ipp->ipp_hopoptslen - *labellen);
+ }
+ }
+ ipp->ipp_hopoptslen = newlen;
+ *labellen = optlen;
+
+ newopts = (uchar_t *)ipp->ipp_hopopts;
+
+ /* If there are any options, then fix up reported length */
+ if (newlen > 0) {
+ newopts[1] = (newlen + 7) / 8 - 1;
+ ipp->ipp_fields |= IPPF_HOPOPTS;
+ }
+
+ /* If there's a label, then insert it now */
+ if (optlen > 0) {
+ /* skip next-header and length fields */
+ newopts += 2;
+ bcopy(labelopt, newopts, rawlen);
+ newopts += rawlen;
+ /* make sure padding comes out right */
+ optlen -= 2 + rawlen;
+ if (optlen == 1) {
+ newopts[0] = IP6OPT_PAD1;
+ } else if (optlen > 1) {
+ newopts[0] = IP6OPT_PADN;
+ optlen -= 2;
+ newopts[1] = optlen;
+ if (optlen > 0)
+ bzero(newopts + 2, optlen);
+ }
+ }
+ return (0);
+}
+
+int
+tsol_update_options(uchar_t **opts, uint_t *totlen, uint_t *labellen,
+ const uchar_t *labelopt)
+{
+ int optlen, newlen;
+ uchar_t *newopts;
+
+ optlen = (labelopt[IPOPT_OLEN] + 3) & ~3;
+ newlen = *totlen + optlen - *labellen;
+ if (optlen > *labellen) {
+ if (newlen > IP_MAX_OPT_LENGTH)
+ return (EHOSTUNREACH);
+ newopts = (uchar_t *)mi_alloc(newlen, BPRI_HI);
+ if (newopts == NULL)
+ return (ENOMEM);
+ if (*totlen > *labellen) {
+ bcopy(*opts + *labellen, newopts + optlen,
+ *totlen - *labellen);
+ }
+ if (*opts != NULL)
+ mi_free((char *)*opts);
+ *opts = newopts;
+ } else if (optlen < *labellen) {
+ if (newlen == 0 && *opts != NULL) {
+ mi_free((char *)*opts);
+ *opts = NULL;
+ }
+ if (*totlen > *labellen) {
+ ovbcopy(*opts + *labellen, *opts + optlen,
+ *totlen - *labellen);
+ }
+ }
+ *totlen = newlen;
+ *labellen = optlen;
+ if (optlen > 0) {
+ newopts = *opts;
+ bcopy(labelopt, newopts, optlen);
+ /* check if there are user-supplied options that follow */
+ if (optlen < newlen) {
+ /* compute amount of embedded alignment needed */
+ optlen -= newopts[IPOPT_OLEN];
+ newopts += newopts[IPOPT_OLEN];
+ while (--optlen >= 0)
+ *newopts++ = IPOPT_NOP;
+ } else if (optlen != newopts[IPOPT_OLEN]) {
+ /*
+ * The label option is the only option and it is
+ * not a multiple of 4 bytes.
+ */
+ optlen -= newopts[IPOPT_OLEN];
+ newopts += newopts[IPOPT_OLEN];
+ while (--optlen >= 0)
+ *newopts++ = IPOPT_EOL;
+ }
+ }
+ return (0);
+}
+
+/*
+ * This does the bulk of the processing for setting IPPROTO_IP {T_,}IP_OPTIONS.
+ */
+boolean_t
+tsol_option_set(uchar_t **opts, uint_t *optlen, uint_t labellen,
+ const uchar_t *useropts, uint_t userlen)
+{
+ int newlen;
+ uchar_t *newopts;
+
+ newlen = userlen + labellen;
+ if (newlen > *optlen) {
+ /* need more room */
+ newopts = (uchar_t *)mi_alloc(newlen, BPRI_HI);
+ if (newopts == NULL)
+ return (ENOMEM);
+ /*
+ * The supplied *opts can't be NULL in this case,
+ * since there's an existing label.
+ */
+ if (labellen > 0)
+ bcopy(*opts, newopts, labellen);
+ if (*opts != NULL)
+ mi_free((char *)*opts);
+ *opts = newopts;
+ }
+
+ if (newlen == 0) {
+ /* special case -- no remaining IP options at all */
+ if (*opts != NULL) {
+ mi_free((char *)*opts);
+ *opts = NULL;
+ }
+ } else if (userlen > 0) {
+ /* merge in the user's options */
+ newopts = *opts;
+ if (labellen > 0) {
+ int extra = labellen - newopts[IPOPT_OLEN];
+
+ newopts += newopts[IPOPT_OLEN];
+ while (--extra >= 0)
+ *newopts++ = IPOPT_NOP;
+ }
+ bcopy(useropts, newopts, userlen);
+ }
+
+ *optlen = newlen;
+ return (0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/inet/ip/tnet.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,2025 @@
+/*
+ * 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/stream.h>
+#include <sys/strsubr.h>
+#include <sys/stropts.h>
+#include <sys/sunddi.h>
+#include <sys/cred.h>
+#include <sys/debug.h>
+#include <sys/kmem.h>
+#include <sys/errno.h>
+#include <sys/disp.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/tcp.h>
+#include <inet/common.h>
+#include <inet/ipclassifier.h>
+#include <inet/ip.h>
+#include <inet/mib2.h>
+#include <inet/nd.h>
+#include <inet/tcp.h>
+#include <inet/ip_rts.h>
+#include <inet/ip_ire.h>
+#include <inet/ip_if.h>
+#include <sys/modhash.h>
+
+#include <sys/tsol/label.h>
+#include <sys/tsol/label_macro.h>
+#include <sys/tsol/tnet.h>
+#include <sys/tsol/tndb.h>
+#include <sys/strsun.h>
+
+/* tunable for strict error-reply behavior (TCP RST and ICMP Unreachable) */
+int tsol_strict_error;
+
+/*
+ * Some notes on the Trusted Solaris IRE gateway security attributes:
+ *
+ * When running in Trusted mode, the routing subsystem determines whether or
+ * not a packet can be delivered to an off-link host (not directly reachable
+ * through an interface) based on the accreditation checks of the packet's
+ * security attributes against those associated with the next-hop gateway.
+ *
+ * The next-hop gateway's security attributes can be derived from two sources
+ * (in order of preference): route-related and the host database. A Trusted
+ * system must be configured with at least the host database containing an
+ * entry for the next-hop gateway, or otherwise no accreditation checks can
+ * be performed, which may result in the inability to send packets to any
+ * off-link destination host.
+ *
+ * The major differences between the two sources are the number and type of
+ * security attributes used for accreditation checks. A host database entry
+ * can contain at most one set of security attributes, specific only to the
+ * next-hop gateway. On contrast, route-related security attributes are made
+ * up of a collection of security attributes for the distant networks, and
+ * are grouped together per next-hop gateway used to reach those networks.
+ * This is the preferred method, and the routing subsystem will fallback to
+ * the host database entry only if there are no route-related attributes
+ * associated with the next-hop gateway.
+ *
+ * In Trusted mode, all of the IRE entries (except LOCAL/LOOPBACK/BROADCAST/
+ * INTERFACE type) are initialized to contain a placeholder to store this
+ * information. The ire_gw_secattr structure gets allocated, initialized
+ * and associated with the IRE during the time of the IRE creation. The
+ * initialization process also includes resolving the host database entry
+ * of the next-hop gateway for fallback purposes. It does not include any
+ * route-related attribute setup, as that process comes separately as part
+ * of the route requests (add/change) made to the routing subsystem.
+ *
+ * The underlying logic which involves associating IREs with the gateway
+ * security attributes are represented by the following data structures:
+ *
+ * tsol_gcdb_t, or "gcdb"
+ *
+ * - This is a system-wide collection of records containing the
+ * currently used route-related security attributes, which are fed
+ * through the routing socket interface, e.g. "route add/change".
+ *
+ * tsol_gc_t, or "gc"
+ *
+ * - This is the gateway credential structure, and it provides for the
+ * only mechanism to access the contents of gcdb. More than one gc
+ * entries may refer to the same gcdb record. gc's in the system are
+ * grouped according to the next-hop gateway address.
+ *
+ * tsol_gcgrp_t, or "gcgrp"
+ *
+ * - Group of gateway credentials, and is unique per next-hop gateway
+ * address. When the group is not empty, i.e. when gcgrp_count is
+ * greater than zero, it contains one or more gc's, each pointing to
+ * a gcdb record which indicates the gateway security attributes
+ * associated with the next-hop gateway.
+ *
+ * The fields of the tsol_ire_gw_secattr_t used from within the IRE are:
+ *
+ * igsa_lock
+ *
+ * - Lock that protects all fields within tsol_ire_gw_secattr_t.
+ *
+ * igsa_rhc
+ *
+ * - Remote host cache database entry of next-hop gateway. This is
+ * used in the case when there are no route-related attributes
+ * configured for the IRE.
+ *
+ * igsa_gc
+ *
+ * - A set of route-related attributes that only get set for prefix
+ * IREs. If this is non-NULL, the prefix IRE has been associated
+ * with a set of gateway security attributes by way of route add/
+ * change functionality. This field stays NULL for IRE_CACHEs.
+ *
+ * igsa_gcgrp
+ *
+ * - Group of gc's which only gets set for IRE_CACHEs. Each of the gc
+ * points to a gcdb record that contains the security attributes
+ * used to perform the credential checks of the packet which uses
+ * the IRE. If the group is not empty, the list of gc's can be
+ * traversed starting at gcgrp_head. This field stays NULL for
+ * prefix IREs.
+ */
+
+static kmem_cache_t *ire_gw_secattr_cache;
+
+#define GCDB_HASH_SIZE 101
+#define GCGRP_HASH_SIZE 101
+
+#define GCDB_REFRELE(p) { \
+ mutex_enter(&gcdb_lock); \
+ ASSERT((p)->gcdb_refcnt > 0); \
+ if (--((p)->gcdb_refcnt) == 0) \
+ gcdb_inactive(p); \
+ ASSERT(MUTEX_HELD(&gcdb_lock)); \
+ mutex_exit(&gcdb_lock); \
+}
+
+static int gcdb_hash_size = GCDB_HASH_SIZE;
+static int gcgrp_hash_size = GCGRP_HASH_SIZE;
+static mod_hash_t *gcdb_hash;
+static mod_hash_t *gcgrp4_hash;
+static mod_hash_t *gcgrp6_hash;
+
+static kmutex_t gcdb_lock;
+kmutex_t gcgrp_lock;
+
+static uint_t gcdb_hash_by_secattr(void *, mod_hash_key_t);
+static int gcdb_hash_cmp(mod_hash_key_t, mod_hash_key_t);
+static tsol_gcdb_t *gcdb_lookup(struct rtsa_s *, boolean_t);
+static void gcdb_inactive(tsol_gcdb_t *);
+
+static uint_t gcgrp_hash_by_addr(void *, mod_hash_key_t);
+static int gcgrp_hash_cmp(mod_hash_key_t, mod_hash_key_t);
+
+static int ire_gw_secattr_constructor(void *, void *, int);
+static void ire_gw_secattr_destructor(void *, void *);
+
+void
+tnet_init(void)
+{
+ ire_gw_secattr_cache = kmem_cache_create("ire_gw_secattr_cache",
+ sizeof (tsol_ire_gw_secattr_t), 64, ire_gw_secattr_constructor,
+ ire_gw_secattr_destructor, NULL, NULL, NULL, 0);
+
+ gcdb_hash = mod_hash_create_extended("gcdb_hash",
+ gcdb_hash_size, mod_hash_null_keydtor, mod_hash_null_valdtor,
+ gcdb_hash_by_secattr, NULL, gcdb_hash_cmp, KM_SLEEP);
+
+ gcgrp4_hash = mod_hash_create_extended("gcgrp4_hash",
+ gcgrp_hash_size, mod_hash_null_keydtor, mod_hash_null_valdtor,
+ gcgrp_hash_by_addr, NULL, gcgrp_hash_cmp, KM_SLEEP);
+
+ gcgrp6_hash = mod_hash_create_extended("gcgrp6_hash",
+ gcgrp_hash_size, mod_hash_null_keydtor, mod_hash_null_valdtor,
+ gcgrp_hash_by_addr, NULL, gcgrp_hash_cmp, KM_SLEEP);
+
+ mutex_init(&gcdb_lock, NULL, MUTEX_DEFAULT, NULL);
+ mutex_init(&gcgrp_lock, NULL, MUTEX_DEFAULT, NULL);
+}
+
+void
+tnet_fini(void)
+{
+ kmem_cache_destroy(ire_gw_secattr_cache);
+ mod_hash_destroy_hash(gcdb_hash);
+ mod_hash_destroy_hash(gcgrp4_hash);
+ mod_hash_destroy_hash(gcgrp6_hash);
+ mutex_destroy(&gcdb_lock);
+ mutex_destroy(&gcgrp_lock);
+}
+
+/* ARGSUSED */
+static int
+ire_gw_secattr_constructor(void *buf, void *cdrarg, int kmflags)
+{
+ tsol_ire_gw_secattr_t *attrp = buf;
+
+ mutex_init(&attrp->igsa_lock, NULL, MUTEX_DEFAULT, NULL);
+
+ attrp->igsa_rhc = NULL;
+ attrp->igsa_gc = NULL;
+ attrp->igsa_gcgrp = NULL;
+
+ return (0);
+}
+
+/* ARGSUSED */
+static void
+ire_gw_secattr_destructor(void *buf, void *cdrarg)
+{
+ tsol_ire_gw_secattr_t *attrp = (tsol_ire_gw_secattr_t *)buf;
+
+ mutex_destroy(&attrp->igsa_lock);
+}
+
+tsol_ire_gw_secattr_t *
+ire_gw_secattr_alloc(int kmflags)
+{
+ return (kmem_cache_alloc(ire_gw_secattr_cache, kmflags));
+}
+
+void
+ire_gw_secattr_free(tsol_ire_gw_secattr_t *attrp)
+{
+ ASSERT(MUTEX_NOT_HELD(&attrp->igsa_lock));
+
+ if (attrp->igsa_rhc != NULL) {
+ TNRHC_RELE(attrp->igsa_rhc);
+ attrp->igsa_rhc = NULL;
+ }
+
+ if (attrp->igsa_gc != NULL) {
+ GC_REFRELE(attrp->igsa_gc);
+ attrp->igsa_gc = NULL;
+ }
+ if (attrp->igsa_gcgrp != NULL) {
+ GCGRP_REFRELE(attrp->igsa_gcgrp);
+ attrp->igsa_gcgrp = NULL;
+ }
+
+ ASSERT(attrp->igsa_rhc == NULL);
+ ASSERT(attrp->igsa_gc == NULL);
+ ASSERT(attrp->igsa_gcgrp == NULL);
+
+ kmem_cache_free(ire_gw_secattr_cache, attrp);
+}
+
+/* ARGSUSED */
+static uint_t
+gcdb_hash_by_secattr(void *hash_data, mod_hash_key_t key)
+{
+ const struct rtsa_s *rp = (struct rtsa_s *)key;
+ const uint32_t *up, *ue;
+ uint_t hash;
+ int i;
+
+ ASSERT(rp != NULL);
+
+ /* See comments in hash_bylabel in zone.c for details */
+ hash = rp->rtsa_doi + (rp->rtsa_doi << 1);
+ up = (const uint32_t *)&rp->rtsa_slrange;
+ ue = up + sizeof (rp->rtsa_slrange) / sizeof (*up);
+ i = 1;
+ while (up < ue) {
+ /* using 2^n + 1, 1 <= n <= 16 as source of many primes */
+ hash += *up + (*up << ((i % 16) + 1));
+ up++;
+ i++;
+ }
+ return (hash);
+}
+
+static int
+gcdb_hash_cmp(mod_hash_key_t key1, mod_hash_key_t key2)
+{
+ struct rtsa_s *rp1 = (struct rtsa_s *)key1;
+ struct rtsa_s *rp2 = (struct rtsa_s *)key2;
+
+ ASSERT(rp1 != NULL && rp2 != NULL);
+
+ if (blequal(&rp1->rtsa_slrange.lower_bound,
+ &rp2->rtsa_slrange.lower_bound) &&
+ blequal(&rp1->rtsa_slrange.upper_bound,
+ &rp2->rtsa_slrange.upper_bound) &&
+ rp1->rtsa_doi == rp2->rtsa_doi)
+ return (0);
+
+ /* No match; not found */
+ return (-1);
+}
+
+/* ARGSUSED */
+static uint_t
+gcgrp_hash_by_addr(void *hash_data, mod_hash_key_t key)
+{
+ tsol_gcgrp_addr_t *ga = (tsol_gcgrp_addr_t *)key;
+ uint_t idx = 0;
+ uint32_t *ap;
+
+ ASSERT(ga != NULL);
+ ASSERT(ga->ga_af == AF_INET || ga->ga_af == AF_INET6);
+
+ ap = (uint32_t *)&ga->ga_addr.s6_addr32[0];
+ idx ^= *ap++;
+ idx ^= *ap++;
+ idx ^= *ap++;
+ idx ^= *ap;
+
+ return (idx);
+}
+
+static int
+gcgrp_hash_cmp(mod_hash_key_t key1, mod_hash_key_t key2)
+{
+ tsol_gcgrp_addr_t *ga1 = (tsol_gcgrp_addr_t *)key1;
+ tsol_gcgrp_addr_t *ga2 = (tsol_gcgrp_addr_t *)key2;
+
+ ASSERT(ga1 != NULL && ga2 != NULL);
+
+ /* Address family must match */
+ if (ga1->ga_af != ga2->ga_af)
+ return (-1);
+
+ if (ga1->ga_addr.s6_addr32[0] == ga2->ga_addr.s6_addr32[0] &&
+ ga1->ga_addr.s6_addr32[1] == ga2->ga_addr.s6_addr32[1] &&
+ ga1->ga_addr.s6_addr32[2] == ga2->ga_addr.s6_addr32[2] &&
+ ga1->ga_addr.s6_addr32[3] == ga2->ga_addr.s6_addr32[3])
+ return (0);
+
+ /* No match; not found */
+ return (-1);
+}
+
+#define RTSAFLAGS "\20\11cipso\3doi\2max_sl\1min_sl"
+
+int
+rtsa_validate(const struct rtsa_s *rp)
+{
+ uint32_t mask = rp->rtsa_mask;
+
+ /* RTSA_CIPSO must be set, and DOI must not be zero */
+ if ((mask & RTSA_CIPSO) == 0 || rp->rtsa_doi == 0) {
+ DTRACE_PROBE2(tx__gcdb__log__error__rtsa__validate, char *,
+ "rtsa(1) lacks flag or has 0 doi.",
+ rtsa_s *, rp);
+ return (EINVAL);
+ }
+ /*
+ * SL range must be specified, and it must have its
+ * upper bound dominating its lower bound.
+ */
+ if ((mask & RTSA_SLRANGE) != RTSA_SLRANGE ||
+ !bldominates(&rp->rtsa_slrange.upper_bound,
+ &rp->rtsa_slrange.lower_bound)) {
+ DTRACE_PROBE2(tx__gcdb__log__error__rtsa__validate, char *,
+ "rtsa(1) min_sl and max_sl not set or max_sl is "
+ "not dominating.", rtsa_s *, rp);
+ return (EINVAL);
+ }
+ return (0);
+}
+
+/*
+ * A brief explanation of the reference counting scheme:
+ *
+ * Prefix IREs have a non-NULL igsa_gc and a NULL igsa_gcgrp;
+ * IRE_CACHEs have it vice-versa.
+ *
+ * Apart from dynamic references due to to reference holds done
+ * actively by threads, we have the following references:
+ *
+ * gcdb_refcnt:
+ * - Every tsol_gc_t pointing to a tsol_gcdb_t contributes a reference
+ * to the gcdb_refcnt.
+ *
+ * gc_refcnt:
+ * - A prefix IRE that points to an igsa_gc contributes a reference
+ * to the gc_refcnt.
+ *
+ * gcgrp_refcnt:
+ * - An IRE_CACHE that points to an igsa_gcgrp contributes a reference
+ * to the gcgrp_refcnt of the associated tsol_gcgrp_t.
+ * - Every tsol_gc_t in the chain headed by tsol_gcgrp_t contributes
+ * a reference to the gcgrp_refcnt.
+ */
+static tsol_gcdb_t *
+gcdb_lookup(struct rtsa_s *rp, boolean_t alloc)
+{
+ tsol_gcdb_t *gcdb = NULL;
+
+ if (rtsa_validate(rp) != 0)
+ return (NULL);
+
+ mutex_enter(&gcdb_lock);
+ /* Find a copy in the cache; otherwise, create one and cache it */
+ if (mod_hash_find(gcdb_hash, (mod_hash_key_t)rp,
+ (mod_hash_val_t *)&gcdb) == 0) {
+ gcdb->gcdb_refcnt++;
+ ASSERT(gcdb->gcdb_refcnt != 0);
+
+ DTRACE_PROBE2(tx__gcdb__log__info__gcdb__lookup, char *,
+ "gcdb(1) is in gcdb_hash(global)", tsol_gcdb_t *, gcdb);
+ } else if (alloc) {
+ gcdb = kmem_zalloc(sizeof (*gcdb), KM_NOSLEEP);
+ if (gcdb != NULL) {
+ gcdb->gcdb_refcnt = 1;
+ gcdb->gcdb_mask = rp->rtsa_mask;
+ gcdb->gcdb_doi = rp->rtsa_doi;
+ gcdb->gcdb_slrange = rp->rtsa_slrange;
+
+ if (mod_hash_insert(gcdb_hash,
+ (mod_hash_key_t)&gcdb->gcdb_attr,
+ (mod_hash_val_t)gcdb) != 0) {
+ mutex_exit(&gcdb_lock);
+ kmem_free(gcdb, sizeof (*gcdb));
+ return (NULL);
+ }
+
+ DTRACE_PROBE2(tx__gcdb__log__info__gcdb__insert, char *,
+ "gcdb(1) inserted in gcdb_hash(global)",
+ tsol_gcdb_t *, gcdb);
+ }
+ }
+ mutex_exit(&gcdb_lock);
+ return (gcdb);
+}
+
+static void
+gcdb_inactive(tsol_gcdb_t *gcdb)
+{
+ ASSERT(MUTEX_HELD(&gcdb_lock));
+ ASSERT(gcdb != NULL && gcdb->gcdb_refcnt == 0);
+
+ (void) mod_hash_remove(gcdb_hash, (mod_hash_key_t)&gcdb->gcdb_attr,
+ (mod_hash_val_t *)&gcdb);
+
+ DTRACE_PROBE2(tx__gcdb__log__info__gcdb__remove, char *,
+ "gcdb(1) removed from gcdb_hash(global)",
+ tsol_gcdb_t *, gcdb);
+ kmem_free(gcdb, sizeof (*gcdb));
+}
+
+tsol_gc_t *
+gc_create(struct rtsa_s *rp, tsol_gcgrp_t *gcgrp, boolean_t *gcgrp_xtrarefp)
+{
+ tsol_gc_t *gc;
+ tsol_gcdb_t *gcdb;
+
+ *gcgrp_xtrarefp = B_TRUE;
+
+ rw_enter(&gcgrp->gcgrp_rwlock, RW_WRITER);
+ if ((gcdb = gcdb_lookup(rp, B_TRUE)) == NULL) {
+ rw_exit(&gcgrp->gcgrp_rwlock);
+ return (NULL);
+ }
+
+ for (gc = gcgrp->gcgrp_head; gc != NULL; gc = gc->gc_next) {
+ if (gc->gc_db == gcdb) {
+ ASSERT(gc->gc_grp == gcgrp);
+
+ gc->gc_refcnt++;
+ ASSERT(gc->gc_refcnt != 0);
+
+ GCDB_REFRELE(gcdb);
+
+ DTRACE_PROBE3(tx__gcdb__log__info__gc__create,
+ char *, "found gc(1) in gcgrp(2)",
+ tsol_gc_t *, gc, tsol_gcgrp_t *, gcgrp);
+ rw_exit(&gcgrp->gcgrp_rwlock);
+ return (gc);
+ }
+ }
+
+ gc = kmem_zalloc(sizeof (*gc), KM_NOSLEEP);
+ if (gc != NULL) {
+ if (gcgrp->gcgrp_head == NULL) {
+ gcgrp->gcgrp_head = gcgrp->gcgrp_tail = gc;
+ } else {
+ gcgrp->gcgrp_tail->gc_next = gc;
+ gc->gc_prev = gcgrp->gcgrp_tail;
+ gcgrp->gcgrp_tail = gc;
+ }
+ gcgrp->gcgrp_count++;
+ ASSERT(gcgrp->gcgrp_count != 0);
+
+ /* caller has incremented gcgrp reference for us */
+ gc->gc_grp = gcgrp;
+
+ gc->gc_db = gcdb;
+ gc->gc_refcnt = 1;
+
+ DTRACE_PROBE3(tx__gcdb__log__info__gc__create, char *,
+ "added gc(1) to gcgrp(2)", tsol_gc_t *, gc,
+ tsol_gcgrp_t *, gcgrp);
+
+ *gcgrp_xtrarefp = B_FALSE;
+ }
+ rw_exit(&gcgrp->gcgrp_rwlock);
+
+ return (gc);
+}
+
+void
+gc_inactive(tsol_gc_t *gc)
+{
+ tsol_gcgrp_t *gcgrp = gc->gc_grp;
+
+ ASSERT(gcgrp != NULL);
+ ASSERT(RW_WRITE_HELD(&gcgrp->gcgrp_rwlock));
+ ASSERT(gc->gc_refcnt == 0);
+
+ if (gc->gc_prev != NULL)
+ gc->gc_prev->gc_next = gc->gc_next;
+ else
+ gcgrp->gcgrp_head = gc->gc_next;
+ if (gc->gc_next != NULL)
+ gc->gc_next->gc_prev = gc->gc_prev;
+ else
+ gcgrp->gcgrp_tail = gc->gc_prev;
+ ASSERT(gcgrp->gcgrp_count > 0);
+ gcgrp->gcgrp_count--;
+
+ /* drop lock before it's destroyed */
+ rw_exit(&gcgrp->gcgrp_rwlock);
+
+ DTRACE_PROBE3(tx__gcdb__log__info__gc__remove, char *,
+ "removed inactive gc(1) from gcgrp(2)",
+ tsol_gc_t *, gc, tsol_gcgrp_t *, gcgrp);
+
+ GCGRP_REFRELE(gcgrp);
+
+ gc->gc_grp = NULL;
+ gc->gc_prev = gc->gc_next = NULL;
+
+ if (gc->gc_db != NULL)
+ GCDB_REFRELE(gc->gc_db);
+
+ kmem_free(gc, sizeof (*gc));
+}
+
+tsol_gcgrp_t *
+gcgrp_lookup(tsol_gcgrp_addr_t *ga, boolean_t alloc)
+{
+ tsol_gcgrp_t *gcgrp = NULL;
+ mod_hash_t *hashp;
+
+ ASSERT(ga->ga_af == AF_INET || ga->ga_af == AF_INET6);
+
+ hashp = (ga->ga_af == AF_INET) ? gcgrp4_hash : gcgrp6_hash;
+
+ mutex_enter(&gcgrp_lock);
+ if (mod_hash_find(hashp, (mod_hash_key_t)ga,
+ (mod_hash_val_t *)&gcgrp) == 0) {
+ gcgrp->gcgrp_refcnt++;
+ ASSERT(gcgrp->gcgrp_refcnt != 0);
+
+ DTRACE_PROBE3(tx__gcdb__log__info__gcgrp__lookup, char *,
+ "found gcgrp(1) in hash(2)", tsol_gcgrp_t *, gcgrp,
+ mod_hash_t *, hashp);
+
+ } else if (alloc) {
+ gcgrp = kmem_zalloc(sizeof (*gcgrp), KM_NOSLEEP);
+ if (gcgrp != NULL) {
+ gcgrp->gcgrp_refcnt = 1;
+ rw_init(&gcgrp->gcgrp_rwlock, NULL, RW_DEFAULT, NULL);
+ bcopy(ga, &gcgrp->gcgrp_addr, sizeof (*ga));
+
+ if (mod_hash_insert(hashp,
+ (mod_hash_key_t)&gcgrp->gcgrp_addr,
+ (mod_hash_val_t)gcgrp) != 0) {
+ mutex_exit(&gcgrp_lock);
+ kmem_free(gcgrp, sizeof (*gcgrp));
+ return (NULL);
+ }
+
+ DTRACE_PROBE3(tx__gcdb__log__info__gcgrp__insert,
+ char *, "inserted gcgrp(1) in hash(2)",
+ tsol_gcgrp_t *, gcgrp, mod_hash_t *, hashp);
+ }
+ }
+ mutex_exit(&gcgrp_lock);
+ return (gcgrp);
+}
+
+void
+gcgrp_inactive(tsol_gcgrp_t *gcgrp)
+{
+ tsol_gcgrp_addr_t *ga;
+ mod_hash_t *hashp;
+
+ ASSERT(MUTEX_HELD(&gcgrp_lock));
+ ASSERT(!RW_LOCK_HELD(&gcgrp->gcgrp_rwlock));
+ ASSERT(gcgrp != NULL && gcgrp->gcgrp_refcnt == 0);
+ ASSERT(gcgrp->gcgrp_head == NULL && gcgrp->gcgrp_count == 0);
+
+ ga = &gcgrp->gcgrp_addr;
+ ASSERT(ga->ga_af == AF_INET || ga->ga_af == AF_INET6);
+
+ hashp = (ga->ga_af == AF_INET) ? gcgrp4_hash : gcgrp6_hash;
+ (void) mod_hash_remove(hashp, (mod_hash_key_t)ga,
+ (mod_hash_val_t *)&gcgrp);
+ rw_destroy(&gcgrp->gcgrp_rwlock);
+
+ DTRACE_PROBE3(tx__gcdb__log__info__gcgrp__remove, char *,
+ "removed inactive gcgrp(1) from hash(2)",
+ tsol_gcgrp_t *, gcgrp, mod_hash_t *, hashp);
+
+ kmem_free(gcgrp, sizeof (*gcgrp));
+}
+
+/*
+ * Converts CIPSO option to sensitivity label.
+ * Validity checks based on restrictions defined in
+ * COMMERCIAL IP SECURITY OPTION (CIPSO 2.2) (draft-ietf-cipso-ipsecurity)
+ */
+static boolean_t
+cipso_to_sl(const uchar_t *option, bslabel_t *sl)
+{
+ const struct cipso_option *co = (const struct cipso_option *)option;
+ const struct cipso_tag_type_1 *tt1;
+
+ tt1 = (struct cipso_tag_type_1 *)&co->cipso_tag_type[0];
+ if (tt1->tag_type != 1 ||
+ tt1->tag_length < TSOL_TT1_MIN_LENGTH ||
+ tt1->tag_length > TSOL_TT1_MAX_LENGTH ||
+ tt1->tag_length + TSOL_CIPSO_TAG_OFFSET > co->cipso_length)
+ return (B_FALSE);
+
+ bsllow(sl); /* assumed: sets compartments to all zeroes */
+ LCLASS_SET((_bslabel_impl_t *)sl, tt1->tag_sl);
+ bcopy(tt1->tag_cat, &((_bslabel_impl_t *)sl)->compartments,
+ tt1->tag_length - TSOL_TT1_MIN_LENGTH);
+ return (B_TRUE);
+}
+
+/*
+ * Parse the CIPSO label in the incoming packet and construct a ts_label_t
+ * that reflects the CIPSO label and attach it to the dblk cred. Later as
+ * the mblk flows up through the stack any code that needs to examine the
+ * packet label can inspect the label from the dblk cred. This function is
+ * called right in ip_rput for all packets, i.e. locally destined and
+ * to be forwarded packets. The forwarding path needs to examine the label
+ * to determine how to forward the packet.
+ *
+ * For IPv4, IP header options have been pulled up, but other headers might not
+ * have been. For IPv6, any hop-by-hop options have been pulled up, but any
+ * other headers might not be present.
+ */
+boolean_t
+tsol_get_pkt_label(mblk_t *mp, int version)
+{
+ tsol_tpc_t *src_rhtp;
+ uchar_t *opt_ptr = NULL;
+ const ipha_t *ipha;
+ bslabel_t sl;
+ uint32_t doi;
+ tsol_ip_label_t label_type;
+ const cipso_option_t *co;
+ const void *src;
+ const ip6_t *ip6h;
+
+ ASSERT(DB_TYPE(mp) == M_DATA);
+
+ if (version == IPV4_VERSION) {
+ ipha = (const ipha_t *)mp->b_rptr;
+ src = &ipha->ipha_src;
+ label_type = tsol_get_option(mp, &opt_ptr);
+ } else {
+ uchar_t *after_secopt;
+ boolean_t hbh_needed;
+ const uchar_t *ip6hbh;
+ size_t optlen;
+
+ label_type = OPT_NONE;
+ ip6h = (const ip6_t *)mp->b_rptr;
+ src = &ip6h->ip6_src;
+ if (ip6h->ip6_nxt == IPPROTO_HOPOPTS) {
+ ip6hbh = (const uchar_t *)&ip6h[1];
+ optlen = (ip6hbh[1] + 1) << 3;
+ ASSERT(ip6hbh + optlen <= mp->b_wptr);
+ opt_ptr = tsol_find_secopt_v6(ip6hbh, optlen,
+ &after_secopt, &hbh_needed);
+ /* tsol_find_secopt_v6 guarantees some sanity */
+ if (opt_ptr != NULL &&
+ (optlen = opt_ptr[1]) >= 8) {
+ opt_ptr += 2;
+ bcopy(opt_ptr, &doi, sizeof (doi));
+ doi = ntohl(doi);
+ if (doi == IP6LS_DOI_V4 &&
+ opt_ptr[4] == IP6LS_TT_V4 &&
+ opt_ptr[5] <= optlen - 4 &&
+ opt_ptr[7] <= optlen - 6) {
+ opt_ptr += sizeof (doi) + 2;
+ label_type = OPT_CIPSO;
+ }
+ }
+ }
+ }
+
+ switch (label_type) {
+ case OPT_CIPSO:
+ /*
+ * Convert the CIPSO label to the internal format
+ * and attach it to the dblk cred.
+ * Validity checks based on restrictions defined in
+ * COMMERCIAL IP SECURITY OPTION (CIPSO 2.2)
+ * (draft-ietf-cipso-ipsecurity)
+ */
+ if (version == IPV6_VERSION && ip6opt_ls == 0)
+ return (B_FALSE);
+ co = (const struct cipso_option *)opt_ptr;
+ if ((co->cipso_length <
+ TSOL_CIPSO_TAG_OFFSET + TSOL_TT1_MIN_LENGTH) ||
+ (co->cipso_length > IP_MAX_OPT_LENGTH))
+ return (B_FALSE);
+ bcopy(co->cipso_doi, &doi, sizeof (doi));
+ doi = ntohl(doi);
+ if (!cipso_to_sl(opt_ptr, &sl))
+ return (B_FALSE);
+ setbltype(&sl, SUN_SL_ID);
+ break;
+
+ case OPT_NONE:
+ /*
+ * Handle special cases that are not currently labeled, even
+ * though the sending system may otherwise be configured as
+ * labeled.
+ * - IGMP
+ * - IPv4 ICMP Router Discovery
+ * - IPv6 Neighbor Discovery
+ */
+ if (version == IPV4_VERSION) {
+ if (ipha->ipha_protocol == IPPROTO_IGMP)
+ return (B_TRUE);
+ if (ipha->ipha_protocol == IPPROTO_ICMP) {
+ const struct icmp *icmp = (const struct icmp *)
+ (mp->b_rptr + IPH_HDR_LENGTH(ipha));
+
+ if ((uchar_t *)icmp > mp->b_wptr) {
+ if (!pullupmsg(mp,
+ (uchar_t *)icmp - mp->b_rptr + 1))
+ return (B_FALSE);
+ icmp = (const struct icmp *)
+ (mp->b_rptr +
+ IPH_HDR_LENGTH(ipha));
+ }
+ if (icmp->icmp_type == ICMP_ROUTERADVERT ||
+ icmp->icmp_type == ICMP_ROUTERSOLICIT)
+ return (B_TRUE);
+ }
+ src = &ipha->ipha_src;
+ } else {
+ if (ip6h->ip6_nxt == IPPROTO_ICMPV6) {
+ const icmp6_t *icmp6 = (const icmp6_t *)
+ (mp->b_rptr + IPV6_HDR_LEN);
+
+ if ((uchar_t *)icmp6 + ICMP6_MINLEN >
+ mp->b_wptr) {
+ if (!pullupmsg(mp,
+ (uchar_t *)icmp6 - mp->b_rptr +
+ ICMP6_MINLEN))
+ return (B_FALSE);
+ icmp6 = (const icmp6_t *)
+ (mp->b_rptr + IPV6_HDR_LEN);
+ }
+ if (icmp6->icmp6_type >= MLD_LISTENER_QUERY &&
+ icmp6->icmp6_type <= ICMP6_MAX_INFO_TYPE)
+ return (B_TRUE);
+ }
+ src = &ip6h->ip6_src;
+ }
+
+ /*
+ * Look up the tnrhtp database and get the implicit label
+ * that is associated with this unlabeled host and attach
+ * it to the packet.
+ */
+ if ((src_rhtp = find_tpc(src, version, B_FALSE)) == NULL)
+ return (B_FALSE);
+
+ /* If the sender is labeled, drop the unlabeled packet. */
+ if (src_rhtp->tpc_tp.host_type != UNLABELED) {
+ TPC_RELE(src_rhtp);
+ pr_addr_dbg("unlabeled packet forged from %s\n",
+ version == IPV4_VERSION ? AF_INET : AF_INET6, src);
+ return (B_FALSE);
+ }
+
+ sl = src_rhtp->tpc_tp.tp_def_label;
+ setbltype(&sl, SUN_SL_ID);
+ doi = src_rhtp->tpc_tp.tp_doi;
+ TPC_RELE(src_rhtp);
+ break;
+
+ default:
+ return (B_FALSE);
+ }
+
+ /* Make sure no other thread is messing with this mblk */
+ ASSERT(DB_REF(mp) == 1);
+ if (DB_CRED(mp) == NULL) {
+ DB_CRED(mp) = newcred_from_bslabel(&sl, doi, KM_NOSLEEP);
+ if (DB_CRED(mp) == NULL)
+ return (B_FALSE);
+ } else {
+ cred_t *newcr;
+
+ newcr = copycred_from_bslabel(DB_CRED(mp), &sl, doi,
+ KM_NOSLEEP);
+ if (newcr == NULL)
+ return (B_FALSE);
+ crfree(DB_CRED(mp));
+ DB_CRED(mp) = newcr;
+ }
+
+ /*
+ * If the source was unlabeled, then flag as such,
+ * while remembering that CIPSO routers add headers.
+ */
+ if (label_type == OPT_NONE)
+ crgetlabel(DB_CRED(mp))->tsl_flags |= TSLF_UNLABELED;
+ else if (label_type == OPT_CIPSO) {
+ if ((src_rhtp = find_tpc(src, version, B_FALSE)) == NULL)
+ return (B_FALSE);
+ if (src_rhtp->tpc_tp.host_type == UNLABELED)
+ crgetlabel(DB_CRED(mp))->tsl_flags |=
+ TSLF_UNLABELED;
+ TPC_RELE(src_rhtp);
+ }
+
+ return (B_TRUE);
+}
+
+/*
+ * This routine determines whether the given packet should be accepted locally.
+ * It does a range/set check on the packet's label by looking up the given
+ * address in the remote host database.
+ */
+boolean_t
+tsol_receive_local(const mblk_t *mp, const void *addr, uchar_t version,
+ boolean_t shared_addr, const conn_t *connp)
+{
+ const cred_t *credp;
+ ts_label_t *plabel, *conn_plabel;
+ tsol_tpc_t *tp;
+ boolean_t retv;
+ const bslabel_t *label, *conn_label;
+
+ /*
+ * The cases in which this can happen are:
+ * - IPv6 Router Alert, where ip_rput_data_v6 deliberately skips
+ * over the label attachment process.
+ * - MLD output looped-back to ourselves.
+ * - IPv4 Router Discovery, where tsol_get_pkt_label intentionally
+ * avoids the labeling process.
+ * We trust that all valid paths in the code set the cred pointer when
+ * needed.
+ */
+ if ((credp = DB_CRED(mp)) == NULL)
+ return (B_TRUE);
+
+ /*
+ * If this packet is from the inside (not a remote host) and has the
+ * same zoneid as the selected destination, then no checks are
+ * necessary. Membership in the zone is enough proof. This is
+ * intended to be a hot path through this function.
+ */
+ if (!crisremote(credp) &&
+ crgetzone(credp) == crgetzone(connp->conn_cred))
+ return (B_TRUE);
+
+ plabel = crgetlabel(credp);
+ conn_plabel = crgetlabel(connp->conn_cred);
+ ASSERT(plabel != NULL && conn_plabel != NULL);
+
+ label = label2bslabel(plabel);
+ conn_label = label2bslabel(crgetlabel(connp->conn_cred));
+
+ /*
+ * MLPs are always validated using the range and set of the local
+ * address, even when the remote host is unlabeled.
+ */
+ if (connp->conn_mlp_type == mlptBoth ||
+ /* LINTED: no consequent */
+ connp->conn_mlp_type == (shared_addr ? mlptShared : mlptPrivate)) {
+ ;
+
+ /*
+ * If this is a packet from an unlabeled sender, then we must apply
+ * different rules. If the label is equal to the zone's label, then
+ * it's allowed. If it's not equal, but the zone is either the global
+ * zone or the label is dominated by the zone's label, then allow it
+ * as long as it's in the range configured for the destination.
+ */
+ } else if (plabel->tsl_flags & TSLF_UNLABELED) {
+ if (plabel->tsl_doi == conn_plabel->tsl_doi &&
+ blequal(label, conn_label))
+ return (B_TRUE);
+
+ if (!connp->conn_mac_exempt ||
+ (connp->conn_zoneid != GLOBAL_ZONEID &&
+ (plabel->tsl_doi != conn_plabel->tsl_doi ||
+ !bldominates(conn_label, label)))) {
+ DTRACE_PROBE3(
+ tx__ip__log__drop__receivelocal__mac_unl,
+ char *,
+ "unlabeled packet mp(1) fails mac for conn(2)",
+ mblk_t *, mp, conn_t *, connp);
+ return (B_FALSE);
+ }
+
+ /*
+ * If this is a private address and the connection is SLP for private
+ * addresses, then the only thing that matters is the label on the
+ * zone, which is the same as the label on the connection. We don't
+ * care (and don't have to care) about the tnrhdb.
+ */
+ } else if (!shared_addr) {
+ /*
+ * Since this is a zone-specific address, we know that any MLP
+ * case should have been handled up above. That means this
+ * connection must not be MLP for zone-specific addresses. We
+ * assert that to be true.
+ */
+ ASSERT(connp->conn_mlp_type == mlptSingle ||
+ connp->conn_mlp_type == mlptShared);
+ if (plabel->tsl_doi == conn_plabel->tsl_doi &&
+ blequal(label, conn_label))
+ return (B_TRUE);
+ DTRACE_PROBE3(tx__ip__log__drop__receivelocal__mac__slp,
+ char *, "packet mp(1) fails exactly SLP match conn(2)",
+ mblk_t *, mp, conn_t *, connp);
+ return (B_FALSE);
+ }
+
+ tp = find_tpc(addr, version, B_FALSE);
+ if (tp == NULL) {
+ DTRACE_PROBE3(tx__ip__log__drop__receivelocal__no__tnr,
+ char *, "dropping mp(1), host(2) lacks entry",
+ mblk_t *, mp, void *, addr);
+ return (B_FALSE);
+ }
+
+ /*
+ * The local host address should not be unlabeled at this point. The
+ * only way this can happen is that the destination isn't unicast. We
+ * assume that the packet should not have had a label, and thus should
+ * have been handled by the TSLF_UNLABELED logic above.
+ */
+ if (tp->tpc_tp.host_type == UNLABELED) {
+ retv = B_FALSE;
+ DTRACE_PROBE3(tx__ip__log__drop__receivelocal__flag, char *,
+ "mp(1) unlabeled source, but tp is not unlabeled.",
+ mblk_t *, mp, tsol_tpc_t *, tp);
+
+ } else if (tp->tpc_tp.host_type != SUN_CIPSO) {
+ retv = B_FALSE;
+ DTRACE_PROBE3(tx__ip__log__drop__receivelocal__tptype, char *,
+ "delivering mp(1), found unrecognized tpc(2) type.",
+ mblk_t *, mp, tsol_tpc_t *, tp);
+
+ } else if (plabel->tsl_doi != tp->tpc_tp.tp_doi) {
+ retv = B_FALSE;
+ DTRACE_PROBE3(tx__ip__log__drop__receivelocal__mac, char *,
+ "mp(1) could not be delievered to tp(2), doi mismatch",
+ mblk_t *, mp, tsol_tpc_t *, tp);
+
+ } else if (!_blinrange(label, &tp->tpc_tp.tp_sl_range_cipso) &&
+ !blinlset(label, tp->tpc_tp.tp_sl_set_cipso)) {
+ retv = B_FALSE;
+ DTRACE_PROBE3(tx__ip__log__drop__receivelocal__mac, char *,
+ "mp(1) could not be delievered to tp(2), bad mac",
+ mblk_t *, mp, tsol_tpc_t *, tp);
+ } else {
+ retv = B_TRUE;
+ }
+
+ TPC_RELE(tp);
+
+ return (retv);
+}
+
+boolean_t
+tsol_can_accept_raw(mblk_t *mp, boolean_t check_host)
+{
+ ts_label_t *plabel = NULL;
+ tsol_tpc_t *src_rhtp, *dst_rhtp;
+ boolean_t retv;
+
+ if (DB_CRED(mp) != NULL)
+ plabel = crgetlabel(DB_CRED(mp));
+
+ /* We are bootstrapping or the internal template was never deleted */
+ if (plabel == NULL)
+ return (B_TRUE);
+
+ if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
+ ipha_t *ipha = (ipha_t *)mp->b_rptr;
+
+ src_rhtp = find_tpc(&ipha->ipha_src, IPV4_VERSION,
+ B_FALSE);
+ if (src_rhtp == NULL)
+ return (B_FALSE);
+ dst_rhtp = find_tpc(&ipha->ipha_dst, IPV4_VERSION,
+ B_FALSE);
+ } else {
+ ip6_t *ip6h = (ip6_t *)mp->b_rptr;
+
+ src_rhtp = find_tpc(&ip6h->ip6_src, IPV6_VERSION,
+ B_FALSE);
+ if (src_rhtp == NULL)
+ return (B_FALSE);
+ dst_rhtp = find_tpc(&ip6h->ip6_dst, IPV6_VERSION,
+ B_FALSE);
+ }
+ if (dst_rhtp == NULL) {
+ TPC_RELE(src_rhtp);
+ return (B_FALSE);
+ }
+
+ if (label2doi(plabel) != src_rhtp->tpc_tp.tp_doi) {
+ retv = B_FALSE;
+
+ /*
+ * Check that the packet's label is in the correct range for labeled
+ * sender, or is equal to the default label for unlabeled sender.
+ */
+ } else if ((src_rhtp->tpc_tp.host_type != UNLABELED &&
+ !_blinrange(label2bslabel(plabel),
+ &src_rhtp->tpc_tp.tp_sl_range_cipso) &&
+ !blinlset(label2bslabel(plabel),
+ src_rhtp->tpc_tp.tp_sl_set_cipso)) ||
+ (src_rhtp->tpc_tp.host_type == UNLABELED &&
+ !blequal(&plabel->tsl_label, &src_rhtp->tpc_tp.tp_def_label))) {
+ retv = B_FALSE;
+
+ } else if (check_host) {
+ retv = B_TRUE;
+
+ /*
+ * Until we have SL range in the Zone structure, pass it
+ * when our own address lookup returned an internal entry.
+ */
+ } else switch (dst_rhtp->tpc_tp.host_type) {
+ case UNLABELED:
+ retv = B_TRUE;
+ break;
+
+ case SUN_CIPSO:
+ retv = _blinrange(label2bslabel(plabel),
+ &dst_rhtp->tpc_tp.tp_sl_range_cipso) ||
+ blinlset(label2bslabel(plabel),
+ dst_rhtp->tpc_tp.tp_sl_set_cipso);
+ break;
+
+ default:
+ retv = B_FALSE;
+ }
+ TPC_RELE(src_rhtp);
+ TPC_RELE(dst_rhtp);
+ return (retv);
+}
+
+/*
+ * This routine determines whether a response to a failed packet delivery or
+ * connection should be sent back. By default, the policy is to allow such
+ * messages to be sent at all times, as these messages reveal little useful
+ * information and are healthy parts of TCP/IP networking.
+ *
+ * If tsol_strict_error is set, then we do strict tests: if the packet label is
+ * within the label range/set of this host/zone, return B_TRUE; otherwise
+ * return B_FALSE, which causes the packet to be dropped silently.
+ *
+ * Note that tsol_get_pkt_label will cause the packet to drop if the sender is
+ * marked as labeled in the remote host database, but the packet lacks a label.
+ * This means that we don't need to do a lookup on the source; the
+ * TSLF_UNLABELED flag is sufficient.
+ */
+boolean_t
+tsol_can_reply_error(const mblk_t *mp)
+{
+ ts_label_t *plabel = NULL;
+ tsol_tpc_t *rhtp;
+ const ipha_t *ipha;
+ const ip6_t *ip6h;
+ boolean_t retv;
+ bslabel_t *pktbs;
+
+ /* Caller must pull up at least the IP header */
+ ASSERT(MBLKL(mp) >= (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION ?
+ sizeof (*ipha) : sizeof (*ip6h)));
+
+ if (!tsol_strict_error)
+ return (B_TRUE);
+
+ if (DB_CRED(mp) != NULL)
+ plabel = crgetlabel(DB_CRED(mp));
+
+ /* We are bootstrapping or the internal template was never deleted */
+ if (plabel == NULL)
+ return (B_TRUE);
+
+ if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
+ ipha = (const ipha_t *)mp->b_rptr;
+ rhtp = find_tpc(&ipha->ipha_dst, IPV4_VERSION, B_FALSE);
+ } else {
+ ip6h = (const ip6_t *)mp->b_rptr;
+ rhtp = find_tpc(&ip6h->ip6_dst, IPV6_VERSION, B_FALSE);
+ }
+
+ if (rhtp == NULL || label2doi(plabel) != rhtp->tpc_tp.tp_doi) {
+ retv = B_FALSE;
+ } else {
+ /*
+ * If we're in the midst of forwarding, then the destination
+ * address might not be labeled. In that case, allow unlabeled
+ * packets through only if the default label is the same, and
+ * labeled ones if they dominate.
+ */
+ pktbs = label2bslabel(plabel);
+ switch (rhtp->tpc_tp.host_type) {
+ case UNLABELED:
+ if (plabel->tsl_flags & TSLF_UNLABELED) {
+ retv = blequal(pktbs,
+ &rhtp->tpc_tp.tp_def_label);
+ } else {
+ retv = bldominates(pktbs,
+ &rhtp->tpc_tp.tp_def_label);
+ }
+ break;
+
+ case SUN_CIPSO:
+ retv = _blinrange(pktbs,
+ &rhtp->tpc_tp.tp_sl_range_cipso) ||
+ blinlset(pktbs, rhtp->tpc_tp.tp_sl_set_cipso);
+ break;
+
+ default:
+ retv = B_FALSE;
+ break;
+ }
+ }
+
+ if (rhtp != NULL)
+ TPC_RELE(rhtp);
+
+ return (retv);
+}
+
+/*
+ * Finds the zone associated with the given packet. Returns GLOBAL_ZONEID if
+ * the zone cannot be located.
+ *
+ * This is used by the classifier when the packet matches an ALL_ZONES IRE, and
+ * there's no MLP defined.
+ */
+zoneid_t
+tsol_packet_to_zoneid(const mblk_t *mp)
+{
+ cred_t *cr = DB_CRED(mp);
+ zone_t *zone;
+ ts_label_t *label;
+
+ if (cr != NULL) {
+ if ((label = crgetlabel(cr)) != NULL) {
+ zone = zone_find_by_label(label);
+ if (zone != NULL) {
+ zoneid_t zoneid = zone->zone_id;
+
+ zone_rele(zone);
+ return (zoneid);
+ }
+ }
+ }
+ return (GLOBAL_ZONEID);
+}
+
+int
+tsol_ire_match_gwattr(ire_t *ire, const ts_label_t *tsl)
+{
+ int error = 0;
+ tsol_ire_gw_secattr_t *attrp = NULL;
+ tsol_tnrhc_t *gw_rhc = NULL;
+ tsol_gcgrp_t *gcgrp = NULL;
+ tsol_gc_t *gc = NULL;
+ in_addr_t ga_addr4;
+ void *paddr = NULL;
+
+ /* Not in Trusted mode or IRE is local/loopback/broadcast/interface */
+ if (!is_system_labeled() ||
+ (ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK | IRE_BROADCAST |
+ IRE_INTERFACE)))
+ goto done;
+
+ /*
+ * If we don't have a label to compare with, or the IRE does not
+ * contain any gateway security attributes, there's not much that
+ * we can do. We let the former case pass, and the latter fail,
+ * since the IRE doesn't qualify for a match due to the lack of
+ * security attributes.
+ */
+ if (tsl == NULL || ire->ire_gw_secattr == NULL) {
+ if (tsl != NULL) {
+ DTRACE_PROBE3(
+ tx__ip__log__drop__irematch__nogwsec, char *,
+ "ire(1) lacks ire_gw_secattr when matching label(2)",
+ ire_t *, ire, ts_label_t *, tsl);
+ error = EACCES;
+ }
+ goto done;
+ }
+
+ attrp = ire->ire_gw_secattr;
+
+ /*
+ * The possible lock order scenarios related to the tsol gateway
+ * attribute locks are documented at the beginning of ip.c in the
+ * lock order scenario section.
+ */
+ mutex_enter(&attrp->igsa_lock);
+
+ /*
+ * Depending on the IRE type (prefix vs. cache), we seek the group
+ * structure which contains all security credentials of the gateway.
+ * A prefix IRE is associated with at most one gateway credential,
+ * while a cache IRE is associated with every credentials that the
+ * gateway has.
+ */
+ if ((gc = attrp->igsa_gc) != NULL) { /* prefix */
+ gcgrp = gc->gc_grp;
+ ASSERT(gcgrp != NULL);
+ rw_enter(&gcgrp->gcgrp_rwlock, RW_READER);
+ } else if ((gcgrp = attrp->igsa_gcgrp) != NULL) { /* cache */
+ rw_enter(&gcgrp->gcgrp_rwlock, RW_READER);
+ gc = gcgrp->gcgrp_head;
+ if (gc == NULL) {
+ /* gc group is empty, so the drop lock now */
+ ASSERT(gcgrp->gcgrp_count == 0);
+ rw_exit(&gcgrp->gcgrp_rwlock);
+ gcgrp = NULL;
+ }
+ }
+
+ if (gcgrp != NULL)
+ GCGRP_REFHOLD(gcgrp);
+
+ if ((gw_rhc = attrp->igsa_rhc) != NULL) {
+ /*
+ * If our cached entry has grown stale, then discard it so we
+ * can get a new one.
+ */
+ if (gw_rhc->rhc_invalid || gw_rhc->rhc_tpc->tpc_invalid) {
+ TNRHC_RELE(gw_rhc);
+ attrp->igsa_rhc = gw_rhc = NULL;
+ } else {
+ TNRHC_HOLD(gw_rhc)
+ }
+ }
+
+ /* Last attempt at loading the template had failed; try again */
+ if (gw_rhc == NULL) {
+ if (gcgrp != NULL) {
+ tsol_gcgrp_addr_t *ga = &gcgrp->gcgrp_addr;
+
+ if (ire->ire_ipversion == IPV4_VERSION) {
+ ASSERT(ga->ga_af == AF_INET);
+ IN6_V4MAPPED_TO_IPADDR(&ga->ga_addr, ga_addr4);
+ paddr = &ga_addr4;
+ } else {
+ ASSERT(ga->ga_af == AF_INET6);
+ paddr = &ga->ga_addr;
+ }
+ } else if (ire->ire_ipversion == IPV6_VERSION &&
+ !IN6_IS_ADDR_UNSPECIFIED(&ire->ire_gateway_addr_v6)) {
+ paddr = &ire->ire_gateway_addr_v6;
+ } else if (ire->ire_ipversion == IPV4_VERSION &&
+ ire->ire_gateway_addr != INADDR_ANY) {
+ paddr = &ire->ire_gateway_addr;
+ }
+
+ /* We've found a gateway address to do the template lookup */
+ if (paddr != NULL) {
+ ASSERT(gw_rhc == NULL);
+ if (ire->ire_ipversion == IPV4_VERSION)
+ gw_rhc = find_rhc_v4(paddr);
+ else
+ gw_rhc = find_rhc_v6(paddr);
+ if (gw_rhc != NULL) {
+ /*
+ * Note that if the lookup above returned an
+ * internal template, we'll use it for the
+ * time being, and do another lookup next
+ * time around.
+ */
+ /* Another thread has loaded the template? */
+ if (attrp->igsa_rhc != NULL) {
+ TNRHC_RELE(gw_rhc)
+ /* reload, it could be different */
+ gw_rhc = attrp->igsa_rhc;
+ } else {
+ attrp->igsa_rhc = gw_rhc;
+ }
+ /*
+ * Hold an extra reference just like we did
+ * above prior to dropping the igsa_lock.
+ */
+ TNRHC_HOLD(gw_rhc)
+ }
+ }
+ }
+
+ mutex_exit(&attrp->igsa_lock);
+ /* Gateway template not found */
+ if (gw_rhc == NULL) {
+ /*
+ * If destination address is directly reachable through an
+ * interface rather than through a learned route, pass it.
+ */
+ if (paddr != NULL) {
+ DTRACE_PROBE3(
+ tx__ip__log__drop__irematch__nogwtmpl, char *,
+ "ire(1), label(2) off-link with no gw_rhc",
+ ire_t *, ire, ts_label_t *, tsl);
+ error = EINVAL;
+ }
+ goto done;
+ }
+
+ if (gc != NULL) {
+ tsol_gcdb_t *gcdb;
+ /*
+ * In the case of IRE_CACHE we've got one or more gateway
+ * security credentials to compare against the passed in label.
+ * Perform label range comparison against each security
+ * credential of the gateway. In the case of a prefix ire
+ * we need to match against the security attributes of
+ * just the route itself, so the loop is executed only once.
+ */
+ ASSERT(gcgrp != NULL);
+ do {
+ gcdb = gc->gc_db;
+ if (tsl->tsl_doi == gcdb->gcdb_doi &&
+ _blinrange(&tsl->tsl_label, &gcdb->gcdb_slrange))
+ break;
+ if (ire->ire_type == IRE_CACHE)
+ gc = gc->gc_next;
+ else
+ gc = NULL;
+ } while (gc != NULL);
+
+ if (gc == NULL) {
+ DTRACE_PROBE3(
+ tx__ip__log__drop__irematch__nogcmatched,
+ char *, "ire(1), tsl(2): all gc failed match",
+ ire_t *, ire, ts_label_t *, tsl);
+ error = EACCES;
+ }
+ } else {
+ /*
+ * We didn't find any gateway credentials in the IRE
+ * attributes; fall back to the gateway's template for
+ * label range checks, if we are required to do so.
+ */
+ ASSERT(gw_rhc != NULL);
+ switch (gw_rhc->rhc_tpc->tpc_tp.host_type) {
+ case SUN_CIPSO:
+ if (tsl->tsl_doi !=
+ gw_rhc->rhc_tpc->tpc_tp.tp_doi ||
+ (!_blinrange(&tsl->tsl_label,
+ &gw_rhc->rhc_tpc->tpc_tp.
+ tp_sl_range_cipso) &&
+ !blinlset(&tsl->tsl_label,
+ gw_rhc->rhc_tpc->tpc_tp.tp_sl_set_cipso))) {
+ error = EACCES;
+ DTRACE_PROBE4(
+ tx__ip__log__drop__irematch__deftmpl,
+ char *, "ire(1), tsl(2), gw_rhc(3) "
+ "failed match (cipso gw)",
+ ire_t *, ire, ts_label_t *, tsl,
+ tsol_tnrhc_t *, gw_rhc);
+ }
+ break;
+
+ case UNLABELED:
+ if (tsl->tsl_doi !=
+ gw_rhc->rhc_tpc->tpc_tp.tp_doi ||
+ (!_blinrange(&tsl->tsl_label,
+ &gw_rhc->rhc_tpc->tpc_tp.tp_gw_sl_range) &&
+ !blinlset(&tsl->tsl_label,
+ gw_rhc->rhc_tpc->tpc_tp.tp_gw_sl_set))) {
+ error = EACCES;
+ DTRACE_PROBE4(
+ tx__ip__log__drop__irematch__deftmpl,
+ char *, "ire(1), tsl(2), gw_rhc(3) "
+ "failed match (unlabeled gw)",
+ ire_t *, ire, ts_label_t *, tsl,
+ tsol_tnrhc_t *, gw_rhc);
+ }
+ break;
+ }
+ }
+
+done:
+
+ if (gcgrp != NULL) {
+ rw_exit(&gcgrp->gcgrp_rwlock);
+ GCGRP_REFRELE(gcgrp);
+ }
+
+ if (gw_rhc != NULL)
+ TNRHC_RELE(gw_rhc)
+
+ return (error);
+}
+
+/*
+ * Performs label accreditation checks for packet forwarding.
+ *
+ * Returns a pointer to the modified mblk if allowed for forwarding,
+ * or NULL if the packet must be dropped.
+ */
+mblk_t *
+tsol_ip_forward(ire_t *ire, mblk_t *mp)
+{
+ tsol_ire_gw_secattr_t *attrp = NULL;
+ ipha_t *ipha;
+ ip6_t *ip6h;
+ const void *pdst;
+ const void *psrc;
+ boolean_t off_link;
+ tsol_tpc_t *dst_rhtp, *gw_rhtp;
+ tsol_ip_label_t label_type;
+ uchar_t *opt_ptr = NULL;
+ ts_label_t *tsl;
+ uint8_t proto;
+ int af, adjust;
+ uint16_t iplen;
+
+ ASSERT(ire != NULL && mp != NULL);
+ ASSERT(ire->ire_stq != NULL);
+
+ af = (ire->ire_ipversion == IPV4_VERSION) ? AF_INET : AF_INET6;
+
+ if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
+ ASSERT(ire->ire_ipversion == IPV4_VERSION);
+ ipha = (ipha_t *)mp->b_rptr;
+ psrc = &ipha->ipha_src;
+ pdst = &ipha->ipha_dst;
+ proto = ipha->ipha_protocol;
+
+ /* destination not directly reachable? */
+ off_link = (ire->ire_gateway_addr != INADDR_ANY);
+ } else {
+ ASSERT(ire->ire_ipversion == IPV6_VERSION);
+ ip6h = (ip6_t *)mp->b_rptr;
+ psrc = &ip6h->ip6_src;
+ pdst = &ip6h->ip6_dst;
+ proto = ip6h->ip6_nxt;
+
+ if (proto != IPPROTO_TCP && proto != IPPROTO_UDP &&
+ proto != IPPROTO_ICMPV6) {
+ uint8_t *nexthdrp;
+ uint16_t hdr_len;
+
+ if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &hdr_len,
+ &nexthdrp)) {
+ /* malformed packet; drop it */
+ return (NULL);
+ }
+ proto = *nexthdrp;
+ }
+
+ /* destination not directly reachable? */
+ off_link = !IN6_IS_ADDR_UNSPECIFIED(&ire->ire_gateway_addr_v6);
+ }
+
+ if ((tsl = MBLK_GETLABEL(mp)) == NULL)
+ return (mp);
+
+ label_type = tsol_get_option(mp, &opt_ptr);
+
+ ASSERT(psrc != NULL && pdst != NULL);
+ dst_rhtp = find_tpc(pdst, ire->ire_ipversion, B_FALSE);
+
+ if (dst_rhtp == NULL) {
+ /*
+ * Without a template we do not know if forwarding
+ * violates MAC
+ */
+ DTRACE_PROBE3(tx__ip__log__drop__forward__nodst, char *,
+ "mp(1) dropped, no template for destination ip4|6(2)",
+ mblk_t *, mp, void *, pdst);
+ return (NULL);
+ }
+
+ /*
+ * Gateway template must have existed for off-link destinations,
+ * since tsol_ire_match_gwattr has ensured such condition.
+ */
+ if (((attrp = ire->ire_gw_secattr) == NULL || attrp->igsa_rhc == NULL ||
+ (gw_rhtp = attrp->igsa_rhc->rhc_tpc) == NULL) && off_link) {
+ DTRACE_PROBE3(tx__ip__log__drop__forward__nogw, char *,
+ "mp(1) dropped, no gateway in ire attributes(2)",
+ mblk_t *, mp, tsol_ire_gw_secattr_t *, attrp);
+ mp = NULL;
+ goto keep_label;
+ }
+
+ /*
+ * Check that the label for the packet is acceptable
+ * by destination host; otherwise, drop it.
+ */
+ switch (dst_rhtp->tpc_tp.host_type) {
+ case SUN_CIPSO:
+ if (tsl->tsl_doi != dst_rhtp->tpc_tp.tp_doi ||
+ (!_blinrange(&tsl->tsl_label,
+ &dst_rhtp->tpc_tp.tp_sl_range_cipso) &&
+ !blinlset(&tsl->tsl_label,
+ dst_rhtp->tpc_tp.tp_sl_set_cipso))) {
+ DTRACE_PROBE4(tx__ip__log__drop__forward__mac, char *,
+ "labeled packet mp(1) dropped, label(2) fails "
+ "destination(3) accredation check",
+ mblk_t *, mp, ts_label_t *, tsl,
+ tsol_tpc_t *, dst_rhtp);
+ mp = NULL;
+ goto keep_label;
+ }
+ break;
+
+
+ case UNLABELED:
+ if (tsl->tsl_doi != dst_rhtp->tpc_tp.tp_doi ||
+ !blequal(&dst_rhtp->tpc_tp.tp_def_label,
+ &tsl->tsl_label)) {
+ DTRACE_PROBE4(tx__ip__log__drop__forward__mac, char *,
+ "unlabeled packet mp(1) dropped, label(2) fails "
+ "destination(3) accredation check",
+ mblk_t *, mp, ts_label_t *, tsl,
+ tsol_tpc_t *, dst_rhtp);
+ mp = NULL;
+ goto keep_label;
+ }
+ break;
+ }
+ if (label_type == OPT_CIPSO) {
+ /*
+ * We keep the label on any of the following cases:
+ *
+ * 1. The destination is labeled (on/off-link).
+ * 2. The unlabeled destination is off-link,
+ * and the next hop gateway is labeled.
+ */
+ if (dst_rhtp->tpc_tp.host_type != UNLABELED ||
+ (off_link &&
+ gw_rhtp->tpc_tp.host_type != UNLABELED))
+ goto keep_label;
+
+ /*
+ * Strip off the CIPSO option from the packet because: the
+ * unlabeled destination host is directly reachable through
+ * an interface (on-link); or, the unlabeled destination host
+ * is not directly reachable (off-link), and the next hop
+ * gateway is unlabeled.
+ */
+ adjust = (af == AF_INET) ? tsol_remove_secopt(ipha, MBLKL(mp)) :
+ tsol_remove_secopt_v6(ip6h, MBLKL(mp));
+
+ ASSERT(adjust <= 0);
+ if (adjust != 0) {
+
+ /* adjust is negative */
+ ASSERT((mp->b_wptr + adjust) >= mp->b_rptr);
+ mp->b_wptr += adjust;
+
+ if (af == AF_INET) {
+ ipha = (ipha_t *)mp->b_rptr;
+ iplen = ntohs(ipha->ipha_length) + adjust;
+ ipha->ipha_length = htons(iplen);
+ ipha->ipha_hdr_checksum = 0;
+ ipha->ipha_hdr_checksum = ip_csum_hdr(ipha);
+ }
+ DTRACE_PROBE3(tx__ip__log__info__forward__adjust,
+ char *,
+ "mp(1) adjusted(2) for CIPSO option removal",
+ mblk_t *, mp, int, adjust);
+ }
+ goto keep_label;
+ }
+
+ ASSERT(label_type == OPT_NONE);
+ ASSERT(dst_rhtp != NULL);
+
+ /*
+ * We need to add CIPSO option if the destination or the next hop
+ * gateway is labeled. Otherwise, pass the packet as is.
+ */
+ if (dst_rhtp->tpc_tp.host_type == UNLABELED &&
+ (!off_link || gw_rhtp->tpc_tp.host_type == UNLABELED))
+ goto keep_label;
+
+ if ((af == AF_INET &&
+ tsol_check_label(DB_CRED(mp), &mp, &adjust, B_FALSE) != 0) ||
+ (af == AF_INET6 &&
+ tsol_check_label_v6(DB_CRED(mp), &mp, &adjust, B_FALSE) != 0)) {
+ mp = NULL;
+ goto keep_label;
+ }
+
+ ASSERT(adjust != -1);
+ if (adjust != 0) {
+ if (af == AF_INET) {
+ ipha = (ipha_t *)mp->b_rptr;
+ iplen = ntohs(ipha->ipha_length) + adjust;
+ ipha->ipha_length = htons(iplen);
+ ipha->ipha_hdr_checksum = 0;
+ ipha->ipha_hdr_checksum = ip_csum_hdr(ipha);
+ }
+
+ DTRACE_PROBE3(tx__ip__log__info__forward__adjust, char *,
+ "mp(1) adjusted(2) for CIPSO option removal",
+ mblk_t *, mp, int, adjust);
+ }
+
+keep_label:
+ TPC_RELE(dst_rhtp);
+ return (mp);
+}
+
+/*
+ * Name: tsol_rtsa_init()
+ *
+ * Normal: Sanity checks on the route security attributes provided by
+ * user. Convert it into a route security parameter list to
+ * be returned to caller.
+ *
+ * Output: EINVAL if bad security attributes in the routing message
+ * ENOMEM if unable to allocate data structures
+ * 0 otherwise.
+ *
+ * Note: On input, cp must point to the end of any addresses in
+ * the rt_msghdr_t structure.
+ */
+int
+tsol_rtsa_init(rt_msghdr_t *rtm, tsol_rtsecattr_t *sp, caddr_t cp)
+{
+ uint_t sacnt;
+ int err;
+ caddr_t lim;
+ tsol_rtsecattr_t *tp;
+
+ ASSERT((cp >= (caddr_t)&rtm[1]) && sp != NULL);
+
+ /*
+ * In theory, we could accept as many security attributes configured
+ * per route destination. However, the current design is limited
+ * such that at most only one set security attributes is allowed to
+ * be associated with a prefix IRE. We therefore assert for now.
+ */
+ /* LINTED */
+ ASSERT(TSOL_RTSA_REQUEST_MAX == 1);
+
+ sp->rtsa_cnt = 0;
+ lim = (caddr_t)rtm + rtm->rtm_msglen;
+ ASSERT(cp <= lim);
+
+ if ((lim - cp) < sizeof (rtm_ext_t) ||
+ ((rtm_ext_t *)cp)->rtmex_type != RTMEX_GATEWAY_SECATTR)
+ return (0);
+
+ if (((rtm_ext_t *)cp)->rtmex_len < sizeof (tsol_rtsecattr_t))
+ return (EINVAL);
+
+ cp += sizeof (rtm_ext_t);
+
+ if ((lim - cp) < sizeof (*tp) ||
+ (tp = (tsol_rtsecattr_t *)cp, (sacnt = tp->rtsa_cnt) == 0) ||
+ (lim - cp) < TSOL_RTSECATTR_SIZE(sacnt))
+ return (EINVAL);
+
+ /*
+ * Trying to add route security attributes when system
+ * labeling service is not available, or when user supllies
+ * more than the maximum number of security attributes
+ * allowed per request.
+ */
+ if ((sacnt > 0 && !is_system_labeled()) ||
+ sacnt > TSOL_RTSA_REQUEST_MAX)
+ return (EINVAL);
+
+ /* Ensure valid credentials */
+ if ((err = rtsa_validate(&((tsol_rtsecattr_t *)cp)->
+ rtsa_attr[0])) != 0) {
+ cp += sizeof (*sp);
+ return (err);
+ }
+
+ bcopy(cp, sp, sizeof (*sp));
+ cp += sizeof (*sp);
+ return (0);
+}
+
+int
+tsol_ire_init_gwattr(ire_t *ire, uchar_t ipversion, tsol_gc_t *gc,
+ tsol_gcgrp_t *gcgrp)
+{
+ tsol_ire_gw_secattr_t *attrp;
+ boolean_t exists = B_FALSE;
+ in_addr_t ga_addr4;
+ void *paddr = NULL;
+
+ ASSERT(ire != NULL);
+
+ /*
+ * The only time that attrp can be NULL is when this routine is
+ * called for the first time during the creation/initialization
+ * of the corresponding IRE. It will only get cleared when the
+ * IRE is deleted.
+ */
+ if ((attrp = ire->ire_gw_secattr) == NULL) {
+ attrp = ire_gw_secattr_alloc(KM_NOSLEEP);
+ if (attrp == NULL)
+ return (ENOMEM);
+ ire->ire_gw_secattr = attrp;
+ } else {
+ exists = B_TRUE;
+ mutex_enter(&attrp->igsa_lock);
+
+ if (attrp->igsa_rhc != NULL) {
+ TNRHC_RELE(attrp->igsa_rhc);
+ attrp->igsa_rhc = NULL;
+ }
+
+ if (attrp->igsa_gc != NULL)
+ GC_REFRELE(attrp->igsa_gc);
+ if (attrp->igsa_gcgrp != NULL)
+ GCGRP_REFRELE(attrp->igsa_gcgrp);
+ }
+ ASSERT(!exists || MUTEX_HELD(&attrp->igsa_lock));
+
+ /*
+ * References already held by caller and we keep them;
+ * note that both gc and gcgrp may be set to NULL to
+ * clear out igsa_gc and igsa_gcgrp, respectively.
+ */
+ attrp->igsa_gc = gc;
+ attrp->igsa_gcgrp = gcgrp;
+
+ if (gcgrp == NULL && gc != NULL) {
+ gcgrp = gc->gc_grp;
+ ASSERT(gcgrp != NULL);
+ }
+
+ /*
+ * Intialize the template for gateway; we use the gateway's
+ * address found in either the passed in gateway credential
+ * or group pointer, or the ire_gateway_addr{_v6} field.
+ */
+ if (gcgrp != NULL) {
+ tsol_gcgrp_addr_t *ga = &gcgrp->gcgrp_addr;
+
+ /*
+ * Caller is holding a reference, and that we don't
+ * need to hold any lock to access the address.
+ */
+ if (ipversion == IPV4_VERSION) {
+ ASSERT(ga->ga_af == AF_INET);
+ IN6_V4MAPPED_TO_IPADDR(&ga->ga_addr, ga_addr4);
+ paddr = &ga_addr4;
+ } else {
+ ASSERT(ga->ga_af == AF_INET6);
+ paddr = &ga->ga_addr;
+ }
+ } else if (ipversion == IPV6_VERSION &&
+ !IN6_IS_ADDR_UNSPECIFIED(&ire->ire_gateway_addr_v6)) {
+ paddr = &ire->ire_gateway_addr_v6;
+ } else if (ipversion == IPV4_VERSION &&
+ ire->ire_gateway_addr != INADDR_ANY) {
+ paddr = &ire->ire_gateway_addr;
+ }
+
+ /*
+ * Lookup the gateway template; note that we could get an internal
+ * template here, which we cache anyway. During IRE matching, we'll
+ * try to update this gateway template cache and hopefully get a
+ * real one.
+ */
+ if (paddr != NULL) {
+ attrp->igsa_rhc = (ipversion == IPV4_VERSION) ?
+ find_rhc_v4(paddr) : find_rhc_v6(paddr);
+ }
+
+ if (exists)
+ mutex_exit(&attrp->igsa_lock);
+
+ return (0);
+}
+
+/*
+ * This function figures the type of MLP that we'll be using based on the
+ * address that the user is binding and the zone. If the address is
+ * unspecified, then we're looking at both private and shared. If it's one
+ * of the zone's private addresses, then it's private only. If it's one
+ * of the global addresses, then it's shared only.
+ *
+ * If we can't figure out what it is, then return mlptSingle. That's actually
+ * an error case.
+ */
+mlp_type_t
+tsol_mlp_addr_type(zoneid_t zoneid, uchar_t version, const void *addr)
+{
+ in_addr_t in4;
+ ire_t *ire;
+ ipif_t *ipif;
+ zoneid_t addrzone;
+
+ ASSERT(addr != NULL);
+
+ if (version == IPV6_VERSION &&
+ IN6_IS_ADDR_V4MAPPED((const in6_addr_t *)addr)) {
+ IN6_V4MAPPED_TO_IPADDR((const in6_addr_t *)addr, in4);
+ addr = &in4;
+ version = IPV4_VERSION;
+ }
+
+ if (version == IPV4_VERSION) {
+ in4 = *(const in_addr_t *)addr;
+ if (in4 == INADDR_ANY)
+ return (mlptBoth);
+ ire = ire_cache_lookup(in4, zoneid, NULL);
+ } else {
+ if (IN6_IS_ADDR_UNSPECIFIED((const in6_addr_t *)addr))
+ return (mlptBoth);
+ ire = ire_cache_lookup_v6(addr, zoneid, NULL);
+ }
+ /*
+ * If we can't find the IRE, then we have to behave exactly like
+ * ip_bind_laddr{,_v6}. That means looking up the IPIF so that users
+ * can bind to addresses on "down" interfaces.
+ *
+ * If we can't find that either, then the bind is going to fail, so
+ * just give up. Note that there's a miniscule chance that the address
+ * is in transition, but we don't bother handling that.
+ */
+ if (ire == NULL) {
+ if (version == IPV4_VERSION)
+ ipif = ipif_lookup_addr(*(const in_addr_t *)addr, NULL,
+ zoneid, NULL, NULL, NULL, NULL);
+ else
+ ipif = ipif_lookup_addr_v6((const in6_addr_t *)addr,
+ NULL, zoneid, NULL, NULL, NULL, NULL);
+ if (ipif == NULL)
+ return (mlptSingle);
+ addrzone = ipif->ipif_zoneid;
+ ipif_refrele(ipif);
+ } else {
+ addrzone = ire->ire_zoneid;
+ ire_refrele(ire);
+ }
+ return (addrzone == ALL_ZONES ? mlptShared : mlptPrivate);
+}
+
+/*
+ * Since we are configuring local interfaces, and we know trusted
+ * extension CDE requires local interfaces to be cipso host type in
+ * order to function correctly, we'll associate a cipso template
+ * to each local interface and let the interface come up. Configuring
+ * a local interface to be "unlabeled" host type is a configuration error.
+ * We'll override that error and make the interface host type to be cipso
+ * here.
+ *
+ * The code is optimized for the usual "success" case and unwinds things on
+ * error. We don't want to go to the trouble and expense of formatting the
+ * interface name for the usual case where everything is configured correctly.
+ */
+boolean_t
+tsol_check_interface_address(const ipif_t *ipif)
+{
+ tsol_tpc_t *tp;
+ char addrbuf[INET6_ADDRSTRLEN];
+ int af;
+ const void *addr;
+ zone_t *zone;
+ ts_label_t *plabel;
+ const bslabel_t *label;
+ char ifbuf[LIFNAMSIZ + 10];
+ const char *ifname;
+ boolean_t retval;
+ tsol_rhent_t rhent;
+
+ if (IN6_IS_ADDR_V4MAPPED(&ipif->ipif_v6lcl_addr)) {
+ af = AF_INET;
+ addr = &V4_PART_OF_V6(ipif->ipif_v6lcl_addr);
+ } else {
+ af = AF_INET6;
+ addr = &ipif->ipif_v6lcl_addr;
+ }
+
+ tp = find_tpc(&ipif->ipif_v6lcl_addr, IPV6_VERSION, B_FALSE);
+ zone = ipif->ipif_zoneid == ALL_ZONES ? NULL :
+ zone_find_by_id(ipif->ipif_zoneid);
+ if (zone != NULL) {
+ plabel = zone->zone_slabel;
+ ASSERT(plabel != NULL);
+ label = label2bslabel(plabel);
+ }
+
+ /*
+ * If it's CIPSO and an all-zones address, then we're done.
+ * If it's a CIPSO zone specific address, the zone's label
+ * must be in the range or set specified in the template.
+ * When the remote host entry is missing or the template
+ * type is incorrect for this interface, we create a
+ * CIPSO host entry in kernel and allow the interface to be
+ * brought up as CIPSO type.
+ */
+ if (tp != NULL && (
+ /* The all-zones case */
+ (tp->tpc_tp.host_type == SUN_CIPSO &&
+ tp->tpc_tp.tp_doi == default_doi &&
+ ipif->ipif_zoneid == ALL_ZONES) ||
+ /* The local-zone case */
+ (zone != NULL && plabel->tsl_doi == tp->tpc_tp.tp_doi &&
+ ((tp->tpc_tp.host_type == SUN_CIPSO &&
+ (_blinrange(label, &tp->tpc_tp.tp_sl_range_cipso) ||
+ blinlset(label, tp->tpc_tp.tp_sl_set_cipso))))))) {
+ if (zone != NULL)
+ zone_rele(zone);
+ TPC_RELE(tp);
+ return (B_TRUE);
+ }
+
+ ifname = ipif->ipif_ill->ill_name;
+ if (ipif->ipif_id != 0) {
+ (void) snprintf(ifbuf, sizeof (ifbuf), "%s:%u", ifname,
+ ipif->ipif_id);
+ ifname = ifbuf;
+ }
+ (void) inet_ntop(af, addr, addrbuf, sizeof (addrbuf));
+
+ if (tp == NULL) {
+ cmn_err(CE_NOTE, "template entry for %s missing. Default to "
+ "CIPSO type for %s", ifname, addrbuf);
+ retval = B_TRUE;
+ } else if (tp->tpc_tp.host_type == UNLABELED) {
+ cmn_err(CE_NOTE, "template type for %s incorrectly configured. "
+ "Change to CIPSO type for %s", ifname, addrbuf);
+ retval = B_TRUE;
+ } else if (ipif->ipif_zoneid == ALL_ZONES) {
+ if (tp->tpc_tp.host_type != SUN_CIPSO) {
+ cmn_err(CE_NOTE, "%s failed: %s isn't set to CIPSO for "
+ "all-zones. Converted to CIPSO.", ifname, addrbuf);
+ retval = B_TRUE;
+ } else {
+ cmn_err(CE_NOTE, "%s failed: %s has wrong DOI %d "
+ "instead of %d", ifname, addrbuf,
+ tp->tpc_tp.tp_doi, default_doi);
+ retval = B_FALSE;
+ }
+ } else if (zone == NULL) {
+ cmn_err(CE_NOTE, "%s failed: zoneid %d unknown",
+ ifname, ipif->ipif_zoneid);
+ retval = B_FALSE;
+ } else if (plabel->tsl_doi != tp->tpc_tp.tp_doi) {
+ cmn_err(CE_NOTE, "%s failed: zone %s has DOI %d but %s has "
+ "DOI %d", ifname, zone->zone_name, plabel->tsl_doi,
+ addrbuf, tp->tpc_tp.tp_doi);
+ retval = B_FALSE;
+ } else {
+ cmn_err(CE_NOTE, "%s failed: zone %s label incompatible with "
+ "%s", ifname, zone->zone_name, addrbuf);
+ tsol_print_label(label, "zone label");
+ retval = B_FALSE;
+ }
+
+ if (zone != NULL)
+ zone_rele(zone);
+ if (tp != NULL)
+ TPC_RELE(tp);
+ if (retval) {
+ /*
+ * we've corrected a config error and let the interface
+ * come up as cipso. Need to insert an rhent.
+ */
+ if ((rhent.rh_address.ta_family = af) == AF_INET) {
+ rhent.rh_prefix = 32;
+ rhent.rh_address.ta_addr_v4 = *(struct in_addr *)addr;
+ } else {
+ rhent.rh_prefix = 128;
+ rhent.rh_address.ta_addr_v6 = *(in6_addr_t *)addr;
+ }
+ (void) strcpy(rhent.rh_template, "cipso");
+ if (tnrh_load(&rhent) != 0) {
+ cmn_err(CE_NOTE, "%s failed: Cannot insert CIPSO "
+ "template for local addr %s", ifname, addrbuf);
+ retval = B_FALSE;
+ }
+ }
+ return (retval);
+}
--- a/usr/src/uts/common/inet/ip6.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip6.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -348,26 +347,24 @@
extern char *inet_ntop(int, const void *, char *, int);
extern int inet_pton(int, char *, void *);
extern void icmp_time_exceeded_v6(queue_t *, mblk_t *, uint8_t,
- boolean_t, boolean_t);
+ boolean_t, boolean_t);
extern void icmp_unreachable_v6(queue_t *, mblk_t *, uint8_t,
- boolean_t, boolean_t);
+ boolean_t, boolean_t);
extern void icmp_inbound_error_fanout_v6(queue_t *, mblk_t *, ip6_t *,
- icmp6_t *, ill_t *, boolean_t, zoneid_t);
+ icmp6_t *, ill_t *, boolean_t, zoneid_t);
extern boolean_t conn_wantpacket_v6(conn_t *, ill_t *, ip6_t *, int, zoneid_t);
extern mblk_t *ip_add_info_v6(mblk_t *, ill_t *, const in6_addr_t *);
extern in6addr_scope_t ip_addr_scope_v6(const in6_addr_t *);
extern mblk_t *ip_bind_v6(queue_t *, mblk_t *, conn_t *, ip6_pkt_t *);
extern void ip_build_hdrs_v6(uchar_t *, uint_t, ip6_pkt_t *, uint8_t);
-extern void ip_deliver_local_v6(queue_t *, mblk_t *, ill_t *, uint8_t,
- uint_t, uint_t);
extern int ip_fanout_send_icmp_v6(queue_t *, mblk_t *, uint_t,
- uint_t, uint8_t, uint_t, boolean_t, zoneid_t);
+ uint_t, uint8_t, uint_t, boolean_t, zoneid_t);
extern int ip_find_hdr_v6(mblk_t *, ip6_t *, ip6_pkt_t *, uint8_t *);
extern in6_addr_t ip_get_dst_v6(ip6_t *, boolean_t *);
extern ip6_rthdr_t *ip_find_rthdr_v6(ip6_t *, uint8_t *);
extern int ip_hdr_complete_v6(ip6_t *, zoneid_t);
extern boolean_t ip_hdr_length_nexthdr_v6(mblk_t *, ip6_t *,
- uint16_t *, uint8_t **);
+ uint16_t *, uint8_t **);
extern int ip_hdr_length_v6(mblk_t *, ip6_t *);
extern uint32_t ip_massage_options_v6(ip6_t *, ip6_rthdr_t *);
extern void ip_wput_frag_v6(mblk_t *, ire_t *, uint_t, conn_t *, int, int);
@@ -376,13 +373,13 @@
extern int ip_total_hdrs_len_v6(ip6_pkt_t *);
extern int ipsec_ah_get_hdr_size_v6(mblk_t *, boolean_t);
extern void ip_wput_local_v6(queue_t *, ill_t *, ip6_t *, mblk_t *,
- ire_t *, int);
+ ire_t *, int);
extern void ip_wput_md_v6(queue_t *, mblk_t *, conn_t *);
extern void ip_output_v6(void *, mblk_t *, void *, int);
extern void ip_xmit_v6(mblk_t *, ire_t *, uint_t, conn_t *, int,
- struct ipsec_out_s *);
+ struct ipsec_out_s *);
extern void ip_rput_data_v6(queue_t *, ill_t *, mblk_t *, ip6_t *,
- uint_t, mblk_t *);
+ uint_t, mblk_t *);
extern void mld_input(queue_t *, mblk_t *, ill_t *);
extern void mld_joingroup(ilm_t *);
extern void mld_leavegroup(ilm_t *);
@@ -391,15 +388,15 @@
extern void pr_addr_dbg(char *, int, const void *);
extern ipif_t *ip_newroute_get_src_ipif_v6(ipif_t *, boolean_t,
- const in6_addr_t *);
+ const in6_addr_t *);
extern int ip_multirt_apply_membership_v6(int (*fn)(conn_t *, boolean_t,
- const in6_addr_t *, int, mcast_record_t, const in6_addr_t *,
- mblk_t *), ire_t *, conn_t *, boolean_t, const in6_addr_t *,
- mcast_record_t, const in6_addr_t *, mblk_t *);
+ const in6_addr_t *, int, mcast_record_t, const in6_addr_t *,
+ mblk_t *), ire_t *, conn_t *, boolean_t, const in6_addr_t *,
+ mcast_record_t, const in6_addr_t *, mblk_t *);
extern void ip_newroute_ipif_v6(queue_t *, mblk_t *, ipif_t *,
- in6_addr_t, int, zoneid_t);
+ in6_addr_t, int, zoneid_t);
extern void ip_newroute_v6(queue_t *, mblk_t *, const in6_addr_t *,
- const in6_addr_t *, ill_t *, zoneid_t);
+ const in6_addr_t *, ill_t *, zoneid_t);
extern void ip6_kstat_init(void);
extern size_t ip6_get_src_preferences(conn_t *, uint32_t *);
extern int ip6_set_src_preferences(conn_t *, uint32_t);
--- a/usr/src/uts/common/inet/ip_if.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip_if.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -30,6 +29,8 @@
#pragma ident "%Z%%M% %I% %E% SMI"
+#include <net/route.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -151,7 +152,7 @@
extern void ill_delete(ill_t *);
extern void ill_delete_tail(ill_t *);
extern int ill_dl_phys(ill_t *, ipif_t *, mblk_t *, queue_t *);
-extern int ill_dls_info(struct sockaddr_dl *, ipif_t *);
+extern int ill_dls_info(struct sockaddr_dl *, const ipif_t *);
extern void ill_fastpath_ack(ill_t *, mblk_t *);
extern void ill_fastpath_nack(ill_t *);
extern int ill_fastpath_probe(ill_t *, mblk_t *);
@@ -186,7 +187,7 @@
extern int ill_up_ipifs(ill_t *, queue_t *, mblk_t *);
extern boolean_t ill_is_probeonly(ill_t *);
-extern char *ipif_get_name(ipif_t *, char *, int);
+extern char *ipif_get_name(const ipif_t *, char *, int);
extern void ipif_init(void);
extern ipif_t *ipif_lookup_addr(ipaddr_t, ill_t *, zoneid_t, queue_t *,
mblk_t *, ipsq_func_t, int *);
@@ -255,13 +256,15 @@
extern int ip_ill_report(queue_t *, mblk_t *, caddr_t, cred_t *);
extern int ip_ipif_report(queue_t *, mblk_t *, caddr_t, cred_t *);
extern void ip_ll_subnet_defaults(ill_t *, mblk_t *);
+
extern int ip_rt_add(ipaddr_t, ipaddr_t, ipaddr_t, ipaddr_t, int,
- ipif_t *, ipif_t *, ire_t **, boolean_t, queue_t *, mblk_t *, ipsq_func_t);
+ ipif_t *, ipif_t *, ire_t **, boolean_t, queue_t *, mblk_t *, ipsq_func_t,
+ struct rtsa_s *);
extern int ip_mrtun_rt_add(ipaddr_t, int, ipif_t *, ipif_t *, ire_t **,
queue_t *, mblk_t *, ipsq_func_t);
extern int ip_rt_add_v6(const in6_addr_t *, const in6_addr_t *,
const in6_addr_t *, const in6_addr_t *, int, ipif_t *, ire_t **,
- queue_t *, mblk_t *, ipsq_func_t);
+ queue_t *, mblk_t *, ipsq_func_t, struct rtsa_s *);
extern int ip_rt_delete(ipaddr_t, ipaddr_t, ipaddr_t, uint_t, int,
ipif_t *, ipif_t *, boolean_t, queue_t *, mblk_t *, ipsq_func_t);
extern int ip_mrtun_rt_delete(ipaddr_t, ipif_t *);
--- a/usr/src/uts/common/inet/ip_ire.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip_ire.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -128,6 +127,7 @@
/* zones or shared IREs */
#define MATCH_IRE_MARK_PRIVATE_ADDR 0x8000 /* Match IRE ire_marks with */
/* IRE_MARK_PRIVATE_ADDR. */
+#define MATCH_IRE_SECATTR 0x10000 /* Match gateway security attributes */
/* Structure for ire_cache_count() */
typedef struct {
@@ -176,6 +176,8 @@
extern uint_t ire_srcif_table_count;
#ifdef _KERNEL
+struct ts_label_s;
+
extern ipaddr_t ip_plen_to_mask(uint_t);
extern in6_addr_t *ip_plen_to_mask_v6(uint_t, in6_addr_t *);
@@ -194,8 +196,8 @@
extern int ip_mask_to_plen(ipaddr_t);
extern int ip_mask_to_plen_v6(const in6_addr_t *);
-extern ire_t *ipif_to_ire(ipif_t *);
-extern ire_t *ipif_to_ire_v6(ipif_t *);
+extern ire_t *ipif_to_ire(const ipif_t *);
+extern ire_t *ipif_to_ire_v6(const ipif_t *);
extern int ire_add(ire_t **, queue_t *, mblk_t *, ipsq_func_t);
extern int ire_add_mrtun(ire_t **, queue_t *, mblk_t *, ipsq_func_t);
@@ -206,19 +208,24 @@
extern void ire_atomic_end(irb_t *irb_ptr, ire_t *ire);
extern void ire_cache_count(ire_t *, char *);
-extern ire_t *ire_cache_lookup(ipaddr_t, zoneid_t);
-extern ire_t *ire_cache_lookup_v6(const in6_addr_t *, zoneid_t);
+extern ire_t *ire_cache_lookup(ipaddr_t, zoneid_t,
+ const struct ts_label_s *);
+extern ire_t *ire_cache_lookup_v6(const in6_addr_t *, zoneid_t,
+ const struct ts_label_s *);
extern void ire_cache_reclaim(ire_t *, char *);
extern void ire_check_bcast_present(ipif_t *, ipaddr_t, int, boolean_t *,
boolean_t *);
+
extern ire_t *ire_create_mp(uchar_t *, uchar_t *, uchar_t *, uchar_t *,
uchar_t *, uint_t, mblk_t *, queue_t *, queue_t *, ushort_t, mblk_t *,
- ipif_t *, ill_t *, ipaddr_t, uint32_t, uint32_t, uint32_t, const iulp_t *);
+ ipif_t *, ill_t *, ipaddr_t, uint32_t, uint32_t, uint32_t, const iulp_t *,
+ tsol_gc_t *, tsol_gcgrp_t *);
extern ire_t *ire_create(uchar_t *, uchar_t *, uchar_t *, uchar_t *,
uchar_t *, uint_t *, mblk_t *, queue_t *, queue_t *, ushort_t, mblk_t *,
- ipif_t *, ill_t *, ipaddr_t, uint32_t, uint32_t, uint32_t, const iulp_t *);
+ ipif_t *, ill_t *, ipaddr_t, uint32_t, uint32_t, uint32_t, const iulp_t *,
+ tsol_gc_t *, tsol_gcgrp_t *);
extern ire_t **ire_check_and_create_bcast(ipif_t *, ipaddr_t,
ire_t **, int);
@@ -226,32 +233,38 @@
extern ire_t *ire_init(ire_t *, uchar_t *, uchar_t *, uchar_t *,
uchar_t *, uchar_t *, uint_t *, mblk_t *, queue_t *, queue_t *, ushort_t,
mblk_t *, ipif_t *, ill_t *, ipaddr_t, uint32_t, uint32_t, uint32_t,
- const iulp_t *);
+ const iulp_t *, tsol_gc_t *, tsol_gcgrp_t *);
-extern void ire_init_common(ire_t *, uint_t *, mblk_t *, queue_t *,
+extern boolean_t ire_init_common(ire_t *, uint_t *, mblk_t *, queue_t *,
queue_t *, ushort_t, mblk_t *, ipif_t *, ill_t *, uint32_t,
- uint32_t, uint32_t, uchar_t, const iulp_t *);
+ uint32_t, uint32_t, uchar_t, const iulp_t *, tsol_gc_t *, tsol_gcgrp_t *);
extern ire_t *ire_create_v6(const in6_addr_t *, const in6_addr_t *,
const in6_addr_t *, const in6_addr_t *, uint_t *, mblk_t *, queue_t *,
queue_t *, ushort_t, mblk_t *, ipif_t *,
- const in6_addr_t *, uint32_t, uint32_t, uint_t, const iulp_t *);
+ const in6_addr_t *, uint32_t, uint32_t, uint_t, const iulp_t *,
+ tsol_gc_t *, tsol_gcgrp_t *);
extern ire_t *ire_create_mp_v6(const in6_addr_t *, const in6_addr_t *,
const in6_addr_t *, const in6_addr_t *, mblk_t *, queue_t *,
queue_t *, ushort_t, mblk_t *, ipif_t *,
- const in6_addr_t *, uint32_t, uint32_t, uint_t, const iulp_t *);
+ const in6_addr_t *, uint32_t, uint32_t, uint_t, const iulp_t *,
+ tsol_gc_t *, tsol_gcgrp_t *);
extern ire_t *ire_init_v6(ire_t *, const in6_addr_t *, const in6_addr_t *,
const in6_addr_t *, const in6_addr_t *, uint_t *, mblk_t *, queue_t *,
queue_t *, ushort_t, mblk_t *, ipif_t *,
- const in6_addr_t *, uint32_t, uint32_t, uint_t, const iulp_t *);
+ const in6_addr_t *, uint32_t, uint32_t, uint_t, const iulp_t *,
+ tsol_gc_t *, tsol_gcgrp_t *);
-extern ire_t *ire_ctable_lookup(ipaddr_t, ipaddr_t, int, ipif_t *,
- zoneid_t, int);
+extern void ire_clookup_delete_cache_gw(ipaddr_t, zoneid_t);
+extern void ire_clookup_delete_cache_gw_v6(const in6_addr_t *, zoneid_t);
+
+extern ire_t *ire_ctable_lookup(ipaddr_t, ipaddr_t, int, const ipif_t *,
+ zoneid_t, const struct ts_label_s *, int);
extern ire_t *ire_ctable_lookup_v6(const in6_addr_t *, const in6_addr_t *,
- int, ipif_t *, zoneid_t, int);
+ int, const ipif_t *, zoneid_t, const struct ts_label_s *, int);
extern void ire_delete(ire_t *);
extern void ire_delete_cache_gw(ire_t *, char *);
@@ -267,11 +280,13 @@
extern void ire_flush_cache_v4(ire_t *, int);
extern void ire_flush_cache_v6(ire_t *, int);
-extern ire_t *ire_ftable_lookup(ipaddr_t, ipaddr_t, ipaddr_t, int, ipif_t *,
- ire_t **, zoneid_t, uint32_t, int);
+extern ire_t *ire_ftable_lookup(ipaddr_t, ipaddr_t, ipaddr_t, int,
+ const ipif_t *, ire_t **, zoneid_t, uint32_t,
+ const struct ts_label_s *, int);
extern ire_t *ire_ftable_lookup_v6(const in6_addr_t *, const in6_addr_t *,
- const in6_addr_t *, int, ipif_t *, ire_t **, zoneid_t, uint32_t, int);
+ const in6_addr_t *, int, const ipif_t *, ire_t **, zoneid_t,
+ uint32_t, const struct ts_label_s *, int);
extern ire_t *ire_ihandle_lookup_onlink(ire_t *);
extern ire_t *ire_ihandle_lookup_offlink(ire_t *, ire_t *);
@@ -287,28 +302,33 @@
extern void ire_refrele(ire_t *);
extern void ire_refrele_notr(ire_t *);
-extern ire_t *ire_route_lookup(ipaddr_t, ipaddr_t, ipaddr_t, int, ipif_t *,
- ire_t **, zoneid_t, int);
+extern ire_t *ire_route_lookup(ipaddr_t, ipaddr_t, ipaddr_t, int,
+ const ipif_t *, ire_t **, zoneid_t, const struct ts_label_s *, int);
extern ire_t *ire_route_lookup_v6(const in6_addr_t *, const in6_addr_t *,
- const in6_addr_t *, int, ipif_t *, ire_t **, zoneid_t, int);
+ const in6_addr_t *, int, const ipif_t *, ire_t **, zoneid_t,
+ const struct ts_label_s *, int);
extern ire_t *ire_srcif_table_lookup(ipaddr_t, int, ipif_t *, ill_t *, int);
-extern ill_t *ire_to_ill(ire_t *);
+extern ill_t *ire_to_ill(const ire_t *);
-extern void ire_walk(pfv_t, char *);
-extern void ire_walk_ill(uint_t, uint_t, pfv_t, char *, ill_t *);
+extern void ire_walk(pfv_t, void *);
+extern void ire_walk_ill(uint_t, uint_t, pfv_t, void *, ill_t *);
extern void ire_walk_ill_mrtun(uint_t, uint_t, pfv_t, void *, ill_t *);
-extern void ire_walk_ill_v4(uint_t, uint_t, pfv_t, char *, ill_t *);
-extern void ire_walk_ill_v6(uint_t, uint_t, pfv_t, char *, ill_t *);
-extern void ire_walk_v4(pfv_t, char *, zoneid_t);
-extern void ire_walk_srcif_table_v4(pfv_t, char *);
-extern void ire_walk_v6(pfv_t, char *, zoneid_t);
+extern void ire_walk_ill_v4(uint_t, uint_t, pfv_t, void *, ill_t *);
+extern void ire_walk_ill_v6(uint_t, uint_t, pfv_t, void *, ill_t *);
+extern void ire_walk_v4(pfv_t, void *, zoneid_t);
+extern void ire_walk_srcif_table_v4(pfv_t, void *);
+extern void ire_walk_v6(pfv_t, void *, zoneid_t);
-extern boolean_t ire_multirt_lookup(ire_t **, ire_t **, uint32_t);
-extern boolean_t ire_multirt_need_resolve(ipaddr_t);
-extern boolean_t ire_multirt_lookup_v6(ire_t **, ire_t **, uint32_t);
-extern boolean_t ire_multirt_need_resolve_v6(const in6_addr_t *);
+extern boolean_t ire_multirt_lookup(ire_t **, ire_t **, uint32_t,
+ const struct ts_label_s *);
+extern boolean_t ire_multirt_need_resolve(ipaddr_t,
+ const struct ts_label_s *);
+extern boolean_t ire_multirt_lookup_v6(ire_t **, ire_t **, uint32_t,
+ const struct ts_label_s *);
+extern boolean_t ire_multirt_need_resolve_v6(const in6_addr_t *,
+ const struct ts_label_s *);
extern ire_t *ipif_lookup_multi_ire(ipif_t *, ipaddr_t);
extern ire_t *ipif_lookup_multi_ire_v6(ipif_t *, const in6_addr_t *);
--- a/usr/src/uts/common/inet/ip_ndp.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip_ndp.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -269,8 +268,8 @@
extern int ndp_sioc_update(ill_t *, lif_nd_req_t *);
extern boolean_t ndp_verify_optlen(nd_opt_hdr_t *, int);
extern void ndp_timer(void *);
-extern void ndp_walk(ill_t *, pfi_t, uchar_t *);
-extern void ndp_walk_impl(ill_t *, pfi_t, uchar_t *, boolean_t);
+extern void ndp_walk(ill_t *, pfi_t, void *);
+extern void ndp_walk_impl(ill_t *, pfi_t, void *, boolean_t);
extern int ndp_add(ill_t *, uchar_t *, const in6_addr_t *,
const in6_addr_t *, const in6_addr_t *,
uint32_t, uint16_t, uint16_t, nce_t **);
--- a/usr/src/uts/common/inet/ip_rts.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ip_rts.h Fri Mar 24 12:29:20 2006 -0800
@@ -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 1992-2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -33,6 +32,13 @@
extern "C" {
#endif
+/*
+ * Maximum number of route security attributes that can be
+ * configured per route destination through the routing
+ * socket message.
+ */
+#define TSOL_RTSA_REQUEST_MAX 1 /* one per route destination */
+
#ifdef _KERNEL
extern void ip_rts_change(int, ipaddr_t, ipaddr_t,
ipaddr_t, ipaddr_t, ipaddr_t, int, int,
@@ -41,21 +47,22 @@
extern void ip_rts_change_v6(int, const in6_addr_t *, const in6_addr_t *,
const in6_addr_t *, const in6_addr_t *, const in6_addr_t *, int, int, int);
-extern void ip_rts_ifmsg(ipif_t *);
+extern void ip_rts_ifmsg(const ipif_t *);
-extern void ip_rts_newaddrmsg(int, int, ipif_t *);
+extern void ip_rts_newaddrmsg(int, int, const ipif_t *);
extern int ip_rts_request(queue_t *, mblk_t *, cred_t *);
extern void ip_rts_rtmsg(int, ire_t *, int);
-extern mblk_t *rts_alloc_msg(int, int, sa_family_t);
+extern mblk_t *rts_alloc_msg(int, int, sa_family_t, uint_t);
-extern size_t rts_data_msg_size(int, sa_family_t);
+extern size_t rts_data_msg_size(int, sa_family_t, uint_t);
extern void rts_fill_msg_v6(int, int, const in6_addr_t *,
const in6_addr_t *, const in6_addr_t *, const in6_addr_t *,
- const in6_addr_t *, const in6_addr_t *, ipif_t *, mblk_t *);
+ const in6_addr_t *, const in6_addr_t *, const ipif_t *, mblk_t *,
+ uint_t, const tsol_gc_t *);
extern size_t rts_header_msg_size(int);
--- a/usr/src/uts/common/inet/ipclassifier.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/ipclassifier.h Fri Mar 24 12:29:20 2006 -0800
@@ -137,30 +137,32 @@
conn_dontroute : 1, /* SO_DONTROUTE state */
conn_loopback : 1, /* SO_LOOPBACK state */
conn_broadcast : 1, /* SO_BROADCAST state */
+
conn_reuseaddr : 1, /* SO_REUSEADDR state */
-
conn_multicast_loop : 1, /* IP_MULTICAST_LOOP */
conn_multi_router : 1, /* Wants all multicast pkts */
conn_draining : 1, /* ip_wsrv running */
+
conn_did_putbq : 1, /* ip_wput did a putbq */
-
conn_unspec_src : 1, /* IP_UNSPEC_SRC */
conn_policy_cached : 1, /* Is policy cached/latched ? */
conn_in_enforce_policy : 1, /* Enforce Policy on inbound */
+
conn_out_enforce_policy : 1, /* Enforce Policy on outbound */
-
conn_af_isv6 : 1, /* ip address family ver 6 */
conn_pkt_isv6 : 1, /* ip packet format ver 6 */
conn_ipv6_recvpktinfo : 1, /* IPV6_RECVPKTINFO option */
+
conn_ipv6_recvhoplimit : 1, /* IPV6_RECVHOPLIMIT option */
-
conn_ipv6_recvhopopts : 1, /* IPV6_RECVHOPOPTS option */
conn_ipv6_recvdstopts : 1, /* IPV6_RECVDSTOPTS option */
conn_ipv6_recvrthdr : 1, /* IPV6_RECVRTHDR option */
+
conn_ipv6_recvrtdstopts : 1, /* IPV6_RECVRTHDRDSTOPTS */
conn_ipv6_v6only : 1, /* IPV6_V6ONLY */
conn_ipv6_recvtclass : 1, /* IPV6_RECVTCLASS */
conn_ipv6_recvpathmtu : 1, /* IPV6_RECVPATHMTU */
+
conn_pathmtu_valid : 1, /* The cached mtu is valid. */
conn_ipv6_dontfrag : 1, /* IPV6_DONTFRAG */
/*
@@ -170,6 +172,7 @@
*/
conn_fully_bound : 1, /* Fully bound connection */
conn_recvif : 1, /* IP_RECVIF option */
+
conn_recvslla : 1, /* IP_RECVSLLA option */
conn_mdt_ok : 1, /* MDT is permitted */
conn_nexthop_set : 1,
@@ -258,6 +261,17 @@
zoneid_t conn_zoneid; /* zone connection is in */
in6_addr_t conn_nexthop_v6; /* nexthop IP address */
#define conn_nexthop_v4 V4_PART_OF_V6(conn_nexthop_v6)
+ cred_t *conn_peercred; /* Peer credentials, if any */
+
+ unsigned int
+ conn_ulp_labeled : 1, /* ULP label is synced */
+ conn_mlp_type : 2, /* mlp_type_t; tsol/tndb.h */
+ conn_anon_mlp : 1, /* user wants anon MLP */
+
+ conn_anon_port : 1, /* user bound anonymously */
+ conn_mac_exempt : 1, /* unlabeled with loose MAC */
+ conn_spare : 26;
+
#ifdef CONN_DEBUG
#define CONN_TRACE_MAX 10
int conn_trace_last; /* ndx of last used tracebuf */
@@ -265,6 +279,11 @@
#endif
};
+#define CONN_CRED(connp) ((connp)->conn_peercred == NULL ? \
+ (connp)->conn_cred : (connp)->conn_peercred)
+#define BEST_CRED(mp, connp) ((DB_CRED(mp) != NULL && \
+ crgetlabel(DB_CRED(mp)) != NULL) ? DB_CRED(mp) : CONN_CRED(connp))
+
/*
* connf_t - connection fanout data.
*
@@ -330,7 +349,7 @@
(((connp)->conn_src == ((ipha)->ipha_dst)) && \
(((connp)->conn_rem == INADDR_ANY) || \
((connp)->conn_rem == ((ipha)->ipha_src))))) && \
- ((connp)->conn_zoneid == (zoneid)) && \
+ ((zoneid) == ALL_ZONES || (connp)->conn_zoneid == (zoneid)) && \
(conn_wantpacket((connp), (ill), (ipha), \
(fanout_flags), (zoneid)) || ((protocol) == IPPROTO_PIM) || \
((protocol) == IPPROTO_RSVP)))
@@ -499,7 +518,7 @@
conn_t *ipcl_classify_v4(mblk_t *, uint8_t, uint_t, zoneid_t);
conn_t *ipcl_classify_v6(mblk_t *, uint8_t, uint_t, zoneid_t);
conn_t *ipcl_classify(mblk_t *, zoneid_t);
-conn_t *ipcl_classify_raw(uint8_t, zoneid_t, uint32_t, ipha_t *);
+conn_t *ipcl_classify_raw(mblk_t *, uint8_t, zoneid_t, uint32_t, ipha_t *);
void ipcl_globalhash_insert(conn_t *);
void ipcl_globalhash_remove(conn_t *);
void ipcl_walk(pfv_t, void *);
--- a/usr/src/uts/common/inet/mib2.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/mib2.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -31,6 +30,8 @@
#pragma ident "%Z%%M% %I% %E% SMI"
#include <netinet/in.h> /* For in6_addr_t */
+#include <sys/tsol/label.h> /* For brange_t */
+#include <sys/tsol/label_macro.h> /* For brange_t */
#ifdef __cplusplus
extern "C" {
@@ -161,6 +162,12 @@
#define EXPER_IP6_GROUP_MEMBERSHIP 101
#define EXPER_IP_GROUP_SOURCES 102
#define EXPER_IP6_GROUP_SOURCES 103
+#define EXPER_IP_RTATTR 104
+
+/*
+ * There can be one of each of these tables per transport (MIB2_* above).
+ */
+#define EXPER_XPORT_MLP 105 /* transportMLPEntry */
/* Old names retained for compatibility */
#define MIB2_IP_20 MIB2_IP_ADDR
@@ -259,6 +266,9 @@
Counter ipOutIPv6;
/* # of times ip_wput has switched to become ip_wput_v6 */
Counter ipOutSwitchIPv6;
+
+ int ipRouteAttributeSize; /* Size of mib2_ipAttributeEntry_t */
+ int transportMLPSize; /* Size of mib2_transportMLPEntry_t */
} mib2_ip_t;
/*
@@ -447,7 +457,6 @@
} ipv6AddrInfo;
} mib2_ipv6AddrEntry_t;
-
/*
* The IP routing table contains an entry for each route presently known to
* this entity. (for IPv4 routes)
@@ -562,6 +571,44 @@
} ipv6RouteInfo;
} mib2_ipv6RouteEntry_t;
+/*
+ * The IPv4 and IPv6 routing table entries on a trusted system also have
+ * security attributes in the form of label ranges. This experimental
+ * interface provides information about these labels.
+ *
+ * Each entry in this table contains a label range and an index that refers
+ * back to the entry in the routing table to which it applies. There may be 0,
+ * 1, or many label ranges for each routing table entry.
+ *
+ * (opthdr.level is set to MIB2_IP for IPv4 entries and MIB2_IP6 for IPv6.
+ * opthdr.name is set to EXPER_IP_GWATTR.)
+ *
+ * ipRouteAttributeTable OBJECT-TYPE
+ * SYNTAX SEQUENCE OF IpAttributeEntry
+ * ACCESS not-accessible
+ * STATUS current
+ * DESCRIPTION
+ * "IPv4 routing attributes table. This table contains
+ * an entry for each valid trusted label attached to a
+ * route in the system."
+ * ::= { ip 102 }
+ *
+ * ipv6RouteAttributeTable OBJECT-TYPE
+ * SYNTAX SEQUENCE OF IpAttributeEntry
+ * ACCESS not-accessible
+ * STATUS current
+ * DESCRIPTION
+ * "IPv6 routing attributes table. This table contains
+ * an entry for each valid trusted label attached to a
+ * route in the system."
+ * ::= { ip6 102 }
+ */
+
+typedef struct mib2_ipAttributeEntry {
+ uint_t iae_routeidx;
+ int iae_doi;
+ brange_t iae_slrange;
+} mib2_ipAttributeEntry_t;
/*
* The IP address translation table contain the IpAddress to
@@ -670,6 +717,26 @@
int ipv6GroupMemberFilterMode;
} ipv6_member_t;
+/*
+ * This is used to mark transport layer entities (e.g., TCP connections) that
+ * are capable of receiving packets from a range of labels. 'level' is set to
+ * the protocol of interest (e.g., MIB2_TCP), and 'name' is set to
+ * EXPER_XPORT_MLP. The tme_connidx refers back to the entry in MIB2_TCP_CONN,
+ * MIB2_TCP6_CONN, or MIB2_SCTP_CONN.
+ *
+ * It is also used to report connections that receive packets at a single label
+ * that's other than the zone's label. This is the case when a TCP connection
+ * is accepted from a particular peer using an MLP listener.
+ */
+typedef struct mib2_transportMLPEntry {
+ uint_t tme_connidx;
+ uint_t tme_flags;
+ int tme_doi;
+ bslabel_t tme_label;
+} mib2_transportMLPEntry_t;
+
+#define MIB2_TMEF_PRIVATE 0x00000001 /* MLP on private addresses */
+#define MIB2_TMEF_SHARED 0x00000002 /* MLP on shared addresses */
/*
* List of IPv4 source addresses being filtered per interface
--- a/usr/src/uts/common/inet/nd.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/nd.h Fri Mar 24 12:29:20 2006 -0800
@@ -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 1992, 1997-2001, 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. */
@@ -31,6 +30,8 @@
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/types.h>
+#include <inet/common.h>
+#include <inet/led.h>
#ifdef __cplusplus
extern "C" {
--- a/usr/src/uts/common/inet/optcom.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/optcom.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -34,15 +33,12 @@
#include <sys/types.h>
#include <sys/stream.h>
#include <sys/stropts.h>
-#include <sys/strlog.h>
#include <sys/strsubr.h>
#include <sys/errno.h>
#define _SUN_TPI_VERSION 2
#include <sys/tihdr.h>
-#include <sys/timod.h>
#include <sys/socket.h>
#include <sys/ddi.h>
-#include <sys/cmn_err.h>
#include <sys/debug.h> /* for ASSERT */
#include <sys/policy.h>
@@ -53,8 +49,6 @@
#include <inet/ip.h>
#include <inet/mib2.h>
#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <netinet/ip_mroute.h>
#include "optcom.h"
#include <inet/optcom.h>
@@ -2229,3 +2223,76 @@
}
return (B_FALSE);
}
+
+/*
+ * This routine appends a pssed in hop-by-hop option to the existing
+ * option (in this case a cipso label encoded in HOPOPT option). The
+ * passed in option is always padded. The 'reservelen' is the
+ * length of reserved data (label). New memory will be allocated if
+ * the current buffer is not large enough. Return failure if memory
+ * can not be allocated.
+ */
+int
+optcom_pkt_set(uchar_t *invalp, uint_t inlen, boolean_t sticky,
+ uchar_t **optbufp, uint_t *optlenp, uint_t reservelen)
+{
+ uchar_t *optbuf;
+ uchar_t *optp;
+
+ if (!sticky) {
+ *optbufp = invalp;
+ *optlenp = inlen;
+ return (0);
+ }
+
+ if (inlen == *optlenp - reservelen) {
+ /* Unchanged length - no need to reallocate */
+ optp = *optbufp + reservelen;
+ bcopy(invalp, optp, inlen);
+ if (reservelen != 0) {
+ /*
+ * Convert the NextHeader and Length of the
+ * passed in hop-by-hop header to pads
+ */
+ optp[0] = IP6OPT_PADN;
+ optp[1] = 0;
+ }
+ return (0);
+ }
+ if (inlen + reservelen > 0) {
+ /* Allocate new buffer before free */
+ optbuf = kmem_alloc(inlen + reservelen, KM_NOSLEEP);
+ if (optbuf == NULL)
+ return (ENOMEM);
+ } else {
+ optbuf = NULL;
+ }
+
+ /* Copy out old reserved data (label) */
+ if (reservelen > 0)
+ bcopy(*optbufp, optbuf, reservelen);
+
+ /* Free old buffer */
+ if (*optlenp != 0)
+ kmem_free(*optbufp, *optlenp);
+
+ if (inlen > 0)
+ bcopy(invalp, optbuf + reservelen, inlen);
+
+ if (reservelen != 0) {
+ /*
+ * Convert the NextHeader and Length of the
+ * passed in hop-by-hop header to pads
+ */
+ optbuf[reservelen] = IP6OPT_PADN;
+ optbuf[reservelen + 1] = 0;
+ /*
+ * Set the Length of the hop-by-hop header, number of 8
+ * byte-words following the 1st 8 bytes
+ */
+ optbuf[1] = (reservelen + inlen - 1) >> 3;
+ }
+ *optbufp = optbuf;
+ *optlenp = inlen + reservelen;
+ return (0);
+}
--- a/usr/src/uts/common/inet/optcom.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/optcom.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -225,6 +224,8 @@
extern int tpi_optcom_buf(queue_t *, mblk_t *, t_scalar_t *, t_scalar_t,
cred_t *, optdb_obj_t *, void *, int *);
extern t_uscalar_t optcom_max_optsize(opdes_t *, uint_t);
+extern int optcom_pkt_set(uchar_t *, uint_t, boolean_t, uchar_t **, uint_t *,
+ uint_t);
#endif /* defined(_KERNEL) && defined(__STDC__) */
--- a/usr/src/uts/common/inet/rawip_impl.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/rawip_impl.h Fri Mar 24 12:29:20 2006 -0800
@@ -98,8 +98,9 @@
icmp_ipv6_recvrtdstopts : 1, /* Obsolete IPV6_RECVRTHDRDSTOPTS */
icmp_old_ipv6_recvdstopts : 1, /* Old ver of IPV6_RECVDSTOPTS */
icmp_timestamp : 1, /* SO_TIMESTAMP "socket" option */
+ icmp_mac_exempt : 1, /* SO_MAC_EXEMPT option */
- icmp_pad_to_bit_31: 8;
+ icmp_pad_to_bit_31: 7;
uint8_t icmp_type_of_service;
uint8_t icmp_ttl; /* TTL or hoplimit */
@@ -111,6 +112,10 @@
uint8_t *icmp_sticky_hdrs; /* Prebuilt IPv6 hdrs */
uint_t icmp_sticky_hdrs_len; /* Incl. ip6h and any ip6i */
zoneid_t icmp_zoneid; /* ID of owning zone */
+ uint_t icmp_label_len; /* length of security label */
+ uint_t icmp_label_len_v6; /* sec. part of sticky opt */
+ in6_addr_t icmp_v6lastdst; /* most recent destination */
+ mblk_t *icmp_delabel; /* send this on close */
} icmp_t;
#endif /* _KERNEL */
--- a/usr/src/uts/common/inet/sctp/sctp.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/sctp/sctp.c Fri Mar 24 12:29:20 2006 -0800
@@ -42,6 +42,7 @@
#include <sys/kmem.h>
#include <sys/cpuvar.h>
#include <sys/random.h>
+#include <sys/priv.h>
#include <sys/errno.h>
#include <sys/signal.h>
@@ -80,7 +81,6 @@
static void sctp_closei_local(sctp_t *sctp);
static int sctp_init_values(sctp_t *, sctp_t *, int);
-void sctp_display_all();
static void sctp_icmp_error_ipv6(sctp_t *sctp, mblk_t *mp);
static void sctp_process_recvq(void *);
static void sctp_rq_tq_init(void);
@@ -89,7 +89,6 @@
static void sctp_conn_cache_fini();
static int sctp_conn_cache_constructor();
static void sctp_conn_cache_destructor();
-void sctp_inc_taskq(void);
/*
* SCTP receive queue taskq
@@ -192,9 +191,13 @@
sctp_t *sctp;
mblk_t *ack_mp, *hb_mp;
conn_t *connp, *pconnp;
+ cred_t *credp;
if ((connp = ipcl_conn_create(IPCL_SCTPCONN, KM_NOSLEEP)) == NULL)
return (NULL);
+
+ connp->conn_ulp_labeled = is_system_labeled();
+
sctp = CONN2SCTP(connp);
if ((ack_mp = sctp_timer_alloc(sctp, sctp_ack_timer)) == NULL ||
@@ -221,9 +224,20 @@
kmem_cache_free(sctp_conn_cache, connp);
return (NULL);
}
- if (pconnp->conn_cred != NULL) {
- connp->conn_cred = pconnp->conn_cred;
- crhold(connp->conn_cred);
+
+ /*
+ * If the parent is multilevel, then we'll fix up the remote cred
+ * when we do sctp_accept_comm.
+ */
+ if ((credp = pconnp->conn_cred) != NULL) {
+ connp->conn_cred = credp;
+ crhold(credp);
+ /*
+ * If the caller has the process-wide flag set, then default to
+ * MAC exempt mode. This allows read-down to unlabeled hosts.
+ */
+ if (getpflags(NET_MAC_AWARE, credp) != 0)
+ connp->conn_mac_exempt = B_TRUE;
}
connp->conn_zoneid = psctp->sctp_zoneid;
sctp->sctp_mss = psctp->sctp_mss;
@@ -250,7 +264,8 @@
(sctp->sctp_ipversion == IPV4_VERSION ||
sctp->sctp_ipversion == IPV6_VERSION)));
- dprint(3, ("sctp_clean_death %p, state %d\n", sctp, sctp->sctp_state));
+ dprint(3, ("sctp_clean_death %p, state %d\n", (void *)sctp,
+ sctp->sctp_state));
sctp->sctp_client_errno = err;
/*
@@ -311,7 +326,8 @@
int error = 0;
sctp_faddr_t *fp;
- dprint(3, ("sctp_disconnect %p, state %d\n", sctp, sctp->sctp_state));
+ dprint(3, ("sctp_disconnect %p, state %d\n", (void *)sctp,
+ sctp->sctp_state));
RUN_SCTP(sctp);
@@ -421,7 +437,8 @@
void
sctp_close(sctp_t *sctp)
{
- dprint(3, ("sctp_close %p, state %d\n", sctp, sctp->sctp_state));
+ dprint(3, ("sctp_close %p, state %d\n", (void *)sctp,
+ sctp->sctp_state));
RUN_SCTP(sctp);
sctp->sctp_detached = 1;
@@ -630,7 +647,6 @@
sctp_free(conn_t *connp)
{
sctp_t *sctp = CONN2SCTP(connp);
- ip6_pkt_t *ipp;
int cnt;
/* Unlink it from the global list */
@@ -692,26 +708,7 @@
list_destroy(&sctp->sctp_saddrs[cnt].sctp_ipif_list);
}
- ipp = &sctp->sctp_sticky_ipp;
- if (ipp->ipp_rthdrlen != 0) {
- kmem_free(ipp->ipp_rthdr, ipp->ipp_rthdrlen);
- ipp->ipp_rthdrlen = 0;
- }
-
- if (ipp->ipp_dstoptslen != 0) {
- kmem_free(ipp->ipp_dstopts, ipp->ipp_dstoptslen);
- ipp->ipp_dstoptslen = 0;
- }
-
- if (ipp->ipp_rtdstoptslen != 0) {
- kmem_free(ipp->ipp_rtdstopts, ipp->ipp_rtdstoptslen);
- ipp->ipp_rtdstoptslen = 0;
- }
-
- if (ipp->ipp_hopoptslen != 0) {
- kmem_free(ipp->ipp_hopopts, ipp->ipp_hopoptslen);
- ipp->ipp_hopoptslen = 0;
- }
+ ip6_pkt_free(&sctp->sctp_sticky_ipp);
if (sctp->sctp_hopopts != NULL) {
mi_free(sctp->sctp_hopopts);
@@ -1062,7 +1059,8 @@
in6_addr_t dst;
sctp_faddr_t *fp;
- dprint(1, ("sctp_icmp_error: sctp=%p, mp=%p\n", sctp, mp));
+ dprint(1, ("sctp_icmp_error: sctp=%p, mp=%p\n", (void *)sctp,
+ (void *)mp));
first_mp = mp;
@@ -1302,6 +1300,9 @@
if ((sctp_connp = ipcl_conn_create(IPCL_SCTPCONN, sleep)) == NULL)
return (NULL);
+
+ sctp_connp->conn_ulp_labeled = is_system_labeled();
+
psctp = (sctp_t *)parent;
sctp = CONN2SCTP(sctp_connp);
@@ -1378,6 +1379,13 @@
sctp_connp->conn_cred = credp;
crhold(credp);
+ /*
+ * If the caller has the process-wide flag set, then default to MAC
+ * exempt mode. This allows read-down to unlabeled hosts.
+ */
+ if (getpflags(NET_MAC_AWARE, credp) != 0)
+ sctp_connp->conn_mac_exempt = B_TRUE;
+
/* Initialize SCTP instance values, our verf tag must never be 0 */
(void) random_get_pseudo_bytes((uint8_t *)&sctp->sctp_lvtag,
sizeof (sctp->sctp_lvtag));
--- a/usr/src/uts/common/inet/sctp/sctp_addr.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/sctp/sctp_addr.c Fri Mar 24 12:29:20 2006 -0800
@@ -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,6 +174,7 @@
int j;
sctp_ipif_t *sctp_ipif;
+ ASSERT(zoneid != ALL_ZONES);
rw_enter(&sctp_g_ipifs_lock, RW_READER);
for (i = 0; i < SCTP_IPIF_HASH; i++) {
if (sctp_g_ipifs[i].ipif_count == 0)
@@ -182,7 +182,8 @@
sctp_ipif = list_head(&sctp_g_ipifs[i].sctp_ipif_list);
for (j = 0; j < sctp_g_ipifs[i].ipif_count; j++) {
rw_enter(&sctp_ipif->sctp_ipif_lock, RW_READER);
- if (zoneid == sctp_ipif->sctp_ipif_zoneid &&
+ if ((zoneid == sctp_ipif->sctp_ipif_zoneid ||
+ sctp_ipif->sctp_ipif_zoneid == ALL_ZONES) &&
SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state) &&
(ifindex == 0 || ifindex ==
sctp_ipif->sctp_ipif_ill->sctp_ill_index) &&
@@ -225,7 +226,8 @@
rw_enter(&sctp_ipif->sctp_ipif_lock, RW_READER);
if (SCTP_IPIF_DISCARD(sctp_ipif->sctp_ipif_flags) ||
!SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state) ||
- sctp_ipif->sctp_ipif_zoneid != sctp->sctp_zoneid ||
+ (sctp_ipif->sctp_ipif_zoneid != ALL_ZONES &&
+ sctp_ipif->sctp_ipif_zoneid != sctp->sctp_zoneid) ||
(sctp->sctp_ipversion == IPV4_VERSION &&
sctp_ipif->sctp_ipif_isv6) ||
(sctp->sctp_connp->conn_ipv6_v6only &&
--- a/usr/src/uts/common/inet/sctp/sctp_asconf.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/sctp/sctp_asconf.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -1138,28 +1137,23 @@
uint16_t type;
mblk_t *mp;
sctp_faddr_t *nfp;
- sctp_parm_hdr_t *oph;
+ sctp_parm_hdr_t *oph = ph;
+ int err;
*cont = 1;
/* Send back an authorization error if addip is disabled */
if (!sctp_addip_enabled) {
- mp = sctp_asconf_adderr(SCTP_ERR_UNAUTHORIZED, ph, cid);
- if (mp == NULL)
- *cont = -1;
- return (mp);
+ err = SCTP_ERR_UNAUTHORIZED;
+ goto error_handler;
}
/* Check input */
if (ntohs(ph->sph_len) < (sizeof (*ph) * 2)) {
- mp = sctp_asconf_adderr(SCTP_ERR_BAD_MANDPARM, ph, cid);
- if (mp == NULL) {
- *cont = -1;
- }
- return (mp);
+ err = SCTP_ERR_BAD_MANDPARM;
+ goto error_handler;
}
type = ntohs(ph->sph_type);
- oph = ph;
ph = (sctp_parm_hdr_t *)((char *)ph + sizeof (sctp_parm_hdr_t) +
sizeof (cid));
mp = sctp_check_addip_addr(ph, oph, cont, cid, &addr);
@@ -1172,12 +1166,8 @@
/* Address is already part of association */
dprint(1, ("addip: addr already here: %x:%x:%x:%x\n",
SCTP_PRINTADDR(addr)));
- mp = sctp_asconf_adderr(SCTP_ERR_BAD_MANDPARM, oph,
- cid);
- if (mp == NULL) {
- *cont = -1;
- }
- return (mp);
+ err = SCTP_ERR_BAD_MANDPARM;
+ goto error_handler;
}
if (!act) {
@@ -1185,13 +1175,17 @@
}
/* Add the new address */
mutex_enter(&sctp->sctp_conn_tfp->tf_lock);
- if (sctp_add_faddr(sctp, &addr, KM_NOSLEEP) != 0) {
- mutex_exit(&sctp->sctp_conn_tfp->tf_lock);
+ err = sctp_add_faddr(sctp, &addr, KM_NOSLEEP);
+ mutex_exit(&sctp->sctp_conn_tfp->tf_lock);
+ if (err == ENOMEM) {
/* no memory */
*cont = -1;
return (NULL);
}
- mutex_exit(&sctp->sctp_conn_tfp->tf_lock);
+ if (err != 0) {
+ err = SCTP_ERR_BAD_MANDPARM;
+ goto error_handler;
+ }
sctp_intf_event(sctp, addr, SCTP_ADDR_ADDED, 0);
} else if (type == PARM_DEL_IP) {
nfp = sctp_lookup_faddr(sctp, &addr);
@@ -1202,34 +1196,22 @@
*/
dprint(1, ("delip: addr not here: %x:%x:%x:%x\n",
SCTP_PRINTADDR(addr)));
- mp = sctp_asconf_adderr(SCTP_ERR_BAD_MANDPARM, oph,
- cid);
- if (mp == NULL) {
- *cont = -1;
- }
- return (mp);
+ err = SCTP_ERR_BAD_MANDPARM;
+ goto error_handler;
}
if (sctp->sctp_faddrs == nfp && nfp->next == NULL) {
/* Peer is trying to delete last address */
dprint(1, ("delip: del last addr: %x:%x:%x:%x\n",
SCTP_PRINTADDR(addr)));
- mp = sctp_asconf_adderr(SCTP_ERR_DEL_LAST_ADDR, oph,
- cid);
- if (mp == NULL) {
- *cont = -1;
- }
- return (mp);
+ err = SCTP_ERR_DEL_LAST_ADDR;
+ goto error_handler;
}
if (nfp == fp) {
/* Peer is trying to delete source address */
dprint(1, ("delip: del src addr: %x:%x:%x:%x\n",
SCTP_PRINTADDR(addr)));
- mp = sctp_asconf_adderr(SCTP_ERR_DEL_SRC_ADDR, oph,
- cid);
- if (mp == NULL) {
- *cont = -1;
- }
- return (mp);
+ err = SCTP_ERR_DEL_SRC_ADDR;
+ goto error_handler;
}
if (!act) {
return (NULL);
@@ -1267,6 +1249,12 @@
/* Successful, don't need to return anything. */
return (NULL);
+
+error_handler:
+ mp = sctp_asconf_adderr(err, oph, cid);
+ if (mp == NULL)
+ *cont = -1;
+ return (mp);
}
/*
--- a/usr/src/uts/common/inet/sctp/sctp_asconf.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/sctp/sctp_asconf.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -40,8 +39,8 @@
if ((fp)->rc_timer_mp != NULL) { \
((sctpt_t *)((fp)->rc_timer_mp->b_rptr))->sctpt_faddr = fp; \
dprint(3, ("faddr_rc_timer_restart: fp=%p %x:%x:%x:%x %d\n", \
- (fp), SCTP_PRINTADDR((fp)->faddr), \
- (int)(intvl))); \
+ (void *)(fp), SCTP_PRINTADDR((fp)->faddr), \
+ (int)(intvl))); \
sctp_timer((sctp), (fp)->rc_timer_mp, (intvl)); \
(fp)->rc_timer_running = 1; \
}
--- a/usr/src/uts/common/inet/sctp/sctp_bind.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/sctp/sctp_bind.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -37,6 +36,8 @@
#include <sys/socket.h>
#include <sys/random.h>
#include <sys/policy.h>
+#include <sys/tsol/tndb.h>
+#include <sys/tsol/tnet.h>
#include <netinet/in.h>
#include <netinet/ip6.h>
@@ -66,7 +67,10 @@
* the same port.
*/
if (*requested_port == 0) {
- *requested_port = sctp_update_next_port(sctp_next_port_to_try);
+ *requested_port = sctp_update_next_port(sctp_next_port_to_try,
+ crgetzone(sctp->sctp_credp));
+ if (*requested_port == 0)
+ return (EACCES);
*user_specified = 0;
} else {
int i;
@@ -101,7 +105,7 @@
dprint(1,
("sctp_bind(x): no prive for port %d",
*requested_port));
- return (TACCES);
+ return (EACCES);
}
}
*user_specified = 1;
@@ -201,28 +205,21 @@
}
bind_to_req_port_only = requested_port == 0 ? B_FALSE : B_TRUE;
- if (sctp_select_port(sctp, &requested_port, &user_specified) != 0) {
- err = EPERM;
+ err = sctp_select_port(sctp, &requested_port, &user_specified);
+ if (err != 0)
goto done;
- }
if ((err = sctp_bind_add(sctp, sa, 1, B_TRUE,
user_specified == 1 ? htons(requested_port) : 0)) != 0) {
goto done;
}
- allocated_port = sctp_bindi(sctp, requested_port,
- bind_to_req_port_only, user_specified);
- if (allocated_port == 0) {
+ err = sctp_bindi(sctp, requested_port, bind_to_req_port_only,
+ user_specified, &allocated_port);
+ if (err != 0) {
sctp_free_saddrs(sctp);
- if (bind_to_req_port_only) {
- err = EADDRINUSE;
- goto done;
- } else {
- err = EADDRNOTAVAIL;
- goto done;
- }
+ } else {
+ ASSERT(sctp->sctp_state == SCTPS_BOUND);
}
- ASSERT(sctp->sctp_state == SCTPS_BOUND);
done:
WAKE_SCTP(sctp);
return (err);
@@ -438,26 +435,30 @@
}
/*
- * If the "bind_to_req_port_only" parameter is set, if the requested port
- * number is available, return it, If not return 0
+ * Returns 0 for success, errno value otherwise.
+ *
+ * If the "bind_to_req_port_only" parameter is set and the requested port
+ * number is available, then set allocated_port to it. If not available,
+ * return an error.
*
- * If "bind_to_req_port_only" parameter is not set and
- * If the requested port number is available, return it. If not, return
- * the first anonymous port we happen across. If no anonymous ports are
- * available, return 0. addr is the requested local address, if any.
+ * If the "bind_to_req_port_only" parameter is not set and the requested port
+ * number is available, then set allocated_port to it. If not available,
+ * find the first anonymous port we can and set allocated_port to that. If no
+ * anonymous ports are available, return an error.
*
- * In either case, when succeeding update the sctp_t to record the port number
+ * In either case, when succeeding, update the sctp_t to record the port number
* and insert it in the bind hash table.
*/
-in_port_t
-sctp_bindi(sctp_t *sctp, in_port_t port, int bind_to_req_port_only,
- int user_specified)
+int
+sctp_bindi(sctp_t *sctp, in_port_t port, boolean_t bind_to_req_port_only,
+ int user_specified, in_port_t *allocated_port)
{
/* number of times we have run around the loop */
int count = 0;
/* maximum number of times to run around the loop */
int loopmax;
zoneid_t zoneid = sctp->sctp_zoneid;
+ zone_t *zone = crgetzone(sctp->sctp_credp);
/*
* Lookup for free addresses is done in a loop and "loopmax"
@@ -507,10 +508,19 @@
lsctp = lsctp->sctp_bind_hash) {
if (lport != lsctp->sctp_lport ||
- lsctp->sctp_zoneid != zoneid ||
lsctp->sctp_state < SCTPS_BOUND)
continue;
+ /*
+ * On a labeled system, we must treat bindings to ports
+ * on shared IP addresses by sockets with MAC exemption
+ * privilege as being in all zones, as there's
+ * otherwise no way to identify the right receiver.
+ */
+ if (lsctp->sctp_zoneid != zoneid &&
+ !lsctp->sctp_mac_exempt && !sctp->sctp_mac_exempt)
+ continue;
+
addrcmp = sctp_compare_saddrs(sctp, lsctp);
if (addrcmp != SCTP_ADDR_DISJOINT) {
if (!sctp->sctp_reuseaddr) {
@@ -535,6 +545,61 @@
/* The port number is busy */
mutex_exit(&tbf->tf_lock);
} else {
+ conn_t *connp = sctp->sctp_connp;
+
+ if (is_system_labeled()) {
+ mlp_type_t addrtype, mlptype;
+
+ /*
+ * On a labeled system we must check the type
+ * of the binding requested by the user (either
+ * MLP or SLP on shared and private addresses),
+ * and that the user's requested binding
+ * is permitted.
+ */
+ addrtype = tsol_mlp_addr_type(zone->zone_id,
+ sctp->sctp_ipversion,
+ sctp->sctp_ipversion == IPV4_VERSION ?
+ (void *)&sctp->sctp_ipha->ipha_src :
+ (void *)&sctp->sctp_ip6h->ip6_src);
+
+ /*
+ * tsol_mlp_addr_type returns the possibilities
+ * for the selected address. Since all local
+ * addresses are either private or shared, the
+ * return value mlptSingle means "local address
+ * not valid (interface not present)."
+ */
+ if (addrtype == mlptSingle) {
+ mutex_exit(&tbf->tf_lock);
+ return (EADDRNOTAVAIL);
+ }
+ mlptype = tsol_mlp_port_type(zone, IPPROTO_SCTP,
+ port, addrtype);
+ if (mlptype != mlptSingle) {
+ if (secpolicy_net_bindmlp(connp->
+ conn_cred) != 0) {
+ mutex_exit(&tbf->tf_lock);
+ return (EACCES);
+ }
+ /*
+ * If we're binding a shared MLP, then
+ * make sure that this zone is the one
+ * that owns that MLP. Shared MLPs can
+ * be owned by at most one zone.
+ */
+
+ if (mlptype == mlptShared &&
+ addrtype == mlptShared &&
+ connp->conn_zoneid !=
+ tsol_mlp_findzone(IPPROTO_SCTP,
+ lport)) {
+ mutex_exit(&tbf->tf_lock);
+ return (EACCES);
+ }
+ connp->conn_mlp_type = mlptype;
+ }
+ }
/*
* This port is ours. Insert in fanout and mark as
* bound to prevent others from getting the port
@@ -542,7 +607,7 @@
*/
sctp->sctp_state = SCTPS_BOUND;
sctp->sctp_lport = lport;
- sctp->sctp_sctph->sh_sport = sctp->sctp_lport;
+ sctp->sctp_sctph->sh_sport = lport;
ASSERT(&sctp_bind_fanout[SCTP_BIND_HASH(port)] == tbf);
sctp_bind_hash_insert(tbf, sctp, 1);
@@ -552,17 +617,17 @@
/*
* We don't want sctp_next_port_to_try to "inherit"
* a port number supplied by the user in a bind.
- */
- if (user_specified != 0)
- return (port);
-
- /*
+ *
* This is the only place where sctp_next_port_to_try
* is updated. After the update, it may or may not
* be in the valid range.
*/
- sctp_next_port_to_try = port + 1;
- return (port);
+ if (user_specified == 0)
+ sctp_next_port_to_try = port + 1;
+
+ *allocated_port = port;
+
+ return (0);
}
if ((count == 0) && (user_specified)) {
@@ -570,18 +635,22 @@
* We may have to return an anonymous port. So
* get one to start with.
*/
- port = sctp_update_next_port(sctp_next_port_to_try);
+ port = sctp_update_next_port(sctp_next_port_to_try,
+ zone);
user_specified = 0;
} else {
- port = sctp_update_next_port(port + 1);
+ port = sctp_update_next_port(port + 1, zone);
}
+ if (port == 0)
+ break;
/*
* Don't let this loop run forever in the case where
* all of the anonymous ports are in use.
*/
} while (++count < loopmax);
- return (0);
+
+ return (bind_to_req_port_only ? EADDRINUSE : EADDRNOTAVAIL);
}
/*
@@ -597,14 +666,22 @@
* - the atomic assignment of the elements of the array
*/
in_port_t
-sctp_update_next_port(in_port_t port)
+sctp_update_next_port(in_port_t port, zone_t *zone)
{
int i;
+ boolean_t restart = B_FALSE;
retry:
- if (port < sctp_smallest_anon_port || port > sctp_largest_anon_port)
+ if (port < sctp_smallest_anon_port)
port = sctp_smallest_anon_port;
+ if (port > sctp_largest_anon_port) {
+ if (restart)
+ return (0);
+ restart = B_TRUE;
+ port = sctp_smallest_anon_port;
+ }
+
if (port < sctp_smallest_nonpriv_port)
port = sctp_smallest_nonpriv_port;
@@ -622,5 +699,12 @@
goto retry;
}
}
+
+ if (is_system_labeled() &&
+ (i = tsol_next_port(zone, port, IPPROTO_SCTP, B_TRUE)) != 0) {
+ port = i;
+ goto retry;
+ }
+
return (port);
}
--- a/usr/src/uts/common/inet/sctp/sctp_common.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/sctp/sctp_common.c Fri Mar 24 12:29:20 2006 -0800
@@ -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,11 +28,14 @@
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/stream.h>
+#include <sys/strsubr.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/kmem.h>
#include <sys/socket.h>
#include <sys/random.h>
+#include <sys/tsol/tndb.h>
+#include <sys/tsol/tnet.h>
#include <netinet/in.h>
#include <netinet/ip6.h>
@@ -43,12 +45,12 @@
#include <inet/ip.h>
#include <inet/ip6.h>
#include <inet/ip_ire.h>
-#include <inet/mi.h>
#include <inet/mib2.h>
#include <inet/nd.h>
#include <inet/optcom.h>
#include <inet/sctp_ip.h>
#include <inet/ipclassifier.h>
+
#include "sctp_impl.h"
#include "sctp_addr.h"
@@ -86,6 +88,7 @@
sctp_saddr_ipif_t *sp;
uint_t ipif_seqid;
int hdrlen;
+ ts_label_t *tsl;
/* Remove the previous cache IRE */
if ((ire = fp->ire) != NULL) {
@@ -102,76 +105,63 @@
fp->state = SCTP_FADDRS_UNCONFIRMED;
}
+ tsl = crgetlabel(CONN_CRED(sctp->sctp_connp));
+
if (fp->isv4) {
IN6_V4MAPPED_TO_IPADDR(&fp->faddr, addr4);
+ ire = ire_cache_lookup(addr4, sctp->sctp_zoneid, tsl);
+ if (ire != NULL)
+ IN6_IPADDR_TO_V4MAPPED(ire->ire_src_addr, &laddr);
+ } else {
+ ire = ire_cache_lookup_v6(&fp->faddr, sctp->sctp_zoneid, tsl);
+ if (ire != NULL)
+ laddr = ire->ire_src_addr_v6;
+ }
- ire = ire_cache_lookup(addr4, sctp->sctp_zoneid);
- if (ire == NULL) {
- dprint(3, ("ire2faddr: no ire for %x:%x:%x:%x\n",
- SCTP_PRINTADDR(fp->faddr)));
- /*
- * It is tempting to just leave the src addr
- * unspecified and let IP figure it out, but we
- * *cannot* do this, since IP may choose a src addr
- * that is not part of this association... unless
- * this sctp has bound to all addrs. So if the ire
- * lookup fails, try to find one in our src addr
- * list, unless the sctp has bound to all addrs, in
- * which case we change the src addr to unspec.
- *
- * Note that if this is a v6 endpoint but it does
- * not have any v4 address at this point (e.g. may
- * have been deleted), sctp_get_valid_addr() will
- * return mapped INADDR_ANY. In this case, this
- * address should be marked not reachable so that
- * it won't be used to send data.
- */
- set_saddr(sctp, fp, B_FALSE);
- goto set_current;
- }
- ipif_seqid = ire->ire_ipif->ipif_seqid;
- dprint(2, ("ire2faddr: got ire for %x:%x:%x:%x, ",
- SCTP_PRINTADDR(fp->faddr)));
+ if (ire == NULL) {
+ dprint(3, ("ire2faddr: no ire for %x:%x:%x:%x\n",
+ SCTP_PRINTADDR(fp->faddr)));
+ /*
+ * It is tempting to just leave the src addr
+ * unspecified and let IP figure it out, but we
+ * *cannot* do this, since IP may choose a src addr
+ * that is not part of this association... unless
+ * this sctp has bound to all addrs. So if the ire
+ * lookup fails, try to find one in our src addr
+ * list, unless the sctp has bound to all addrs, in
+ * which case we change the src addr to unspec.
+ *
+ * Note that if this is a v6 endpoint but it does
+ * not have any v4 address at this point (e.g. may
+ * have been deleted), sctp_get_valid_addr() will
+ * return mapped INADDR_ANY. In this case, this
+ * address should be marked not reachable so that
+ * it won't be used to send data.
+ */
+ set_saddr(sctp, fp, B_FALSE);
+ goto set_current;
+ }
+
+ ipif_seqid = ire->ire_ipif->ipif_seqid;
+ dprint(2, ("ire2faddr: got ire for %x:%x:%x:%x, ",
+ SCTP_PRINTADDR(fp->faddr)));
+ if (fp->isv4) {
dprint(2, ("src = %x\n", ire->ire_src_addr));
- IN6_IPADDR_TO_V4MAPPED(ire->ire_src_addr, &laddr);
-
- /* make sure the laddr is part of this association */
- if ((sp = sctp_ipif_lookup(sctp, ipif_seqid)) !=
- NULL && !sp->saddr_ipif_dontsrc) {
- if (sp->saddr_ipif_unconfirmed == 1)
- sp->saddr_ipif_unconfirmed = 0;
- fp->saddr = laddr;
- } else {
- ip2dbg(("ire2faddr: src addr is not part of assc\n"));
- set_saddr(sctp, fp, B_FALSE);
- }
} else {
- ire = ire_cache_lookup_v6(&fp->faddr, sctp->sctp_zoneid);
- if (ire == NULL) {
- dprint(3, ("ire2faddr: no ire for %x:%x:%x:%x\n",
- SCTP_PRINTADDR(fp->faddr)));
- set_saddr(sctp, fp, B_TRUE);
- goto set_current;
- }
- ipif_seqid = ire->ire_ipif->ipif_seqid;
- dprint(2, ("ire2faddr: got ire for %x:%x:%x:%x, ",
- SCTP_PRINTADDR(fp->faddr)));
dprint(2, ("src=%x:%x:%x:%x\n",
SCTP_PRINTADDR(ire->ire_src_addr_v6)));
- laddr = ire->ire_src_addr_v6;
-
- /* make sure the laddr is part of this association */
+ }
- if ((sp = sctp_ipif_lookup(sctp, ipif_seqid)) !=
- NULL && !sp->saddr_ipif_dontsrc) {
- if (sp->saddr_ipif_unconfirmed == 1)
- sp->saddr_ipif_unconfirmed = 0;
- fp->saddr = laddr;
- } else {
- dprint(2, ("ire2faddr: src addr is not part "
- "of assc\n"));
- set_saddr(sctp, fp, B_TRUE);
- }
+ /* make sure the laddr is part of this association */
+ if ((sp = sctp_ipif_lookup(sctp, ipif_seqid)) != NULL &&
+ !sp->saddr_ipif_dontsrc) {
+ if (sp->saddr_ipif_unconfirmed == 1)
+ sp->saddr_ipif_unconfirmed = 0;
+ fp->saddr = laddr;
+ } else {
+ dprint(2, ("ire2faddr: src addr is not part of assc\n"));
+ /* set the src to the first saddr and hope for the best */
+ set_saddr(sctp, fp, B_TRUE);
}
/* Cache the IRE */
@@ -227,7 +217,6 @@
}
}
-/*ARGSUSED*/
void
sctp_faddr2ire(sctp_t *sctp, sctp_faddr_t *fp)
{
@@ -239,7 +228,7 @@
mutex_enter(&ire->ire_lock);
- /* If the cached IRE is going sway, there is no point to update it. */
+ /* If the cached IRE is going away, there is no point to update it. */
if (ire->ire_marks & IRE_MARK_CONDEMNED) {
mutex_exit(&ire->ire_lock);
IRE_REFRELE_NOTR(ire);
@@ -322,9 +311,10 @@
ipsctplen = sctp->sctp_hdr6_len;
}
- mp = allocb(ipsctplen + sctp_wroff_xtra + trailer, BPRI_MED);
+ mp = allocb_cred(ipsctplen + sctp_wroff_xtra + trailer,
+ CONN_CRED(sctp->sctp_connp));
if (mp == NULL) {
- ip1dbg(("sctp_make_mp: error makign mp..\n"));
+ ip1dbg(("sctp_make_mp: error making mp..\n"));
return (NULL);
}
mp->b_rptr += sctp_wroff_xtra;
@@ -470,66 +460,114 @@
}
/*
- * Returns 0 on success, -1 on memory allocation failure. If sleep
- * is true, should never fail.
* Caller must hold conn fanout lock.
*/
-int
-sctp_add_faddr(sctp_t *sctp, in6_addr_t *addr, int sleep)
+static int
+sctp_add_faddr_entry(sctp_t *sctp, in6_addr_t *addr, int sleep,
+ boolean_t first)
{
sctp_faddr_t *faddr;
- dprint(4, ("add_faddr: %x:%x:%x:%x %d\n", SCTP_PRINTADDR(*addr),
- sleep));
+ if (is_system_labeled()) {
+ ts_label_t *tsl;
+ tsol_tpc_t *rhtp;
+ int retv;
+
+ tsl = crgetlabel(CONN_CRED(sctp->sctp_connp));
+ ASSERT(tsl != NULL);
+
+ /* find_tpc automatically does the right thing with IPv4 */
+ rhtp = find_tpc(addr, IPV6_VERSION, B_FALSE);
+ if (rhtp == NULL)
+ return (EACCES);
- if ((faddr = kmem_cache_alloc(sctp_kmem_faddr_cache, sleep)) == NULL) {
- return (-1);
+ retv = EACCES;
+ if (tsl->tsl_doi == rhtp->tpc_tp.tp_doi) {
+ switch (rhtp->tpc_tp.host_type) {
+ case UNLABELED:
+ /*
+ * Can talk to unlabeled hosts if any of the
+ * following are true:
+ * 1. zone's label matches the remote host's
+ * default label,
+ * 2. mac_exempt is on and the zone dominates
+ * the remote host's label, or
+ * 3. mac_exempt is on and the socket is from
+ * the global zone.
+ */
+ if (blequal(&rhtp->tpc_tp.tp_def_label,
+ &tsl->tsl_label) ||
+ (sctp->sctp_mac_exempt &&
+ (sctp->sctp_zoneid == GLOBAL_ZONEID ||
+ bldominates(&tsl->tsl_label,
+ &rhtp->tpc_tp.tp_def_label))))
+ retv = 0;
+ break;
+ case SUN_CIPSO:
+ if (_blinrange(&tsl->tsl_label,
+ &rhtp->tpc_tp.tp_sl_range_cipso) ||
+ blinlset(&tsl->tsl_label,
+ rhtp->tpc_tp.tp_sl_set_cipso))
+ retv = 0;
+ break;
+ }
+ }
+ TPC_RELE(rhtp);
+ if (retv != 0)
+ return (retv);
}
+ if ((faddr = kmem_cache_alloc(sctp_kmem_faddr_cache, sleep)) == NULL)
+ return (ENOMEM);
+
sctp_init_faddr(sctp, faddr, addr);
ASSERT(faddr->next == NULL);
- /* tack it on to the end */
- if (sctp->sctp_lastfaddr != NULL) {
- sctp->sctp_lastfaddr->next = faddr;
+ if (sctp->sctp_faddrs == NULL) {
+ ASSERT(sctp->sctp_lastfaddr == NULL);
+ /* only element on list; first and last are same */
+ sctp->sctp_faddrs = sctp->sctp_lastfaddr = faddr;
+ } else if (first) {
+ ASSERT(sctp->sctp_lastfaddr != NULL);
+ faddr->next = sctp->sctp_faddrs;
+ sctp->sctp_faddrs = faddr;
} else {
- /* list is empty */
- ASSERT(sctp->sctp_faddrs == NULL);
- sctp->sctp_faddrs = faddr;
+ sctp->sctp_lastfaddr->next = faddr;
+ sctp->sctp_lastfaddr = faddr;
}
- sctp->sctp_lastfaddr = faddr;
sctp->sctp_nfaddrs++;
return (0);
}
/*
+ * Add new address to end of list.
+ * Returns 0 on success, or errno on failure:
+ * ENOMEM - allocation failure; only for sleep==KM_NOSLEEP
+ * EACCES - label is incompatible with caller or connection
+ * (labeled [trusted] solaris only)
+ * Caller must hold conn fanout lock.
+ */
+int
+sctp_add_faddr(sctp_t *sctp, in6_addr_t *addr, int sleep)
+{
+ dprint(4, ("add_faddr: %x:%x:%x:%x %d\n", SCTP_PRINTADDR(*addr),
+ sleep));
+
+ return (sctp_add_faddr_entry(sctp, addr, sleep, B_FALSE));
+}
+
+/*
+ * Same as sctp_add_faddr above, but put new entry at front of list.
* Caller must hold conn fanout lock.
*/
int
sctp_add_faddr_first(sctp_t *sctp, in6_addr_t *addr, int sleep)
{
- sctp_faddr_t *faddr;
-
dprint(4, ("add_faddr_first: %x:%x:%x:%x %d\n", SCTP_PRINTADDR(*addr),
sleep));
- if ((faddr = kmem_cache_alloc(sctp_kmem_faddr_cache, sleep)) == NULL) {
- return (-1);
- }
- sctp_init_faddr(sctp, faddr, addr);
- ASSERT(faddr->next == NULL);
-
- /* Put it at the beginning of the list */
- if (sctp->sctp_faddrs != NULL) {
- faddr->next = sctp->sctp_faddrs;
- } else {
- sctp->sctp_lastfaddr = faddr;
- }
- sctp->sctp_faddrs = faddr;
- sctp->sctp_nfaddrs++;
-
- return (0);
+ return (sctp_add_faddr_entry(sctp, addr, sleep, B_TRUE));
}
sctp_faddr_t *
@@ -914,6 +952,7 @@
ip6_pkt_t *ipp = &sctp->sctp_sticky_ipp;
in6_addr_t src;
in6_addr_t dst;
+
/*
* save the existing sctp header and source/dest IP addresses
*/
@@ -1028,11 +1067,60 @@
return (0);
}
+static int
+sctp_v4_label(sctp_t *sctp)
+{
+ uchar_t optbuf[IP_MAX_OPT_LENGTH];
+ const cred_t *cr = CONN_CRED(sctp->sctp_connp);
+ int added;
+
+ if (tsol_compute_label(cr, sctp->sctp_ipha->ipha_dst, optbuf,
+ sctp->sctp_mac_exempt) != 0)
+ return (EACCES);
+
+ added = tsol_remove_secopt(sctp->sctp_ipha, sctp->sctp_hdr_len);
+ if (added == -1)
+ return (EACCES);
+ sctp->sctp_hdr_len += added;
+ sctp->sctp_sctph = (sctp_hdr_t *)((uchar_t *)sctp->sctp_sctph + added);
+ sctp->sctp_ip_hdr_len += added;
+ if ((sctp->sctp_v4label_len = optbuf[IPOPT_OLEN]) != 0) {
+ sctp->sctp_v4label_len = (sctp->sctp_v4label_len + 3) & ~3;
+ added = tsol_prepend_option(optbuf, sctp->sctp_ipha,
+ sctp->sctp_hdr_len);
+ if (added == -1)
+ return (EACCES);
+ sctp->sctp_hdr_len += added;
+ sctp->sctp_sctph = (sctp_hdr_t *)((uchar_t *)sctp->sctp_sctph +
+ added);
+ sctp->sctp_ip_hdr_len += added;
+ }
+ return (0);
+}
+
+static int
+sctp_v6_label(sctp_t *sctp)
+{
+ uchar_t optbuf[TSOL_MAX_IPV6_OPTION];
+ const cred_t *cr = CONN_CRED(sctp->sctp_connp);
+
+ if (tsol_compute_label_v6(cr, &sctp->sctp_ip6h->ip6_dst, optbuf,
+ sctp->sctp_mac_exempt) != 0)
+ return (EACCES);
+ if (tsol_update_sticky(&sctp->sctp_sticky_ipp, &sctp->sctp_v6label_len,
+ optbuf) != 0)
+ return (EACCES);
+ if (sctp_build_hdrs(sctp) != 0)
+ return (EACCES);
+ return (0);
+}
+
/*
* XXX implement more sophisticated logic
*/
-void
-sctp_set_hdraddrs(sctp_t *sctp)
+/* ARGSUSED */
+int
+sctp_set_hdraddrs(sctp_t *sctp, cred_t *cr)
{
sctp_faddr_t *fp;
int gotv4 = 0;
@@ -1048,15 +1136,18 @@
/* saddr may be unspec; make_mp() will handle this */
IN6_V4MAPPED_TO_IPADDR(&sctp->sctp_primary->saddr,
sctp->sctp_ipha->ipha_src);
- gotv4 = 1;
- if (sctp->sctp_ipversion == IPV4_VERSION) {
- goto copyports;
+ if (!is_system_labeled() || sctp_v4_label(sctp) == 0) {
+ gotv4 = 1;
+ if (sctp->sctp_ipversion == IPV4_VERSION) {
+ goto copyports;
+ }
}
} else {
sctp->sctp_ip6h->ip6_dst = sctp->sctp_primary->faddr;
/* saddr may be unspec; make_mp() will handle this */
sctp->sctp_ip6h->ip6_src = sctp->sctp_primary->saddr;
- gotv6 = 1;
+ if (!is_system_labeled() || sctp_v6_label(sctp) == 0)
+ gotv6 = 1;
}
for (fp = sctp->sctp_faddrs; fp; fp = fp->next) {
@@ -1066,28 +1157,36 @@
/* copy in the faddr_t's saddr */
IN6_V4MAPPED_TO_IPADDR(&fp->saddr,
sctp->sctp_ipha->ipha_src);
- gotv4 = 1;
- if (sctp->sctp_ipversion == IPV4_VERSION || gotv6) {
- break;
+ if (!is_system_labeled() || sctp_v4_label(sctp) == 0) {
+ gotv4 = 1;
+ if (sctp->sctp_ipversion == IPV4_VERSION ||
+ gotv6) {
+ break;
+ }
}
} else if (!gotv6) {
sctp->sctp_ip6h->ip6_dst = fp->faddr;
/* copy in the faddr_t's saddr */
sctp->sctp_ip6h->ip6_src = fp->saddr;
- gotv6 = 1;
- if (gotv4) {
- break;
+ if (!is_system_labeled() || sctp_v6_label(sctp) == 0) {
+ gotv6 = 1;
+ if (gotv4)
+ break;
}
}
}
copyports:
+ if (!gotv4 && !gotv6)
+ return (EACCES);
+
/* copy in the ports for good measure */
sctp->sctp_sctph->sh_sport = sctp->sctp_lport;
sctp->sctp_sctph->sh_dport = sctp->sctp_fport;
sctp->sctp_sctph6->sh_sport = sctp->sctp_lport;
sctp->sctp_sctph6->sh_dport = sctp->sctp_fport;
+ return (0);
}
void
@@ -1251,8 +1350,9 @@
fp = sctp_lookup_faddr(sctp, hdrsaddr);
if (fp == NULL) {
/* not included; add it now */
- if (sctp_add_faddr_first(sctp, hdrsaddr, KM_NOSLEEP) == -1)
- return (ENOMEM);
+ err = sctp_add_faddr_first(sctp, hdrsaddr, KM_NOSLEEP);
+ if (err != 0)
+ return (err);
/* sctp_faddrs will be the hdr addr */
fp = sctp->sctp_faddrs;
@@ -1351,10 +1451,9 @@
goto next;
/* OK, add it to the faddr set */
- if (sctp_add_faddr(sctp, &addr,
- KM_NOSLEEP) != 0) {
- return (ENOMEM);
- }
+ err = sctp_add_faddr(sctp, &addr, KM_NOSLEEP);
+ if (err != 0)
+ return (err);
}
} else if (ph->sph_type == htons(PARM_ADDR6) &&
sctp->sctp_family == AF_INET6) {
@@ -1378,10 +1477,10 @@
if (sctp_lookup_faddr(sctp, addr6) != NULL)
goto next;
- if (sctp_add_faddr(sctp,
- (in6_addr_t *)(ph + 1), KM_NOSLEEP) != 0) {
- return (ENOMEM);
- }
+ err = sctp_add_faddr(sctp,
+ (in6_addr_t *)(ph + 1), KM_NOSLEEP);
+ if (err != 0)
+ return (err);
}
} else if (ph->sph_type == htons(PARM_FORWARD_TSN)) {
if (sctp_options != NULL)
@@ -1570,7 +1669,7 @@
if (compres == SCTP_ADDR_OVERLAP) {
dprint(1,
("new assoc from %x:%x:%x:%x overlaps with %p\n",
- SCTP_PRINTADDR(*hdraddr), sctp));
+ SCTP_PRINTADDR(*hdraddr), (void *)sctp));
/*
* While we still hold the lock, we need to
* figure out which addresses have been
@@ -1669,77 +1768,6 @@
}
}
-/*
- * Return zero if the buffers are identical in length and content.
- * This is used for comparing extension header buffers.
- * Note that an extension header would be declared different
- * even if all that changed was the next header value in that header i.e.
- * what really changed is the next extension header.
- */
-boolean_t
-sctp_cmpbuf(void *a, uint_t alen, boolean_t b_valid, void *b, uint_t blen)
-{
- if (!b_valid)
- blen = 0;
-
- if (alen != blen)
- return (B_TRUE);
- if (alen == 0)
- return (B_FALSE); /* Both zero length */
- return (bcmp(a, b, alen));
-}
-
-/*
- * Preallocate memory for sctp_savebuf(). Returns B_TRUE if ok.
- * Return B_FALSE if memory allocation fails - don't change any state!
- */
-boolean_t
-sctp_allocbuf(void **dstp, uint_t *dstlenp, boolean_t src_valid,
- void *src, uint_t srclen)
-{
- void *dst;
-
- if (!src_valid)
- srclen = 0;
-
- ASSERT(*dstlenp == 0);
- if (src != NULL && srclen != 0) {
- dst = mi_zalloc(srclen);
- if (dst == NULL)
- return (B_FALSE);
- } else {
- dst = NULL;
- }
- if (*dstp != NULL) {
- mi_free(*dstp);
- *dstp = NULL;
- *dstlenp = 0;
- }
- *dstp = dst;
- if (dst != NULL)
- *dstlenp = srclen;
- else
- *dstlenp = 0;
- return (B_TRUE);
-}
-
-/*
- * Replace what is in *dst, *dstlen with the source.
- * Assumes sctp_allocbuf has already been called.
- */
-void
-sctp_savebuf(void **dstp, uint_t *dstlenp, boolean_t src_valid,
- void *src, uint_t srclen)
-{
- if (!src_valid)
- srclen = 0;
-
- ASSERT(*dstlenp == srclen);
- if (src != NULL && srclen != 0) {
- bcopy(src, *dstp, srclen);
- }
-}
-
static void
sctp_init_faddr(sctp_t *sctp, sctp_faddr_t *fp, in6_addr_t *addr)
{
@@ -1799,7 +1827,7 @@
}
void
-sctp_faddr_init()
+sctp_faddr_init(void)
{
sctp_kmem_faddr_cache = kmem_cache_create("sctp_faddr_cache",
sizeof (sctp_faddr_t), 0, NULL, faddr_destructor,
@@ -1807,7 +1835,7 @@
}
void
-sctp_faddr_fini()
+sctp_faddr_fini(void)
{
kmem_cache_destroy(sctp_kmem_faddr_cache);
}
--- a/usr/src/uts/common/inet/sctp/sctp_conn.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/sctp/sctp_conn.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -36,6 +35,7 @@
#include <sys/stropts.h>
#include <sys/strsubr.h>
#include <sys/socket.h>
+#include <sys/tsol/tndb.h>
#include <netinet/in.h>
#include <netinet/ip6.h>
@@ -63,6 +63,8 @@
sctp_init_chunk_t *init;
int err;
uint_t sctp_options;
+ conn_t *lconnp;
+ cred_t *cr;
sctph = (sctp_hdr_t *)(cr_pkt->b_rptr + ip_hdr_len);
ASSERT(OK_32PTR(sctph));
@@ -80,6 +82,20 @@
if (err != 0)
return (err);
+ lconnp = listener->sctp_connp;
+ if (lconnp->conn_mlp_type != mlptSingle) {
+ cr = lconnp->conn_peercred = DB_CRED(cr_pkt);
+ if (cr != NULL)
+ crhold(cr);
+ else
+ cr = lconnp->conn_cred;
+ } else {
+ cr = lconnp->conn_cred;
+ }
+
+ if ((err = sctp_set_hdraddrs(acceptor, cr)) != 0)
+ return (err);
+
if ((sctp_options & SCTP_PRSCTP_OPTION) &&
listener->sctp_prsctp_aware && sctp_prsctp_enabled) {
acceptor->sctp_prsctp_aware = B_TRUE;
@@ -89,8 +105,6 @@
/* The new sctp_t is fully bound now. */
acceptor->sctp_connp->conn_fully_bound = B_TRUE;
- sctp_set_hdraddrs(acceptor);
-
/* Get initial TSNs */
acceptor->sctp_ltsn = ntohl(iack->sic_inittsn);
acceptor->sctp_recovery_tsn = acceptor->sctp_lastack_rxd =
@@ -298,7 +312,6 @@
* bind and conn fanouts, sends the INIT, and replies to the client
* with an OK ack.
*/
-/* ARGSUSED */
int
sctp_connect(sctp_t *sctp, const struct sockaddr *dst, uint32_t addrlen)
{
@@ -313,6 +326,7 @@
int sleep = sctp->sctp_cansleep ? KM_SLEEP : KM_NOSLEEP;
int hdrlen;
ip6_rthdr_t *rth;
+ int err;
sctp_faddr_t *cur_fp;
/*
@@ -406,7 +420,6 @@
switch (sctp->sctp_state) {
case SCTPS_IDLE: {
- int err;
struct sockaddr_storage ss;
/*
@@ -464,10 +477,10 @@
* OK; set up the peer addr (this may grow after we get
* the INIT ACK from the peer with additional addresses).
*/
- if (sctp_add_faddr(sctp, &dstaddr, sleep) < 0) {
+ if ((err = sctp_add_faddr(sctp, &dstaddr, sleep)) != 0) {
mutex_exit(&tbf->tf_lock);
WAKE_SCTP(sctp);
- return (ENOMEM);
+ return (err);
}
/* No valid src addr, return. */
if (sctp->sctp_faddrs->state == SCTP_FADDRS_UNREACH) {
@@ -483,7 +496,11 @@
mutex_exit(&tbf->tf_lock);
/* initialize composite headers */
- sctp_set_hdraddrs(sctp);
+ if ((err = sctp_set_hdraddrs(sctp, NULL)) != 0) {
+ sctp_conn_hash_remove(sctp);
+ WAKE_SCTP(sctp);
+ return (err);
+ }
/*
* Massage a routing header (if present) putting the first hop
--- a/usr/src/uts/common/inet/sctp/sctp_cookie.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/sctp/sctp_cookie.c Fri Mar 24 12:29:20 2006 -0800
@@ -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,6 +33,7 @@
#include <sys/kmem.h>
#include <sys/strsubr.h>
#include <sys/random.h>
+#include <sys/tsol/tnet.h>
#include <netinet/in.h>
#include <netinet/ip6.h>
@@ -441,6 +441,7 @@
mblk_t *errmp = NULL;
boolean_t initcollision = B_FALSE;
boolean_t linklocal = B_FALSE;
+ cred_t *cr;
BUMP_LOCAL(sctp->sctp_ibchunks);
isv4 = (IPH_HDR_VERSION(initmp->b_rptr) == IPV4_VERSION);
@@ -533,7 +534,8 @@
pad = 4 - pad;
ipsctplen += pad;
}
- iackmp = allocb(ipsctplen + sctp_wroff_xtra, BPRI_MED);
+ iackmp = allocb_cred(ipsctplen + sctp_wroff_xtra,
+ CONN_CRED(sctp->sctp_connp));
if (iackmp == NULL) {
sctp_send_abort(sctp, sctp_init2vtag(ch),
SCTP_ERR_NO_RESOURCES, NULL, 0, initmp, 0, B_FALSE);
@@ -693,6 +695,30 @@
iackmp->b_wptr = iackmp->b_rptr + ipsctplen;
iackmp->b_cont = errmp; /* OK if NULL */
+ if (is_system_labeled() && (cr = DB_CRED(initmp)) != NULL &&
+ crgetlabel(cr) != NULL) {
+ conn_t *connp = sctp->sctp_connp;
+ int err, adjust;
+
+ if (isv4)
+ err = tsol_check_label(cr, &iackmp, &adjust,
+ connp->conn_mac_exempt);
+ else
+ err = tsol_check_label_v6(cr, &iackmp, &adjust,
+ connp->conn_mac_exempt);
+ if (err != 0) {
+ sctp_send_abort(sctp, sctp_init2vtag(ch),
+ SCTP_ERR_AUTH_ERR, NULL, 0, initmp, 0, B_FALSE);
+ freemsg(iackmp);
+ return;
+ }
+ if (isv4) {
+ iackiph = (ipha_t *)iackmp->b_rptr;
+ adjust += ntohs(iackiph->ipha_length);
+ iackiph->ipha_length = htons(adjust);
+ }
+ }
+
/*
* Stash the conn ptr info. for IP only as e don't have any
* cached IRE.
@@ -1303,7 +1329,7 @@
dprint(1,
("sctp_addrlist2sctp: src=%x:%x:%x:%x, sctp=%p\n",
- SCTP_PRINTADDR(src), sctp));
+ SCTP_PRINTADDR(src), (void *)sctp));
if (sctp != NULL) {
@@ -1316,7 +1342,7 @@
dprint(1,
("sctp_addrlist2sctp: src=%x:%x:%x:%x, sctp=%p\n",
- SCTP_PRINTADDR(src), sctp));
+ SCTP_PRINTADDR(src), (void *)sctp));
if (sctp != NULL) {
return (sctp);
--- a/usr/src/uts/common/inet/sctp/sctp_error.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/sctp/sctp_error.c Fri Mar 24 12:29:20 2006 -0800
@@ -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 <sys/cmn_err.h>
#include <sys/ddi.h>
#include <sys/strsubr.h>
+#include <sys/tsol/tnet.h>
#include <netinet/in.h>
#include <netinet/ip6.h>
@@ -161,6 +161,9 @@
int isv4;
ire_t *ire;
irb_t *irb;
+ ts_label_t *tsl;
+ conn_t *connp;
+ cred_t *cr;
isv4 = (IPH_HDR_VERSION(inmp->b_rptr) == IPV4_VERSION);
if (isv4) {
@@ -169,7 +172,14 @@
ahlen = sctp->sctp_hdr6_len;
}
- hmp = allocb(sctp_wroff_xtra + ahlen, BPRI_MED);
+ /*
+ * If this is a labeled system, then check to see if we're allowed to
+ * send a response to this particular sender. If not, then just drop.
+ */
+ if (is_system_labeled() && !tsol_can_reply_error(inmp))
+ return;
+
+ hmp = allocb_cred(sctp_wroff_xtra + ahlen, CONN_CRED(sctp->sctp_connp));
if (hmp == NULL) {
/* XXX no resources */
return;
@@ -233,24 +243,48 @@
ahip6h->ip6_plen = htons(alen + sizeof (*sh));
}
- /* Stash the conn ptr info. for IP */
- SCTP_STASH_IPINFO(hmp, (ire_t *)NULL);
-
BUMP_MIB(&sctp_mib, sctpAborted);
BUMP_LOCAL(sctp->sctp_obchunks);
- CONN_INC_REF(sctp->sctp_connp);
+ connp = sctp->sctp_connp;
+ if (is_system_labeled() && (cr = DB_CRED(inmp)) != NULL &&
+ crgetlabel(cr) != NULL) {
+ int err, adjust;
+
+ if (isv4)
+ err = tsol_check_label(cr, &hmp, &adjust,
+ connp->conn_mac_exempt);
+ else
+ err = tsol_check_label_v6(cr, &hmp, &adjust,
+ connp->conn_mac_exempt);
+ if (err != 0) {
+ freemsg(hmp);
+ return;
+ }
+ if (isv4) {
+ ahiph = (ipha_t *)hmp->b_rptr;
+ adjust += ntohs(ahiph->ipha_length);
+ ahiph->ipha_length = htons(adjust);
+ }
+ }
+
+ /* Stash the conn ptr info. for IP */
+ SCTP_STASH_IPINFO(hmp, NULL);
+
+ CONN_INC_REF(connp);
hmp->b_flag |= MSGHASREF;
- IP_PUT(hmp, sctp->sctp_connp, sctp->sctp_current == NULL ? B_TRUE :
+ IP_PUT(hmp, connp, sctp->sctp_current == NULL ? B_TRUE :
sctp->sctp_current->isv4);
/*
* Let's just mark the IRE for this destination as temporary
* to prevent any DoS attack.
*/
+ tsl = cr == NULL ? NULL : crgetlabel(cr);
if (isv4)
- ire = ire_cache_lookup(iniph->ipha_src, sctp->sctp_zoneid);
+ ire = ire_cache_lookup(iniph->ipha_src, sctp->sctp_zoneid, tsl);
else
- ire = ire_cache_lookup_v6(&inip6h->ip6_src, sctp->sctp_zoneid);
+ ire = ire_cache_lookup_v6(&inip6h->ip6_src, sctp->sctp_zoneid,
+ tsl);
/*
* In the normal case the ire would be non-null, however it could be
* null, say, if IP needs to resolve the gateway for this address. We
--- a/usr/src/uts/common/inet/sctp/sctp_hash.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/sctp/sctp_hash.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -30,7 +29,8 @@
#include <sys/socket.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
-#include <sys/strsun.h>
+#include <sys/tsol/tndb.h>
+#include <sys/tsol/tnet.h>
#include <netinet/in.h>
#include <netinet/ip6.h>
@@ -339,6 +339,7 @@
return (sctp);
}
+/* called by ipsec_sctp_pol */
conn_t *
sctp_find_conn(in6_addr_t *src, in6_addr_t *dst, uint32_t ports,
uint_t ipif_seqid, zoneid_t zoneid)
@@ -356,6 +357,37 @@
return (sctp->sctp_connp);
}
+conn_t *
+sctp_fanout(in6_addr_t *src, in6_addr_t *dst, uint32_t ports,
+ uint_t ipif_seqid, zoneid_t zoneid, mblk_t *mp)
+{
+ sctp_t *sctp;
+
+ if ((sctp = sctp_conn_match(src, dst, ports, ipif_seqid,
+ zoneid)) == NULL) {
+ if (zoneid == ALL_ZONES) {
+ zoneid = tsol_mlp_findzone(IPPROTO_SCTP,
+ htons(ntohl(ports) & 0xFFFF));
+ /*
+ * If no shared MLP is found, tsol_mlp_findzone returns
+ * ALL_ZONES. In that case, we assume it's SLP, and
+ * search for the zone based on the packet label.
+ * That will also return ALL_ZONES on failure.
+ */
+ if (zoneid == ALL_ZONES)
+ zoneid = tsol_packet_to_zoneid(mp);
+ if (zoneid == ALL_ZONES)
+ return (NULL);
+ }
+ /* Not in conn fanout; check listen fanout */
+ if ((sctp = listen_match(dst, ports, ipif_seqid,
+ zoneid)) == NULL) {
+ return (NULL);
+ }
+ }
+ return (sctp->sctp_connp);
+}
+
/*
* Fanout for SCTP packets
* The caller puts <fport, lport> in the ports parameter.
@@ -400,7 +432,7 @@
dst = &map_dst;
isv4 = B_TRUE;
}
- if ((connp = sctp_find_conn(src, dst, ports, ipif_seqid, zoneid)) ==
+ if ((connp = sctp_fanout(src, dst, ports, ipif_seqid, zoneid, mp)) ==
NULL) {
ip_fanout_sctp_raw(mp, recv_ill, ipha, isv4,
ports, mctl_present, flags, ip_policy,
--- a/usr/src/uts/common/inet/sctp/sctp_heartbeat.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/sctp/sctp_heartbeat.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -67,7 +66,7 @@
ASSERT(fp != NULL);
dprint(3, ("sctp_return_heartbeat: %p got hb from %x:%x:%x:%x\n",
- sctp, SCTP_PRINTADDR(addr)));
+ (void *)sctp, SCTP_PRINTADDR(addr)));
/*
* XXX It's really tempting to reuse the heartbeat mblk. But
@@ -276,7 +275,7 @@
sizeof (sent) + sizeof (secret) + sizeof (addr))) {
/* drop it */
dprint(2, ("sctp_process_heartbeat: malformed ack %p\n",
- sctp));
+ (void *)sctp));
return;
}
@@ -285,7 +284,7 @@
ntohs(hpp->sph_len) != (ntohs(cp->sch_len) - sizeof (*cp))) {
dprint(2,
("sctp_process_heartbeat: malformed param in ack %p\n",
- sctp));
+ (void *)sctp));
return;
}
@@ -305,13 +304,13 @@
fp = sctp_lookup_faddr(sctp, &addr);
if (fp == NULL) {
dprint(2, ("sctp_process_heartbeat: invalid faddr (sctp=%p)\n",
- sctp));
+ (void *)sctp));
return;
}
if (secret != fp->hb_secret) {
dprint(2,
("sctp_process_heartbeat: invalid secret in ack %p\n",
- sctp));
+ (void *)sctp));
return;
}
--- a/usr/src/uts/common/inet/sctp/sctp_impl.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/sctp/sctp_impl.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -37,6 +36,7 @@
#include <sys/taskq.h>
#include <sys/list.h>
#include <sys/strsun.h>
+#include <sys/zone.h>
#include <netinet/ip6.h>
#include <inet/optcom.h>
#include <netinet/sctp.h>
@@ -73,8 +73,8 @@
if ((fp)->timer_mp != NULL) { \
((sctpt_t *)((fp)->timer_mp->b_rptr))->sctpt_faddr = fp; \
dprint(3, ("faddr_timer_restart: fp=%p %x:%x:%x:%x %d\n", \
- (fp), SCTP_PRINTADDR((fp)->faddr), \
- (int)(intvl))); \
+ (void *)(fp), SCTP_PRINTADDR((fp)->faddr), \
+ (int)(intvl))); \
sctp_timer((sctp), (fp)->timer_mp, (intvl)); \
(fp)->timer_running = 1; \
}
@@ -428,16 +428,12 @@
/* debugging */
#undef dprint
-#if defined(DEBUG) && !defined(lint)
+#ifdef DEBUG
extern int sctpdebug;
-
#define dprint(level, args) { if (sctpdebug > (level)) printf args; }
-
-#else /* define(DEBUG) && !defined(lint) */
-
+#else
#define dprint(level, args) {}
-
-#endif /* defined(DEBUG) && !defined(lint) */
+#endif
/* Peer address tracking */
@@ -746,7 +742,9 @@
sctp_chk_fast_rexmit : 1, /* check for fast rexmit message */
sctp_prsctp_aware : 1, /* is peer PR-SCTP aware? */
- sctp_linklocal : 1; /* is linklocal assoc. */
+ sctp_linklocal : 1, /* is linklocal assoc. */
+ sctp_mac_exempt : 1, /* SO_MAC_EXEMPT */
+ sctp_dummy : 5;
} sctp_bits;
struct {
uint32_t
@@ -788,6 +786,7 @@
#define sctp_chk_fast_rexmit sctp_bits.sctp_chk_fast_rexmit
#define sctp_prsctp_aware sctp_bits.sctp_prsctp_aware
#define sctp_linklocal sctp_bits.sctp_linklocal
+#define sctp_mac_exempt sctp_bits.sctp_mac_exempt
#define sctp_recvsndrcvinfo sctp_events.sctp_recvsndrcvinfo
#define sctp_recvassocevnt sctp_events.sctp_recvassocevnt
@@ -901,6 +900,9 @@
/* Stats */
uint64_t sctp_msgcount;
uint64_t sctp_prsctpdrop;
+
+ uint_t sctp_v4label_len; /* length of cached v4 label */
+ uint_t sctp_v6label_len; /* length of cached v6 label */
} sctp_t;
extern list_t sctp_g_list; /* Head of SCTP instance data chain */
@@ -933,13 +935,12 @@
uint_t, zoneid_t);
extern void sctp_add_hdr(sctp_t *, uchar_t *, size_t);
extern void sctp_check_adv_ack_pt(sctp_t *, mblk_t *, mblk_t *);
-extern boolean_t sctp_allocbuf(void **, uint_t *, boolean_t, void *, uint_t);
extern void sctp_assoc_event(sctp_t *, uint16_t, uint16_t,
sctp_chunk_hdr_t *);
extern void sctp_bind_hash_insert(sctp_tf_t *, sctp_t *, int);
extern void sctp_bind_hash_remove(sctp_t *);
-extern in_port_t sctp_bindi(sctp_t *, in_port_t, int, int);
+extern int sctp_bindi(sctp_t *, in_port_t, boolean_t, int, in_port_t *);
extern int sctp_bind_add(sctp_t *, const void *, uint32_t, boolean_t,
in_port_t);
extern int sctp_bind_del(sctp_t *, const void *, uint32_t, boolean_t);
@@ -949,7 +950,6 @@
extern void sctp_chunkify(sctp_t *, int, int);
extern void sctp_clean_death(sctp_t *, int);
extern void sctp_close_eager(sctp_t *);
-extern boolean_t sctp_cmpbuf(void *, uint_t, boolean_t, void *, uint_t);
extern int sctp_compare_faddrsets(sctp_faddr_t *, sctp_faddr_t *);
extern void sctp_congest_reset(sctp_t *);
extern void sctp_conn_hash_insert(sctp_tf_t *, sctp_t *, int);
@@ -966,14 +966,14 @@
extern void sctp_dispatch_rput(queue_t *, sctp_t *, sctp_hdr_t *, mblk_t *,
uint_t, uint_t, in6_addr_t);
extern char *sctp_display(sctp_t *, char *);
-extern void sctp_display_all();
+extern void sctp_display_all(void);
extern void sctp_error_event(sctp_t *, sctp_chunk_hdr_t *);
extern void sctp_faddr_alive(sctp_t *, sctp_faddr_t *);
extern int sctp_faddr_dead(sctp_t *, sctp_faddr_t *, int);
-extern void sctp_faddr_fini();
-extern void sctp_faddr_init();
+extern void sctp_faddr_fini(void);
+extern void sctp_faddr_init(void);
extern void sctp_faddr2hdraddr(sctp_faddr_t *, sctp_t *);
extern void sctp_faddr2ire(sctp_t *, sctp_faddr_t *);
extern void sctp_fast_rexmit(sctp_t *);
@@ -994,7 +994,6 @@
extern mblk_t *sctp_get_first_sent(sctp_t *);
extern mblk_t *sctp_get_msg_to_send(sctp_t *, mblk_t **, mblk_t *, int *,
int32_t, uint32_t, sctp_faddr_t *);
-extern in_port_t sctp_get_next_priv_port();
extern void sctp_get_saddr_list(sctp_t *, uchar_t *, size_t);
extern int sctp_handle_error(sctp_t *, sctp_hdr_t *, sctp_chunk_hdr_t *,
@@ -1039,9 +1038,9 @@
extern void sctp_maxpsz_set(sctp_t *);
extern void sctp_move_faddr_timers(queue_t *, sctp_t *);
-extern void sctp_nd_free();
+extern void sctp_nd_free(void);
extern int sctp_nd_getset(queue_t *, MBLKP);
-extern boolean_t sctp_nd_init();
+extern boolean_t sctp_nd_init(void);
extern sctp_parm_hdr_t *sctp_next_parm(sctp_parm_hdr_t *, ssize_t *);
extern void sctp_ootb_shutdown_ack(sctp_t *, mblk_t *, uint_t);
@@ -1065,7 +1064,6 @@
extern sctp_faddr_t *sctp_rotate_faddr(sctp_t *, sctp_faddr_t *);
extern void sctp_sack(sctp_t *, mblk_t *);
-extern void sctp_savebuf(void **, uint_t *, boolean_t, void *, uint_t);
extern int sctp_secure_restart_check(mblk_t *, sctp_chunk_hdr_t *,
uint32_t, int);
extern void sctp_send_abort(sctp_t *, uint32_t, uint16_t, char *, size_t,
@@ -1077,9 +1075,9 @@
extern void sctp_send_shutdown(sctp_t *, int);
extern void sctp_send_heartbeat(sctp_t *, sctp_faddr_t *);
extern void sctp_sendfail_event(sctp_t *, mblk_t *, int, boolean_t);
-extern void sctp_set_hdraddrs(sctp_t *);
-extern void sctp_sets_init();
-extern void sctp_sets_fini();
+extern int sctp_set_hdraddrs(sctp_t *, cred_t *);
+extern void sctp_sets_init(void);
+extern void sctp_sets_fini(void);
extern void sctp_shutdown_event(sctp_t *);
extern void sctp_stop_faddr_timers(sctp_t *);
extern int sctp_shutdown_received(sctp_t *, sctp_chunk_hdr_t *, int, int);
@@ -1097,7 +1095,7 @@
extern void sctp_timer_stop(mblk_t *);
extern void sctp_unlink_faddr(sctp_t *, sctp_faddr_t *);
-extern in_port_t sctp_update_next_port(in_port_t);
+extern in_port_t sctp_update_next_port(in_port_t, zone_t *zone);
extern void sctp_update_rtt(sctp_t *, sctp_faddr_t *, clock_t);
extern void sctp_user_abort(sctp_t *, mblk_t *, boolean_t);
--- a/usr/src/uts/common/inet/sctp/sctp_input.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/sctp/sctp_input.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -382,14 +381,15 @@
}
/* If app asked for hopbyhop headers and it has changed ... */
if ((sctp->sctp_ipv6_recvancillary & SCTP_IPV6_RECVHOPOPTS) &&
- sctp_cmpbuf(sctp->sctp_hopopts, sctp->sctp_hopoptslen,
+ ip_cmpbuf(sctp->sctp_hopopts, sctp->sctp_hopoptslen,
(ipp->ipp_fields & IPPF_HOPOPTS),
ipp->ipp_hopopts, ipp->ipp_hopoptslen)) {
- optlen += sizeof (*cmsg) + ipp->ipp_hopoptslen;
+ optlen += sizeof (*cmsg) + ipp->ipp_hopoptslen -
+ sctp->sctp_v6label_len;
if (hdrlen == 0)
hdrlen = sizeof (struct T_unitdata_ind);
addflag |= SCTP_IPV6_RECVHOPOPTS;
- if (!sctp_allocbuf((void **)&sctp->sctp_hopopts,
+ if (!ip_allocbuf((void **)&sctp->sctp_hopopts,
&sctp->sctp_hopoptslen,
(ipp->ipp_fields & IPPF_HOPOPTS),
ipp->ipp_hopopts, ipp->ipp_hopoptslen))
@@ -397,14 +397,14 @@
}
/* If app asked for dst headers before routing headers ... */
if ((sctp->sctp_ipv6_recvancillary & SCTP_IPV6_RECVRTDSTOPTS) &&
- sctp_cmpbuf(sctp->sctp_rtdstopts, sctp->sctp_rtdstoptslen,
+ ip_cmpbuf(sctp->sctp_rtdstopts, sctp->sctp_rtdstoptslen,
(ipp->ipp_fields & IPPF_RTDSTOPTS),
ipp->ipp_rtdstopts, ipp->ipp_rtdstoptslen)) {
optlen += sizeof (*cmsg) + ipp->ipp_rtdstoptslen;
if (hdrlen == 0)
hdrlen = sizeof (struct T_unitdata_ind);
addflag |= SCTP_IPV6_RECVRTDSTOPTS;
- if (!sctp_allocbuf((void **)&sctp->sctp_rtdstopts,
+ if (!ip_allocbuf((void **)&sctp->sctp_rtdstopts,
&sctp->sctp_rtdstoptslen,
(ipp->ipp_fields & IPPF_RTDSTOPTS),
ipp->ipp_rtdstopts, ipp->ipp_rtdstoptslen))
@@ -412,14 +412,14 @@
}
/* If app asked for routing headers and it has changed ... */
if (sctp->sctp_ipv6_recvancillary & SCTP_IPV6_RECVRTHDR) {
- if (sctp_cmpbuf(sctp->sctp_rthdr, sctp->sctp_rthdrlen,
+ if (ip_cmpbuf(sctp->sctp_rthdr, sctp->sctp_rthdrlen,
(ipp->ipp_fields & IPPF_RTHDR),
ipp->ipp_rthdr, ipp->ipp_rthdrlen)) {
optlen += sizeof (*cmsg) + ipp->ipp_rthdrlen;
if (hdrlen == 0)
hdrlen = sizeof (struct T_unitdata_ind);
addflag |= SCTP_IPV6_RECVRTHDR;
- if (!sctp_allocbuf((void **)&sctp->sctp_rthdr,
+ if (!ip_allocbuf((void **)&sctp->sctp_rthdr,
&sctp->sctp_rthdrlen,
(ipp->ipp_fields & IPPF_RTHDR),
ipp->ipp_rthdr, ipp->ipp_rthdrlen))
@@ -428,14 +428,14 @@
}
/* If app asked for dest headers and it has changed ... */
if ((sctp->sctp_ipv6_recvancillary & SCTP_IPV6_RECVDSTOPTS) &&
- sctp_cmpbuf(sctp->sctp_dstopts, sctp->sctp_dstoptslen,
+ ip_cmpbuf(sctp->sctp_dstopts, sctp->sctp_dstoptslen,
(ipp->ipp_fields & IPPF_DSTOPTS),
ipp->ipp_dstopts, ipp->ipp_dstoptslen)) {
optlen += sizeof (*cmsg) + ipp->ipp_dstoptslen;
if (hdrlen == 0)
hdrlen = sizeof (struct T_unitdata_ind);
addflag |= SCTP_IPV6_RECVDSTOPTS;
- if (!sctp_allocbuf((void **)&sctp->sctp_dstopts,
+ if (!ip_allocbuf((void **)&sctp->sctp_dstopts,
&sctp->sctp_dstoptslen,
(ipp->ipp_fields & IPPF_DSTOPTS),
ipp->ipp_dstopts, ipp->ipp_dstoptslen))
@@ -546,7 +546,7 @@
optptr += ipp->ipp_hopoptslen;
ASSERT(OK_32PTR(optptr));
/* Save as last value */
- sctp_savebuf((void **)&sctp->sctp_hopopts,
+ ip_savebuf((void **)&sctp->sctp_hopopts,
&sctp->sctp_hopoptslen,
(ipp->ipp_fields & IPPF_HOPOPTS),
ipp->ipp_hopopts, ipp->ipp_hopoptslen);
@@ -562,7 +562,7 @@
optptr += ipp->ipp_rtdstoptslen;
ASSERT(OK_32PTR(optptr));
/* Save as last value */
- sctp_savebuf((void **)&sctp->sctp_rtdstopts,
+ ip_savebuf((void **)&sctp->sctp_rtdstopts,
&sctp->sctp_rtdstoptslen,
(ipp->ipp_fields & IPPF_RTDSTOPTS),
ipp->ipp_rtdstopts, ipp->ipp_rtdstoptslen);
@@ -578,7 +578,7 @@
optptr += ipp->ipp_rthdrlen;
ASSERT(OK_32PTR(optptr));
/* Save as last value */
- sctp_savebuf((void **)&sctp->sctp_rthdr,
+ ip_savebuf((void **)&sctp->sctp_rthdr,
&sctp->sctp_rthdrlen,
(ipp->ipp_fields & IPPF_RTHDR),
ipp->ipp_rthdr, ipp->ipp_rthdrlen);
@@ -594,7 +594,7 @@
optptr += ipp->ipp_dstoptslen;
ASSERT(OK_32PTR(optptr));
/* Save as last value */
- sctp_savebuf((void **)&sctp->sctp_dstopts,
+ ip_savebuf((void **)&sctp->sctp_dstopts,
&sctp->sctp_dstoptslen,
(ipp->ipp_fields & IPPF_DSTOPTS),
ipp->ipp_dstopts, ipp->ipp_dstoptslen);
@@ -1207,7 +1207,7 @@
dc = (sctp_data_hdr_t *)ch;
tsn = ntohl(dc->sdh_tsn);
- dprint(3, ("sctp_data_chunk: mp=%p tsn=%x\n", mp, tsn));
+ dprint(3, ("sctp_data_chunk: mp=%p tsn=%x\n", (void *)mp, tsn));
/* Check for duplicates */
if (SEQ_LT(tsn, sctp->sctp_ftsn)) {
@@ -1628,7 +1628,7 @@
if (sctp->sctp_sack_toggle < 2) {
/* no need to SACK right now */
dprint(2, ("sctp_make_sack: %p no sack (toggle)\n",
- sctp));
+ (void *)sctp));
return (NULL);
} else if (sctp->sctp_sack_toggle >= 2) {
sctp->sctp_sack_toggle = 0;
@@ -1636,7 +1636,8 @@
}
if (sctp->sctp_ftsn == sctp->sctp_lastacked + 1) {
- dprint(2, ("sctp_make_sack: %p no sack (already)\n", sctp));
+ dprint(2, ("sctp_make_sack: %p no sack (already)\n",
+ (void *)sctp));
return (NULL);
}
@@ -1686,7 +1687,8 @@
sctp_set_iplen(sctp, smp);
dprint(2, ("sctp_sack: sending to %p %x:%x:%x:%x\n",
- sctp->sctp_lastdata, SCTP_PRINTADDR(sctp->sctp_lastdata->faddr)));
+ (void *)sctp->sctp_lastdata,
+ SCTP_PRINTADDR(sctp->sctp_lastdata->faddr)));
sctp->sctp_active = lbolt64;
@@ -3453,7 +3455,8 @@
/* Have a valid sctp for this packet */
fp = sctp_lookup_faddr(sctp, &src);
- dprint(2, ("sctp_dispatch_rput: mp=%p fp=%p sctp=%p\n", mp, fp, sctp));
+ dprint(2, ("sctp_dispatch_rput: mp=%p fp=%p sctp=%p\n", (void *)mp,
+ (void *)fp, (void *)sctp));
gotdata = 0;
trysend = 0;
@@ -3688,6 +3691,8 @@
BUMP_MIB(&sctp_mib, sctpPassiveEstab);
if (mlen > ntohs(ch->sch_len)) {
eager->sctp_cookie_mp = dupb(mp);
+ mblk_setcred(eager->sctp_cookie_mp,
+ CONN_CRED(eager->sctp_connp));
/*
* If no mem, just let
* the peer retransmit.
--- a/usr/src/uts/common/inet/sctp/sctp_opt_data.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/sctp/sctp_opt_data.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -63,171 +62,57 @@
static int sctp_getpeeraddrs(sctp_t *, void *, int *);
/*
- * Set optbuf and optlen for the option.
- * Allocate memory (if not already present).
- * Otherwise just point optbuf and optlen at invalp and inlen.
- * Returns failure if memory can not be allocated.
- */
-static int
-sctp_pkt_set(uchar_t *invalp, uint_t inlen, uchar_t **optbufp, uint_t *optlenp)
-{
- uchar_t *optbuf;
-
- if (inlen == *optlenp) {
- /* Unchanged length - no need to realocate */
- bcopy(invalp, *optbufp, inlen);
- return (0);
- }
- if (inlen != 0) {
- /* Allocate new buffer before free */
- optbuf = kmem_zalloc(inlen, KM_NOSLEEP);
- if (optbuf == NULL)
- return (ENOMEM);
- } else {
- optbuf = NULL;
- }
- /* Free old buffer */
- if (*optlenp != 0)
- kmem_free(*optbufp, *optlenp);
-
- bcopy(invalp, optbuf, inlen);
- *optbufp = optbuf;
- *optlenp = inlen;
- return (0);
-}
-
-/*
- * Use the outgoing IP header to create an IP_OPTIONS option the way
- * it was passed down from the application.
- */
-static int
-sctp_opt_get_user(ipha_t *ipha, uchar_t *buf)
-{
- uchar_t *opt;
- int totallen;
- uint32_t optval;
- uint32_t optlen;
- uint32_t len = 0;
- uchar_t *buf1 = buf;
-
- buf += IP_ADDR_LEN; /* Leave room for final destination */
- len += IP_ADDR_LEN;
- bzero(buf1, IP_ADDR_LEN);
-
- totallen = ipha->ipha_version_and_hdr_length -
- (uint8_t)((IP_VERSION << 4) + IP_SIMPLE_HDR_LENGTH_IN_WORDS);
- opt = (uchar_t *)&ipha[1];
- totallen <<= 2;
- while (totallen != 0) {
- switch (optval = opt[IPOPT_OPTVAL]) {
- case IPOPT_EOL:
- goto done;
- case IPOPT_NOP:
- optlen = 1;
- break;
- default:
- optlen = opt[IPOPT_OLEN];
- }
- if (optlen == 0 || optlen > totallen)
- break;
-
- switch (optval) {
- int off;
- case IPOPT_SSRR:
- case IPOPT_LSRR:
-
- /*
- * Insert ipha_dst as the first entry in the source
- * route and move down the entries on step.
- * The last entry gets placed at buf1.
- */
- buf[IPOPT_OPTVAL] = optval;
- buf[IPOPT_OLEN] = optlen;
- buf[IPOPT_OFFSET] = optlen;
-
- off = optlen - IP_ADDR_LEN;
- if (off < 0) {
- /* No entries in source route */
- break;
- }
- /* Last entry in source route */
- bcopy(opt + off, buf1, IP_ADDR_LEN);
- off -= IP_ADDR_LEN;
-
- while (off > 0) {
- bcopy(opt + off,
- buf + off + IP_ADDR_LEN,
- IP_ADDR_LEN);
- off -= IP_ADDR_LEN;
- }
- /* ipha_dst into first slot */
- bcopy(&ipha->ipha_dst,
- buf + off + IP_ADDR_LEN,
- IP_ADDR_LEN);
- buf += optlen;
- len += optlen;
- break;
- default:
- bcopy(opt, buf, optlen);
- buf += optlen;
- len += optlen;
- break;
- }
- totallen -= optlen;
- opt += optlen;
- }
-done:
- /* Pad the resulting options */
- while (len & 0x3) {
- *buf++ = IPOPT_EOL;
- len++;
- }
- return (len);
-}
-
-
-/*
* Copy the standard header into its new location,
* lay in the new options and then update the relevant
* fields in both sctp_t and the standard header.
- * NOTE: this could be simpler if we trusted bcopy()
- * with overlapping src/dst.
+ * Returns 0 on success, errno otherwise.
*/
static int
-sctp_opt_set_header(sctp_t *sctp, boolean_t checkonly, const void *ptr,
- uint_t len)
+sctp_opt_set_header(sctp_t *sctp, const void *ptr, uint_t len)
{
- char buf[SCTP_MAX_HDR_LENGTH];
- uint_t sctph_len;
-
- if (checkonly) {
- /*
- * do not really set, just pretend to - T_CHECK
- */
- if (len != 0) {
- /*
- * there is value supplied, validate it as if
- * for a real set operation.
- */
- if ((len > SCTP_MAX_IP_OPTIONS_LENGTH) || (len & 0x3))
- return (EINVAL);
- }
- return (0);
- }
+ uint8_t *ip_optp;
+ sctp_hdr_t *new_sctph;
if ((len > SCTP_MAX_IP_OPTIONS_LENGTH) || (len & 0x3))
return (EINVAL);
- sctph_len = sizeof (sctp_hdr_t);
- bcopy(sctp->sctp_sctph, buf, sctph_len);
- bcopy(ptr, (char *)sctp->sctp_ipha + IP_SIMPLE_HDR_LENGTH, len);
- len += IP_SIMPLE_HDR_LENGTH;
- sctp->sctp_sctph = (sctp_hdr_t *)((char *)sctp->sctp_ipha + len);
- bcopy(buf, sctp->sctp_sctph, sctph_len);
+
+ if (len > IP_MAX_OPT_LENGTH - sctp->sctp_v4label_len)
+ return (EINVAL);
+
+ ip_optp = (uint8_t *)sctp->sctp_ipha + IP_SIMPLE_HDR_LENGTH;
+
+ if (sctp->sctp_v4label_len > 0) {
+ int padlen;
+ uint8_t opt;
+
+ /* convert list termination to no-ops as needed */
+ padlen = sctp->sctp_v4label_len - ip_optp[IPOPT_OLEN];
+ ip_optp += ip_optp[IPOPT_OLEN];
+ opt = len > 0 ? IPOPT_NOP : IPOPT_EOL;
+ while (--padlen >= 0)
+ *ip_optp++ = opt;
+ ASSERT(ip_optp == (uint8_t *)sctp->sctp_ipha +
+ IP_SIMPLE_HDR_LENGTH + sctp->sctp_v4label_len);
+ }
+
+ /*
+ * Move the existing SCTP header out where it belongs.
+ */
+ new_sctph = (sctp_hdr_t *)(ip_optp + len);
+ ovbcopy(sctp->sctp_sctph, new_sctph, sizeof (sctp_hdr_t));
+ sctp->sctp_sctph = new_sctph;
+
+ /*
+ * Insert the new user-supplied IP options.
+ */
+ if (len > 0)
+ bcopy(ptr, ip_optp, len);
+
+ len += sctp->sctp_v4label_len;
sctp->sctp_ip_hdr_len = len;
sctp->sctp_ipha->ipha_version_and_hdr_length =
- (IP_VERSION << 4) | (len >> 2);
- len += sctph_len;
- sctp->sctp_hdr_len = len;
+ (IP_VERSION << 4) | (len >> 2);
+ sctp->sctp_hdr_len = len + sizeof (sctp_hdr_t);
if (sctp->sctp_current) {
/*
@@ -839,6 +724,9 @@
case SO_RCVBUF:
*i1 = sctp->sctp_rwnd;
break;
+ case SO_MAC_EXEMPT:
+ *i1 = sctp->sctp_mac_exempt ? SO_MAC_EXEMPT : 0;
+ break;
default:
retval = EINVAL;
break;
@@ -1006,7 +894,7 @@
* will contain the final destination. Allocate a
* buffer large enough to hold all the options, we
* add IP_ADDR_LEN to SCTP_MAX_IP_OPTIONS_LENGTH since
- * sctp_opt_get_user() adds the final destination
+ * ip_opt_get_user() adds the final destination
* at the start.
*/
char *opt_ptr;
@@ -1022,7 +910,7 @@
* TODO: Do we have to handle getsockopt on an
* initiator as well?
*/
- opt_len = sctp_opt_get_user(sctp->sctp_ipha,
+ opt_len = ip_opt_get_user(sctp->sctp_ipha,
obuf);
ASSERT(opt_len <= sizeof (obuf));
} else {
@@ -1148,16 +1036,35 @@
*optlen = sizeof (sin6_t);
break;
}
- case IPV6_HOPOPTS:
+ case IPV6_HOPOPTS: {
+ int len;
+
if (!(ipp->ipp_fields & IPPF_HOPOPTS))
break;
- if (buflen < ipp->ipp_hopoptslen) {
+ len = ipp->ipp_hopoptslen - sctp->sctp_v6label_len;
+ if (len <= 0)
+ break;
+ if (buflen < len) {
retval = EINVAL;
break;
}
- bcopy(ipp->ipp_hopopts, ptr, ipp->ipp_hopoptslen);
- *optlen = ipp->ipp_hopoptslen;
+ bcopy((char *)ipp->ipp_hopopts +
+ sctp->sctp_v6label_len, ptr, len);
+ if (sctp->sctp_v6label_len > 0) {
+ char *cptr = ptr;
+
+ /*
+ * If the label length is greater than zero,
+ * then we need to hide the label from user.
+ * Make it look as though a normal Hop-By-Hop
+ * Options Header is present here.
+ */
+ cptr[0] = ((char *)ipp->ipp_hopopts)[0];
+ cptr[1] = (len + 7) / 8 - 1;
+ }
+ *optlen = len;
break;
+ }
case IPV6_RTHDRDSTOPTS:
if (!(ipp->ipp_fields & IPPF_RTDSTOPTS))
break;
@@ -1316,6 +1223,15 @@
* and sctp_opt_get ?
*/
break;
+ case SO_MAC_EXEMPT:
+ if (secpolicy_net_mac_aware(sctp->sctp_credp) != 0 ||
+ sctp->sctp_state >= SCTPS_BOUND) {
+ retval = EACCES;
+ } else {
+ sctp->sctp_mac_exempt = onoff;
+ connp->conn_mac_exempt = onoff;
+ }
+ break;
default:
retval = EINVAL;
break;
@@ -1465,8 +1381,7 @@
switch (name) {
case IP_OPTIONS:
case T_IP_OPTIONS:
- retval = sctp_opt_set_header(sctp, B_FALSE,
- invalp, inlen);
+ retval = sctp_opt_set_header(sctp, invalp, inlen);
break;
case IP_TOS:
case T_IP_TOS:
@@ -1700,8 +1615,9 @@
ire_t *ire;
ire = ire_route_lookup_v6(
- &sin6->sin6_addr, 0, 0, 0, NULL,
- NULL, NULL, MATCH_IRE_DEFAULT);
+ &sin6->sin6_addr, NULL, NULL, 0,
+ NULL, NULL, ALL_ZONES, NULL,
+ MATCH_IRE_DEFAULT);
if (ire == NULL) {
retval = EHOSTUNREACH;
break;
@@ -1722,16 +1638,15 @@
break;
}
- if (inlen == 0) {
+ retval = optcom_pkt_set((uchar_t *)invalp, inlen,
+ B_TRUE, (uchar_t **)&ipp->ipp_hopopts,
+ &ipp->ipp_hopoptslen, sctp->sctp_v6label_len);
+ if (retval != 0)
+ break;
+ if (ipp->ipp_hopoptslen == 0)
ipp->ipp_fields &= ~IPPF_HOPOPTS;
- } else {
- retval = sctp_pkt_set((uchar_t *)invalp, inlen,
- (uchar_t **)&ipp->ipp_hopopts,
- &ipp->ipp_hopoptslen);
- if (retval != 0)
- break;
+ else
ipp->ipp_fields |= IPPF_HOPOPTS;
- }
retval = sctp_build_hdrs(sctp);
break;
}
@@ -1744,16 +1659,15 @@
break;
}
- if (inlen == 0) {
+ retval = optcom_pkt_set((uchar_t *)invalp, inlen,
+ B_TRUE, (uchar_t **)&ipp->ipp_rtdstopts,
+ &ipp->ipp_rtdstoptslen, 0);
+ if (retval != 0)
+ break;
+ if (ipp->ipp_rtdstoptslen == 0)
ipp->ipp_fields &= ~IPPF_RTDSTOPTS;
- } else {
- retval = sctp_pkt_set((uchar_t *)invalp, inlen,
- (uchar_t **)&ipp->ipp_rtdstopts,
- &ipp->ipp_rtdstoptslen);
- if (retval != 0)
- break;
+ else
ipp->ipp_fields |= IPPF_RTDSTOPTS;
- }
retval = sctp_build_hdrs(sctp);
break;
}
@@ -1766,16 +1680,15 @@
break;
}
- if (inlen == 0) {
+ retval = optcom_pkt_set((uchar_t *)invalp, inlen,
+ B_TRUE, (uchar_t **)&ipp->ipp_dstopts,
+ &ipp->ipp_dstoptslen, 0);
+ if (retval != 0)
+ break;
+ if (ipp->ipp_dstoptslen == 0)
ipp->ipp_fields &= ~IPPF_DSTOPTS;
- } else {
- retval = sctp_pkt_set((uchar_t *)invalp, inlen,
- (uchar_t **)&ipp->ipp_dstopts,
- &ipp->ipp_dstoptslen);
- if (retval != 0)
- break;
+ else
ipp->ipp_fields |= IPPF_DSTOPTS;
- }
retval = sctp_build_hdrs(sctp);
break;
}
@@ -1788,16 +1701,15 @@
break;
}
- if (inlen == 0) {
+ retval = optcom_pkt_set((uchar_t *)invalp, inlen,
+ B_TRUE, (uchar_t **)&ipp->ipp_rthdr,
+ &ipp->ipp_rthdrlen, 0);
+ if (retval != 0)
+ break;
+ if (ipp->ipp_rthdrlen == 0)
ipp->ipp_fields &= ~IPPF_RTHDR;
- } else {
- retval = sctp_pkt_set((uchar_t *)invalp, inlen,
- (uchar_t **)&ipp->ipp_rthdr,
- &ipp->ipp_rthdrlen);
- if (retval != 0)
- break;
+ else
ipp->ipp_fields |= IPPF_RTHDR;
- }
retval = sctp_build_hdrs(sctp);
break;
}
--- a/usr/src/uts/common/inet/sctp/sctp_output.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/sctp/sctp_output.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -37,17 +36,15 @@
#include <sys/strsun.h>
#include <sys/strsubr.h>
#include <sys/socketvar.h>
-
-#include <netinet/in.h>
-#include <netinet/ip6.h>
-#include <netinet/tcp_seq.h>
-#include <netinet/sctp.h>
+/* swilly code in sys/socketvar.h turns off DEBUG */
+#ifdef __lint
+#define DEBUG
+#endif
#include <inet/common.h>
#include <inet/mi.h>
#include <inet/ip.h>
#include <inet/ip6.h>
-#include <inet/ip_ire.h>
#include <inet/sctp_ip.h>
#include <inet/ipclassifier.h>
@@ -589,7 +586,8 @@
* data was moved into chunks, or during retransmission,
* or things like snoop is running.
*/
- nmp = allocb(sctp_wroff_xtra + hdrlen + sacklen, BPRI_MED);
+ nmp = allocb_cred(sctp_wroff_xtra + hdrlen + sacklen,
+ CONN_CRED(sctp->sctp_connp));
if (nmp == NULL) {
if (error != NULL)
*error = ENOMEM;
@@ -601,6 +599,7 @@
mp = nmp;
} else {
mp->b_rptr -= (hdrlen + sacklen);
+ mblk_setcred(mp, CONN_CRED(sctp->sctp_connp));
}
bcopy(hdr, mp->b_rptr, hdrlen);
if (sacklen) {
@@ -1210,10 +1209,10 @@
ASSERT(cansend >= seglen - pad - xtralen);
cansend -= (seglen - pad - xtralen);
dprint(2, ("sctp_output: Sending packet %d bytes, tsn %x "
- "ssn %d to %p (rwnd %d, cansend %d, lastack_rxd %x)\n",
- seglen - xtralen, ntohl(sdc->sdh_tsn),
- ntohs(sdc->sdh_ssn), fp, sctp->sctp_frwnd, cansend,
- sctp->sctp_lastack_rxd));
+ "ssn %d to %p (rwnd %d, cansend %d, lastack_rxd %x)\n",
+ seglen - xtralen, ntohl(sdc->sdh_tsn),
+ ntohs(sdc->sdh_ssn), (void *)fp, sctp->sctp_frwnd,
+ cansend, sctp->sctp_lastack_rxd));
sctp_set_iplen(sctp, head);
sctp_add_sendq(sctp, head);
/* arm rto timer (if not set) */
@@ -1348,7 +1347,7 @@
xtralen = sctp->sctp_hdr_len + sctp_wroff_xtra;
else
xtralen = sctp->sctp_hdr6_len + sctp_wroff_xtra;
- ftsn_mp = allocb(xtralen + seglen, BPRI_MED);
+ ftsn_mp = allocb_cred(xtralen + seglen, CONN_CRED(sctp->sctp_connp));
if (ftsn_mp == NULL)
return (NULL);
ftsn_mp->b_rptr += xtralen;
@@ -1818,8 +1817,8 @@
}
dprint(2, ("sctp_rexmit: Sending packet %d bytes, tsn %x "
"ssn %d to %p (rwnd %d, lastack_rxd %x)\n",
- seglen, ntohl(sdc->sdh_tsn), ntohs(sdc->sdh_ssn), fp,
- sctp->sctp_frwnd, sctp->sctp_lastack_rxd));
+ seglen, ntohl(sdc->sdh_tsn), ntohs(sdc->sdh_ssn),
+ (void *)fp, sctp->sctp_frwnd, sctp->sctp_lastack_rxd));
sctp_set_iplen(sctp, head);
sctp_add_sendq(sctp, head);
--- a/usr/src/uts/common/inet/sctp/sctp_snmp.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/sctp/sctp_snmp.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -33,6 +32,7 @@
#include <sys/tihdr.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
+#include <sys/tsol/tndb.h>
#include <netinet/in.h>
@@ -306,16 +306,23 @@
mblk_t *mp_rem_ctl = NULL;
mblk_t *mp_rem_data;
mblk_t *mp_rem_tail = NULL;
+ mblk_t *mp_attr_ctl = NULL;
+ mblk_t *mp_attr_data;
+ mblk_t *mp_attr_tail = NULL;
struct opthdr *optp;
sctp_t *sctp, *sctp_prev = NULL;
sctp_faddr_t *fp;
mib2_sctpConnEntry_t sce;
mib2_sctpConnLocalEntry_t scle;
mib2_sctpConnRemoteEntry_t scre;
+ mib2_transportMLPEntry_t mlp;
int i;
int l;
int scanned = 0;
zoneid_t zoneid = Q_TO_CONN(q)->conn_zoneid;
+ conn_t *connp;
+ boolean_t needattr;
+ int idx;
/*
* Make copies of the original message.
@@ -326,10 +333,13 @@
mp_conn_ctl = copymsg(mpctl);
mp_local_ctl = copymsg(mpctl);
mp_rem_ctl = copymsg(mpctl);
+ mp_attr_ctl = copymsg(mpctl);
mpdata = mpctl->b_cont;
- if (!mp_conn_ctl || !mp_local_ctl || !mp_rem_ctl || !mpdata) {
+ if (mp_conn_ctl == NULL || mp_local_ctl == NULL ||
+ mp_rem_ctl == NULL || mp_attr_ctl == NULL || mpdata == NULL) {
+ freemsg(mp_attr_ctl);
freemsg(mp_rem_ctl);
freemsg(mp_local_ctl);
freemsg(mp_conn_ctl);
@@ -340,6 +350,7 @@
mp_conn_data = mp_conn_ctl->b_cont;
mp_local_data = mp_local_ctl->b_cont;
mp_rem_data = mp_rem_ctl->b_cont;
+ mp_attr_data = mp_attr_ctl->b_cont;
/* hostname address parameters are not supported in Solaris */
sce.sctpAssocRemHostName.o_length = 0;
@@ -355,6 +366,7 @@
SET_MIB(sctp_mib.sctpMaxInitRetr, sctp_max_init_retr);
SET_MIB(sctp_mib.sctpCurrEstab, 0);
+ idx = 0;
sctp = gsctp;
mutex_enter(&sctp_g_lock);
while (sctp != NULL) {
@@ -492,6 +504,26 @@
(void) snmp_append_data2(mp_rem_data, &mp_rem_tail,
(char *)&scre, sizeof (scre));
}
+ connp = sctp->sctp_connp;
+ needattr = B_FALSE;
+ bzero(&mlp, sizeof (mlp));
+ if (connp->conn_mlp_type != mlptSingle) {
+ if (connp->conn_mlp_type == mlptShared ||
+ connp->conn_mlp_type == mlptBoth)
+ mlp.tme_flags |= MIB2_TMEF_SHARED;
+ if (connp->conn_mlp_type == mlptPrivate ||
+ connp->conn_mlp_type == mlptBoth)
+ mlp.tme_flags |= MIB2_TMEF_PRIVATE;
+ needattr = B_TRUE;
+ }
+ if (connp->conn_peercred != NULL) {
+ ts_label_t *tsl;
+
+ tsl = crgetlabel(connp->conn_peercred);
+ mlp.tme_doi = label2doi(tsl);
+ mlp.tme_label = *label2bslabel(tsl);
+ needattr = B_TRUE;
+ }
WAKE_SCTP(sctp);
sce.sctpAssocState = sctp_snmp_state(sctp);
sce.sctpAssocInStreams = sctp->sctp_num_istr;
@@ -511,6 +543,10 @@
sce.sctpConnEntryInfo.ce_mss = sctp->sctp_mss;
(void) snmp_append_data2(mp_conn_data, &mp_conn_tail,
(char *)&sce, sizeof (sce));
+ mlp.tme_connidx = idx++;
+ if (needattr)
+ (void) snmp_append_data2(mp_attr_ctl->b_cont,
+ &mp_attr_tail, (char *)&mlp, sizeof (mlp));
next_sctp:
sctp_prev = sctp;
mutex_enter(&sctp_g_lock);
@@ -555,6 +591,17 @@
optp->len = msgdsize(mp_rem_data);
qreply(q, mp_rem_ctl);
+ /* table of MLP attributes */
+ optp = (struct opthdr *)&mp_attr_ctl->b_rptr[
+ sizeof (struct T_optmgmt_ack)];
+ optp->level = MIB2_SCTP;
+ optp->name = EXPER_XPORT_MLP;
+ optp->len = msgdsize(mp_attr_data);
+ if (optp->len == 0)
+ freemsg(mp_attr_ctl);
+ else
+ qreply(q, mp_attr_ctl);
+
return (mp_ret);
}
--- a/usr/src/uts/common/inet/sctp/sctp_timer.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/sctp/sctp_timer.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -237,7 +236,7 @@
sctp_tb = (sctp_tb_t *)mp->b_datap->db_base;
state = sctp_tb->sctp_tb_state;
- dprint(5, ("sctp_timer_free %p state %d\n", mp, state));
+ dprint(5, ("sctp_timer_free %p state %d\n", (void *)mp, state));
if (state == SCTP_TB_RUNNING) {
if (untimeout(sctp_tb->sctp_tb_tid) < 0) {
@@ -272,7 +271,7 @@
sctp_tb = (sctp_tb_t *)mp->b_datap->db_base;
state = sctp_tb->sctp_tb_state;
- dprint(5, ("sctp_timer_stop %p %d\n", mp, state));
+ dprint(5, ("sctp_timer_stop %p %d\n", (void *)mp, state));
if (state == SCTP_TB_RUNNING) {
if (untimeout(sctp_tb->sctp_tb_tid) < 0) {
@@ -673,7 +672,7 @@
rtt = (int)delta;
rtt = rtt > 0 ? rtt : 1;
- dprint(5, ("sctp_update_rtt: fp = %p, rtt = %d\n", fp, rtt));
+ dprint(5, ("sctp_update_rtt: fp = %p, rtt = %d\n", (void *)fp, rtt));
/* Is this the first RTT measurement? */
if (fp->srtt == -1) {
--- a/usr/src/uts/common/inet/sctp_ip.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/sctp_ip.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -42,6 +41,9 @@
extern void sctp_ddi_destroy(void);
extern conn_t *sctp_find_conn(in6_addr_t *, in6_addr_t *, uint32_t, uint_t,
zoneid_t);
+extern conn_t *sctp_fanout(in6_addr_t *, in6_addr_t *, uint32_t, uint_t,
+ zoneid_t, mblk_t *);
+
extern void sctp_input(conn_t *, ipha_t *, mblk_t *, mblk_t *, ill_t *,
boolean_t, boolean_t);
extern void sctp_wput(queue_t *, mblk_t *);
--- a/usr/src/uts/common/inet/tcp.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/tcp.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -551,6 +550,7 @@
boolean_t tcp_kssl_inhandshake; /* during SSL handshake */
kssl_ent_t tcp_kssl_ent; /* SSL table entry */
kssl_ctx_t tcp_kssl_ctx; /* SSL session */
+ uint_t tcp_label_len; /* length of cached label */
} tcp_t;
extern void tcp_free(tcp_t *tcp);
--- a/usr/src/uts/common/inet/tcp/tcp.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/tcp/tcp.c Fri Mar 24 12:29:20 2006 -0800
@@ -54,6 +54,7 @@
#include <sys/multidata_impl.h>
#include <sys/pattr.h>
#include <sys/policy.h>
+#include <sys/priv.h>
#include <sys/zone.h>
#include <sys/errno.h>
@@ -95,6 +96,10 @@
#include <inet/ipp_common.h>
#include <sys/squeue.h>
#include <inet/kssl/ksslapi.h>
+#include <sys/tsol/label.h>
+#include <sys/tsol/tnet.h>
+#include <sys/sdt.h>
+#include <rpc/pmap_prot.h>
/*
* TCP Notes: aka FireEngine Phase I (PSARC 2002/433)
@@ -218,7 +223,6 @@
* can be sent out.
*/
-
extern major_t TCP6_MAJ;
/*
@@ -838,7 +842,6 @@
static boolean_t tcp_allow_connopt_set(int level, int name);
int tcp_opt_default(queue_t *q, int level, int name, uchar_t *ptr);
int tcp_opt_get(queue_t *q, int level, int name, uchar_t *ptr);
-static int tcp_opt_get_user(ipha_t *ipha, uchar_t *ptr);
int tcp_opt_set(queue_t *q, uint_t optset_context, int level,
int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp,
uchar_t *outvalp, void *thisdg_attrs, cred_t *cr,
@@ -891,8 +894,9 @@
cred_t *cr);
static void tcp_timer(void *arg);
static void tcp_timer_callback(void *);
-static in_port_t tcp_update_next_port(in_port_t port, boolean_t random);
-static in_port_t tcp_get_next_priv_port(void);
+static in_port_t tcp_update_next_port(in_port_t port, const tcp_t *tcp,
+ boolean_t random);
+static in_port_t tcp_get_next_priv_port(const tcp_t *);
static void tcp_wput_sock(queue_t *q, mblk_t *mp);
void tcp_wput_accept(queue_t *q, mblk_t *mp);
static void tcp_wput_data(tcp_t *tcp, mblk_t *mp, boolean_t urgent);
@@ -912,7 +916,6 @@
int num_sack_blk);
static void tcp_wsrv(queue_t *q);
static int tcp_xmit_end(tcp_t *tcp);
-void tcp_xmit_listeners_reset(mblk_t *mp, uint_t ip_hdr_len);
static mblk_t *tcp_xmit_mp(tcp_t *tcp, mblk_t *mp, int32_t max_to_send,
int32_t *offset, mblk_t **end_mp, uint32_t seq,
boolean_t sendall, uint32_t *seg_len, boolean_t rexmit);
@@ -930,15 +933,8 @@
boolean_t, boolean_t);
static void tcp_icmp_error_ipv6(tcp_t *tcp, mblk_t *mp,
boolean_t ipsec_mctl);
-static boolean_t tcp_cmpbuf(void *a, uint_t alen,
- boolean_t b_valid, void *b, uint_t blen);
-static boolean_t tcp_allocbuf(void **dstp, uint_t *dstlenp,
- boolean_t src_valid, void *src, uint_t srclen);
-static void tcp_savebuf(void **dstp, uint_t *dstlenp,
- boolean_t src_valid, void *src, uint_t srclen);
static mblk_t *tcp_setsockopt_mp(int level, int cmd,
char *opt, int optlen);
-static int tcp_pkt_set(uchar_t *, uint_t, uchar_t **, uint_t *);
static int tcp_build_hdrs(queue_t *, tcp_t *);
static void tcp_time_wait_processing(tcp_t *tcp, mblk_t *mp,
uint32_t seg_seq, uint32_t seg_ack, int seg_len,
@@ -1107,7 +1103,7 @@
kmutex_t tcp_epriv_port_lock;
/*
- * The smallest anonymous port in the priviledged port range which TCP
+ * The smallest anonymous port in the privileged port range which TCP
* looks for free port. Use in the option TCP_ANONPRIVBIND.
*/
static in_port_t tcp_min_anonpriv_port = 512;
@@ -1360,14 +1356,14 @@
/*
* This controls the rate some ndd info report functions can be used
- * by non-priviledged users. It stores the last time such info is
+ * by non-privileged users. It stores the last time such info is
* requested. When those report functions are called again, this
* is checked with the current time and compare with the ndd param
* tcp_ndd_get_info_interval.
*/
static clock_t tcp_last_ndd_get_info_time = 0;
#define NDD_TOO_QUICK_MSG \
- "ndd get info rate too high for non-priviledged users, try again " \
+ "ndd get info rate too high for non-privileged users, try again " \
"later.\n"
#define NDD_OUT_OF_BUF_MSG "<< Out of buffer >>\n"
@@ -1724,6 +1720,10 @@
tcp_iphc_len = tcp->tcp_iphc_len;
tcp_hdr_grown = tcp->tcp_hdr_grown;
+ if (connp->conn_cred != NULL)
+ crfree(connp->conn_cred);
+ if (connp->conn_peercred != NULL)
+ crfree(connp->conn_peercred);
bzero(connp, sizeof (conn_t));
bzero(tcp, sizeof (tcp_t));
@@ -2410,10 +2410,17 @@
ASSERT(eager->tcp_ack_tid == 0);
econnp->conn_dev = aconnp->conn_dev;
+ if (eager->tcp_cred != NULL)
+ crfree(eager->tcp_cred);
eager->tcp_cred = econnp->conn_cred = aconnp->conn_cred;
econnp->conn_zoneid = aconnp->conn_zoneid;
aconnp->conn_cred = NULL;
+ econnp->conn_mac_exempt = aconnp->conn_mac_exempt;
+ aconnp->conn_mac_exempt = B_FALSE;
+
+ ASSERT(aconnp->conn_peercred == NULL);
+
/* Do the IPC initialization */
CONN_INC_REF(econnp);
@@ -2475,6 +2482,9 @@
conn_t *connp = tcp->tcp_connp;
boolean_t ire_cacheable = B_FALSE;
zoneid_t zoneid = connp->conn_zoneid;
+ int match_flags = MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT |
+ MATCH_IRE_SECATTR;
+ ts_label_t *tsl = crgetlabel(CONN_CRED(connp));
ill_t *ill = NULL;
boolean_t incoming = (ire_mp == NULL);
@@ -2493,16 +2503,25 @@
* ire, if it exists, will be marked private.
* If that is not available, use the interface ire
* for the nexthop.
+ *
+ * TSol: tcp_update_label will detect label mismatches based
+ * only on the destination's label, but that would not
+ * detect label mismatches based on the security attributes
+ * of routes or next hop gateway. Hence we need to pass the
+ * label to ire_ftable_lookup below in order to locate the
+ * right prefix (and/or) ire cache. Similarly we also need
+ * pass the label to the ire_cache_lookup below to locate
+ * the right ire that also matches on the label.
*/
if (tcp->tcp_connp->conn_nexthop_set) {
ire = ire_ctable_lookup(tcp->tcp_connp->conn_rem,
tcp->tcp_connp->conn_nexthop_v4, 0, NULL, zoneid,
- MATCH_IRE_MARK_PRIVATE_ADDR | MATCH_IRE_GW);
+ tsl, MATCH_IRE_MARK_PRIVATE_ADDR | MATCH_IRE_GW);
if (ire == NULL) {
ire = ire_ftable_lookup(
tcp->tcp_connp->conn_nexthop_v4,
0, 0, IRE_INTERFACE, NULL, NULL, zoneid, 0,
- MATCH_IRE_TYPE);
+ tsl, match_flags);
if (ire == NULL)
return (0);
} else {
@@ -2510,7 +2529,7 @@
}
} else {
ire = ire_cache_lookup(tcp->tcp_connp->conn_rem,
- zoneid);
+ zoneid, tsl);
if (ire != NULL) {
ire_cacheable = B_TRUE;
ire_uinfo = (ire_mp != NULL) ?
@@ -2522,7 +2541,7 @@
ire = ire_ftable_lookup(
tcp->tcp_connp->conn_rem,
0, 0, 0, NULL, &sire, zoneid, 0,
- (MATCH_IRE_RECURSIVE |
+ tsl, (MATCH_IRE_RECURSIVE |
MATCH_IRE_DEFAULT));
if (ire == NULL)
return (0);
@@ -2601,7 +2620,6 @@
*/
ill_t *dst_ill = NULL;
ipif_t *dst_ipif = NULL;
- int match_flags = MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT;
ASSERT(connp->conn_outgoing_ill == connp->conn_incoming_ill);
@@ -2619,7 +2637,7 @@
dst_ipif = dst_ill->ill_ipif;
}
ire = ire_ctable_lookup_v6(&tcp->tcp_connp->conn_remv6,
- 0, 0, dst_ipif, zoneid, match_flags);
+ 0, 0, dst_ipif, zoneid, tsl, match_flags);
if (ire != NULL) {
ire_cacheable = B_TRUE;
@@ -2631,7 +2649,7 @@
ire = ire_ftable_lookup_v6(
&tcp->tcp_connp->conn_remv6,
0, 0, 0, dst_ipif, &sire, zoneid,
- 0, match_flags);
+ 0, tsl, match_flags);
if (ire == NULL) {
if (dst_ill != NULL)
ill_refrele(dst_ill);
@@ -2955,6 +2973,11 @@
uint_t origipversion;
int err;
queue_t *q = tcp->tcp_wq;
+ conn_t *connp;
+ mlp_type_t addrtype, mlptype;
+ zone_t *zone;
+ cred_t *cr;
+ in_port_t mlp_port;
ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX);
if ((mp->b_wptr - mp->b_rptr) < sizeof (*tbr)) {
@@ -3134,14 +3157,41 @@
* still check for ports only in the range > tcp_smallest_non_priv_port,
* unless TCP_ANONPRIVBIND option is set.
*/
+ mlptype = mlptSingle;
+ mlp_port = requested_port;
if (requested_port == 0) {
requested_port = tcp->tcp_anon_priv_bind ?
- tcp_get_next_priv_port() :
- tcp_update_next_port(tcp_next_port_to_try, B_TRUE);
+ tcp_get_next_priv_port(tcp) :
+ tcp_update_next_port(tcp_next_port_to_try, tcp, B_TRUE);
+ if (requested_port == 0) {
+ tcp_err_ack(tcp, mp, TNOADDR, 0);
+ return;
+ }
user_specified = B_FALSE;
+
+ /*
+ * If the user went through one of the RPC interfaces to create
+ * this socket and RPC is MLP in this zone, then give him an
+ * anonymous MLP.
+ */
+ cr = DB_CREDDEF(mp, tcp->tcp_cred);
+ connp = tcp->tcp_connp;
+ if (connp->conn_anon_mlp && is_system_labeled()) {
+ zone = crgetzone(cr);
+ addrtype = tsol_mlp_addr_type(zone->zone_id,
+ IPV6_VERSION, &v6addr);
+ if (addrtype == mlptSingle) {
+ tcp_err_ack(tcp, mp, TNOADDR, 0);
+ return;
+ }
+ mlptype = tsol_mlp_port_type(zone, IPPROTO_TCP,
+ PMAPPORT, addrtype);
+ mlp_port = PMAPPORT;
+ }
} else {
int i;
boolean_t priv = B_FALSE;
+
/*
* If the requested_port is in the well-known privileged range,
* verify that the stream was opened by a privileged user.
@@ -3151,6 +3201,7 @@
* changes
* - the atomic assignment of the elements of the array
*/
+ cr = DB_CREDDEF(mp, tcp->tcp_cred);
if (requested_port < tcp_smallest_nonpriv_port) {
priv = B_TRUE;
} else {
@@ -3163,8 +3214,6 @@
}
}
if (priv) {
- cred_t *cr = DB_CREDDEF(mp, tcp->tcp_cred);
-
if (secpolicy_net_privaddr(cr, requested_port) != 0) {
if (tcp->tcp_debug) {
(void) strlog(TCP_MOD_ID, 0, 1,
@@ -3177,12 +3226,87 @@
}
}
user_specified = B_TRUE;
+
+ connp = tcp->tcp_connp;
+ if (is_system_labeled()) {
+ zone = crgetzone(cr);
+ addrtype = tsol_mlp_addr_type(zone->zone_id,
+ IPV6_VERSION, &v6addr);
+ if (addrtype == mlptSingle) {
+ tcp_err_ack(tcp, mp, TNOADDR, 0);
+ return;
+ }
+ mlptype = tsol_mlp_port_type(zone, IPPROTO_TCP,
+ requested_port, addrtype);
+ }
+ }
+
+ if (mlptype != mlptSingle) {
+ if (secpolicy_net_bindmlp(cr) != 0) {
+ if (tcp->tcp_debug) {
+ (void) strlog(TCP_MOD_ID, 0, 1,
+ SL_ERROR|SL_TRACE,
+ "tcp_bind: no priv for multilevel port %d",
+ requested_port);
+ }
+ tcp_err_ack(tcp, mp, TACCES, 0);
+ return;
+ }
+
+ /*
+ * If we're specifically binding a shared IP address and the
+ * port is MLP on shared addresses, then check to see if this
+ * zone actually owns the MLP. Reject if not.
+ */
+ if (mlptype == mlptShared && addrtype == mlptShared) {
+ zoneid_t mlpzone;
+
+ mlpzone = tsol_mlp_findzone(IPPROTO_TCP,
+ htons(mlp_port));
+ if (connp->conn_zoneid != mlpzone) {
+ if (tcp->tcp_debug) {
+ (void) strlog(TCP_MOD_ID, 0, 1,
+ SL_ERROR|SL_TRACE,
+ "tcp_bind: attempt to bind port "
+ "%d on shared addr in zone %d "
+ "(should be %d)",
+ mlp_port, connp->conn_zoneid,
+ mlpzone);
+ }
+ tcp_err_ack(tcp, mp, TACCES, 0);
+ return;
+ }
+ }
+
+ if (!user_specified) {
+ err = tsol_mlp_anon(zone, mlptype, connp->conn_ulp,
+ requested_port, B_TRUE);
+ if (err != 0) {
+ if (tcp->tcp_debug) {
+ (void) strlog(TCP_MOD_ID, 0, 1,
+ SL_ERROR|SL_TRACE,
+ "tcp_bind: cannot establish anon "
+ "MLP for port %d",
+ requested_port);
+ }
+ tcp_err_ack(tcp, mp, TSYSERR, err);
+ return;
+ }
+ connp->conn_anon_port = B_TRUE;
+ }
+ connp->conn_mlp_type = mlptype;
}
allocated_port = tcp_bindi(tcp, requested_port, &v6addr,
tcp->tcp_reuseaddr, B_FALSE, bind_to_req_port_only, user_specified);
if (allocated_port == 0) {
+ connp->conn_mlp_type = mlptSingle;
+ if (connp->conn_anon_port) {
+ connp->conn_anon_port = B_FALSE;
+ (void) tsol_mlp_anon(zone, mlptype, connp->conn_ulp,
+ requested_port, B_FALSE);
+ }
if (bind_to_req_port_only) {
if (tcp->tcp_debug) {
(void) strlog(TCP_MOD_ID, 0, 1,
@@ -3227,7 +3351,13 @@
IPV6_ADDR_LEN);
}
}
- if (!mp1) {
+ if (mp1 == NULL) {
+ if (connp->conn_anon_port) {
+ connp->conn_anon_port = B_FALSE;
+ (void) tsol_mlp_anon(zone, mlptype, connp->conn_ulp,
+ requested_port, B_FALSE);
+ }
+ connp->conn_mlp_type = mlptSingle;
tcp_err_ack(tcp, mp, TSYSERR, ENOMEM);
return;
}
@@ -3314,7 +3444,8 @@
int count = 0;
/* maximum number of times to run around the loop */
int loopmax;
- zoneid_t zoneid = tcp->tcp_connp->conn_zoneid;
+ conn_t *connp = tcp->tcp_connp;
+ zoneid_t zoneid = connp->conn_zoneid;
/*
* Lookup for free addresses is done in a loop and "loopmax"
@@ -3349,6 +3480,7 @@
uint16_t lport;
tf_t *tbf;
tcp_t *ltcp;
+ conn_t *lconnp;
lport = htons(port);
@@ -3368,10 +3500,21 @@
mutex_enter(&tbf->tf_lock);
for (ltcp = tbf->tf_tcp; ltcp != NULL;
ltcp = ltcp->tcp_bind_hash) {
- if (lport != ltcp->tcp_lport ||
- ltcp->tcp_connp->conn_zoneid != zoneid) {
+ if (lport != ltcp->tcp_lport)
continue;
- }
+
+ lconnp = ltcp->tcp_connp;
+
+ /*
+ * On a labeled system, we must treat bindings to ports
+ * on shared IP addresses by sockets with MAC exemption
+ * privilege as being in all zones, as there's
+ * otherwise no way to identify the right receiver.
+ */
+ if (lconnp->conn_zoneid != zoneid &&
+ !lconnp->conn_mac_exempt &&
+ !connp->conn_mac_exempt)
+ continue;
/*
* If TCP_EXCLBIND is set for either the bound or
@@ -3389,6 +3532,9 @@
* spec unspec no
* spec spec yes if A
*
+ * For labeled systems, SO_MAC_EXEMPT behaves the same
+ * as UDP_EXCLBIND, except that zoneid is ignored.
+ *
* Note:
*
* 1. Because of TLI semantics, an endpoint can go
@@ -3416,7 +3562,8 @@
* in future, we can change this going back semantics,
* we can add the above check.
*/
- if (ltcp->tcp_exclbind || tcp->tcp_exclbind) {
+ if (ltcp->tcp_exclbind || tcp->tcp_exclbind ||
+ lconnp->conn_mac_exempt || connp->conn_mac_exempt) {
if (V6_OR_V4_INADDR_ANY(
ltcp->tcp_bound_source_v6) ||
V6_OR_V4_INADDR_ANY(*laddr) ||
@@ -3538,7 +3685,7 @@
}
if (tcp->tcp_anon_priv_bind) {
- port = tcp_get_next_priv_port();
+ port = tcp_get_next_priv_port(tcp);
} else {
if (count == 0 && user_specified) {
/*
@@ -3547,12 +3694,15 @@
*/
port =
tcp_update_next_port(tcp_next_port_to_try,
- B_TRUE);
+ tcp, B_TRUE);
user_specified = B_FALSE;
} else {
- port = tcp_update_next_port(port + 1, B_FALSE);
- }
- }
+ port = tcp_update_next_port(port + 1, tcp,
+ B_FALSE);
+ }
+ }
+ if (port == 0)
+ break;
/*
* Don't let this loop run forever in the case where
@@ -3821,9 +3971,6 @@
qprocsoff(q);
inet_minor_free(ip_minor_arena, connp->conn_dev);
- ASSERT(connp->conn_cred != NULL);
- crfree(connp->conn_cred);
- tcp->tcp_cred = connp->conn_cred = NULL;
tcp->tcp_cpid = -1;
/*
@@ -4327,31 +4474,9 @@
ASSERT(tcp->tcp_rthdrlen == 0);
ipp = &tcp->tcp_sticky_ipp;
- if ((ipp->ipp_fields & (IPPF_HOPOPTS | IPPF_RTDSTOPTS |
- IPPF_DSTOPTS | IPPF_RTHDR)) != 0) {
- if ((ipp->ipp_fields & IPPF_HOPOPTS) != 0) {
- kmem_free(ipp->ipp_hopopts, ipp->ipp_hopoptslen);
- ipp->ipp_hopopts = NULL;
- ipp->ipp_hopoptslen = 0;
- }
- if ((ipp->ipp_fields & IPPF_RTDSTOPTS) != 0) {
- kmem_free(ipp->ipp_rtdstopts, ipp->ipp_rtdstoptslen);
- ipp->ipp_rtdstopts = NULL;
- ipp->ipp_rtdstoptslen = 0;
- }
- if ((ipp->ipp_fields & IPPF_DSTOPTS) != 0) {
- kmem_free(ipp->ipp_dstopts, ipp->ipp_dstoptslen);
- ipp->ipp_dstopts = NULL;
- ipp->ipp_dstoptslen = 0;
- }
- if ((ipp->ipp_fields & IPPF_RTHDR) != 0) {
- kmem_free(ipp->ipp_rthdr, ipp->ipp_rthdrlen);
- ipp->ipp_rthdr = NULL;
- ipp->ipp_rthdrlen = 0;
- }
- ipp->ipp_fields &= ~(IPPF_HOPOPTS | IPPF_RTDSTOPTS |
- IPPF_DSTOPTS | IPPF_RTHDR);
- }
+ if (ipp->ipp_fields & (IPPF_HOPOPTS | IPPF_RTDSTOPTS | IPPF_DSTOPTS |
+ IPPF_RTHDR))
+ ip6_pkt_free(ipp);
/*
* Free memory associated with the tcp/ip header template.
@@ -5096,6 +5221,59 @@
return ((void *)connp);
}
+/*
+ * Update the cached label for the given tcp_t. This should be called once per
+ * connection, and before any packets are sent or tcp_process_options is
+ * invoked. Returns B_FALSE if the correct label could not be constructed.
+ */
+static boolean_t
+tcp_update_label(tcp_t *tcp, const cred_t *cr)
+{
+ conn_t *connp = tcp->tcp_connp;
+
+ if (tcp->tcp_ipversion == IPV4_VERSION) {
+ uchar_t optbuf[IP_MAX_OPT_LENGTH];
+ int added;
+
+ if (tsol_compute_label(cr, tcp->tcp_remote, optbuf,
+ connp->conn_mac_exempt) != 0)
+ return (B_FALSE);
+
+ added = tsol_remove_secopt(tcp->tcp_ipha, tcp->tcp_hdr_len);
+ if (added == -1)
+ return (B_FALSE);
+ tcp->tcp_hdr_len += added;
+ tcp->tcp_tcph = (tcph_t *)((uchar_t *)tcp->tcp_tcph + added);
+ tcp->tcp_ip_hdr_len += added;
+ if ((tcp->tcp_label_len = optbuf[IPOPT_OLEN]) != 0) {
+ tcp->tcp_label_len = (tcp->tcp_label_len + 3) & ~3;
+ added = tsol_prepend_option(optbuf, tcp->tcp_ipha,
+ tcp->tcp_hdr_len);
+ if (added == -1)
+ return (B_FALSE);
+ tcp->tcp_hdr_len += added;
+ tcp->tcp_tcph = (tcph_t *)
+ ((uchar_t *)tcp->tcp_tcph + added);
+ tcp->tcp_ip_hdr_len += added;
+ }
+ } else {
+ uchar_t optbuf[TSOL_MAX_IPV6_OPTION];
+
+ if (tsol_compute_label_v6(cr, &tcp->tcp_remote_v6, optbuf,
+ connp->conn_mac_exempt) != 0)
+ return (B_FALSE);
+ if (tsol_update_sticky(&tcp->tcp_sticky_ipp,
+ &tcp->tcp_label_len, optbuf) != 0)
+ return (B_FALSE);
+ if (tcp_build_hdrs(tcp->tcp_rq, tcp) != 0)
+ return (B_FALSE);
+ }
+
+ connp->conn_ulp_labeled = 1;
+
+ return (B_TRUE);
+}
+
/* BEGIN CSTYLED */
/*
*
@@ -5232,6 +5410,7 @@
conn_t *connp = (conn_t *)arg;
tcp_t *tcp = connp->conn_tcp;
ire_t *ire;
+ cred_t *credp;
if (tcp->tcp_state != TCPS_LISTEN)
goto error2;
@@ -5377,6 +5556,46 @@
econnp->conn_nexthop_v4 = connp->conn_nexthop_v4;
}
+ /*
+ * TSOL: tsol_input_proc() needs the eager's cred before the
+ * eager is accepted
+ */
+ econnp->conn_cred = eager->tcp_cred = credp = connp->conn_cred;
+ crhold(credp);
+
+ /*
+ * If the caller has the process-wide flag set, then default to MAC
+ * exempt mode. This allows read-down to unlabeled hosts.
+ */
+ if (getpflags(NET_MAC_AWARE, credp) != 0)
+ econnp->conn_mac_exempt = B_TRUE;
+
+ if (is_system_labeled()) {
+ cred_t *cr;
+
+ if (connp->conn_mlp_type != mlptSingle) {
+ cr = econnp->conn_peercred = DB_CRED(mp);
+ if (cr != NULL)
+ crhold(cr);
+ else
+ cr = econnp->conn_cred;
+ DTRACE_PROBE2(mlp_syn_accept, conn_t *,
+ econnp, cred_t *, cr)
+ } else {
+ cr = econnp->conn_cred;
+ DTRACE_PROBE2(syn_accept, conn_t *,
+ econnp, cred_t *, cr)
+ }
+
+ if (!tcp_update_label(eager, cr)) {
+ DTRACE_PROBE3(
+ tx__ip__log__error__connrequest__tcp,
+ char *, "eager connp(1) label on SYN mp(2) failed",
+ conn_t *, econnp, mblk_t *, mp);
+ goto error3;
+ }
+ }
+
eager->tcp_hard_binding = B_TRUE;
tcp_bind_hash_insert(&tcp_bind_fanout[
@@ -5530,7 +5749,6 @@
NULL, NULL, eager->tcp_iss, B_FALSE, NULL, B_FALSE);
if (mp1 == NULL)
goto error1;
- mblk_setcred(mp1, tcp->tcp_cred);
DB_CPID(mp1) = tcp->tcp_cpid;
/*
@@ -6107,7 +6325,7 @@
* tcp_bindi will pick an unused port, insert the connection
* in the bind hash and transition to BOUND state.
*/
- lport = tcp_update_next_port(tcp_next_port_to_try, B_TRUE);
+ lport = tcp_update_next_port(tcp_next_port_to_try, tcp, B_TRUE);
lport = tcp_bindi(tcp, lport, &tcp->tcp_ip_src_v6, 0, B_TRUE,
B_FALSE, B_FALSE);
if (lport == 0) {
@@ -6140,6 +6358,7 @@
if (mp1) {
/* Hang onto the T_OK_ACK for later. */
linkb(mp1, mp);
+ mblk_setcred(mp1, tcp->tcp_cred);
if (tcp->tcp_family == AF_INET)
mp1 = ip_bind_v4(tcp->tcp_wq, mp1, tcp->tcp_connp);
else {
@@ -6304,7 +6523,7 @@
* tcp_bindi will pick an unused port, insert the connection
* in the bind hash and transition to BOUND state.
*/
- lport = tcp_update_next_port(tcp_next_port_to_try, B_TRUE);
+ lport = tcp_update_next_port(tcp_next_port_to_try, tcp, B_TRUE);
lport = tcp_bindi(tcp, lport, &tcp->tcp_ip_src_v6, 0, B_TRUE,
B_FALSE, B_FALSE);
if (lport == 0) {
@@ -6330,6 +6549,7 @@
if (mp1) {
/* Hang onto the T_OK_ACK for later. */
linkb(mp1, mp);
+ mblk_setcred(mp1, tcp->tcp_cred);
mp1 = ip_bind_v6(tcp->tcp_wq, mp1, tcp->tcp_connp,
&tcp->tcp_sticky_ipp);
BUMP_MIB(&tcp_mib, tcpActiveOpens);
@@ -7798,6 +8018,7 @@
{
tcph_t *tcph;
uint32_t sum;
+ conn_t *connp;
/*
* This is a simple initialization. If there's
@@ -7813,6 +8034,11 @@
return (ENOMEM);
}
}
+
+ /* options are gone; may need a new label */
+ connp = tcp->tcp_connp;
+ connp->conn_mlp_type = mlptSingle;
+ connp->conn_ulp_labeled = !is_system_labeled();
ASSERT(tcp->tcp_iphc_len >= TCP_MAX_COMBINED_HEADER_LENGTH);
tcp->tcp_ipha = (ipha_t *)tcp->tcp_iphc;
tcp->tcp_ip6h = NULL;
@@ -7854,6 +8080,7 @@
{
tcph_t *tcph;
uint32_t sum;
+ conn_t *connp;
/*
* This is a simple initialization. If there's
@@ -7877,6 +8104,12 @@
return (ENOMEM);
}
}
+
+ /* options are gone; may need a new label */
+ connp = tcp->tcp_connp;
+ connp->conn_mlp_type = mlptSingle;
+ connp->conn_ulp_labeled = !is_system_labeled();
+
ASSERT(tcp->tcp_iphc_len >= TCP_MAX_COMBINED_HEADER_LENGTH);
tcp->tcp_ipversion = IPV6_VERSION;
tcp->tcp_hdr_len = IPV6_HDR_LEN + sizeof (tcph_t);
@@ -9147,6 +9380,15 @@
crhold(connp->conn_cred);
tcp->tcp_cpid = curproc->p_pid;
connp->conn_zoneid = zoneid;
+ connp->conn_mlp_type = mlptSingle;
+ connp->conn_ulp_labeled = !is_system_labeled();
+
+ /*
+ * If the caller has the process-wide flag set, then default to MAC
+ * exempt mode. This allows read-down to unlabeled hosts.
+ */
+ if (getpflags(NET_MAC_AWARE, credp) != 0)
+ connp->conn_mac_exempt = B_TRUE;
connp->conn_dev = conn_dev;
@@ -9345,6 +9587,12 @@
*i1 = tcp->tcp_snd_zcopy_on ?
SO_SND_COPYAVOID : 0;
break;
+ case SO_ANON_MLP:
+ *i1 = connp->conn_anon_mlp;
+ break;
+ case SO_MAC_EXEMPT:
+ *i1 = connp->conn_mac_exempt;
+ break;
default:
return (-1);
}
@@ -9406,17 +9654,18 @@
* as the last entry. The first 4 bytes of the option
* will contain the final destination.
*/
- char *opt_ptr;
int opt_len;
- opt_ptr = (char *)tcp->tcp_ipha + IP_SIMPLE_HDR_LENGTH;
- opt_len = (char *)tcp->tcp_tcph - opt_ptr;
+
+ opt_len = (char *)tcp->tcp_tcph - (char *)tcp->tcp_ipha;
+ opt_len -= tcp->tcp_label_len + IP_SIMPLE_HDR_LENGTH;
+ ASSERT(opt_len >= 0);
/* Caller ensures enough space */
if (opt_len > 0) {
/*
* TODO: Do we have to handle getsockopt on an
* initiator as well?
*/
- return (tcp_opt_get_user(tcp->tcp_ipha, ptr));
+ return (ip_opt_get_user(tcp->tcp_ipha, ptr));
}
return (0);
}
@@ -9536,8 +9785,16 @@
case IPV6_HOPOPTS:
if (!(ipp->ipp_fields & IPPF_HOPOPTS))
return (0);
- bcopy(ipp->ipp_hopopts, ptr, ipp->ipp_hopoptslen);
- return (ipp->ipp_hopoptslen);
+ if (ipp->ipp_hopoptslen <= tcp->tcp_label_len)
+ return (0);
+ bcopy((char *)ipp->ipp_hopopts + tcp->tcp_label_len,
+ ptr, ipp->ipp_hopoptslen - tcp->tcp_label_len);
+ if (tcp->tcp_label_len > 0) {
+ ptr[0] = ((char *)ipp->ipp_hopopts)[0];
+ ptr[1] = (ipp->ipp_hopoptslen -
+ tcp->tcp_label_len + 7) / 8 - 1;
+ }
+ return (ipp->ipp_hopoptslen - tcp->tcp_label_len);
case IPV6_RTHDRDSTOPTS:
if (!(ipp->ipp_fields & IPPF_RTDSTOPTS))
return (0);
@@ -9585,7 +9842,8 @@
uint_t inlen, uchar_t *invalp, uint_t *outlenp, uchar_t *outvalp,
void *thisdg_attrs, cred_t *cr, mblk_t *mblk)
{
- tcp_t *tcp = Q_TO_TCP(q);
+ conn_t *connp = Q_TO_CONN(q);
+ tcp_t *tcp = connp->conn_tcp;
int *i1 = (int *)invalp;
boolean_t onoff = (*i1 == 0) ? 0 : 1;
boolean_t checkonly;
@@ -9713,7 +9971,7 @@
break;
case SO_DONTROUTE:
/*
- * SO_DONTROUTE, SO_USELOOPBACK and SO_BROADCAST are
+ * SO_DONTROUTE, SO_USELOOPBACK, and SO_BROADCAST are
* only of interest to IP. We track them here only so
* that we can report their current value.
*/
@@ -9814,6 +10072,23 @@
tcp->tcp_snd_zcopy_aware = 1;
}
break;
+ case SO_ANON_MLP:
+ if (!checkonly) {
+ mutex_enter(&connp->conn_lock);
+ connp->conn_anon_mlp = onoff;
+ mutex_exit(&connp->conn_lock);
+ }
+ break;
+ case SO_MAC_EXEMPT:
+ if (secpolicy_net_mac_aware(cr) != 0 ||
+ IPCL_IS_BOUND(connp))
+ return (EACCES);
+ if (!checkonly) {
+ mutex_enter(&connp->conn_lock);
+ connp->conn_mac_exempt = onoff;
+ mutex_exit(&connp->conn_lock);
+ }
+ break;
default:
*outlenp = 0;
return (EINVAL);
@@ -10241,6 +10516,7 @@
break;
case IPV6_HOPOPTS: {
ip6_hbh_t *hopts = (ip6_hbh_t *)invalp;
+
/*
* Sanity checks - minimum size, size a multiple of
* eight bytes, and matching size passed in.
@@ -10252,22 +10528,15 @@
if (checkonly)
break;
- if (inlen == 0) {
- if ((ipp->ipp_fields & IPPF_HOPOPTS) != 0) {
- kmem_free(ipp->ipp_hopopts,
- ipp->ipp_hopoptslen);
- ipp->ipp_hopopts = NULL;
- ipp->ipp_hopoptslen = 0;
- }
+ reterr = optcom_pkt_set(invalp, inlen, B_TRUE,
+ (uchar_t **)&ipp->ipp_hopopts,
+ &ipp->ipp_hopoptslen, tcp->tcp_label_len);
+ if (reterr != 0)
+ return (reterr);
+ if (ipp->ipp_hopoptslen == 0)
ipp->ipp_fields &= ~IPPF_HOPOPTS;
- } else {
- reterr = tcp_pkt_set(invalp, inlen,
- (uchar_t **)&ipp->ipp_hopopts,
- &ipp->ipp_hopoptslen);
- if (reterr != 0)
- return (reterr);
+ else
ipp->ipp_fields |= IPPF_HOPOPTS;
- }
reterr = tcp_build_hdrs(q, tcp);
if (reterr != 0)
return (reterr);
@@ -10287,22 +10556,15 @@
if (checkonly)
break;
- if (inlen == 0) {
- if ((ipp->ipp_fields & IPPF_RTDSTOPTS) != 0) {
- kmem_free(ipp->ipp_rtdstopts,
- ipp->ipp_rtdstoptslen);
- ipp->ipp_rtdstopts = NULL;
- ipp->ipp_rtdstoptslen = 0;
- }
+ reterr = optcom_pkt_set(invalp, inlen, B_TRUE,
+ (uchar_t **)&ipp->ipp_rtdstopts,
+ &ipp->ipp_rtdstoptslen, 0);
+ if (reterr != 0)
+ return (reterr);
+ if (ipp->ipp_rtdstoptslen == 0)
ipp->ipp_fields &= ~IPPF_RTDSTOPTS;
- } else {
- reterr = tcp_pkt_set(invalp, inlen,
- (uchar_t **)&ipp->ipp_rtdstopts,
- &ipp->ipp_rtdstoptslen);
- if (reterr != 0)
- return (reterr);
+ else
ipp->ipp_fields |= IPPF_RTDSTOPTS;
- }
reterr = tcp_build_hdrs(q, tcp);
if (reterr != 0)
return (reterr);
@@ -10322,22 +10584,15 @@
if (checkonly)
break;
- if (inlen == 0) {
- if ((ipp->ipp_fields & IPPF_DSTOPTS) != 0) {
- kmem_free(ipp->ipp_dstopts,
- ipp->ipp_dstoptslen);
- ipp->ipp_dstopts = NULL;
- ipp->ipp_dstoptslen = 0;
- }
+ reterr = optcom_pkt_set(invalp, inlen, B_TRUE,
+ (uchar_t **)&ipp->ipp_dstopts,
+ &ipp->ipp_dstoptslen, 0);
+ if (reterr != 0)
+ return (reterr);
+ if (ipp->ipp_dstoptslen == 0)
ipp->ipp_fields &= ~IPPF_DSTOPTS;
- } else {
- reterr = tcp_pkt_set(invalp, inlen,
- (uchar_t **)&ipp->ipp_dstopts,
- &ipp->ipp_dstoptslen);
- if (reterr != 0)
- return (reterr);
+ else
ipp->ipp_fields |= IPPF_DSTOPTS;
- }
reterr = tcp_build_hdrs(q, tcp);
if (reterr != 0)
return (reterr);
@@ -10357,22 +10612,15 @@
if (checkonly)
break;
- if (inlen == 0) {
- if ((ipp->ipp_fields & IPPF_RTHDR) != 0) {
- kmem_free(ipp->ipp_rthdr,
- ipp->ipp_rthdrlen);
- ipp->ipp_rthdr = NULL;
- ipp->ipp_rthdrlen = 0;
- }
+ reterr = optcom_pkt_set(invalp, inlen, B_TRUE,
+ (uchar_t **)&ipp->ipp_rthdr,
+ &ipp->ipp_rthdrlen, 0);
+ if (reterr != 0)
+ return (reterr);
+ if (ipp->ipp_rthdrlen == 0)
ipp->ipp_fields &= ~IPPF_RTHDR;
- } else {
- reterr = tcp_pkt_set(invalp, inlen,
- (uchar_t **)&ipp->ipp_rthdr,
- &ipp->ipp_rthdrlen);
- if (reterr != 0)
- return (reterr);
+ else
ipp->ipp_fields |= IPPF_RTHDR;
- }
reterr = tcp_build_hdrs(q, tcp);
if (reterr != 0)
return (reterr);
@@ -10545,116 +10793,6 @@
}
/*
- * Set optbuf and optlen for the option.
- * Allocate memory (if not already present).
- * Otherwise just point optbuf and optlen at invalp and inlen.
- * Returns failure if memory can not be allocated.
- */
-static int
-tcp_pkt_set(uchar_t *invalp, uint_t inlen, uchar_t **optbufp, uint_t *optlenp)
-{
- uchar_t *optbuf;
-
- if (inlen == *optlenp) {
- /* Unchanged length - no need to realocate */
- bcopy(invalp, *optbufp, inlen);
- return (0);
- }
- if (inlen != 0) {
- /* Allocate new buffer before free */
- optbuf = kmem_alloc(inlen, KM_NOSLEEP);
- if (optbuf == NULL)
- return (ENOMEM);
- } else {
- optbuf = NULL;
- }
- /* Free old buffer */
- if (*optlenp != 0)
- kmem_free(*optbufp, *optlenp);
-
- bcopy(invalp, optbuf, inlen);
- *optbufp = optbuf;
- *optlenp = inlen;
- return (0);
-}
-
-
-/*
- * Use the outgoing IP header to create an IP_OPTIONS option the way
- * it was passed down from the application.
- */
-static int
-tcp_opt_get_user(ipha_t *ipha, uchar_t *buf)
-{
- ipoptp_t opts;
- uchar_t *opt;
- uint8_t optval;
- uint8_t optlen;
- uint32_t len = 0;
- uchar_t *buf1 = buf;
-
- buf += IP_ADDR_LEN; /* Leave room for final destination */
- len += IP_ADDR_LEN;
- bzero(buf1, IP_ADDR_LEN);
-
- for (optval = ipoptp_first(&opts, ipha);
- optval != IPOPT_EOL;
- optval = ipoptp_next(&opts)) {
- opt = opts.ipoptp_cur;
- optlen = opts.ipoptp_len;
- switch (optval) {
- int off;
- case IPOPT_SSRR:
- case IPOPT_LSRR:
-
- /*
- * Insert ipha_dst as the first entry in the source
- * route and move down the entries on step.
- * The last entry gets placed at buf1.
- */
- buf[IPOPT_OPTVAL] = optval;
- buf[IPOPT_OLEN] = optlen;
- buf[IPOPT_OFFSET] = optlen;
-
- off = optlen - IP_ADDR_LEN;
- if (off < 0) {
- /* No entries in source route */
- break;
- }
- /* Last entry in source route */
- bcopy(opt + off, buf1, IP_ADDR_LEN);
- off -= IP_ADDR_LEN;
-
- while (off > 0) {
- bcopy(opt + off,
- buf + off + IP_ADDR_LEN,
- IP_ADDR_LEN);
- off -= IP_ADDR_LEN;
- }
- /* ipha_dst into first slot */
- bcopy(&ipha->ipha_dst,
- buf + off + IP_ADDR_LEN,
- IP_ADDR_LEN);
- buf += optlen;
- len += optlen;
- break;
- default:
- bcopy(opt, buf, optlen);
- buf += optlen;
- len += optlen;
- break;
- }
- }
-done:
- /* Pad the resulting options */
- while (len & 0x3) {
- *buf++ = IPOPT_EOL;
- len++;
- }
- return (len);
-}
-
-/*
* Transfer any source route option from ipha to buf/dst in reversed form.
*/
static int
@@ -10774,41 +10912,46 @@
tcp_opt_set_header(tcp_t *tcp, boolean_t checkonly, uchar_t *ptr, uint_t len)
{
uint_t tcph_len;
- char *ip_optp;
+ uint8_t *ip_optp;
tcph_t *new_tcph;
+ if ((len > TCP_MAX_IP_OPTIONS_LENGTH) || (len & 0x3))
+ return (EINVAL);
+
+ if (len > IP_MAX_OPT_LENGTH - tcp->tcp_label_len)
+ return (EINVAL);
+
if (checkonly) {
/*
* do not really set, just pretend to - T_CHECK
*/
- if (len != 0) {
- /*
- * there is value supplied, validate it as if
- * for a real set operation.
- */
- if ((len > TCP_MAX_IP_OPTIONS_LENGTH) || (len & 0x3))
- return (EINVAL);
- }
return (0);
}
- if ((len > TCP_MAX_IP_OPTIONS_LENGTH) || (len & 0x3))
- return (EINVAL);
-
- ip_optp = (char *)tcp->tcp_ipha + IP_SIMPLE_HDR_LENGTH;
+ ip_optp = (uint8_t *)tcp->tcp_ipha + IP_SIMPLE_HDR_LENGTH;
+ if (tcp->tcp_label_len > 0) {
+ int padlen;
+ uint8_t opt;
+
+ /* convert list termination to no-ops */
+ padlen = tcp->tcp_label_len - ip_optp[IPOPT_OLEN];
+ ip_optp += ip_optp[IPOPT_OLEN];
+ opt = len > 0 ? IPOPT_NOP : IPOPT_EOL;
+ while (--padlen >= 0)
+ *ip_optp++ = opt;
+ }
tcph_len = tcp->tcp_tcp_hdr_len;
new_tcph = (tcph_t *)(ip_optp + len);
- ovbcopy((char *)tcp->tcp_tcph, (char *)new_tcph, tcph_len);
+ ovbcopy(tcp->tcp_tcph, new_tcph, tcph_len);
tcp->tcp_tcph = new_tcph;
bcopy(ptr, ip_optp, len);
- len += IP_SIMPLE_HDR_LENGTH;
+ len += IP_SIMPLE_HDR_LENGTH + tcp->tcp_label_len;
tcp->tcp_ip_hdr_len = len;
tcp->tcp_ipha->ipha_version_and_hdr_length =
- (IP_VERSION << 4) | (len >> 2);
- len += tcph_len;
- tcp->tcp_hdr_len = len;
+ (IP_VERSION << 4) | (len >> 2);
+ tcp->tcp_hdr_len = len + tcph_len;
if (!TCP_IS_DETACHED(tcp)) {
/* Always allocate room for all options. */
(void) mi_set_sth_wroff(tcp->tcp_rq,
@@ -12601,7 +12744,6 @@
mp1 = tcp_xmit_mp(tcp, tcp->tcp_xmit_head, tcp->tcp_mss,
NULL, NULL, tcp->tcp_iss, B_FALSE, NULL, B_FALSE);
if (mp1) {
- mblk_setcred(mp1, tcp->tcp_cred);
DB_CPID(mp1) = tcp->tcp_cpid;
TCP_RECORD_TRACE(tcp, mp1, TCP_TRACE_SEND_PKT);
tcp_send_data(tcp, tcp->tcp_wq, mp1);
@@ -14723,57 +14865,59 @@
optlen += sizeof (struct T_opthdr) + sizeof (uint_t);
addflag |= TCP_IPV6_RECVTCLASS;
}
- /* If app asked for hopbyhop headers and it has changed ... */
+ /*
+ * If app asked for hopbyhop headers and it has changed ...
+ * For security labels, note that (1) security labels can't change on
+ * a connected socket at all, (2) we're connected to at most one peer,
+ * (3) if anything changes, then it must be some other extra option.
+ */
if ((tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVHOPOPTS) &&
- tcp_cmpbuf(tcp->tcp_hopopts, tcp->tcp_hopoptslen,
- (ipp->ipp_fields & IPPF_HOPOPTS),
- ipp->ipp_hopopts, ipp->ipp_hopoptslen)) {
- optlen += sizeof (struct T_opthdr) + ipp->ipp_hopoptslen;
+ ip_cmpbuf(tcp->tcp_hopopts, tcp->tcp_hopoptslen,
+ (ipp->ipp_fields & IPPF_HOPOPTS),
+ ipp->ipp_hopopts, ipp->ipp_hopoptslen)) {
+ optlen += sizeof (struct T_opthdr) + ipp->ipp_hopoptslen -
+ tcp->tcp_label_len;
addflag |= TCP_IPV6_RECVHOPOPTS;
- if (!tcp_allocbuf((void **)&tcp->tcp_hopopts,
- &tcp->tcp_hopoptslen,
- (ipp->ipp_fields & IPPF_HOPOPTS),
+ if (!ip_allocbuf((void **)&tcp->tcp_hopopts,
+ &tcp->tcp_hopoptslen, (ipp->ipp_fields & IPPF_HOPOPTS),
ipp->ipp_hopopts, ipp->ipp_hopoptslen))
return (mp);
}
/* If app asked for dst headers before routing headers ... */
if ((tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVRTDSTOPTS) &&
- tcp_cmpbuf(tcp->tcp_rtdstopts, tcp->tcp_rtdstoptslen,
+ ip_cmpbuf(tcp->tcp_rtdstopts, tcp->tcp_rtdstoptslen,
(ipp->ipp_fields & IPPF_RTDSTOPTS),
ipp->ipp_rtdstopts, ipp->ipp_rtdstoptslen)) {
optlen += sizeof (struct T_opthdr) +
ipp->ipp_rtdstoptslen;
addflag |= TCP_IPV6_RECVRTDSTOPTS;
- if (!tcp_allocbuf((void **)&tcp->tcp_rtdstopts,
- &tcp->tcp_rtdstoptslen,
- (ipp->ipp_fields & IPPF_RTDSTOPTS),
+ if (!ip_allocbuf((void **)&tcp->tcp_rtdstopts,
+ &tcp->tcp_rtdstoptslen, (ipp->ipp_fields & IPPF_RTDSTOPTS),
ipp->ipp_rtdstopts, ipp->ipp_rtdstoptslen))
return (mp);
}
/* If app asked for routing headers and it has changed ... */
if ((tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVRTHDR) &&
- tcp_cmpbuf(tcp->tcp_rthdr, tcp->tcp_rthdrlen,
- (ipp->ipp_fields & IPPF_RTHDR),
- ipp->ipp_rthdr, ipp->ipp_rthdrlen)) {
+ ip_cmpbuf(tcp->tcp_rthdr, tcp->tcp_rthdrlen,
+ (ipp->ipp_fields & IPPF_RTHDR),
+ ipp->ipp_rthdr, ipp->ipp_rthdrlen)) {
optlen += sizeof (struct T_opthdr) + ipp->ipp_rthdrlen;
addflag |= TCP_IPV6_RECVRTHDR;
- if (!tcp_allocbuf((void **)&tcp->tcp_rthdr,
- &tcp->tcp_rthdrlen,
- (ipp->ipp_fields & IPPF_RTHDR),
+ if (!ip_allocbuf((void **)&tcp->tcp_rthdr,
+ &tcp->tcp_rthdrlen, (ipp->ipp_fields & IPPF_RTHDR),
ipp->ipp_rthdr, ipp->ipp_rthdrlen))
return (mp);
}
/* If app asked for dest headers and it has changed ... */
if ((tcp->tcp_ipv6_recvancillary &
- (TCP_IPV6_RECVDSTOPTS | TCP_OLD_IPV6_RECVDSTOPTS)) &&
- tcp_cmpbuf(tcp->tcp_dstopts, tcp->tcp_dstoptslen,
- (ipp->ipp_fields & IPPF_DSTOPTS),
- ipp->ipp_dstopts, ipp->ipp_dstoptslen)) {
+ (TCP_IPV6_RECVDSTOPTS | TCP_OLD_IPV6_RECVDSTOPTS)) &&
+ ip_cmpbuf(tcp->tcp_dstopts, tcp->tcp_dstoptslen,
+ (ipp->ipp_fields & IPPF_DSTOPTS),
+ ipp->ipp_dstopts, ipp->ipp_dstoptslen)) {
optlen += sizeof (struct T_opthdr) + ipp->ipp_dstoptslen;
addflag |= TCP_IPV6_RECVDSTOPTS;
- if (!tcp_allocbuf((void **)&tcp->tcp_dstopts,
- &tcp->tcp_dstoptslen,
- (ipp->ipp_fields & IPPF_DSTOPTS),
+ if (!ip_allocbuf((void **)&tcp->tcp_dstopts,
+ &tcp->tcp_dstoptslen, (ipp->ipp_fields & IPPF_DSTOPTS),
ipp->ipp_dstopts, ipp->ipp_dstoptslen))
return (mp);
}
@@ -14857,15 +15001,16 @@
toh = (struct T_opthdr *)optptr;
toh->level = IPPROTO_IPV6;
toh->name = IPV6_HOPOPTS;
- toh->len = sizeof (*toh) + ipp->ipp_hopoptslen;
+ toh->len = sizeof (*toh) + ipp->ipp_hopoptslen -
+ tcp->tcp_label_len;
toh->status = 0;
optptr += sizeof (*toh);
- bcopy(ipp->ipp_hopopts, optptr, ipp->ipp_hopoptslen);
- optptr += ipp->ipp_hopoptslen;
+ bcopy((uchar_t *)ipp->ipp_hopopts + tcp->tcp_label_len, optptr,
+ ipp->ipp_hopoptslen - tcp->tcp_label_len);
+ optptr += ipp->ipp_hopoptslen - tcp->tcp_label_len;
ASSERT(OK_32PTR(optptr));
/* Save as last value */
- tcp_savebuf((void **)&tcp->tcp_hopopts,
- &tcp->tcp_hopoptslen,
+ ip_savebuf((void **)&tcp->tcp_hopopts, &tcp->tcp_hopoptslen,
(ipp->ipp_fields & IPPF_HOPOPTS),
ipp->ipp_hopopts, ipp->ipp_hopoptslen);
}
@@ -14880,7 +15025,7 @@
optptr += ipp->ipp_rtdstoptslen;
ASSERT(OK_32PTR(optptr));
/* Save as last value */
- tcp_savebuf((void **)&tcp->tcp_rtdstopts,
+ ip_savebuf((void **)&tcp->tcp_rtdstopts,
&tcp->tcp_rtdstoptslen,
(ipp->ipp_fields & IPPF_RTDSTOPTS),
ipp->ipp_rtdstopts, ipp->ipp_rtdstoptslen);
@@ -14896,8 +15041,7 @@
optptr += ipp->ipp_rthdrlen;
ASSERT(OK_32PTR(optptr));
/* Save as last value */
- tcp_savebuf((void **)&tcp->tcp_rthdr,
- &tcp->tcp_rthdrlen,
+ ip_savebuf((void **)&tcp->tcp_rthdr, &tcp->tcp_rthdrlen,
(ipp->ipp_fields & IPPF_RTHDR),
ipp->ipp_rthdr, ipp->ipp_rthdrlen);
}
@@ -14912,8 +15056,7 @@
optptr += ipp->ipp_dstoptslen;
ASSERT(OK_32PTR(optptr));
/* Save as last value */
- tcp_savebuf((void **)&tcp->tcp_dstopts,
- &tcp->tcp_dstoptslen,
+ ip_savebuf((void **)&tcp->tcp_dstopts, &tcp->tcp_dstoptslen,
(ipp->ipp_fields & IPPF_DSTOPTS),
ipp->ipp_dstopts, ipp->ipp_dstoptslen);
}
@@ -15094,6 +15237,12 @@
if (tcp->tcp_state != TCPS_SYN_SENT)
goto after_syn_sent;
+ if (is_system_labeled() &&
+ !tcp_update_label(tcp, CONN_CRED(tcp->tcp_connp))) {
+ tcp_bind_failed(tcp, mp, EHOSTUNREACH);
+ return;
+ }
+
ASSERT(q == tcp->tcp_rq);
/*
* tcp_adapt_ire() does not adjust
@@ -15162,21 +15311,9 @@
syn_mp = tcp_xmit_mp(tcp, NULL, 0, NULL, NULL,
tcp->tcp_iss, B_FALSE, NULL, B_FALSE);
if (syn_mp) {
- cred_t *cr;
pid_t pid;
- /*
- * Obtain the credential from the
- * thread calling connect(); the credential
- * lives on in the second mblk which
- * originated from T_CONN_REQ and is echoed
- * with the T_BIND_ACK from ip. If none
- * can be found, default to the creator
- * of the socket.
- */
- if (mp->b_cont == NULL ||
- (cr = DB_CRED(mp->b_cont)) == NULL) {
- cr = tcp->tcp_cred;
+ if (mp->b_cont == NULL) {
pid = tcp->tcp_cpid;
} else {
pid = DB_CPID(mp->b_cont);
@@ -15184,7 +15321,6 @@
TCP_RECORD_TRACE(tcp, syn_mp,
TCP_TRACE_SEND_PKT);
- mblk_setcred(syn_mp, cr);
DB_CPID(syn_mp) = pid;
tcp_send_data(tcp, tcp->tcp_wq, syn_mp);
}
@@ -15593,34 +15729,39 @@
{
mblk_t *mpdata;
mblk_t *mp_conn_ctl = NULL;
- mblk_t *mp_conn_data;
+ mblk_t *mp_conn_tail;
+ mblk_t *mp_attr_ctl = NULL;
+ mblk_t *mp_attr_tail;
mblk_t *mp6_conn_ctl = NULL;
- mblk_t *mp6_conn_data;
- mblk_t *mp_conn_tail = NULL;
- mblk_t *mp6_conn_tail = NULL;
+ mblk_t *mp6_conn_tail;
+ mblk_t *mp6_attr_ctl = NULL;
+ mblk_t *mp6_attr_tail;
struct opthdr *optp;
mib2_tcpConnEntry_t tce;
mib2_tcp6ConnEntry_t tce6;
+ mib2_transportMLPEntry_t mlp;
connf_t *connfp;
conn_t *connp;
int i;
boolean_t ispriv;
zoneid_t zoneid;
+ int v4_conn_idx;
+ int v6_conn_idx;
if (mpctl == NULL ||
(mpdata = mpctl->b_cont) == NULL ||
(mp_conn_ctl = copymsg(mpctl)) == NULL ||
- (mp6_conn_ctl = copymsg(mpctl)) == NULL) {
- if (mp_conn_ctl != NULL)
- freemsg(mp_conn_ctl);
- if (mp6_conn_ctl != NULL)
- freemsg(mp6_conn_ctl);
+ (mp_attr_ctl = copymsg(mpctl)) == NULL ||
+ (mp6_conn_ctl = copymsg(mpctl)) == NULL ||
+ (mp6_attr_ctl = copymsg(mpctl)) == NULL) {
+ freemsg(mp_conn_ctl);
+ freemsg(mp_attr_ctl);
+ freemsg(mp6_conn_ctl);
+ freemsg(mp6_attr_ctl);
return (0);
}
/* build table of connections -- need count in fixed part */
- mp_conn_data = mp_conn_ctl->b_cont;
- mp6_conn_data = mp6_conn_ctl->b_cont;
SET_MIB(tcp_mib.tcpRtoAlgorithm, 4); /* vanj */
SET_MIB(tcp_mib.tcpRtoMin, tcp_rexmit_interval_min);
SET_MIB(tcp_mib.tcpRtoMax, tcp_rexmit_interval_max);
@@ -15631,6 +15772,9 @@
secpolicy_net_config((Q_TO_CONN(q))->conn_cred, B_TRUE) == 0;
zoneid = Q_TO_CONN(q)->conn_zoneid;
+ v4_conn_idx = v6_conn_idx = 0;
+ mp_conn_tail = mp_attr_tail = mp6_conn_tail = mp6_attr_tail = NULL;
+
for (i = 0; i < CONN_G_HASH_SIZE; i++) {
connfp = &ipcl_globalhash_fanout[i];
@@ -15640,6 +15784,7 @@
while ((connp =
ipcl_get_next_conn(connfp, connp, IPCL_TCP)) != NULL) {
tcp_t *tcp;
+ boolean_t needattr;
if (connp->conn_zoneid != zoneid)
continue; /* not in this zone */
@@ -15656,6 +15801,26 @@
tce.tcpConnState == MIB2_TCP_closeWait)
BUMP_MIB(&tcp_mib, tcpCurrEstab);
+ needattr = B_FALSE;
+ bzero(&mlp, sizeof (mlp));
+ if (connp->conn_mlp_type != mlptSingle) {
+ if (connp->conn_mlp_type == mlptShared ||
+ connp->conn_mlp_type == mlptBoth)
+ mlp.tme_flags |= MIB2_TMEF_SHARED;
+ if (connp->conn_mlp_type == mlptPrivate ||
+ connp->conn_mlp_type == mlptBoth)
+ mlp.tme_flags |= MIB2_TMEF_PRIVATE;
+ needattr = B_TRUE;
+ }
+ if (connp->conn_peercred != NULL) {
+ ts_label_t *tsl;
+
+ tsl = crgetlabel(connp->conn_peercred);
+ mlp.tme_doi = label2doi(tsl);
+ mlp.tme_label = *label2bslabel(tsl);
+ needattr = B_TRUE;
+ }
+
/* Create a message to report on IPv6 entries */
if (tcp->tcp_ipversion == IPV6_VERSION) {
tce6.tcp6ConnLocalAddress = tcp->tcp_ip_src_v6;
@@ -15692,8 +15857,14 @@
tce6.tcp6ConnEntryInfo.ce_rto = tcp->tcp_rto;
tce6.tcp6ConnEntryInfo.ce_mss = tcp->tcp_mss;
tce6.tcp6ConnEntryInfo.ce_state = tcp->tcp_state;
- (void) snmp_append_data2(mp6_conn_data, &mp6_conn_tail,
- (char *)&tce6, sizeof (tce6));
+
+ (void) snmp_append_data2(mp6_conn_ctl->b_cont,
+ &mp6_conn_tail, (char *)&tce6, sizeof (tce6));
+
+ mlp.tme_connidx = v6_conn_idx++;
+ if (needattr)
+ (void) snmp_append_data2(mp6_attr_ctl->b_cont,
+ &mp6_attr_tail, (char *)&mlp, sizeof (mlp));
}
/*
* Create an IPv4 table entry for IPv4 entries and also
@@ -15747,8 +15918,16 @@
tce.tcpConnEntryInfo.ce_mss = tcp->tcp_mss;
tce.tcpConnEntryInfo.ce_state =
tcp->tcp_state;
- (void) snmp_append_data2(mp_conn_data,
+
+ (void) snmp_append_data2(mp_conn_ctl->b_cont,
&mp_conn_tail, (char *)&tce, sizeof (tce));
+
+ mlp.tme_connidx = v4_conn_idx++;
+ if (needattr)
+ (void) snmp_append_data2(
+ mp_attr_ctl->b_cont,
+ &mp_attr_tail, (char *)&mlp,
+ sizeof (mlp));
}
}
}
@@ -15768,16 +15947,38 @@
sizeof (struct T_optmgmt_ack)];
optp->level = MIB2_TCP;
optp->name = MIB2_TCP_CONN;
- optp->len = msgdsize(mp_conn_data);
+ optp->len = msgdsize(mp_conn_ctl->b_cont);
qreply(q, mp_conn_ctl);
+ /* table of MLP attributes... */
+ optp = (struct opthdr *)&mp_attr_ctl->b_rptr[
+ sizeof (struct T_optmgmt_ack)];
+ optp->level = MIB2_TCP;
+ optp->name = EXPER_XPORT_MLP;
+ optp->len = msgdsize(mp_attr_ctl->b_cont);
+ if (optp->len == 0)
+ freemsg(mp_attr_ctl);
+ else
+ qreply(q, mp_attr_ctl);
+
/* table of IPv6 connections... */
optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[
sizeof (struct T_optmgmt_ack)];
optp->level = MIB2_TCP6;
optp->name = MIB2_TCP6_CONN;
- optp->len = msgdsize(mp6_conn_data);
+ optp->len = msgdsize(mp6_conn_ctl->b_cont);
qreply(q, mp6_conn_ctl);
+
+ /* table of IPv6 MLP attributes... */
+ optp = (struct opthdr *)&mp6_attr_ctl->b_rptr[
+ sizeof (struct T_optmgmt_ack)];
+ optp->level = MIB2_TCP6;
+ optp->name = EXPER_XPORT_MLP;
+ optp->len = msgdsize(mp6_attr_ctl->b_cont);
+ if (optp->len == 0)
+ freemsg(mp6_attr_ctl);
+ else
+ qreply(q, mp6_attr_ctl);
return (1);
}
@@ -16633,11 +16834,16 @@
* but instead the code relies on:
* - the fact that the address of the array and its size never changes
* - the atomic assignment of the elements of the array
+ *
+ * Returns 0 if there are no more ports available.
+ *
+ * TS note: skip multilevel ports.
*/
static in_port_t
-tcp_update_next_port(in_port_t port, boolean_t random)
+tcp_update_next_port(in_port_t port, const tcp_t *tcp, boolean_t random)
{
int i;
+ boolean_t restart = B_FALSE;
if (random && tcp_random_anon_port != 0) {
(void) random_get_pseudo_bytes((uint8_t *)&port,
@@ -16659,9 +16865,16 @@
}
retry:
- if (port < tcp_smallest_anon_port || port > tcp_largest_anon_port)
+ if (port < tcp_smallest_anon_port)
port = (in_port_t)tcp_smallest_anon_port;
+ if (port > tcp_largest_anon_port) {
+ if (restart)
+ return (0);
+ restart = B_TRUE;
+ port = (in_port_t)tcp_smallest_anon_port;
+ }
+
if (port < tcp_smallest_nonpriv_port)
port = (in_port_t)tcp_smallest_nonpriv_port;
@@ -16671,30 +16884,47 @@
/*
* Make sure whether the port is in the
* valid range.
- *
- * XXX Note that if tcp_g_epriv_ports contains
- * all the anonymous ports this will be an
- * infinite loop.
*/
goto retry;
}
}
+ if (is_system_labeled() &&
+ (i = tsol_next_port(crgetzone(tcp->tcp_cred), port,
+ IPPROTO_TCP, B_TRUE)) != 0) {
+ port = i;
+ goto retry;
+ }
return (port);
}
/*
- * Return the next anonymous port in the priviledged port range for
+ * Return the next anonymous port in the privileged port range for
* bind checking. It starts at IPPORT_RESERVED - 1 and goes
* downwards. This is the same behavior as documented in the userland
* library call rresvport(3N).
+ *
+ * TS note: skip multilevel ports.
*/
static in_port_t
-tcp_get_next_priv_port(void)
+tcp_get_next_priv_port(const tcp_t *tcp)
{
static in_port_t next_priv_port = IPPORT_RESERVED - 1;
-
- if (next_priv_port < tcp_min_anonpriv_port) {
+ in_port_t nextport;
+ boolean_t restart = B_FALSE;
+
+retry:
+ if (next_priv_port < tcp_min_anonpriv_port ||
+ next_priv_port >= IPPORT_RESERVED) {
next_priv_port = IPPORT_RESERVED - 1;
+ if (restart)
+ return (0);
+ restart = B_TRUE;
+ }
+ if (is_system_labeled() &&
+ (nextport = tsol_next_port(crgetzone(tcp->tcp_cred),
+ next_priv_port, IPPROTO_TCP, B_FALSE)) != 0) {
+ next_priv_port = nextport;
+ goto retry;
}
return (next_priv_port--);
}
@@ -17435,9 +17665,6 @@
q->q_qinfo = &tcp_winit;
listener = eager->tcp_listener;
eager->tcp_issocket = B_TRUE;
- eager->tcp_cred = econnp->conn_cred =
- listener->tcp_connp->conn_cred;
- crhold(econnp->conn_cred);
econnp->conn_zoneid = listener->tcp_connp->conn_zoneid;
/* Put the ref for IP */
@@ -17660,8 +17887,7 @@
return;
}
if (type == T_SVR4_OPTMGMT_REQ) {
- cred_t *cr = DB_CREDDEF(mp,
- tcp->tcp_cred);
+ cred_t *cr = DB_CREDDEF(mp, tcp->tcp_cred);
if (snmpcom_req(q, mp, tcp_snmp_set, tcp_snmp_get,
cr)) {
/*
@@ -17945,12 +18171,15 @@
ASSERT(DB_TYPE(mp) == M_DATA);
+ mblk_setcred(mp, CONN_CRED(connp));
+
ipha = (ipha_t *)mp->b_rptr;
src = ipha->ipha_src;
dst = ipha->ipha_dst;
/*
- * Drop off slow path for IPv6 and also if options are present.
+ * Drop off fast path for IPv6 and also if options are present or
+ * we need to resolve a TS label.
*/
if (tcp->tcp_ipversion != IPV4_VERSION ||
!IPCL_IS_CONNECTED(connp) ||
@@ -17959,6 +18188,7 @@
connp->conn_nexthop_set ||
connp->conn_xmit_if_ill != NULL ||
connp->conn_nofailover_ill != NULL ||
+ !connp->conn_ulp_labeled ||
ipha->ipha_ident == IP_HDR_INCLUDED ||
ipha->ipha_version_and_hdr_length != IP_SIMPLE_HDR_VERSION ||
IPP_ENABLED(IPP_LOCAL_OUT)) {
@@ -17987,7 +18217,8 @@
mutex_exit(&connp->conn_lock);
if (ire != NULL)
IRE_REFRELE_NOTR(ire);
- ire = ire_cache_lookup(dst, connp->conn_zoneid);
+ ire = ire_cache_lookup(dst, connp->conn_zoneid,
+ MBLK_GETLABEL(mp));
if (ire == NULL) {
if (tcp->tcp_snd_zcopy_aware)
mp = tcp_zcopy_backoff(tcp, mp, 0);
@@ -18018,6 +18249,12 @@
*/
if (!cached)
IRE_REFRELE_NOTR(ire);
+
+ /*
+ * Rampart note: no need to select a new label here, since
+ * labels are not allowed to change during the life of a TCP
+ * connection.
+ */
}
if (ire->ire_flags & RTF_MULTIRT ||
@@ -18759,6 +18996,7 @@
ill_zerocopy_capab_t *zc_cap = NULL;
uint16_t *up;
int err;
+ conn_t *connp;
#ifdef _BIG_ENDIAN
#define IPVER(ip6h) ((((uint32_t *)ip6h)[0] >> 28) & 0x7)
@@ -18795,9 +19033,11 @@
tcp->tcp_ip_hdr_len == IP_SIMPLE_HDR_LENGTH) ||
(tcp->tcp_ipversion == IPV6_VERSION &&
tcp->tcp_ip_hdr_len == IPV6_HDR_LEN));
- ASSERT(tcp->tcp_connp != NULL);
- ASSERT(CONN_IS_MD_FASTPATH(tcp->tcp_connp));
- ASSERT(!CONN_IPSEC_OUT_ENCAPSULATED(tcp->tcp_connp));
+
+ connp = tcp->tcp_connp;
+ ASSERT(connp != NULL);
+ ASSERT(CONN_IS_MD_FASTPATH(connp));
+ ASSERT(!CONN_IPSEC_OUT_ENCAPSULATED(connp));
/*
* Note that tcp will only declare at most 2 payload spans per
@@ -18828,33 +19068,35 @@
* in proceeding any further, and we should just hand everything
* off to the legacy path.
*/
- mutex_enter(&tcp->tcp_connp->conn_lock);
- ire = tcp->tcp_connp->conn_ire_cache;
- ASSERT(!(tcp->tcp_connp->conn_state_flags & CONN_INCIPIENT));
+ mutex_enter(&connp->conn_lock);
+ ire = connp->conn_ire_cache;
+ ASSERT(!(connp->conn_state_flags & CONN_INCIPIENT));
if (ire != NULL && ((af == AF_INET && ire->ire_addr == dst) ||
(af == AF_INET6 && IN6_ARE_ADDR_EQUAL(&ire->ire_addr_v6,
&tcp->tcp_ip6h->ip6_dst))) &&
!(ire->ire_marks & IRE_MARK_CONDEMNED)) {
IRE_REFHOLD(ire);
- mutex_exit(&tcp->tcp_connp->conn_lock);
+ mutex_exit(&connp->conn_lock);
} else {
boolean_t cached = B_FALSE;
+ ts_label_t *tsl;
/* force a recheck later on */
tcp->tcp_ire_ill_check_done = B_FALSE;
TCP_DBGSTAT(tcp_ire_null1);
- tcp->tcp_connp->conn_ire_cache = NULL;
- mutex_exit(&tcp->tcp_connp->conn_lock);
+ connp->conn_ire_cache = NULL;
+ mutex_exit(&connp->conn_lock);
/* Release the old ire */
if (ire != NULL)
IRE_REFRELE_NOTR(ire);
+ tsl = crgetlabel(CONN_CRED(connp));
ire = (af == AF_INET) ?
- ire_cache_lookup(dst, tcp->tcp_connp->conn_zoneid) :
+ ire_cache_lookup(dst, connp->conn_zoneid, tsl) :
ire_cache_lookup_v6(&tcp->tcp_ip6h->ip6_dst,
- tcp->tcp_connp->conn_zoneid);
+ connp->conn_zoneid, tsl);
if (ire == NULL) {
TCP_STAT(tcp_ire_null);
@@ -18869,10 +19111,10 @@
* unplumb thread has not yet started cleaning up the conns.
* Hence we don't need to grab the conn lock.
*/
- if (!(tcp->tcp_connp->conn_state_flags & CONN_CLOSING)) {
+ if (!(connp->conn_state_flags & CONN_CLOSING)) {
rw_enter(&ire->ire_bucket->irb_lock, RW_READER);
if (!(ire->ire_marks & IRE_MARK_CONDEMNED)) {
- tcp->tcp_connp->conn_ire_cache = ire;
+ connp->conn_ire_cache = ire;
cached = B_TRUE;
}
rw_exit(&ire->ire_bucket->irb_lock);
@@ -18917,7 +19159,7 @@
TCP_STAT(tcp_mdt_conn_halted2);
tcp->tcp_mdt = B_FALSE;
ip1dbg(("tcp_multisend: disabling MDT for connp %p on "
- "interface %s\n", (void *)tcp->tcp_connp, ill->ill_name));
+ "interface %s\n", (void *)connp, ill->ill_name));
/* IRE will be released prior to returning */
goto legacy_send_no_md;
}
@@ -21129,6 +21371,7 @@
void *addr;
queue_t *q = tcp_g_q;
tcp_t *tcp = Q_TO_TCP(q);
+ cred_t *cr;
if (!tcp_send_rst_chk()) {
tcp_rst_unsent++;
@@ -21253,6 +21496,35 @@
BUMP_MIB(&tcp_mib, tcpOutRsts);
BUMP_MIB(&tcp_mib, tcpOutControl);
}
+
+ /* IP trusts us to set up labels when required. */
+ if (is_system_labeled() && (cr = DB_CRED(mp)) != NULL &&
+ crgetlabel(cr) != NULL) {
+ int err, adjust;
+
+ if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION)
+ err = tsol_check_label(cr, &mp, &adjust,
+ tcp->tcp_connp->conn_mac_exempt);
+ else
+ err = tsol_check_label_v6(cr, &mp, &adjust,
+ tcp->tcp_connp->conn_mac_exempt);
+ if (mctl_present)
+ ipsec_mp->b_cont = mp;
+ else
+ ipsec_mp = mp;
+ if (err != 0) {
+ freemsg(ipsec_mp);
+ return;
+ }
+ if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
+ ipha = (ipha_t *)mp->b_rptr;
+ adjust += ntohs(ipha->ipha_length);
+ ipha->ipha_length = htons(adjust);
+ } else {
+ ip6h = (ip6_t *)mp->b_rptr;
+ }
+ }
+
if (mctl_present) {
ipsec_in_t *ii = (ipsec_in_t *)ipsec_mp->b_rptr;
@@ -21263,9 +21535,15 @@
}
/*
* NOTE: one might consider tracing a TCP packet here, but
- * this function has no active TCP state nd no tcp structure
- * which has trace buffer. If we traced here, we would have
+ * this function has no active TCP state and no tcp structure
+ * that has a trace buffer. If we traced here, we would have
* to keep a local trace buffer in tcp_record_trace().
+ *
+ * TSol note: The mblk that contains the incoming packet was
+ * reused by tcp_xmit_listener_reset, so it already contains
+ * the right credentials and we don't need to call mblk_setcred.
+ * Also the conn's cred is not right since it is associated
+ * with tcp_g_q.
*/
CALL_IP_WPUT(tcp->tcp_connp, tcp->tcp_wq, ipsec_mp);
@@ -21452,7 +21730,15 @@
if (ipsec_mp == NULL)
return;
}
-
+ if (is_system_labeled() && !tsol_can_reply_error(mp)) {
+ DTRACE_PROBE2(
+ tx__ip__log__error__nolistener__tcp,
+ char *, "Could not reply with RST to mp(1)",
+ mblk_t *, mp);
+ ip2dbg(("tcp_xmit_listeners_reset: not permitted to reply\n"));
+ freemsg(ipsec_mp);
+ return;
+ }
rptr = mp->b_rptr;
@@ -24271,77 +24557,6 @@
}
/*
- * Return zero if the buffers are identical in length and content.
- * This is used for comparing extension header buffers.
- * Note that an extension header would be declared different
- * even if all that changed was the next header value in that header i.e.
- * what really changed is the next extension header.
- */
-static boolean_t
-tcp_cmpbuf(void *a, uint_t alen, boolean_t b_valid, void *b, uint_t blen)
-{
- if (!b_valid)
- blen = 0;
-
- if (alen != blen)
- return (B_TRUE);
- if (alen == 0)
- return (B_FALSE); /* Both zero length */
- return (bcmp(a, b, alen));
-}
-
-/*
- * Preallocate memory for tcp_savebuf(). Returns B_TRUE if ok.
- * Return B_FALSE if memory allocation fails - don't change any state!
- */
-static boolean_t
-tcp_allocbuf(void **dstp, uint_t *dstlenp, boolean_t src_valid,
- void *src, uint_t srclen)
-{
- void *dst;
-
- if (!src_valid)
- srclen = 0;
-
- ASSERT(*dstlenp == 0);
- if (src != NULL && srclen != 0) {
- dst = mi_alloc(srclen, BPRI_MED);
- if (dst == NULL)
- return (B_FALSE);
- } else {
- dst = NULL;
- }
- if (*dstp != NULL) {
- mi_free(*dstp);
- *dstp = NULL;
- *dstlenp = 0;
- }
- *dstp = dst;
- if (dst != NULL)
- *dstlenp = srclen;
- else
- *dstlenp = 0;
- return (B_TRUE);
-}
-
-/*
- * Replace what is in *dst, *dstlen with the source.
- * Assumes tcp_allocbuf has already been called.
- */
-static void
-tcp_savebuf(void **dstp, uint_t *dstlenp, boolean_t src_valid,
- void *src, uint_t srclen)
-{
- if (!src_valid)
- srclen = 0;
-
- ASSERT(*dstlenp == srclen);
- if (src != NULL && srclen != 0) {
- bcopy(src, *dstp, srclen);
- }
-}
-
-/*
* Allocate a T_SVR4_OPTMGMT_REQ.
* The caller needs to increment tcp_drop_opt_ack_cnt when sending these so
* that tcp_rput_other can drop the acks.
--- a/usr/src/uts/common/inet/tcp/tcp_opt_data.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/tcp/tcp_opt_data.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -40,7 +39,6 @@
#include <netinet/in.h>
#include <netinet/tcp.h>
-#include <netinet/ip_mroute.h>
#include <inet/optcom.h>
@@ -76,6 +74,10 @@
{ SO_DGRAM_ERRIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0
},
{ SO_SND_COPYAVOID, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
+{ SO_ANON_MLP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int),
+ 0 },
+{ SO_MAC_EXEMPT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int),
+ 0 },
{ TCP_NODELAY, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0
},
{ TCP_MAXSEG, IPPROTO_TCP, OA_R, OA_R, OP_NP, OP_PASSNEXT, sizeof (uint_t),
--- a/usr/src/uts/common/inet/udp/udp.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/udp/udp.c Fri Mar 24 12:29:20 2006 -0800
@@ -39,7 +39,6 @@
#define _SUN_TPI_VERSION 2
#include <sys/tihdr.h>
#include <sys/timod.h>
-#include <sys/tiuser.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/strsubr.h>
@@ -85,11 +84,15 @@
/*
* The ipsec_info.h header file is here since it has the definition for the
* M_CTL message types used by IP to convey information to the ULP. The
- * ipsec_info.h needs the pfkeyv2.h, hence the latters presence.
+ * ipsec_info.h needs the pfkeyv2.h, hence the latter's presence.
*/
#include <net/pfkeyv2.h>
#include <inet/ipsec_info.h>
+#include <sys/tsol/label.h>
+#include <sys/tsol/tnet.h>
+#include <rpc/pmap_prot.h>
+
/*
* Synchronization notes:
*
@@ -249,17 +252,24 @@
/*
* This controls the rate some ndd info report functions can be used
- * by non-priviledged users. It stores the last time such info is
+ * by non-privileged users. It stores the last time such info is
* requested. When those report functions are called again, this
* is checked with the current time and compare with the ndd param
* udp_ndd_get_info_interval.
*/
static clock_t udp_last_ndd_get_info_time;
#define NDD_TOO_QUICK_MSG \
- "ndd get info rate too high for non-priviledged users, try again " \
+ "ndd get info rate too high for non-privileged users, try again " \
"later.\n"
#define NDD_OUT_OF_BUF_MSG "<< Out of buffer >>\n"
+/* Option processing attrs */
+typedef struct udpattrs_s {
+ ip6_pkt_t *udpattr_ipp;
+ mblk_t *udpattr_mb;
+ boolean_t udpattr_credset;
+} udpattrs_t;
+
static void udp_addr_req(queue_t *q, mblk_t *mp);
static void udp_bind(queue_t *q, mblk_t *mp);
static void udp_bind_hash_insert(udp_fanout_t *uf, udp_t *udp);
@@ -287,14 +297,12 @@
static int udp_open(queue_t *q, dev_t *devp, int flag, int sflag,
cred_t *credp);
static int udp_unitdata_opt_process(queue_t *q, mblk_t *mp,
- int *errorp, void *thisdg_attrs);
+ int *errorp, udpattrs_t *udpattrs);
static boolean_t udp_opt_allow_udr_set(t_scalar_t level, t_scalar_t name);
static int udp_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr);
static boolean_t udp_param_register(udpparam_t *udppa, int cnt);
static int udp_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
cred_t *cr);
-static int udp_pkt_set(uchar_t *invalp, uint_t inlen, boolean_t sticky,
- uchar_t **optbufp, uint_t *optlenp);
static void udp_report_item(mblk_t *mp, udp_t *udp);
static void udp_rput(queue_t *q, mblk_t *mp);
static void udp_rput_other(queue_t *, mblk_t *);
@@ -307,12 +315,13 @@
static void udp_ud_err(queue_t *q, mblk_t *mp, uchar_t *destaddr,
t_scalar_t destlen, t_scalar_t err);
static void udp_unbind(queue_t *q, mblk_t *mp);
-static in_port_t udp_update_next_port(in_port_t port, boolean_t random);
+static in_port_t udp_update_next_port(udp_t *udp, in_port_t port,
+ boolean_t random);
static void udp_wput(queue_t *q, mblk_t *mp);
static mblk_t *udp_output_v4(conn_t *, mblk_t *mp, ipaddr_t v4dst,
uint16_t port, uint_t srcid, int *error);
static mblk_t *udp_output_v6(conn_t *connp, mblk_t *mp, sin6_t *sin6,
- t_scalar_t tudr_optlen, int *error);
+ int *error);
static void udp_wput_other(queue_t *q, mblk_t *mp);
static void udp_wput_iocdata(queue_t *q, mblk_t *mp);
static void udp_output(conn_t *connp, mblk_t *mp, struct sockaddr *addr,
@@ -459,7 +468,7 @@
/* END CSTYLED */
/*
- * The smallest anonymous port in the priviledged port range which UDP
+ * The smallest anonymous port in the privileged port range which UDP
* looks for free port. Use in the option UDP_ANONPRIVBIND.
*/
static in_port_t udp_min_anonpriv_port = 512;
@@ -903,17 +912,38 @@
}
/*
- * Return the next anonymous port in the priviledged port range for
+ * Return the next anonymous port in the privileged port range for
* bind checking.
+ *
+ * Trusted Extension (TX) notes: TX allows administrator to mark or
+ * reserve ports as Multilevel ports (MLP). MLP has special function
+ * on TX systems. Once a port is made MLP, it's not available as
+ * ordinary port. This creates "holes" in the port name space. It
+ * may be necessary to skip the "holes" find a suitable anon port.
*/
static in_port_t
-udp_get_next_priv_port(void)
+udp_get_next_priv_port(udp_t *udp)
{
static in_port_t next_priv_port = IPPORT_RESERVED - 1;
-
- if (next_priv_port < udp_min_anonpriv_port) {
+ in_port_t nextport;
+ boolean_t restart = B_FALSE;
+
+retry:
+ if (next_priv_port < udp_min_anonpriv_port ||
+ next_priv_port >= IPPORT_RESERVED) {
next_priv_port = IPPORT_RESERVED - 1;
- }
+ if (restart)
+ return (0);
+ restart = B_TRUE;
+ }
+
+ if (is_system_labeled() &&
+ (nextport = tsol_next_port(crgetzone(udp->udp_connp->conn_cred),
+ next_priv_port, IPPROTO_UDP, B_FALSE)) != 0) {
+ next_priv_port = nextport;
+ goto retry;
+ }
+
return (next_priv_port--);
}
@@ -1098,6 +1128,8 @@
zoneid_t zoneid;
conn_t *connp;
udp_t *udp;
+ boolean_t is_inaddr_any;
+ mlp_type_t addrtype, mlptype;
connp = Q_TO_CONN(q);
udp = connp->conn_udp;
@@ -1198,10 +1230,10 @@
* valid range.
*/
if (udp->udp_anon_priv_bind) {
- port = udp_get_next_priv_port();
+ port = udp_get_next_priv_port(udp);
} else {
- port = udp_update_next_port(udp_g_next_port_to_try,
- B_TRUE);
+ port = udp_update_next_port(udp,
+ udp_g_next_port_to_try, B_TRUE);
}
} else {
/*
@@ -1232,6 +1264,11 @@
}
}
+ if (port == 0) {
+ udp_err_ack(q, mp, TNOADDR, 0);
+ return;
+ }
+
/*
* Copy the source address into our udp structure. This address
* may still be zero; if so, IP will fill in the correct address
@@ -1286,13 +1323,13 @@
loopmax = udp_largest_anon_port - udp_smallest_anon_port + 1;
}
+ is_inaddr_any = V6_OR_V4_INADDR_ANY(v6src);
zoneid = connp->conn_zoneid;
+
for (;;) {
udp_t *udp1;
- boolean_t is_inaddr_any;
boolean_t found_exclbind = B_FALSE;
- is_inaddr_any = V6_OR_V4_INADDR_ANY(v6src);
/*
* Walk through the list of udp streams bound to
* requested port with the same IP address.
@@ -1302,8 +1339,17 @@
mutex_enter(&udpf->uf_lock);
for (udp1 = udpf->uf_udp; udp1 != NULL;
udp1 = udp1->udp_bind_hash) {
- if (lport != udp1->udp_port ||
- zoneid != udp1->udp_connp->conn_zoneid)
+ if (lport != udp1->udp_port)
+ continue;
+
+ /*
+ * On a labeled system, we must treat bindings to ports
+ * on shared IP addresses by sockets with MAC exemption
+ * privilege as being in all zones, as there's
+ * otherwise no way to identify the right receiver.
+ */
+ if (zoneid != udp1->udp_connp->conn_zoneid &&
+ !udp->udp_mac_exempt && !udp1->udp_mac_exempt)
continue;
/*
@@ -1321,8 +1367,12 @@
* unspec spec no
* spec unspec no
* spec spec yes if A
+ *
+ * For labeled systems, SO_MAC_EXEMPT behaves the same
+ * as UDP_EXCLBIND, except that zoneid is ignored.
*/
- if (udp1->udp_exclbind || udp->udp_exclbind) {
+ if (udp1->udp_exclbind || udp->udp_exclbind ||
+ udp1->udp_mac_exempt || udp->udp_mac_exempt) {
if (V6_OR_V4_INADDR_ANY(
udp1->udp_bound_v6src) ||
is_inaddr_any ||
@@ -1388,7 +1438,7 @@
}
if (udp->udp_anon_priv_bind) {
- port = udp_get_next_priv_port();
+ port = udp_get_next_priv_port(udp);
} else {
if ((count == 0) && (requested_port != 0)) {
/*
@@ -1397,15 +1447,16 @@
* requested_port to 0, so that we will
* update udp_g_next_port_to_try below.
*/
- port = udp_update_next_port(
+ port = udp_update_next_port(udp,
udp_g_next_port_to_try, B_TRUE);
requested_port = 0;
} else {
- port = udp_update_next_port(port + 1, B_FALSE);
+ port = udp_update_next_port(udp, port + 1,
+ B_FALSE);
}
}
- if (++count >= loopmax) {
+ if (port == 0 || ++count >= loopmax) {
/*
* We've tried every possible port number and
* there are none available, so send an error
@@ -1468,6 +1519,88 @@
}
+ connp->conn_anon_port = (is_system_labeled() && requested_port == 0);
+ if (is_system_labeled() && (!connp->conn_anon_port ||
+ connp->conn_anon_mlp)) {
+ uint16_t mlpport;
+ cred_t *cr = connp->conn_cred;
+ zone_t *zone;
+
+ connp->conn_mlp_type = udp->udp_recvucred ? mlptBoth :
+ mlptSingle;
+ addrtype = tsol_mlp_addr_type(zoneid, IPV6_VERSION, &v6src);
+ if (addrtype == mlptSingle) {
+ udp_err_ack(q, mp, TNOADDR, 0);
+ connp->conn_anon_port = B_FALSE;
+ connp->conn_mlp_type = mlptSingle;
+ return;
+ }
+ mlpport = connp->conn_anon_port ? PMAPPORT : port;
+ zone = crgetzone(cr);
+ mlptype = tsol_mlp_port_type(zone, IPPROTO_UDP, mlpport,
+ addrtype);
+ if (mlptype != mlptSingle &&
+ (connp->conn_mlp_type == mlptSingle ||
+ secpolicy_net_bindmlp(cr) != 0)) {
+ if (udp->udp_debug) {
+ (void) strlog(UDP_MOD_ID, 0, 1,
+ SL_ERROR|SL_TRACE,
+ "udp_bind: no priv for multilevel port %d",
+ mlpport);
+ }
+ udp_err_ack(q, mp, TACCES, 0);
+ connp->conn_anon_port = B_FALSE;
+ connp->conn_mlp_type = mlptSingle;
+ return;
+ }
+
+ /*
+ * If we're specifically binding a shared IP address and the
+ * port is MLP on shared addresses, then check to see if this
+ * zone actually owns the MLP. Reject if not.
+ */
+ if (mlptype == mlptShared && addrtype == mlptShared) {
+ zoneid_t mlpzone;
+
+ mlpzone = tsol_mlp_findzone(IPPROTO_UDP,
+ htons(mlpport));
+ if (connp->conn_zoneid != mlpzone) {
+ if (udp->udp_debug) {
+ (void) strlog(UDP_MOD_ID, 0, 1,
+ SL_ERROR|SL_TRACE,
+ "udp_bind: attempt to bind port "
+ "%d on shared addr in zone %d "
+ "(should be %d)",
+ mlpport, connp->conn_zoneid,
+ mlpzone);
+ }
+ udp_err_ack(q, mp, TACCES, 0);
+ connp->conn_anon_port = B_FALSE;
+ connp->conn_mlp_type = mlptSingle;
+ return;
+ }
+ }
+ if (connp->conn_anon_port) {
+ int error;
+
+ error = tsol_mlp_anon(zone, mlptype, connp->conn_ulp,
+ port, B_TRUE);
+ if (error != 0) {
+ if (udp->udp_debug) {
+ (void) strlog(UDP_MOD_ID, 0, 1,
+ SL_ERROR|SL_TRACE,
+ "udp_bind: cannot establish anon "
+ "MLP for port %d", port);
+ }
+ udp_err_ack(q, mp, TACCES, 0);
+ connp->conn_anon_port = B_FALSE;
+ connp->conn_mlp_type = mlptSingle;
+ return;
+ }
+ }
+ connp->conn_mlp_type = mlptype;
+ }
+
/* Pass the protocol number in the message following the address. */
*mp->b_wptr++ = IPPROTO_UDP;
if (!V6_OR_V4_INADDR_ANY(udp->udp_v6src)) {
@@ -1769,6 +1902,7 @@
linkb(mp1, mp);
linkb(mp1, mp2);
+ mblk_setcred(mp1, udp->udp_connp->conn_cred);
if (udp->udp_family == AF_INET)
mp1 = ip_bind_v4(q, mp1, udp->udp_connp);
else
@@ -1819,6 +1953,7 @@
connp->conn_flags &= ~IPCL_UDP;
connp->conn_state_flags &=
~(CONN_CLOSING | CONN_CONDEMNED | CONN_QUIESCED);
+ connp->conn_ulp_labeled = B_FALSE;
return (0);
}
@@ -1879,28 +2014,7 @@
udp->udp_sticky_hdrs_len = 0;
}
- if (udp->udp_sticky_ipp.ipp_fields & IPPF_HOPOPTS) {
- kmem_free(udp->udp_sticky_ipp.ipp_hopopts,
- udp->udp_sticky_ipp.ipp_hopoptslen);
- udp->udp_sticky_ipp.ipp_hopopts = NULL;
- }
- if (udp->udp_sticky_ipp.ipp_fields & IPPF_RTDSTOPTS) {
- kmem_free(udp->udp_sticky_ipp.ipp_rtdstopts,
- udp->udp_sticky_ipp.ipp_rtdstoptslen);
- udp->udp_sticky_ipp.ipp_rtdstopts = NULL;
- }
- if (udp->udp_sticky_ipp.ipp_fields & IPPF_RTHDR) {
- kmem_free(udp->udp_sticky_ipp.ipp_rthdr,
- udp->udp_sticky_ipp.ipp_rthdrlen);
- udp->udp_sticky_ipp.ipp_rthdr = NULL;
- }
- if (udp->udp_sticky_ipp.ipp_fields & IPPF_DSTOPTS) {
- kmem_free(udp->udp_sticky_ipp.ipp_dstopts,
- udp->udp_sticky_ipp.ipp_dstoptslen);
- udp->udp_sticky_ipp.ipp_dstopts = NULL;
- }
- udp->udp_sticky_ipp.ipp_fields &=
- ~(IPPF_HOPOPTS|IPPF_RTDSTOPTS|IPPF_RTHDR|IPPF_DSTOPTS);
+ ip6_pkt_free(&udp->udp_sticky_ipp);
udp->udp_connp = NULL;
connp->conn_udp = NULL;
@@ -2835,10 +2949,20 @@
connp->conn_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
connp->conn_zoneid = zoneid;
+ /*
+ * If the caller has the process-wide flag set, then default to MAC
+ * exempt mode. This allows read-down to unlabeled hosts.
+ */
+ if (getpflags(NET_MAC_AWARE, credp) != 0)
+ udp->udp_mac_exempt = B_TRUE;
+
if (connp->conn_flags & IPCL_SOCKET) {
udp->udp_issocket = B_TRUE;
udp->udp_direct_sockfs = B_TRUE;
}
+
+ connp->conn_ulp_labeled = is_system_labeled();
+
mutex_exit(&connp->conn_lock);
/*
@@ -2853,6 +2977,7 @@
if (udp->udp_family == AF_INET6) {
/* Build initial header template for transmit */
if ((err = udp_build_hdrs(q, udp)) != 0) {
+error:
qprocsoff(UDP_RD(q));
udp->udp_connp = NULL;
connp->conn_udp = NULL;
@@ -2931,6 +3056,7 @@
conn_t *connp;
udp_t *udp;
ip6_pkt_t *ipp;
+ int len;
q = UDP_WR(q);
connp = Q_TO_CONN(q);
@@ -2979,6 +3105,12 @@
case SO_TIMESTAMP:
*i1 = udp->udp_timestamp;
break;
+ case SO_ANON_MLP:
+ *i1 = udp->udp_anon_mlp;
+ break; /* goto sizeof (int) option return */
+ case SO_MAC_EXEMPT:
+ *i1 = udp->udp_mac_exempt;
+ break; /* goto sizeof (int) option return */
default:
return (-1);
}
@@ -2989,10 +3121,12 @@
switch (name) {
case IP_OPTIONS:
case T_IP_OPTIONS:
- if (udp->udp_ip_rcv_options_len)
- bcopy(udp->udp_ip_rcv_options, ptr,
- udp->udp_ip_rcv_options_len);
- return (udp->udp_ip_rcv_options_len);
+ len = udp->udp_ip_rcv_options_len - udp->udp_label_len;
+ if (len > 0) {
+ bcopy(udp->udp_ip_rcv_options +
+ udp->udp_label_len, ptr, len);
+ }
+ return (len);
case IP_TOS:
case T_IP_TOS:
*i1 = (int)udp->udp_type_of_service;
@@ -3153,8 +3287,21 @@
case IPV6_HOPOPTS:
if (!(ipp->ipp_fields & IPPF_HOPOPTS))
return (0);
- bcopy(ipp->ipp_hopopts, ptr, ipp->ipp_hopoptslen);
- return (ipp->ipp_hopoptslen);
+ if (ipp->ipp_hopoptslen <= udp->udp_label_len_v6)
+ return (0);
+ /*
+ * The cipso/label option is added by kernel.
+ * User is not usually aware of this option.
+ * We copy out the hbh opt after the label option.
+ */
+ bcopy((char *)ipp->ipp_hopopts + udp->udp_label_len_v6,
+ ptr, ipp->ipp_hopoptslen - udp->udp_label_len_v6);
+ if (udp->udp_label_len_v6 > 0) {
+ ptr[0] = ((char *)ipp->ipp_hopopts)[0];
+ ptr[1] = (ipp->ipp_hopoptslen -
+ udp->udp_label_len_v6 + 7) / 8 - 1;
+ }
+ return (ipp->ipp_hopoptslen - udp->udp_label_len_v6);
case IPV6_RTHDRDSTOPTS:
if (!(ipp->ipp_fields & IPPF_RTDSTOPTS))
return (0);
@@ -3208,12 +3355,14 @@
int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp,
uchar_t *outvalp, void *thisdg_attrs, cred_t *cr, mblk_t *mblk)
{
+ udpattrs_t *attrs = thisdg_attrs;
int *i1 = (int *)invalp;
boolean_t onoff = (*i1 == 0) ? 0 : 1;
boolean_t checkonly;
int error;
conn_t *connp;
udp_t *udp;
+ uint_t newlen;
q = UDP_WR(q);
connp = Q_TO_CONN(q);
@@ -3332,6 +3481,55 @@
if (!checkonly)
udp->udp_timestamp = onoff;
break;
+ case SO_ANON_MLP:
+ if (!checkonly)
+ udp->udp_anon_mlp = onoff;
+ break;
+ case SO_MAC_EXEMPT:
+ if (secpolicy_net_mac_aware(cr) != 0 ||
+ udp->udp_state != TS_UNBND)
+ return (EACCES);
+ if (!checkonly)
+ udp->udp_mac_exempt = onoff;
+ break;
+ case SCM_UCRED: {
+ struct ucred_s *ucr;
+ cred_t *cr, *newcr;
+ ts_label_t *tsl;
+
+ /*
+ * Only sockets that have proper privileges and are
+ * bound to MLPs will have any other value here, so
+ * this implicitly tests for privilege to set label.
+ */
+ if (connp->conn_mlp_type == mlptSingle)
+ break;
+ ucr = (struct ucred_s *)invalp;
+ if (inlen != ucredsize ||
+ ucr->uc_labeloff < sizeof (*ucr) ||
+ ucr->uc_labeloff + sizeof (bslabel_t) > inlen)
+ return (EINVAL);
+ if (!checkonly) {
+ mblk_t *mb;
+
+ if (attrs == NULL ||
+ (mb = attrs->udpattr_mb) == NULL)
+ return (EINVAL);
+ if ((cr = DB_CRED(mb)) == NULL)
+ cr = udp->udp_connp->conn_cred;
+ ASSERT(cr != NULL);
+ if ((tsl = crgetlabel(cr)) == NULL)
+ return (EINVAL);
+ newcr = copycred_from_bslabel(cr, UCLABEL(ucr),
+ tsl->tsl_doi, KM_NOSLEEP);
+ if (newcr == NULL)
+ return (ENOSR);
+ mblk_setcred(mb, newcr);
+ attrs->udpattr_credset = B_TRUE;
+ crfree(newcr);
+ }
+ break;
+ }
default:
*outlenp = 0;
return (EINVAL);
@@ -3346,32 +3544,27 @@
case IP_OPTIONS:
case T_IP_OPTIONS:
/* Save options for use by IP. */
- if (inlen & 0x3) {
+ newlen = inlen + udp->udp_label_len;
+ if ((inlen & 0x3) || newlen > IP_MAX_OPT_LENGTH) {
*outlenp = 0;
return (EINVAL);
}
if (checkonly)
break;
- if (udp->udp_ip_snd_options) {
- mi_free((char *)udp->udp_ip_snd_options);
- udp->udp_ip_snd_options_len = 0;
- udp->udp_ip_snd_options = NULL;
+ if (!tsol_option_set(&udp->udp_ip_snd_options,
+ &udp->udp_ip_snd_options_len,
+ udp->udp_label_len, invalp, inlen)) {
+ *outlenp = 0;
+ return (ENOMEM);
}
- if (inlen) {
- udp->udp_ip_snd_options =
- (uchar_t *)mi_alloc(inlen, BPRI_HI);
- if (udp->udp_ip_snd_options) {
- bcopy(invalp, udp->udp_ip_snd_options,
- inlen);
- udp->udp_ip_snd_options_len = inlen;
- }
- }
+
udp->udp_max_hdr_len = IP_SIMPLE_HDR_LENGTH +
UDPH_SIZE + udp->udp_ip_snd_options_len;
(void) mi_set_sth_wroff(RD(q), udp->udp_max_hdr_len +
udp_wroff_extra);
break;
+
case IP_TTL:
if (!checkonly) {
udp->udp_ttl = (uchar_t)*i1;
@@ -3471,14 +3664,11 @@
/*
* Deal with both sticky options and ancillary data
*/
- if (thisdg_attrs == NULL) {
+ sticky = B_FALSE;
+ if (attrs == NULL || (ipp = attrs->udpattr_ipp) == NULL) {
/* sticky options, or none */
ipp = &udp->udp_sticky_ipp;
sticky = B_TRUE;
- } else {
- /* ancillary data */
- ipp = (ip6_pkt_t *)thisdg_attrs;
- sticky = B_FALSE;
}
switch (name) {
@@ -3739,22 +3929,16 @@
if (checkonly)
break;
- if (inlen == 0) {
- if (sticky &&
- (ipp->ipp_fields & IPPF_HOPOPTS) != 0) {
- kmem_free(ipp->ipp_hopopts,
- ipp->ipp_hopoptslen);
- ipp->ipp_hopopts = NULL;
- ipp->ipp_hopoptslen = 0;
- }
+ error = optcom_pkt_set(invalp, inlen, sticky,
+ (uchar_t **)&ipp->ipp_hopopts,
+ &ipp->ipp_hopoptslen,
+ sticky ? udp->udp_label_len_v6 : 0);
+ if (error != 0)
+ return (error);
+ if (ipp->ipp_hopoptslen == 0) {
ipp->ipp_fields &= ~IPPF_HOPOPTS;
ipp->ipp_sticky_ignored |= IPPF_HOPOPTS;
} else {
- error = udp_pkt_set(invalp, inlen, sticky,
- (uchar_t **)&ipp->ipp_hopopts,
- &ipp->ipp_hopoptslen);
- if (error != 0)
- return (error);
ipp->ipp_fields |= IPPF_HOPOPTS;
}
if (sticky) {
@@ -3790,9 +3974,9 @@
ipp->ipp_fields &= ~IPPF_RTDSTOPTS;
ipp->ipp_sticky_ignored |= IPPF_RTDSTOPTS;
} else {
- error = udp_pkt_set(invalp, inlen, sticky,
+ error = optcom_pkt_set(invalp, inlen, sticky,
(uchar_t **)&ipp->ipp_rtdstopts,
- &ipp->ipp_rtdstoptslen);
+ &ipp->ipp_rtdstoptslen, 0);
if (error != 0)
return (error);
ipp->ipp_fields |= IPPF_RTDSTOPTS;
@@ -3829,9 +4013,9 @@
ipp->ipp_fields &= ~IPPF_DSTOPTS;
ipp->ipp_sticky_ignored |= IPPF_DSTOPTS;
} else {
- error = udp_pkt_set(invalp, inlen, sticky,
+ error = optcom_pkt_set(invalp, inlen, sticky,
(uchar_t **)&ipp->ipp_dstopts,
- &ipp->ipp_dstoptslen);
+ &ipp->ipp_dstoptslen, 0);
if (error != 0)
return (error);
ipp->ipp_fields |= IPPF_DSTOPTS;
@@ -3868,9 +4052,9 @@
ipp->ipp_fields &= ~IPPF_RTHDR;
ipp->ipp_sticky_ignored |= IPPF_RTHDR;
} else {
- error = udp_pkt_set(invalp, inlen, sticky,
+ error = optcom_pkt_set(invalp, inlen, sticky,
(uchar_t **)&ipp->ipp_rthdr,
- &ipp->ipp_rthdrlen);
+ &ipp->ipp_rthdrlen, 0);
if (error != 0)
return (error);
ipp->ipp_fields |= IPPF_RTHDR;
@@ -4018,46 +4202,6 @@
}
/*
- * Set optbuf and optlen for the option.
- * If sticky is set allocate memory (if not already present).
- * Otherwise just point optbuf and optlen at invalp and inlen.
- * Returns failure if memory can not be allocated.
- */
-static int
-udp_pkt_set(uchar_t *invalp, uint_t inlen, boolean_t sticky,
- uchar_t **optbufp, uint_t *optlenp)
-{
- uchar_t *optbuf;
-
- if (!sticky) {
- *optbufp = invalp;
- *optlenp = inlen;
- return (0);
- }
- if (inlen == *optlenp) {
- /* Unchanged length - no need to realocate */
- bcopy(invalp, *optbufp, inlen);
- return (0);
- }
- if (inlen != 0) {
- /* Allocate new buffer before free */
- optbuf = kmem_alloc(inlen, KM_NOSLEEP);
- if (optbuf == NULL)
- return (ENOMEM);
- } else {
- optbuf = NULL;
- }
- /* Free old buffer */
- if (*optlenp != 0)
- kmem_free(*optbufp, *optlenp);
-
- bcopy(invalp, optbuf, inlen);
- *optbufp = optbuf;
- *optlenp = inlen;
- return (0);
-}
-
-/*
* This routine retrieves the value of an ND variable in a udpparam_t
* structure. It is called through nd_getset when a user reads the
* variable.
@@ -4140,6 +4284,156 @@
return (0);
}
+/*
+ * Copy hop-by-hop option from ipp->ipp_hopopts to the buffer provided (with
+ * T_opthdr) and return the number of bytes copied. 'dbuf' may be NULL to
+ * just count the length needed for allocation. If 'dbuf' is non-NULL,
+ * then it's assumed to be allocated to be large enough.
+ *
+ * Returns zero if trimming of the security option causes all options to go
+ * away.
+ */
+static size_t
+copy_hop_opts(const ip6_pkt_t *ipp, uchar_t *dbuf)
+{
+ struct T_opthdr *toh;
+ size_t hol = ipp->ipp_hopoptslen;
+ ip6_hbh_t *dstopt = NULL;
+ const ip6_hbh_t *srcopt = ipp->ipp_hopopts;
+ size_t tlen, olen, plen;
+ boolean_t deleting;
+ const struct ip6_opt *sopt, *lastpad;
+ struct ip6_opt *dopt;
+
+ if ((toh = (struct T_opthdr *)dbuf) != NULL) {
+ toh->level = IPPROTO_IPV6;
+ toh->name = IPV6_HOPOPTS;
+ toh->status = 0;
+ dstopt = (ip6_hbh_t *)(toh + 1);
+ }
+
+ /*
+ * If labeling is enabled, then skip the label option
+ * but get other options if there are any.
+ */
+ if (is_system_labeled()) {
+ dopt = NULL;
+ if (dstopt != NULL) {
+ /* will fill in ip6h_len later */
+ dstopt->ip6h_nxt = srcopt->ip6h_nxt;
+ dopt = (struct ip6_opt *)(dstopt + 1);
+ }
+ sopt = (const struct ip6_opt *)(srcopt + 1);
+ hol -= sizeof (*srcopt);
+ tlen = sizeof (*dstopt);
+ lastpad = NULL;
+ deleting = B_FALSE;
+ /*
+ * This loop finds the first (lastpad pointer) of any number of
+ * pads that preceeds the security option, then treats the
+ * security option as though it were a pad, and then finds the
+ * next non-pad option (or end of list).
+ *
+ * It then treats the entire block as one big pad. To preserve
+ * alignment of any options that follow, or just the end of the
+ * list, it computes a minimal new padding size that keeps the
+ * same alignment for the next option.
+ *
+ * If it encounters just a sequence of pads with no security
+ * option, those are copied as-is rather than collapsed.
+ *
+ * Note that to handle the end of list case, the code makes one
+ * loop with 'hol' set to zero.
+ */
+ for (;;) {
+ if (hol > 0) {
+ if (sopt->ip6o_type == IP6OPT_PAD1) {
+ if (lastpad == NULL)
+ lastpad = sopt;
+ sopt = (const struct ip6_opt *)
+ &sopt->ip6o_len;
+ hol--;
+ continue;
+ }
+ olen = sopt->ip6o_len + sizeof (*sopt);
+ if (olen > hol)
+ olen = hol;
+ if (sopt->ip6o_type == IP6OPT_PADN ||
+ sopt->ip6o_type == ip6opt_ls) {
+ if (sopt->ip6o_type == ip6opt_ls)
+ deleting = B_TRUE;
+ if (lastpad == NULL)
+ lastpad = sopt;
+ sopt = (const struct ip6_opt *)
+ ((const char *)sopt + olen);
+ hol -= olen;
+ continue;
+ }
+ } else {
+ /* if nothing was copied at all, then delete */
+ if (tlen == sizeof (*dstopt))
+ return (0);
+ /* last pass; pick up any trailing padding */
+ olen = 0;
+ }
+ if (deleting) {
+ /*
+ * compute aligning effect of deleted material
+ * to reproduce with pad.
+ */
+ plen = ((const char *)sopt -
+ (const char *)lastpad) & 7;
+ tlen += plen;
+ if (dopt != NULL) {
+ if (plen == 1) {
+ dopt->ip6o_type = IP6OPT_PAD1;
+ } else if (plen > 1) {
+ plen -= sizeof (*dopt);
+ dopt->ip6o_type = IP6OPT_PADN;
+ dopt->ip6o_len = plen;
+ if (plen > 0)
+ bzero(dopt + 1, plen);
+ }
+ dopt = (struct ip6_opt *)
+ ((char *)dopt + plen);
+ }
+ deleting = B_FALSE;
+ lastpad = NULL;
+ }
+ /* if there's uncopied padding, then copy that now */
+ if (lastpad != NULL) {
+ olen += (const char *)sopt -
+ (const char *)lastpad;
+ sopt = lastpad;
+ lastpad = NULL;
+ }
+ if (dopt != NULL && olen > 0) {
+ bcopy(sopt, dopt, olen);
+ dopt = (struct ip6_opt *)((char *)dopt + olen);
+ }
+ if (hol == 0)
+ break;
+ tlen += olen;
+ sopt = (const struct ip6_opt *)
+ ((const char *)sopt + olen);
+ hol -= olen;
+ }
+ /* go back and patch up the length value, rounded upward */
+ if (dstopt != NULL)
+ dstopt->ip6h_len = (tlen - 1) >> 3;
+ } else {
+ tlen = hol;
+ if (dstopt != NULL)
+ bcopy(srcopt, dstopt, hol);
+ }
+
+ tlen += sizeof (*toh);
+ if (toh != NULL)
+ toh->len = tlen;
+
+ return (tlen);
+}
+
static void
udp_input(conn_t *connp, mblk_t *mp)
{
@@ -4160,6 +4454,7 @@
cred_t *cr = NULL;
queue_t *q = connp->conn_rq;
pid_t cpid;
+ cred_t *rcr = connp->conn_cred;
TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_START,
"udp_rput_start: q %p mp %p", q, mp);
@@ -4502,7 +4797,7 @@
toh->name = SCM_UCRED;
toh->len = sizeof (struct T_opthdr) + ucredsize;
toh->status = 0;
- (void) cred2ucred(cr, cpid, &toh[1]);
+ (void) cred2ucred(cr, cpid, &toh[1], rcr);
dstopt += toh->len;
udi_size -= toh->len;
}
@@ -4563,9 +4858,13 @@
IPPF_RTHDR|IPPF_IFINDEX)) {
if (udp->udp_ipv6_recvhopopts &&
(ipp.ipp_fields & IPPF_HOPOPTS)) {
- udi_size += sizeof (struct T_opthdr) +
- ipp.ipp_hopoptslen;
+ size_t hlen;
+
UDP_STAT(udp_in_recvhopopts);
+ hlen = copy_hop_opts(&ipp, NULL);
+ if (hlen == 0)
+ ipp.ipp_fields &= ~IPPF_HOPOPTS;
+ udi_size += hlen;
}
if ((udp->udp_ipv6_recvdstopts ||
udp->udp_old_ipv6_recvdstopts) &&
@@ -4731,19 +5030,11 @@
}
if (udp->udp_ipv6_recvhopopts &&
(ipp.ipp_fields & IPPF_HOPOPTS)) {
- struct T_opthdr *toh;
-
- toh = (struct T_opthdr *)dstopt;
- toh->level = IPPROTO_IPV6;
- toh->name = IPV6_HOPOPTS;
- toh->len = sizeof (struct T_opthdr) +
- ipp.ipp_hopoptslen;
- toh->status = 0;
- dstopt += sizeof (struct T_opthdr);
- bcopy(ipp.ipp_hopopts, dstopt,
- ipp.ipp_hopoptslen);
- dstopt += ipp.ipp_hopoptslen;
- udi_size -= toh->len;
+ size_t hlen;
+
+ hlen = copy_hop_opts(&ipp, dstopt);
+ dstopt += hlen;
+ udi_size -= hlen;
}
if (udp->udp_ipv6_recvdstopts &&
udp->udp_ipv6_recvrthdr &&
@@ -4803,7 +5094,7 @@
toh->name = SCM_UCRED;
toh->len = sizeof (struct T_opthdr) + ucredsize;
toh->status = 0;
- (void) cred2ucred(cr, cpid, &toh[1]);
+ (void) cred2ucred(cr, cpid, &toh[1], rcr);
dstopt += toh->len;
udi_size -= toh->len;
}
@@ -4882,6 +5173,7 @@
cred_t *cr = NULL;
udp_t *udp = Q_TO_UDP(q);
pid_t cpid;
+ cred_t *rcr = udp->udp_connp->conn_cred;
TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_START,
"udp_rput_other: q %p mp %p", q, mp);
@@ -5202,7 +5494,7 @@
toh->name = SCM_UCRED;
toh->len = sizeof (struct T_opthdr) + ucredsize;
toh->status = 0;
- (void) cred2ucred(cr, cpid, &toh[1]);
+ (void) cred2ucred(cr, cpid, &toh[1], rcr);
dstopt += toh->len;
udi_size -= toh->len;
}
@@ -5376,32 +5668,40 @@
{
mblk_t *mpdata;
mblk_t *mp_conn_ctl;
+ mblk_t *mp_attr_ctl;
mblk_t *mp6_conn_ctl;
- mblk_t *mp_conn_data;
- mblk_t *mp6_conn_data;
- mblk_t *mp_conn_tail = NULL;
- mblk_t *mp6_conn_tail = NULL;
+ mblk_t *mp6_attr_ctl;
+ mblk_t *mp_conn_tail;
+ mblk_t *mp_attr_tail;
+ mblk_t *mp6_conn_tail;
+ mblk_t *mp6_attr_tail;
struct opthdr *optp;
mib2_udpEntry_t ude;
mib2_udp6Entry_t ude6;
+ mib2_transportMLPEntry_t mlp;
int state;
zoneid_t zoneid;
int i;
connf_t *connfp;
conn_t *connp = Q_TO_CONN(q);
udp_t *udp = connp->conn_udp;
-
+ int v4_conn_idx;
+ int v6_conn_idx;
+ boolean_t needattr;
+
+ mp_conn_ctl = mp_attr_ctl = mp6_conn_ctl = NULL;
if (mpctl == NULL ||
(mpdata = mpctl->b_cont) == NULL ||
(mp_conn_ctl = copymsg(mpctl)) == NULL ||
- (mp6_conn_ctl = copymsg(mpctl)) == NULL) {
+ (mp_attr_ctl = copymsg(mpctl)) == NULL ||
+ (mp6_conn_ctl = copymsg(mpctl)) == NULL ||
+ (mp6_attr_ctl = copymsg(mpctl)) == NULL) {
freemsg(mp_conn_ctl);
+ freemsg(mp_attr_ctl);
+ freemsg(mp6_conn_ctl);
return (0);
}
- mp_conn_data = mp_conn_ctl->b_cont;
- mp6_conn_data = mp6_conn_ctl->b_cont;
-
zoneid = connp->conn_zoneid;
/* fixed length structure for IPv4 and IPv6 counters */
@@ -5414,6 +5714,9 @@
optp->len = msgdsize(mpdata);
qreply(q, mpctl);
+ mp_conn_tail = mp_attr_tail = mp6_conn_tail = mp6_attr_tail = NULL;
+ v4_conn_idx = v6_conn_idx = 0;
+
for (i = 0; i < CONN_G_HASH_SIZE; i++) {
connfp = &ipcl_globalhash_fanout[i];
connp = NULL;
@@ -5438,6 +5741,18 @@
else
state = MIB2_UDP_unknown;
+ needattr = B_FALSE;
+ bzero(&mlp, sizeof (mlp));
+ if (connp->conn_mlp_type != mlptSingle) {
+ if (connp->conn_mlp_type == mlptShared ||
+ connp->conn_mlp_type == mlptBoth)
+ mlp.tme_flags |= MIB2_TMEF_SHARED;
+ if (connp->conn_mlp_type == mlptPrivate ||
+ connp->conn_mlp_type == mlptBoth)
+ mlp.tme_flags |= MIB2_TMEF_PRIVATE;
+ needattr = B_TRUE;
+ }
+
/*
* Create an IPv4 table entry for IPv4 entries and also
* any IPv6 entries which are bound to in6addr_any
@@ -5472,8 +5787,13 @@
ude.udpEntryInfo.ue_RemoteAddress = 0;
ude.udpEntryInfo.ue_RemotePort = 0;
}
- (void) snmp_append_data2(mp_conn_data,
+ (void) snmp_append_data2(mp_conn_ctl->b_cont,
&mp_conn_tail, (char *)&ude, sizeof (ude));
+ mlp.tme_connidx = v4_conn_idx++;
+ if (needattr)
+ (void) snmp_append_data2(
+ mp_attr_ctl->b_cont, &mp_attr_tail,
+ (char *)&mlp, sizeof (mlp));
}
if (udp->udp_ipversion == IPV6_VERSION) {
ude6.udp6EntryInfo.ue_state = state;
@@ -5490,9 +5810,15 @@
sin6_null.sin6_addr;
ude6.udp6EntryInfo.ue_RemotePort = 0;
}
- (void) snmp_append_data2(mp6_conn_data,
+ (void) snmp_append_data2(mp6_conn_ctl->b_cont,
&mp6_conn_tail, (char *)&ude6,
sizeof (ude6));
+ mlp.tme_connidx = v6_conn_idx++;
+ if (needattr)
+ (void) snmp_append_data2(
+ mp6_attr_ctl->b_cont,
+ &mp6_attr_tail, (char *)&mlp,
+ sizeof (mlp));
}
}
}
@@ -5502,17 +5828,39 @@
sizeof (struct T_optmgmt_ack)];
optp->level = MIB2_UDP;
optp->name = MIB2_UDP_ENTRY;
- optp->len = msgdsize(mp_conn_data);
+ optp->len = msgdsize(mp_conn_ctl->b_cont);
qreply(q, mp_conn_ctl);
+ /* table of MLP attributes... */
+ optp = (struct opthdr *)&mp_attr_ctl->b_rptr[
+ sizeof (struct T_optmgmt_ack)];
+ optp->level = MIB2_UDP;
+ optp->name = EXPER_XPORT_MLP;
+ optp->len = msgdsize(mp_attr_ctl->b_cont);
+ if (optp->len == 0)
+ freemsg(mp_attr_ctl);
+ else
+ qreply(q, mp_attr_ctl);
+
/* IPv6 UDP endpoints */
optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[
sizeof (struct T_optmgmt_ack)];
optp->level = MIB2_UDP6;
optp->name = MIB2_UDP6_ENTRY;
- optp->len = msgdsize(mp6_conn_data);
+ optp->len = msgdsize(mp6_conn_ctl->b_cont);
qreply(q, mp6_conn_ctl);
+ /* table of MLP attributes... */
+ optp = (struct opthdr *)&mp6_attr_ctl->b_rptr[
+ sizeof (struct T_optmgmt_ack)];
+ optp->level = MIB2_UDP6;
+ optp->name = EXPER_XPORT_MLP;
+ optp->len = msgdsize(mp6_attr_ctl->b_cont);
+ if (optp->len == 0)
+ freemsg(mp6_attr_ctl);
+ else
+ qreply(q, mp6_attr_ctl);
+
return (1);
}
@@ -5733,15 +6081,17 @@
/*
* Don't let port fall into the privileged range.
- * Since the extra priviledged ports can be arbitrary we also
+ * Since the extra privileged ports can be arbitrary we also
* ensure that we exclude those from consideration.
* udp_g_epriv_ports is not sorted thus we loop over it until
* there are no changes.
*/
static in_port_t
-udp_update_next_port(in_port_t port, boolean_t random)
+udp_update_next_port(udp_t *udp, in_port_t port, boolean_t random)
{
int i;
+ in_port_t nextport;
+ boolean_t restart = B_FALSE;
if (random && udp_random_anon_port != 0) {
(void) random_get_pseudo_bytes((uint8_t *)&port,
@@ -5763,8 +6113,15 @@
}
retry:
- if (port < udp_smallest_anon_port || port > udp_largest_anon_port)
+ if (port < udp_smallest_anon_port)
+ port = udp_smallest_anon_port;
+
+ if (port > udp_largest_anon_port) {
port = udp_smallest_anon_port;
+ if (restart)
+ return (0);
+ restart = B_TRUE;
+ }
if (port < udp_smallest_nonpriv_port)
port = udp_smallest_nonpriv_port;
@@ -5779,27 +6136,103 @@
goto retry;
}
}
+
+ if (is_system_labeled() &&
+ (nextport = tsol_next_port(crgetzone(udp->udp_connp->conn_cred),
+ port, IPPROTO_UDP, B_TRUE)) != 0) {
+ port = nextport;
+ goto retry;
+ }
+
return (port);
}
+static int
+udp_update_label(queue_t *wq, mblk_t *mp, ipaddr_t dst)
+{
+ int err;
+ uchar_t opt_storage[IP_MAX_OPT_LENGTH];
+ udp_t *udp = Q_TO_UDP(wq);
+
+ err = tsol_compute_label(DB_CREDDEF(mp, udp->udp_connp->conn_cred), dst,
+ opt_storage, udp->udp_mac_exempt);
+ if (err == 0) {
+ err = tsol_update_options(&udp->udp_ip_snd_options,
+ &udp->udp_ip_snd_options_len, &udp->udp_label_len,
+ opt_storage);
+ }
+ if (err != 0) {
+ DTRACE_PROBE4(
+ tx__ip__log__info__updatelabel__udp,
+ char *, "queue(1) failed to update options(2) on mp(3)",
+ queue_t *, wq, char *, opt_storage, mblk_t *, mp);
+ } else {
+ IN6_IPADDR_TO_V4MAPPED(dst, &udp->udp_v6lastdst);
+ }
+ return (err);
+}
+
static mblk_t *
udp_output_v4(conn_t *connp, mblk_t *mp, ipaddr_t v4dst, uint16_t port,
uint_t srcid, int *error)
{
udp_t *udp = connp->conn_udp;
queue_t *q = connp->conn_wq;
- mblk_t *mp1 = (DB_TYPE(mp) == M_DATA ? mp : mp->b_cont);
+ mblk_t *mp1 = mp;
mblk_t *mp2;
ipha_t *ipha;
int ip_hdr_length;
uint32_t ip_len;
udpha_t *udpha;
+ udpattrs_t attrs;
*error = 0;
+ if (v4dst == INADDR_ANY)
+ v4dst = htonl(INADDR_LOOPBACK);
+
+ /*
+ * If options passed in, feed it for verification and handling
+ */
+ attrs.udpattr_credset = B_FALSE;
+ if (DB_TYPE(mp) != M_DATA) {
+ mp1 = mp->b_cont;
+ if (((struct T_unitdata_req *)mp->b_rptr)->OPT_length != 0) {
+ attrs.udpattr_ipp = NULL;
+ attrs.udpattr_mb = mp;
+ if (udp_unitdata_opt_process(q, mp, error, &attrs) < 0)
+ goto done;
+ /*
+ * Note: success in processing options.
+ * mp option buffer represented by
+ * OPT_length/offset now potentially modified
+ * and contain option setting results
+ */
+ ASSERT(*error == 0);
+ }
+ }
+
/* mp1 points to the M_DATA mblk carrying the packet */
ASSERT(mp1 != NULL && DB_TYPE(mp1) == M_DATA);
+ /* Check if our saved options are valid; update if not */
+ if (is_system_labeled()) {
+ /* Using UDP MLP requires SCM_UCRED from user */
+ if (connp->conn_mlp_type != mlptSingle &&
+ !attrs.udpattr_credset) {
+ DTRACE_PROBE4(
+ tx__ip__log__info__output__udp,
+ char *, "MLP mp(1) lacks SCM_UCRED attr(2) on q(3)",
+ mblk_t *, mp1, udpattrs_t *, &attrs, queue_t *, q);
+ *error = ECONNREFUSED;
+ goto done;
+ }
+ if ((!IN6_IS_ADDR_V4MAPPED(&udp->udp_v6lastdst) ||
+ V4_PART_OF_V6(udp->udp_v6lastdst) != v4dst) &&
+ (*error = udp_update_label(q, mp, v4dst)) != 0)
+ goto done;
+ }
+
/* Add an IP header */
ip_hdr_length = IP_SIMPLE_HDR_LENGTH + UDPH_SIZE +
udp->udp_ip_snd_options_len;
@@ -5887,10 +6320,7 @@
/*
* Copy in the destination address
*/
- if (v4dst == INADDR_ANY)
- ipha->ipha_dst = htonl(INADDR_LOOPBACK);
- else
- ipha->ipha_dst = v4dst;
+ ipha->ipha_dst = v4dst;
/*
* Set ttl based on IP_MULTICAST_TTL to match IPv6 logic.
@@ -5951,6 +6381,8 @@
}
/* Set UDP length and checksum */
*((uint32_t *)&udpha->uha_length) = ip_len;
+ if (DB_CRED(mp) != NULL)
+ mblk_setcred(mp1, DB_CRED(mp));
if (DB_TYPE(mp) != M_DATA) {
ASSERT(mp != mp1);
@@ -6059,10 +6491,12 @@
if (CLASSD(dst)) {
ASSERT(ipif != NULL);
ire = ire_ctable_lookup(dst, 0, 0, ipif,
- connp->conn_zoneid, MATCH_IRE_ILL_GROUP);
+ connp->conn_zoneid, MBLK_GETLABEL(mp),
+ MATCH_IRE_ILL_GROUP);
} else {
ASSERT(ipif == NULL);
- ire = ire_cache_lookup(dst, connp->conn_zoneid);
+ ire = ire_cache_lookup(dst, connp->conn_zoneid,
+ MBLK_GETLABEL(mp));
}
if (ire == NULL) {
@@ -6226,6 +6660,30 @@
IRE_REFRELE(ire);
}
+static boolean_t
+udp_update_label_v6(queue_t *wq, mblk_t *mp, in6_addr_t *dst)
+{
+ udp_t *udp = Q_TO_UDP(wq);
+ int err;
+ uchar_t opt_storage[TSOL_MAX_IPV6_OPTION];
+
+ err = tsol_compute_label_v6(DB_CREDDEF(mp, udp->udp_connp->conn_cred),
+ dst, opt_storage, udp->udp_mac_exempt);
+ if (err == 0) {
+ err = tsol_update_sticky(&udp->udp_sticky_ipp,
+ &udp->udp_label_len_v6, opt_storage);
+ }
+ if (err != 0) {
+ DTRACE_PROBE4(
+ tx__ip__log__drop__updatelabel__udp6,
+ char *, "queue(1) failed to update options(2) on mp(3)",
+ queue_t *, wq, char *, opt_storage, mblk_t *, mp);
+ } else {
+ udp->udp_v6lastdst = *dst;
+ }
+ return (err);
+}
+
/*
* This routine handles all messages passed downstream. It either
* consumes the message or passes it downstream; it never queues a
@@ -6241,7 +6699,6 @@
uint_t srcid;
queue_t *q = connp->conn_wq;
udp_t *udp = connp->conn_udp;
- t_scalar_t optlen;
int error = 0;
struct sockaddr_storage ss;
@@ -6271,7 +6728,6 @@
ASSERT(udp->udp_issocket);
UDP_DBGSTAT(udp_data_notconn);
/* Not connected; do some more checks below */
- optlen = 0;
break;
}
/* M_DATA for connected socket */
@@ -6310,7 +6766,7 @@
mp = udp_output_v4(connp, mp, v4dst,
udp->udp_dstport, 0, &error);
} else {
- mp = udp_output_v6(connp, mp, sin6, 0, &error);
+ mp = udp_output_v6(connp, mp, sin6, &error);
}
if (error != 0) {
ASSERT(addr != NULL && addrlen != 0);
@@ -6356,8 +6812,7 @@
addr = (struct sockaddr *)
&mp->b_rptr[tudr->DEST_offset];
addrlen = tudr->DEST_length;
- optlen = tudr->OPT_length;
- if (optlen != 0)
+ if (tudr->OPT_length != 0)
UDP_STAT(udp_out_opt);
break;
}
@@ -6386,7 +6841,7 @@
* Destination is a non-IPv4-compatible IPv6 address.
* Send out an IPv6 format packet.
*/
- mp = udp_output_v6(connp, mp, sin6, optlen, &error);
+ mp = udp_output_v6(connp, mp, sin6, &error);
if (error != 0)
goto ud_error;
@@ -6430,26 +6885,6 @@
break;
}
- /*
- * If options passed in, feed it for verification and handling
- */
- if (optlen != 0) {
- ASSERT(DB_TYPE(mp) != M_DATA);
- if (udp_unitdata_opt_process(q, mp, &error, NULL) < 0) {
- /* failure */
- TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END,
- "udp_wput_end: q %p (%S)", q,
- "udp_unitdata_opt_process");
- goto ud_error;
- }
- /*
- * Note: success in processing options.
- * mp option buffer represented by
- * OPT_length/offset now potentially modified
- * and contain option setting results
- */
- }
- ASSERT(error == 0);
mp = udp_output_v4(connp, mp, v4dst, port, srcid, &error);
if (error != 0) {
ud_error:
@@ -6566,12 +7001,11 @@
* address.
*/
static mblk_t *
-udp_output_v6(conn_t *connp, mblk_t *mp, sin6_t *sin6, t_scalar_t tudr_optlen,
- int *error)
+udp_output_v6(conn_t *connp, mblk_t *mp, sin6_t *sin6, int *error)
{
ip6_t *ip6h;
ip6i_t *ip6i; /* mp1->b_rptr even if no ip6i_t */
- mblk_t *mp1 = (DB_TYPE(mp) == M_DATA ? mp : mp->b_cont);
+ mblk_t *mp1 = mp;
mblk_t *mp2;
int udp_ip_hdr_len = IPV6_HDR_LEN + UDPH_SIZE;
size_t ip_len;
@@ -6586,13 +7020,12 @@
uint_t option_exists = 0, is_sticky = 0;
uint8_t *cp;
uint8_t *nxthdr_ptr;
+ in6_addr_t ip6_dst;
+ udpattrs_t attrs;
+ boolean_t opt_present;
*error = 0;
- /* mp1 points to the M_DATA mblk carrying the packet */
- ASSERT(mp1 != NULL && DB_TYPE(mp1) == M_DATA);
- ASSERT(tudr_optlen == 0 || DB_TYPE(mp) != M_DATA);
-
/*
* If the local address is a mapped address return
* an error.
@@ -6611,14 +7044,23 @@
/*
* If TPI options passed in, feed it for verification and handling
*/
- if (tudr_optlen != 0) {
- if (udp_unitdata_opt_process(q, mp, error, (void *)ipp) < 0) {
- /* failure */
- goto done;
- }
- ignore = ipp->ipp_sticky_ignored;
- ASSERT(*error == 0);
- }
+ attrs.udpattr_credset = B_FALSE;
+ opt_present = B_FALSE;
+ if (DB_TYPE(mp) != M_DATA) {
+ mp1 = mp->b_cont;
+ if (((struct T_unitdata_req *)mp->b_rptr)->OPT_length != 0) {
+ attrs.udpattr_ipp = ipp;
+ attrs.udpattr_mb = mp;
+ if (udp_unitdata_opt_process(q, mp, error, &attrs) < 0)
+ goto done;
+ ASSERT(*error == 0);
+ opt_present = B_TRUE;
+ }
+ }
+ ignore = ipp->ipp_sticky_ignored;
+
+ /* mp1 points to the M_DATA mblk carrying the packet */
+ ASSERT(mp1 != NULL && DB_TYPE(mp1) == M_DATA);
if (sin6->sin6_scope_id != 0 &&
IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
@@ -6630,6 +7072,45 @@
option_exists |= IPPF_SCOPE_ID;
}
+ /*
+ * Compute the destination address
+ */
+ ip6_dst = sin6->sin6_addr;
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
+ ip6_dst = ipv6_loopback;
+
+ /*
+ * If we're not going to the same destination as last time, then
+ * recompute the label required. This is done in a separate routine to
+ * avoid blowing up our stack here.
+ */
+ if (is_system_labeled()) {
+ /* Using UDP MLP requires SCM_UCRED from user */
+ if (connp->conn_mlp_type != mlptSingle &&
+ !attrs.udpattr_credset) {
+ DTRACE_PROBE4(
+ tx__ip__log__info__output__udp6,
+ char *, "MLP mp(1) lacks SCM_UCRED attr(2) on q(3)",
+ mblk_t *, mp1, udpattrs_t *, &attrs, queue_t *, q);
+ *error = ECONNREFUSED;
+ goto done;
+ }
+ if ((opt_present ||
+ !IN6_ARE_ADDR_EQUAL(&udp->udp_v6lastdst, &ip6_dst)) &&
+ (*error = udp_update_label_v6(q, mp, &ip6_dst)) != 0)
+ goto done;
+ }
+
+ /*
+ * If there's a security label here, then we ignore any options the
+ * user may try to set. We keep the peer's label as a hidden sticky
+ * option.
+ */
+ if (udp->udp_label_len_v6 > 0) {
+ ignore &= ~IPPF_HOPOPTS;
+ ipp->ipp_fields &= ~IPPF_HOPOPTS;
+ }
+
if ((udp->udp_sticky_ipp.ipp_fields == 0) && (ipp->ipp_fields == 0)) {
/* No sticky options nor ancillary data. */
goto no_options;
@@ -6944,10 +7425,7 @@
/*
* Copy in the destination address
*/
- if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
- ip6h->ip6_dst = ipv6_loopback;
- else
- ip6h->ip6_dst = sin6->sin6_addr;
+ ip6h->ip6_dst = ip6_dst;
ip6h->ip6_vcf =
(IPV6_DEFAULT_VERS_AND_FLOW & IPV6_VERS_AND_FLOW_MASK) |
@@ -7045,6 +7523,8 @@
ip_len = htons(ip_len);
#endif
ip6h->ip6_plen = ip_len;
+ if (DB_CRED(mp) != NULL)
+ mblk_setcred(mp1, DB_CRED(mp));
if (DB_TYPE(mp) != M_DATA) {
ASSERT(mp != mp1);
@@ -7459,7 +7939,7 @@
static int
udp_unitdata_opt_process(queue_t *q, mblk_t *mp, int *errorp,
- void *thisdg_attrs)
+ udpattrs_t *udpattrs)
{
struct T_unitdata_req *udreqp;
int is_absreq_failure;
@@ -7471,7 +7951,6 @@
cr = DB_CREDDEF(mp, connp->conn_cred);
udreqp = (struct T_unitdata_req *)mp->b_rptr;
- *errorp = 0;
/*
* Use upper queue for option processing since the callback
@@ -7479,7 +7958,7 @@
*/
*errorp = tpi_optcom_buf(_WR(UDP_RD(q)), mp, &udreqp->OPT_length,
udreqp->OPT_offset, cr, &udp_opt_obj,
- thisdg_attrs, &is_absreq_failure);
+ udpattrs, &is_absreq_failure);
if (*errorp != 0) {
/*
--- a/usr/src/uts/common/inet/udp/udp_opt_data.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/udp/udp_opt_data.c Fri Mar 24 12:29:20 2006 -0800
@@ -36,6 +36,7 @@
#include <inet/common.h>
#include <netinet/ip6.h>
#include <inet/ip.h>
+#include <inet/udp_impl.h>
/*
* MK_XXX Following 2 includes temporary to import ip6_rthdr_t
* definition. May not be needed if we fix ip6_dg_snd_attrs_t
@@ -45,19 +46,9 @@
#include <inet/ip6.h>
#include <netinet/in.h>
-#include <netinet/tcp.h>
#include <netinet/udp.h>
-#include <netinet/ip_mroute.h>
#include <inet/optcom.h>
-extern int udp_opt_default(queue_t *q, t_scalar_t level, t_scalar_t name,
- uchar_t *ptr);
-extern int udp_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name,
- uchar_t *ptr);
-extern int udp_opt_set(queue_t *q, uint_t optset_context,
- int level, int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp,
- uchar_t *outvalp, void *thisdg_attrs, cred_t *cr, mblk_t *mblk);
-
/*
* Table of all known options handled on a UDP protocol stack.
*
@@ -82,6 +73,12 @@
},
{ SO_TIMESTAMP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0
},
+{ SO_ANON_MLP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int),
+ 0 },
+{ SO_MAC_EXEMPT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int),
+ 0 },
+{ SCM_UCRED, SOL_SOCKET, OA_W, OA_W, OP_NP, OP_VARLEN|OP_NODEFAULT, 512, 0 },
+
{ IP_OPTIONS, IPPROTO_IP, OA_RW, OA_RW, OP_NP,
(OP_PASSNEXT|OP_VARLEN|OP_NODEFAULT), 40, -1 /* not initialized */ },
{ T_IP_OPTIONS, IPPROTO_IP, OA_RW, OA_RW, OP_NP,
--- a/usr/src/uts/common/inet/udp_impl.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/inet/udp_impl.h Fri Mar 24 12:29:20 2006 -0800
@@ -48,6 +48,7 @@
#include <inet/common.h>
#include <inet/ip.h>
+#include <inet/optcom.h>
#define UDP_MOD_ID 5607
@@ -122,7 +123,9 @@
udp_direct_sockfs : 1, /* direct calls to/from sockfs */
udp_timestamp : 1, /* SO_TIMESTAMP "socket" option */
- udp_pad_to_bit_31 : 3;
+ udp_anon_mlp : 1, /* SO_ANON_MLP */
+ udp_mac_exempt : 1, /* SO_MAC_EXEMPT */
+ udp_pad_to_bit_31 : 1;
uint8_t udp_type_of_service; /* IP_TOS option */
uint8_t udp_ttl; /* TTL or hoplimit */
@@ -146,6 +149,9 @@
uint_t udp_rcv_cnt; /* total data in rcv_list */
uint_t udp_rcv_msgcnt; /* total messages in rcv_list */
size_t udp_rcv_hiwat; /* receive high watermark */
+ uint_t udp_label_len; /* length of security label */
+ uint_t udp_label_len_v6; /* len of v6 security label */
+ in6_addr_t udp_v6lastdst; /* most recent destination */
} udp_t;
/* UDP Protocol header */
@@ -156,7 +162,6 @@
uint16_t uha_length; /* UDP length */
uint16_t uha_checksum; /* UDP checksum */
} udpha_t;
-#define UDPH_SIZE 8
/* Named Dispatch Parameter Management Structure */
typedef struct udpparam_s {
@@ -245,6 +250,22 @@
extern void udp_wput_data(queue_t *, mblk_t *, struct sockaddr *,
socklen_t);
+extern int udp_opt_default(queue_t *q, t_scalar_t level, t_scalar_t name,
+ uchar_t *ptr);
+extern int udp_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name,
+ uchar_t *ptr);
+extern int udp_opt_set(queue_t *q, uint_t optset_context,
+ int level, int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp,
+ uchar_t *outvalp, void *thisdg_attrs, cred_t *cr, mblk_t *mblk);
+
+/*
+ * Object to represent database of options to search passed to
+ * {sock,tpi}optcom_req() interface routine to take care of option
+ * management and associated methods.
+ */
+extern optdb_obj_t udp_opt_obj;
+extern uint_t udp_max_optsize;
+
#endif /* _KERNEL */
#ifdef __cplusplus
--- a/usr/src/uts/common/io/tl.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/io/tl.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -863,7 +862,7 @@
static void tl_icon_sendmsgs(tl_endpt_t *, mblk_t **);
static void tl_icon_freemsgs(mblk_t **);
static void tl_merror(queue_t *, mblk_t *, int);
-static void tl_fill_option(uchar_t *, cred_t *, pid_t, int);
+static void tl_fill_option(uchar_t *, cred_t *, pid_t, int, cred_t *);
static int tl_default_opt(queue_t *, int, int, uchar_t *);
static int tl_get_opt(queue_t *, int, int, uchar_t *);
static int tl_set_opt(queue_t *, uint_t, int, int, uint_t, uchar_t *, uint_t *,
@@ -3242,7 +3241,7 @@
tl_fill_option(cimp->b_rptr + ci->OPT_offset,
DB_CREDDEF(cimp, tep->te_credp),
TLPID(cimp, tep),
- peer_tep->te_flag);
+ peer_tep->te_flag, peer_tep->te_credp);
} else if (ooff != 0) {
/* Copy option from T_CONN_REQ */
ci->OPT_offset = (t_scalar_t)T_ALIGN(ci->SRC_offset +
@@ -3723,7 +3722,8 @@
cc->RES_length);
cc->OPT_length = olen;
tl_fill_option(ccmp->b_rptr + cc->OPT_offset,
- acc_ep->te_credp, acc_ep->te_cpid, cl_ep->te_flag);
+ acc_ep->te_credp, acc_ep->te_cpid, cl_ep->te_flag,
+ cl_ep->te_credp);
} else {
cc->OPT_offset = 0;
cc->OPT_length = 0;
@@ -5212,7 +5212,7 @@
tl_fill_option(ui_mp->b_rptr + udind->OPT_offset +
oldolen,
DB_CREDDEF(mp, tep->te_credp), TLPID(mp, tep),
- peer_tep->te_flag);
+ peer_tep->te_flag, peer_tep->te_credp);
} else {
bcopy((void *)((uintptr_t)udreq + ooff),
(void *)((uintptr_t)udind + udind->OPT_offset),
@@ -5928,7 +5928,7 @@
}
static void
-tl_fill_option(uchar_t *buf, cred_t *cr, pid_t cpid, int flag)
+tl_fill_option(uchar_t *buf, cred_t *cr, pid_t cpid, int flag, cred_t *pcr)
{
if (flag & TL_SETCRED) {
struct opthdr *opt = (struct opthdr *)buf;
@@ -5953,7 +5953,7 @@
opt->name = TL_OPT_PEER_UCRED;
opt->len = (t_uscalar_t)OPTLEN(ucredsize);
- (void) cred2ucred(cr, cpid, (void *)(opt + 1));
+ (void) cred2ucred(cr, cpid, (void *)(opt + 1), pcr);
} else {
struct T_opthdr *topt = (struct T_opthdr *)buf;
ASSERT(flag & TL_SOCKUCRED);
@@ -5962,7 +5962,7 @@
topt->name = SCM_UCRED;
topt->len = ucredsize + sizeof (*topt);
topt->status = 0;
- (void) cred2ucred(cr, cpid, (void *)(topt + 1));
+ (void) cred2ucred(cr, cpid, (void *)(topt + 1), pcr);
}
}
--- a/usr/src/uts/common/net/route.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/net/route.h Fri Mar 24 12:29:20 2006 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 1992-2002 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
@@ -48,6 +48,9 @@
#pragma ident "%Z%%M% %I% %E% SMI"
/* from UCB 8.5 (Berkeley) 2/8/95 */
+#include <sys/tsol/label.h>
+#include <sys/tsol/label_macro.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -219,6 +222,38 @@
#define RTAX_SRCIFP 9
#define RTAX_MAX RTA_NUMBITS /* size of array to allocate */
+/*
+ * Routing socket message extension after sockaddrs.
+ */
+typedef struct rtm_ext_s {
+ uint32_t rtmex_type; /* identifier for type of extension */
+ uint32_t rtmex_len; /* length of this extension */
+} rtm_ext_t;
+
+#define RTMEX_GATEWAY_SECATTR 1 /* extension is tsol_rtsecattr */
+#define RTMEX_MAX RTMEX_GATEWAY_SECATTR
+
+/*
+ * Trusted Solaris route security attributes extension.
+ */
+typedef struct tsol_rtsecattr_s {
+ uint32_t rtsa_cnt; /* number of attributes */
+ struct rtsa_s {
+ uint32_t rtsa_mask; /* see RTSA_* below */
+ uint32_t rtsa_doi; /* domain of interpretation */
+ brange_t rtsa_slrange; /* sensitivity label range */
+ } rtsa_attr[1];
+} tsol_rtsecattr_t;
+
+#define TSOL_RTSECATTR_SIZE(n) \
+ (sizeof (tsol_rtsecattr_t) + (((n) - 1) * sizeof (struct rtsa_s)))
+
+#define RTSA_MINSL 0x1 /* minimum sensitivity label is valid */
+#define RTSA_MAXSL 0x2 /* maximum sensitivity label is valid */
+#define RTSA_DOI 0x4 /* domain of interpretation is valid */
+#define RTSA_CIPSO 0x100 /* CIPSO protocol */
+#define RTSA_SLRANGE (RTSA_MINSL|RTSA_MAXSL)
+
#ifdef __cplusplus
}
#endif
--- a/usr/src/uts/common/netinet/ip6.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/netinet/ip6.h Fri Mar 24 12:29:20 2006 -0800
@@ -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,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.
*/
@@ -155,6 +153,10 @@
#define IP6OPT_HOME_ADDRESS 0xc9 /* 11 0 01001 */
#define IP6OPT_EID 0x8a /* 10 0 01010 */
+#define IP6OPT_LS 0x0a /* 00 0 01010 */
+
+#define IP6_MAX_OPT_LENGTH 255
+
/* Jumbo Payload Option */
struct ip6_opt_jumbo {
uint8_t ip6oj_type;
@@ -242,6 +244,23 @@
/* Followed by sub-options */
};
+/* Labeled Security Option */
+struct ip6_opt_labeled_security {
+ uint8_t ip6ol_type;
+ uint8_t ip6ol_len; /* always even for defined values */
+ uint8_t ip6ol_doi[4];
+ /* Followed by sub-options */
+};
+
+#define IP6LS_DOI_V4 0 /* IPv4 transition */
+
+#define IP6LS_TT_LEVEL 1 /* level or classification; 2-octet value */
+#define IP6LS_TT_VECTOR 2 /* compartments; bit vector (even # octets) */
+#define IP6LS_TT_ENUM 3 /* set membership; list of 2-octet values */
+#define IP6LS_TT_RANGES 4 /* set membership; pairs of 2-octet values */
+#define IP6LS_TT_V4 5 /* IPv4 compatible option */
+#define IP6LS_TT_DEST 6 /* destination-only data; per DOI */
+
#ifdef __cplusplus
}
#endif
--- a/usr/src/uts/common/nfs/nfs.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/nfs/nfs.h Fri Mar 24 12:29:20 2006 -0800
@@ -38,10 +38,12 @@
#include <rpc/types.h>
#include <sys/types32.h>
#ifdef _KERNEL
-#include <rpc/xdr.h>
+#include <rpc/rpc.h>
#include <sys/fcntl.h>
#include <sys/kstat.h>
#include <sys/dirent.h>
+#include <sys/zone.h>
+#include <sys/tsol/label.h>
#include <nfs/mount.h>
#endif
#include <vm/page.h>
@@ -926,6 +928,8 @@
extern void nfsauth_init();
extern void nfsauth_fini();
extern int nfs_setopts(vnode_t *vp, model_t model, struct nfs_args *args);
+extern int nfs_mount_label_policy(vfs_t *vfsp, struct netbuf *addr,
+ struct knetconfig *knconf, cred_t *cr);
extern void nfs_srv_stop_all(void);
extern void nfs_srv_quiesce_all(void);
extern void (*nfs_srv_quiesce_func)(void);
--- a/usr/src/uts/common/os/cred.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/os/cred.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -50,9 +49,7 @@
#include <sys/kmem.h>
#include <sys/user.h>
#include <sys/proc.h>
-#include <sys/acct.h>
#include <sys/syscall.h>
-#include <sys/cmn_err.h>
#include <sys/debug.h>
#include <sys/atomic.h>
#include <sys/ucred.h>
@@ -60,12 +57,14 @@
#include <sys/modctl.h>
#include <c2/audit.h>
#include <sys/zone.h>
+#include <sys/tsol/label.h>
static struct kmem_cache *cred_cache;
static size_t crsize = 0;
static int audoff = 0;
uint32_t ucredsize;
cred_t *kcred;
+static cred_t *dummycr;
int rstlink; /* link(2) restricted to files owned by user? */
@@ -74,6 +73,7 @@
#define CR_AUINFO(c) (auditinfo_addr_t *)((audoff == 0) ? NULL : \
((char *)(c)) + audoff)
+#define REMOTE_PEER_CRED(c) ((c)->cr_gid == -1)
/*
* Initialize credentials data structures.
@@ -106,6 +106,19 @@
NULL, NULL, NULL, NULL, NULL, 0);
/*
+ * dummycr is used to copy initial state for creds.
+ */
+ dummycr = cralloc();
+ bzero(dummycr, crsize);
+ dummycr->cr_ref = 1;
+ dummycr->cr_uid = -1;
+ dummycr->cr_gid = -1;
+ dummycr->cr_ruid = -1;
+ dummycr->cr_rgid = -1;
+ dummycr->cr_suid = -1;
+ dummycr->cr_sgid = -1;
+
+ /*
* kcred is used by anything that needs all privileges; it's
* also the template used for crget as it has all the compatible
* sets filled in.
@@ -130,7 +143,8 @@
priv_delset(&CR_IPRIV(kcred), PRIV_FILE_LINK_ANY);
CR_EPRIV(kcred) = CR_PPRIV(kcred) = CR_IPRIV(kcred);
- /* CR_FLAGS(kcred) == 0, courtesy of bzero() */
+
+ CR_FLAGS(kcred) = NET_MAC_AWARE;
/*
* Set up credentials of p0.
@@ -150,6 +164,7 @@
cred_t *cr = kmem_cache_alloc(cred_cache, KM_SLEEP);
cr->cr_ref = 1; /* So we can crfree() */
cr->cr_zone = NULL;
+ cr->cr_label = NULL;
return (cr);
}
@@ -165,6 +180,8 @@
bcopy(kcred, cr, crsize);
cr->cr_ref = 1;
zone_cred_hold(cr->cr_zone);
+ if (cr->cr_label)
+ label_hold(cr->cr_label);
return (cr);
}
@@ -220,12 +237,15 @@
/*
* Release previous hold on a cred structure. Free it if refcnt == 0.
+ * If cred uses label different from zone label, free it.
*/
void
crfree(cred_t *cr)
{
if (atomic_add_32_nv(&cr->cr_ref, -1) == 0) {
ASSERT(cr != kcred);
+ if (cr->cr_label)
+ label_rele(cr->cr_label);
if (cr->cr_zone)
zone_cred_rele(cr->cr_zone);
kmem_cache_free(cred_cache, cr);
@@ -246,6 +266,8 @@
bcopy(cr, newcr, crsize);
if (newcr->cr_zone)
zone_cred_hold(newcr->cr_zone);
+ if (newcr->cr_label)
+ label_hold(cr->cr_label);
crfree(cr);
newcr->cr_ref = 2; /* caller gets two references */
return (newcr);
@@ -264,6 +286,8 @@
bcopy(oldcr, newcr, crsize);
if (newcr->cr_zone)
zone_cred_hold(newcr->cr_zone);
+ if (newcr->cr_label)
+ label_hold(newcr->cr_label);
crfree(oldcr);
newcr->cr_ref = 2; /* caller gets two references */
}
@@ -281,6 +305,8 @@
bcopy(cr, newcr, crsize);
if (newcr->cr_zone)
zone_cred_hold(newcr->cr_zone);
+ if (newcr->cr_label)
+ label_hold(newcr->cr_label);
newcr->cr_ref = 1;
return (newcr);
}
@@ -297,6 +323,8 @@
bcopy(oldcr, newcr, crsize);
if (newcr->cr_zone)
zone_cred_hold(newcr->cr_zone);
+ if (newcr->cr_label)
+ label_hold(newcr->cr_label);
newcr->cr_ref = 1;
}
@@ -304,7 +332,7 @@
* Return the (held) credentials for the current running process.
*/
cred_t *
-crgetcred()
+crgetcred(void)
{
cred_t *cr;
proc_t *p;
@@ -500,7 +528,9 @@
zoneid_t
crgetzoneid(const cred_t *cr)
{
- return (cr->cr_zone->zone_id);
+ return (cr->cr_zone == NULL ?
+ (cr->cr_uid == -1 ? (zoneid_t)-1 : GLOBAL_ZONEID) :
+ cr->cr_zone->zone_id);
}
projid_t
@@ -509,6 +539,26 @@
return (cr->cr_projid);
}
+zone_t *
+crgetzone(const cred_t *cr)
+{
+ return (cr->cr_zone);
+}
+
+struct ts_label_s *
+crgetlabel(const cred_t *cr)
+{
+ return (cr->cr_label ?
+ cr->cr_label :
+ (cr->cr_zone ? cr->cr_zone->zone_slabel : NULL));
+}
+
+boolean_t
+crisremote(const cred_t *cr)
+{
+ return (REMOTE_PEER_CRED(cr));
+}
+
#define BADID(x) ((x) != -1 && (unsigned int)(x) > MAXUID)
int
@@ -618,12 +668,12 @@
}
static int
-cred2ucaud(const cred_t *cr, auditinfo64_addr_t *ainfo)
+cred2ucaud(const cred_t *cr, auditinfo64_addr_t *ainfo, const cred_t *rcr)
{
auditinfo_addr_t *ai;
au_tid_addr_t tid;
- if (secpolicy_audit_getattr(CRED()) != 0)
+ if (secpolicy_audit_getattr(rcr) != 0)
return (-1);
ai = CR_AUINFO(cr); /* caller makes sure this is non-NULL */
@@ -642,13 +692,26 @@
return (0);
}
+void
+cred2uclabel(const cred_t *cr, bslabel_t *labelp)
+{
+ ts_label_t *tslp;
+
+ if ((tslp = crgetlabel(cr)) != NULL)
+ bcopy(&tslp->tsl_label, labelp, sizeof (bslabel_t));
+}
+
/*
* Convert a credential into a "ucred". Allow the caller to specify
* and aligned buffer, e.g., in an mblk, so we don't have to allocate
* memory and copy it twice.
+ *
+ * This function may call cred2ucaud(), which calls CRED(). Since this
+ * can be called from an interrupt thread, receiver's cred (rcr) is needed
+ * to determine whether audit info should be included.
*/
struct ucred_s *
-cred2ucred(const cred_t *cr, pid_t pid, void *buf)
+cred2ucred(const cred_t *cr, pid_t pid, void *buf, const cred_t *rcr)
{
struct ucred_s *uc;
@@ -663,14 +726,32 @@
uc->uc_credoff = UCRED_CRED_OFF;
uc->uc_privoff = UCRED_PRIV_OFF;
uc->uc_audoff = UCRED_AUD_OFF;
+ uc->uc_labeloff = UCRED_LABEL_OFF;
uc->uc_pid = pid;
uc->uc_projid = cr->cr_projid;
uc->uc_zoneid = crgetzoneid(cr);
- cred2prcred(cr, UCCRED(uc));
- cred2prpriv(cr, UCPRIV(uc));
- if (audoff == 0 || cred2ucaud(cr, UCAUD(uc)) != 0)
+ /*
+ * Note that cred2uclabel() call should not be factored out
+ * to the bottom of the if-else. UCXXX() macros depend on
+ * uc_xxxoff values to work correctly.
+ */
+ if (REMOTE_PEER_CRED(cr)) {
+ /*
+ * other than label, the rest of cred info about a
+ * remote peer isn't available.
+ */
+ cred2uclabel(cr, UCLABEL(uc));
+ uc->uc_credoff = 0;
+ uc->uc_privoff = 0;
uc->uc_audoff = 0;
+ } else {
+ cred2prcred(cr, UCCRED(uc));
+ cred2prpriv(cr, UCPRIV(uc));
+ if (audoff == 0 || cred2ucaud(cr, UCAUD(uc), rcr) != 0)
+ uc->uc_audoff = 0;
+ cred2uclabel(cr, UCLABEL(uc));
+ }
return (uc);
}
@@ -689,7 +770,7 @@
crhold(cr);
mutex_exit(&p->p_crlock);
- uc = cred2ucred(cr, p->p_pid, NULL);
+ uc = cred2ucred(cr, p->p_pid, NULL, CRED());
crfree(cr);
return (uc);
@@ -762,3 +843,64 @@
if (oldzptr)
zone_cred_rele(oldzptr);
}
+
+/*
+ * Create a new cred based on the supplied label
+ */
+cred_t *
+newcred_from_bslabel(bslabel_t *blabel, uint32_t doi, int flags)
+{
+ ts_label_t *lbl = labelalloc(blabel, doi, flags);
+ cred_t *cr = NULL;
+
+ if (lbl != NULL) {
+ if ((cr = kmem_cache_alloc(cred_cache, flags)) != NULL) {
+ bcopy(dummycr, cr, crsize);
+ cr->cr_label = lbl;
+ } else {
+ label_rele(lbl);
+ }
+ }
+
+ return (cr);
+}
+
+/*
+ * Derive a new cred from the existing cred, but with a different label.
+ * To be used when a cred is being shared, but the label needs to be changed
+ * by a caller without affecting other users
+ */
+cred_t *
+copycred_from_bslabel(cred_t *cr, bslabel_t *blabel, uint32_t doi, int flags)
+{
+ ts_label_t *lbl = labelalloc(blabel, doi, flags);
+ cred_t *newcr = NULL;
+
+ if (lbl != NULL) {
+ if ((newcr = kmem_cache_alloc(cred_cache, flags)) != NULL) {
+ bcopy(cr, newcr, crsize);
+ if (newcr->cr_zone)
+ zone_cred_hold(newcr->cr_zone);
+ newcr->cr_label = lbl;
+ newcr->cr_ref = 1;
+ } else {
+ label_rele(lbl);
+ }
+ }
+
+ return (newcr);
+}
+
+/*
+ * This function returns a pointer to the kcred-equivalent in the current zone.
+ */
+cred_t *
+zone_kcred(void)
+{
+ zone_t *zone;
+
+ if ((zone = CRED()->cr_zone) != NULL)
+ return (zone->zone_kcred);
+ else
+ return (kcred);
+}
--- a/usr/src/uts/common/os/exec.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/os/exec.c Fri Mar 24 12:29:20 2006 -0800
@@ -78,6 +78,7 @@
#define PRIV_SETID 0x02 /* needs to change uids */
#define PRIV_SETUGID 0x04 /* is setuid/setgid/forced privs */
#define PRIV_INCREASE 0x08 /* child runs with more privs */
+#define MAC_FLAGS 0x10 /* need to adjust MAC flags */
static int execsetid(struct vnode *, struct vattr *, uid_t *, uid_t *);
static int hold_execsw(struct execsw *);
@@ -515,6 +516,12 @@
cred->cr_sgid = gid;
}
+ if (privflags & MAC_FLAGS) {
+ if (!(CR_FLAGS(cred) & NET_MAC_AWARE_INHERIT))
+ CR_FLAGS(cred) &= ~NET_MAC_AWARE;
+ CR_FLAGS(cred) &= ~NET_MAC_AWARE_INHERIT;
+ }
+
/*
* Implement the privilege updates:
*
@@ -831,6 +838,11 @@
!priv_isequalset(&CR_PPRIV(cr), &CR_IPRIV(cr)))
privflags |= PRIV_RESET;
+ /* If MAC-aware flag(s) are on, need to update cred to remove. */
+ if ((CR_FLAGS(cr) & NET_MAC_AWARE) ||
+ (CR_FLAGS(cr) & NET_MAC_AWARE_INHERIT))
+ privflags |= MAC_FLAGS;
+
/*
* When we introduce the "forced" set then we will need
* to set PRIV_INCREASE here if I not a subset of P.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/os/labelsys.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,1384 @@
+/*
+ * 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/systm.h>
+#include <sys/types.h>
+#include <sys/stream.h>
+#include <sys/kmem.h>
+#include <sys/strsubr.h>
+#include <sys/cmn_err.h>
+#include <sys/debug.h>
+#include <sys/param.h>
+#include <sys/model.h>
+#include <sys/errno.h>
+#include <sys/modhash.h>
+
+#include <sys/policy.h>
+#include <sys/tsol/label.h>
+#include <sys/tsol/tsyscall.h>
+#include <sys/tsol/tndb.h>
+#include <sys/tsol/tnet.h>
+#include <sys/disp.h>
+
+#include <inet/ip.h>
+#include <inet/ip6.h>
+#include <sys/sdt.h>
+
+static mod_hash_t *tpc_name_hash; /* hash of cache entries by name */
+static kmutex_t tpc_lock;
+
+static tsol_tpc_t *tpc_unlab;
+
+/*
+ * tnrhc_table and tnrhc_table_v6 are similar to the IP forwarding tables
+ * in organization and search. The tnrhc_table[_v6] is an array of 33/129
+ * pointers to the 33/129 tnrhc tables indexed by the prefix length.
+ * A largest prefix match search is done by find_rhc_v[46] and it walks the
+ * tables from the most specific to the least specific table. Table 0
+ * corresponds to the single entry for 0.0.0.0/0 or ::0/0.
+ */
+tnrhc_hash_t *tnrhc_table[TSOL_MASK_TABLE_SIZE];
+tnrhc_hash_t *tnrhc_table_v6[TSOL_MASK_TABLE_SIZE_V6];
+kmutex_t tnrhc_g_lock;
+
+static void tsol_create_i_tmpls(void);
+
+static void tsol_create_i_tnrh(const tnaddr_t *);
+
+/* List of MLPs on valid on shared addresses */
+static tsol_mlp_list_t shared_mlps;
+
+/*
+ * Convert length for a mask to the mask.
+ */
+static ipaddr_t
+tsol_plen_to_mask(uint_t masklen)
+{
+ return (masklen == 0 ? 0 : htonl(IP_HOST_MASK << (IP_ABITS - masklen)));
+}
+
+/*
+ * Convert a prefix length to the mask for that prefix.
+ * Returns the argument bitmask.
+ */
+static void
+tsol_plen_to_mask_v6(uint_t plen, in6_addr_t *bitmask)
+{
+ uint32_t *ptr;
+
+ ASSERT(plen <= IPV6_ABITS);
+
+ ptr = (uint32_t *)bitmask;
+ while (plen >= 32) {
+ *ptr++ = 0xffffffffU;
+ plen -= 32;
+ }
+ if (plen > 0)
+ *ptr++ = htonl(0xffffffff << (32 - plen));
+ while (ptr < (uint32_t *)(bitmask + 1))
+ *ptr++ = 0;
+}
+
+boolean_t
+tnrhc_init_table(tnrhc_hash_t *table[], short prefix_len, int kmflag)
+{
+ int i;
+
+ mutex_enter(&tnrhc_g_lock);
+
+ if (table[prefix_len] == NULL) {
+ table[prefix_len] = (tnrhc_hash_t *)
+ kmem_zalloc(TNRHC_SIZE * sizeof (tnrhc_hash_t), kmflag);
+ if (table[prefix_len] == NULL) {
+ mutex_exit(&tnrhc_g_lock);
+ return (B_FALSE);
+ }
+ for (i = 0; i < TNRHC_SIZE; i++) {
+ mutex_init(&table[prefix_len][i].tnrh_lock,
+ NULL, MUTEX_DEFAULT, 0);
+ }
+ }
+ mutex_exit(&tnrhc_g_lock);
+ return (B_TRUE);
+}
+
+void
+tcache_init(void)
+{
+ tnaddr_t address;
+
+ /*
+ * Note: unable to use mod_hash_create_strhash here, since it's
+ * assymetric. It assumes that the user has allocated exactly
+ * strlen(key) + 1 bytes for the key when inserted, and attempts to
+ * kmem_free that memory on a delete.
+ */
+ tpc_name_hash = mod_hash_create_extended("tnrhtpc_by_name", 256,
+ mod_hash_null_keydtor, mod_hash_null_valdtor, mod_hash_bystr,
+ NULL, mod_hash_strkey_cmp, KM_SLEEP);
+ mutex_init(&tpc_lock, NULL, MUTEX_DEFAULT, NULL);
+
+ mutex_init(&tnrhc_g_lock, NULL, MUTEX_DEFAULT, NULL);
+
+ /* label_init always called before tcache_init */
+ ASSERT(l_admin_low != NULL && l_admin_high != NULL);
+
+ /* Initialize the zeroth table prior to loading the 0.0.0.0 entry */
+ (void) tnrhc_init_table(tnrhc_table, 0, KM_SLEEP);
+ (void) tnrhc_init_table(tnrhc_table_v6, 0, KM_SLEEP);
+ /*
+ * create an internal host template called "_unlab"
+ */
+ tsol_create_i_tmpls();
+
+ /*
+ * create a host entry, 0.0.0.0 = _unlab
+ */
+ bzero(&address, sizeof (tnaddr_t));
+ address.ta_family = AF_INET;
+ tsol_create_i_tnrh(&address);
+
+ /*
+ * create a host entry, ::0 = _unlab
+ */
+ address.ta_family = AF_INET6;
+ tsol_create_i_tnrh(&address);
+
+ rw_init(&shared_mlps.mlpl_rwlock, NULL, RW_DEFAULT, NULL);
+}
+
+/* Called only by the TNRHC_RELE macro when the refcount goes to zero. */
+void
+tnrhc_free(tsol_tnrhc_t *tnrhc)
+{
+ /*
+ * We assert rhc_invalid here to make sure that no new thread could
+ * possibly end up finding this entry. If it could, then the
+ * mutex_destroy would panic.
+ */
+ DTRACE_PROBE1(tx__tndb__l3__tnrhcfree, tsol_tnrhc_t *, tnrhc);
+ ASSERT(tnrhc->rhc_next == NULL && tnrhc->rhc_invalid);
+ mutex_exit(&tnrhc->rhc_lock);
+ mutex_destroy(&tnrhc->rhc_lock);
+ if (tnrhc->rhc_tpc != NULL)
+ TPC_RELE(tnrhc->rhc_tpc);
+ kmem_free(tnrhc, sizeof (*tnrhc));
+}
+
+/* Called only by the TPC_RELE macro when the refcount goes to zero. */
+void
+tpc_free(tsol_tpc_t *tpc)
+{
+ DTRACE_PROBE1(tx__tndb__l3__tpcfree, tsol_tpc_t *, tpc);
+ ASSERT(tpc->tpc_invalid);
+ mutex_exit(&tpc->tpc_lock);
+ mutex_destroy(&tpc->tpc_lock);
+ kmem_free(tpc, sizeof (*tpc));
+}
+
+/*
+ * Find and hold a reference to a template entry by name. Ignores entries that
+ * are being deleted.
+ */
+static tsol_tpc_t *
+tnrhtp_find(const char *name, mod_hash_t *hash)
+{
+ mod_hash_val_t hv;
+ tsol_tpc_t *tpc = NULL;
+
+ mutex_enter(&tpc_lock);
+ if (mod_hash_find(hash, (mod_hash_key_t)name, &hv) == 0) {
+ tpc = (tsol_tpc_t *)hv;
+ if (tpc->tpc_invalid)
+ tpc = NULL;
+ else
+ TPC_HOLD(tpc);
+ }
+ mutex_exit(&tpc_lock);
+ return (tpc);
+}
+
+static int
+tnrh_delete(const tsol_rhent_t *rhent)
+{
+ tsol_tnrhc_t *current;
+ tsol_tnrhc_t **prevp;
+ ipaddr_t tmpmask;
+ in6_addr_t tmpmask_v6;
+ tnrhc_hash_t *tnrhc_hash;
+
+ if (rhent->rh_address.ta_family == AF_INET) {
+ if (rhent->rh_prefix < 0 || rhent->rh_prefix > IP_ABITS)
+ return (EINVAL);
+ if (tnrhc_table[rhent->rh_prefix] == NULL)
+ return (ENOENT);
+ tmpmask = tsol_plen_to_mask(rhent->rh_prefix);
+ tnrhc_hash = &tnrhc_table[rhent->rh_prefix][
+ TSOL_ADDR_HASH(rhent->rh_address.ta_addr_v4.s_addr &
+ tmpmask, TNRHC_SIZE)];
+ } else if (rhent->rh_address.ta_family == AF_INET6) {
+ if (rhent->rh_prefix < 0 || rhent->rh_prefix > IPV6_ABITS)
+ return (EINVAL);
+ if (tnrhc_table_v6[rhent->rh_prefix] == NULL)
+ return (ENOENT);
+ tsol_plen_to_mask_v6(rhent->rh_prefix, &tmpmask_v6);
+ tnrhc_hash = &tnrhc_table_v6[rhent->rh_prefix][
+ TSOL_ADDR_MASK_HASH_V6(rhent->rh_address.ta_addr_v6,
+ tmpmask_v6, TNRHC_SIZE)];
+ } else {
+ return (EAFNOSUPPORT);
+ }
+
+ /* search for existing entry */
+ mutex_enter(&tnrhc_hash->tnrh_lock);
+ prevp = &tnrhc_hash->tnrh_list;
+ while ((current = *prevp) != NULL) {
+ if (TNADDR_EQ(&rhent->rh_address, ¤t->rhc_host))
+ break;
+ prevp = ¤t->rhc_next;
+ }
+
+ if (current != NULL) {
+ DTRACE_PROBE(tx__tndb__l2__tnrhdelete_existingrhentry);
+ *prevp = current->rhc_next;
+ mutex_enter(¤t->rhc_lock);
+ current->rhc_next = NULL;
+ current->rhc_invalid = 1;
+ mutex_exit(¤t->rhc_lock);
+ TNRHC_RELE(current);
+ }
+ mutex_exit(&tnrhc_hash->tnrh_lock);
+ return (current == NULL ? ENOENT : 0);
+}
+
+/*
+ * Flush all remote host entries from the database.
+ *
+ * Note that the htable arrays themselves do not have reference counters, so,
+ * unlike the remote host entries, they cannot be freed.
+ */
+static void
+flush_rh_table(tnrhc_hash_t **htable, int nbits)
+{
+ tnrhc_hash_t *hent, *hend;
+ tsol_tnrhc_t *rhc, *rhnext;
+
+ while (--nbits >= 0) {
+ if ((hent = htable[nbits]) == NULL)
+ continue;
+ hend = hent + TNRHC_SIZE;
+ while (hent < hend) {
+ /*
+ * List walkers hold this lock during the walk. It
+ * protects tnrh_list and rhc_next.
+ */
+ mutex_enter(&hent->tnrh_lock);
+ rhnext = hent->tnrh_list;
+ hent->tnrh_list = NULL;
+ mutex_exit(&hent->tnrh_lock);
+ /*
+ * There may still be users of the rhcs at this point,
+ * but not of the list or its next pointer. Thus, the
+ * only thing that would need to be done under a lock
+ * is setting the invalid bit, but that's atomic
+ * anyway, so no locks needed here.
+ */
+ while ((rhc = rhnext) != NULL) {
+ rhnext = rhc->rhc_next;
+ rhc->rhc_next = NULL;
+ rhc->rhc_invalid = 1;
+ TNRHC_RELE(rhc);
+ }
+ hent++;
+ }
+ }
+}
+
+/*
+ * Load a remote host entry into kernel cache. Create a new one if a matching
+ * entry isn't found, otherwise replace the contents of the previous one by
+ * deleting it and recreating it. (Delete and recreate is used to avoid
+ * allowing other threads to see an unstable data structure.)
+ *
+ * A "matching" entry is the one whose address matches that of the one
+ * being loaded.
+ *
+ * Return 0 for success, error code for failure.
+ */
+int
+tnrh_load(const tsol_rhent_t *rhent)
+{
+ tsol_tnrhc_t **rhp;
+ tsol_tnrhc_t *rh, *new;
+ tsol_tpc_t *tpc;
+ ipaddr_t tmpmask;
+ in6_addr_t tmpmask_v6;
+ tnrhc_hash_t *tnrhc_hash;
+
+ /* Find the existing entry, if any, leaving the hash locked */
+ if (rhent->rh_address.ta_family == AF_INET) {
+ if (rhent->rh_prefix < 0 || rhent->rh_prefix > IP_ABITS)
+ return (EINVAL);
+ if (tnrhc_table[rhent->rh_prefix] == NULL &&
+ !tnrhc_init_table(tnrhc_table, rhent->rh_prefix,
+ KM_NOSLEEP))
+ return (ENOMEM);
+ tmpmask = tsol_plen_to_mask(rhent->rh_prefix);
+ tnrhc_hash = &tnrhc_table[rhent->rh_prefix][
+ TSOL_ADDR_HASH(rhent->rh_address.ta_addr_v4.s_addr &
+ tmpmask, TNRHC_SIZE)];
+ mutex_enter(&tnrhc_hash->tnrh_lock);
+ for (rhp = &tnrhc_hash->tnrh_list; (rh = *rhp) != NULL;
+ rhp = &rh->rhc_next) {
+ ASSERT(rh->rhc_host.ta_family == AF_INET);
+ if (((rh->rhc_host.ta_addr_v4.s_addr ^
+ rhent->rh_address.ta_addr_v4.s_addr) & tmpmask) ==
+ 0)
+ break;
+ }
+ } else if (rhent->rh_address.ta_family == AF_INET6) {
+ if (rhent->rh_prefix < 0 || rhent->rh_prefix > IPV6_ABITS)
+ return (EINVAL);
+ if (tnrhc_table_v6[rhent->rh_prefix] == NULL &&
+ !tnrhc_init_table(tnrhc_table_v6, rhent->rh_prefix,
+ KM_NOSLEEP))
+ return (ENOMEM);
+ tsol_plen_to_mask_v6(rhent->rh_prefix, &tmpmask_v6);
+ tnrhc_hash = &tnrhc_table_v6[rhent->rh_prefix][
+ TSOL_ADDR_MASK_HASH_V6(rhent->rh_address.ta_addr_v6,
+ tmpmask_v6, TNRHC_SIZE)];
+ mutex_enter(&tnrhc_hash->tnrh_lock);
+ for (rhp = &tnrhc_hash->tnrh_list; (rh = *rhp) != NULL;
+ rhp = &rh->rhc_next) {
+ ASSERT(rh->rhc_host.ta_family == AF_INET6);
+ if (V6_MASK_EQ_2(rh->rhc_host.ta_addr_v6, tmpmask_v6,
+ rhent->rh_address.ta_addr_v6))
+ break;
+ }
+ } else {
+ return (EAFNOSUPPORT);
+ }
+
+ if ((new = kmem_zalloc(sizeof (*new), KM_NOSLEEP)) == NULL) {
+ mutex_exit(&tnrhc_hash->tnrh_lock);
+ return (ENOMEM);
+ }
+
+ /* Find and bump the reference count on the named template */
+ if ((tpc = tnrhtp_find(rhent->rh_template, tpc_name_hash)) == NULL) {
+ mutex_exit(&tnrhc_hash->tnrh_lock);
+ kmem_free(new, sizeof (*new));
+ return (EINVAL);
+ }
+
+ /* Clobber the old remote host entry. */
+ if (rh != NULL) {
+ ASSERT(!rh->rhc_invalid);
+ rh->rhc_invalid = 1;
+ *rhp = rh->rhc_next;
+ rh->rhc_next = NULL;
+ TNRHC_RELE(rh);
+ }
+
+ /* Initialize the new entry. */
+ mutex_init(&new->rhc_lock, NULL, MUTEX_DEFAULT, NULL);
+ new->rhc_host = rhent->rh_address;
+
+ /* The rhc now owns this tpc reference, so no TPC_RELE past here */
+ new->rhc_tpc = tpc;
+
+ ASSERT(tpc->tpc_tp.host_type == UNLABELED ||
+ tpc->tpc_tp.host_type == SUN_CIPSO);
+
+ TNRHC_HOLD(new);
+ new->rhc_next = tnrhc_hash->tnrh_list;
+ tnrhc_hash->tnrh_list = new;
+ DTRACE_PROBE(tx__tndb__l2__tnrhload__addedrh);
+ mutex_exit(&tnrhc_hash->tnrh_lock);
+
+ return (0);
+}
+
+static int
+tnrh_get(tsol_rhent_t *rhent)
+{
+ tsol_tpc_t *tpc;
+
+ switch (rhent->rh_address.ta_family) {
+ case AF_INET:
+ tpc = find_tpc(&rhent->rh_address.ta_addr_v4, IPV4_VERSION,
+ B_TRUE);
+ break;
+
+ case AF_INET6:
+ tpc = find_tpc(&rhent->rh_address.ta_addr_v6, IPV6_VERSION,
+ B_TRUE);
+ break;
+
+ default:
+ return (EINVAL);
+ }
+ if (tpc == NULL)
+ return (ENOENT);
+
+ DTRACE_PROBE2(tx__tndb__l4__tnrhget__foundtpc, tsol_rhent_t *,
+ rhent, tsol_tpc_t *, tpc);
+ bcopy(tpc->tpc_tp.name, rhent->rh_template,
+ sizeof (rhent->rh_template));
+ TPC_RELE(tpc);
+ return (0);
+}
+
+static boolean_t
+template_name_ok(const char *name)
+{
+ const char *name_end = name + TNTNAMSIZ;
+
+ while (name < name_end) {
+ if (*name == '\0')
+ break;
+ name++;
+ }
+ return (name < name_end);
+}
+
+static int
+tnrh(int cmd, void *buf)
+{
+ int retv;
+ tsol_rhent_t rhent;
+
+ /* Make sure user has sufficient privilege */
+ if (cmd != TNDB_GET &&
+ (retv = secpolicy_net_config(CRED(), B_FALSE)) != 0)
+ return (set_errno(retv));
+
+ /*
+ * Get arguments
+ */
+ if (cmd != TNDB_FLUSH &&
+ copyin(buf, &rhent, sizeof (rhent)) != 0) {
+ DTRACE_PROBE(tx__tndb__l0__tnrhdelete__copyin);
+ return (set_errno(EFAULT));
+ }
+
+ switch (cmd) {
+ case TNDB_LOAD:
+ DTRACE_PROBE(tx__tndb__l2__tnrhdelete__tndbload);
+ if (!template_name_ok(rhent.rh_template)) {
+ retv = EINVAL;
+ } else {
+ retv = tnrh_load(&rhent);
+ }
+ break;
+
+ case TNDB_DELETE:
+ DTRACE_PROBE(tx__tndb__l2__tnrhdelete__tndbdelete);
+ retv = tnrh_delete(&rhent);
+ break;
+
+ case TNDB_GET:
+ DTRACE_PROBE(tx__tndb__l4__tnrhdelete__tndbget);
+ if (!template_name_ok(rhent.rh_template)) {
+ retv = EINVAL;
+ break;
+ }
+
+ retv = tnrh_get(&rhent);
+ if (retv != 0)
+ break;
+
+ /*
+ * Copy out result
+ */
+ if (copyout(&rhent, buf, sizeof (rhent)) != 0) {
+ DTRACE_PROBE(tx__tndb__l0__tnrhdelete__copyout);
+ retv = EFAULT;
+ }
+ break;
+
+ case TNDB_FLUSH:
+ DTRACE_PROBE(tx__tndb__l2__tnrhdelete__flush);
+ flush_rh_table(tnrhc_table, TSOL_MASK_TABLE_SIZE);
+ flush_rh_table(tnrhc_table_v6, TSOL_MASK_TABLE_SIZE_V6);
+ break;
+
+ default:
+ DTRACE_PROBE1(tx__tndb__l0__tnrhdelete__unknowncmd,
+ int, cmd);
+ retv = EOPNOTSUPP;
+ break;
+ }
+
+ if (retv != 0)
+ return (set_errno(retv));
+ else
+ return (retv);
+}
+
+static tsol_tpc_t *
+tnrhtp_create(const tsol_tpent_t *tpent, int kmflags)
+{
+ tsol_tpc_t *tpc;
+ mod_hash_val_t hv;
+
+ /*
+ * We intentionally allocate a new entry before taking the lock on the
+ * entire database.
+ */
+ if ((tpc = kmem_zalloc(sizeof (*tpc), kmflags)) == NULL)
+ return (NULL);
+
+ mutex_enter(&tpc_lock);
+ if (mod_hash_find(tpc_name_hash, (mod_hash_key_t)tpent->name,
+ &hv) == 0) {
+ tsol_tpc_t *found_tpc = (tsol_tpc_t *)hv;
+
+ found_tpc->tpc_invalid = 1;
+ (void) mod_hash_destroy(tpc_name_hash,
+ (mod_hash_key_t)tpent->name);
+ TPC_RELE(found_tpc);
+ }
+
+ mutex_init(&tpc->tpc_lock, NULL, MUTEX_DEFAULT, NULL);
+ /* tsol_tpent_t is the same on LP64 and ILP32 */
+ bcopy(tpent, &tpc->tpc_tp, sizeof (tpc->tpc_tp));
+ (void) mod_hash_insert(tpc_name_hash, (mod_hash_key_t)tpc->tpc_tp.name,
+ (mod_hash_val_t)tpc);
+ TPC_HOLD(tpc);
+ mutex_exit(&tpc_lock);
+
+ return (tpc);
+}
+
+static int
+tnrhtp_delete(const char *tname)
+{
+ tsol_tpc_t *tpc;
+ mod_hash_val_t hv;
+ int retv = ENOENT;
+
+ mutex_enter(&tpc_lock);
+ if (mod_hash_find(tpc_name_hash, (mod_hash_key_t)tname, &hv) == 0) {
+ tpc = (tsol_tpc_t *)hv;
+ ASSERT(!tpc->tpc_invalid);
+ tpc->tpc_invalid = 1;
+ (void) mod_hash_destroy(tpc_name_hash,
+ (mod_hash_key_t)tpc->tpc_tp.name);
+ TPC_RELE(tpc);
+ retv = 0;
+ }
+ mutex_exit(&tpc_lock);
+ return (retv);
+}
+
+/* ARGSUSED */
+static uint_t
+tpc_delete(mod_hash_key_t key, mod_hash_val_t *val, void *arg)
+{
+ tsol_tpc_t *tpc = (tsol_tpc_t *)val;
+
+ ASSERT(!tpc->tpc_invalid);
+ tpc->tpc_invalid = 1;
+ TPC_RELE(tpc);
+ return (MH_WALK_CONTINUE);
+}
+
+static void
+tnrhtp_flush(void)
+{
+ mutex_enter(&tpc_lock);
+ mod_hash_walk(tpc_name_hash, tpc_delete, NULL);
+ mod_hash_clear(tpc_name_hash);
+ mutex_exit(&tpc_lock);
+}
+
+static int
+tnrhtp(int cmd, void *buf)
+{
+ int retv;
+ int type;
+ tsol_tpent_t rhtpent;
+ tsol_tpc_t *tpc;
+
+ /* Make sure user has sufficient privilege */
+ if (cmd != TNDB_GET &&
+ (retv = secpolicy_net_config(CRED(), B_FALSE)) != 0)
+ return (set_errno(retv));
+
+ /*
+ * Get argument. Note that tsol_tpent_t is the same on LP64 and ILP32,
+ * so no special handling is required.
+ */
+ if (cmd != TNDB_FLUSH) {
+ if (copyin(buf, &rhtpent, sizeof (rhtpent)) != 0) {
+ DTRACE_PROBE(tx__tndb__l0__tnrhtp__copyin);
+ return (set_errno(EFAULT));
+ }
+
+ /*
+ * Don't let the user give us a bogus (unterminated) template
+ * name.
+ */
+ if (!template_name_ok(rhtpent.name))
+ return (set_errno(EINVAL));
+ }
+
+ switch (cmd) {
+ case TNDB_LOAD:
+ DTRACE_PROBE1(tx__tndb__l2__tnrhtp__tndbload, char *,
+ rhtpent.name);
+ type = rhtpent.host_type;
+ if (type != UNLABELED && type != SUN_CIPSO) {
+ retv = EINVAL;
+ break;
+ }
+
+ if (tnrhtp_create(&rhtpent, KM_NOSLEEP) == NULL)
+ retv = ENOMEM;
+ else
+ retv = 0;
+ break;
+
+ case TNDB_GET:
+ DTRACE_PROBE1(tx__tndb__l4__tnrhtp__tndbget, char *,
+ rhtpent.name);
+ tpc = tnrhtp_find(rhtpent.name, tpc_name_hash);
+ if (tpc == NULL) {
+ retv = ENOENT;
+ break;
+ }
+
+ /* Copy out result */
+ if (copyout(&tpc->tpc_tp, buf, sizeof (tpc->tpc_tp)) != 0) {
+ DTRACE_PROBE(tx__tndb__l0__tnrhtp__copyout);
+ retv = EFAULT;
+ } else {
+ retv = 0;
+ }
+ TPC_RELE(tpc);
+ break;
+
+ case TNDB_DELETE:
+ DTRACE_PROBE1(tx__tndb__l4__tnrhtp__tndbdelete, char *,
+ rhtpent.name);
+ retv = tnrhtp_delete(rhtpent.name);
+ break;
+
+ case TNDB_FLUSH:
+ DTRACE_PROBE(tx__tndb__l4__tnrhtp__flush);
+ tnrhtp_flush();
+ retv = 0;
+ break;
+
+ default:
+ DTRACE_PROBE1(tx__tndb__l0__tnrhtp__unknowncmd, int,
+ cmd);
+ retv = EOPNOTSUPP;
+ break;
+ }
+
+ if (retv != 0)
+ return (set_errno(retv));
+ else
+ return (retv);
+}
+
+/*
+ * MLP entry ordering logic
+ *
+ * There are two loops in this routine. The first loop finds the entry that
+ * either logically follows the new entry to be inserted, or is the entry that
+ * precedes and overlaps the new entry, or is NULL to mean end-of-list. This
+ * is 'tme.' The second loop scans ahead from that point to find any overlap
+ * on the front or back of this new entry.
+ *
+ * For the first loop, we can have the following cases in the list (note that
+ * the port-portmax range is inclusive):
+ *
+ * port portmax
+ * +--------+
+ * 1: +------+ ................... precedes; skip to next
+ * 2: +------+ ............. overlaps; stop here if same protocol
+ * 3: +------+ ......... overlaps; stop if same or higher protocol
+ * 4: +-------+ .... overlaps or succeeds; stop here
+ *
+ * For the second loop, we can have the following cases (note that we need not
+ * care about other protocol entries at this point, because we're only looking
+ * for overlap, not an insertion point):
+ *
+ * port portmax
+ * +--------+
+ * 5: +------+ ............. overlaps; stop if same protocol
+ * 6: +------+ ......... overlaps; stop if same protocol
+ * 7: +-------+ .... overlaps; stop if same protocol
+ * 8: +---+ . follows; search is done
+ *
+ * In other words, this second search needs to consider only whether the entry
+ * has a starting port number that's greater than the end point of the new
+ * entry. All others are overlaps.
+ */
+static int
+mlp_add_del(tsol_mlp_list_t *mlpl, zoneid_t zoneid, uint8_t proto,
+ uint16_t port, uint16_t portmax, boolean_t addflag)
+{
+ int retv;
+ tsol_mlp_entry_t *tme, *tme2, *newent;
+
+ if (addflag) {
+ if ((newent = kmem_zalloc(sizeof (*newent), KM_NOSLEEP)) ==
+ NULL)
+ return (ENOMEM);
+ } else {
+ newent = NULL;
+ }
+ rw_enter(&mlpl->mlpl_rwlock, RW_WRITER);
+
+ /*
+ * First loop: find logical insertion point or overlap. Table is kept
+ * in order of port number first, and then, within that, by protocol
+ * number.
+ */
+ for (tme = mlpl->mlpl_first; tme != NULL; tme = tme->mlpe_next) {
+ /* logically next (case 4) */
+ if (tme->mlpe_mlp.mlp_port > port)
+ break;
+ /* if this is logically next or overlap, then stop (case 3) */
+ if (tme->mlpe_mlp.mlp_port == port &&
+ tme->mlpe_mlp.mlp_ipp >= proto)
+ break;
+ /* earlier or same port sequence; check for overlap (case 2) */
+ if (tme->mlpe_mlp.mlp_ipp == proto &&
+ tme->mlpe_mlp.mlp_port_upper >= port)
+ break;
+ /* otherwise, loop again (case 1) */
+ }
+
+ /* Second loop: scan ahead for overlap */
+ for (tme2 = tme; tme2 != NULL; tme2 = tme2->mlpe_next) {
+ /* check if entry follows; no overlap (case 8) */
+ if (tme2->mlpe_mlp.mlp_port > portmax) {
+ tme2 = NULL;
+ break;
+ }
+ /* only exact protocol matches at this point (cases 5-7) */
+ if (tme2->mlpe_mlp.mlp_ipp == proto)
+ break;
+ }
+
+ retv = 0;
+ if (addflag) {
+ if (tme2 != NULL) {
+ retv = EEXIST;
+ } else {
+ newent->mlpe_zoneid = zoneid;
+ newent->mlpe_mlp.mlp_ipp = proto;
+ newent->mlpe_mlp.mlp_port = port;
+ newent->mlpe_mlp.mlp_port_upper = portmax;
+ newent->mlpe_next = tme;
+ if (tme == NULL) {
+ tme2 = mlpl->mlpl_last;
+ mlpl->mlpl_last = newent;
+ } else {
+ tme2 = tme->mlpe_prev;
+ tme->mlpe_prev = newent;
+ }
+ newent->mlpe_prev = tme2;
+ if (tme2 == NULL)
+ mlpl->mlpl_first = newent;
+ else
+ tme2->mlpe_next = newent;
+ newent = NULL;
+ }
+ } else {
+ if (tme2 == NULL || tme2->mlpe_mlp.mlp_port != port ||
+ tme2->mlpe_mlp.mlp_port_upper != portmax) {
+ retv = ENOENT;
+ } else {
+ if ((tme2 = tme->mlpe_prev) == NULL)
+ mlpl->mlpl_first = tme->mlpe_next;
+ else
+ tme2->mlpe_next = tme->mlpe_next;
+ if ((tme2 = tme->mlpe_next) == NULL)
+ mlpl->mlpl_last = tme->mlpe_prev;
+ else
+ tme2->mlpe_prev = tme->mlpe_prev;
+ newent = tme;
+ }
+ }
+ rw_exit(&mlpl->mlpl_rwlock);
+
+ if (newent != NULL)
+ kmem_free(newent, sizeof (*newent));
+
+ return (retv);
+}
+
+/*
+ * Add or remove an MLP entry from the database so that the classifier can find
+ * it.
+ *
+ * Note: port number is in host byte order.
+ */
+int
+tsol_mlp_anon(zone_t *zone, mlp_type_t mlptype, uchar_t proto, uint16_t port,
+ boolean_t addflag)
+{
+ int retv = 0;
+
+ if (mlptype == mlptBoth || mlptype == mlptPrivate)
+ retv = mlp_add_del(&zone->zone_mlps, zone->zone_id, proto,
+ port, port, addflag);
+ if ((retv == 0 || !addflag) &&
+ (mlptype == mlptBoth || mlptype == mlptShared)) {
+ retv = mlp_add_del(&shared_mlps, zone->zone_id, proto, port,
+ port, addflag);
+ if (retv != 0 && addflag)
+ (void) mlp_add_del(&zone->zone_mlps, zone->zone_id,
+ proto, port, port, B_FALSE);
+ }
+ return (retv);
+}
+
+static void
+mlp_flush(tsol_mlp_list_t *mlpl, zoneid_t zoneid)
+{
+ tsol_mlp_entry_t *tme, *tme2, *tmnext;
+
+ rw_enter(&mlpl->mlpl_rwlock, RW_WRITER);
+ for (tme = mlpl->mlpl_first; tme != NULL; tme = tmnext) {
+ tmnext = tme->mlpe_next;
+ if (zoneid == ALL_ZONES || tme->mlpe_zoneid == zoneid) {
+ if ((tme2 = tme->mlpe_prev) == NULL)
+ mlpl->mlpl_first = tmnext;
+ else
+ tme2->mlpe_next = tmnext;
+ if (tmnext == NULL)
+ mlpl->mlpl_last = tme2;
+ else
+ tmnext->mlpe_prev = tme2;
+ kmem_free(tme, sizeof (*tme));
+ }
+ }
+ rw_exit(&mlpl->mlpl_rwlock);
+}
+
+/*
+ * Note: user supplies port numbers in host byte order.
+ */
+static int
+tnmlp(int cmd, void *buf)
+{
+ int retv;
+ tsol_mlpent_t tsme;
+ zone_t *zone;
+ tsol_mlp_list_t *mlpl;
+ tsol_mlp_entry_t *tme;
+
+ /* Make sure user has sufficient privilege */
+ if (cmd != TNDB_GET &&
+ (retv = secpolicy_net_config(CRED(), B_FALSE)) != 0)
+ return (set_errno(retv));
+
+ /*
+ * Get argument. Note that tsol_mlpent_t is the same on LP64 and
+ * ILP32, so no special handling is required.
+ */
+ if (copyin(buf, &tsme, sizeof (tsme)) != 0) {
+ DTRACE_PROBE(tx__tndb__l0__tnmlp__copyin);
+ return (set_errno(EFAULT));
+ }
+
+ /* MLPs on shared IP addresses */
+ if (tsme.tsme_flags & TSOL_MEF_SHARED) {
+ zone = NULL;
+ mlpl = &shared_mlps;
+ } else {
+ zone = zone_find_by_id(tsme.tsme_zoneid);
+ if (zone == NULL)
+ return (set_errno(EINVAL));
+ mlpl = &zone->zone_mlps;
+ }
+ if (tsme.tsme_mlp.mlp_port_upper == 0)
+ tsme.tsme_mlp.mlp_port_upper = tsme.tsme_mlp.mlp_port;
+
+ switch (cmd) {
+ case TNDB_LOAD:
+ DTRACE_PROBE1(tx__tndb__l2__tnmlp__tndbload,
+ tsol_mlpent_t *, &tsme);
+ if (tsme.tsme_mlp.mlp_ipp == 0 || tsme.tsme_mlp.mlp_port == 0 ||
+ tsme.tsme_mlp.mlp_port > tsme.tsme_mlp.mlp_port_upper) {
+ retv = EINVAL;
+ break;
+ }
+ retv = mlp_add_del(mlpl, tsme.tsme_zoneid,
+ tsme.tsme_mlp.mlp_ipp, tsme.tsme_mlp.mlp_port,
+ tsme.tsme_mlp.mlp_port_upper, B_TRUE);
+ break;
+
+ case TNDB_GET:
+ DTRACE_PROBE1(tx__tndb__l2__tnmlp__tndbget,
+ tsol_mlpent_t *, &tsme);
+
+ /*
+ * Search for the requested element or, failing that, the one
+ * that's logically next in the sequence.
+ */
+ rw_enter(&mlpl->mlpl_rwlock, RW_READER);
+ for (tme = mlpl->mlpl_first; tme != NULL;
+ tme = tme->mlpe_next) {
+ if (tsme.tsme_zoneid != ALL_ZONES &&
+ tme->mlpe_zoneid != tsme.tsme_zoneid)
+ continue;
+ if (tme->mlpe_mlp.mlp_ipp >= tsme.tsme_mlp.mlp_ipp &&
+ tme->mlpe_mlp.mlp_port == tsme.tsme_mlp.mlp_port)
+ break;
+ if (tme->mlpe_mlp.mlp_port > tsme.tsme_mlp.mlp_port)
+ break;
+ }
+ if (tme == NULL) {
+ retv = ENOENT;
+ } else {
+ tsme.tsme_zoneid = tme->mlpe_zoneid;
+ tsme.tsme_mlp = tme->mlpe_mlp;
+ retv = 0;
+ }
+ rw_exit(&mlpl->mlpl_rwlock);
+ break;
+
+ case TNDB_DELETE:
+ DTRACE_PROBE1(tx__tndb__l4__tnmlp__tndbdelete,
+ tsol_mlpent_t *, &tsme);
+ retv = mlp_add_del(mlpl, tsme.tsme_zoneid,
+ tsme.tsme_mlp.mlp_ipp, tsme.tsme_mlp.mlp_port,
+ tsme.tsme_mlp.mlp_port_upper, B_FALSE);
+ break;
+
+ case TNDB_FLUSH:
+ DTRACE_PROBE1(tx__tndb__l4__tnmlp__tndbflush,
+ tsol_mlpent_t *, &tsme);
+ mlp_flush(mlpl, ALL_ZONES);
+ mlp_flush(&shared_mlps, tsme.tsme_zoneid);
+ retv = 0;
+ break;
+
+ default:
+ DTRACE_PROBE1(tx__tndb__l0__tnmlp__unknowncmd, int,
+ cmd);
+ retv = EOPNOTSUPP;
+ break;
+ }
+
+ if (zone != NULL)
+ zone_rele(zone);
+
+ if (cmd == TNDB_GET && retv == 0) {
+ /* Copy out result */
+ if (copyout(&tsme, buf, sizeof (tsme)) != 0) {
+ DTRACE_PROBE(tx__tndb__l0__tnmlp__copyout);
+ retv = EFAULT;
+ }
+ }
+
+ if (retv != 0)
+ return (set_errno(retv));
+ else
+ return (retv);
+}
+
+/*
+ * Returns a tnrhc matching the addr address.
+ * The returned rhc's refcnt is incremented.
+ */
+tsol_tnrhc_t *
+find_rhc_v4(const in_addr_t *in4)
+{
+ tsol_tnrhc_t *rh = NULL;
+ tnrhc_hash_t *tnrhc_hash;
+ ipaddr_t tmpmask;
+ int i;
+
+ for (i = (TSOL_MASK_TABLE_SIZE - 1); i >= 0; i--) {
+
+ if ((tnrhc_table[i]) == NULL)
+ continue;
+
+ tmpmask = tsol_plen_to_mask(i);
+ tnrhc_hash = &tnrhc_table[i][
+ TSOL_ADDR_HASH(*in4 & tmpmask, TNRHC_SIZE)];
+
+ mutex_enter(&tnrhc_hash->tnrh_lock);
+ for (rh = tnrhc_hash->tnrh_list; rh != NULL;
+ rh = rh->rhc_next) {
+ if ((rh->rhc_host.ta_family == AF_INET) &&
+ ((rh->rhc_host.ta_addr_v4.s_addr & tmpmask) ==
+ (*in4 & tmpmask))) {
+ TNRHC_HOLD(rh);
+ mutex_exit(&tnrhc_hash->tnrh_lock);
+ return (rh);
+ }
+ }
+ mutex_exit(&tnrhc_hash->tnrh_lock);
+ }
+
+ return (NULL);
+}
+
+/*
+ * Returns a tnrhc matching the addr address.
+ * The returned rhc's refcnt is incremented.
+ */
+tsol_tnrhc_t *
+find_rhc_v6(const in6_addr_t *in6)
+{
+ tsol_tnrhc_t *rh = NULL;
+ tnrhc_hash_t *tnrhc_hash;
+ in6_addr_t tmpmask;
+ int i;
+
+ if (IN6_IS_ADDR_V4MAPPED(in6)) {
+ in_addr_t in4;
+
+ IN6_V4MAPPED_TO_IPADDR(in6, in4);
+ return (find_rhc_v4(&in4));
+ }
+
+ for (i = (TSOL_MASK_TABLE_SIZE_V6 - 1); i >= 0; i--) {
+ if ((tnrhc_table_v6[i]) == NULL)
+ continue;
+
+ tsol_plen_to_mask_v6(i, &tmpmask);
+ tnrhc_hash = &tnrhc_table_v6[i][
+ TSOL_ADDR_MASK_HASH_V6(*in6, tmpmask, TNRHC_SIZE)];
+
+ mutex_enter(&tnrhc_hash->tnrh_lock);
+ for (rh = tnrhc_hash->tnrh_list; rh != NULL;
+ rh = rh->rhc_next) {
+ if ((rh->rhc_host.ta_family == AF_INET6) &&
+ V6_MASK_EQ_2(rh->rhc_host.ta_addr_v6, tmpmask,
+ *in6)) {
+ TNRHC_HOLD(rh);
+ mutex_exit(&tnrhc_hash->tnrh_lock);
+ return (rh);
+ }
+ }
+ mutex_exit(&tnrhc_hash->tnrh_lock);
+ }
+
+ return (NULL);
+}
+
+tsol_tpc_t *
+find_tpc(const void *addr, uchar_t version, boolean_t staleok)
+{
+ tsol_tpc_t *tpc;
+ tsol_tnrhc_t *rhc;
+
+ if (version == IPV4_VERSION)
+ rhc = find_rhc_v4(addr);
+ else
+ rhc = find_rhc_v6(addr);
+
+ if (rhc != NULL) {
+ tpc = rhc->rhc_tpc;
+ if (!staleok && tpc->tpc_invalid) {
+ /*
+ * This should not happen unless the user deletes
+ * templates without recreating them. Try to find the
+ * new version of template. If there is none, then
+ * just give up.
+ */
+ tpc = tnrhtp_find(tpc->tpc_tp.name, tpc_name_hash);
+ if (tpc != NULL) {
+ TPC_RELE(rhc->rhc_tpc);
+ rhc->rhc_tpc = tpc;
+ }
+ }
+ if (tpc != NULL)
+ TPC_HOLD(tpc);
+ TNRHC_RELE(rhc);
+ return (tpc);
+ }
+ DTRACE_PROBE(tx__tndb__l1__findtpc__notemplate);
+ return (NULL);
+}
+
+/*
+ * create an internal template called "_unlab":
+ *
+ * _unlab;\
+ * host_type = unlabeled;\
+ * def_label = ADMIN_LOW[ADMIN_LOW];\
+ * min_sl = ADMIN_LOW;\
+ * max_sl = ADMIN_HIGH;
+ */
+static void
+tsol_create_i_tmpls(void)
+{
+ tsol_tpent_t rhtpent;
+
+ bzero(&rhtpent, sizeof (rhtpent));
+
+ /* create _unlab */
+ (void) strcpy(rhtpent.name, "_unlab");
+
+ rhtpent.host_type = UNLABELED;
+ rhtpent.tp_mask_unl = TSOL_MSK_DEF_LABEL | TSOL_MSK_DEF_CL |
+ TSOL_MSK_SL_RANGE_TSOL;
+
+ rhtpent.tp_gw_sl_range.lower_bound = *label2bslabel(l_admin_low);
+ rhtpent.tp_def_label = rhtpent.tp_gw_sl_range.lower_bound;
+ rhtpent.tp_gw_sl_range.upper_bound = *label2bslabel(l_admin_high);
+ rhtpent.tp_cipso_doi_unl = default_doi;
+ tpc_unlab = tnrhtp_create(&rhtpent, KM_SLEEP);
+}
+
+/*
+ * set up internal host template, called from kernel only.
+ */
+static void
+tsol_create_i_tnrh(const tnaddr_t *sa)
+{
+ tsol_tnrhc_t *rh, *new;
+ tnrhc_hash_t *tnrhc_hash;
+
+ /* Allocate a new entry before taking the lock */
+ new = kmem_zalloc(sizeof (*new), KM_SLEEP);
+
+ tnrhc_hash = (sa->ta_family == AF_INET) ? &tnrhc_table[0][0] :
+ &tnrhc_table_v6[0][0];
+
+ mutex_enter(&tnrhc_hash->tnrh_lock);
+ rh = tnrhc_hash->tnrh_list;
+
+ if (rh == NULL) {
+ /* We're keeping the new entry. */
+ rh = new;
+ new = NULL;
+ rh->rhc_host = *sa;
+ mutex_init(&rh->rhc_lock, NULL, MUTEX_DEFAULT, NULL);
+ TNRHC_HOLD(rh);
+ tnrhc_hash->tnrh_list = rh;
+ }
+
+ /*
+ * Link the entry to internal_unlab
+ */
+ if (rh->rhc_tpc != tpc_unlab) {
+ if (rh->rhc_tpc != NULL)
+ TPC_RELE(rh->rhc_tpc);
+ rh->rhc_tpc = tpc_unlab;
+ TPC_HOLD(tpc_unlab);
+ }
+ mutex_exit(&tnrhc_hash->tnrh_lock);
+ if (new != NULL)
+ kmem_free(new, sizeof (*new));
+}
+
+/*
+ * Returns 0 if the port is known to be SLP. Returns next possible port number
+ * (wrapping through 1) if port is MLP on shared or global. Administrator
+ * should not make all ports MLP. If that's done, then we'll just pretend
+ * everything is SLP to avoid looping forever.
+ *
+ * Note: port is in host byte order.
+ */
+in_port_t
+tsol_next_port(zone_t *zone, in_port_t port, int proto, boolean_t upward)
+{
+ boolean_t loop;
+ tsol_mlp_entry_t *tme;
+ int newport = port;
+
+ loop = B_FALSE;
+ for (;;) {
+ if (zone != NULL && zone->zone_mlps.mlpl_first != NULL) {
+ rw_enter(&zone->zone_mlps.mlpl_rwlock, RW_READER);
+ for (tme = zone->zone_mlps.mlpl_first; tme != NULL;
+ tme = tme->mlpe_next) {
+ if (proto == tme->mlpe_mlp.mlp_ipp &&
+ newport >= tme->mlpe_mlp.mlp_port &&
+ newport <= tme->mlpe_mlp.mlp_port_upper)
+ newport = upward ?
+ tme->mlpe_mlp.mlp_port_upper + 1 :
+ tme->mlpe_mlp.mlp_port - 1;
+ }
+ rw_exit(&zone->zone_mlps.mlpl_rwlock);
+ }
+ if (shared_mlps.mlpl_first != NULL) {
+ rw_enter(&shared_mlps.mlpl_rwlock, RW_READER);
+ for (tme = shared_mlps.mlpl_first; tme != NULL;
+ tme = tme->mlpe_next) {
+ if (proto == tme->mlpe_mlp.mlp_ipp &&
+ newport >= tme->mlpe_mlp.mlp_port &&
+ newport <= tme->mlpe_mlp.mlp_port_upper)
+ newport = upward ?
+ tme->mlpe_mlp.mlp_port_upper + 1 :
+ tme->mlpe_mlp.mlp_port - 1;
+ }
+ rw_exit(&shared_mlps.mlpl_rwlock);
+ }
+ if (newport <= 65535 && newport > 0)
+ break;
+ if (loop)
+ return (0);
+ loop = B_TRUE;
+ newport = upward ? 1 : 65535;
+ }
+ return (newport == port ? 0 : newport);
+}
+
+/*
+ * tsol_mlp_port_type will check if the given (zone, proto, port) is a
+ * multilevel port. If it is, return the type (shared, private, or both), or
+ * indicate that it's single-level.
+ *
+ * Note: port is given in host byte order, not network byte order.
+ */
+mlp_type_t
+tsol_mlp_port_type(zone_t *zone, uchar_t proto, uint16_t port,
+ mlp_type_t mlptype)
+{
+ tsol_mlp_entry_t *tme;
+
+ if (mlptype == mlptBoth || mlptype == mlptPrivate) {
+ tme = NULL;
+ if (zone->zone_mlps.mlpl_first != NULL) {
+ rw_enter(&zone->zone_mlps.mlpl_rwlock, RW_READER);
+ for (tme = zone->zone_mlps.mlpl_first; tme != NULL;
+ tme = tme->mlpe_next) {
+ if (proto == tme->mlpe_mlp.mlp_ipp &&
+ port >= tme->mlpe_mlp.mlp_port &&
+ port <= tme->mlpe_mlp.mlp_port_upper)
+ break;
+ }
+ rw_exit(&zone->zone_mlps.mlpl_rwlock);
+ }
+ if (tme == NULL) {
+ if (mlptype == mlptBoth)
+ mlptype = mlptShared;
+ else if (mlptype == mlptPrivate)
+ mlptype = mlptSingle;
+ }
+ }
+ if (mlptype == mlptBoth || mlptype == mlptShared) {
+ tme = NULL;
+ if (shared_mlps.mlpl_first != NULL) {
+ rw_enter(&shared_mlps.mlpl_rwlock, RW_READER);
+ for (tme = shared_mlps.mlpl_first; tme != NULL;
+ tme = tme->mlpe_next) {
+ if (proto == tme->mlpe_mlp.mlp_ipp &&
+ port >= tme->mlpe_mlp.mlp_port &&
+ port <= tme->mlpe_mlp.mlp_port_upper)
+ break;
+ }
+ rw_exit(&shared_mlps.mlpl_rwlock);
+ }
+ if (tme == NULL) {
+ if (mlptype == mlptBoth)
+ mlptype = mlptPrivate;
+ else if (mlptype == mlptShared)
+ mlptype = mlptSingle;
+ }
+ }
+ return (mlptype);
+}
+
+/*
+ * tsol_mlp_findzone will check if the given (proto, port) is a multilevel port
+ * on a shared address. If it is, return the owning zone.
+ *
+ * Note: lport is in network byte order, unlike the other MLP functions,
+ * because the callers of this function are all dealing with packets off the
+ * wire.
+ */
+zoneid_t
+tsol_mlp_findzone(uchar_t proto, uint16_t lport)
+{
+ tsol_mlp_entry_t *tme;
+ zoneid_t zoneid;
+ uint16_t port;
+
+ if (shared_mlps.mlpl_first == NULL)
+ return (ALL_ZONES);
+ port = ntohs(lport);
+ rw_enter(&shared_mlps.mlpl_rwlock, RW_READER);
+ for (tme = shared_mlps.mlpl_first; tme != NULL; tme = tme->mlpe_next) {
+ if (proto == tme->mlpe_mlp.mlp_ipp &&
+ port >= tme->mlpe_mlp.mlp_port &&
+ port <= tme->mlpe_mlp.mlp_port_upper)
+ break;
+ }
+ zoneid = tme == NULL ? ALL_ZONES : tme->mlpe_zoneid;
+ rw_exit(&shared_mlps.mlpl_rwlock);
+ return (zoneid);
+}
+
+/* Debug routine */
+void
+tsol_print_label(const blevel_t *blev, const char *name)
+{
+ const _blevel_impl_t *bli = (const _blevel_impl_t *)blev;
+
+ /* We really support only sensitivity labels */
+ cmn_err(CE_NOTE, "%s %x:%x:%08x%08x%08x%08x%08x%08x%08x%08x",
+ name, bli->id, LCLASS(bli), ntohl(bli->_comps.c1),
+ ntohl(bli->_comps.c2), ntohl(bli->_comps.c3), ntohl(bli->_comps.c4),
+ ntohl(bli->_comps.c5), ntohl(bli->_comps.c6), ntohl(bli->_comps.c7),
+ ntohl(bli->_comps.c8));
+}
+
+/*
+ * Name: labelsys()
+ *
+ * Normal: Routes TSOL syscalls.
+ *
+ * Output: As defined for each TSOL syscall.
+ * Returns ENOSYS for unrecognized calls.
+ */
+/* ARGSUSED */
+int
+labelsys(int op, void *a1, void *a2, void *a3, void *a4, void *a5)
+{
+ switch (op) {
+ case TSOL_SYSLABELING:
+ return (sys_labeling);
+ case TSOL_TNRH:
+ return (tnrh((int)(uintptr_t)a1, a2));
+ case TSOL_TNRHTP:
+ return (tnrhtp((int)(uintptr_t)a1, a2));
+ case TSOL_TNMLP:
+ return (tnmlp((int)(uintptr_t)a1, a2));
+ case TSOL_GETLABEL:
+ return (getlabel((char *)a1, (bslabel_t *)a2));
+ case TSOL_FGETLABEL:
+ return (fgetlabel((int)(uintptr_t)a1, (bslabel_t *)a2));
+ default:
+ return (set_errno(ENOSYS));
+ }
+ /* NOTREACHED */
+}
--- a/usr/src/uts/common/os/main.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/os/main.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -45,7 +44,6 @@
#include <sys/file.h>
#include <sys/priocntl.h>
#include <sys/procset.h>
-#include <sys/var.h>
#include <sys/disp.h>
#include <sys/callo.h>
#include <sys/callb.h>
--- a/usr/src/uts/common/os/policy.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/os/policy.c Fri Mar 24 12:29:20 2006 -0800
@@ -39,7 +39,6 @@
#include <sys/proc.h>
#include <sys/acct.h>
#include <sys/ipc_impl.h>
-#include <sys/syscall.h>
#include <sys/cmn_err.h>
#include <sys/debug.h>
#include <sys/policy.h>
@@ -51,16 +50,12 @@
#include <sys/modctl.h>
#include <sys/disp.h>
#include <sys/zone.h>
-#include <inet/common.h>
#include <inet/optcom.h>
#include <sys/sdt.h>
-#include <sys/mount.h>
#include <sys/vfs.h>
#include <sys/mntent.h>
#include <sys/contract_impl.h>
-#include <sys/sunddi.h>
-
/*
* There are two possible layers of privilege routines and two possible
* levels of secpolicy. Plus one other we may not be interested in, so
@@ -503,6 +498,27 @@
}
/*
+ * Binding to a multilevel port on a trusted (labeled) system.
+ */
+int
+secpolicy_net_bindmlp(const cred_t *cr)
+{
+ return (PRIV_POLICY(cr, PRIV_NET_BINDMLP, B_FALSE, EACCES,
+ NULL));
+}
+
+/*
+ * Allow a communication between a zone and an unlabeled host when their
+ * labels don't match.
+ */
+int
+secpolicy_net_mac_aware(const cred_t *cr)
+{
+ return (PRIV_POLICY(cr, PRIV_NET_MAC_AWARE, B_FALSE, EACCES,
+ NULL));
+}
+
+/*
* Common routine which determines whether a given credential can
* act on a given mount.
* When called through mount, the parameter needoptcheck is a pointer
@@ -1677,6 +1693,12 @@
return (secpolicy_require_set(cr, PRIV_FULLSET, NULL));
}
+boolean_t
+secpolicy_net_reply_equal(const cred_t *cr)
+{
+ return (PRIV_POLICY(cr, PRIV_SYS_CONFIG, B_FALSE, EPERM, NULL));
+}
+
int
secpolicy_swapctl(const cred_t *cr)
{
--- a/usr/src/uts/common/os/priv_defs Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/os/priv_defs Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*
INSERT COMMENT
@@ -105,6 +104,14 @@
In order to write files owned by uid 0 in the absence of an
effective uid of 0 ALL privileges are required.
+privilege PRIV_FILE_DOWNGRADE_SL
+
+ Allows a process to set the sensitivity label of a file or
+ directory to a sensitivity label that does not dominate the
+ existing sensitivity label.
+ This privilege is interpreted only if the system is configured
+ with Trusted Extensions.
+
basic privilege PRIV_FILE_LINK_ANY
Allows a process to create hardlinks to files owned by a uid
@@ -134,6 +141,14 @@
Additional restrictions apply when creating or modifying a
set-uid 0 file.
+privilege PRIV_FILE_UPGRADE_SL
+
+ Allows a process to set the sensitivity label of a file or
+ directory to a sensitivity label that dominates the existing
+ sensitivity label.
+ This privilege is interpreted only if the system is configured
+ with Trusted Extensions.
+
privilege PRIV_GART_ACCESS
Allows a process to make ioctls to agpgart device except
@@ -175,10 +190,33 @@
Additional restrictions apply if the owner of the object has uid 0
and the effective uid of the current process is not 0.
+privilege PRIV_NET_BINDMLP
+
+ Allow a process to bind to a port that is configured as a
+ multi-level port(MLP) for the process's zone. This privilege
+ applies to both shared address and zone-specific address MLPs.
+ See tnzonecfg(4) from the Trusted Extensions manual pages for
+ information on configuring MLP ports.
+ This privilege is interpreted only if the system is configured
+ with Trusted Extensions.
+
privilege PRIV_NET_ICMPACCESS
Allows a process to send and receive ICMP packets.
+privilege PRIV_NET_MAC_AWARE
+
+ Allows a process to set NET_MAC_AWARE process flag by using
+ setpflags(2). This privilege also allows a process to set
+ SO_MAC_EXEMPT socket option by using setsockopt(3SOCKET).
+ The NET_MAC_AWARE process flag and the SO_MAC_EXEMPT socket
+ option both allow a local process to communicate with an
+ unlabeled peer if the local process' label dominates the
+ peer's default label, or if the local process runs in the
+ global zone.
+ This privilege is interpreted only if the system is configured
+ with Trusted Extensions.
+
privilege PRIV_NET_PRIVADDR
Allows a process to bind to a privileged port
@@ -374,6 +412,117 @@
Allows a process to manipulate system time using any of the
appropriate system calls: stime, adjtime, ntp_adjtime and
the IA specific RTC calls.
+
+privilege PRIV_SYS_TRANS_LABEL
+
+ Allows a process to translate labels that are not dominated
+ by the process' sensitivity label to and from an external
+ string form.
+ This privilege is interpreted only if the system is configured
+ with Trusted Extensions.
+
+privilege PRIV_WIN_COLORMAP
+
+ Allows a process to override colormap restrictions.
+ Allows a process to install or remove colormaps.
+ Allows a process to retrieve colormap cell entries allocated
+ by other processes.
+ This privilege is interpreted only if the system is configured
+ with Trusted Extensions.
+
+privilege PRIV_WIN_CONFIG
+
+ Allows a process to configure or destroy resources that are
+ permanently retained by the X server.
+ Allows a process to use SetScreenSaver to set the screen
+ saver timeout value.
+ Allows a process to use ChangeHosts to modify the display
+ access control list.
+ Allows a process to use GrabServer.
+ Allows a process to use the SetCloseDownMode request which
+ may retain window, pixmap, colormap, property, cursor, font,
+ or graphic context resources.
+ This privilege is interpreted only if the system is configured
+ with Trusted Extensions.
+
+privilege PRIV_WIN_DAC_READ
+
+ Allows a process to read from a window resource that it does
+ not own (has a different user ID).
+ This privilege is interpreted only if the system is configured
+ with Trusted Extensions.
+
+privilege PRIV_WIN_DAC_WRITE
+
+ Allows a process to write to or create a window resource that
+ it does not own (has a different user ID). A newly created
+ window property is created with the window's user ID.
+ This privilege is interpreted only if the system is configured
+ with Trusted Extensions.
+
+privilege PRIV_WIN_DEVICES
+
+ Allows a process to perform operations on window input devices.
+ Allows a process to get and set keyboard and pointer controls.
+ Allows a process to modify pointer button and key mappings.
+ This privilege is interpreted only if the system is configured
+ with Trusted Extensions.
+
+privilege PRIV_WIN_DGA
+
+ Allows a process to use the direct graphics access (DGA) X protocol
+ extensions. Direct process access to the frame buffer is still
+ required. Thus the process must have MAC and DAC privileges that
+ allow access to the frame buffer, or the frame buffer must be
+ allocated to the process.
+ This privilege is interpreted only if the system is configured
+ with Trusted Extensions.
+
+privilege PRIV_WIN_DOWNGRADE_SL
+
+ Allows a process to set the sensitivity label of a window resource
+ to a sensitivity label that does not dominate the existing
+ sensitivity label.
+ This privilege is interpreted only if the system is configured
+ with Trusted Extensions.
+
+privilege PRIV_WIN_FONTPATH
+
+ Allows a process to set a font path.
+ This privilege is interpreted only if the system is configured
+ with Trusted Extensions.
+
+privilege PRIV_WIN_MAC_READ
+
+ Allows a process to read from a window resource whose sensitivity
+ label is not equal to the process sensitivity label.
+ This privilege is interpreted only if the system is configured
+ with Trusted Extensions.
+
+privilege PRIV_WIN_MAC_WRITE
+
+ Allows a process to create a window resource whose sensitivity
+ label is not equal to the process sensitivity label.
+ A newly created window property is created with the window's
+ sensitivity label.
+ This privilege is interpreted only if the system is configured
+ with Trusted Extensions.
+
+privilege PRIV_WIN_SELECTION
+
+ Allows a process to request inter-window data moves without the
+ intervention of the selection confirmer.
+ This privilege is interpreted only if the system is configured
+ with Trusted Extensions.
+
+privilege PRIV_WIN_UPGRADE_SL
+
+ Allows a process to set the sensitivity label of a window
+ resource to a sensitivity label that dominates the existing
+ sensitivity label.
+ This privilege is interpreted only if the system is configured
+ with Trusted Extensions.
+
set PRIV_EFFECTIVE
Set of privileges currently in effect.
--- a/usr/src/uts/common/os/sysent.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/os/sysent.c Fri Mar 24 12:29:20 2006 -0800
@@ -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 @@
*/
/* ONC_PLUS EXTRACT START */
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -83,6 +82,7 @@
int ioctl();
int issetugid();
int kill();
+int labelsys();
int link();
off32_t lseek32();
off_t lseek64();
@@ -664,7 +664,7 @@
/* 181 */ SYSENT_CI("rusagesys", rusagesys, 2),
/* 182 */ SYSENT_LOADABLE(), /* portfs */
/* 183 */ SYSENT_CI("pollsys", pollsys, 4),
- /* 184 */ SYSENT_LOADABLE(), /* tsolsys */
+ /* 184 */ SYSENT_CI("labelsys", labelsys, 5),
/* 185 */ SYSENT_CI("acl", acl, 4),
/* 186 */ SYSENT_AP("auditsys", auditsys, 2),
/* 187 */ SYSENT_CI("processor_bind", processor_bind, 4),
@@ -742,7 +742,7 @@
SYSENT_NOSYS(),
SYSENT_CI("open64", open64, 3)),
/* 226 */ SYSENT_LOADABLE(), /* rpcsys */
- /* 227 */ SYSENT_CL("zone", zone, 6),
+ /* 227 */ SYSENT_CL("zone", zone, 5),
/* 228 */ SYSENT_LOADABLE(), /* autofssys */
/* 229 */ SYSENT_CI("getcwd", getcwd, 2),
/* 230 */ SYSENT_CI("so_socket", so_socket, 5),
@@ -1042,7 +1042,7 @@
/* 181 */ SYSENT_CI("rusagesys", rusagesys, 2),
/* 182 */ SYSENT_LOADABLE32(), /* portfs */
/* 183 */ SYSENT_CI("pollsys", pollsys, 4),
- /* 184 */ SYSENT_LOADABLE32(), /* tsolsys */
+ /* 184 */ SYSENT_CI("labelsys", labelsys, 5),
/* 185 */ SYSENT_CI("acl", acl, 4),
/* 186 */ SYSENT_AP("auditsys", auditsys, 2),
/* 187 */ SYSENT_CI("processor_bind", processor_bind, 4),
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/os/tlabel.c Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,621 @@
+/*
+ * 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/param.h>
+#include <sys/cmn_err.h>
+#include <sys/systm.h>
+#include <sys/cred.h>
+#include <sys/modctl.h>
+#include <sys/vfs.h>
+#include <sys/vnode.h>
+#include <sys/tiuser.h>
+#include <sys/kmem.h>
+#include <sys/pathname.h>
+#include <sys/zone.h>
+#include <sys/tsol/label.h>
+#include <sys/tsol/tnet.h>
+#include <sys/fs/lofs_node.h>
+#include <inet/ip6.h>
+#include <rpc/auth.h>
+#include <rpc/clnt.h>
+#include <nfs/nfs.h>
+#include <nfs/nfs4.h>
+#include <nfs/nfs_clnt.h>
+#include <sys/dnlc.h>
+
+
+int sys_labeling = -1; /* initially unset */
+
+static kmem_cache_t *tslabel_cache;
+ts_label_t *l_admin_low;
+ts_label_t *l_admin_high;
+
+uint32_t default_doi = DEFAULT_DOI;
+
+/*
+ * Initialize labels infrastructure.
+ * This is called during startup() time (before vfs_mntroot) by thread_init().
+ * It has to be called early so that the is_system_labeled() function returns
+ * the right value when called by the networking code on a diskless boot.
+ */
+void
+label_init(void)
+{
+ bslabel_t label;
+
+ /*
+ * Use the value of "label_services" within the edition module.
+ * If for some reason label_services is not found, this will
+ * result in the appropriate default -- "off."
+ */
+ if (modgetsymvalue("label_services", B_FALSE) != 0)
+ sys_labeling = 1;
+ else
+ sys_labeling = 0;
+
+ tslabel_cache = kmem_cache_create("tslabel_cache", sizeof (ts_label_t),
+ 0, NULL, NULL, NULL, NULL, NULL, 0);
+ bsllow(&label);
+ l_admin_low = labelalloc(&label, default_doi, KM_SLEEP);
+ bslhigh(&label);
+ l_admin_high = labelalloc(&label, default_doi, KM_SLEEP);
+}
+
+/*
+ * Allocate new ts_label_t.
+ */
+ts_label_t *
+labelalloc(const bslabel_t *val, uint32_t doi, int flag)
+{
+ ts_label_t *lab = kmem_cache_alloc(tslabel_cache, flag);
+
+ if (lab != NULL) {
+ lab->tsl_ref = 1;
+ lab->tsl_doi = doi;
+ if (val == NULL)
+ bzero(&lab->tsl_label, sizeof (bslabel_t));
+ else
+ bcopy(val, &lab->tsl_label, sizeof (bslabel_t));
+ }
+ return (lab);
+}
+
+/*
+ * Put a hold on a label structure.
+ */
+void
+label_hold(ts_label_t *lab)
+{
+ atomic_add_32(&lab->tsl_ref, 1);
+}
+
+/*
+ * Release previous hold on a label structure. Free it if refcnt == 0.
+ */
+void
+label_rele(ts_label_t *lab)
+{
+ if (atomic_add_32_nv(&lab->tsl_ref, -1) == 0)
+ kmem_cache_free(tslabel_cache, lab);
+}
+
+bslabel_t *
+label2bslabel(ts_label_t *lab)
+{
+ return (&lab->tsl_label);
+}
+
+
+uint32_t
+label2doi(ts_label_t *lab)
+{
+ return (lab->tsl_doi);
+}
+
+/*
+ * Compare labels. Return 1 if equal, 0 otherwise.
+ */
+boolean_t
+label_equal(const ts_label_t *l1, const ts_label_t *l2)
+{
+ return ((l1->tsl_doi == l2->tsl_doi) &&
+ blequal(&l1->tsl_label, &l2->tsl_label));
+}
+
+/*
+ * There's no protocol today to obtain the label from the server.
+ * So we rely on conventions: zones, zone names, and zone paths
+ * must match across TX servers and their TX clients. Now use
+ * the exported name to find the equivalent local zone and its
+ * label. Caller is responsible for doing a label_rele of the
+ * returned ts_label.
+ */
+ts_label_t *
+getflabel_cipso(vfs_t *vfsp)
+{
+ zone_t *reszone;
+ zone_t *new_reszone;
+ char *nfspath, *respath;
+ refstr_t *resource_ref;
+ boolean_t treat_abs = B_FALSE;
+
+ if (vfsp->vfs_resource == NULL)
+ return (NULL); /* error */
+ resource_ref = vfs_getresource(vfsp);
+
+ nfspath = (char *)refstr_value(resource_ref);
+ respath = strchr(nfspath, ':'); /* skip server name */
+ if (respath)
+ respath++; /* skip over ":" */
+ if (*respath != '/') {
+ /* treat path as absolute but it doesn't have leading '/' */
+ treat_abs = B_TRUE;
+ }
+
+ reszone = zone_find_by_any_path(respath, treat_abs);
+ if (reszone == global_zone) {
+ refstr_rele(resource_ref);
+ label_hold(l_admin_low);
+ zone_rele(reszone);
+ return (l_admin_low);
+ }
+
+ /*
+ * Skip over zonepath (not including "root"), e.g. /zone/internal
+ */
+ respath += reszone->zone_rootpathlen - 7;
+ if (treat_abs)
+ respath--; /* no leading '/' to skip */
+ if (strncmp(respath, "/root/", 6) == 0) {
+ /* Check if we now have something like "/zone/public/" */
+
+ respath += 5; /* skip "/root" first */
+ new_reszone = zone_find_by_any_path(respath, B_FALSE);
+ if (new_reszone != global_zone) {
+ zone_rele(reszone);
+ reszone = new_reszone;
+ } else {
+ zone_rele(new_reszone);
+ }
+ }
+
+ refstr_rele(resource_ref);
+ label_hold(reszone->zone_slabel);
+ zone_rele(reszone);
+
+ return (reszone->zone_slabel);
+}
+
+static ts_label_t *
+getflabel_nfs(vfs_t *vfsp)
+{
+ bslabel_t *server_sl;
+ ts_label_t *srv_label;
+ tsol_tpc_t *tp;
+ int addr_type;
+ void *ipaddr;
+ struct servinfo *svp;
+ struct netbuf *addr;
+ struct knetconfig *knconf;
+ mntinfo_t *mi;
+
+ mi = VFTOMI(vfsp);
+ svp = mi->mi_curr_serv;
+ addr = &svp->sv_addr;
+ knconf = svp->sv_knconf;
+
+ if (strcmp(knconf->knc_protofmly, NC_INET) == 0) {
+ addr_type = IPV4_VERSION;
+ /* LINTED: following cast to ipaddr is OK */
+ ipaddr = &((struct sockaddr_in *)addr->buf)->sin_addr;
+ } else if (strcmp(knconf->knc_protofmly, NC_INET6) == 0) {
+ addr_type = IPV6_VERSION;
+ /* LINTED: following cast to ipaddr is OK */
+ ipaddr = &((struct sockaddr_in6 *)addr->buf)->sin6_addr;
+ } else {
+ goto errout;
+ }
+
+ tp = find_tpc(ipaddr, addr_type, B_FALSE);
+ if (tp == NULL)
+ goto errout;
+
+ if (tp->tpc_tp.host_type == SUN_CIPSO) {
+ TPC_RELE(tp);
+ return (getflabel_cipso(vfsp));
+ }
+
+ if (tp->tpc_tp.host_type != UNLABELED)
+ goto errout;
+
+ server_sl = &tp->tpc_tp.tp_def_label;
+ srv_label = labelalloc(server_sl, default_doi, KM_SLEEP);
+
+ TPC_RELE(tp);
+
+ return (srv_label);
+
+errout:
+ return (NULL);
+}
+
+/*
+ * getflabel -
+ *
+ * Return pointer to the ts_label associated with the specified file,
+ * or returns NULL if error occurs. Caller is responsible for doing
+ * a label_rele of the ts_label.
+ */
+ts_label_t *
+getflabel(vnode_t *vp)
+{
+ vfs_t *vfsp, *rvfsp, *nvfs;
+ vnode_t *rvp, *rvp2;
+ zone_t *zone;
+ ts_label_t *zl;
+ boolean_t vfs_is_held = B_FALSE;
+ refstr_t *resource_ref = NULL;
+ char *resource = NULL;
+ char vpath[MAXPATHLEN];
+
+ ASSERT(vp);
+ vfsp = rvfsp = nvfs = vp->v_vfsp;
+ if (vfsp == NULL)
+ return (NULL);
+
+ rvp = rvp2 = vp;
+
+ /*
+ * Get rid of all but the last loopback vfs, since the last such mount
+ * has the correct resource to use (except for nfs case, handled later).
+ */
+ while (strcmp(vfssw[nvfs->vfs_fstype].vsw_name, "lofs") == 0) {
+ rvp = rvp2;
+ rvfsp = nvfs;
+ if ((rvp2 = realvp(rvp)) == NULL)
+ break;
+ if (((nvfs = rvp2->v_vfsp) == NULL) || (nvfs == rvfsp))
+ break;
+ }
+
+ /*
+ * rvp/rvfsp now represent the preliminary vnode/vfs we may use. Now
+ * check if the next vfs is nfs; if so, then it has the correct info
+ * to use. And finally, for some cases on loop-back mounts there will
+ * be no resource; for these, use the underlying vfs also.
+ */
+ if (strcmp(vfssw[rvfsp->vfs_fstype].vsw_name, "lofs") == 0) {
+ if (((rvp2 = realvp(rvp)) != NULL) &&
+ ((nvfs = rvp2->v_vfsp) != NULL) &&
+ ((strcmp(vfssw[nvfs->vfs_fstype].vsw_name, "nfs") == 0)) ||
+ (rvfsp->vfs_resource == NULL)) {
+ rvp = rvp2;
+ rvfsp = nvfs;
+ }
+ }
+
+ /* rvp/rvfsp now represent the real vnode/vfs we will be using */
+
+ /* Go elsewhere to handle all nfs files. */
+ if (strncmp(vfssw[rvfsp->vfs_fstype].vsw_name, "nfs", 3) == 0)
+ return (getflabel_nfs(rvfsp));
+
+ /*
+ * Fast path, for objects in a labeled zone: everything except
+ * for lofs/nfs will be just the label of that zone.
+ */
+ if ((rvfsp->vfs_zone != NULL) && (rvfsp->vfs_zone != global_zone)) {
+ if ((strcmp(vfssw[rvfsp->vfs_fstype].vsw_name,
+ "lofs") != 0)) {
+ zone = rvfsp->vfs_zone;
+ zone_hold(zone);
+ goto zone_out; /* return this label */
+ }
+ }
+
+ if (rvfsp->vfs_resource) {
+ resource_ref = vfs_getresource(rvfsp);
+ resource = (char *)refstr_value(resource_ref);
+ }
+
+ /*
+ * Sanity check - resource may be weird for some cases, like devices.
+ * In this case, the label must be "local", so just use the mount point.
+ */
+ if ((resource == NULL) || (*resource != '/')) {
+ if (resource_ref)
+ refstr_rele(resource_ref);
+ if (rvfsp->vfs_mntpt) {
+ resource_ref = vfs_getmntpoint(rvfsp);
+ resource = (char *)refstr_value(resource_ref);
+ }
+ if ((resource == NULL) || (*resource != '/')) {
+ zone = curproc->p_zone;
+ zone_hold(zone);
+ goto zone_out;
+ }
+ }
+
+ VFS_HOLD(vfsp);
+ vfs_is_held = B_TRUE;
+
+ zone = zone_find_by_any_path(resource, B_FALSE);
+
+ /*
+ * If the vfs source zone is properly set to a non-global zone, or
+ * any zone if the mount is R/W, then use the label of that zone.
+ */
+ if ((zone != global_zone) || ((vfsp->vfs_flag & VFS_RDONLY) != 0))
+ goto zone_out; /* return this label */
+
+ /*
+ * Otherwise, if we're not in the global zone, use the label of
+ * our zone.
+ */
+ if ((zone = curproc->p_zone) != global_zone) {
+ zone_hold(zone);
+ goto zone_out; /* return this label */
+ }
+
+ /*
+ * We're in the global zone and the mount is R/W ... so the file
+ * may actually be in the global zone -- or in the root of any zone.
+ * Always build our own path for the file, to be sure it's simplified
+ * (i.e., no ".", "..", "//", and so on).
+ */
+ if (vnodetopath(NULL, vp, vpath, sizeof (vpath), CRED()) != 0) {
+ if (vfs_is_held)
+ VFS_RELE(vfsp);
+ if (resource_ref)
+ refstr_rele(resource_ref);
+ zone_rele(zone);
+ return (NULL);
+ }
+
+ zone_rele(zone);
+ zone = zone_find_by_any_path(vpath, B_FALSE);
+
+zone_out:
+ if ((curproc->p_zone == global_zone) && (zone == global_zone)) {
+ vfs_t *nvfs;
+ boolean_t exported = B_FALSE;
+ refstr_t *mntpt_ref;
+ char *mntpt;
+
+ /*
+ * File is in the global zone - check whether it's admin_high.
+ * If it's in a filesys that was exported from the global zone,
+ * it's admin_low by definition. Otherwise, if it's in a
+ * filesys that's NOT exported to any zone, it's admin_high.
+ *
+ * And for these files if there wasn't a valid mount resource,
+ * the file must be admin_high (not exported, probably a global
+ * zone device).
+ */
+ if (!vfs_is_held)
+ goto out_high;
+
+ mntpt_ref = vfs_getmntpoint(vfsp);
+ mntpt = (char *)refstr_value(mntpt_ref);
+
+ if ((mntpt != NULL) && (*mntpt == '/')) {
+ zone_t *to_zone;
+
+ to_zone = zone_find_by_any_path(mntpt, B_FALSE);
+ zone_rele(to_zone);
+ if (to_zone != global_zone) {
+ /* force admin_low */
+ exported = B_TRUE;
+ }
+ }
+ if (mntpt_ref)
+ refstr_rele(mntpt_ref);
+
+ if (!exported) {
+ size_t plen = strlen(vpath);
+
+ vfs_list_read_lock();
+ nvfs = vfsp->vfs_next;
+ while (nvfs != vfsp) {
+ const char *rstr;
+ size_t rlen = 0;
+
+ rstr = refstr_value(nvfs->vfs_resource);
+ if (rstr != NULL)
+ rlen = strlen(rstr);
+
+ /*
+ * Check for a match: does this vfs correspond
+ * to our global zone file path? I.e., check
+ * if the resource string of this vfs is a
+ * prefix of our path.
+ */
+ if ((rlen > 0) && (rlen <= plen) &&
+ (strncmp(rstr, vpath, rlen) == 0) &&
+ (vpath[rlen] == '/' ||
+ vpath[rlen] == '\0')) {
+ /* force admin_low */
+ exported = B_TRUE;
+ break;
+ }
+ nvfs = nvfs->vfs_next;
+ }
+ vfs_list_unlock();
+ }
+
+ if (!exported)
+ goto out_high;
+ }
+
+ if (vfs_is_held)
+ VFS_RELE(vfsp);
+
+ if (resource_ref)
+ refstr_rele(resource_ref);
+
+ /*
+ * Now that we have the "home" zone for the file, return the slabel
+ * of that zone.
+ */
+ zl = zone->zone_slabel;
+ label_hold(zl);
+ zone_rele(zone);
+ return (zl);
+
+out_high:
+ if (vfs_is_held)
+ VFS_RELE(vfsp);
+ if (resource_ref)
+ refstr_rele(resource_ref);
+
+ label_hold(l_admin_high);
+ zone_rele(zone);
+ return (l_admin_high);
+}
+
+static int
+cgetlabel(bslabel_t *label_p, vnode_t *vp)
+{
+ ts_label_t *tsl;
+ int error = 0;
+
+ if ((tsl = getflabel(vp)) == NULL)
+ return (EIO);
+
+ if (copyout((caddr_t)label2bslabel(tsl), (caddr_t)label_p,
+ sizeof (*(label_p))) != 0)
+ error = EFAULT;
+
+ label_rele(tsl);
+ return (error);
+}
+
+/*
+ * fgetlabel(2TSOL) - get file label
+ * getlabel(2TSOL) - get file label
+ */
+int
+getlabel(const char *path, bslabel_t *label_p)
+{
+ struct vnode *vp;
+ char *spath;
+ int error;
+
+ /* Sanity check arguments */
+ if (path == NULL)
+ return (set_errno(EINVAL));
+
+ spath = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
+ if ((error = copyinstr(path, spath, MAXPATHLEN, NULL)) != 0) {
+ kmem_free(spath, MAXPATHLEN);
+ return (set_errno(error));
+ }
+
+ if (error = lookupname(spath, UIO_SYSSPACE, FOLLOW, NULLVPP, &vp)) {
+ kmem_free(spath, MAXPATHLEN);
+ return (set_errno(error));
+ }
+ kmem_free(spath, MAXPATHLEN);
+
+ error = cgetlabel(label_p, vp);
+
+ VN_RELE(vp);
+ if (error != 0)
+ return (set_errno(error));
+ else
+ return (0);
+}
+
+int
+fgetlabel(int fd, bslabel_t *label_p)
+{
+ file_t *fp;
+ int error;
+
+ if ((fp = getf(fd)) == NULL)
+ return (set_errno(EBADF));
+
+ error = cgetlabel(label_p, fp->f_vnode);
+ releasef(fd);
+
+ if (error != 0)
+ return (set_errno(error));
+ else
+ return (0);
+}
+
+/*
+ * Used by NFSv4 to query label of a pathname
+ * component during lookup/access ops.
+ */
+ts_label_t *
+nfs4_getflabel(vnode_t *vp)
+{
+ zone_t *zone;
+ ts_label_t *zone_label;
+ char path[MAXNAMELEN];
+ vnode_t *pvp, *tvp;
+
+ mutex_enter(&vp->v_lock);
+ /*
+ * mount traverse has been done by caller
+ * before calling this routine.
+ */
+ ASSERT(!vn_ismntpt(vp));
+ if (vp->v_path != NULL) {
+ zone = zone_find_by_any_path(vp->v_path, B_FALSE);
+ mutex_exit(&vp->v_lock);
+ } else {
+ /*
+ * v_path not cached. Since we rely on path
+ * of an obj to get its label, we need to get
+ * path corresponding to the parent vnode.
+ */
+ tvp = vp;
+ do {
+ mutex_exit(&tvp->v_lock);
+ if ((pvp = dnlc_reverse_lookup(tvp, path,
+ sizeof (path))) == NULL)
+ return (NULL);
+ mutex_enter(&pvp->v_lock);
+ tvp = pvp;
+ } while (pvp->v_path == NULL);
+ zone = zone_find_by_any_path(pvp->v_path, B_FALSE);
+ mutex_exit(&pvp->v_lock);
+ }
+ /*
+ * Caller has verified that the file is either
+ * exported or visible. So if the path falls in
+ * global zone, admin_low is returned; otherwise
+ * the zone's label is returned.
+ */
+ zone_label = zone->zone_slabel;
+ label_hold(zone_label);
+ zone_rele(zone);
+ return (zone_label);
+}
--- a/usr/src/uts/common/os/zone.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/os/zone.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
@@ -186,11 +185,11 @@
#include <sys/priv_impl.h>
#include <sys/cred.h>
#include <c2/audit.h>
-#include <sys/ddi.h>
#include <sys/debug.h>
#include <sys/file.h>
#include <sys/kmem.h>
#include <sys/mutex.h>
+#include <sys/note.h>
#include <sys/pathname.h>
#include <sys/proc.h>
#include <sys/project.h>
@@ -210,7 +209,6 @@
#include <sys/pool.h>
#include <sys/pool_pset.h>
#include <sys/pset.h>
-#include <sys/log.h>
#include <sys/sysmacros.h>
#include <sys/callb.h>
#include <sys/vmparam.h>
@@ -218,7 +216,6 @@
#include <sys/door.h>
#include <sys/cpuvar.h>
-#include <sys/fs/snode.h>
#include <sys/uadmin.h>
#include <sys/session.h>
@@ -228,6 +225,7 @@
#include <sys/rctl.h>
#include <sys/fss.h>
#include <sys/zone.h>
+#include <sys/tsol/label.h>
/*
* cv used to signal that all references to the zone have been released. This
@@ -255,7 +253,7 @@
static list_t zsd_registered_keys;
int zone_hash_size = 256;
-static mod_hash_t *zonehashbyname, *zonehashbyid;
+static mod_hash_t *zonehashbyname, *zonehashbyid, *zonehashbylabel;
static kmutex_t zonehash_lock;
static uint_t zonecount;
static id_space_t *zoneid_space;
@@ -323,6 +321,7 @@
static kmutex_t mount_lock;
const char * const zone_initname = "/sbin/init";
+static char * const zone_prefix = "/zone/";
static int zone_shutdown(zoneid_t zoneid);
@@ -337,8 +336,10 @@
* error reporting when zone_create() fails.
* Version 3 alters the zone_create system call in order to support the
* import of ZFS datasets to zones.
+ * Version 4 alters the zone_create system call in order to support
+ * Trusted Extensions.
*/
-static const int ZONE_SYSCALL_API_VERSION = 3;
+static const int ZONE_SYSCALL_API_VERSION = 4;
/*
* Certain filesystems (such as NFS and autofs) need to know which zone
@@ -998,6 +999,51 @@
}
/*
+ * Compute a hash value based on the contents of the label and the DOI. The
+ * hash algorithm is somewhat arbitrary, but is based on the observation that
+ * humans will likely pick labels that differ by amounts that work out to be
+ * multiples of the number of hash chains, and thus stirring in some primes
+ * should help.
+ */
+static uint_t
+hash_bylabel(void *hdata, mod_hash_key_t key)
+{
+ const ts_label_t *lab = (ts_label_t *)key;
+ const uint32_t *up, *ue;
+ uint_t hash;
+ int i;
+
+ _NOTE(ARGUNUSED(hdata));
+
+ hash = lab->tsl_doi + (lab->tsl_doi << 1);
+ /* we depend on alignment of label, but not representation */
+ up = (const uint32_t *)&lab->tsl_label;
+ ue = up + sizeof (lab->tsl_label) / sizeof (*up);
+ i = 1;
+ while (up < ue) {
+ /* using 2^n + 1, 1 <= n <= 16 as source of many primes */
+ hash += *up + (*up << ((i % 16) + 1));
+ up++;
+ i++;
+ }
+ return (hash);
+}
+
+/*
+ * All that mod_hash cares about here is zero (equal) versus non-zero (not
+ * equal). This may need to be changed if less than / greater than is ever
+ * needed.
+ */
+static int
+hash_labelkey_cmp(mod_hash_key_t key1, mod_hash_key_t key2)
+{
+ ts_label_t *lab1 = (ts_label_t *)key1;
+ ts_label_t *lab2 = (ts_label_t *)key2;
+
+ return (label_equal(lab1, lab2) ? 0 : 1);
+}
+
+/*
* Called by main() to initialize the zones framework.
*/
void
@@ -1063,20 +1109,42 @@
* pool_default hasn't been initialized yet, so we let pool_init() take
* care of making the global zone is in the default pool.
*/
+
+ /*
+ * Initialize zone label.
+ * mlp are initialized when tnzonecfg is loaded.
+ */
+ zone0.zone_slabel = l_admin_low;
+ rw_init(&zone0.zone_mlps.mlpl_rwlock, NULL, RW_DEFAULT, NULL);
+ label_hold(l_admin_low);
+
mutex_enter(&zonehash_lock);
zone_uniqid(&zone0);
ASSERT(zone0.zone_uniqid == GLOBAL_ZONEUNIQID);
- mutex_exit(&zonehash_lock);
+
zonehashbyid = mod_hash_create_idhash("zone_by_id", zone_hash_size,
mod_hash_null_valdtor);
zonehashbyname = mod_hash_create_strhash("zone_by_name",
zone_hash_size, mod_hash_null_valdtor);
+ /*
+ * maintain zonehashbylabel only for labeled systems
+ */
+ if (is_system_labeled())
+ zonehashbylabel = mod_hash_create_extended("zone_by_label",
+ zone_hash_size, mod_hash_null_keydtor,
+ mod_hash_null_valdtor, hash_bylabel, NULL,
+ hash_labelkey_cmp, KM_SLEEP);
zonecount = 1;
(void) mod_hash_insert(zonehashbyid, (mod_hash_key_t)GLOBAL_ZONEID,
(mod_hash_val_t)&zone0);
(void) mod_hash_insert(zonehashbyname, (mod_hash_key_t)zone0.zone_name,
(mod_hash_val_t)&zone0);
+ if (is_system_labeled())
+ (void) mod_hash_insert(zonehashbylabel,
+ (mod_hash_key_t)zone0.zone_slabel, (mod_hash_val_t)&zone0);
+ mutex_exit(&zonehash_lock);
+
/*
* We avoid setting zone_kcred until now, since kcred is initialized
* sometime after zone_zsd_init() and before zone_init().
@@ -1126,6 +1194,8 @@
kmem_free(zone->zone_rootpath, zone->zone_rootpathlen);
if (zone->zone_name != NULL)
kmem_free(zone->zone_name, ZONENAME_MAX);
+ if (zone->zone_slabel != NULL)
+ label_rele(zone->zone_slabel);
if (zone->zone_nodename != NULL)
kmem_free(zone->zone_nodename, _SYS_NMLN);
if (zone->zone_domain != NULL)
@@ -1139,6 +1209,7 @@
id_free(zoneid_space, zone->zone_id);
mutex_destroy(&zone->zone_lock);
cv_destroy(&zone->zone_cv);
+ rw_destroy(&zone->zone_mlps.mlpl_rwlock);
kmem_free(zone, sizeof (zone_t));
}
@@ -1513,6 +1584,24 @@
}
static zone_t *
+zone_find_all_by_label(const ts_label_t *label)
+{
+ mod_hash_val_t hv;
+ zone_t *zone = NULL;
+
+ ASSERT(MUTEX_HELD(&zonehash_lock));
+
+ /*
+ * zonehashbylabel is not maintained for unlabeled systems
+ */
+ if (!is_system_labeled())
+ return (NULL);
+ if (mod_hash_find(zonehashbylabel, (mod_hash_key_t)label, &hv) == 0)
+ zone = (zone_t *)hv;
+ return (zone);
+}
+
+static zone_t *
zone_find_all_by_name(char *name)
{
mod_hash_val_t hv;
@@ -1558,6 +1647,34 @@
}
/*
+ * Similar to zone_find_by_id, but using zone label as the key.
+ */
+zone_t *
+zone_find_by_label(const ts_label_t *label)
+{
+ zone_t *zone;
+
+ mutex_enter(&zonehash_lock);
+ if ((zone = zone_find_all_by_label(label)) == NULL) {
+ mutex_exit(&zonehash_lock);
+ return (NULL);
+ }
+ mutex_enter(&zone_status_lock);
+ if (zone_status_get(zone) > ZONE_IS_DOWN) {
+ /*
+ * For all practical purposes the zone doesn't exist.
+ */
+ mutex_exit(&zone_status_lock);
+ zone = NULL;
+ } else {
+ mutex_exit(&zone_status_lock);
+ zone_hold(zone);
+ }
+ mutex_exit(&zonehash_lock);
+ return (zone);
+}
+
+/*
* Similar to zone_find_by_id, but using zone name as the key.
*/
zone_t *
@@ -2591,6 +2708,23 @@
return (set_errno(er_error));
}
+static int
+zone_set_label(zone_t *zone, const bslabel_t *lab, uint32_t doi)
+{
+ ts_label_t *tsl;
+ bslabel_t blab;
+
+ /* Get label from user */
+ if (copyin(lab, &blab, sizeof (blab)) != 0)
+ return (EFAULT);
+ tsl = labelalloc(&blab, doi, KM_NOSLEEP);
+ if (tsl == NULL)
+ return (ENOMEM);
+
+ zone->zone_slabel = tsl;
+ return (0);
+}
+
/*
* Parses a comma-separated list of ZFS datasets into a per-zone dictionary.
*/
@@ -2643,7 +2777,8 @@
/*
* System call to create/initialize a new zone named 'zone_name', rooted
* at 'zone_root', with a zone-wide privilege limit set of 'zone_privs',
- * and initialized with the zone-wide rctls described in 'rctlbuf'.
+ * and initialized with the zone-wide rctls described in 'rctlbuf', and
+ * with labeling set by 'match', 'doi', and 'label'.
*
* If extended error is non-null, we may use it to return more detailed
* error information.
@@ -2652,7 +2787,8 @@
zone_create(const char *zone_name, const char *zone_root,
const priv_set_t *zone_privs, size_t zone_privssz,
caddr_t rctlbuf, size_t rctlbufsz,
- caddr_t zfsbuf, size_t zfsbufsz, int *extended_error)
+ caddr_t zfsbuf, size_t zfsbufsz, int *extended_error,
+ int match, uint32_t doi, const bslabel_t *label)
{
struct zsched_arg zarg;
nvlist_t *rctls = NULL;
@@ -2687,6 +2823,7 @@
offsetof(struct zsd_entry, zsd_linkage));
list_create(&zone->zone_datasets, sizeof (zone_dataset_t),
offsetof(zone_dataset_t, zd_linkage));
+ rw_init(&zone->zone_mlps.mlpl_rwlock, NULL, RW_DEFAULT, NULL);
if ((error = zone_set_name(zone, zone_name)) != 0) {
zone_free(zone);
@@ -2728,6 +2865,23 @@
}
/*
+ * Read in the trusted system parameters:
+ * match flag and sensitivity label.
+ */
+ zone->zone_match = match;
+ if (is_system_labeled()) {
+ error = zone_set_label(zone, label, doi);
+ if (error != 0) {
+ zone_free(zone);
+ return (set_errno(error));
+ }
+ } else {
+ /* all zones get an admin_low label if system is not labeled */
+ zone->zone_slabel = l_admin_low;
+ label_hold(l_admin_low);
+ }
+
+ /*
* Stop all lwps since that's what normally happens as part of fork().
* This needs to happen before we grab any locks to avoid deadlock
* (another lwp in the process could be waiting for the held lock).
@@ -2765,8 +2919,13 @@
mutex_enter(&zonehash_lock);
/*
* Make sure zone doesn't already exist.
+ *
+ * If the system and zone are labeled,
+ * make sure no other zone exists that has the same label.
*/
- if ((ztmp = zone_find_all_by_name(zone->zone_name)) != NULL) {
+ if ((ztmp = zone_find_all_by_name(zone->zone_name)) != NULL ||
+ (zone->zone_slabel != NULL &&
+ (ztmp = zone_find_all_by_label(zone->zone_slabel)) != NULL)) {
zone_status_t status;
status = zone_status_get(ztmp);
@@ -2813,6 +2972,11 @@
(void) strcpy(str, zone->zone_name);
(void) mod_hash_insert(zonehashbyname, (mod_hash_key_t)str,
(mod_hash_val_t)(uintptr_t)zone);
+ if (is_system_labeled()) {
+ (void) mod_hash_insert(zonehashbylabel,
+ (mod_hash_key_t)zone->zone_slabel, (mod_hash_val_t)zone);
+ }
+
/*
* Insert into active list. At this point there are no 'hold's
* on the zone, but everyone else knows not to use it, so we can
@@ -2836,6 +3000,11 @@
*/
mutex_enter(&zonehash_lock);
list_remove(&zone_active, zone);
+ if (is_system_labeled()) {
+ ASSERT(zone->zone_slabel != NULL);
+ (void) mod_hash_destroy(zonehashbylabel,
+ (mod_hash_key_t)zone->zone_slabel);
+ }
(void) mod_hash_destroy(zonehashbyname,
(mod_hash_key_t)(uintptr_t)zone->zone_name);
(void) mod_hash_destroy(zonehashbyid,
@@ -2982,6 +3151,42 @@
}
/*
+ * This function implements the policy for zone visibility.
+ *
+ * In standard Solaris, a non-global zone can only see itself.
+ *
+ * In Trusted Extensions, a labeled zone can lookup any zone whose label
+ * it dominates. For this test, the label of the global zone is treated as
+ * admin_high so it is special-cased instead of being checked for dominance.
+ *
+ * Returns true if zone attributes are viewable, false otherwise.
+ */
+static boolean_t
+zone_list_access(zone_t *zone)
+{
+
+ if (curproc->p_zone == global_zone ||
+ curproc->p_zone == zone) {
+ return (B_TRUE);
+ } else if (is_system_labeled()) {
+ bslabel_t *curproc_label;
+ bslabel_t *zone_label;
+
+ curproc_label = label2bslabel(curproc->p_zone->zone_slabel);
+ zone_label = label2bslabel(zone->zone_slabel);
+
+ if (zone->zone_id != GLOBAL_ZONEID &&
+ bldominates(curproc_label, zone_label)) {
+ return (B_TRUE);
+ } else {
+ return (B_FALSE);
+ }
+ } else {
+ return (B_FALSE);
+ }
+}
+
+/*
* Systemcall to start the zone's halt sequence. By the time this
* function successfully returns, all user processes and kernel threads
* executing in it will have exited, ZSD shutdown callbacks executed,
@@ -3237,6 +3442,9 @@
(mod_hash_key_t)zone->zone_name);
(void) mod_hash_destroy(zonehashbyid,
(mod_hash_key_t)(uintptr_t)zone->zone_id);
+ if (is_system_labeled() && zone->zone_slabel != NULL)
+ (void) mod_hash_destroy(zonehashbylabel,
+ (mod_hash_key_t)zone->zone_slabel);
mutex_exit(&zonehash_lock);
/*
@@ -3274,6 +3482,7 @@
zone_status_t zone_status;
pid_t initpid;
boolean_t global = (curproc->p_zone == global_zone);
+ boolean_t curzone = (curproc->p_zone->zone_id == zoneid);
mutex_enter(&zonehash_lock);
if ((zone = zone_find_all_by_id(zoneid)) == NULL) {
@@ -3289,9 +3498,11 @@
mutex_exit(&zonehash_lock);
/*
- * If not in the global zone, don't show information about other zones.
+ * If not in the global zone, don't show information about other zones,
+ * unless the system is labeled and the local zone's label dominates
+ * the other zone.
*/
- if (!global && curproc->p_zone != zone) {
+ if (!zone_list_access(zone)) {
zone_rele(zone);
return (set_errno(EINVAL));
}
@@ -3311,12 +3522,29 @@
bcopy(zone->zone_rootpath, zonepath, size);
zonepath[size - 1] = '\0';
} else {
- /*
- * Caller is not in the global zone, just return
- * faked-up path for current zone.
- */
- zonepath = "/";
- size = 2;
+ if (curzone || !is_system_labeled()) {
+ /*
+ * Caller is not in the global zone.
+ * if the query is on the current zone
+ * or the system is not labeled,
+ * just return faked-up path for current zone.
+ */
+ zonepath = "/";
+ size = 2;
+ } else {
+ /*
+ * Return related path for current zone.
+ */
+ int prefix_len = strlen(zone_prefix);
+ int zname_len = strlen(zone->zone_name);
+
+ size = prefix_len + zname_len + 1;
+ zonepath = kmem_alloc(size, KM_SLEEP);
+ bcopy(zone_prefix, zonepath, prefix_len);
+ bcopy(zone->zone_name, zonepath +
+ prefix_len, zname_len);
+ zonepath[size - 1] = '\0';
+ }
}
if (bufsize > size)
bufsize = size;
@@ -3325,7 +3553,7 @@
if (err != 0 && err != ENAMETOOLONG)
error = EFAULT;
}
- if (global)
+ if (global || (is_system_labeled() && !curzone))
kmem_free(zonepath, size);
break;
@@ -3388,6 +3616,17 @@
error = EFAULT;
}
break;
+ case ZONE_ATTR_SLBL:
+ size = sizeof (bslabel_t);
+ if (bufsize > size)
+ bufsize = size;
+ if (zone->zone_slabel == NULL)
+ error = EINVAL;
+ else if (buf != NULL &&
+ copyout(label2bslabel(zone->zone_slabel), buf,
+ bufsize) != 0)
+ error = EFAULT;
+ break;
case ZONE_ATTR_INITPID:
size = sizeof (initpid);
if (bufsize > size)
@@ -3778,6 +4017,7 @@
* Systemcall entry point for zone_list(2).
*
* Processes running in a (non-global) zone only see themselves.
+ * On labeled systems, they see all zones whose label they dominate.
*/
static int
zone_list(zoneid_t *zoneidlist, uint_t *numzones)
@@ -3785,47 +4025,79 @@
zoneid_t *zoneids;
zone_t *zone;
uint_t user_nzones, real_nzones;
- int error = 0;
- uint_t i;
+ uint_t domi_nzones;
+ int error;
if (copyin(numzones, &user_nzones, sizeof (uint_t)) != 0)
return (set_errno(EFAULT));
if (curproc->p_zone != global_zone) {
- /* just return current zone */
- real_nzones = 1;
- zoneids = kmem_alloc(sizeof (zoneid_t), KM_SLEEP);
- zoneids[0] = curproc->p_zone->zone_id;
+ bslabel_t *mybslab;
+
+ if (!is_system_labeled()) {
+ /* just return current zone */
+ real_nzones = domi_nzones = 1;
+ zoneids = kmem_alloc(sizeof (zoneid_t), KM_SLEEP);
+ zoneids[0] = curproc->p_zone->zone_id;
+ } else {
+ /* return all zones that are dominated */
+ mutex_enter(&zonehash_lock);
+ real_nzones = zonecount;
+ domi_nzones = 0;
+ if (real_nzones > 0) {
+ zoneids = kmem_alloc(real_nzones *
+ sizeof (zoneid_t), KM_SLEEP);
+ mybslab = label2bslabel(curproc->p_zone->
+ zone_slabel);
+ for (zone = list_head(&zone_active);
+ zone != NULL;
+ zone = list_next(&zone_active, zone)) {
+ if (zone->zone_id == GLOBAL_ZONEID)
+ continue;
+ if (bldominates(mybslab,
+ label2bslabel(zone->zone_slabel))) {
+ zoneids[domi_nzones++] =
+ zone->zone_id;
+ }
+ }
+ }
+ mutex_exit(&zonehash_lock);
+ }
} else {
mutex_enter(&zonehash_lock);
real_nzones = zonecount;
- if (real_nzones) {
+ domi_nzones = 0;
+ if (real_nzones > 0) {
zoneids = kmem_alloc(real_nzones * sizeof (zoneid_t),
KM_SLEEP);
- i = 0;
for (zone = list_head(&zone_active); zone != NULL;
zone = list_next(&zone_active, zone))
- zoneids[i++] = zone->zone_id;
- ASSERT(i == real_nzones);
+ zoneids[domi_nzones++] = zone->zone_id;
+ ASSERT(domi_nzones == real_nzones);
}
mutex_exit(&zonehash_lock);
}
- if (user_nzones > real_nzones)
- user_nzones = real_nzones;
-
- if (copyout(&real_nzones, numzones, sizeof (uint_t)) != 0)
+ /*
+ * If user has allocated space for fewer entries than we found, then
+ * return only up to his limit. Either way, tell him exactly how many
+ * we found.
+ */
+ if (domi_nzones < user_nzones)
+ user_nzones = domi_nzones;
+ error = 0;
+ if (copyout(&domi_nzones, numzones, sizeof (uint_t)) != 0) {
error = EFAULT;
- else if (zoneidlist != NULL && user_nzones != 0) {
+ } else if (zoneidlist != NULL && user_nzones != 0) {
if (copyout(zoneids, zoneidlist,
user_nzones * sizeof (zoneid_t)) != 0)
error = EFAULT;
}
- if (real_nzones)
+ if (real_nzones > 0)
kmem_free(zoneids, real_nzones * sizeof (zoneid_t));
- if (error)
+ if (error != 0)
return (set_errno(error));
else
return (0);
@@ -3834,7 +4106,8 @@
/*
* Systemcall entry point for zone_lookup(2).
*
- * Non-global zones are only able to see themselves.
+ * Non-global zones are only able to see themselves and (on labeled systems)
+ * the zones they dominate.
*/
static zoneid_t
zone_lookup(const char *zone_name)
@@ -3858,15 +4131,20 @@
mutex_enter(&zonehash_lock);
zone = zone_find_all_by_name(kname);
kmem_free(kname, ZONENAME_MAX);
- if (zone == NULL || zone_status_get(zone) < ZONE_IS_READY ||
- (curproc->p_zone != global_zone && curproc->p_zone != zone)) {
- /* in non-global zone, can only lookup own name */
+ /*
+ * In a non-global zone, can only lookup global and own name.
+ * In Trusted Extensions zone label dominance rules apply.
+ */
+ if (zone == NULL ||
+ zone_status_get(zone) < ZONE_IS_READY ||
+ !zone_list_access(zone)) {
mutex_exit(&zonehash_lock);
return (set_errno(EINVAL));
+ } else {
+ zoneid = zone->zone_id;
+ mutex_exit(&zonehash_lock);
+ return (zoneid);
}
- zoneid = zone->zone_id;
- mutex_exit(&zonehash_lock);
- return (zoneid);
}
static int
@@ -3912,6 +4190,9 @@
zs.zfsbufsz = zs32.zfsbufsz;
zs.extended_error =
(int *)(unsigned long)zs32.extended_error;
+ zs.match = zs32.match;
+ zs.doi = zs32.doi;
+ zs.label = (const bslabel_t *)(uintptr_t)zs32.label;
#else
panic("get_udatamodel() returned bogus result\n");
#endif
@@ -3921,7 +4202,8 @@
zs.zone_privs, zs.zone_privssz,
(caddr_t)zs.rctlbuf, zs.rctlbufsz,
(caddr_t)zs.zfsbuf, zs.zfsbufsz,
- zs.extended_error));
+ zs.extended_error, zs.match, zs.doi,
+ zs.label));
case ZONE_BOOT:
return (zone_boot((zoneid_t)(uintptr_t)arg1,
(const char *)arg2));
@@ -4261,3 +4543,65 @@
return (0);
}
+
+/*
+ * zone_find_by_any_path() -
+ *
+ * kernel-private routine similar to zone_find_by_path(), but which
+ * effectively compares against zone paths rather than zonerootpath
+ * (i.e., the last component of zonerootpaths, which should be "root/",
+ * are not compared.) This is done in order to accurately identify all
+ * paths, whether zone-visible or not, including those which are parallel
+ * to /root/, such as /dev/, /home/, etc...
+ *
+ * If the specified path does not fall under any zone path then global
+ * zone is returned.
+ *
+ * The treat_abs parameter indicates whether the path should be treated as
+ * an absolute path although it does not begin with "/". (This supports
+ * nfs mount syntax such as host:any/path.)
+ *
+ * The caller is responsible for zone_rele of the returned zone.
+ */
+zone_t *
+zone_find_by_any_path(const char *path, boolean_t treat_abs)
+{
+ zone_t *zone;
+ int path_offset = 0;
+
+ if (path == NULL) {
+ zone_hold(global_zone);
+ return (global_zone);
+ }
+
+ if (*path != '/') {
+ ASSERT(treat_abs);
+ path_offset = 1;
+ }
+
+ mutex_enter(&zonehash_lock);
+ for (zone = list_head(&zone_active); zone != NULL;
+ zone = list_next(&zone_active, zone)) {
+ char *c;
+ size_t pathlen;
+
+ if (zone == global_zone) /* skip global zone */
+ continue;
+
+ /* scan backwards to find start of last component */
+ c = zone->zone_rootpath + zone->zone_rootpathlen - 2;
+ do {
+ c--;
+ } while (*c != '/');
+
+ pathlen = c - zone->zone_rootpath + 1;
+ if (strncmp(path, zone->zone_rootpath + path_offset,
+ pathlen - path_offset) == 0)
+ break;
+ }
+ if (zone == NULL)
+ zone = global_zone;
+ zone_hold(zone);
+ mutex_exit(&zonehash_lock);
+ return (zone);
+}
--- a/usr/src/uts/common/rpc/clnt_clts.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/rpc/clnt_clts.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -1428,6 +1427,7 @@
int error;
int retval;
zoneid_t zoneid = rpc_zoneid();
+ cred_t *cr;
RPCLOG(1, "endpnt_get: protofmly %s, ", config->knc_protofmly);
RPCLOG(1, "rdev %ld\n", config->knc_rdev);
@@ -1633,8 +1633,9 @@
/*
* The transport should be opened with sufficient privs
*/
+ cr = zone_kcred();
error = t_kopen(NULL, config->knc_rdev, FREAD|FWRITE|FNDELAY, &tiptr,
- kcred);
+ cr);
if (error) {
RPCLOG(1, "endpnt_get: t_kopen: %d\n", error);
goto bad;
@@ -1647,14 +1648,14 @@
* Allow the kernel to push the module on behalf of the user.
*/
error = strioctl(tiptr->fp->f_vnode, I_PUSH, (intptr_t)"rpcmod", 0,
- K_TO_K, kcred, &retval);
+ K_TO_K, cr, &retval);
if (error) {
RPCLOG(1, "endpnt_get: kstr_push on rpcmod failed %d\n", error);
goto bad;
}
error = strioctl(tiptr->fp->f_vnode, RPC_CLIENT, 0, 0, K_TO_K,
- kcred, &retval);
+ cr, &retval);
if (error) {
RPCLOG(1, "endpnt_get: strioctl failed %d\n", error);
goto bad;
@@ -1666,7 +1667,7 @@
new->e_wq = tiptr->fp->f_vnode->v_stream->sd_wrq->q_next;
error = strioctl(tiptr->fp->f_vnode, I_PUSH, (intptr_t)"timod", 0,
- K_TO_K, kcred, &retval);
+ K_TO_K, cr, &retval);
if (error) {
RPCLOG(1, "endpnt_get: kstr_push on timod failed %d\n", error);
goto bad;
@@ -1704,8 +1705,8 @@
* reopen with all privileges
*/
error = t_kopen(NULL, config->knc_rdev,
- FREAD|FWRITE|FNDELAY,
- &new->e_tiptr, kcred);
+ FREAD|FWRITE|FNDELAY,
+ &new->e_tiptr, cr);
if (error) {
RPCLOG(1, "endpnt_get: t_kopen: %d\n", error);
new->e_tiptr = NULL;
--- a/usr/src/uts/common/rpc/clnt_cots.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/rpc/clnt_cots.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -1989,7 +1988,7 @@
RPCLOG0(8, "connmgr_get: creating new connection\n");
rpcerr->re_status = RPC_TLIERROR;
- i = t_kopen(NULL, device, FREAD|FWRITE|FNDELAY, &tiptr, kcred);
+ i = t_kopen(NULL, device, FREAD|FWRITE|FNDELAY, &tiptr, zone_kcred());
if (i) {
RPCLOG(1, "connmgr_get: can't open cots device, error %d\n", i);
rpcerr->re_errno = i;
--- a/usr/src/uts/common/rpc/svc.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/rpc/svc.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -212,6 +211,7 @@
#include <sys/vtrace.h>
#include <sys/zone.h>
#include <nfs/nfs.h>
+#include <sys/tsol/label_macro.h>
#define RQCRED_SIZE 400 /* this size is excessive */
@@ -1305,6 +1305,8 @@
"svc_getreq_start:");
ASSERT(clone_xprt->xp_master != NULL);
+ ASSERT(!is_system_labeled() || DB_CRED(mp) != NULL ||
+ mp->b_datap->db_type != M_DATA);
/*
* Firstly, allocate the authentication parameters' storage
@@ -1326,6 +1328,28 @@
r.rq_clntcred = &(cred_area[2 * MAX_AUTH_BYTES]);
/*
+ * underlying transport recv routine may modify mblk data
+ * and make it difficult to extract label afterwards. So
+ * get the label from the raw mblk data now.
+ */
+ if (is_system_labeled()) {
+ mblk_t *lmp;
+
+ r.rq_label = kmem_alloc(sizeof (bslabel_t), KM_SLEEP);
+ if (DB_CRED(mp) != NULL)
+ lmp = mp;
+ else {
+ ASSERT(mp->b_cont != NULL);
+ lmp = mp->b_cont;
+ ASSERT(DB_CRED(lmp) != NULL);
+ }
+ bcopy(label2bslabel(crgetlabel(DB_CRED(lmp))), r.rq_label,
+ sizeof (bslabel_t));
+ } else {
+ r.rq_label = NULL;
+ }
+
+ /*
* Now receive a message from the transport.
*/
if (SVC_RECV(clone_xprt, mp, &msg)) {
@@ -1410,6 +1434,9 @@
}
}
+ if (r.rq_label != NULL)
+ kmem_free(r.rq_label, sizeof (bslabel_t));
+
/*
* Free authentication parameters' storage
*/
@@ -1442,7 +1469,6 @@
/* Fre credentials from crget() */
if (clone_xprt->xp_cred)
crfree(clone_xprt->xp_cred);
-
kmem_free(clone_xprt, sizeof (SVCXPRT));
}
@@ -1480,6 +1506,7 @@
/* Restore per-thread fields (xp_cred) */
clone_xprt->xp_cred = cred;
+
/*
* NOTICE: There is no transport-type specific code now.
* If you want to add a transport-type specific cloning code
@@ -2379,6 +2406,9 @@
TRACE_0(TR_FAC_KRPC, TR_SVC_QUEUEREQ_START, "svc_queuereq_start");
+ ASSERT(!is_system_labeled() || DB_CRED(mp) != NULL ||
+ mp->b_datap->db_type != M_DATA);
+
/*
* Step 1.
* Grab the transport's request lock and put
--- a/usr/src/uts/common/rpc/svc.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/rpc/svc.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -44,6 +43,7 @@
#include <rpc/rpc_msg.h>
#include <sys/tihdr.h>
#include <sys/poll.h>
+#include <sys/tsol/label.h>
#ifdef _KERNEL
#include <rpc/svc_auth.h>
@@ -110,6 +110,7 @@
struct opaque_auth rq_cred; /* raw creds from the wire */
caddr_t rq_clntcred; /* read only cooked cred */
SVCXPRT *rq_xprt; /* associated transport */
+ bslabel_t *rq_label; /* TSOL label of the request */
};
#ifdef _KERNEL
@@ -991,6 +992,8 @@
extern int svc_dg_enablecache();
#endif /* __STDC__ */
+extern boolean_t is_multilevel(rpcprog_t);
+
#ifdef PORTMAP
/* For backward compatibility */
#include <rpc/svc_soc.h>
--- a/usr/src/uts/common/sys/Makefile Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/sys/Makefile Fri Mar 24 12:29:20 2006 -0800
@@ -841,6 +841,13 @@
rsmpi_driver.h \
rsmka_path_int.h
+TSOLHDRS= \
+ label.h \
+ label_macro.h \
+ priv.h \
+ tndb.h \
+ tsyscall.h
+
I1394HDRS= \
cmd1394.h \
id1394.h \
@@ -939,7 +946,8 @@
$(UGENHDRS:%.h=usb/clients/ugen/%.check) \
$(USBHDRS:%.h=usb/%.check) \
$(I1394HDRS:%.h=1394/%.check) \
- $(RSMHDRS:%.h=rsm/%.check)
+ $(RSMHDRS:%.h=rsm/%.check) \
+ $(TSOLHDRS:%.h=tsol/%.check)
.KEEP_STATE:
@@ -984,6 +992,7 @@
$(ROOTHOTPLUGHDRS) \
$(ROOTHOTPLUGPCIHDRS) \
$(ROOTRSMHDRS) \
+ $(ROOTTSOLHDRS) \
$($(MACH)_ROOTHDRS)
@@ -1029,6 +1038,7 @@
$(ROOTHOTPLUGHDRS) \
$(ROOTHOTPLUGPCIHDRS) \
$(ROOTRSMHDRS) \
+ $(ROOTTSOLHDRS) \
$($(MACH)_ROOTHDRS)
all_h: $(GENHDRS)
--- a/usr/src/uts/common/sys/Makefile.syshdrs Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/sys/Makefile.syshdrs Fri Mar 24 12:29:20 2006 -0800
@@ -111,6 +111,9 @@
rsm/%.check: rsm/%.h
$(DOT_H_CHECK)
+tsol/%.check: tsol/%.h
+ $(DOT_H_CHECK)
+
ROOTDIR= $(ROOT)/usr/include/sys
ROOTDKTPDIR= $(ROOTDIR)/dktp
@@ -162,6 +165,7 @@
$(ROOTDIR)/usb/clients/ugen \
$(ROOTDIR)/1394 \
$(ROOTDIR)/rsm \
+ $(ROOTDIR)/tsol \
$($(MACH)_ROOTDIRS)
@@ -234,6 +238,7 @@
ROOTHOTPLUGHDRS= $(HOTPLUGHDRS:%=$(ROOTDIR)/hotplug/%)
ROOTHOTPLUGPCIHDRS= $(HOTPLUGPCIHDRS:%=$(ROOTDIR)/hotplug/pci/%)
+ROOTTSOLHDRS= $(TSOLHDRS:%=$(ROOTDIR)/tsol/%)
sparc_ROOTHDRS= $(ROOTSDKTPHDRS) $(ROOTSCSICADHDRS) $(ROOTSCSITARGETSHDRS) \
$(ROOTFCHDRS) $(ROOTUSBHDRS) $(ROOTUSBHUBDHDRS) $(ROOTPCMCIAHDRS) \
@@ -340,6 +345,9 @@
$(ROOTDIR)/rsm/%: rsm/%
$(INS.file)
+$(ROOTDIR)/tsol/%: tsol/%
+ $(INS.file)
+
$(ROOTDIRS):
$(INS.dir)
--- a/usr/src/uts/common/sys/cred.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/sys/cred.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -81,6 +80,7 @@
extern int hasprocperm(const cred_t *, const cred_t *);
extern int prochasprocperm(struct proc *, struct proc *, const cred_t *);
extern int crcmp(const cred_t *, const cred_t *);
+extern cred_t *zone_kcred(void);
extern uid_t crgetuid(const cred_t *);
extern uid_t crgetruid(const cred_t *);
@@ -91,6 +91,7 @@
extern zoneid_t crgetzoneid(const cred_t *);
extern projid_t crgetprojid(const cred_t *);
+
extern const struct auditinfo_addr *crgetauinfo(const cred_t *);
extern struct auditinfo_addr *crgetauinfo_modifiable(cred_t *);
@@ -120,6 +121,7 @@
*/
struct zone;
extern void crsetzone(cred_t *, struct zone *);
+extern struct zone *crgetzone(const cred_t *);
/*
* Private interface for setting project id in credential.
@@ -136,6 +138,13 @@
*/
extern void cred2prcred(const cred_t *, struct prcred *);
+/*
+ * Private interfaces for Rampart Trusted Solaris.
+ */
+struct ts_label_s;
+extern struct ts_label_s *crgetlabel(const cred_t *);
+extern boolean_t crisremote(const cred_t *);
+
#endif /* _KERNEL */
#ifdef __cplusplus
--- a/usr/src/uts/common/sys/cred_impl.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/sys/cred_impl.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -63,6 +62,7 @@
#if defined(_KERNEL) || defined(_KMEMUSER)
struct zone; /* forward reference */
+struct ts_label_s; /* forward reference */
struct cred {
uint_t cr_ref; /* reference count */
@@ -77,6 +77,7 @@
cred_priv_t cr_priv; /* privileges */
projid_t cr_projid; /* project */
struct zone *cr_zone; /* pointer to per-zone structure */
+ struct ts_label_s *cr_label; /* pointer to the effective label */
gid_t cr_groups[1]; /* cr_groups size not fixed */
/* audit info is defined dynamically */
/* and valid only when audit enabled */
--- a/usr/src/uts/common/sys/policy.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/sys/policy.h Fri Mar 24 12:29:20 2006 -0800
@@ -102,10 +102,13 @@
int secpolicy_lock_memory(const cred_t *);
int secpolicy_modctl(const cred_t *, int);
int secpolicy_net(const cred_t *, int, boolean_t);
+int secpolicy_net_bindmlp(const cred_t *);
int secpolicy_net_config(const cred_t *, boolean_t);
int secpolicy_net_icmpaccess(const cred_t *);
+int secpolicy_net_mac_aware(const cred_t *);
int secpolicy_net_privaddr(const cred_t *, in_port_t);
int secpolicy_net_rawaccess(const cred_t *);
+boolean_t secpolicy_net_reply_equal(const cred_t *);
int secpolicy_newproc(const cred_t *);
int secpolicy_nfs(const cred_t *);
int secpolicy_pcfs_modify_bootpartition(const cred_t *);
--- a/usr/src/uts/common/sys/priv.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/sys/priv.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -133,7 +132,11 @@
#define PRIV_AWARE 0x0002 /* Is privilege aware */
#define PRIV_AWARE_INHERIT 0x0004 /* Inherit awareness */
#define __PROC_PROTECT 0x0008 /* Private */
-#define PRIV_USER (PRIV_DEBUG) /* User settable */
+#define NET_MAC_AWARE 0x0010 /* Is MAC aware */
+#define NET_MAC_AWARE_INHERIT 0x0020 /* Inherit MAC aware */
+
+/* user-settable flags: */
+#define PRIV_USER (PRIV_DEBUG | NET_MAC_AWARE | NET_MAC_AWARE_INHERIT)
/*
* Header of the privilege info data structure; multiple structures can
@@ -228,6 +231,9 @@
extern void priv_adjust_PA(cred_t *);
extern boolean_t priv_can_clear_PA(const cred_t *);
+extern int setpflags(uint_t, uint_t, cred_t *);
+extern uint_t getpflags(uint_t, const cred_t *);
+
#endif /* _KERNEL */
#ifdef __cplusplus
--- a/usr/src/uts/common/sys/socket.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/sys/socket.h Fri Mar 24 12:29:20 2006 -0800
@@ -142,6 +142,8 @@
#define SO_ERROR 0x1007 /* get error status and clear */
#define SO_TYPE 0x1008 /* get socket type */
#define SO_PROTOTYPE 0x1009 /* get/set protocol type */
+#define SO_ANON_MLP 0x100a /* create MLP on anonymous bind */
+#define SO_MAC_EXEMPT 0x100b /* allow dominated unlabeled peers */
/* "Socket"-level control message types: */
#define SCM_RIGHTS 0x1010 /* access rights (array of int) */
--- a/usr/src/uts/common/sys/strsun.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/sys/strsun.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -55,6 +54,9 @@
#define MBLKIN(mp, off, len) (((off) <= MBLKL(mp)) && \
(((mp)->b_rptr + (off) + (len)) <= (mp)->b_wptr))
+#define MBLK_GETLABEL(mp) \
+ (DB_CRED(mp) != NULL ? crgetlabel(DB_CRED(mp)) : NULL)
+
#ifdef _KERNEL
extern void mcopyin(mblk_t *, void *, size_t, void *);
extern void mcopyout(mblk_t *, void *, size_t, void *, mblk_t *);
--- a/usr/src/uts/common/sys/syscall.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/sys/syscall.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -395,7 +394,7 @@
* port_dispatch(...) :: portfs(PORT_DISPATCH, ...)
*/
#define SYS_pollsys 183
-#define SYS_tsolsys 184
+#define SYS_labelsys 184
#define SYS_acl 185
#define SYS_auditsys 186
#define SYS_processor_bind 187
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/tsol/label.h Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,146 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_TSOL_LABEL_H
+#define _SYS_TSOL_LABEL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#ifdef _KERNEL
+#include <sys/cred.h>
+#include <sys/vnode.h>
+#include <sys/tsol/label_macro.h>
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Binary Label Structure Definitions */
+
+typedef struct _mac_label_impl m_label_t;
+
+typedef m_label_t blevel_t, /* compatibility */
+ bslabel_t, /* Sensitivity Label */
+ bclear_t; /* Clearance */
+
+typedef struct _tsol_binary_level_lrange { /* Level Range */
+ m_label_t *lower_bound;
+ m_label_t *upper_bound;
+} m_range_t;
+
+typedef m_range_t blrange_t;
+
+#define NMLP_MAX 0x10
+#define NSLS_MAX 0x4
+
+typedef m_label_t blset_t[NSLS_MAX];
+
+typedef struct tsol_mlp_s {
+ uchar_t mlp_ipp;
+ uint16_t mlp_port;
+ uint16_t mlp_port_upper;
+} tsol_mlp_t;
+
+/* Procedure Interface Definitions available to user and kernel */
+
+extern int bltype(const void *, uint8_t);
+extern int blequal(const m_label_t *, const m_label_t *);
+extern int bldominates(const m_label_t *, const m_label_t *);
+extern int blstrictdom(const m_label_t *, const m_label_t *);
+extern int blinrange(const m_label_t *, const m_range_t *);
+extern void blmaximum(m_label_t *, const m_label_t *);
+extern void blminimum(m_label_t *, const m_label_t *);
+extern void bsllow(m_label_t *);
+extern void bslhigh(m_label_t *);
+extern void bclearlow(m_label_t *);
+extern void bclearhigh(m_label_t *);
+extern void bslundef(m_label_t *);
+extern void bclearundef(m_label_t *);
+extern void setbltype(void *, uint8_t);
+extern boolean_t bisinvalid(const void *);
+
+#ifdef _KERNEL
+typedef struct tsol_mlp_entry_s {
+ struct tsol_mlp_entry_s *mlpe_next, *mlpe_prev;
+ zoneid_t mlpe_zoneid;
+ tsol_mlp_t mlpe_mlp;
+} tsol_mlp_entry_t;
+
+typedef struct tsol_mlp_list_s {
+ krwlock_t mlpl_rwlock;
+ tsol_mlp_entry_t *mlpl_first, *mlpl_last;
+} tsol_mlp_list_t;
+
+typedef struct ts_label_s {
+ uint_t tsl_ref; /* Reference count */
+ uint32_t tsl_doi; /* Domain of Interpretation */
+ uint32_t tsl_flags; /* TSLF_* below */
+ m_label_t tsl_label; /* Actual label */
+} ts_label_t;
+
+#define DEFAULT_DOI 1
+
+#define TSLF_UNLABELED 0x00000001 /* source was unlabeled */
+
+#define CR_SL(cr) (label2bslabel(crgetlabel(cr)))
+
+extern ts_label_t *l_admin_low;
+extern ts_label_t *l_admin_high;
+extern uint32_t default_doi;
+extern int sys_labeling;
+
+extern void label_init(void);
+extern ts_label_t *labelalloc(const m_label_t *, uint32_t, int);
+extern void label_hold(ts_label_t *);
+extern void label_rele(ts_label_t *);
+extern m_label_t *label2bslabel(ts_label_t *);
+extern uint32_t label2doi(ts_label_t *);
+extern boolean_t label_equal(const ts_label_t *, const ts_label_t *);
+extern cred_t *newcred_from_bslabel(m_label_t *, uint32_t, int);
+extern cred_t *copycred_from_bslabel(cred_t *, m_label_t *,
+ uint32_t, int);
+extern ts_label_t *getflabel(vnode_t *);
+extern int getlabel(const char *, m_label_t *);
+extern int fgetlabel(int, m_label_t *);
+extern int _blinrange(const m_label_t *, const brange_t *);
+extern int blinlset(const m_label_t *, const blset_t);
+extern ts_label_t *nfs4_getflabel(vnode_t *);
+
+/*
+ * The use of '!!' here prevents users from referencing this function-like
+ * macro as though it were an l-value, and in normal use is optimized away
+ * by the compiler.
+ */
+#define is_system_labeled() (!!(sys_labeling > 0))
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_SYS_TSOL_LABEL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/tsol/label_macro.h Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,356 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _LABEL_MACRO_H
+#define _LABEL_MACRO_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* PRIVATE ONLY TO THE LABEL LIBRARY. DO NOT USE ELSEWHERE */
+
+/* Actual Binary Label Structure Definitions */
+
+typedef int16_t _Classification;
+typedef struct {
+ union {
+ uint8_t class_ar[2];
+ _Classification class_chunk;
+ } class_u;
+} Classification_t;
+
+typedef struct {
+ uint32_t c1;
+ uint32_t c2;
+ uint32_t c3;
+ uint32_t c4;
+ uint32_t c5;
+ uint32_t c6;
+ uint32_t c7;
+ uint32_t c8;
+} Compartments_t;
+
+typedef struct {
+ uint32_t m1;
+ uint32_t m2;
+ uint32_t m3;
+ uint32_t m4;
+ uint32_t m5;
+ uint32_t m6;
+ uint32_t m7;
+ uint32_t m8;
+} Markings_t;
+
+typedef struct _mac_label_impl {
+ uint8_t id; /* Magic to say label type */
+ uint8_t _c_len; /* Number of Compartment words */
+ Classification_t classification;
+ Compartments_t compartments;
+} _mac_label_impl_t;
+
+typedef _mac_label_impl_t _blevel_impl_t, /* compatibility */
+ _bslabel_impl_t, /* Sensitivity Label */
+ _bclear_impl_t; /* Clearance */
+
+typedef struct _binary_information_label_impl { /* Information Label */
+ _mac_label_impl_t binformation_level;
+ Markings_t markings;
+} _bilabel_impl_t;
+
+typedef struct _binary_cmw_label_impl { /* CMW Label */
+ _bslabel_impl_t bcl_sensitivity_label;
+ _bilabel_impl_t bcl_information_label;
+} _bclabel_impl_t;
+
+typedef struct _binary_level_range_impl { /* Level Range */
+ _mac_label_impl_t lower_bound;
+ _mac_label_impl_t upper_bound;
+} _brange_impl_t, brange_t;
+
+/* Label Identifier Types */
+
+#define SUN_MAC_ID 0x41 /* MAC label, legacy SUN_SL_ID */
+#define SUN_UCLR_ID 0x49 /* User Clearance, legacy SUN_CLR_ID */
+
+#define _C_LEN 8 /* number of compartments words */
+
+/* m_label_t macros */
+#define _MTYPE(l, t) \
+ (((_mac_label_impl_t *)(l))->id == (t))
+
+#define _MSETTYPE(l, t) \
+ (((_mac_label_impl_t *)(l))->id = (t))
+
+#define _MGETTYPE(l) (((_mac_label_impl_t *)(l))->id)
+
+#define _MEQUAL(l1, l2) \
+ (LCLASS(l1) == LCLASS(l2) && \
+ (l1)->_comps.c1 == (l2)->_comps.c1 && \
+ (l1)->_comps.c2 == (l2)->_comps.c2 && \
+ (l1)->_comps.c3 == (l2)->_comps.c3 && \
+ (l1)->_comps.c4 == (l2)->_comps.c4 && \
+ (l1)->_comps.c5 == (l2)->_comps.c5 && \
+ (l1)->_comps.c6 == (l2)->_comps.c6 && \
+ (l1)->_comps.c7 == (l2)->_comps.c7 && \
+ (l1)->_comps.c8 == (l2)->_comps.c8)
+
+#define SUN_INVALID_ID 0 /* uninitialized label */
+#define SUN_CMW_ID 0x83 /* 104 - total bytes in CMW Label */
+#define SUN_SL_ID 0x41 /* 36 - total bytes in Sensitivity Label */
+#define SUN_SL_UN 0xF1 /* undefined Sensitivity Label */
+#define SUN_IL_ID 0x42 /* 68 - total bytes in Information Label */
+#define SUN_IL_UN 0x73 /* undefined Information Label */
+#define SUN_CLR_ID 0x49 /* 36 - total bytes in Clearance */
+#define SUN_CLR_UN 0xF9 /* undefined Clearance */
+
+#define _bcl_sl bcl_sensitivity_label
+#define _bcl_il bcl_information_label
+#define _bslev_il binformation_level
+
+#define _lclass classification
+#ifdef _BIG_ENDIAN
+#define LCLASS(slp) ((slp)->_lclass.class_u.class_chunk)
+#define LCLASS_SET(slp, l) ((slp)->_lclass.class_u.class_chunk = (l))
+#else
+#define LCLASS(slp) \
+ ((_Classification)(((slp)->_lclass.class_u.class_ar[0] << 8) | \
+ (slp)->_lclass.class_u.class_ar[1]))
+#define LCLASS_SET(slp, l) \
+ ((slp)->_lclass.class_u.class_ar[0] = (uint8_t)((l)>> 8), \
+ (slp)->_lclass.class_u.class_ar[1] = (uint8_t)(l))
+#endif /* _BIG_ENDIAN */
+#define _comps compartments
+
+#define _iid _bslev_il.id
+#define _i_c_len _bslev_il._c_len
+#define _iclass _bslev_il._lclass
+#ifdef _BIG_ENDIAN
+#define ICLASS(ilp) ((ilp)->_iclass.class_u.class_chunk)
+#define ICLASS_SET(ilp, l) ((ilp)->_iclass.class_u.class_chunk = (l))
+#else
+#define ICLASS(ilp) \
+ ((_Classification)(((ilp)->_iclass.class_u.class_ar[0] << 8) | \
+ (ilp)->_iclass.class_u.class_ar[1]))
+#define ICLASS_SET(ilp, l) \
+ ((ilp)->_iclass.class_u.class_ar[0] = (uint8_t)((l)>> 8), \
+ (ilp)->_iclass.class_u.class_ar[1] = (uint8_t)(l))
+#endif /* _BIG_ENDIAN */
+#define _icomps _bslev_il._comps
+#define _imarks markings
+
+/* Manifest Constant Values */
+
+#define LOW_CLASS 0 /* Admin_Low classification value */
+#define HIGH_CLASS 0x7FFF /* Admin_High classification value */
+#define EMPTY_SET 0 /* Empty compartments and markings set */
+#define UNIVERSAL_SET 0xFFFFFFFFU /* Universal compartments and */
+ /* markings set */
+
+/* Construct initial labels */
+
+#define _LOW_LABEL(l, t) \
+ ((l)->id = t, (l)->_c_len = _C_LEN, LCLASS_SET(l, LOW_CLASS), \
+ (l)->_comps.c1 = (l)->_comps.c2 = (l)->_comps.c3 = (l)->_comps.c4 = \
+ (l)->_comps.c5 = (l)->_comps.c6 = (l)->_comps.c7 = (l)->_comps.c8 = \
+ EMPTY_SET)
+
+#define _HIGH_LABEL(l, t) \
+ ((l)->id = t, (l)->_c_len = _C_LEN, LCLASS_SET(l, HIGH_CLASS), \
+ (l)->_comps.c1 = (l)->_comps.c2 = (l)->_comps.c3 = (l)->_comps.c4 = \
+ (l)->_comps.c5 = (l)->_comps.c6 = (l)->_comps.c7 = (l)->_comps.c8 = \
+ UNIVERSAL_SET)
+
+/* Macro equivalents */
+
+/* Is this memory a properly formatted label of type t? */
+#define BLTYPE(l, t) \
+ ((t) == SUN_CMW_ID ? \
+ (((_bclabel_impl_t *)(l))->_bcl_sl.id == SUN_SL_ID || \
+ ((_bclabel_impl_t *)(l))->_bcl_sl.id == SUN_SL_UN) && \
+ (((_bclabel_impl_t *)(l))->_bcl_il._iid == SUN_IL_ID || \
+ ((_bclabel_impl_t *)(l))->_bcl_il._iid == SUN_IL_UN) : \
+ ((_mac_label_impl_t *)(l))->id == (t))
+
+/* Are the levels of these labels equal? */
+#define BLEQUAL(l1, l2) \
+ _BLEQUAL((_mac_label_impl_t *)(l1), (_mac_label_impl_t *)(l2))
+
+#define _BLEQUAL(l1, l2) \
+ (LCLASS(l1) == LCLASS(l2) && \
+ (l1)->_comps.c1 == (l2)->_comps.c1 && \
+ (l1)->_comps.c2 == (l2)->_comps.c2 && \
+ (l1)->_comps.c3 == (l2)->_comps.c3 && \
+ (l1)->_comps.c4 == (l2)->_comps.c4 && \
+ (l1)->_comps.c5 == (l2)->_comps.c5 && \
+ (l1)->_comps.c6 == (l2)->_comps.c6 && \
+ (l1)->_comps.c7 == (l2)->_comps.c7 && \
+ (l1)->_comps.c8 == (l2)->_comps.c8)
+
+/* Does the level of l1 dominate that of l2? */
+#define BLDOMINATES(l1, l2) \
+ _BLDOMINATES((_mac_label_impl_t *)(l1), (_mac_label_impl_t *)(l2))
+
+#define _BLDOMINATES(l1, l2) (LCLASS(l1) >= LCLASS(l2) && \
+ (l2)->_comps.c1 == ((l1)->_comps.c1 & (l2)->_comps.c1) && \
+ (l2)->_comps.c2 == ((l1)->_comps.c2 & (l2)->_comps.c2) && \
+ (l2)->_comps.c3 == ((l1)->_comps.c3 & (l2)->_comps.c3) && \
+ (l2)->_comps.c4 == ((l1)->_comps.c4 & (l2)->_comps.c4) && \
+ (l2)->_comps.c5 == ((l1)->_comps.c5 & (l2)->_comps.c5) && \
+ (l2)->_comps.c6 == ((l1)->_comps.c6 & (l2)->_comps.c6) && \
+ (l2)->_comps.c7 == ((l1)->_comps.c7 & (l2)->_comps.c7) && \
+ (l2)->_comps.c8 == ((l1)->_comps.c8 & (l2)->_comps.c8))
+
+/* Does the level of l1 strictly dominate that of l2? */
+#define BLSTRICTDOM(l1, l2) (!BLEQUAL(l1, l2) && BLDOMINATES(l1, l2))
+
+/* Is the level of l within the range r? */
+#define BLINRANGE(l, r)\
+ (BLDOMINATES((l), &((r)->lower_bound)) && \
+ BLDOMINATES(&((r)->upper_bound), (l)))
+
+/* Least Upper Bound level l1 and l2 replacing l1 with the result. */
+#define BLMAXIMUM(l1, l2) \
+ _BLMAXIMUM((_mac_label_impl_t *)(l1), (_mac_label_impl_t *)(l2))
+
+#define _BLMAXIMUM(l1, l2)\
+ (((l1)->_lclass = (LCLASS(l1) < LCLASS(l2)) ? \
+ (l2)->_lclass : (l1)->_lclass), \
+ (l1)->_comps.c1 |= (l2)->_comps.c1, \
+ (l1)->_comps.c2 |= (l2)->_comps.c2, \
+ (l1)->_comps.c3 |= (l2)->_comps.c3, \
+ (l1)->_comps.c4 |= (l2)->_comps.c4, \
+ (l1)->_comps.c5 |= (l2)->_comps.c5, \
+ (l1)->_comps.c6 |= (l2)->_comps.c6, \
+ (l1)->_comps.c7 |= (l2)->_comps.c7, \
+ (l1)->_comps.c8 |= (l2)->_comps.c8)
+
+/* Greatest Lower Bound level l1 and l2 replacing l1 with the result. */
+#define BLMINIMUM(l1, l2) \
+ _BLMINIMUM((_mac_label_impl_t *)(l1), (_mac_label_impl_t *)(l2))
+
+#define _BLMINIMUM(l1, l2)\
+ (((l1)->_lclass = (LCLASS(l1) > LCLASS(l2)) ? \
+ (l2)->_lclass : (l1)->_lclass), \
+ (l1)->_comps.c1 &= (l2)->_comps.c1, \
+ (l1)->_comps.c2 &= (l2)->_comps.c2, \
+ (l1)->_comps.c3 &= (l2)->_comps.c3, \
+ (l1)->_comps.c4 &= (l2)->_comps.c4, \
+ (l1)->_comps.c5 &= (l2)->_comps.c5, \
+ (l1)->_comps.c6 &= (l2)->_comps.c6, \
+ (l1)->_comps.c7 &= (l2)->_comps.c7, \
+ (l1)->_comps.c8 &= (l2)->_comps.c8)
+
+/* Create Manifest Labels */
+
+/* Write a System_Low CMW Label into this memory. */
+#define BCLLOW(l) (BSLLOW(BCLTOSL(l)), BILLOW(BCLTOIL(l)))
+
+/* Write a System_Low Sensitivity Label into this memory. */
+#define BSLLOW(l) _BSLLOW((_bslabel_impl_t *)(l))
+
+#define _BSLLOW(l) \
+ ((l)->id = SUN_SL_ID, (l)->_c_len = _C_LEN, LCLASS_SET(l, LOW_CLASS), \
+ (l)->_comps.c1 = (l)->_comps.c2 = (l)->_comps.c3 = (l)->_comps.c4 = \
+ (l)->_comps.c5 = (l)->_comps.c6 = (l)->_comps.c7 = (l)->_comps.c8 = \
+ EMPTY_SET)
+
+/* Write a System_High Sensitivity Label into this memory. */
+#define BSLHIGH(l) _BSLHIGH((_bslabel_impl_t *)(l))
+
+#define _BSLHIGH(l) \
+ ((l)->id = SUN_SL_ID, (l)->_c_len = _C_LEN, LCLASS_SET(l, HIGH_CLASS), \
+ (l)->_comps.c1 = (l)->_comps.c2 = (l)->_comps.c3 = (l)->_comps.c4 = \
+ (l)->_comps.c5 = (l)->_comps.c6 = (l)->_comps.c7 = (l)->_comps.c8 = \
+ UNIVERSAL_SET)
+
+/* Write a System_Low Information Label into this memory. */
+#define BILLOW(l) _BILLOW((_bilabel_impl_t *)(l))
+
+#define _BILLOW(l) \
+ ((l)->_iid = SUN_IL_ID, (l)->_i_c_len = _C_LEN, \
+ ICLASS_SET(l, LOW_CLASS), \
+ (l)->_icomps.c1 = (l)->_icomps.c2 = (l)->_icomps.c3 = \
+ (l)->_icomps.c4 = (l)->_icomps.c5 = (l)->_icomps.c6 = \
+ (l)->_icomps.c7 = (l)->_icomps.c8 = EMPTY_SET, \
+ (l)->_imarks.m1 = (l)->_imarks.m2 = (l)->_imarks.m3 = \
+ (l)->_imarks.m4 = (l)->_imarks.m5 = (l)->_imarks.m6 = \
+ (l)->_imarks.m7 = (l)->_imarks.m8 = EMPTY_SET)
+
+
+/* Write a System_Low Sensitivity Label into this memory. */
+#define BCLEARLOW(l) _BCLEARLOW((_bclear_impl_t *)(l))
+
+#define _BCLEARLOW(c) \
+ ((c)->id = SUN_CLR_ID, (c)->_c_len = _C_LEN, \
+ LCLASS_SET(c, LOW_CLASS), \
+ (c)->_comps.c1 = (c)->_comps.c2 = (c)->_comps.c3 = (c)->_comps.c4 = \
+ (c)->_comps.c5 = (c)->_comps.c6 = (c)->_comps.c7 = (c)->_comps.c8 = \
+ EMPTY_SET)
+
+/* Write a System_High Sensitivity Label into this memory. */
+#define BCLEARHIGH(l) _BCLEARHIGH((_bclear_impl_t *)(l))
+
+#define _BCLEARHIGH(c) \
+ ((c)->id = SUN_CLR_ID, (c)->_c_len = _C_LEN, \
+ LCLASS_SET(c, HIGH_CLASS), \
+ (c)->_comps.c1 = (c)->_comps.c2 = (c)->_comps.c3 = (c)->_comps.c4 = \
+ (c)->_comps.c5 = (c)->_comps.c6 = (c)->_comps.c7 = (c)->_comps.c8 = \
+ UNIVERSAL_SET)
+
+/* Write an undefined Sensitivity Label into this memory. */
+#define BSLUNDEF(l) (((_bslabel_impl_t *)(l))->id = SUN_SL_UN)
+
+/* Write an undefined Clearance into this memory. */
+#define BCLEARUNDEF(c) (((_bclear_impl_t *)(c))->id = SUN_CLR_UN)
+
+/* Retrieve the Sensitivity Label portion of a CMW Label */
+#define BCLTOSL(l) ((bslabel_t *)&((_bclabel_impl_t *)(l))->_bcl_sl)
+
+/* Retrieve the Information Label portion of a CMW Label */
+#define BCLTOIL(l) ((_bilabel_impl_t *)&((_bclabel_impl_t *)(l))->_bcl_il)
+
+/* Copy the Sensitivity Label portion from a CMW Label */
+#define GETCSL(l1, l2) \
+ (*((_bslabel_impl_t *)(l1)) = ((_bclabel_impl_t *)(l2))->_bcl_sl)
+
+/* Replace the Sensitivity Label portion of a CMW Label */
+#define SETCSL(l1, l2) \
+ (((_bclabel_impl_t *)(l1))->_bcl_sl = *((_bslabel_impl_t *)(l2)))
+
+/* Set type of this memory to the label type 't' */
+#define SETBLTYPE(l, t) (((_bclabel_impl_t *)(l))->_bcl_sl.id = (t))
+
+#define GETBLTYPE(l) (((const _bclabel_impl_t *)(l))->_bcl_sl.id)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_LABEL_MACRO_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/tsol/priv.h Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,116 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_TSOL_PRIV_H
+#define _SYS_TSOL_PRIV_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/priv.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum priv_ftype {
+ PRIV_ALLOWED,
+ PRIV_FORCED
+} priv_ftype_t;
+
+/*
+ * Privilege macros.
+ */
+
+/*
+ * PRIV_ASSERT(a, b) setst.privilege "b" in privilege set "a".
+ */
+#define PRIV_ASSERT(a, b) (priv_addset(a, b))
+
+/*
+ * PRIV_CLEAR(a,b) clearst.privilege "b" in privilege set "a".
+ */
+#define PRIV_CLEAR(a, b) (priv_delset(a, b))
+
+/*
+ * PRIV_EQUAL(set_a, set_b) is true if set_a and set_b are identical.
+ */
+#define PRIV_EQUAL(a, b) (priv_isequalset(a, b))
+#define PRIV_EMPTY(a) (priv_emptyset(a))
+#define PRIV_FILL(a) (priv_fillset(a))
+
+/*
+ * PRIV_ISASSERT tests if privilege 'b' is asserted in privilege set 'a'.
+ */
+#define PRIV_ISASSERT(a, b) (priv_ismember(a, b))
+#define PRIV_ISEMPTY(a) (priv_isemptyset(a))
+#define PRIV_ISFULL(a) (priv_isfullset(a))
+
+/*
+ * This macro returns 1 if all privileges asserted in privilege set "a"
+ * are also asserted in privilege set "b" (i.e. if a is a subset of b)
+ */
+#define PRIV_ISSUBSET(a, b) (priv_issubset(a, b))
+
+/*
+ * Takes intersection of "a" and "b" and stores in "b".
+ */
+#define PRIV_INTERSECT(a, b) (priv_intersect(a, b))
+
+/*
+ * Replaces "a" with inverse of "a".
+ */
+#define PRIV_INVERSE(a) (priv_inverse(a))
+
+/*
+ * Takes union of "a" and "b" and stores in "b".
+ */
+#define PRIV_UNION(a, b) (priv_union(a, b))
+
+
+#define PRIV_FILE_UPGRADE_SL ((const char *)"file_upgrade_sl")
+#define PRIV_FILE_DOWNGRADE_SL ((const char *)"file_downgrade_sl")
+#
+#define PRIV_PROC_AUDIT_TCB ((const char *)"proc_audit")
+#define PRIV_PROC_AUDIT_APPL ((const char *)"proc_audit")
+#
+#define PRIV_SYS_TRANS_LABEL ((const char *)"sys_trans_label")
+#define PRIV_WIN_COLORMAP ((const char *)"win_colormap")
+#define PRIV_WIN_CONFIG ((const char *)"win_config")
+#define PRIV_WIN_DAC_READ ((const char *)"win_dac_read")
+#define PRIV_WIN_DAC_WRITE ((const char *)"win_dac_write")
+#define PRIV_WIN_DGA ((const char *)"win_dga")
+#define PRIV_WIN_DEVICES ((const char *)"win_devices")
+#define PRIV_WIN_DOWNGRADE_SL ((const char *)"win_downgrade_sl")
+#define PRIV_WIN_FONTPATH ((const char *)"win_fontpath")
+#define PRIV_WIN_MAC_READ ((const char *)"win_mac_read")
+#define PRIV_WIN_MAC_WRITE ((const char *)"win_mac_write")
+#define PRIV_WIN_SELECTION ((const char *)"win_selection")
+#define PRIV_WIN_UPGRADE_SL ((const char *)"win_upgrade_sl")
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_TSOL_PRIV_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/tsol/tndb.h Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,405 @@
+/*
+ * 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.
+ *
+ * from "tndb.h 7.34 01/08/31 SMI; TSOL 2.x"
+ */
+
+#ifndef _SYS_TSOL_TNDB_H
+#define _SYS_TSOL_TNDB_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <sys/tsol/label.h>
+#include <sys/tsol/label_macro.h>
+#include <net/if.h>
+
+#ifdef _KERNEL
+#include <net/route.h>
+#include <sys/zone.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* same on ILP32 and LP64 */
+typedef union tnaddr {
+ struct sockaddr_in ip_addr_v4;
+ struct sockaddr_in6 ip_addr_v6;
+} tnaddr_t;
+
+#define ta_family ip_addr_v4.sin_family
+#define ta_addr_v4 ip_addr_v4.sin_addr
+#define ta_addr_v6 ip_addr_v6.sin6_addr
+#define ta_port_v4 ip_addr_v4.sin_port
+#define ta_port_v6 ip_addr_v6.sin6_port
+
+#define TNADDR_EQ(addr1, addr2) \
+ (((addr1)->ta_family == AF_INET && (addr2)->ta_family == AF_INET && \
+ (addr1)->ta_addr_v4.s_addr == (addr2)->ta_addr_v4.s_addr) || \
+ ((addr1)->ta_family == AF_INET6 && (addr2)->ta_family == AF_INET6 && \
+ IN6_ARE_ADDR_EQUAL(&(addr1)->ta_addr_v6, &(addr2)->ta_addr_v6)))
+
+/*
+ * structure for TN database access routines and TN system calls
+ */
+
+typedef enum tsol_dbops {
+ TNDB_NOOP = 0,
+ TNDB_LOAD = 1,
+ TNDB_DELETE = 2,
+ TNDB_FLUSH = 3,
+ TNDB_GET = 5
+} tsol_dbops_t;
+
+#define TNTNAMSIZ 32 /* template name size */
+#define IP_STR_SIZE 200 /* string ip address size */
+
+#define TNRHDB_NCOL 2 /* # of columns in tnrhdb */
+
+/*
+ * For tnrhdb access library routines and tnrh(2TSOL)
+ * same for both ILP32 and LP64.
+ */
+typedef struct tsol_rhent {
+ short rh_prefix; /* length of subnet mask */
+ short rh_unused; /* padding */
+ tnaddr_t rh_address; /* IP address */
+ char rh_template[TNTNAMSIZ]; /* template name */
+} tsol_rhent_t;
+
+typedef struct tsol_rhstr_s {
+ int family;
+ char *address;
+ char *template;
+} tsol_rhstr_t;
+
+/*
+ * host types recognized by tsol hosts
+ */
+typedef enum {
+ UNLABELED = 1,
+ SUN_CIPSO = 3
+} tsol_host_type_t;
+
+typedef enum {
+ OPT_NONE = 0,
+ OPT_CIPSO = 1
+} tsol_ip_label_t;
+
+typedef struct cipso_tag_type_1 {
+ uchar_t tag_type; /* Tag Type (1) */
+ uchar_t tag_length; /* Length of Tag */
+ uchar_t tag_align; /* Alignment Octet */
+ uchar_t tag_sl; /* Sensitivity Level */
+ uchar_t tag_cat[1]; /* Categories */
+} cipso_tag_type_1_t;
+
+#define TSOL_CIPSO_MIN_LENGTH 6
+#define TSOL_CIPSO_MAX_LENGTH IP_MAX_OPT_LENGTH
+#define TSOL_TT1_MIN_LENGTH 4
+#define TSOL_TT1_MAX_LENGTH 34
+
+#define TSOL_CIPSO_DOI_OFFSET 2
+#define TSOL_CIPSO_TAG_OFFSET 6
+
+typedef struct cipso_option {
+ uchar_t cipso_type; /* Type of option (134) */
+ uchar_t cipso_length; /* Length of option */
+ uchar_t cipso_doi[4]; /* Domain of Interpretation */
+ uchar_t cipso_tag_type[1]; /* variable length */
+} cipso_option_t;
+
+/*
+ * RIPSO classifications
+ */
+#define TSOL_CL_TOP_SECRET 0x3d
+#define TSOL_CL_SECRET 0x5a
+#define TSOL_CL_CONFIDENTIAL 0x96
+#define TSOL_CL_UNCLASSIFIED 0xab
+
+/*
+ * RIPSO protection authorities
+ */
+#define TSOL_PA_GENSER 0x80
+#define TSOL_PA_SIOP_ESI 0x40
+#define TSOL_PA_SCI 0x20
+#define TSOL_PA_NSA 0x10
+#define TSOL_PA_DOE 0x08
+
+/*
+ * this mask is only used for tndb structures, and is different
+ * from t6mask_t bits definitions
+ */
+
+typedef unsigned int tnmask_t;
+
+/*
+ * unlabeled host structure for the tnrhtp template.
+ * same for both ILP32 and LP64.
+ */
+struct tsol_unl {
+ tnmask_t mask; /* tells which attributes are returned by the library */
+ bslabel_t def_label; /* default label */
+ brange_t gw_sl_range; /* for routing only */
+ blset_t sl_set; /* label set */
+};
+
+/*
+ * CIPSO host structure for the tnrhtp template
+ * same for both ILP32 and LP64.
+ */
+struct tsol_cipso {
+ tnmask_t mask; /* tells which attributes are returned by the library */
+ bclear_t def_cl; /* default clearance */
+ brange_t sl_range; /* min/max SL range */
+ blset_t sl_set; /* label set */
+};
+
+/*
+ * Valid keys and values of the key=value pairs for tnrhtp
+ */
+#define TP_UNLABELED "unlabeled"
+#define TP_CIPSO "cipso"
+#define TP_ZONE "zone"
+#define TP_HOSTTYPE "host_type"
+#define TP_DOI "doi"
+#define TP_DEFLABEL "def_label"
+#define TP_MINLABEL "min_sl"
+#define TP_MAXLABEL "max_sl"
+#define TP_SET "sl_set"
+
+#define TP_COMMA ","
+
+#define TNRHTP_NCOL 2 /* # of columns in tnrhtp */
+
+/*
+ * For tnrhtp access library routines and tnrhtp(2TSOL)
+ * same for both ILP32 and LP64.
+ */
+typedef struct tsol_tpent {
+ char name[TNTNAMSIZ]; /* template name */
+ tsol_host_type_t host_type; /* specifies host type */
+ int tp_doi; /* Domain of Interpretation */
+#define tp_cipso_doi_unl tp_doi
+#define tp_cipso_doi_cipso tp_doi
+ union {
+ struct tsol_unl unl; /* template for unlabeled */
+#define tp_mask_unl un.unl.mask
+#define tp_def_label un.unl.def_label
+#define tp_gw_sl_range un.unl.gw_sl_range
+#define tp_gw_sl_set un.unl.sl_set
+
+ struct tsol_cipso cipso; /* template for CIPSO */
+#define tp_mask_cipso un.cipso.mask
+#define tp_def_cl_cipso un.cipso.def_cl
+#define tp_sl_range_cipso un.cipso.sl_range
+#define tp_sl_set_cipso un.cipso.sl_set
+ } un;
+} tsol_tpent_t;
+
+typedef struct tsol_tpstr_s {
+ char *template;
+ char *attrs;
+} tsol_tpstr_t;
+
+/*
+ * For tnmlp(2TSOL); same for both ILP32 and LP64.
+ */
+typedef struct tsol_mlpent {
+ zoneid_t tsme_zoneid;
+ uint_t tsme_flags; /* TSOL_MEF_* */
+ tsol_mlp_t tsme_mlp;
+} tsol_mlpent_t;
+
+#define TSOL_MEF_SHARED 0x00000001 /* MLP defined on shared addresses */
+
+/*
+ * For tnzonecfg access library routines.
+ * List of MLPs ends with null entry, where protocol and port are both zero.
+ */
+typedef struct tsol_zcent {
+ char zc_name[TNTNAMSIZ];
+ int zc_doi;
+ bslabel_t zc_label;
+ int zc_match;
+ tsol_mlp_t *zc_private_mlp;
+ tsol_mlp_t *zc_shared_mlp;
+} tsol_zcent_t;
+#define TSOL_MLP_END(mlp) ((mlp)->mlp_ipp == 0 && (mlp)->mlp_port == 0)
+
+typedef struct tsol_tpc {
+ kmutex_t tpc_lock; /* lock for structure */
+ uint_t tpc_refcnt; /* reference count */
+ boolean_t tpc_invalid; /* entry has been deleted */
+ struct tsol_tpent tpc_tp; /* template */
+} tsol_tpc_t;
+
+typedef struct tsol_tnrhc {
+ struct tsol_tnrhc *rhc_next; /* link to next entry */
+ kmutex_t rhc_lock; /* lock for structure */
+ tnaddr_t rhc_host; /* IPv4/IPv6 host address */
+ tsol_tpc_t *rhc_tpc; /* pointer to template */
+ uint_t rhc_refcnt; /* Number of references */
+ char rhc_invalid; /* out-of-date rhc */
+ char rhc_isbcast; /* broadcast address */
+ char rhc_local; /* loopback or local interace */
+} tsol_tnrhc_t;
+
+/* Size of remote host hash tables in kernel */
+#define TNRHC_SIZE 256
+#define TSOL_MASK_TABLE_SIZE 33
+#define TSOL_MASK_TABLE_SIZE_V6 129
+
+#ifdef _KERNEL
+#define TNRHC_HOLD(a) { \
+ mutex_enter(&(a)->rhc_lock); \
+ (a)->rhc_refcnt++; \
+ ASSERT((a)->rhc_refcnt > 0); \
+ mutex_exit(&(a)->rhc_lock); \
+}
+#define TNRHC_RELE(a) { \
+ mutex_enter(&(a)->rhc_lock); \
+ ASSERT((a)->rhc_refcnt > 0); \
+ if (--(a)->rhc_refcnt <= 0) \
+ tnrhc_free(a); \
+ else \
+ mutex_exit(&(a)->rhc_lock); \
+}
+extern void tnrhc_free(tsol_tnrhc_t *);
+#define TPC_HOLD(a) { \
+ mutex_enter(&(a)->tpc_lock); \
+ (a)->tpc_refcnt++; \
+ ASSERT((a)->tpc_refcnt > 0); \
+ mutex_exit(&(a)->tpc_lock); \
+}
+#define TPC_RELE(a) { \
+ mutex_enter(&(a)->tpc_lock); \
+ ASSERT((a)->tpc_refcnt > 0); \
+ if (--(a)->tpc_refcnt <= 0) \
+ tpc_free(a); \
+ else \
+ mutex_exit(&(a)->tpc_lock); \
+}
+extern void tpc_free(tsol_tpc_t *);
+#endif /* _KERNEL */
+
+/*
+ * The next three hashing macros are copied from macros in ip_ire.h.
+ */
+#define TSOL_ADDR_HASH(addr, table_size) \
+ (((((addr) >> 16) ^ (addr)) ^ ((((addr) >> 16) ^ (addr))>> 8)) \
+ % (table_size))
+
+#define TSOL_ADDR_HASH_V6(addr, table_size) \
+ (((addr).s6_addr8[8] ^ (addr).s6_addr8[9] ^ \
+ (addr).s6_addr8[10] ^ (addr).s6_addr8[13] ^ \
+ (addr).s6_addr8[14] ^ (addr).s6_addr8[15]) % (table_size))
+
+/* This assumes that table_size is a power of 2. */
+#define TSOL_ADDR_MASK_HASH_V6(addr, mask, table_size) \
+ ((((addr).s6_addr8[8] & (mask).s6_addr8[8]) ^ \
+ ((addr).s6_addr8[9] & (mask).s6_addr8[9]) ^ \
+ ((addr).s6_addr8[10] & (mask).s6_addr8[10]) ^ \
+ ((addr).s6_addr8[13] & (mask).s6_addr8[13]) ^ \
+ ((addr).s6_addr8[14] & (mask).s6_addr8[14]) ^ \
+ ((addr).s6_addr8[15] & (mask).s6_addr8[15])) & ((table_size) - 1))
+
+
+/*
+ * Constants used for getting the mask value in struct tsol_tpent
+ */
+enum {
+ TNT_DEF_LABEL,
+ TNT_DEF_CL,
+ TNT_SL_RANGE_TSOL, /* use this for both unl and zone */
+ TNT_CIPSO_DOI
+};
+
+/*
+ * mask definitions
+ */
+#define tsol_tntmask(value) ((unsigned int)(1<<(value)))
+
+#define TSOL_MSK_DEF_LABEL tsol_tntmask(TNT_DEF_LABEL)
+#define TSOL_MSK_DEF_CL tsol_tntmask(TNT_DEF_CL)
+#define TSOL_MSK_SL_RANGE_TSOL tsol_tntmask(TNT_SL_RANGE_TSOL)
+#define TSOL_MSK_CIPSO_DOI tsol_tntmask(TNT_CIPSO_DOI)
+
+/*
+ * TN errors
+ */
+#define TSOL_PARSE_ERANGE 1 /* result buffer not allocated */
+#define TSOL_NOT_SUPPORTED 2 /* address family not supported */
+#define TSOL_NOT_FOUND 3 /* search by * routines target not found */
+
+/*
+ * Structure used to hold a list of IP addresses.
+ */
+typedef struct tsol_address {
+ struct tsol_address *next;
+ in_addr_t ip_address;
+} tsol_address_t;
+
+/* This is shared between tcache and mdb */
+typedef struct tnrhc_hash_s {
+ tsol_tnrhc_t *tnrh_list;
+ kmutex_t tnrh_lock;
+} tnrhc_hash_t;
+
+#ifdef _KERNEL
+typedef enum {
+ mlptSingle,
+ mlptPrivate,
+ mlptShared,
+ mlptBoth
+} mlp_type_t;
+
+extern tsol_tpc_t *find_tpc(const void *, uchar_t, boolean_t);
+extern void tcache_init(void);
+extern in_port_t tsol_next_port(zone_t *, in_port_t, int, boolean_t);
+extern mlp_type_t tsol_mlp_port_type(zone_t *, uchar_t, uint16_t, mlp_type_t);
+extern zoneid_t tsol_mlp_findzone(uchar_t, uint16_t);
+extern int tsol_mlp_anon(zone_t *, mlp_type_t, uchar_t, uint16_t, boolean_t);
+extern void tsol_print_label(const blevel_t *, const char *);
+
+struct tsol_gc_s;
+struct tsol_gcgrp_s;
+struct tsol_gcgrp_addr_s;
+
+extern struct tsol_gc_s *gc_create(struct rtsa_s *, struct tsol_gcgrp_s *,
+ boolean_t *);
+extern void gc_inactive(struct tsol_gc_s *);
+extern int rtsa_validate(const struct rtsa_s *);
+extern struct tsol_gcgrp_s *gcgrp_lookup(struct tsol_gcgrp_addr_s *, boolean_t);
+extern void gcgrp_inactive(struct tsol_gcgrp_s *);
+extern int tnrh_load(const tsol_rhent_t *);
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_TSOL_TNDB_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/tsol/tnet.h Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ *
+ * from "tnet.h 7.44 02/10/09 SMI; TSOL 2.x"
+ */
+
+#ifndef _SYS_TSOL_TNET_H
+#define _SYS_TSOL_TNET_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <sys/stream.h>
+#include <sys/tsol/label.h>
+#include <sys/tsol/tndb.h>
+#include <netinet/in.h>
+#include <inet/ip.h>
+#include <net/route.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _KERNEL
+/* Maximum label returned by tsol_compute_label_v6 */
+#define TSOL_MAX_IPV6_OPTION (8 + IP_MAX_OPT_LENGTH)
+
+extern int tsol_tnrh_chk(tsol_tpent_t *, bslabel_t *, int);
+extern tsol_tnrhc_t *find_rhc_v4(const in_addr_t *);
+extern tsol_tnrhc_t *find_rhc_v6(const in6_addr_t *);
+extern int tsol_compute_label(const cred_t *, ipaddr_t, uchar_t *, boolean_t);
+extern int tsol_compute_label_v6(const cred_t *, const in6_addr_t *, uchar_t *,
+ boolean_t);
+extern int tsol_check_label(const cred_t *, mblk_t **, int *, boolean_t);
+extern int tsol_check_label_v6(const cred_t *, mblk_t **, int *, boolean_t);
+extern int tsol_prepend_option(uchar_t *, ipha_t *, int);
+extern int tsol_prepend_option_v6(uchar_t *, ip6_t *, int);
+extern int tsol_remove_secopt(ipha_t *, int);
+extern int tsol_remove_secopt_v6(ip6_t *, int);
+extern int tsol_update_sticky(ip6_pkt_t *, uint_t *, const uchar_t *);
+extern int tsol_update_options(uchar_t **, uint_t *, uint_t *,
+ const uchar_t *);
+extern boolean_t tsol_option_set(uchar_t **, uint_t *, uint_t, const uchar_t *,
+ uint_t);
+
+extern tsol_ire_gw_secattr_t *ire_gw_secattr_alloc(int);
+extern void ire_gw_secattr_free(tsol_ire_gw_secattr_t *);
+
+extern boolean_t tsol_can_reply_error(const mblk_t *);
+extern boolean_t tsol_receive_local(const mblk_t *, const void *, uchar_t,
+ boolean_t, const conn_t *);
+extern boolean_t tsol_can_accept_raw(mblk_t *, boolean_t);
+extern boolean_t tsol_get_pkt_label(mblk_t *, int);
+extern zoneid_t tsol_packet_to_zoneid(const mblk_t *);
+
+extern tsol_ip_label_t tsol_get_option(mblk_t *, uint8_t **);
+extern uchar_t *tsol_find_secopt_v6(const uchar_t *, uint_t, uchar_t **,
+ boolean_t *);
+
+extern int tsol_ire_match_gwattr(ire_t *, const ts_label_t *);
+extern int tsol_rtsa_init(rt_msghdr_t *, tsol_rtsecattr_t *, caddr_t);
+extern int tsol_ire_init_gwattr(ire_t *, uchar_t, tsol_gc_t *, tsol_gcgrp_t *);
+extern mblk_t *tsol_ip_forward(ire_t *, mblk_t *);
+
+extern mlp_type_t tsol_mlp_addr_type(zoneid_t, uchar_t, const void *);
+extern boolean_t tsol_check_interface_address(const ipif_t *);
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_TSOL_TNET_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/tsol/tsyscall.h Fri Mar 24 12:29:20 2006 -0800
@@ -0,0 +1,50 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_TSOL_TSYSCALL_H
+#define _SYS_TSOL_TSYSCALL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * the defines for subcode of labelsys system call.
+ */
+
+#define TSOL_SYSLABELING 1
+#define TSOL_TNRH 2
+#define TSOL_TNRHTP 3
+#define TSOL_TNMLP 4
+#define TSOL_GETLABEL 5
+#define TSOL_FGETLABEL 6
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_TSOL_TSYSCALL_H */
--- a/usr/src/uts/common/sys/ucred.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/sys/ucred.h Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*
* File with private definitions for the ucred structure for use by the
@@ -36,6 +35,8 @@
#include <sys/procfs.h>
#include <sys/cred.h>
#include <sys/priv.h>
+#include <sys/tsol/label.h>
+#include <sys/tsol/label_macro.h>
#ifdef _KERNEL
#include <c2/audit.h>
@@ -67,6 +68,7 @@
uint32_t uc_audoff; /* Audit info offset: 0 - no aud */
zoneid_t uc_zoneid; /* Zone id */
projid_t uc_projid; /* Project id */
+ uint32_t uc_labeloff; /* label offset: 0 - no label */
/* The rest goes here */
};
@@ -82,6 +84,10 @@
#define UCAUD(uc) (auditinfo64_addr_t *)(((uc)->uc_audoff == 0) ? NULL : \
((char *)(uc)) + (uc)->uc_audoff)
+/* Get peer security label info */
+#define UCLABEL(uc) (bslabel_t *)(((uc)->uc_labeloff == 0) ? NULL : \
+ ((char *)(uc)) + (uc)->uc_labeloff)
+
#define UCRED_CRED_OFF (sizeof (struct ucred_s))
#endif /* _KERNEL || _STRUCTURED_PROC != 0 */
@@ -99,12 +105,14 @@
#define UCRED_PRIV_OFF (UCRED_CRED_OFF + sizeof (prcred_t) + \
(ngroups_max - 1) * sizeof (gid_t))
#define UCRED_AUD_OFF (UCRED_PRIV_OFF + priv_prgetprivsize(NULL))
-#define UCRED_SIZE (UCRED_AUD_OFF + get_audit_ucrsize())
+#define UCRED_LABEL_OFF (UCRED_AUD_OFF + get_audit_ucrsize())
+#define UCRED_SIZE (UCRED_LABEL_OFF + sizeof (bslabel_t))
struct proc;
extern struct ucred_s *pgetucred(struct proc *);
-extern struct ucred_s *cred2ucred(const cred_t *, pid_t, void *);
+extern struct ucred_s *cred2ucred(const cred_t *, pid_t, void *,
+ const cred_t *);
extern int get_audit_ucrsize(void);
#else
@@ -117,7 +125,8 @@
sizeof (priv_chunk_t) * \
((ip)->priv_setsize * (ip)->priv_nsets - 1) + \
(ip)->priv_infosize + \
- sizeof (auditinfo64_addr_t))
+ sizeof (auditinfo64_addr_t) + \
+ sizeof (bslabel_t))
#endif
extern struct ucred_s *_ucred_alloc(void);
--- a/usr/src/uts/common/sys/zone.h Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/sys/zone.h Fri Mar 24 12:29:20 2006 -0800
@@ -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,6 +33,7 @@
#include <sys/param.h>
#include <sys/rctl.h>
#include <sys/pset.h>
+#include <sys/tsol/label.h>
#ifdef __cplusplus
extern "C" {
@@ -57,6 +57,11 @@
#define GLOBAL_ZONEID 0
#define ZONEID_WIDTH 4 /* for printf */
+/*
+ * Special zoneid_t token to refer to all zones.
+ */
+#define ALL_ZONES (-1)
+
/* system call subcodes */
#define ZONE_CREATE 0
#define ZONE_DESTROY 1
@@ -76,6 +81,7 @@
#define ZONE_ATTR_UNIQID 5
#define ZONE_ATTR_POOLID 6
#define ZONE_ATTR_INITPID 7
+#define ZONE_ATTR_SLBL 8
#define ZONE_EVENT_CHANNEL "com.sun:zones:status"
#define ZONE_EVENT_STATUS_CLASS "status"
@@ -103,6 +109,9 @@
caddr32_t extended_error;
caddr32_t zfsbuf;
size32_t zfsbufsz;
+ int match;
+ int doi;
+ caddr32_t label;
} zone_def32;
#endif
typedef struct {
@@ -115,6 +124,9 @@
int *extended_error;
const char *zfsbuf;
size_t zfsbufsz;
+ int match; /* match level */
+ int doi; /* DOI for label */
+ const bslabel_t *label; /* label associated with zone */
} zone_def;
/* extended error information */
@@ -192,7 +204,6 @@
*/
#define ZONE_DOOR_PATH ZONES_TMPDIR "/%s.zoneadmd_door"
-
#ifdef _KERNEL
/*
* We need to protect the definition of 'list_t' from userland applications and
@@ -293,6 +304,10 @@
* List of ZFS datasets exported to this zone.
*/
list_t zone_datasets; /* list of datasets */
+
+ ts_label_t *zone_slabel;
+ int zone_match;
+ tsol_mlp_list_t zone_mlps; /* MLPs on zone-private addresses */
} zone_t;
/*
@@ -317,8 +332,10 @@
extern void zone_task_hold(zone_t *);
extern void zone_task_rele(zone_t *);
extern zone_t *zone_find_by_id(zoneid_t);
+extern zone_t *zone_find_by_label(const ts_label_t *);
extern zone_t *zone_find_by_name(char *);
extern zone_t *zone_find_by_path(const char *);
+extern zone_t *zone_find_by_any_path(const char *, boolean_t);
extern zoneid_t getzoneid(void);
/*
@@ -401,11 +418,6 @@
#define ZONE_SPECIALPID(x) ((x) == 0 || (x) == 1)
/*
- * Special zoneid_t token to refer to all zones.
- */
-#define ALL_ZONES (-1)
-
-/*
* Zone-safe version of thread_create() to be used when the caller wants to
* create a kernel thread to run within the current zone's context.
*/
--- a/usr/src/uts/common/syscall/ppriv.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/syscall/ppriv.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -33,7 +32,6 @@
#include <sys/cred_impl.h>
#include <sys/errno.h>
#include <sys/proc.h>
-#include <sys/debug.h>
#include <sys/priv_impl.h>
#include <sys/policy.h>
#include <sys/ddi.h>
@@ -210,22 +208,27 @@
}
/*
- * Set privilege flags
+ * Set process flags in the given target cred. If NULL is specified, then
+ * CRED() is used; otherwise the cred is assumed to be modifiable (i.e. newly
+ * crdup'ed, or equivalent). Some flags are set in the proc rather than cred;
+ * for these, curproc is always used.
*
* For now we cheat: the flags are actually bit masks so we can simplify
* some; we do make sure that the arguments are valid, though.
*/
-static int
-setpflags(uint_t flag, uint_t val)
+int
+setpflags(uint_t flag, uint_t val, cred_t *tcr)
{
cred_t *cr, *pcr;
proc_t *p = curproc;
uint_t newflags;
+ boolean_t use_curcred = (tcr == NULL);
if (val > 1 || (flag != PRIV_DEBUG && flag != PRIV_AWARE &&
+ flag != NET_MAC_AWARE && flag != NET_MAC_AWARE_INHERIT &&
flag != __PROC_PROTECT)) {
- return (set_errno(EINVAL));
+ return (EINVAL);
}
if (flag == __PROC_PROTECT) {
@@ -238,11 +241,13 @@
return (0);
}
- cr = cralloc();
-
- mutex_enter(&p->p_crlock);
-
- pcr = p->p_cred;
+ if (use_curcred) {
+ cr = cralloc();
+ mutex_enter(&p->p_crlock);
+ pcr = p->p_cred;
+ } else {
+ cr = pcr = tcr;
+ }
newflags = CR_FLAGS(pcr);
@@ -253,20 +258,38 @@
/* No change */
if (CR_FLAGS(pcr) == newflags) {
- mutex_exit(&p->p_crlock);
- crfree(cr);
+ if (use_curcred) {
+ mutex_exit(&p->p_crlock);
+ crfree(cr);
+ }
return (0);
}
+ /*
+ * Need net_mac_aware priv to turn either net_mac_aware* flag on
+ * current cred.
+ */
+ if ((flag == NET_MAC_AWARE || flag == NET_MAC_AWARE_INHERIT) &&
+ (val == 1) && use_curcred) {
+ if (secpolicy_net_mac_aware(cr) != 0) {
+ mutex_exit(&p->p_crlock);
+ crfree(cr);
+ return (EPERM);
+ }
+ }
+
/* Trying to unset PA; if we can't, return an error */
if (flag == PRIV_AWARE && val == 0 && !priv_can_clear_PA(pcr)) {
- mutex_exit(&p->p_crlock);
- crfree(cr);
- return (set_errno(EPERM));
+ if (use_curcred) {
+ mutex_exit(&p->p_crlock);
+ crfree(cr);
+ }
+ return (EPERM);
}
/* Committed to changing the flag */
- crcopy_to(pcr, cr);
+ if (use_curcred)
+ crcopy_to(pcr, cr);
if (flag == PRIV_AWARE) {
if (val != 0)
priv_set_PA(cr);
@@ -276,11 +299,11 @@
CR_FLAGS(cr) = newflags;
}
- p->p_cred = cr;
-
- mutex_exit(&p->p_crlock);
-
- crset(p, cr);
+ if (use_curcred) {
+ p->p_cred = cr;
+ mutex_exit(&p->p_crlock);
+ crset(p, cr);
+ }
return (0);
}
@@ -288,13 +311,14 @@
/*
* Getpflags. Currently only implements single bit flags.
*/
-static uint_t
-getpflags(uint_t flag)
+uint_t
+getpflags(uint_t flag, const cred_t *cr)
{
- if (flag != PRIV_DEBUG && flag != PRIV_AWARE)
- return (set_errno(EINVAL));
+ if (flag != PRIV_DEBUG && flag != PRIV_AWARE &&
+ flag != NET_MAC_AWARE && flag != NET_MAC_AWARE_INHERIT)
+ return ((uint_t)-1);
- return ((CR_FLAGS(CRED()) & flag) != 0);
+ return ((CR_FLAGS(cr) & flag) != 0);
}
/*
@@ -303,6 +327,8 @@
int
privsys(int code, priv_op_t op, priv_ptype_t type, void *buf, size_t bufsize)
{
+ int retv;
+
switch (code) {
case PRIVSYS_SETPPRIV:
if (bufsize < sizeof (priv_set_t))
@@ -315,10 +341,11 @@
case PRIVSYS_GETIMPLINFO:
return (getprivimplinfo(buf, bufsize));
case PRIVSYS_SETPFLAGS:
- return (setpflags((uint_t)op, (uint_t)type));
+ retv = setpflags((uint_t)op, (uint_t)type, NULL);
+ return (retv != 0 ? set_errno(retv) : 0);
case PRIVSYS_GETPFLAGS:
- return ((int)getpflags((uint_t)op));
-
+ retv = (int)getpflags((uint_t)op, CRED());
+ return (retv == -1 ? set_errno(EINVAL) : retv);
}
return (set_errno(EINVAL));
}
--- a/usr/src/uts/common/syscall/sendfile.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/syscall/sendfile.c Fri Mar 24 12:29:20 2006 -0800
@@ -54,6 +54,11 @@
#include <sys/socket.h>
#include <sys/socketvar.h>
+/* swilly code in sys/socketvar.h turns off DEBUG */
+#ifdef __lint
+#define DEBUG
+#endif
+
#include <netinet/in.h>
#include <sys/sendfile.h>
#include <sys/un.h>
--- a/usr/src/uts/common/syscall/ucredsys.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/common/syscall/ucredsys.c Fri Mar 24 12:29:20 2006 -0800
@@ -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.
*/
@@ -111,7 +110,7 @@
if (kpc.pc_cr != NULL) {
ASSERT(err == 0);
- uc = cred2ucred(kpc.pc_cr, kpc.pc_cpid, NULL);
+ uc = cred2ucred(kpc.pc_cr, kpc.pc_cpid, NULL, CRED());
crfree(kpc.pc_cr);
@@ -172,7 +171,7 @@
return (set_errno(err));
}
- uc = cred2ucred(pcr, pid, NULL);
+ uc = cred2ucred(pcr, pid, NULL, CRED());
crfree(pcr);
--- a/usr/src/uts/i86pc/os/startup.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/i86pc/os/startup.c Fri Mar 24 12:29:20 2006 -0800
@@ -49,18 +49,14 @@
#include <sys/kstat.h>
#include <sys/reboot.h>
-#include <sys/uadmin.h>
#include <sys/cred.h>
#include <sys/vnode.h>
#include <sys/file.h>
#include <sys/procfs.h>
-#include <sys/acct.h>
#include <sys/vfs.h>
-#include <sys/dnlc.h>
-#include <sys/var.h>
#include <sys/cmn_err.h>
#include <sys/utsname.h>
#include <sys/debug.h>
@@ -70,12 +66,8 @@
#include <sys/bootconf.h>
#include <sys/varargs.h>
#include <sys/promif.h>
-#include <sys/prom_emul.h> /* for create_prom_prop */
#include <sys/modctl.h> /* for "procfs" hack */
-#include <sys/consdev.h>
-#include <sys/frame.h>
-
#include <sys/sunddi.h>
#include <sys/sunndi.h>
#include <sys/ndi_impldefs.h>
@@ -84,11 +76,9 @@
#include <sys/regset.h>
#include <sys/clock.h>
#include <sys/pte.h>
-#include <sys/mmu.h>
#include <sys/tss.h>
#include <sys/stack.h>
#include <sys/trap.h>
-#include <sys/pic.h>
#include <sys/fp.h>
#include <vm/anon.h>
#include <vm/as.h>
@@ -102,7 +92,6 @@
#include <vm/seg_kp.h>
#include <sys/memnode.h>
#include <vm/vm_dep.h>
-#include <sys/swap.h>
#include <sys/thread.h>
#include <sys/sysconf.h>
#include <sys/vm_machparam.h>
@@ -111,14 +100,12 @@
#include <vm/hat.h>
#include <vm/hat_i86.h>
#include <sys/pmem.h>
-#include <sys/instance.h>
#include <sys/smp_impldefs.h>
#include <sys/x86_archext.h>
#include <sys/segments.h>
#include <sys/clconf.h>
#include <sys/kobj.h>
#include <sys/kobj_lex.h>
-#include <sys/prom_emul.h>
#include <sys/cpc_impl.h>
#include <sys/chip.h>
#include <sys/x86_archext.h>
@@ -1365,6 +1352,8 @@
if (modload("fs", "devfs") == -1)
halt("Can't load devfs");
+ (void) modloadonly("sys", "lbl_edition");
+
dispinit();
/*
@@ -2411,7 +2400,7 @@
int enable_relaxed_mtrr = 0;
void
-setup_mtrr()
+setup_mtrr(void)
{
int i, ecx;
int vcnt;
@@ -2463,7 +2452,7 @@
* On other cpu's its invoked from mp_startup().
*/
void
-mtrr_sync()
+mtrr_sync(void)
{
uint_t crvalue, cr0_orig;
int vcnt, i, ecx;
@@ -2512,7 +2501,7 @@
* resync mtrr so that BIOS is happy. Called from mdboot
*/
void
-mtrr_resync()
+mtrr_resync(void)
{
if ((x86_feature & X86_PAT) && enable_relaxed_mtrr) {
/*
@@ -2525,7 +2514,7 @@
}
void
-get_system_configuration()
+get_system_configuration(void)
{
char prop[32];
u_longlong_t nodes_ll, cpus_pernode_ll, lvalue;
--- a/usr/src/uts/req.flg Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/req.flg Fri Mar 24 12:29:20 2006 -0800
@@ -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,7 +20,6 @@
#
# CDDL HEADER END
#
-#
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -52,3 +51,4 @@
find_files "s.*" usr/src/common/acl
find_files "s.*" usr/src/common/zfs
find_files "s.*" usr/src/common/smbios
+find_files "s.*" usr/src/common/tsol
--- a/usr/src/uts/sun4/os/startup.c Thu Mar 23 19:49:27 2006 -0800
+++ b/usr/src/uts/sun4/os/startup.c Fri Mar 24 12:29:20 2006 -0800
@@ -1638,6 +1638,8 @@
if (modloadonly("misc", "swapgeneric") == -1)
halt("Can't load swapgeneric");
+ (void) modloadonly("sys", "lbl_edition");
+
dispinit();
/*