summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/Makefile.lint2
-rw-r--r--usr/src/Targetdirs10
-rw-r--r--usr/src/cmd/Makefile2
-rw-r--r--usr/src/cmd/Makefile.check3
-rw-r--r--usr/src/cmd/iscsi/Makefile70
-rw-r--r--usr/src/cmd/iscsi/Makefile.iscsi30
-rw-r--r--usr/src/cmd/iscsi/iscsitadm/Makefile68
-rw-r--r--usr/src/cmd/iscsi/iscsitadm/cmdparse.c934
-rw-r--r--usr/src/cmd/iscsi/iscsitadm/cmdparse.h283
-rw-r--r--usr/src/cmd/iscsi/iscsitadm/helper.c517
-rw-r--r--usr/src/cmd/iscsi/iscsitadm/helper.h91
-rw-r--r--usr/src/cmd/iscsi/iscsitadm/main.c1674
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/Makefile94
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/Makefile.com91
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/amd64/Makefile31
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/errcode.h126
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/i386/Makefile31
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/iscsi.d248
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/iscsi_authclient.c3042
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/iscsi_authglue.c374
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/iscsi_cmd.c381
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/iscsi_cmd.h170
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/iscsi_conn.c1591
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/iscsi_conn.h216
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/iscsi_crc.c205
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/iscsi_ffp.c1129
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/iscsi_ffp.h45
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/iscsi_login.c949
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/iscsi_login.h42
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/iscsi_provider.d107
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/iscsi_provider_impl.h70
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/iscsi_sess.c785
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/iscsi_sess.h142
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/iscsi_target.xml116
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/isns.c702
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/isns_client.c1830
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/isns_client.h179
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/isns_protocol.h200
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/main.c940
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/mgmt.c260
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c1447
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/mgmt_list.c508
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/mgmt_modify.c1191
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c555
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/mgmt_scf.c1647
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/mgmt_scf.h101
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/port.h48
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/queue.h289
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/radius.c514
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/radius.h243
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/sparcv9/Makefile32
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/svc-iscsitgt64
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/t10.h663
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/t10_osd.c596
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/t10_osd.h174
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/t10_raw_if.c1572
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/t10_sam.c2790
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/t10_sbc.c2311
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/t10_sbc.h198
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/t10_spc.c1198
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/t10_spc.h460
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.c2126
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.h165
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/t10_ssc.c1646
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/t10_ssc.h317
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/target.h258
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/util.c1844
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/util_err.c211
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/util_ifname.c342
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/util_port.c265
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/util_queue.c493
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/utility.h104
-rw-r--r--usr/src/cmd/svc/shell/mfsthistory4
-rw-r--r--usr/src/cmd/truss/codes.c2
-rw-r--r--usr/src/cmd/zfs/zfs_main.c119
-rw-r--r--usr/src/common/zfs/zfs_prop.c4
-rw-r--r--usr/src/lib/Makefile4
-rw-r--r--usr/src/lib/libiscsitgt/Makefile56
-rw-r--r--usr/src/lib/libiscsitgt/Makefile.com54
-rw-r--r--usr/src/lib/libiscsitgt/amd64/Makefile31
-rw-r--r--usr/src/lib/libiscsitgt/common/gen.c266
-rw-r--r--usr/src/lib/libiscsitgt/common/if_gen.c48
-rw-r--r--usr/src/lib/libiscsitgt/common/if_zfs.c155
-rw-r--r--usr/src/lib/libiscsitgt/common/iscsitgt_impl.h211
-rw-r--r--usr/src/lib/libiscsitgt/common/libiscsitgt.h578
-rw-r--r--usr/src/lib/libiscsitgt/common/llib-liscsitgt30
-rw-r--r--usr/src/lib/libiscsitgt/common/mapfile-vers72
-rw-r--r--usr/src/lib/libiscsitgt/common/xml.c914
-rw-r--r--usr/src/lib/libiscsitgt/i386/Makefile30
-rw-r--r--usr/src/lib/libiscsitgt/sparc/Makefile30
-rw-r--r--usr/src/lib/libiscsitgt/sparcv9/Makefile31
-rw-r--r--usr/src/lib/libsecdb/auth_attr.txt4
-rw-r--r--usr/src/lib/libsecdb/exec_attr.txt1
-rw-r--r--usr/src/lib/libsecdb/help/auths/Makefile1
-rw-r--r--usr/src/lib/libsecdb/prof_attr.txt2
-rw-r--r--usr/src/lib/libzfs/common/libzfs.h7
-rw-r--r--usr/src/lib/libzfs/common/libzfs_changelist.c40
-rw-r--r--usr/src/lib/libzfs/common/libzfs_dataset.c76
-rw-r--r--usr/src/lib/libzfs/common/libzfs_impl.h3
-rw-r--r--usr/src/lib/libzfs/common/libzfs_mount.c138
-rw-r--r--usr/src/lib/libzfs/common/libzfs_util.c10
-rw-r--r--usr/src/lib/libzfs/common/mapfile-vers4
-rw-r--r--usr/src/pkg/manifests/SUNWcs.mf1
-rw-r--r--usr/src/pkg/manifests/SUNWiscsitgt.mf31
-rw-r--r--usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf1
-rw-r--r--usr/src/pkg/manifests/network-iscsi-target-legacy.mf77
-rw-r--r--usr/src/tools/scripts/bfu.sh62
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_ioctl.c59
-rw-r--r--usr/src/uts/common/io/comstar/port/iscsit/iscsit.c3
-rw-r--r--usr/src/uts/common/sys/fs/zfs.h2
110 files changed, 102 insertions, 45211 deletions
diff --git a/usr/src/Makefile.lint b/usr/src/Makefile.lint
index 8c535e5fc5..90b76afe47 100644
--- a/usr/src/Makefile.lint
+++ b/usr/src/Makefile.lint
@@ -172,7 +172,6 @@ COMMON_SUBDIRS = \
cmd/ipcs \
cmd/isaexec \
cmd/isalist \
- cmd/iscsi \
cmd/iscsiadm \
cmd/iscsid \
cmd/iscsitsvc \
@@ -382,7 +381,6 @@ COMMON_SUBDIRS = \
lib/libipp \
lib/libipsecutil \
lib/libiscsit \
- lib/libiscsitgt \
lib/libkmf \
lib/libkstat \
lib/liblgrp \
diff --git a/usr/src/Targetdirs b/usr/src/Targetdirs
index e03c47e54e..61f6e0c00c 100644
--- a/usr/src/Targetdirs
+++ b/usr/src/Targetdirs
@@ -843,8 +843,6 @@ $(ROOT)/usr/lib/libinetutil.so.1:= REALPATH=../../lib/libinetutil.so.1
$(ROOT)/usr/lib/libinetutil.so:= REALPATH=../../lib/libinetutil.so.1
$(ROOT)/usr/lib/libintl.so.1:= REALPATH=../../lib/libintl.so.1
$(ROOT)/usr/lib/libintl.so:= REALPATH=../../lib/libintl.so.1
-$(ROOT)/usr/lib/libiscsitgt.so.1:= REALPATH=../../lib/libiscsitgt.so.1
-$(ROOT)/usr/lib/libiscsitgt.so:= REALPATH=../../lib/libiscsitgt.so.1
$(ROOT)/usr/lib/libkmf.so.1:= REALPATH=../../lib/libkmf.so.1
$(ROOT)/usr/lib/libkmf.so:= REALPATH=../../lib/libkmf.so.1
$(ROOT)/usr/lib/libkmfberder.so.1:= REALPATH=../../lib/libkmfberder.so.1
@@ -1127,10 +1125,6 @@ $(ROOT)/usr/lib/$(MACH64)/libintl.so.1:= \
REALPATH=../../../lib/$(MACH64)/libintl.so.1
$(ROOT)/usr/lib/$(MACH64)/libintl.so:= \
REALPATH=../../../lib/$(MACH64)/libintl.so.1
-$(ROOT)/usr/lib/$(MACH64)/libiscsitgt.so.1:= \
- REALPATH=../../../lib/$(MACH64)/libiscsitgt.so.1
-$(ROOT)/usr/lib/$(MACH64)/libiscsitgt.so:= \
- REALPATH=../../../lib/$(MACH64)/libiscsitgt.so.1
$(ROOT)/usr/lib/$(MACH64)/libkstat.so.1:= \
REALPATH=../../../lib/$(MACH64)/libkstat.so.1
$(ROOT)/usr/lib/$(MACH64)/libkstat.so:= \
@@ -1449,8 +1443,6 @@ SYM.USRLIB= \
/usr/lib/libinetutil.so.1 \
/usr/lib/libintl.so \
/usr/lib/libintl.so.1 \
- /usr/lib/libiscsitgt.so \
- /usr/lib/libiscsitgt.so.1 \
/usr/lib/libkstat.so \
/usr/lib/libkstat.so.1 \
/usr/lib/liblddbg.so.4 \
@@ -1689,8 +1681,6 @@ SYM.USRLIB64= \
/usr/lib/$(MACH64)/libinetutil.so.1 \
/usr/lib/$(MACH64)/libintl.so \
/usr/lib/$(MACH64)/libintl.so.1 \
- /usr/lib/$(MACH64)/libiscsitgt.so \
- /usr/lib/$(MACH64)/libiscsitgt.so.1 \
/usr/lib/$(MACH64)/libkstat.so \
/usr/lib/$(MACH64)/libkstat.so.1 \
/usr/lib/$(MACH64)/liblddbg.so.4 \
diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile
index f4afcc0390..36b830bfbf 100644
--- a/usr/src/cmd/Makefile
+++ b/usr/src/cmd/Makefile
@@ -207,7 +207,6 @@ COMMON_SUBDIRS= \
ipf \
isainfo \
isalist \
- iscsi \
itutools \
iscsiadm \
iscsid \
@@ -599,7 +598,6 @@ MSGSUBDIRS= \
id \
idmap \
isaexec \
- iscsi \
iscsiadm \
iscsid \
isns \
diff --git a/usr/src/cmd/Makefile.check b/usr/src/cmd/Makefile.check
index 964719eb6c..bc13f620b7 100644
--- a/usr/src/cmd/Makefile.check
+++ b/usr/src/cmd/Makefile.check
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -117,7 +117,6 @@ MANIFEST_SUBDIRS= \
hostid/smf \
idmap/idmapd \
ipf/svc \
- iscsi/iscsitgtd \
isns/isnsd \
krb5/kadmin/server \
krb5/krb5kdc \
diff --git a/usr/src/cmd/iscsi/Makefile b/usr/src/cmd/iscsi/Makefile
deleted file mode 100644
index 79aac24e7c..0000000000
--- a/usr/src/cmd/iscsi/Makefile
+++ /dev/null
@@ -1,70 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
-#
-# Makefile definitions for volume management
-#
-#
-# cmd/iscsi/Makefile
-#
-
-include ../Makefile.cmd
-
-SUBDIRS = iscsitgtd iscsitadm
-POSUBDIRS = iscsitgtd iscsitadm
-POFILE = SUNW_ISCSI.po
-POFILES = $(POSUBDIRS:%=%/%.po)
-
-CAT= cat
-
-all := TARGET= all
-install := TARGET= install
-clean := TARGET= clean
-clobber := TARGET= clobber
-lint := TARGET= lint
-cstyle := TARGET= cstyle
-_msg := TARGET= catalog
-
-.KEEP_STATE:
-
-all install cstyle lint _msg: $(SUBDIRS)
-
-clean: $(SUBDIRS)
- $(RM) $(POFILES)
-
-clobber: $(SUBDIRS)
- $(RM) $(POFILE)
-
-$(SUBDIRS): FRC
- @cd $@; pwd; $(MAKE) $(TARGET)
-
-$(POFILE): $(POFILES)
- $(BUILDPO.pofiles)
-
-_msg: $(POSUBDIRS) .WAIT $(MSGDOMAINPOFILE)
-
-FRC:
-
-include $(SRC)/Makefile.msg.targ
diff --git a/usr/src/cmd/iscsi/Makefile.iscsi b/usr/src/cmd/iscsi/Makefile.iscsi
deleted file mode 100644
index d24117eb4d..0000000000
--- a/usr/src/cmd/iscsi/Makefile.iscsi
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-CPPFLAGS += -D_FILE_OFFSET_BITS=64 -I/usr/include/libxml2
-
-ISCSISRC = $(SRC)/cmd/iscsi
-ISCSICOMMONDIR = $(ISCSISRC)/common
-HDCRCCOMMONDIR = $(SRC)/common/hdcrc
diff --git a/usr/src/cmd/iscsi/iscsitadm/Makefile b/usr/src/cmd/iscsi/iscsitadm/Makefile
deleted file mode 100644
index f8d91cd936..0000000000
--- a/usr/src/cmd/iscsi/iscsitadm/Makefile
+++ /dev/null
@@ -1,68 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-PROG = iscsitadm
-OBJS = main.o helper.o cmdparse.o
-SRCS =$(OBJS:%.o=%.c)
-POFILES= $(OBJS:%.o=%.po)
-
-include $(SRC)/cmd/Makefile.cmd
-include $(SRC)/cmd/iscsi/Makefile.iscsi
-
-LDLIBS += -liscsitgt
-XMLLIB = -lxml2
-CFLAGS += $(CCVERBOSE) -I${ISCSICOMMONDIR}
-FILEMODE= 0555
-
-.KEEP_STATE:
-
-all: $(PROG)
-
-install: all $(ROOTUSRSBINPROG)
-
-$(PROG): $(OBJS) $(COMMON_OBJS)
- $(LINK.c) -o $(PROG) $(OBJS) $(COMMON_OBJS) $(LDLIBS) $(XMLLIB)
- $(POST_PROCESS)
-
-catalog: $(POFILE)
-
-lint := LINTFLAGS += -u
-lint := LINTFLAGS64 += -u
-
-lint: $$(SRCS)
- $(LINT.c) $(SRCS) $(LDLIBS)
-
-$(POFILE): $(POFILES)
- $(RM) $@
- cat $(POFILES) > $@
-
-%.o : $(ISCSICOMMONDIR)/%.c
- $(COMPILE.c) -o $@ $<
- $(POST_PROCESS_O)
-
-clean:
- -$(RM) $(OBJS) $(COMMON_OBJS)
-
-include $(SRC)/cmd/Makefile.targ
diff --git a/usr/src/cmd/iscsi/iscsitadm/cmdparse.c b/usr/src/cmd/iscsi/iscsitadm/cmdparse.c
deleted file mode 100644
index d94e54538c..0000000000
--- a/usr/src/cmd/iscsi/iscsitadm/cmdparse.c
+++ /dev/null
@@ -1,934 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <strings.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <libintl.h>
-#include <errno.h>
-#include <string.h>
-#include <assert.h>
-#include <getopt.h>
-#include "cmdparse.h"
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-
-/* Usage types */
-#define GENERAL_USAGE 1
-#define HELP_USAGE 2
-#define DETAIL_USAGE 3
-
-/* printable ascii character set len */
-#define MAXOPTIONS (uint_t)('~' - '!' + 1)
-
-/*
- * MAXOPTIONSTRING is the max length of the options string used in getopt and
- * will be the printable character set + ':' for each character,
- * providing for options with arguments. e.g. "t:Cs:hglr:"
- */
-#define MAXOPTIONSTRING MAXOPTIONS * 2
-
-/* standard command options table to support -?, -V */
-struct option standardCmdOptions[] = {
- {"help", no_argument, NULL, '?'},
- {"version", no_argument, NULL, 'V'},
- {NULL, 0, NULL, 0}
-};
-
-/* standard subcommand options table to support -? */
-struct option standardSubCmdOptions[] = {
- {"help", no_argument, NULL, '?'},
- {NULL, 0, NULL, 0}
-};
-
-/* forward declarations */
-static int getSubcommand(char *, subcommand_t **);
-static char *getExecBasename(char *);
-static void usage(uint_t);
-static void subUsage(uint_t, subcommand_t *);
-static void subUsageObject(uint_t, subcommand_t *, object_t *);
-static int getObject(char *, object_t **);
-static int getObjectRules(uint_t, objectRules_t **);
-static char *getLongOption(int);
-static optionProp_t *getOptions(uint_t, uint_t);
-static char *getOptionArgDesc(int);
-
-/* global data */
-static struct option *_longOptions;
-static subcommand_t *_subcommands;
-static object_t *_objects;
-static objectRules_t *_objectRules;
-static optionRules_t *_optionRules;
-static optionTbl_t *_clientOptionTbl;
-static char *commandName;
-
-
-/*
- * input:
- * object - object value
- * output:
- * opCmd - pointer to opCmd_t structure allocated by caller
- *
- * On successful return, opCmd contains the rules for the value in
- * object. On failure, the contents of opCmd is unspecified.
- *
- * Returns:
- * zero on success
- * non-zero on failure
- *
- */
-static int
-getObjectRules(uint_t object, objectRules_t **objectRules)
-{
- objectRules_t *sp;
-
- for (sp = _objectRules; sp->value; sp++) {
- if (sp->value == object) {
- *objectRules = sp;
- return (0);
- }
- }
- return (1);
-}
-
-/*
- * input:
- * arg - pointer to array of char containing object string
- *
- * output:
- * object - pointer to object_t structure pointer
- * on success, contains the matching object structure based on
- * input object name
- *
- * Returns:
- * zero on success
- * non-zero otherwise
- *
- */
-static int
-getObject(char *arg, object_t **object)
-{
-
- object_t *op;
- int len;
-
- for (op = _objects; op->name; op++) {
- len = strlen(arg);
- if (len == strlen(op->name) &&
- strncasecmp(arg, op->name, len) == 0) {
- *object = op;
- return (0);
- }
- }
- return (1);
-}
-
-/*
- * input:
- * arg - pointer to array of char containing subcommand string
- * output:
- * subcommand - pointer to subcommand_t pointer
- * on success, contains the matching subcommand structure based on
- * input subcommand name
- *
- * Returns:
- * zero on success
- * non-zero on failure
- */
-static int
-getSubcommand(char *arg, subcommand_t **subcommand)
-{
- subcommand_t *sp;
- int len;
-
- for (sp = _subcommands; sp->name; sp++) {
- len = strlen(arg);
- if (len == strlen(sp->name) &&
- strncasecmp(arg, sp->name, len) == 0) {
- *subcommand = sp;
- return (0);
- }
- }
- return (1);
-}
-
-/*
- * input:
- * object - object for which to get options
- * subcommand - subcommand for which to get options
- *
- * Returns:
- * on success, optionsProp_t pointer to structure matching input object
- * value
- * on failure, NULL is returned
- */
-static optionProp_t *
-getOptions(uint_t object, uint_t subcommand)
-{
- uint_t currObject;
- optionRules_t *op = _optionRules;
- while (op && ((currObject = op->objectValue) != 0)) {
- if ((currObject == object) &&
- (op->subcommandValue == subcommand)) {
- return (&(op->optionProp));
- }
- op++;
- }
- return (NULL);
-}
-
-/*
- * input:
- * shortOption - short option character for which to return the
- * associated long option string
- *
- * Returns:
- * on success, long option name
- * on failure, NULL
- */
-static char *
-getLongOption(int shortOption)
-{
- struct option *op;
- for (op = _longOptions; op->name; op++) {
- if (shortOption == op->val) {
- return (op->name);
- }
- }
- return (NULL);
-}
-
-/*
- * input
- * shortOption - short option character for which to return the
- * option argument
- * Returns:
- * on success, argument string
- * on failure, NULL
- */
-static char *
-getOptionArgDesc(int shortOption)
-{
- optionTbl_t *op;
- for (op = _clientOptionTbl; op->name; op++) {
- if (op->val == shortOption &&
- op->has_arg == required_argument) {
- return (op->argDesc);
- }
- }
- return (NULL);
-}
-
-
-/*
- * Print usage for a subcommand.
- *
- * input:
- * usage type - GENERAL_USAGE, HELP_USAGE, DETAIL_USAGE
- * subcommand - pointer to subcommand_t structure
- *
- * Returns:
- * none
- *
- */
-static void
-subUsage(uint_t usageType, subcommand_t *subcommand)
-{
- int i;
- object_t *objp;
-
-
- (void) fprintf(stdout, "%s:\t%s %s [",
- gettext("Usage"), commandName, subcommand->name);
-
- for (i = 0; standardSubCmdOptions[i].name; i++) {
- (void) fprintf(stdout, "-%c",
- standardSubCmdOptions[i].val);
- if (standardSubCmdOptions[i+1].name)
- (void) fprintf(stdout, ",");
- }
-
- (void) fprintf(stdout, "] %s [", "<OBJECT>");
-
- for (i = 0; standardSubCmdOptions[i].name; i++) {
- (void) fprintf(stdout, "-%c",
- standardSubCmdOptions[i].val);
- if (standardSubCmdOptions[i+1].name)
- (void) fprintf(stdout, ",");
- }
-
- (void) fprintf(stdout, "] %s", "[<OPERAND>]");
- (void) fprintf(stdout, "\n");
-
- if (usageType == GENERAL_USAGE) {
- return;
- }
-
- (void) fprintf(stdout, "%s:\n", gettext("Usage by OBJECT"));
-
- /*
- * iterate through object table
- * For each object, print appropriate usage
- * based on rules tables
- */
- for (objp = _objects; objp->value; objp++) {
- subUsageObject(usageType, subcommand, objp);
- }
-}
-
-/*
- * Print usage for a subcommand and object.
- *
- * input:
- * usage type - GENERAL_USAGE, HELP_USAGE, DETAIL_USAGE
- * subcommand - pointer to subcommand_t structure
- * objp - pointer to a object_t structure
- *
- * Returns:
- * none
- *
- */
-static void
-subUsageObject(uint_t usageType, subcommand_t *subcommand, object_t *objp)
-{
- int i;
- objectRules_t *objRules = NULL;
- opCmd_t *opCmd = NULL;
- optionProp_t *options;
- char *optionArgDesc;
- char *longOpt;
-
-
- if (getObjectRules(objp->value, &objRules) != 0) {
- /*
- * internal subcommand rules table error
- * no object entry in object
- */
- assert(0);
- }
-
- opCmd = &(objRules->opCmd);
-
- if (opCmd->invOpCmd & subcommand->value) {
- return;
- }
-
- options = getOptions(objp->value, subcommand->value);
-
- /* print generic subcommand usage */
- (void) fprintf(stdout, "\t%s %s ", commandName, subcommand->name);
-
- /* print object */
- (void) fprintf(stdout, "%s ", objp->name);
-
- /* print options if applicable */
- if (options != NULL) {
- if (options->required) {
- (void) fprintf(stdout, "%s", gettext("<"));
- } else {
- (void) fprintf(stdout, "%s", gettext("["));
- }
- (void) fprintf(stdout, "%s", gettext("OPTIONS"));
- if (options->required) {
- (void) fprintf(stdout, "%s ", gettext(">"));
- } else {
- (void) fprintf(stdout, "%s ", gettext("]"));
- }
- }
-
- /* print operand requirements */
- if (opCmd->optOpCmd & subcommand->value) {
- (void) fprintf(stdout, gettext("["));
- }
- if (!(opCmd->noOpCmd & subcommand->value)) {
- (void) fprintf(stdout, gettext("<"));
- if (objRules->operandDefinition) {
- (void) fprintf(stdout, "%s",
- objRules->operandDefinition);
- } else {
- /*
- * Missing operand description
- * from table
- */
- assert(0);
- }
- }
- if (opCmd->multOpCmd & subcommand->value) {
- (void) fprintf(stdout, gettext(" ..."));
- }
- if (!(opCmd->noOpCmd & subcommand->value)) {
- (void) fprintf(stdout, gettext(">"));
- }
- if (opCmd->optOpCmd & subcommand->value) {
- (void) fprintf(stdout, gettext("]"));
- }
-
- if (usageType == HELP_USAGE) {
- (void) fprintf(stdout, "\n");
- return;
- }
-
- /* print options for subcommand, object */
- if (options != NULL && options->optionString != NULL) {
- (void) fprintf(stdout, "\n\t%s:", gettext("OPTIONS"));
- for (i = 0; i < strlen(options->optionString); i++) {
- if ((longOpt = getLongOption(
- options->optionString[i]))
- == NULL) {
- /* no long option exists for short option */
- assert(0);
- }
- (void) fprintf(stdout, "\n\t\t-%c, --%s ",
- options->optionString[i], longOpt);
- optionArgDesc =
- getOptionArgDesc(options->optionString[i]);
- if (optionArgDesc != NULL) {
- (void) fprintf(stdout, "<%s>", optionArgDesc);
- }
- if (options->exclusive &&
- strchr(options->exclusive,
- options->optionString[i])) {
- (void) fprintf(stdout, " (%s)",
- gettext("exclusive"));
- }
- }
- }
- (void) fprintf(stdout, "\n");
-}
-
-/*
- * input:
- * type of usage statement to print
- *
- * Returns:
- * return value of subUsage
- */
-static void
-usage(uint_t usageType)
-{
- int i;
- subcommand_t subcommand;
- subcommand_t *sp;
-
- /* print general command usage */
- (void) fprintf(stdout, "%s:\t%s ",
- gettext("Usage"), commandName);
-
- for (i = 0; standardCmdOptions[i].name; i++) {
- (void) fprintf(stdout, "-%c",
- standardCmdOptions[i].val);
- if (standardCmdOptions[i+1].name)
- (void) fprintf(stdout, ",");
- }
-
- if (usageType == HELP_USAGE || usageType == GENERAL_USAGE) {
- for (i = 0; standardSubCmdOptions[i].name; i++) {
- (void) fprintf(stdout, ",--%s",
- standardSubCmdOptions[i].name);
- if (standardSubCmdOptions[i+1].name)
- (void) fprintf(stdout, ",");
- }
- }
-
- (void) fprintf(stdout, "\n");
-
-
- /* print all subcommand usage */
- for (sp = _subcommands; sp->name; sp++) {
- subcommand.name = sp->name;
- subcommand.value = sp->value;
- if (usageType == HELP_USAGE) {
- (void) fprintf(stdout, "\n");
- }
- subUsage(usageType, &subcommand);
- }
-}
-
-/*
- * input:
- * execFullName - exec name of program (argv[0])
- *
- * Returns:
- * command name portion of execFullName
- */
-static char *
-getExecBasename(char *execFullname)
-{
- char *lastSlash, *execBasename;
-
- /* guard against '/' at end of command invocation */
- for (;;) {
- lastSlash = strrchr(execFullname, '/');
- if (lastSlash == NULL) {
- execBasename = execFullname;
- break;
- } else {
- execBasename = lastSlash + 1;
- if (*execBasename == '\0') {
- *lastSlash = '\0';
- continue;
- }
- break;
- }
- }
- return (execBasename);
-}
-
-/*
- * cmdParse is a parser that checks syntax of the input command against
- * various rules tables.
- *
- * It provides usage feedback based upon the passed rules tables by calling
- * two usage functions, usage, subUsage, and subUsageObject handling command,
- * subcommand and object usage respectively.
- *
- * When syntax is successfully validated, the associated function is called
- * using the subcommands table functions.
- *
- * Syntax is as follows:
- * command subcommand object [<options>] [<operand>]
- *
- * There are two standard short and long options assumed:
- * -?, --help Provides usage on a command or subcommand
- * and stops further processing of the arguments
- *
- * -V, --version Provides version information on the command
- * and stops further processing of the arguments
- *
- * These options are loaded by this function.
- *
- * input:
- * argc, argv from main
- * syntax rules tables (synTables_t structure)
- * callArgs - void * passed by caller to be passed to subcommand function
- *
- * output:
- * funcRet - pointer to int that holds subcommand function return value
- *
- * Returns:
- *
- * zero on successful syntax parse and function call
- *
- * 1 on unsuccessful syntax parse (no function has been called)
- * This could be due to a version or help call or simply a
- * general usage call.
- *
- * -1 check errno, call failed
- *
- * This module is not MT-safe.
- *
- */
-int
-cmdParse(int argc, char *argv[], synTables_t synTable, void *callArgs,
- int *funcRet)
-{
- int getoptargc;
- char **getoptargv;
- int opt;
- int operInd;
- int i, j;
- int len;
- char *versionString;
- char optionStringAll[MAXOPTIONSTRING + 1];
- optionProp_t *availOptions;
- objectRules_t *objRules = NULL;
- opCmd_t *opCmd = NULL;
- subcommand_t *subcommand;
- object_t *object;
- cmdOptions_t cmdOptions[MAXOPTIONS + 1];
- struct option *lp;
- optionTbl_t *optionTbl;
- struct option intLongOpt[MAXOPTIONS + 1];
-
- /*
- * Check for NULLs on mandatory input arguments
- *
- * Note: longOptionTbl and optionRulesTbl can be NULL in the case
- * where there is no caller defined options
- *
- */
- if (synTable.versionString == NULL ||
- synTable.subcommandTbl == NULL ||
- synTable.objectRulesTbl == NULL ||
- synTable.objectTbl == NULL ||
- funcRet == NULL) {
- assert(0);
- }
-
-
- versionString = synTable.versionString;
-
- /* set global command name */
- commandName = getExecBasename(argv[0]);
-
- /* Set unbuffered output */
- setbuf(stdout, NULL);
-
- /* load globals */
- _subcommands = synTable.subcommandTbl;
- _objectRules = synTable.objectRulesTbl;
- _optionRules = synTable.optionRulesTbl;
- _objects = synTable.objectTbl;
- _clientOptionTbl = synTable.longOptionTbl;
-
- /* There must be at least two arguments */
- if (argc < 2) {
- usage(GENERAL_USAGE);
- return (1);
- }
-
- bzero(&intLongOpt[0], sizeof (intLongOpt));
-
- /*
- * load standard subcommand options to internal long options table
- * Two separate getopt_long(3C) tables are used.
- */
- for (i = 0; standardSubCmdOptions[i].name; i++) {
- intLongOpt[i].name = standardSubCmdOptions[i].name;
- intLongOpt[i].has_arg = standardSubCmdOptions[i].has_arg;
- intLongOpt[i].flag = standardSubCmdOptions[i].flag;
- intLongOpt[i].val = standardSubCmdOptions[i].val;
- }
-
- /*
- * copy caller's long options into internal long options table
- * We do this for two reasons:
- * 1) We need to use the getopt_long option structure internally
- * 2) We need to prepend the table with the standard option
- * for all subcommands (currently -?)
- */
- for (optionTbl = synTable.longOptionTbl;
- optionTbl && optionTbl->name; optionTbl++, i++) {
- if (i > MAXOPTIONS - 1) {
- /* option table too long */
- assert(0);
- }
- intLongOpt[i].name = optionTbl->name;
- intLongOpt[i].has_arg = optionTbl->has_arg;
- intLongOpt[i].flag = NULL;
- intLongOpt[i].val = optionTbl->val;
- }
-
- /* set option table global */
- _longOptions = &intLongOpt[0];
-
-
- /*
- * Check for help/version request immediately following command
- * '+' in option string ensures POSIX compliance in getopt_long()
- * which means that processing will stop at first non-option
- * argument.
- */
- while ((opt = getopt_long(argc, argv, "+?V", standardCmdOptions,
- NULL)) != EOF) {
- switch (opt) {
- case '?':
- /*
- * getopt can return a '?' when no
- * option letters match string. Check for
- * the 'real' '?' in optopt.
- */
- if (optopt == '?') {
- usage(HELP_USAGE);
- return (1);
- } else {
- usage(GENERAL_USAGE);
- return (1);
- }
- case 'V':
- (void) fprintf(stdout, "%s: %s %s\n",
- commandName, gettext("Version"),
- versionString);
- return (1);
- default:
- break;
- }
- }
-
- /*
- * subcommand is always in the second argument. If there is no
- * recognized subcommand in the second argument, print error,
- * general usage and then return.
- */
- if (getSubcommand(argv[1], &subcommand) != 0) {
- (void) fprintf(stderr, "%s: %s\n",
- commandName, gettext("invalid subcommand"));
- usage(GENERAL_USAGE);
- return (1);
- }
-
- if (argc == 2) {
- (void) fprintf(stderr, "%s: %s\n",
- commandName, gettext("missing object"));
- subUsage(GENERAL_USAGE, subcommand);
- return (1);
- }
-
- getoptargv = argv;
- getoptargv++;
- getoptargc = argc;
- getoptargc -= 1;
-
- while ((opt = getopt_long(getoptargc, getoptargv, "+?",
- standardSubCmdOptions, NULL)) != EOF) {
- switch (opt) {
- case '?':
- /*
- * getopt can return a '?' when no
- * option letters match string. Check for
- * the 'real' '?' in optopt.
- */
- if (optopt == '?') {
- subUsage(HELP_USAGE, subcommand);
- return (1);
- } else {
- subUsage(GENERAL_USAGE, subcommand);
- return (1);
- }
- default:
- break;
- }
- }
-
-
- /*
- * object is always in the third argument. If there is no
- * recognized object in the third argument, print error,
- * help usage for the subcommand and then return.
- */
- if (getObject(argv[2], &object) != 0) {
- (void) fprintf(stderr, "%s: %s\n",
- commandName, gettext("invalid object"));
- subUsage(HELP_USAGE, subcommand);
- return (1);
- }
-
- if (getObjectRules(object->value, &objRules) != 0) {
- /*
- * internal subcommand rules table error
- * no object entry in object table
- */
- assert(0);
- }
-
- opCmd = &(objRules->opCmd);
-
- /*
- * Is command valid for this object?
- */
- if (opCmd->invOpCmd & subcommand->value) {
- (void) fprintf(stderr, "%s: %s %s\n", commandName,
- gettext("invalid subcommand for"), object->name);
- subUsage(HELP_USAGE, subcommand);
- return (1);
- }
-
- /*
- * offset getopt arg begin since
- * getopt(3C) assumes options
- * follow first argument
- */
- getoptargv = argv;
- getoptargv++;
- getoptargv++;
- getoptargc = argc;
- getoptargc -= 2;
-
- bzero(optionStringAll, sizeof (optionStringAll));
- bzero(&cmdOptions[0], sizeof (cmdOptions));
-
- j = 0;
- /*
- * Build optionStringAll from long options table
- */
- for (lp = _longOptions; lp->name; lp++, j++) {
- /* sanity check on string length */
- if (j + 1 >= sizeof (optionStringAll)) {
- /* option table too long */
- assert(0);
- }
- optionStringAll[j] = lp->val;
- if (lp->has_arg == required_argument) {
- optionStringAll[++j] = ':';
- }
- }
-
- i = 0;
- /*
- * Run getopt for all arguments against all possible options
- * Store all options/option arguments in an array for retrieval
- * later.
- * Once all options are retrieved, check against object
- * and subcommand (option rules table) for validity.
- * This is done later.
- */
- while ((opt = getopt_long(getoptargc, getoptargv, optionStringAll,
- _longOptions, NULL)) != EOF) {
- switch (opt) {
- case '?':
- if (optopt == '?') {
- subUsageObject(DETAIL_USAGE,
- subcommand, object);
- return (1);
- } else {
- subUsage(GENERAL_USAGE, subcommand);
- return (1);
- }
- default:
- cmdOptions[i].optval = opt;
- if (optarg) {
- len = strlen(optarg);
- if (len > sizeof (cmdOptions[i].optarg)
- - 1) {
- (void) fprintf(stderr,
- "%s: %s\n",
- commandName,
- gettext("option too long"));
- errno = EINVAL;
- return (-1);
- }
- (void) strncpy(cmdOptions[i].optarg,
- optarg, len);
- }
- i++;
- break;
- }
- }
-
- /*
- * increment past last option
- */
- operInd = optind + 2;
-
- /*
- * Check validity of given options, if any were given
- */
-
- /* get option string for this object and subcommand */
- availOptions = getOptions(object->value, subcommand->value);
-
- if (cmdOptions[0].optval != 0) { /* options were input */
- if (availOptions == NULL) { /* no options permitted */
- (void) fprintf(stderr, "%s: %s\n",
- commandName, gettext("no options permitted"));
- subUsageObject(HELP_USAGE, subcommand, object);
- return (1);
- }
- for (i = 0; cmdOptions[i].optval; i++) {
- /* Check for invalid options */
- if (availOptions->optionString == NULL) {
- /*
- * internal option table error
- * There must be an option string if
- * there is an entry in the table
- */
- assert(0);
- }
- /* is the option in the available option string? */
-
- if (!(strchr(availOptions->optionString,
- cmdOptions[i].optval))) {
- (void) fprintf(stderr,
- "%s: '-%c': %s\n",
- commandName, cmdOptions[i].optval,
- gettext("invalid option"));
- subUsageObject(DETAIL_USAGE, subcommand,
- object);
- return (1);
-
- /* Check for exclusive options */
- } else if (cmdOptions[1].optval != 0 &&
- availOptions->exclusive &&
- strchr(availOptions->exclusive,
- cmdOptions[i].optval)) {
- (void) fprintf(stderr,
- "%s: '-%c': %s\n",
- commandName, cmdOptions[i].optval,
- gettext("is an exclusive option"));
- subUsageObject(DETAIL_USAGE, subcommand,
- object);
- return (1);
- }
- }
- } else { /* no options were input */
- if (availOptions != NULL && (availOptions->required)) {
- (void) fprintf(stderr, "%s: %s\n", commandName,
- gettext("at least one option required"));
- subUsageObject(DETAIL_USAGE, subcommand,
- object);
- return (1);
- }
- }
-
- /*
- * If there are no more arguments (operands),
- * check to see if this is okay
- */
- if ((operInd == argc) &&
- (opCmd->reqOpCmd & subcommand->value)) {
- (void) fprintf(stderr, "%s: %s %s %s\n",
- commandName, subcommand->name, object->name,
- gettext("requires an operand"));
- subUsageObject(HELP_USAGE, subcommand, object);
- return (1);
- }
-
- /*
- * If there are more operands,
- * check to see if this is okay
- */
- if ((argc > operInd) && (opCmd->noOpCmd & subcommand->value)) {
- (void) fprintf(stderr, "%s: %s %s %s\n", commandName,
- subcommand->name, object->name,
- gettext("takes no operands"));
- subUsageObject(HELP_USAGE, subcommand, object);
- return (1);
- }
-
- /*
- * If there is more than one more operand,
- * check to see if this is okay
- */
- if ((argc > operInd) && ((argc - operInd) != 1) &&
- !(opCmd->multOpCmd & subcommand->value)) {
- (void) fprintf(stderr, "%s: %s %s %s\n", commandName,
- subcommand->name, object->name,
- gettext("accepts only a single operand"));
- subUsageObject(HELP_USAGE, subcommand, object);
- return (1);
- }
-
- /* Finished syntax checks */
-
-
- /* Call appropriate function */
- *funcRet = subcommand->handler(argc - operInd, &argv[operInd],
- object->value, &cmdOptions[0], callArgs);
-
- return (0);
-}
diff --git a/usr/src/cmd/iscsi/iscsitadm/cmdparse.h b/usr/src/cmd/iscsi/iscsitadm/cmdparse.h
deleted file mode 100644
index 6a8fe56c1d..0000000000
--- a/usr/src/cmd/iscsi/iscsitadm/cmdparse.h
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _CMDPARSE_H
-#define _CMDPARSE_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "getopt.h"
-
-/* subcommands must have a single bit on and must have exclusive values */
-#define SUBCOMMAND_BASE 1
-#define SUBCOMMAND(x) (SUBCOMMAND_BASE << x)
-
-#define OBJECT_BASE 1
-#define OBJECT(x) (OBJECT_BASE << x)
-
-/* maximum length of an option argument */
-#define MAXOPTARGLEN 256
-
-
-/*
- * Add objects here
- *
- * EXAMPLE:
- * object_t object[] = {
- * {"target", TARGET},
- * {NULL, 0}
- * };
- */
-typedef struct _object {
- char *name;
- uint_t value;
-} object_t;
-
-/*
- * This structure is passed into the caller's callback function and
- * will contain a list of all options entered and their associated
- * option arguments if applicable
- */
-typedef struct _cmdOptions {
- int optval;
- char optarg[MAXOPTARGLEN + 1];
-} cmdOptions_t;
-
-
-/*
- * list of objects, subcommands, valid short options, required flag and
- * exlusive option string
- *
- * objectValue -> object
- * subcommandValue -> subcommand value
- * optionProp.optionString -> short options that are valid
- * optionProp.required -> flag indicating whether at least one option is
- * required
- * optionProp.exclusive -> short options that are required to be exclusively
- * entered
- *
- *
- * If it's not here, there are no options for that object.
- *
- * The long options table specifies whether an option argument is required.
- *
- *
- * EXAMPLE:
- *
- * Based on DISCOVERY entry below:
- *
- * MODIFY DISCOVERY accepts -i, -s, -t and -l
- * MODIFY DISCOVERY requires at least one option
- * MODIFY DISCOVERY has no exclusive options
- *
- *
- * optionRules_t optionRules[] = {
- * {DISCOVERY, MODIFY, "istl", B_TRUE, NULL},
- * {0, 0, NULL, 0, NULL}
- * };
- */
-typedef struct _optionProp {
- char *optionString;
- boolean_t required;
- char *exclusive;
-} optionProp_t;
-
-typedef struct _optionRules {
- uint_t objectValue;
- uint_t subcommandValue;
- optionProp_t optionProp;
-} optionRules_t;
-
-/*
- * Rules for subcommands and object operands
- *
- * Every object requires an entry
- *
- * value, reqOpCmd, optOpCmd, noOpCmd, invCmd, multOpCmd
- *
- * value -> numeric value of object
- *
- * The following five fields are comprised of values that are
- * a bitwise OR of the subcommands related to the object
- *
- * reqOpCmd -> subcommands that must have an operand
- * optOpCmd -> subcommands that may have an operand
- * noOpCmd -> subcommands that will have no operand
- * invCmd -> subcommands that are invalid
- * multOpCmd -> subcommands that can accept multiple operands
- * operandDefinition -> Usage definition for the operand of this object
- *
- *
- * EXAMPLE:
- *
- * based on TARGET entry below:
- * MODIFY and DELETE subcomamnds require an operand
- * LIST optionally requires an operand
- * There are no subcommands that requires that no operand is specified
- * ADD and REMOVE are invalid subcommands for this operand
- * DELETE can accept multiple operands
- *
- * objectRules_t objectRules[] = {
- * {TARGET, MODIFY|DELETE, LIST, 0, ADD|REMOVE, DELETE,
- * "target-name"},
- * {0, 0, 0, 0, 0, NULL}
- * };
- */
-typedef struct _opCmd {
- uint_t reqOpCmd;
- uint_t optOpCmd;
- uint_t noOpCmd;
- uint_t invOpCmd;
- uint_t multOpCmd;
-} opCmd_t;
-
-typedef struct _objectRules {
- uint_t value;
- opCmd_t opCmd;
- char *operandDefinition;
-} objectRules_t;
-
-
-/*
- * subcommand callback function
- *
- * argc - number of arguments in argv
- * argv - operand arguments
- * options - options entered on command line
- * callData - pointer to caller data to be passed to subcommand function
- */
-typedef int (*handler_t)(int argc, char *argv[], int, cmdOptions_t *options,
- void *callData);
-
-/*
- * Add new subcommands here
- *
- * EXAMPLE:
- * subcommand_t subcommands[] = {
- * {"add", ADD, addFunc},
- * {NULL, 0, NULL}
- * };
- */
-typedef struct _subcommand {
- char *name;
- uint_t value;
- handler_t handler;
-} subcommand_t;
-
-#define required_arg required_argument
-#define no_arg no_argument
-
-/*
- * Add short options and long options here
- *
- * name -> long option name
- * has_arg -> required_arg, no_arg
- * val -> short option character
- * argDesc -> description of option argument
- *
- * Note: This structure may not be used if your CLI has no
- * options. However, -?, --help and -V, --version will still be supported
- * as they are standard for every CLI.
- *
- * EXAMPLE:
- *
- * optionTbl_t options[] = {
- * {"filename", arg_required, 'f', "out-filename"},
- * {NULL, 0, 0}
- * };
- *
- */
-typedef struct _optionTbl {
- char *name;
- int has_arg;
- int val;
- char *argDesc;
-} optionTbl_t;
-
-/*
- * After tables are set, assign them to this structure
- * for passing into cmdparse()
- */
-typedef struct _synTables {
- char *versionString;
- optionTbl_t *longOptionTbl;
- subcommand_t *subcommandTbl;
- object_t *objectTbl;
- objectRules_t *objectRulesTbl;
- optionRules_t *optionRulesTbl;
-} synTables_t;
-
-/*
- * cmdParse is a parser that checks syntax of the input command against
- * various rules tables.
- *
- * When syntax is successfully validated, the function associated with the
- * subcommand is called using the subcommands table functions.
- *
- * Syntax for the command is as follows:
- *
- * command subcommand [<options>] object [<operand ...>]
- *
- *
- * There are two standard short and long options assumed:
- * -?, --help Provides usage on a command or subcommand
- * and stops further processing of the arguments
- *
- * -V, --version Provides version information on the command
- * and stops further processing of the arguments
- *
- * These options are loaded by this function.
- *
- * input:
- * argc, argv from main
- * syntax rules tables (synTables_t structure)
- * callArgs - void * passed by caller to be passed to subcommand function
- *
- * output:
- * funcRet - pointer to int that holds subcommand function return value
- *
- * Returns:
- *
- * zero on successful syntax parse and function call
- *
- * 1 on unsuccessful syntax parse (no function has been called)
- * This could be due to a version or help call or simply a
- * general usage call.
- *
- * -1 check errno, call failed
- *
- */
-int cmdParse(int numOperands, char *operands[], synTables_t synTables,
- void *callerArgs, int *funcRet);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _CMDPARSE_H */
diff --git a/usr/src/cmd/iscsi/iscsitadm/helper.c b/usr/src/cmd/iscsi/iscsitadm/helper.c
deleted file mode 100644
index e34bd3f8b6..0000000000
--- a/usr/src/cmd/iscsi/iscsitadm/helper.c
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <wchar.h>
-#include <widec.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <unistd.h>
-#include <libintl.h>
-#include <limits.h>
-#include <string.h>
-#include <strings.h>
-#include <syslog.h>
-#include <errno.h>
-#include <netinet/in.h>
-#include <sys/iscsi_protocol.h>
-#include <door.h>
-#include <sys/scsi/generic/inquiry.h>
-#include <sys/mman.h>
-#include <sys/filio.h>
-#include <libxml/xmlreader.h>
-#include <libscf.h>
-#include <fcntl.h>
-
-#include <iscsitgt_impl.h>
-#include "cmdparse.h"
-#include "utility.h"
-#include "helper.h"
-
-extern char *cmdName;
-
-static stat_delta_t *stat_head;
-
-/*
- * []----
- * | buffer_xml -- buffer incoming XML response until complete
- * |
- * | Incoming data from target may not be a complete XML message. So,
- * | we need to wait until we've got everything otherwise the XML routines
- * | will generate a parsing error for a short buffer.
- * []----
- */
-Boolean_t
-buffer_xml(char *s, char **storage, tgt_node_t **np)
-{
- tgt_node_t *node = NULL;
- xmlTextReaderPtr r;
- char *p,
- *e,
- *end_tag,
- hold_ch;
-
- p = *storage;
- if (s != NULL) {
- if (p == NULL) {
- p = strdup(s);
- } else {
- p = realloc(p, strlen(p) + strlen(s) + 1);
- (void) strcat(p, s);
- }
- }
- if (p == NULL) {
- return (False);
- }
-
- if (*p != '<') {
- return (False);
- }
-
- if ((e = strchr(p, '>')) == NULL) {
- return (False);
- }
-
- /*
- * The +3 is for the slash, closing tag character and null
- * For example if p is pointing at a string which starts with
- * "<foo>...."
- * p will point at '<' and e will point at '>'. e - p is 4, yet
- * the tag length is really 5 characters. We will need to create
- * the end tag which also has a slash and NULL byte.
- */
- if ((end_tag = malloc(e - p + 3)) == NULL) {
- return (False);
- }
-
- end_tag[0] = '<';
- end_tag[1] = '/';
-
- /*
- * Copy in the tag value and the closing tag character '>'.
- */
- bcopy(p + 1, &end_tag[2], e - p);
-
- /*
- * Add the null byte
- */
- end_tag[e - p + 2] = '\0';
-
- /*
- * Do we have the closing string yet? If not, just return
- */
- if ((e = strstr(p, end_tag)) == NULL) {
- *storage = p;
- return (False);
- }
-
- /*
- * Move past the closing tag and free the end_tag memory
- */
- e += strlen(end_tag);
- free(end_tag);
-
- /*
- * NULL terminate the string and remember to save that character
- * so that we can restore it later.
- */
- hold_ch = *e;
- *e = '\0';
-
- if ((r = (xmlTextReaderPtr)xmlReaderForMemory(p, strlen(p), NULL,
- NULL, 0)) == NULL)
- return (False);
-
- while (xmlTextReaderRead(r) == 1) {
- if (tgt_node_process(r, &node) == False)
- break;
- }
-
- *np = node;
-
- xmlFreeTextReader(r);
-
- *e = hold_ch;
- for (; isspace(*e); e++)
- ;
- if (*e != '\0') {
- *storage = strdup(e);
- } else
- *storage = NULL;
- free(p);
- return (True);
-}
-
-/*
- * Retrieve CHAP secret from input
- */
-int
-getSecret(char *secret, int *secretLen, int minSecretLen, int maxSecretLen)
-{
- char *chapSecret;
-
- /* XXX Should we prompt for hex or ascii printable input? */
-
- /* get password */
- chapSecret = getpassphrase(gettext("Enter secret:"));
-
- if (strlen(chapSecret) > maxSecretLen) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("secret too long"));
- *secret = NULL;
- return (1);
- }
-
- if (strlen(chapSecret) < minSecretLen && strlen(chapSecret) != 0) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("secret too short"));
- *secret = NULL;
- return (1);
- }
-
- (void) strcpy(secret, chapSecret);
-
- chapSecret = getpassphrase(gettext("Re-enter secret:"));
- if (strcmp(secret, chapSecret) != 0) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("secret not changed"));
- *secret = NULL;
- return (1);
- }
- *secretLen = strlen(chapSecret);
- return (0);
-}
-
-void
-iSCSINameCheckStatusDisplay(iSCSINameCheckStatusType status)
-{
- switch (status) {
- case iSCSINameLenZero:
- (void) fprintf(stderr, "%s: %s\n",
- cmdName, gettext("empty iSCSI name."));
- break;
- case iSCSINameLenExceededMax:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("iSCSI name exceeded maximum length."));
- break;
- case iSCSINameUnknownType:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("unknown iSCSI name type."));
- break;
- case iSCSINameIqnFormatError:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("iqn formatting error."));
- break;
- case iSCSINameEUIFormatError:
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("eui formatting error."));
- break;
- }
-}
-
-/*
- * This helper function could go into a utility module for general use.
- */
-int
-parseAddress(char *address_port_str,
- uint16_t defaultPort,
- char *address_str,
- size_t address_str_len,
- uint16_t *port,
- boolean_t *isIpv6)
-{
- char port_str[64];
- int tmp_port;
-
- if (address_port_str[0] == '[') {
- /* IPv6 address */
- char *close_bracket_pos;
- close_bracket_pos = strchr(address_port_str, ']');
- if (!close_bracket_pos) {
- syslog(LOG_USER|LOG_DEBUG,
- "IP address format error: %s\n", address_str);
- return (PARSE_ADDR_MISSING_CLOSING_BRACKET);
- }
-
- *close_bracket_pos = NULL;
- (void) strlcpy(address_str, &address_port_str[1],
- address_str_len);
-
- /* Extract the port number */
- close_bracket_pos++;
- if (*close_bracket_pos == ':') {
- close_bracket_pos++;
- if (*close_bracket_pos != NULL) {
- (void) strlcpy(port_str, close_bracket_pos,
- 64);
- tmp_port = atoi(port_str);
- if (((tmp_port > 0) &&
- (tmp_port > USHRT_MAX)) ||
- (tmp_port < 0)) {
- /* Port number out of range */
- syslog(LOG_USER|LOG_DEBUG,
- "Specified port out of range: %d",
- tmp_port);
- return (PARSE_ADDR_PORT_OUT_OF_RANGE);
- } else {
- *port = (uint16_t)tmp_port;
- }
- } else {
- *port = defaultPort;
- }
- } else {
- *port = defaultPort;
- }
-
- *isIpv6 = B_TRUE;
- } else {
- /* IPv4 address */
- char *colon_pos;
- colon_pos = strchr(address_port_str, ':');
- if (!colon_pos) {
- /* No port number specified. */
- *port = defaultPort;
- (void) strlcpy(address_str, address_port_str,
- address_str_len);
- } else {
- *colon_pos = (char)NULL;
- (void) strlcpy(address_str, address_port_str,
- address_str_len);
-
- /* Extract the port number */
- colon_pos++;
- if (*colon_pos != NULL) {
- (void) strlcpy(port_str, colon_pos, 64);
- tmp_port = atoi(port_str);
- if (((tmp_port > 0) &&
- (tmp_port > USHRT_MAX)) ||
- (tmp_port < 0)) {
- /* Port number out of range */
- syslog(LOG_USER|LOG_DEBUG,
- "Specified port out of range: %d",
- tmp_port);
- return (PARSE_ADDR_PORT_OUT_OF_RANGE);
- } else {
- *port = (uint16_t)tmp_port;
- }
- } else {
- *port = defaultPort;
- }
- }
-
- *isIpv6 = B_FALSE;
- }
-
- return (PARSE_ADDR_OK);
-}
-
-/*
- * []----
- * | Following routine (number_to_scaled_string) is lifted
- * | from usr/src/cmd/fs.d/df.c
- * []----
- */
-/*
- * Convert an unsigned long long to a string representation and place the
- * result in the caller-supplied buffer.
- * The given number is in units of "unit_from" size,
- * this will first be converted to a number in 1024 or 1000 byte size,
- * depending on the scaling factor.
- * Then the number is scaled down until it is small enough to be in a good
- * human readable format i.e. in the range 0 thru scale-1.
- * If it's smaller than 10 there's room enough to provide one decimal place.
- * The value "(unsigned long long)-1" is a special case and is always
- * converted to "-1".
- * Returns a pointer to the caller-supplied buffer.
- */
-char *
-number_to_scaled_string(
- char *buf, /* put the result here */
- unsigned long long number, /* convert this number */
- int unit_from,
- int scale)
-{
- unsigned long long save = 0;
- char *M = "KMGTPE"; /* Measurement: kilo, mega, giga, tera, peta, exa */
- char *uom = M; /* unit of measurement, initially 'K' (=M[0]) */
-
- if ((long long)number == (long long)-1) {
- (void) strcpy(buf, "-1");
- return (buf);
- }
-
- if ((number < scale) && (unit_from == 1)) {
- (void) sprintf(buf, "%4llu", number);
- return (buf);
- }
- /*
- * Convert number from unit_from to given scale (1024 or 1000).
- * This means multiply number by unit_from and divide by scale.
- *
- * Would like to multiply by unit_from and then divide by scale,
- * but if the first multiplication would overflow, then need to
- * divide by scale and then multiply by unit_from.
- */
- if (number > (UINT64_MAX / (unsigned long long)unit_from)) {
- number = (number / (unsigned long long)scale) *
- (unsigned long long)unit_from;
- } else {
- number = (number * (unsigned long long)unit_from) /
- (unsigned long long)scale;
- }
-
- /*
- * Now we have number as a count of scale units.
- * Stop scaling when we reached exa bytes, then something is
- * probably wrong with our number.
- */
-
- while ((number >= scale) && (*uom != 'E')) {
- uom++; /* next unit of measurement */
- save = number;
- number = (number + (scale / 2)) / scale;
- }
- /* check if we should output a decimal place after the point */
- if (save && ((save / scale) < 10)) {
- /* sprintf() will round for us */
- float fnum = (float)save / scale;
- (void) sprintf(buf, "%2.1f%c", fnum, *uom);
- } else {
- (void) sprintf(buf, "%4llu%c", number, *uom);
- }
- return (buf);
-}
-
-void
-stats_load_counts(tgt_node_t *n, stat_delta_t *d)
-{
- tgt_node_t *conn = NULL,
- *lun;
- char *val;
-
- bzero(d, sizeof (*d));
- d->device = n->x_value;
-
- while (conn = tgt_node_next(n, XML_ELEMENT_CONN, conn)) {
- lun = NULL;
- while (lun = tgt_node_next(conn, XML_ELEMENT_LUN, lun)) {
- if (tgt_find_value_str(lun, XML_ELEMENT_READCMDS,
- &val) == True) {
- d->read_cmds += strtoll(val, NULL, 0);
- free(val);
- }
- if (tgt_find_value_str(lun, XML_ELEMENT_WRITECMDS,
- &val) == True) {
- d->write_cmds += strtoll(val, NULL, 0);
- free(val);
- }
- if (tgt_find_value_str(lun, XML_ELEMENT_READBLKS,
- &val) == True) {
- d->read_blks += strtoll(val, NULL, 0);
- free(val);
- }
- if (tgt_find_value_str(lun, XML_ELEMENT_WRITEBLKS,
- &val) == True) {
- d->write_blks += strtoll(val, NULL, 0);
- free(val);
- }
- }
- }
-}
-
-stat_delta_t *
-stats_prev_counts(stat_delta_t *cp)
-{
- stat_delta_t *n;
-
- for (n = stat_head; n; n = n->next) {
- if (strcmp(n->device, cp->device) == 0)
- return (n);
- }
- if ((n = calloc(1, sizeof (*n))) == NULL)
- return (NULL);
- n->device = strdup(cp->device);
- if (stat_head == NULL)
- stat_head = n;
- else {
- n->next = stat_head;
- stat_head = n;
- }
- return (n);
-}
-
-void
-stats_update_counts(stat_delta_t *p, stat_delta_t *c)
-{
- p->read_cmds += c->read_cmds - p->read_cmds;
- p->write_cmds += c->write_cmds - p->write_cmds;
- p->read_blks += c->read_blks - p->read_blks;
- p->write_blks += c->write_blks - p->write_blks;
-}
-
-void
-stats_free()
-{
- stat_delta_t *n;
-
- /* CSTYLED */
- for (;stat_head;) {
- n = stat_head->next;
- free(stat_head->device);
- free(stat_head);
- stat_head = n;
- }
-}
-
-static char spaces[128];
-
-/*
- * []----
- * | dospace -- generate a string which has the appropriate number of spaces
- * |
- * | NOTE: Since this function modifies a static buffer usage of this
- * | function may not be what's expected. For example:
- * | printf("%sfoo%sbar\n", dospace(1), dospace(2)); would produce
- * | ' foo bar'
- * | instead of
- * | ' foo bar'
- * []----
- */
-char *
-dospace(int n)
-{
- (void) memset(spaces, ' ', sizeof (spaces));
- spaces[sizeof (spaces) - 1] = '\0';
-
- if (n < sizeof (spaces))
- spaces[n * 4] = '\0';
- return (spaces);
-}
diff --git a/usr/src/cmd/iscsi/iscsitadm/helper.h b/usr/src/cmd/iscsi/iscsitadm/helper.h
deleted file mode 100644
index 0f4727db6e..0000000000
--- a/usr/src/cmd/iscsi/iscsitadm/helper.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _HELPER_H
-#define _HELPER_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define MAX_ISCSI_NAME_LEN 223
-#define MAX_ADDRESS_LEN 255
-#define MIN_CHAP_SECRET_LEN 12
-#define MAX_CHAP_SECRET_LEN 16
-#define DEFAULT_ISCSI_PORT 3260
-#define DEFAULT_RADIUS_PORT 1812
-#define MAX_CHAP_NAME_LEN 512
-
-/* forward declarations */
-#define PARSE_ADDR_OK 0
-#define PARSE_ADDR_MISSING_CLOSING_BRACKET 1
-#define PARSE_ADDR_PORT_OUT_OF_RANGE 2
-#define PARSE_TARGET_OK 0
-#define PARSE_TARGET_INVALID_TPGT 1
-#define PARSE_TARGET_INVALID_ADDR 2
-
-typedef enum iSCSINameCheckStatus {
- iSCSINameCheckOK,
- iSCSINameLenZero,
- iSCSINameLenExceededMax,
- iSCSINameUnknownType,
- iSCSINameIqnFormatError,
- iSCSINameEUIFormatError
-} iSCSINameCheckStatusType;
-
-typedef struct stat_delta {
- struct stat_delta *next;
- char *device;
- size_t read_cmds,
- write_cmds,
- read_blks,
- write_blks;
-} stat_delta_t;
-
-/* helper functions */
-int getSecret(char *, int *, int, int);
-tgt_node_t *send_data(char *hostname, char *first_str);
-int parseAddress(char *address_port_str, uint16_t defaultPort,
- char *address_str, size_t address_str_len,
- uint16_t *port, boolean_t *isIpv6);
-char *number_to_scaled_string(
- char *buf,
- unsigned long long number,
- int unit_from,
- int scale);
-void stats_load_counts(tgt_node_t *n, stat_delta_t *d);
-stat_delta_t *stats_prev_counts(stat_delta_t *cp);
-void stats_update_counts(stat_delta_t *p, stat_delta_t *c);
-void stats_free();
-char *dospace(int n);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _HELPER_H */
diff --git a/usr/src/cmd/iscsi/iscsitadm/main.c b/usr/src/cmd/iscsi/iscsitadm/main.c
deleted file mode 100644
index a9fde81567..0000000000
--- a/usr/src/cmd/iscsi/iscsitadm/main.c
+++ /dev/null
@@ -1,1674 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <unistd.h>
-#include <libintl.h>
-#include <limits.h>
-#include <string.h>
-#include <syslog.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <zone.h>
-#include <netdb.h>
-
-#include <iscsitgt_impl.h>
-#include "cmdparse.h"
-#include "helper.h"
-
-#define CREATE SUBCOMMAND(0)
-#define LIST SUBCOMMAND(1)
-#define MODIFY SUBCOMMAND(2)
-#define DELETE SUBCOMMAND(3)
-#define SHOW SUBCOMMAND(4)
-
-#define TARGET OBJECT(0)
-#define INITIATOR OBJECT(1)
-#define ADMIN OBJECT(2)
-#define TPGT OBJECT(3)
-#define STATS OBJECT(4)
-
-#define VERSION_STRING_MAX_LEN 10
-#define MAX_IPADDRESS_LEN 128
-
-/*
- * Version number:
- * MAJOR - This should only change when there is an incompatible change made
- * to the interfaces or the output.
- *
- * MINOR - This should change whenever there is a new command or new feature
- * with no incompatible change.
- */
-#define VERSION_STRING_MAJOR "1"
-#define VERSION_STRING_MINOR "0"
-
-#define OPT_ENABLE "enable"
-#define OPT_DISABLE "disable"
-#define OPT_TRUE "true"
-#define OPT_FALSE "false"
-
-/* subcommand functions */
-static int createFunc(int, char **, int, cmdOptions_t *, void *);
-static int listFunc(int, char **, int, cmdOptions_t *, void *);
-static int modifyFunc(int, char **, int, cmdOptions_t *, void *);
-static int deleteFunc(int, char **, int, cmdOptions_t *, void *);
-static int showFunc(int, char **, int, cmdOptions_t *, void *);
-
-/* object functions per subcommand */
-static int createTarget(int, char *[], cmdOptions_t *);
-static int createInitiator(int, char *[], cmdOptions_t *);
-static int createTpgt(int, char *[], cmdOptions_t *);
-static int modifyTarget(int, char *[], cmdOptions_t *);
-static int modifyInitiator(int, char *[], cmdOptions_t *);
-static int modifyTpgt(int, char *[], cmdOptions_t *);
-static int modifyAdmin(int, char *[], cmdOptions_t *);
-static int deleteTarget(int, char *[], cmdOptions_t *);
-static int deleteInitiator(int, char *[], cmdOptions_t *);
-static int deleteTpgt(int, char *[], cmdOptions_t *);
-static int listTarget(int, char *[], cmdOptions_t *);
-static int listInitiator(int, char *[], cmdOptions_t *);
-static int listTpgt(int, char *[], cmdOptions_t *);
-static int showAdmin(int, char *[], cmdOptions_t *);
-static int showStats(int, char *[], cmdOptions_t *);
-
-/* globals */
-char *cmdName;
-
-/*
- * Add new options here
- */
-optionTbl_t longOptions[] = {
- {"size", required_arg, 'z', "size k/m/g/t"},
- {"type", required_arg, 't', "disk/tape/osd/raw"},
- {"lun", required_arg, 'u', "number"},
- {"alias", required_arg, 'a', "value"},
- {"backing-store", required_arg, 'b', "pathname"},
- {"tpgt", required_arg, 'p', "tpgt number"},
- {"acl", required_arg, 'l', "local initiator"},
- {"maxrecv", required_arg, 'm', "max recv data segment length"},
- {"chap-secret", no_arg, 'C', NULL},
- {"chap-name", required_arg, 'H', "chap username"},
- {"iqn", required_arg, 'n', "iSCSI node name"},
- {"ip-address", required_arg, 'i', "ip address"},
- {"base-directory", required_arg, 'd', "directory"},
- {"radius-access", required_arg, 'R', "enable/disable"},
- {"radius-server", required_arg, 'r', "hostname[:port]"},
- {"radius-secret", no_arg, 'P', NULL},
- {"isns-access", required_arg, 'S', "enable/disable"},
- {"isns-server", required_arg, 's', "hostname[:port]"},
- {"fast-write-ack", required_arg, 'f', "enable/disable"},
- {"verbose", no_arg, 'v', NULL},
- {"interval", required_arg, 'I', "seconds"},
- {"count", required_arg, 'N', "number"},
- {"all", no_arg, 'A', NULL},
- {NULL, 0, 0, 0}
-};
-
-/*
- * Add new subcommands here
- */
-subcommand_t subcommands[] = {
- {"create", CREATE, createFunc},
- {"list", LIST, listFunc},
- {"modify", MODIFY, modifyFunc},
- {"delete", DELETE, deleteFunc},
- {"show", SHOW, showFunc},
- {NULL, 0, NULL}
-};
-
-/*
- * Add objects here
- */
-object_t objects[] = {
- {"target", TARGET},
- {"initiator", INITIATOR},
- {"admin", ADMIN},
- {"tpgt", TPGT},
- {"stats", STATS},
- {NULL, 0}
-};
-
-/*
- * Rules for subcommands and objects
- * ReqiredOp, OptioalOp, NoOp, InvalidOp, MultiOp
- */
-objectRules_t objectRules[] = {
- /*
- * create/modify/delete subcmd requires an operand
- * list subcmd optionally requires an operand
- * no subcmd requires no operand
- * no subcmd is invalid for this operand
- * no subcmd can accept multiple operands
- */
- {TARGET, CREATE|MODIFY|DELETE, LIST, 0, SHOW, 0, "local-target"},
- /*
- * create/modify/delete subcmd requires an operand
- * list subcmd optionally requires an operand
- * no subcmd requires no operand
- * no subcmd is invalid for this operand
- * no subcmd can accept multiple operands
- */
- {INITIATOR, CREATE|MODIFY|DELETE, LIST, 0, SHOW, 0, "local-initiator"},
- /*
- * no subcmd requires an operand
- * no subcmd optionally requires an operand
- * modify/list subcmd requires no operand
- * create/delete subcmd are invlaid for this operand
- * no subcmd can accept multiple operands
- */
- {ADMIN, 0, 0, MODIFY|SHOW, CREATE|DELETE|LIST, 0, NULL},
- /*
- * create/modify/delete subcmd requires an operand
- * list subcmd optionally requires an operand
- * no subcmd requires no operand
- * no subcmd is invalid for this operand
- * no subcmd can accept multiple operands
- */
- {TPGT, CREATE|MODIFY|DELETE, LIST, 0, SHOW, 0, "local-tpgt"},
- /*
- * no subcmd requires an operand
- * list subcmd optionally requires an operand
- * no subcmd requires no operand
- * create/delete/modify subcmd are invalid for this operand
- * no subcmd can accept multiple operands
- */
- {STATS, 0, SHOW, 0, CREATE|MODIFY|DELETE|LIST, 0, "local-target"},
- {0, 0, 0, 0, 0, NULL}
-};
-
-/*
- * list of objects, subcommands, valid short options, required flag and
- * exclusive option string
- *
- * If it's not here, there are no options for that object.
- */
-optionRules_t optionRules[] = {
- {TARGET, CREATE, "tuzab", B_TRUE, NULL},
- {TARGET, MODIFY, "plamzu", B_TRUE, NULL},
- {TARGET, DELETE, "ulp", B_TRUE, NULL},
- {TARGET, LIST, "v", B_FALSE, NULL},
- {INITIATOR, CREATE, "n", B_TRUE, NULL},
- {INITIATOR, MODIFY, "CH", B_TRUE, NULL},
- {INITIATOR, DELETE, "A", B_TRUE, NULL},
- {INITIATOR, LIST, "v", B_FALSE, NULL},
- {TPGT, MODIFY, "i", B_TRUE, NULL},
- {TPGT, DELETE, "Ai", B_TRUE, NULL},
- {TPGT, LIST, "v", B_FALSE, NULL},
- {ADMIN, MODIFY, "dHCRrPSsf", B_TRUE, NULL},
- {STATS, SHOW, "IN", B_FALSE, NULL},
-};
-
-
-
-/*ARGSUSED*/
-static int
-createFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
- void *addArgs)
-{
- int ret;
-
- switch (object) {
- case TARGET:
- ret = createTarget(operandLen, operand, options);
- break;
- case INITIATOR:
- ret = createInitiator(operandLen, operand, options);
- break;
- case TPGT:
- ret = createTpgt(operandLen, operand, options);
- break;
- default:
- (void) fprintf(stderr, "%s: %s\n",
- cmdName, gettext("unknown object"));
- ret = 1;
- break;
- }
- return (ret);
-}
-
-/*ARGSUSED*/
-static int
-listFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
- void *addArgs)
-{
- int ret;
-
- switch (object) {
- case TARGET:
- ret = listTarget(operandLen, operand, options);
- break;
- case INITIATOR:
- ret = listInitiator(operandLen, operand, options);
- break;
- case TPGT:
- ret = listTpgt(operandLen, operand, options);
- break;
- default:
- (void) fprintf(stderr, "%s: %s\n",
- cmdName, gettext("unknown object"));
- ret = 1;
- break;
- }
- return (ret);
-}
-
-/*ARGSUSED*/
-static int
-showFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
- void *addArgs)
-{
- int ret;
-
- switch (object) {
- case STATS:
- ret = showStats(operandLen, operand, options);
- break;
- case ADMIN:
- ret = showAdmin(operandLen, operand, options);
- break;
- default:
- (void) fprintf(stderr, "%s: %s\n",
- cmdName, gettext("unknown object"));
- ret = 1;
- break;
- }
- return (ret);
-}
-
-/*ARGSUSED*/
-static int
-modifyFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
- void *addArgs)
-{
- int ret;
-
- switch (object) {
- case TARGET:
- ret = modifyTarget(operandLen, operand, options);
- break;
- case INITIATOR:
- ret = modifyInitiator(operandLen, operand, options);
- break;
- case TPGT:
- ret = modifyTpgt(operandLen, operand, options);
- break;
- case ADMIN:
- ret = modifyAdmin(operandLen, operand, options);
- break;
- default:
- (void) fprintf(stderr, "%s: %s\n",
- cmdName, gettext("unknown object"));
- ret = 1;
- break;
- }
- return (ret);
-}
-
-/*ARGSUSED*/
-static int
-deleteFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
- void *addArgs)
-{
- int ret;
-
- switch (object) {
- case TARGET:
- ret = deleteTarget(operandLen, operand, options);
- break;
- case INITIATOR:
- ret = deleteInitiator(operandLen, operand, options);
- break;
- case TPGT:
- ret = deleteTpgt(operandLen, operand, options);
- break;
- default:
- (void) fprintf(stderr, "%s: %s\n",
- cmdName, gettext("unknown object"));
- ret = 1;
- break;
- }
- return (ret);
-}
-
-static int
-formatErrString(tgt_node_t *node)
-{
- int code = 0;
- int rtn = 0;
- char *msg = NULL;
-
- if (node == NULL) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("Unable to contact target daemon"));
- return (1);
- }
- if ((strcmp(node->x_name, XML_ELEMENT_ERROR) == 0) &&
- (tgt_find_value_int(node, XML_ELEMENT_CODE, &code) == B_TRUE) &&
- (tgt_find_value_str(node, XML_ELEMENT_MESSAGE, &msg) == B_TRUE)) {
-
- /*
- * 1000 is the success code, so we don't need to display
- * the success message.
- */
- if (code != 1000) {
- (void) fprintf(stderr, "%s: %s %s\n",
- cmdName, gettext("Error"), msg);
- rtn = 1;
- }
- } else {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("Bad XML response"));
- rtn = 1;
- }
- if (msg)
- free(msg);
- return (rtn);
-}
-
-/*ARGSUSED*/
-static int
-createTarget(int operandLen, char *operand[], cmdOptions_t *options)
-{
- char *first_str = NULL;
- tgt_node_t *node;
- cmdOptions_t *optionList = options;
-
- if (operand == NULL)
- return (1);
-
- tgt_buf_add_tag(&first_str, "create", Tag_Start);
- tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start);
- tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]);
-
- for (; optionList->optval; optionList++) {
- switch (optionList->optval) {
- case 't': /* type */
- if ((strcmp(optionList->optarg, "disk")) &&
- (strcmp(optionList->optarg, "tape")) &&
- (strcmp(optionList->optarg, "raw")) &&
- (strcmp(optionList->optarg, "osd"))) {
- (void) fprintf(stderr, "%s: %c: %s\n",
- cmdName, optionList->optval,
- gettext("unknown type"));
- free(first_str);
- return (1);
- } else {
- tgt_buf_add(&first_str,
- XML_ELEMENT_TYPE,
- optionList->optarg);
- }
- break;
- case 'z': /* size */
- tgt_buf_add(&first_str, XML_ELEMENT_SIZE,
- optionList->optarg);
- break;
- case 'u': /* lun number */
- tgt_buf_add(&first_str, XML_ELEMENT_LUN,
- optionList->optarg);
- break;
- case 'a': /* alias */
- tgt_buf_add(&first_str, XML_ELEMENT_ALIAS,
- optionList->optarg);
- break;
- case 'b': /* backing store */
- tgt_buf_add(&first_str, XML_ELEMENT_BACK,
- optionList->optarg);
- break;
- default:
- (void) fprintf(stderr, "%s: %c: %s\n",
- cmdName, optionList->optval,
- gettext("unknown option"));
- free(first_str);
- return (1);
- }
- }
-
- tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End);
- tgt_buf_add_tag(&first_str, "create", Tag_End);
-
- node = tgt_door_call(first_str, 0);
- free(first_str);
- return (formatErrString(node));
-}
-
-/*ARGSUSED*/
-static int
-createInitiator(int operandLen, char *operand[], cmdOptions_t *options)
-{
- char *first_str = NULL;
- tgt_node_t *node;
- cmdOptions_t *optionList = options;
-
- if (operand == NULL)
- return (1);
- if (options == NULL)
- return (1);
-
- tgt_buf_add_tag(&first_str, "create", Tag_Start);
- tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start);
- tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]);
-
- switch (optionList->optval) {
- case 'n': /* iqn */
- tgt_buf_add(&first_str, XML_ELEMENT_INAME, optionList->optarg);
- break;
- default:
- (void) fprintf(stderr, "%s: %c: %s\n",
- cmdName, optionList->optval,
- gettext("unknown option"));
- free(first_str);
- return (1);
- }
-
- tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End);
- tgt_buf_add_tag(&first_str, "create", Tag_End);
-
- node = tgt_door_call(first_str, 0);
- free(first_str);
- return (formatErrString(node));
-}
-
-/*ARGSUSED*/
-static int
-createTpgt(int operandLen, char *operand[], cmdOptions_t *options)
-{
- char *first_str = NULL;
- tgt_node_t *node;
-
- if (operand == NULL)
- return (1);
-
- tgt_buf_add_tag(&first_str, "create", Tag_Start);
- tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start);
- tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]);
- tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End);
- tgt_buf_add_tag(&first_str, "create", Tag_End);
-
- node = tgt_door_call(first_str, 0);
- free(first_str);
- return (formatErrString(node));
-}
-
-/*ARGSUSED*/
-static int
-modifyTarget(int operandLen, char *operand[], cmdOptions_t *options)
-{
- char *first_str = NULL;
- tgt_node_t *node;
- cmdOptions_t *optionList = options;
-
- if (operand == NULL)
- return (1);
-
- tgt_buf_add_tag(&first_str, "modify", Tag_Start);
- tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start);
- tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]);
-
- for (; optionList->optval; optionList++) {
- switch (optionList->optval) {
- case 'p': /* tpgt number */
- tgt_buf_add(&first_str, XML_ELEMENT_TPGT,
- optionList->optarg);
- break;
- case 'l': /* acl */
- tgt_buf_add(&first_str, XML_ELEMENT_ACL,
- optionList->optarg);
- break;
- case 'a': /* alias */
- tgt_buf_add(&first_str, XML_ELEMENT_ALIAS,
- optionList->optarg);
- break;
- case 'm': /* max recv */
- tgt_buf_add(&first_str, XML_ELEMENT_MAXRECV,
- optionList->optarg);
- break;
- case 'z': /* grow lun size */
- tgt_buf_add(&first_str, XML_ELEMENT_SIZE,
- optionList->optarg);
- break;
- case 'u':
- tgt_buf_add(&first_str, XML_ELEMENT_LUN,
- optionList->optarg);
- break;
- default:
- (void) fprintf(stderr, "%s: %c: %s\n",
- cmdName, optionList->optval,
- gettext("unknown option"));
- free(first_str);
- return (1);
- }
- }
-
- tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End);
- tgt_buf_add_tag(&first_str, "modify", Tag_End);
-
- node = tgt_door_call(first_str, 0);
- free(first_str);
- return (formatErrString(node));
-}
-
-/*ARGSUSED*/
-static int
-modifyInitiator(int operandLen, char *operand[], cmdOptions_t *options)
-{
- char *first_str = NULL;
- tgt_node_t *node;
- cmdOptions_t *optionList = options;
- char chapSecret[MAX_CHAP_SECRET_LEN+1];
- int secretLen = 0;
- int ret = 0;
-
- if (operand == NULL)
- return (1);
- if (options == NULL)
- return (1);
-
- tgt_buf_add_tag(&first_str, "modify", Tag_Start);
- tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start);
- tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]);
-
- for (; optionList->optval; optionList++) {
- switch (optionList->optval) {
- case 'H': /* chap-name */
- if (strlen(optionList->optarg) != 0) {
- tgt_buf_add(&first_str, XML_ELEMENT_CHAPNAME,
- optionList->optarg);
- } else {
- tgt_buf_add(&first_str,
- XML_ELEMENT_DELETE_CHAPNAME,
- OPT_TRUE);
- }
- break;
- case 'C': /* chap-secret */
- ret = getSecret((char *)&chapSecret[0], &secretLen,
- MIN_CHAP_SECRET_LEN, MAX_CHAP_SECRET_LEN);
- if (ret != 0) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("Cannot read CHAP secret"));
- return (ret);
- }
- chapSecret[secretLen] = '\0';
- if (secretLen != 0) {
- tgt_buf_add(&first_str, XML_ELEMENT_CHAPSECRET,
- chapSecret);
- } else {
- tgt_buf_add(&first_str,
- XML_ELEMENT_DELETE_CHAPSECRET,
- OPT_TRUE);
- }
- break;
- default:
- (void) fprintf(stderr, "%s: %c: %s\n",
- cmdName, optionList->optval,
- gettext("unknown option"));
- free(first_str);
- return (1);
- }
- }
- tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End);
- tgt_buf_add_tag(&first_str, "modify", Tag_End);
-
- node = tgt_door_call(first_str, 0);
- free(first_str);
- return (formatErrString(node));
-}
-
-/*ARGSUSED*/
-static int
-modifyTpgt(int operandLen, char *operand[], cmdOptions_t *options)
-{
- char *first_str = NULL;
- tgt_node_t *node;
- cmdOptions_t *optionList = options;
- boolean_t isIpv6 = B_FALSE;
- uint16_t port;
- char IpAddress[MAX_IPADDRESS_LEN];
-
- if (operand == NULL)
- return (1);
- if (optionList == NULL)
- return (1);
-
- tgt_buf_add_tag(&first_str, "modify", Tag_Start);
- tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start);
- tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]);
-
- switch (optionList->optval) {
- case 'i': /* ip address */
- if (parseAddress(optionList->optarg, 0,
- IpAddress, 256, &port, &isIpv6) !=
- PARSE_ADDR_OK) {
- return (1);
- }
- tgt_buf_add(&first_str, XML_ELEMENT_IPADDR, IpAddress);
- break;
- default:
- (void) fprintf(stderr, "%s: %c: %s\n",
- cmdName, optionList->optval,
- gettext("unknown option"));
- free(first_str);
- return (1);
- }
-
- tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End);
- tgt_buf_add_tag(&first_str, "modify", Tag_End);
-
- node = tgt_door_call(first_str, 0);
- free(first_str);
- return (formatErrString(node));
-}
-
-/*ARGSUSED*/
-static int
-modifyAdmin(int operandLen, char *operand[], cmdOptions_t *options)
-{
- char *first_str = NULL;
- tgt_node_t *node;
- cmdOptions_t *optionList = options;
- char chapSecret[MAX_CHAP_SECRET_LEN+1];
- char olddir[MAXPATHLEN];
- char newdir[MAXPATHLEN];
- int secretLen = 0;
- int ret = 0;
-
- if (operand == NULL)
- return (1);
- if (options == NULL)
- return (1);
-
- tgt_buf_add_tag(&first_str, "modify", Tag_Start);
- tgt_buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_Start);
- tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]);
-
- for (; optionList->optval; optionList++) {
- switch (optionList->optval) {
- case 'd': /* base directory */
- (void) getcwd(olddir, sizeof (olddir));
-
- /*
- * Attempt to create the new base directory.
- * This may fail for one of two reasons.
- * (a) The path given is invalid or (b) it
- * already exists. If (a) is true then then
- * following chdir() will fail and the user
- * notified. If (b) is true, then chdir() will
- * succeed.
- */
- (void) mkdir(optionList->optarg, 0700);
-
- if (chdir(optionList->optarg) == -1) {
- (void) fprintf(stderr, "%s: %s\n",
- cmdName, gettext("Invalid path"));
- free(first_str);
- return (1);
- }
- (void) getcwd(newdir, sizeof (newdir));
- tgt_buf_add(&first_str, XML_ELEMENT_BASEDIR,
- newdir);
- (void) chdir(olddir);
- break;
- case 'H': /* chap name */
- if (strlen(optionList->optarg) != 0) {
- tgt_buf_add(&first_str,
- XML_ELEMENT_CHAPNAME,
- optionList->optarg);
- } else {
- tgt_buf_add(&first_str,
- XML_ELEMENT_DELETE_CHAPNAME,
- OPT_TRUE);
- }
- break;
- case 'C': /* chap secert */
- ret = getSecret((char *)&chapSecret[0],
- &secretLen,
- MIN_CHAP_SECRET_LEN,
- MAX_CHAP_SECRET_LEN);
- if (ret != 0) {
- (void) fprintf(stderr, "%s: %s\n",
- cmdName,
- gettext("Cannot read CHAP secret"));
- free(first_str);
- return (ret);
- }
- chapSecret[secretLen] = '\0';
- if (secretLen != 0) {
- tgt_buf_add(&first_str,
- XML_ELEMENT_CHAPSECRET,
- chapSecret);
- } else {
- tgt_buf_add(&first_str,
- XML_ELEMENT_DELETE_CHAPSECRET,
- OPT_TRUE);
- }
- break;
- case 'R': /* radius access */
- if (strcmp(optionList->optarg,
- OPT_ENABLE) == 0) {
- tgt_buf_add(&first_str,
- XML_ELEMENT_RAD_ACCESS, OPT_TRUE);
- } else
- if (strcmp(optionList->optarg,
- OPT_DISABLE) == 0) {
- tgt_buf_add(&first_str,
- XML_ELEMENT_RAD_ACCESS, OPT_FALSE);
- } else {
- (void) fprintf(stderr, "%s: %s\n",
- cmdName,
- gettext("Option value should be"
- "enable/disable"));
- free(first_str);
- return (1);
- }
- break;
- case 'r': /* radius server */
- if (strlen(optionList->optarg) != 0) {
- tgt_buf_add(&first_str,
- XML_ELEMENT_RAD_SERV,
- optionList->optarg);
- } else {
- tgt_buf_add(&first_str,
- XML_ELEMENT_DELETE_RAD_SERV,
- OPT_TRUE);
- }
- break;
- case 'P': /* radius secret */
- ret = getSecret((char *)&chapSecret[0],
- &secretLen, MIN_CHAP_SECRET_LEN,
- MAX_CHAP_SECRET_LEN);
- if (ret != 0) {
- (void) fprintf(stderr, "%s: %s\n",
- cmdName,
- gettext("Cannot read RADIUS "
- "secret"));
- free(first_str);
- return (ret);
- }
- chapSecret[secretLen] = '\0';
- if (secretLen != 0) {
- tgt_buf_add(&first_str,
- XML_ELEMENT_RAD_SECRET,
- chapSecret);
- } else {
- tgt_buf_add(&first_str,
- XML_ELEMENT_DELETE_RAD_SECRET,
- OPT_TRUE);
- }
- break;
- case 'S': /* iSNS access */
- if (strcmp(optionList->optarg,
- OPT_ENABLE) == 0) {
- tgt_buf_add(&first_str,
- XML_ELEMENT_ISNS_ACCESS, OPT_TRUE);
- } else
- if (strcmp(optionList->optarg,
- OPT_DISABLE) == 0) {
- tgt_buf_add(&first_str,
- XML_ELEMENT_ISNS_ACCESS, OPT_FALSE);
- } else {
- (void) fprintf(stderr, "%s: %s\n",
- cmdName,
- gettext("Option value should be"
- "enable/disable"));
- free(first_str);
- return (1);
- }
- break;
- case 's': /* iSNS server */
- if (strlen(optionList->optarg) >
- MAXHOSTNAMELEN) {
- (void) fprintf(stderr, "%s: %s\n",
- cmdName,
- gettext("option too long"));
- return (1);
- }
- tgt_buf_add(&first_str, XML_ELEMENT_ISNS_SERV,
- optionList->optarg);
- break;
- case 'f': /* fast write back */
- if (strcmp(optionList->optarg,
- OPT_ENABLE) == 0) {
- tgt_buf_add(&first_str,
- XML_ELEMENT_FAST, OPT_TRUE);
- } else
- if (strcmp(optionList->optarg,
- OPT_DISABLE) == 0) {
- tgt_buf_add(&first_str,
- XML_ELEMENT_FAST, OPT_FALSE);
- } else {
- (void) fprintf(stderr, "%s: %s\n",
- cmdName,
- gettext("Option value should be"
- "enable/disable"));
- free(first_str);
- return (1);
- }
- break;
- default:
- (void) fprintf(stderr, "%s: %c: %s\n",
- cmdName, optionList->optval,
- gettext("unknown option"));
- free(first_str);
- return (1);
- }
- }
-
- tgt_buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_End);
- tgt_buf_add_tag(&first_str, "modify", Tag_End);
-
- node = tgt_door_call(first_str, 0);
- free(first_str);
- return (formatErrString(node));
-}
-
-/*ARGSUSED*/
-static int
-deleteTarget(int operandLen, char *operand[], cmdOptions_t *options)
-{
- char *first_str = NULL;
- tgt_node_t *node;
- cmdOptions_t *optionList = options;
-
- if (operand == NULL)
- return (1);
- if (options == NULL)
- return (1);
-
- tgt_buf_add_tag(&first_str, "delete", Tag_Start);
- tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start);
- tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]);
-
- switch (optionList->optval) {
- case 'u': /* all */
- tgt_buf_add(&first_str, XML_ELEMENT_LUN, optionList->optarg);
- break;
- case 'l': /* acl */
- tgt_buf_add(&first_str, XML_ELEMENT_ACL, optionList->optarg);
- break;
- case 'p': /* tpgt number */
- tgt_buf_add(&first_str, XML_ELEMENT_TPGT, optionList->optarg);
- break;
- default:
- (void) fprintf(stderr, "%s: %c: %s\n",
- cmdName, optionList->optval,
- gettext("unknown option"));
- free(first_str);
- return (1);
- }
-
- tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End);
- tgt_buf_add_tag(&first_str, "delete", Tag_End);
-
- node = tgt_door_call(first_str, 0);
- free(first_str);
- return (formatErrString(node));
-}
-
-/*ARGSUSED*/
-static int
-deleteInitiator(int operandLen, char *operand[], cmdOptions_t *options)
-{
- char *first_str = NULL;
- tgt_node_t *node;
- cmdOptions_t *optionList = options;
-
- if (operand == NULL)
- return (1);
- if (options == NULL)
- return (1);
-
- tgt_buf_add_tag(&first_str, "delete", Tag_Start);
- tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start);
- tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]);
-
- switch (optionList->optval) {
- case 'A': /* all */
- tgt_buf_add(&first_str, XML_ELEMENT_ALL, optionList->optarg);
- break;
- default:
- (void) fprintf(stderr, "%s: %c: %s\n",
- cmdName, optionList->optval,
- gettext("unknown option"));
- free(first_str);
- return (1);
- }
-
- tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End);
- tgt_buf_add_tag(&first_str, "delete", Tag_End);
-
- node = tgt_door_call(first_str, 0);
- free(first_str);
- return (formatErrString(node));
-}
-
-/*ARGSUSED*/
-static int
-deleteTpgt(int operandLen, char *operand[], cmdOptions_t *options)
-{
- char *first_str = NULL;
- tgt_node_t *node;
- cmdOptions_t *optionList = options;
- boolean_t isIpv6 = B_FALSE;
- uint16_t port;
- char IpAddress[MAX_IPADDRESS_LEN];
-
- if (operand == NULL)
- return (1);
- if (options == NULL)
- return (1);
-
- tgt_buf_add_tag(&first_str, "delete", Tag_Start);
- tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start);
- tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]);
-
- switch (optionList->optval) {
- case 'A': /* all */
- tgt_buf_add(&first_str, XML_ELEMENT_ALL, optionList->optarg);
- break;
- case 'i': /* ip address */
- if (parseAddress(optionList->optarg, 0,
- IpAddress, 256, &port, &isIpv6) !=
- PARSE_ADDR_OK) {
- return (1);
- }
- tgt_buf_add(&first_str, XML_ELEMENT_IPADDR, IpAddress);
- break;
- default:
- (void) fprintf(stderr, "%s: %c: %s\n",
- cmdName, optionList->optval,
- gettext("unknown option"));
- free(first_str);
- return (1);
- }
-
- tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End);
- tgt_buf_add_tag(&first_str, "delete", Tag_End);
-
- node = tgt_door_call(first_str, 0);
- free(first_str);
- return (formatErrString(node));
-}
-
-static int
-listTarget(int operandLen, char *operand[], cmdOptions_t *options)
-{
- char *first_str = NULL;
- tgt_node_t *node = NULL;
- tgt_node_t *n1 = NULL; /* pointer to node (depth=1) */
- tgt_node_t *n2 = NULL; /* pointer to node (depth=2) */
- tgt_node_t *n3 = NULL; /* pointer to node (depth=3) */
- tgt_node_t *n4 = NULL; /* pointer to node (depth=4) */
- int conns;
- char buf[32];
- Boolean_t verbose = False;
-
- if (operand == NULL)
- return (1);
-
- tgt_buf_add_tag(&first_str, "list", Tag_Start);
- tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start);
-
- if (operandLen)
- tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]);
-
- /*
- * Always retrieve the iostats which will give us the
- * connection count information even if we're not doing
- * a verbose output.
- */
- tgt_buf_add(&first_str, XML_ELEMENT_IOSTAT, OPT_TRUE);
-
- if (options) {
- switch (options->optval) {
- case 0:
- break;
- case 'v':
- tgt_buf_add(&first_str, XML_ELEMENT_LUNINFO, OPT_TRUE);
- verbose = True;
- break;
- default:
- (void) fprintf(stderr, "%s: %c: %s\n", cmdName,
- options->optval, gettext("unknown option"));
- free(first_str);
- return (1);
- }
- }
-
- tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End);
- tgt_buf_add_tag(&first_str, "list", Tag_End);
-
- if ((node = tgt_door_call(first_str, 0)) == NULL) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("No reponse from daemon"));
- return (1);
- }
- free(first_str);
-
- if (strcmp(node->x_name, XML_ELEMENT_RESULT)) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("Bad XML response"));
- return (1);
- }
-
- n1 = NULL;
- while ((n1 = tgt_node_next_child(node, XML_ELEMENT_TARG, n1)) != NULL) {
- (void) printf("%s: %s\n", gettext("Target"), n1->x_value);
- n2 = tgt_node_next_child(n1, XML_ELEMENT_INAME, NULL);
- (void) printf("%s%s: %s\n", dospace(1), gettext("iSCSI Name"),
- n2 ? n2->x_value : gettext("Not set"));
-
- if ((n2 = tgt_node_next_child(n1, XML_ELEMENT_ALIAS, NULL)) !=
- NULL)
- (void) printf("%s%s: %s\n", dospace(1),
- gettext("Alias"), n2->x_value);
-
- if ((n2 = tgt_node_next_child(n1, XML_ELEMENT_MAXRECV, NULL)) !=
- NULL)
- (void) printf("%s%s: %s\n", dospace(1),
- gettext("MaxRecv"), n2->x_value);
-
- /*
- * Count the number of connections available.
- */
- n2 = NULL;
- conns = 0;
- while (n2 = tgt_node_next_child(n1, XML_ELEMENT_CONN, n2))
- conns++;
- (void) printf("%s%s: %d\n", dospace(1), gettext("Connections"),
- conns);
-
- if (verbose == False)
- continue;
-
- /*
- * Displaying the individual connections must be done
- * first when verbose is turned on because you'll notice
- * above that we've left the output hanging with a label
- * indicating connections are coming next.
- */
- n2 = NULL;
- while (n2 = tgt_node_next_child(n1, XML_ELEMENT_CONN, n2)) {
- (void) printf("%s%s:\n", dospace(2),
- gettext("Initiator"));
- (void) printf("%s%s: %s\n", dospace(3),
- gettext("iSCSI Name"), n2->x_value);
- n3 = tgt_node_next_child(n2, XML_ELEMENT_ALIAS, NULL);
- (void) printf("%s%s: %s\n", dospace(3),
- gettext("Alias"),
- n3 ? n3->x_value : gettext("unknown"));
- }
-
- (void) printf("%s%s:\n", dospace(1), gettext("ACL list"));
- n2 = tgt_node_next_child(n1, XML_ELEMENT_ACLLIST, NULL);
- n3 = NULL;
- while (n3 = tgt_node_next_child(n2, XML_ELEMENT_INIT, n3)) {
- (void) printf("%s%s: %s\n", dospace(2),
- gettext("Initiator"),
- n3->x_value);
- }
-
- (void) printf("%s%s:\n", dospace(1), gettext("TPGT list"));
- n2 = tgt_node_next_child(n1, XML_ELEMENT_TPGTLIST, NULL);
- n3 = NULL;
- while (n3 = tgt_node_next_child(n2, XML_ELEMENT_TPGT, n3)) {
- (void) printf("%s%s: %s\n", dospace(2),
- gettext("TPGT"),
- n3->x_value);
- }
-
- (void) printf("%s%s:\n", dospace(1),
- gettext("LUN information"));
- n2 = tgt_node_next_child(n1, XML_ELEMENT_LUNINFO, NULL);
- n3 = NULL;
- while (n3 = tgt_node_next_child(n2, XML_ELEMENT_LUN, n3)) {
- (void) printf("%s%s: %s\n", dospace(2), gettext("LUN"),
- n3->x_value);
-
- n4 = tgt_node_next_child(n3, XML_ELEMENT_GUID, NULL);
- (void) printf("%s%s: %s\n", dospace(3), gettext("GUID"),
- n4 ? n4->x_value : gettext("unknown"));
-
- n4 = tgt_node_next_child(n3, XML_ELEMENT_VID, NULL);
- (void) printf("%s%s: %s\n", dospace(3), gettext("VID"),
- n4 ? n4->x_value : gettext("unknown"));
-
- n4 = tgt_node_next_child(n3, XML_ELEMENT_PID, NULL);
- (void) printf("%s%s: %s\n", dospace(3), gettext("PID"),
- n4 ? n4->x_value : gettext("unknown"));
-
- n4 = tgt_node_next_child(n3, XML_ELEMENT_DTYPE, NULL);
- (void) printf("%s%s: %s\n", dospace(3), gettext("Type"),
- n4 ? n4->x_value : gettext("unknown"));
-
- n4 = tgt_node_next_child(n3, XML_ELEMENT_SIZE, NULL);
- if (n4 && (strtol(n4->x_value, NULL, 0) != 0)) {
- (void) printf("%s%s: %s\n", dospace(3),
- gettext("Size"),
- number_to_scaled_string(buf,
- strtoll(n4->x_value,
- NULL, 0), 512, 1024));
- } else {
- (void) printf("%s%s: %s\n", dospace(3),
- gettext("Size"), gettext("unknown"));
- }
-
- n4 = tgt_node_next_child(n3, XML_ELEMENT_BACK, NULL);
- if (n4) {
- (void) printf("%s%s: %s\n", dospace(3),
- gettext("Backing store"), n4->x_value);
- }
-
- n4 = tgt_node_next_child(n3, XML_ELEMENT_STATUS, NULL);
- (void) printf("%s%s: %s\n", dospace(3),
- gettext("Status"),
- n4 ? n4->x_value : gettext("unknown"));
- }
- }
-
- return (0);
-}
-
-static int
-listInitiator(int operandLen, char *operand[], cmdOptions_t *options)
-{
- char *first_str = NULL;
- tgt_node_t *node;
- tgt_node_t *n1 = NULL; /* pointer to node (depth=1) */
- tgt_node_t *n2 = NULL; /* pointer to node (depth=2) */
- Boolean_t verbose = False;
- cmdOptions_t *optionList = options;
-
- if (operand == NULL)
- return (1);
-
- tgt_buf_add_tag(&first_str, "list", Tag_Start);
- tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start);
-
- if (operandLen) {
- tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]);
- }
- if (optionList) {
- switch (optionList->optval) {
- case 0:
- break;
- case 'v':
- verbose = True;
- tgt_buf_add(&first_str,
- XML_ELEMENT_VERBOSE, OPT_TRUE);
- break;
-
- default:
- (void) fprintf(stderr, "%s: %c: %s\n",
- cmdName, optionList->optval,
- gettext("unknown option"));
- free(first_str);
- return (1);
- }
- }
-
- tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End);
- tgt_buf_add_tag(&first_str, "list", Tag_End);
-
- if ((node = tgt_door_call(first_str, 0)) == NULL) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("No reponse from daemon"));
- return (1);
- }
- free(first_str);
-
- if (strcmp(node->x_name, XML_ELEMENT_RESULT)) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("Bad XML response"));
- return (1);
- }
-
- n1 = NULL;
- while (n1 = tgt_node_next_child(node, XML_ELEMENT_INIT, n1)) {
- (void) printf("%s: %s\n", gettext("Initiator"), n1->x_value);
-
- n2 = tgt_node_next_child(n1, XML_ELEMENT_INAME, NULL);
- (void) printf("%s%s: %s\n", dospace(1), gettext("iSCSI Name"),
- n2 ? n2->x_value : gettext("Not set"));
-
- n2 = tgt_node_next_child(n1, XML_ELEMENT_CHAPNAME, NULL);
- (void) printf("%s%s: %s\n", dospace(1), gettext("CHAP Name"),
- n2 ? n2->x_value : gettext("Not set"));
-
- if (verbose == True) {
- n2 = tgt_node_next_child(n1, XML_ELEMENT_CHAPSECRET,
- NULL);
- (void) printf("%s%s: %s\n", dospace(1),
- gettext("CHAP Secret"),
- n2 ? gettext("Set") : gettext("Not set"));
- }
-
- }
-
- return (0);
-}
-
-static int
-listTpgt(int operandLen, char *operand[], cmdOptions_t *options)
-{
- char *first_str = NULL;
- tgt_node_t *node = NULL;
- tgt_node_t *n1 = NULL; /* pointer to node (depth=1) */
- tgt_node_t *n2 = NULL; /* pointer to node (depth=2) */
- cmdOptions_t *optionList = options;
- Boolean_t verbose = False;
- int addrs;
-
- if (operand == NULL)
- return (1);
-
- tgt_buf_add_tag(&first_str, "list", Tag_Start);
- tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start);
-
- if (operandLen)
- tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]);
- if (optionList) {
- switch (optionList->optval) {
- case 0: /* no options, treat as --verbose */
- break;
- case 'v':
- verbose = True;
- tgt_buf_add(&first_str,
- XML_ELEMENT_VERBOSE, OPT_TRUE);
- break;
- default:
- (void) fprintf(stderr, "%s: %c: %s\n",
- cmdName, optionList->optval,
- gettext("unknown option"));
- free(first_str);
- return (1);
- }
- }
-
- tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End);
- tgt_buf_add_tag(&first_str, "list", Tag_End);
-
- if ((node = tgt_door_call(first_str, 0)) == NULL) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("No reponse from daemon"));
- return (1);
- }
- free(first_str);
-
- if (strcmp(node->x_name, XML_ELEMENT_RESULT)) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("Bad XML response"));
- return (1);
- }
-
- n1 = NULL;
- while (n1 = tgt_node_next_child(node, XML_ELEMENT_TPGT, n1)) {
- (void) printf("%s: %s\n", gettext("TPGT"), n1->x_value);
- n2 = NULL;
- addrs = 0;
- while (n2 = tgt_node_next(n1, XML_ELEMENT_IPADDR, n2)) {
- if (verbose == True)
- (void) printf("%s%s: %s\n", dospace(1),
- gettext("IP Address"),
- n2 ? n2->x_value : gettext("Not set"));
- addrs++;
- }
-
- if (verbose == False) {
- (void) printf("%s%s: %d\n", dospace(1),
- gettext("IP Address count"), addrs);
- } else if (addrs == 0) {
-
- /*
- * Verbose is true, but there where no addresses
- * for this TPGT. To keep the output consistent
- * dump a "Not set" string out.
- */
- (void) printf("%s%s: %s\n", dospace(1),
- gettext("IP Address"), gettext("Not set"));
- }
- }
-
- return (0);
-}
-
-/*ARGSUSED*/
-static int
-showAdmin(int operandLen, char *operand[], cmdOptions_t *options)
-{
- char *first_str = NULL;
- tgt_node_t *node = NULL;
- tgt_node_t *n1 = NULL; /* pointer to node (depth=1) */
- tgt_node_t *n2 = NULL; /* pointer to node (depth=2) */
-
- if (operand == NULL)
- return (1);
-
- tgt_buf_add_tag(&first_str, "list", Tag_Start);
- tgt_buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_Start);
- tgt_buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_End);
- tgt_buf_add_tag(&first_str, "list", Tag_End);
-
- if ((node = tgt_door_call(first_str, 0)) == NULL) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("No reponse from daemon"));
- return (1);
- }
- free(first_str);
-
- if (strcmp(node->x_name, XML_ELEMENT_RESULT)) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("Bad XML response"));
- return (1);
- }
-
- (void) printf("%s:\n", cmdName);
-
- n1 = tgt_node_next_child(node, XML_ELEMENT_ADMIN, NULL);
- if (n1 == NULL) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("Bad XML response"));
- return (1);
- }
-
- n2 = tgt_node_next_child(n1, XML_ELEMENT_BASEDIR, NULL);
- (void) printf("%s%s: %s\n", dospace(1), gettext("Base Directory"),
- n2 ? n2->x_value : gettext("Not set"));
-
- n2 = tgt_node_next_child(n1, XML_ELEMENT_CHAPNAME, NULL);
- (void) printf("%s%s: %s\n", dospace(1), gettext("CHAP Name"),
- n2 ? n2->x_value : gettext("Not set"));
-
- n2 = tgt_node_next_child(n1, XML_ELEMENT_RAD_ACCESS, NULL);
- (void) printf("%s%s: ", dospace(1), gettext("RADIUS Access"));
- if (n2) {
- if (strcmp(n2->x_value, OPT_TRUE) == 0)
- (void) printf("%s\n", gettext("Enabled"));
- else
- (void) printf("%s\n", gettext("Disabled"));
- } else
- (void) printf("%s\n", gettext("Not set"));
-
- n2 = tgt_node_next_child(n1, XML_ELEMENT_RAD_SERV, NULL);
- (void) printf("%s%s: %s\n", dospace(1), gettext("RADIUS Server"),
- n2 ? n2->x_value : gettext("Not set"));
-
- n2 = tgt_node_next_child(n1, XML_ELEMENT_ISNS_ACCESS, NULL);
- (void) printf("%s%s: ", dospace(1), gettext("iSNS Access"));
- if (n2) {
- if (strcmp(n2->x_value, OPT_TRUE) == 0)
- (void) printf("%s\n", gettext("Enabled"));
- else
- (void) printf("%s\n", gettext("Disabled"));
- } else
- (void) printf("%s\n", gettext("Not set"));
-
- n2 = tgt_node_next_child(n1, XML_ELEMENT_ISNS_SERV, NULL);
- (void) printf("%s%s: %s\n", dospace(1), gettext("iSNS Server"),
- n2 ? n2->x_value : gettext("Not set"));
-
- n2 = tgt_node_next_child(n1, XML_ELEMENT_ISNS_SERVER_STATUS, NULL);
- if (n2) {
- /*
- * if NULL, that means either the isns discovery is
- * disabled or the server address is not set.
- */
- if (n2->x_value != NULL) {
- (void) printf("%s%s: ", dospace(1),
- gettext("iSNS Server Status"));
- (void) printf("%s\n", n2->x_value);
- }
- }
-
- n2 = tgt_node_next_child(n1, XML_ELEMENT_FAST, NULL);
- (void) printf("%s%s: ", dospace(1), gettext("Fast Write ACK"));
- if (n2) {
- if (strcmp(n2->x_value, OPT_TRUE) == 0)
- (void) printf("%s\n", gettext("Enabled"));
- else
- (void) printf("%s\n", gettext("Disabled"));
- } else
- (void) printf("%s\n", gettext("Not set"));
-
- return (0);
-}
-
-static int
-showStats(int operandLen, char *operand[], cmdOptions_t *options)
-{
- char *first_str = NULL;
- char scale_buf[16];
- tgt_node_t *node, *n1;
- int interval = -1;
- int count = -1;
- int header;
- stat_delta_t cur_data, *pd;
-
- tgt_buf_add_tag(&first_str, "list", Tag_Start);
- tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start);
-
- tgt_buf_add(&first_str, XML_ELEMENT_IOSTAT, OPT_TRUE);
- if (operandLen)
- tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]);
-
- for (; options->optval; options++) {
- switch (options->optval) {
- case 0:
- break;
- case 'I': /* optarg = refresh interval */
- interval = atoi(options->optarg);
- if (interval == 0) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("interval must be non-zero"));
- free(first_str);
- return (1);
- }
- break;
- case 'N':
- count = atoi(options->optarg);
- if (count == 0) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("count must be non-zero"));
- free(first_str);
- return (1);
- }
- break;
- default:
- (void) fprintf(stderr, "%s: %c: %s\n", cmdName,
- options->optval, gettext("unknown option"));
- free(first_str);
- return (1);
- }
- }
-
- tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End);
- tgt_buf_add_tag(&first_str, "list", Tag_End);
-
- header = 1;
- /*CONSTANTCONDITION*/
- while (1) {
- if (--header == 0) {
- (void) printf("%20s %12s %12s\n", " ",
- gettext("operations"), gettext("bandwidth "));
- (void) printf("%-20s %5s %5s %5s %5s\n",
- gettext("device"), gettext("read"),
- gettext("write"), gettext("read"),
- gettext("write"));
- (void) printf("%-20s %5s %5s %5s %5s\n",
- "--------------------", "-----", "-----",
- "-----", "-----");
- header = 20;
- }
- if ((node = tgt_door_call(first_str, 0)) == NULL) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("No reponse from daemon"));
- return (1);
- }
-
- if (strcmp(node->x_name, XML_ELEMENT_RESULT)) {
- (void) fprintf(stderr, "%s: %s\n", cmdName,
- gettext("Bad XML response"));
- free(first_str);
- tgt_node_free(node);
- stats_free();
- return (1);
- }
-
- n1 = NULL;
- while (n1 = tgt_node_next_child(node, XML_ELEMENT_TARG, n1)) {
- stats_load_counts(n1, &cur_data);
- if ((pd = stats_prev_counts(&cur_data)) == NULL) {
- free(first_str);
- tgt_node_free(node);
- return (1);
- }
- (void) printf("%-20s ", pd->device);
- (void) printf("%5s ",
- number_to_scaled_string(scale_buf,
- cur_data.read_cmds - pd->read_cmds, 1, 1024));
- (void) printf("%5s ",
- number_to_scaled_string(scale_buf,
- cur_data.write_cmds - pd->write_cmds, 1, 1024));
- (void) printf("%5s ",
- number_to_scaled_string(scale_buf,
- cur_data.read_blks - pd->read_blks, 512, 1024));
- (void) printf("%5s\n",
- number_to_scaled_string(scale_buf,
- cur_data.write_blks - pd->write_blks, 512, 1024));
- stats_update_counts(pd, &cur_data);
- }
- tgt_node_free(node);
-
- if (count == -1) {
- if (interval == -1)
- /* No count or internal, do it just once */
- break;
- else
- (void) sleep(interval);
- } else if (--count) {
- if (interval == -1)
- break;
- else
- (void) sleep(interval);
- } else
- break;
- }
-
- stats_free();
- free(first_str);
- return (0);
-}
-
-/*
- * input:
- * execFullName - exec name of program (argv[0])
- *
- * Returns:
- * command name portion of execFullName
- */
-static char *
-getExecBasename(char *execFullname)
-{
- char *lastSlash, *execBasename;
-
- /* guard against '/' at end of command invocation */
- for (;;) {
- lastSlash = strrchr(execFullname, '/');
- if (lastSlash == NULL) {
- execBasename = execFullname;
- break;
- } else {
- execBasename = lastSlash + 1;
- if (*execBasename == '\0') {
- *lastSlash = '\0';
- continue;
- }
- break;
- }
- }
- return (execBasename);
-}
-
-/*
- * main calls a parser that checks syntax of the input command against
- * various rules tables.
- *
- * The parser provides usage feedback based upon same tables by calling
- * two usage functions, usage and subUsage, handling command and subcommand
- * usage respectively.
- *
- * The parser handles all printing of usage syntactical errors
- *
- * When syntax is successfully validated, the parser calls the associated
- * function using the subcommands table functions.
- *
- * Syntax is as follows:
- * command subcommand [options] resource-type [<object>]
- *
- * The return value from the function is placed in funcRet
- */
-int
-main(int argc, char *argv[])
-{
- synTables_t synTables;
- char versionString[VERSION_STRING_MAX_LEN];
- int ret;
- int funcRet;
- void *subcommandArgs = NULL;
-
- /* set global command name */
- cmdName = getExecBasename(argv[0]);
-
- if (getzoneid() != GLOBAL_ZONEID) {
- (void) fprintf(stderr,
- "%s: this command is only available in the 'global' "
- "zone\n", cmdName);
- exit(1);
- }
-
- (void) snprintf(versionString, sizeof (versionString), "%s.%s",
- VERSION_STRING_MAJOR, VERSION_STRING_MINOR);
- synTables.versionString = versionString;
- synTables.longOptionTbl = &longOptions[0];
- synTables.subcommandTbl = &subcommands[0];
- synTables.objectTbl = &objects[0];
- synTables.objectRulesTbl = &objectRules[0];
- synTables.optionRulesTbl = &optionRules[0];
-
- /* call the CLI parser */
- ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet);
- if (ret == 1) {
- (void) printf("%s %s(1M)\n",
- gettext("For more information, please see"), cmdName);
- return (1);
- } else if (ret == -1) {
- perror(cmdName);
- return (1);
- }
-
- return (funcRet);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/Makefile b/usr/src/cmd/iscsi/iscsitgtd/Makefile
deleted file mode 100644
index 8e13a10705..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/Makefile
+++ /dev/null
@@ -1,94 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-PROG= iscsitgtd
-OBJS = main.o mgmt.o mgmt_create.o mgmt_list.o mgmt_modify.o mgmt_remove.o
-OBJS += iscsi_authclient.o iscsi_authglue.o iscsi_cmd.o iscsi_conn.o
-OBJS += iscsi_crc.o iscsi_ffp.o iscsi_login.o iscsi_sess.o radius.o
-OBJS += t10_sam.o t10_spc.o t10_sbc.o t10_raw_if.o t10_ssc.o t10_osd.o
-OBJS += t10_spc_pr.o util.o util_err.o util_ifname.o util_port.o util_queue.o
-OBJS += isns_client.o isns.o mgmt_scf.o
-POFILE= iscsitgtd.po
-POFILES = $(OBJS:%.o=%.po)
-
-include ../../Makefile.cmd
-include $(SRC)/cmd/iscsi/Makefile.iscsi
-
-$(64ONLY)SUBDIRS= $(MACH)
-$(BUILD64)SUBDIRS += $(MACH64)
-
-MANIFEST = iscsi_target.xml
-SVCMETHOD = svc-iscsitgt
-
-ROOTMANIFESTDIR = $(ROOTSVCSYSTEM)
-$(ROOTSVCSYSTEM)/iscsi_target.xml := FILEMODE = 0444
-
-DLIBSRCS = iscsi.d
-
-ROOTDLIBDIR = $(ROOT)/usr/lib/dtrace
-ROOTDLIBS = $(DLIBSRCS:%=$(ROOTDLIBDIR)/%)
-$(ROOTDLIBS) := FILEMODE = 0644
-
-CPPFLAGS += -D_FILE_OFFSET_BITS=64 -I${ISCSICOMMONDIR} -I${HDCRCCOMMONDIR}
-
-all := TARGET = all
-install := TARGET = install
-clean := TARGET = clean
-clobber := TARGET = clobber
-lint := TARGET = lint
-
-.KEEP_STATE:
-
-all: $(SUBDIRS)
-
-clean clobber lint: $(SUBDIRS)
-
-install: $(SUBDIRS) $(ROOTMANIFEST) $(ROOTDLIBS) $(ROOTSVCMETHOD)
- -$(RM) $(ROOTUSRSBINPROG)
- -$(LN) $(ISAEXEC) $(ROOTUSRSBINPROG)
-
-$(SUBDIRS): FRC
- @cd $@; pwd; $(MAKE) $(TARGET)
-
-catalog: $(POFILE)
-
-$(POFILE): $(POFILES)
- $(RM) $@
- cat $(POFILES) > $@
-
-check: $(CHKMANIFEST)
-
-$(ROOTDLIBDIR):
- $(INS.dir)
-
-$(ROOTDLIBDIR)/%.d: %.d
- $(INS.file)
-
-$(ROOTDLIBS): $(ROOTDLIBDIR)
-
-FRC:
-
-include ../../Makefile.targ
diff --git a/usr/src/cmd/iscsi/iscsitgtd/Makefile.com b/usr/src/cmd/iscsi/iscsitgtd/Makefile.com
deleted file mode 100644
index 6f11ad50d3..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/Makefile.com
+++ /dev/null
@@ -1,91 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-PROG = iscsitgtd
-
-DSRC = iscsi_provider.d
-DTRACE_HEADER = $(DSRC:%.d=%.h)
-
-COBJS = main.o mgmt.o mgmt_create.o mgmt_list.o mgmt_modify.o mgmt_remove.o
-COBJS += iscsi_authclient.o iscsi_authglue.o iscsi_cmd.o iscsi_conn.o
-COBJS += iscsi_crc.o iscsi_ffp.o iscsi_login.o iscsi_sess.o radius.o
-COBJS += t10_sam.o t10_spc.o t10_sbc.o t10_raw_if.o t10_ssc.o t10_osd.o
-COBJS += t10_spc_pr.o util.o util_err.o util_ifname.o util_port.o util_queue.o
-COBJS += isns_client.o isns.o mgmt_scf.o
-OBJS= $(COBJS) $(DSRC:%.d=%.o)
-SRCS= $(COBJS:%.o=../%.c) $(COMMON_SRCS)
-
-include ../../../Makefile.cmd
-include $(SRC)/cmd/iscsi/Makefile.iscsi
-
-CTFMERGE_HOOK = && $(CTFMERGE) -L VERSION -o $@ $(OBJS)
-CTFCONVERT_HOOK = && $(CTFCONVERT_O)
-CFLAGS += $(CTF_FLAGS)
-CFLAGS64 += $(CTF_FLAGS)
-NATIVE_CFLAGS += $(CTF_FLAGS)
-
-CFLAGS += $(CCVERBOSE)
-CPPFLAGS += -D_LARGEFILE64_SOURCE=1 -I/usr/include/libxml2 -I${HDCRCCOMMONDIR}
-CFLAGS64 += $(CCVERBOSE)
-
-CLEANFILES += $(OBJS) ../$(DTRACE_HEADER)
-
-.KEEP_STATE:
-
-all: $(PROG)
-
-LDLIBS += -lumem -luuid -lsocket -lnsl -lavl -lmd5 -ladm -lefi
-LDLIBS += -liscsitgt -lzfs -ldlpi -lscf -lsasl
-XMLLIB = -lxml2
-
-$(PROG): $(OBJS) $(COMMON_OBJS)
- $(LINK.c) $(OBJS) $(COMMON_OBJS) -o $@ $(LDLIBS) $(XMLLIB) $(CTFMERGE_HOOK)
- $(POST_PROCESS)
-
-lint := LINTFLAGS += -unv
-lint := LINTFLAGS64 += -unv
-
-lint: $$(SRCS)
- $(LINT.c) -I.. ${INCLUDES} $(SRCS) $(LDLIBS)
-
-
-../%.h: ../%.d
- $(DTRACE) -xnolibs -h -s $< -o $@
-
-%.o: $(ISCSICOMMONDIR)/%.c ../$(DTRACE_HEADER)
- $(COMPILE.c) $< $(CTFCONVERT_HOOK)
- $(POST_PROCESS_O)
-
-%.o: ../%.c ../$(DTRACE_HEADER)
- $(COMPILE.c) $< $(CTFCONVERT_HOOK)
- $(POST_PROCESS_O)
-
-%.o: ../%.d $(COBJS)
- $(COMPILE.d) -xnolibs -s $< $(COBJS)
-
-clean:
- $(RM) $(CLEANFILES) $(COMMON_OBJS)
-
-include ../../../Makefile.targ
diff --git a/usr/src/cmd/iscsi/iscsitgtd/amd64/Makefile b/usr/src/cmd/iscsi/iscsitgtd/amd64/Makefile
deleted file mode 100644
index cee9d7ffbe..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/amd64/Makefile
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
-#
-
-include ../Makefile.com
-include ../../../Makefile.cmd.64
-
-install: all $(ROOTUSRSBINPROG64)
diff --git a/usr/src/cmd/iscsi/iscsitgtd/errcode.h b/usr/src/cmd/iscsi/iscsitgtd/errcode.h
deleted file mode 100644
index ff351bbb85..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/errcode.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _TARGET_ERRCODE_H
-#define _TARGET_ERRCODE_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Block comment which describes the contents of this file.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef enum {
- ERR_SUCCESS = 1000,
- ERR_NULL_XML_MESSAGE,
- ERR_SYNTAX_EMPTY,
- ERR_SYNTAX_MISSING_ALL,
- ERR_SYNTAX_MISSING_BACKING_STORE,
- ERR_SYNTAX_MISSING_INAME,
- ERR_SYNTAX_MISSING_IPADDR,
- ERR_SYNTAX_MISSING_NAME,
- ERR_SYNTAX_MISSING_OBJECT,
- ERR_SYNTAX_MISSING_OPERAND,
- ERR_SYNTAX_MISSING_SIZE,
- ERR_SYNTAX_MISSING_TYPE,
- ERR_SYNTAX_EMPTY_ACL,
- ERR_SYNTAX_EMPTY_ALIAS,
- ERR_SYNTAX_EMPTY_CHAPNAME,
- ERR_SYNTAX_EMPTY_CHAPSECRET,
- ERR_SYNTAX_EMPTY_IPADDR,
- ERR_SYNTAX_EMPTY_MAXRECV,
- ERR_SYNTAX_EMPTY_TPGT,
- ERR_SYNTAX_INVALID_NAME,
- ERR_INVALID_COMMAND,
- ERR_INVALID_OBJECT,
- ERR_INVALID_IP,
- ERR_INVALID_BASEDIR,
- ERR_INVALID_TPGT,
- ERR_INVALID_MAXRECV,
- ERR_INVALID_RADSRV,
- ERR_INVALID_SIZE,
- ERR_INIT_EXISTS,
- ERR_NAME_TOO_LONG,
- ERR_LUN_EXISTS,
- ERR_TPGT_EXISTS,
- ERR_ACL_NOT_FOUND,
- ERR_INIT_NOT_FOUND,
- ERR_TARG_NOT_FOUND,
- ERR_LUN_NOT_FOUND,
- ERR_LUN_INVALID_RANGE,
- ERR_TPGT_NOT_FOUND,
- ERR_ACCESS_RAW_DEVICE_FAILED,
- ERR_CREATE_METADATA_FAILED,
- ERR_CREATE_SYMLINK_FAILED,
- ERR_CREATE_NAME_TOO_LONG,
- ERR_DISK_BACKING_MUST_BE_REGULAR_FILE,
- ERR_DISK_BACKING_NOT_VALID_RAW,
- ERR_DISK_BACKING_SIZE_OR_FILE,
- ERR_STAT_BACKING_FAILED,
- ERR_RAW_PART_NOT_CAP,
- ERR_CREATE_TARGET_DIR_FAILED,
- ERR_ENCODE_GUID_FAILED,
- ERR_INIT_XML_READER_FAILED,
- ERR_INVALID_XML_REQUEST,
- ERR_OPEN_PARAM_FILE_FAILED,
- ERR_UPDATE_MAINCFG_FAILED,
- ERR_UPDATE_TARGCFG_FAILED,
- ERR_VALID_TARG_EXIST,
- ERR_TARGCFG_MISSING_INAME,
- ERR_NO_MATCH,
- ERR_NO_MEM,
- ERR_LUN_ZERO_NOT_LAST,
- ERR_LUN_ZERO_NOT_FIRST,
- ERR_SIZE_MOD_BLOCK,
- ERR_CANT_SHRINK_LU,
- ERR_RESIZE_WRONG_TYPE,
- ERR_RESIZE_WRONG_DTYPE,
- ERR_LUN_NOT_GROWN,
- ERR_FILE_TOO_BIG,
- ERR_FAILED_TO_CREATE_LU,
- ERR_TAPE_NOT_SUPPORTED_IN_32BIT,
- ERR_INTERNAL_ERROR,
- ERR_BAD_CREDS,
- ERR_NO_PERMISSION,
- ERR_INVALID_ISNS_SRV,
- ERR_ISNS_ERROR,
- ERR_TPGT_NO_IPADDR,
- ERR_TPGT_IN_USE,
- ERR_ZFS_ISCSISHARE_OFF
-} err_code_t;
-
-char *
-errcode_to_str(err_code_t err_code);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _TARGET_ERRCODE_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/i386/Makefile b/usr/src/cmd/iscsi/iscsitgtd/i386/Makefile
deleted file mode 100644
index fde14781e6..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/i386/Makefile
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-#ident "%Z%%M% %I% %E% SMI"
-#
-# cmd/iscsi/iscsitgt/i386/Makefile
-
-include ../Makefile.com
-
-install: all $(ROOTUSRSBINPROG32)
diff --git a/usr/src/cmd/iscsi/iscsitgtd/iscsi.d b/usr/src/cmd/iscsi/iscsitgtd/iscsi.d
deleted file mode 100644
index f77d53cf25..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi.d
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma D depends_on library net.d
-#pragma D depends_on module genunix
-#pragma D depends_on library scsi.d
-
-typedef struct uiscsiproto uiscsiproto_t;
-
-typedef struct uiscsiproto64 {
- struct sockaddr_storage *uip_taddr;
- struct sockaddr_storage *uip_iaddr;
-
- uint64_t uip_target;
- uint64_t uip_initiator;
- uint64_t uip_lun;
-
- uint32_t uip_itt;
- uint32_t uip_ttt;
-
- uint32_t uip_cmdsn;
- uint32_t uip_statsn;
- uint32_t uip_datasn;
-
- uint32_t uip_datalen;
- uint32_t uip_flags;
-} uiscsiproto64_t;
-
-typedef struct uiscsiproto32 {
- struct sockaddr_storage *uip_taddr;
- struct sockaddr_storage *uip_iaddr;
-
- uint32_t uip_target;
- uint32_t uip_initiator;
- uint64_t uip_lun;
-
- uint32_t uip_itt;
- uint32_t uip_ttt;
-
- uint32_t uip_cmdsn;
- uint32_t uip_statsn;
- uint32_t uip_datasn;
-
- uint32_t uip_datalen;
- uint32_t uip_flags;
-} uiscsiproto32_t;
-
-#pragma D binding "1.5" translator
-translator conninfo_t < uiscsiproto_t *P > {
- ci_local = (2 == *(sa_family_t *)
- copyin((uintptr_t)((curthread->t_procp->p_model == 0x00100000) ?
- *(uint32_t *)copyin((uintptr_t)
- &(((uiscsiproto32_t *)P)->uip_taddr), sizeof (uint32_t)) :
- *(uint64_t *)copyin((uintptr_t)
- &(((uiscsiproto64_t *)P)->uip_taddr), sizeof (uint64_t))),
- sizeof (sa_family_t))) ?
-
- inet_ntoa((ipaddr_t *)copyin((uintptr_t)
- &((struct sockaddr_in *)
- ((curthread->t_procp->p_model == 0x00100000) ?
- *(uint32_t *)copyin((uintptr_t)
- &(((uiscsiproto32_t *)P)->uip_taddr), sizeof (uint32_t)) :
- *(uint64_t *)copyin((uintptr_t)
- &(((uiscsiproto64_t *)P)->uip_taddr), sizeof (uint64_t))))
- ->sin_addr, sizeof (ipaddr_t))) :
-
- inet_ntoa6((in6_addr_t *)copyin((uintptr_t)
- &((struct sockaddr_in6 *)
- ((curthread->t_procp->p_model == 0x00100000) ?
- *(uint32_t *)copyin((uintptr_t)
- &(((uiscsiproto32_t *)P)->uip_taddr), sizeof (uint32_t)) :
- *(uint64_t *)copyin((uintptr_t)
- &(((uiscsiproto64_t *)P)->uip_taddr), sizeof (uint64_t))))
- ->sin6_addr, sizeof (in6_addr_t)));
-
- ci_remote = (2 == *(sa_family_t *)
- copyin((uintptr_t)((curthread->t_procp->p_model == 0x00100000) ?
- *(uint32_t *)copyin((uintptr_t)
- &(((uiscsiproto32_t *)P)->uip_iaddr), sizeof (uint32_t)) :
- *(uint64_t *)copyin((uintptr_t)
- &(((uiscsiproto64_t *)P)->uip_iaddr), sizeof (uint64_t))),
- sizeof (sa_family_t))) ?
-
- inet_ntoa((ipaddr_t *)copyin((uintptr_t)
- &((struct sockaddr_in *)
- ((curthread->t_procp->p_model == 0x00100000) ?
- *(uint32_t *)copyin((uintptr_t)
- &(((uiscsiproto32_t *)P)->uip_iaddr), sizeof (uint32_t)) :
- *(uint64_t *)copyin((uintptr_t)
- &(((uiscsiproto64_t *)P)->uip_iaddr), sizeof (uint64_t))))
- ->sin_addr, sizeof (ipaddr_t))) :
-
- inet_ntoa6((in6_addr_t *)copyin((uintptr_t)
- &((struct sockaddr_in6 *)
- ((curthread->t_procp->p_model == 0x00100000) ?
- *(uint32_t *)copyin((uintptr_t)
- &(((uiscsiproto32_t *)P)->uip_iaddr), sizeof (uint32_t)) :
- *(uint64_t *)copyin((uintptr_t)
- &(((uiscsiproto64_t *)P)->uip_iaddr), sizeof (uint64_t))))
- ->sin6_addr, sizeof (in6_addr_t)));
-
- ci_protocol = (*(sa_family_t *)copyin((uintptr_t)
- ((curthread->t_procp->p_model == 0x00100000) ?
-
- *(uint32_t *)copyin((uintptr_t)
- &(((uiscsiproto32_t *)P)->uip_taddr), sizeof (uint32_t)) :
-
- *(uint64_t *)copyin((uintptr_t)
- &(((uiscsiproto64_t *)P)->uip_taddr), sizeof (uint64_t))),
-
- sizeof (sa_family_t)) == 2) ? "ipv4" : "ipv6";
-};
-
-#pragma D binding "1.5" translator
-translator iscsiinfo_t < uiscsiproto_t *P > {
- ii_initiator = (curthread->t_procp->p_model == 0x00100000) ?
- copyinstr((uintptr_t)*(uint32_t *)copyin((uintptr_t)
- &((uiscsiproto32_t *)P)->uip_initiator, sizeof (uint32_t))) :
- copyinstr((uintptr_t)*(uint64_t *)copyin((uintptr_t)
- &((uiscsiproto64_t *)P)->uip_initiator, sizeof (uint64_t)));
-
- ii_target = (curthread->t_procp->p_model == 0x00100000) ?
- copyinstr((uintptr_t)*(uint32_t *)copyin((uintptr_t)
- &((uiscsiproto32_t *)P)->uip_target, sizeof (uint32_t))) :
- copyinstr((uintptr_t)*(uint64_t *)copyin((uintptr_t)
- &((uiscsiproto64_t *)P)->uip_target, sizeof (uint64_t)));
-
- ii_lun = (curthread->t_procp->p_model == 0x00100000) ?
- *(uint64_t *)copyin((uintptr_t)
- &((uiscsiproto32_t *)P)->uip_lun, sizeof (uint64_t)) :
- *(uint64_t *)copyin((uintptr_t)
- &((uiscsiproto64_t *)P)->uip_lun, sizeof (uint64_t));
-
- ii_itt = (curthread->t_procp->p_model == 0x00100000) ?
- *(uint32_t *)copyin((uintptr_t)
- &((uiscsiproto32_t *)P)->uip_itt, sizeof (uint32_t)) :
- *(uint32_t *)copyin((uintptr_t)
- &((uiscsiproto64_t *)P)->uip_itt, sizeof (uint32_t));
-
- ii_ttt = (curthread->t_procp->p_model == 0x00100000) ?
- *(uint32_t *)copyin((uintptr_t)
- &((uiscsiproto32_t *)P)->uip_ttt, sizeof (uint32_t)) :
- *(uint32_t *)copyin((uintptr_t)
- &((uiscsiproto64_t *)P)->uip_ttt, sizeof (uint32_t));
-
- ii_cmdsn = (curthread->t_procp->p_model == 0x00100000) ?
- *(uint32_t *)copyin((uintptr_t)
- &((uiscsiproto32_t *)P)->uip_cmdsn, sizeof (uint32_t)) :
- *(uint32_t *)copyin((uintptr_t)
- &((uiscsiproto64_t *)P)->uip_cmdsn, sizeof (uint32_t));
-
- ii_statsn = (curthread->t_procp->p_model == 0x00100000) ?
- *(uint32_t *)copyin((uintptr_t)
- &((uiscsiproto32_t *)P)->uip_statsn, sizeof (uint32_t)) :
- *(uint32_t *)copyin((uintptr_t)
- &((uiscsiproto64_t *)P)->uip_statsn, sizeof (uint32_t));
-
- ii_datasn = (curthread->t_procp->p_model == 0x00100000) ?
- *(uint32_t *)copyin((uintptr_t)
- &((uiscsiproto32_t *)P)->uip_datasn, sizeof (uint32_t)) :
- *(uint32_t *)copyin((uintptr_t)
- &((uiscsiproto64_t *)P)->uip_datasn, sizeof (uint32_t));
-
- ii_datalen = (curthread->t_procp->p_model == 0x00100000) ?
- *(uint32_t *)copyin((uintptr_t)
- &((uiscsiproto32_t *)P)->uip_datalen, sizeof (uint32_t)) :
- *(uint32_t *)copyin((uintptr_t)
- &((uiscsiproto64_t *)P)->uip_datalen, sizeof (uint32_t));
-
- ii_flags = (curthread->t_procp->p_model == 0x00100000) ?
- *(uint32_t *)copyin((uintptr_t)
- &((uiscsiproto32_t *)P)->uip_flags, sizeof (uint32_t)) :
- *(uint32_t *)copyin((uintptr_t)
- &((uiscsiproto64_t *)P)->uip_flags, sizeof (uint32_t));
-};
-
-typedef struct iscsicmd {
- uint64_t ic_len; /* CDB length */
- uint8_t *ic_cdb; /* CDB data */
-} iscsicmd_t;
-
-typedef struct uiscsicmd {
- uint64_t uic_len;
- uint8_t *uic_cdb;
-} uiscsicmd_t;
-
-#pragma D binding "1.5" translator
-translator iscsicmd_t < uiscsicmd_t *P > {
- ic_len = *(uint64_t *)copyin((uintptr_t)&P->uic_len, sizeof (uint64_t));
- ic_cdb = (uint8_t *)copyin((curthread->t_procp->p_model == 0x00100000) ?
- (uintptr_t)*(uint32_t *)copyin((uintptr_t)&P->uic_cdb,
- sizeof (uint32_t)) :
- (uintptr_t)*(uint64_t *)copyin((uintptr_t)&P->uic_cdb,
- sizeof (uint64_t)),
- *(uint64_t *)copyin((uintptr_t)&P->uic_len, sizeof (uint64_t)));
-};
-
-inline int ISCSI_FLAG_FINAL = 0x80;
-#pragma D binding "1.5" ISCSI_FLAG_FINAL
-inline int ISCSI_FLAG_CMD_WRITE = 0x20;
-#pragma D binding "1.5" ISCSI_FLAG_CMD_WRITE
-inline int ISCSI_FLAG_CMD_READ = 0x40;
-#pragma D binding "1.5" ISCSI_FLAG_CMD_READ
-inline int ISCSI_FLAG_CMD_BIDI_UNDERFLOW = 0x08;
-#pragma D binding "1.5" ISCSI_FLAG_CMD_BIDI_UNDERFLOW
-inline int ISCSI_FLAG_CMD_BIDI_OVERFLOW = 0x10;
-#pragma D binding "1.5" ISCSI_FLAG_CMD_BIDI_OVERFLOW
-inline int ISCSI_FLAG_CMD_UNDERFLOW = 0x02;
-#pragma D binding "1.5" ISCSI_FLAG_CMD_UNDERFLOW
-inline int ISCSI_FLAG_CMD_OVERFLOW = 0x04;
-#pragma D binding "1.5" ISCSI_FLAG_CMD_OVERFLOW
-inline int ISCSI_FLAG_DATA_STATUS = 0x01;
-#pragma D binding "1.5" ISCSI_FLAG_DATA_STATUS
-inline int ISCSI_FLAG_DATA_UNDERFLOW = 0x02;
-#pragma D binding "1.5" ISCSI_FLAG_DATA_UNDERFLOW
-inline int ISCSI_FLAG_DATA_OVERFLOW = 0x04;
-#pragma D binding "1.5" ISCSI_FLAG_DATA_OVERFLOW
-inline int ISCSI_FLAG_DATA_ACK = 0x40;
-#pragma D binding "1.5" ISCSI_FLAG_DATA_ACK
-inline int ISCSI_FLAG_TEXT_CONTINUE = 0x40;
-#pragma D binding "1.5" ISCSI_FLAG_TEXT_CONTINUE
-inline int ISCSI_FLAG_LOGIN_CONTINUE = 0x40;
-#pragma D binding "1.5" ISCSI_FLAG_LOGIN_CONTINUE
-inline int ISCSI_FLAG_LOGIN_TRANSIT = 0x80;
-#pragma D binding "1.5" ISCSI_FLAG_LOGIN_TRANSIT
diff --git a/usr/src/cmd/iscsi/iscsitgtd/iscsi_authclient.c b/usr/src/cmd/iscsi/iscsitgtd/iscsi_authclient.c
deleted file mode 100644
index 8aa279ed0e..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_authclient.c
+++ /dev/null
@@ -1,3042 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2000 by Cisco Systems, Inc. All rights reserved.
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- *
- * FIXME: If this is true we have some problems. draft 15!?
- *
- * This file implements the iSCSI CHAP authentication method based on
- * draft-ietf-ips-iscsi-15.txt. The code in this file is meant
- * to be platform independent, and makes use of only limited library
- * functions, presently only string.h. Platform dependent routines
- * are defined in iscsi_authclient.h, but implemented in another file.
- *
- * This code in this files assumes a single thread of execution
- * for each IscsiAuthClient structure, and does no locking.
- */
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef _KERNEL
-
-#include "iscsi.h"
-
-#else
-
-#include <strings.h>
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#endif
-
-#include <sys/iscsi_authclient.h>
-
-struct iscsiAuthKeyInfo_t {
- const char *name;
-};
-typedef struct iscsiAuthKeyInfo_t IscsiAuthKeyInfo;
-
-
-IscsiAuthClientGlobalStats iscsiAuthClientGlobalStats;
-
-/*
- * Note: The ordering of this table must match the order
- * defined by IscsiAuthKeyType in iscsiAuthClient.h.
- */
-static IscsiAuthKeyInfo iscsiAuthClientKeyInfo[iscsiAuthKeyTypeMaxCount] = {
- {"AuthMethod"},
- {"CHAP_A"},
- {"CHAP_N"},
- {"CHAP_R"},
- {"CHAP_I"},
- {"CHAP_C"}
-};
-
-static const char iscsiAuthClientHexString[] = "0123456789abcdefABCDEF";
-static const char iscsiAuthClientBase64String[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-static const char iscsiAuthClientAuthMethodChapOptionName[] = "CHAP";
-
-
-static int
-iscsiAuthClientCheckString(const char *s,
- unsigned int maxLength, unsigned int *pOutLength)
-{
- unsigned int length;
-
- if (!s) {
- return (TRUE);
- }
-
- for (length = 0; length < maxLength; length++) {
- if (*s++ == '\0') {
- if (pOutLength) {
- *pOutLength = length;
- }
- return (FALSE);
- }
- }
-
- return (TRUE);
-}
-
-
-static int
-iscsiAuthClientStringCopy(char *stringOut, const char *stringIn,
- unsigned int length)
-{
- if (!stringOut || !stringIn || length == 0) {
- return (TRUE);
- }
-
- while ((*stringOut++ = *stringIn++) != '\0') {
- if (--length == 0) {
- stringOut--;
- *stringOut = '\0';
- return (TRUE);
- }
- }
-
- return (FALSE);
-}
-
-
-static int
-iscsiAuthClientStringAppend(char *stringOut, const char *stringIn,
- unsigned int length)
-{
- if (!stringOut || !stringIn || length == 0) {
- return (TRUE);
- }
-
- while (*stringOut++ != '\0') {
- if (--length == 0) {
- stringOut--;
- *stringOut = '\0';
- return (TRUE);
- }
- }
-
- stringOut--;
-
- while ((*stringOut++ = *stringIn++) != '\0') {
- if (--length == 0) {
- stringOut--;
- *stringOut = '\0';
- return (TRUE);
- }
- }
-
- return (FALSE);
-}
-
-
-static int
-iscsiAuthClientStringIndex(const char *s, int c)
-{
- int n = 0;
-
- while (*s != '\0') {
- if (*s++ == c) {
- return (n);
- }
- n++;
- }
-
- return (-1);
-}
-
-
-static int
-iscsiAuthClientCheckNodeType(int nodeType)
-{
- if (nodeType == iscsiAuthNodeTypeInitiator ||
- nodeType == iscsiAuthNodeTypeTarget) {
- return (FALSE);
- }
-
- return (TRUE);
-}
-
-
-static int
-iscsiAuthClientCheckVersion(int value)
-{
- if (value == iscsiAuthVersionDraft8 || value == iscsiAuthVersionRfc) {
-
- return (FALSE);
- }
-
- return (TRUE);
-}
-
-static int
-iscsiAuthClientCheckAuthMethodOption(int value)
-{
- if (value == iscsiAuthOptionNone || value == iscsiAuthMethodChap) {
-
- return (FALSE);
- }
-
- return (TRUE);
-}
-
-
-static const char *
-iscsiAuthClientAuthMethodOptionToText(IscsiAuthClient * client, int value)
-{
- const char *s;
-
- switch (value) {
- case iscsiAuthOptionReject:
- s = client->rejectOptionName;
- break;
-
- case iscsiAuthOptionNone:
- s = client->noneOptionName;
- break;
-
- case iscsiAuthMethodChap:
- s = iscsiAuthClientAuthMethodChapOptionName;
- break;
-
- default:
- s = 0;
- }
-
- return (s);
-}
-
-
-static int
-iscsiAuthClientCheckChapAlgorithmOption(int chapAlgorithm)
-{
- if (chapAlgorithm == iscsiAuthOptionNone ||
- chapAlgorithm == iscsiAuthChapAlgorithmMd5) {
- return (FALSE);
- }
-
- return (TRUE);
-}
-
-
-static int
-iscsiAuthClientDataToHex(unsigned char *data, unsigned int dataLength,
- char *text, unsigned int textLength)
-{
- unsigned long n;
-
- if (!text || textLength == 0) {
- return (TRUE);
- }
-
- if (!data || dataLength == 0) {
- *text = '\0';
- return (TRUE);
- }
-
- if (textLength < 3) {
- *text = '\0';
- return (TRUE);
- }
-
- *text++ = '0';
- *text++ = 'x';
-
- textLength -= 2;
-
- while (dataLength > 0) {
-
- if (textLength < 3) {
- *text = '\0';
- return (TRUE);
- }
-
- n = *data++;
- dataLength--;
-
- *text++ = iscsiAuthClientHexString[(n >> 4) & 0xf];
- *text++ = iscsiAuthClientHexString[n & 0xf];
-
- textLength -= 2;
- }
-
- *text = '\0';
-
- return (FALSE);
-}
-
-
-static int
-iscsiAuthClientDataToBase64(unsigned char *data, unsigned int dataLength,
- char *text, unsigned int textLength)
-{
- unsigned long n;
-
- if (!text || textLength == 0) {
- return (TRUE);
- }
-
- if (!data || dataLength == 0) {
- *text = '\0';
- return (TRUE);
- }
-
- if (textLength < 3) {
- *text = '\0';
- return (TRUE);
- }
-
- *text++ = '0';
- *text++ = 'b';
-
- textLength -= 2;
-
- while (dataLength >= 3) {
-
- if (textLength < 5) {
- *text = '\0';
- return (TRUE);
- }
-
- n = *data++;
- n = (n << 8) | *data++;
- n = (n << 8) | *data++;
- dataLength -= 3;
-
- *text++ = iscsiAuthClientBase64String[(n >> 18) & 0x3f];
- *text++ = iscsiAuthClientBase64String[(n >> 12) & 0x3f];
- *text++ = iscsiAuthClientBase64String[(n >> 6) & 0x3f];
- *text++ = iscsiAuthClientBase64String[n & 0x3f];
-
- textLength -= 4;
- }
-
- if (dataLength == 1) {
-
- if (textLength < 5) {
- *text = '\0';
- return (TRUE);
- }
-
- n = *data++;
- n = n << 4;
-
- *text++ = iscsiAuthClientBase64String[(n >> 6) & 0x3f];
- *text++ = iscsiAuthClientBase64String[n & 0x3f];
- *text++ = '=';
- *text++ = '=';
-
- } else if (dataLength == 2) {
-
- if (textLength < 5) {
- return (TRUE);
- }
-
- n = *data++;
- n = (n << 8) | *data++;
- n = n << 2;
-
- *text++ = iscsiAuthClientBase64String[(n >> 12) & 0x3f];
- *text++ = iscsiAuthClientBase64String[(n >> 6) & 0x3f];
- *text++ = iscsiAuthClientBase64String[n & 0x3f];
- *text++ = '=';
- }
-
- *text = '\0';
-
- return (FALSE);
-}
-
-
-static int
-iscsiAuthClientDataToText(int base64, unsigned char *data,
- unsigned int dataLength, char *text, unsigned int textLength)
-{
- int status;
-
- if (base64) {
- status = iscsiAuthClientDataToBase64(
- data, dataLength, text, textLength);
- } else {
- status = iscsiAuthClientDataToHex(
- data, dataLength, text, textLength);
- }
-
- return (status);
-}
-
-
-static int
-iscsiAuthClientHexToData(const char *text, unsigned int textLength,
- unsigned char *data, unsigned int *pDataLength)
-{
- int i;
- unsigned int n1;
- unsigned int n2;
- unsigned int dataLength = *pDataLength;
-
- if ((textLength % 2) == 1) {
- i = iscsiAuthClientStringIndex(iscsiAuthClientHexString,
- *text++);
- if (i < 0) {
- return (TRUE); /* error, bad character */
- }
-
- if (i > 15)
- i -= 6;
- n2 = i;
-
- if (dataLength < 1) {
- return (TRUE); /* error, too much data */
- }
-
- *data++ = n2;
- dataLength--;
- }
-
- while (*text != '\0') {
-
- i = iscsiAuthClientStringIndex(
- iscsiAuthClientHexString, *text++);
- if (i < 0) {
- return (TRUE); /* error, bad character */
- }
-
- if (i > 15)
- i -= 6;
- n1 = i;
-
- if (*text == '\0') {
- return (TRUE); /* error, odd string length */
- }
-
- i = iscsiAuthClientStringIndex(
- iscsiAuthClientHexString, *text++);
- if (i < 0) {
- return (TRUE); /* error, bad character */
- }
-
- if (i > 15)
- i -= 6;
- n2 = i;
-
- if (dataLength < 1) {
- return (TRUE); /* error, too much data */
- }
-
- *data++ = (n1 << 4) | n2;
- dataLength--;
- }
-
- if (dataLength >= *pDataLength) {
- return (TRUE); /* error, no data */
- }
-
- *pDataLength = *pDataLength - dataLength;
-
- return (FALSE); /* no error */
-}
-
-
-static int
-iscsiAuthClientBase64ToData(const char *text, unsigned int textLength,
- unsigned char *data, unsigned int *pDataLength)
-{
- int i;
- unsigned int n;
- unsigned int count;
- unsigned int dataLength = *pDataLength;
-
- textLength = textLength; /* not used */
-
- n = 0;
- count = 0;
-
- while (*text != '\0' && *text != '=') {
-
- i = iscsiAuthClientStringIndex(
- iscsiAuthClientBase64String, *text++);
- if (i < 0) {
- return (TRUE); /* error, bad character */
- }
-
- n = (n << 6 | (unsigned int)i);
- count++;
-
- if (count >= 4) {
- if (dataLength < 3) {
- return (TRUE); /* error, too much data */
- }
- *data++ = n >> 16;
- *data++ = n >> 8;
- *data++ = n;
- dataLength -= 3;
- n = 0;
- count = 0;
- }
- }
-
- while (*text != '\0') {
- if (*text++ != '=') {
- return (TRUE); /* error, bad pad */
- }
- }
-
- if (count == 0) {
- /*
- * do nothing
- */
- /* EMPTY */
- } else if (count == 2) {
- if (dataLength < 1) {
- return (TRUE); /* error, too much data */
- }
- n = n >> 4;
- *data++ = n;
- dataLength--;
- } else if (count == 3) {
- if (dataLength < 2) {
- return (TRUE); /* error, too much data */
- }
- n = n >> 2;
- *data++ = n >> 8;
- *data++ = n;
- dataLength -= 2;
- } else {
- return (TRUE); /* bad encoding */
- }
-
- if (dataLength >= *pDataLength) {
- return (TRUE); /* error, no data */
- }
-
- *pDataLength = *pDataLength - dataLength;
-
- return (FALSE); /* no error */
-}
-
-
-static int
-iscsiAuthClientTextToData(const char *text, unsigned char *data,
- unsigned int *dataLength)
-{
- int status;
- unsigned int textLength;
-
- status = iscsiAuthClientCheckString(text,
- 2 + 2 * iscsiAuthLargeBinaryMaxLength + 1, &textLength);
-
- if (status) {
- return (status);
- }
-
- if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X')) {
- /*
- * skip prefix
- */
- text += 2;
- textLength -= 2;
- status = iscsiAuthClientHexToData(text,
- textLength, data, dataLength);
- } else if (text[0] == '0' && (text[1] == 'b' || text[1] == 'B')) {
- /*
- * skip prefix
- */
- text += 2;
- textLength -= 2;
- status = iscsiAuthClientBase64ToData(text,
- textLength, data, dataLength);
- } else {
- status = TRUE; /* prefix not recognized. */
- }
-
- return (status);
-}
-
-
-static IscsiAuthDebugStatus
-iscsiAuthClientChapComputeResponse(IscsiAuthClient * client,
- int remoteAuthentication, unsigned int id,
- unsigned char *challengeData, unsigned int challengeLength,
- unsigned char *responseData)
-{
- unsigned char idData[1];
- IscsiAuthMd5Context context;
- unsigned char outData[iscsiAuthStringMaxLength];
- unsigned int outLength = iscsiAuthStringMaxLength;
-
- if (!client->passwordPresent) {
- return (iscsiAuthDebugStatusLocalPasswordNotSet);
- }
-
- iscsiAuthMd5Init(&context);
-
- /*
- * id byte
- */
- idData[0] = id;
- iscsiAuthMd5Update(&context, idData, 1);
-
- /*
- * decrypt password
- */
- if (iscsiAuthClientData(outData, &outLength,
- client->passwordData, client->passwordLength)) {
-
- return (iscsiAuthDebugStatusPasswordDecryptFailed);
- }
-
- if (!remoteAuthentication && !client->ipSec && outLength < 12) {
- return (iscsiAuthDebugStatusPasswordTooShortWithNoIpSec);
- }
-
- /*
- * shared secret
- */
- iscsiAuthMd5Update(&context, outData, outLength);
-
- /*
- * clear decrypted password
- */
- bzero(outData, iscsiAuthStringMaxLength);
-
- /*
- * challenge value
- */
- iscsiAuthMd5Update(&context, challengeData, challengeLength);
-
- iscsiAuthMd5Final(responseData, &context);
-
- return (iscsiAuthDebugStatusNotSet); /* no error */
-}
-
-
-static void
-iscsiAuthClientInitKeyBlock(IscsiAuthKeyBlock * keyBlock)
-{
- char *stringBlock = keyBlock->stringBlock;
-
- bzero(keyBlock, sizeof (*keyBlock));
- keyBlock->stringBlock = stringBlock;
-}
-
-
-static void
-iscsiAuthClientSetKeyValue(IscsiAuthKeyBlock * keyBlock,
- int keyType, const char *keyValue)
-{
- unsigned int length;
- char *string;
-
- if (keyBlock->key[keyType].valueSet) {
- keyBlock->duplicateSet = TRUE;
- return;
- }
-
- keyBlock->key[keyType].valueSet = TRUE;
-
- if (!keyValue) {
- return;
- }
-
- if (iscsiAuthClientCheckString(keyValue,
- iscsiAuthStringMaxLength, &length)) {
- keyBlock->stringTooLong = TRUE;
- return;
- }
-
- length += 1;
-
- if ((keyBlock->blockLength + length) > iscsiAuthStringBlockMaxLength) {
- keyBlock->tooMuchData = TRUE;
- return;
- }
-
- string = &keyBlock->stringBlock[keyBlock->blockLength];
-
- if (iscsiAuthClientStringCopy(string, keyValue, length)) {
- keyBlock->tooMuchData = TRUE;
- return;
- }
- keyBlock->blockLength += length;
-
- keyBlock->key[keyType].string = string;
- keyBlock->key[keyType].present = TRUE;
-}
-
-
-static const char *
-iscsiAuthClientGetKeyValue(IscsiAuthKeyBlock * keyBlock, int keyType)
-{
- keyBlock->key[keyType].processed = TRUE;
-
- if (!keyBlock->key[keyType].present) {
- return (0);
- }
-
- return (keyBlock->key[keyType].string);
-}
-
-
-static void
-iscsiAuthClientCheckKey(IscsiAuthClient * client,
- int keyType,
- int *negotiatedOption,
- unsigned int optionCount,
- int *optionList, const char *(*valueToText) (IscsiAuthClient *, int))
-{
- const char *keyValue;
- int length;
- unsigned int i;
-
- keyValue = iscsiAuthClientGetKeyValue(&client->recvKeyBlock, keyType);
- if (!keyValue) {
- *negotiatedOption = iscsiAuthOptionNotPresent;
- return;
- }
-
- while (*keyValue != '\0') {
-
- length = 0;
-
- while (*keyValue != '\0' && *keyValue != ',') {
- client->scratchKeyValue[length++] = *keyValue++;
- }
-
- if (*keyValue == ',')
- keyValue++;
- client->scratchKeyValue[length++] = '\0';
-
- for (i = 0; i < optionCount; i++) {
- const char *s = (*valueToText) (client, optionList[i]);
-
- if (!s)
- continue;
-
- if (strcmp(client->scratchKeyValue, s) == 0) {
- *negotiatedOption = optionList[i];
- return;
- }
- }
- }
-
- *negotiatedOption = iscsiAuthOptionReject;
-}
-
-
-static void
-iscsiAuthClientSetKey(IscsiAuthClient * client,
- int keyType,
- unsigned int optionCount,
- int *optionList, const char *(*valueToText) (IscsiAuthClient *, int))
-{
- unsigned int i;
-
- if (optionCount == 0) {
- /*
- * No valid options to send, but we always want to
- * send something.
- */
- iscsiAuthClientSetKeyValue(&client->sendKeyBlock, keyType,
- client->noneOptionName);
- return;
- }
-
- if (optionCount == 1 && optionList[0] == iscsiAuthOptionNotPresent) {
- iscsiAuthClientSetKeyValue(&client->sendKeyBlock, keyType, 0);
- return;
- }
-
- for (i = 0; i < optionCount; i++) {
- const char *s = (*valueToText) (client, optionList[i]);
-
- if (!s)
- continue;
-
- if (i == 0) {
- (void) iscsiAuthClientStringCopy(client->scratchKeyValue,
- s, iscsiAuthStringMaxLength);
- } else {
- (void) iscsiAuthClientStringAppend(client->scratchKeyValue,
- ",", iscsiAuthStringMaxLength);
- (void) iscsiAuthClientStringAppend(client->scratchKeyValue,
- s, iscsiAuthStringMaxLength);
- }
- }
-
- iscsiAuthClientSetKeyValue(&client->sendKeyBlock,
- keyType, client->scratchKeyValue);
-}
-
-
-static void
-iscsiAuthClientCheckAuthMethodKey(IscsiAuthClient * client)
-{
- iscsiAuthClientCheckKey(client,
- iscsiAuthKeyTypeAuthMethod,
- &client->negotiatedAuthMethod,
- client->authMethodValidCount,
- client->authMethodValidList, iscsiAuthClientAuthMethodOptionToText);
-}
-
-
-static void
-iscsiAuthClientSetAuthMethodKey(IscsiAuthClient * client,
- unsigned int authMethodCount, int *authMethodList)
-{
- iscsiAuthClientSetKey(client, iscsiAuthKeyTypeAuthMethod,
- authMethodCount, authMethodList,
- iscsiAuthClientAuthMethodOptionToText);
-}
-
-
-static void
-iscsiAuthClientCheckChapAlgorithmKey(IscsiAuthClient * client)
-{
- const char *keyValue;
- int length;
- unsigned long number;
- unsigned int i;
-
- keyValue = iscsiAuthClientGetKeyValue(&client->recvKeyBlock,
- iscsiAuthKeyTypeChapAlgorithm);
- if (!keyValue) {
- client->negotiatedChapAlgorithm = iscsiAuthOptionNotPresent;
- return;
- }
-
- while (*keyValue != '\0') {
- length = 0;
-
- while (*keyValue != '\0' && *keyValue != ',') {
- client->scratchKeyValue[length++] = *keyValue++;
- }
-
- if (*keyValue == ',')
- keyValue++;
- client->scratchKeyValue[length++] = '\0';
-
- if (iscsiAuthClientTextToNumber(client->scratchKeyValue,
- &number)) {
- continue;
- }
-
- for (i = 0; i < client->chapAlgorithmCount; i++) {
-
- if (number == (unsigned long)client->
- chapAlgorithmList[i]) {
- client->negotiatedChapAlgorithm = number;
- return;
- }
- }
- }
-
- client->negotiatedChapAlgorithm = iscsiAuthOptionReject;
-}
-
-
-static void
-iscsiAuthClientSetChapAlgorithmKey(IscsiAuthClient * client,
- unsigned int chapAlgorithmCount, int *chapAlgorithmList)
-{
- unsigned int i;
-
- if (chapAlgorithmCount == 0) {
- iscsiAuthClientSetKeyValue(&client->sendKeyBlock,
- iscsiAuthKeyTypeChapAlgorithm, 0);
- return;
- }
-
- if (chapAlgorithmCount == 1 &&
- chapAlgorithmList[0] == iscsiAuthOptionNotPresent) {
- iscsiAuthClientSetKeyValue(&client->sendKeyBlock,
- iscsiAuthKeyTypeChapAlgorithm, 0);
- return;
- }
-
- if (chapAlgorithmCount == 1 &&
- chapAlgorithmList[0] == iscsiAuthOptionReject) {
- iscsiAuthClientSetKeyValue(&client->sendKeyBlock,
- iscsiAuthKeyTypeChapAlgorithm, client->rejectOptionName);
- return;
- }
-
- for (i = 0; i < chapAlgorithmCount; i++) {
- char s[20];
-
- iscsiAuthClientNumberToText(chapAlgorithmList[i],
- s, sizeof (s));
-
- if (i == 0) {
- (void) iscsiAuthClientStringCopy(client->scratchKeyValue, s,
- iscsiAuthStringMaxLength);
- } else {
- (void) iscsiAuthClientStringAppend(client->scratchKeyValue,
- ",", iscsiAuthStringMaxLength);
- (void) iscsiAuthClientStringAppend(client->scratchKeyValue,
- s, iscsiAuthStringMaxLength);
- }
- }
-
- iscsiAuthClientSetKeyValue(&client->sendKeyBlock,
- iscsiAuthKeyTypeChapAlgorithm, client->scratchKeyValue);
-}
-
-
-static void
-iscsiAuthClientNextPhase(IscsiAuthClient * client)
-{
- switch (client->phase) {
- case iscsiAuthPhaseConfigure:
- client->phase = iscsiAuthPhaseNegotiate;
- break;
-
- case iscsiAuthPhaseNegotiate:
- client->phase = iscsiAuthPhaseAuthenticate;
-
- if (client->negotiatedAuthMethod ==
- iscsiAuthOptionReject ||
- client->negotiatedAuthMethod ==
- iscsiAuthOptionNotPresent ||
- client->negotiatedAuthMethod == iscsiAuthOptionNone) {
-
- client->localState = iscsiAuthLocalStateDone;
- client->remoteState = iscsiAuthRemoteStateDone;
-
- if (client->authRemote) {
- client->remoteAuthStatus = iscsiAuthStatusFail;
- client->phase = iscsiAuthPhaseDone;
- } else {
- client->remoteAuthStatus = iscsiAuthStatusPass;
- }
-
- switch (client->negotiatedAuthMethod) {
- case iscsiAuthOptionReject:
- client->debugStatus =
- iscsiAuthDebugStatusAuthMethodReject;
- break;
-
- case iscsiAuthOptionNotPresent:
- client->debugStatus =
- iscsiAuthDebugStatusAuthMethodNotPresent;
- break;
-
- case iscsiAuthOptionNone:
- client->debugStatus =
- iscsiAuthDebugStatusAuthMethodNone;
- }
-
- } else if (client->negotiatedAuthMethod ==
- iscsiAuthMethodChap) {
- client->localState = iscsiAuthLocalStateSendAlgorithm;
- client->remoteState = iscsiAuthRemoteStateSendAlgorithm;
- } else {
- client->localState = iscsiAuthLocalStateDone;
- client->remoteState = iscsiAuthRemoteStateDone;
- client->remoteAuthStatus = iscsiAuthStatusFail;
- client->debugStatus = iscsiAuthDebugStatusAuthMethodBad;
- }
-
- break;
-
- case iscsiAuthPhaseAuthenticate:
- client->phase = iscsiAuthPhaseDone;
- break;
-
- case iscsiAuthPhaseDone:
- case iscsiAuthPhaseError:
- default:
- client->phase = iscsiAuthPhaseError;
- }
-}
-
-
-static void
-iscsiAuthClientLocalAuthentication(IscsiAuthClient * client)
-{
- unsigned int chapIdentifier;
- unsigned char responseData[iscsiAuthChapResponseLength];
- unsigned long number;
- int status;
- IscsiAuthDebugStatus debugStatus;
- const char *chapIdentifierKeyValue;
- const char *chapChallengeKeyValue;
-
- switch (client->localState) {
- case iscsiAuthLocalStateSendAlgorithm:
- if (client->nodeType == iscsiAuthNodeTypeInitiator) {
- iscsiAuthClientSetChapAlgorithmKey(
- client, client->chapAlgorithmCount,
- client->chapAlgorithmList);
- client->localState = iscsiAuthLocalStateRecvAlgorithm;
- break;
- }
-
- /* FALLTHRU */
-
- case iscsiAuthLocalStateRecvAlgorithm:
- iscsiAuthClientCheckChapAlgorithmKey(client);
-
- if (client->nodeType == iscsiAuthNodeTypeTarget) {
-
- iscsiAuthClientSetChapAlgorithmKey(client, 1,
- &client->negotiatedChapAlgorithm);
- }
-
- /*
- * Make sure only supported CHAP algorithm is used.
- */
- if (client->negotiatedChapAlgorithm ==
- iscsiAuthOptionNotPresent) {
- client->localState = iscsiAuthLocalStateError;
- client->debugStatus =
- iscsiAuthDebugStatusChapAlgorithmExpected;
- break;
-
- } else if (client->negotiatedChapAlgorithm ==
- iscsiAuthOptionReject) {
- client->localState = iscsiAuthLocalStateError;
- client->debugStatus =
- iscsiAuthDebugStatusChapAlgorithmReject;
- break;
-
- } else if (client->negotiatedChapAlgorithm !=
- iscsiAuthChapAlgorithmMd5) {
- client->localState = iscsiAuthLocalStateError;
- client->debugStatus =
- iscsiAuthDebugStatusChapAlgorithmBad;
- break;
- }
-
- if (client->nodeType == iscsiAuthNodeTypeTarget) {
-
- client->localState = iscsiAuthLocalStateRecvChallenge;
- break;
- }
-
- /* FALLTHRU */
-
- case iscsiAuthLocalStateRecvChallenge:
- chapIdentifierKeyValue = iscsiAuthClientGetKeyValue(
- &client->recvKeyBlock, iscsiAuthKeyTypeChapIdentifier);
- chapChallengeKeyValue = iscsiAuthClientGetKeyValue(
- &client->recvKeyBlock, iscsiAuthKeyTypeChapChallenge);
-
- if (client->nodeType == iscsiAuthNodeTypeTarget) {
- if (!chapIdentifierKeyValue && !chapChallengeKeyValue) {
- client->localState = iscsiAuthLocalStateDone;
- break;
- }
- }
-
- if (!chapIdentifierKeyValue) {
- client->localState = iscsiAuthLocalStateError;
- client->debugStatus =
- iscsiAuthDebugStatusChapIdentifierExpected;
- break;
- }
-
- if (!chapChallengeKeyValue) {
- client->localState = iscsiAuthLocalStateError;
- client->debugStatus =
- iscsiAuthDebugStatusChapChallengeExpected;
- break;
- }
-
- status = iscsiAuthClientTextToNumber(
- chapIdentifierKeyValue, &number);
-
- if (status || (255 < number)) {
- client->localState = iscsiAuthLocalStateError;
- client->debugStatus =
- iscsiAuthDebugStatusChapIdentifierBad;
- break;
- }
- chapIdentifier = number;
-
- if (client->recvChapChallengeStatus) {
- client->localState = iscsiAuthLocalStateError;
- client->debugStatus =
- iscsiAuthDebugStatusChapChallengeBad;
- break;
- }
-
- if (client->nodeType == iscsiAuthNodeTypeTarget &&
- client->recvChapChallenge.length ==
- client->sendChapChallenge.length &&
- bcmp(client->recvChapChallenge.largeBinary,
- client->sendChapChallenge.largeBinary,
- client->sendChapChallenge.length) == 0) {
-
- client->localState = iscsiAuthLocalStateError;
- client->debugStatus =
- iscsiAuthDebugStatusChapChallengeReflected;
- break;
- }
-
- debugStatus = iscsiAuthClientChapComputeResponse(client,
- FALSE,
- chapIdentifier,
- client->recvChapChallenge.largeBinary,
- client->recvChapChallenge.length, responseData);
-
- if (debugStatus != iscsiAuthDebugStatusNotSet) {
- client->localState = iscsiAuthLocalStateError;
- client->debugStatus = debugStatus;
- break;
- }
-
- (void) iscsiAuthClientDataToText(client->base64,
- responseData, iscsiAuthChapResponseLength,
- client->scratchKeyValue, iscsiAuthStringMaxLength);
- iscsiAuthClientSetKeyValue(&client->sendKeyBlock,
- iscsiAuthKeyTypeChapResponse, client->scratchKeyValue);
-
- iscsiAuthClientSetKeyValue(&client->sendKeyBlock,
- iscsiAuthKeyTypeChapUsername, client->username);
-
- client->localState = iscsiAuthLocalStateDone;
- break;
-
- case iscsiAuthLocalStateDone:
- break;
-
- case iscsiAuthLocalStateError:
- default:
- client->phase = iscsiAuthPhaseError;
- }
-}
-
-
-static void
-iscsiAuthClientRemoteAuthentication(IscsiAuthClient * client)
-{
- unsigned char idData[1];
- unsigned char responseData[iscsiAuthStringMaxLength];
- unsigned int responseLength = iscsiAuthStringMaxLength;
- unsigned char myResponseData[iscsiAuthChapResponseLength];
- int status;
- IscsiAuthDebugStatus debugStatus;
- const char *chapResponseKeyValue;
- const char *chapUsernameKeyValue;
-
- switch (client->remoteState) {
- case iscsiAuthRemoteStateSendAlgorithm:
- if (client->nodeType == iscsiAuthNodeTypeInitiator) {
- client->remoteState = iscsiAuthRemoteStateSendChallenge;
- break;
- }
-
- /* FALLTHRU */
-
- case iscsiAuthRemoteStateSendChallenge:
- if (!client->authRemote) {
- client->remoteAuthStatus = iscsiAuthStatusPass;
- client->debugStatus =
- iscsiAuthDebugStatusAuthRemoteFalse;
- client->remoteState = iscsiAuthRemoteStateDone;
- break;
- }
-
- iscsiAuthRandomSetData(idData, 1);
- client->sendChapIdentifier = idData[0];
-
- iscsiAuthClientNumberToText(client->sendChapIdentifier,
- client->scratchKeyValue, iscsiAuthStringMaxLength);
- iscsiAuthClientSetKeyValue(&client->sendKeyBlock,
- iscsiAuthKeyTypeChapIdentifier, client->scratchKeyValue);
-
- client->sendChapChallenge.length = client->chapChallengeLength;
- iscsiAuthRandomSetData(client->sendChapChallenge.largeBinary,
- client->sendChapChallenge.length);
-
- iscsiAuthClientSetKeyValue(&client->sendKeyBlock,
- iscsiAuthKeyTypeChapChallenge, "");
-
- client->remoteState = iscsiAuthRemoteStateRecvResponse;
- break;
-
- case iscsiAuthRemoteStateRecvResponse:
- chapResponseKeyValue = iscsiAuthClientGetKeyValue(
- &client->recvKeyBlock, iscsiAuthKeyTypeChapResponse);
-
- chapUsernameKeyValue = iscsiAuthClientGetKeyValue(
- &client->recvKeyBlock, iscsiAuthKeyTypeChapUsername);
-
- if (!chapResponseKeyValue) {
- client->remoteState = iscsiAuthRemoteStateError;
- client->debugStatus =
- iscsiAuthDebugStatusChapResponseExpected;
- break;
- }
-
- if (!chapUsernameKeyValue) {
- client->remoteState = iscsiAuthRemoteStateError;
- client->debugStatus =
- iscsiAuthDebugStatusChapUsernameExpected;
- break;
- }
-
- status = iscsiAuthClientTextToData(chapResponseKeyValue,
- responseData, &responseLength);
-
- if (status) {
- client->remoteState = iscsiAuthRemoteStateError;
- client->debugStatus =
- iscsiAuthDebugStatusChapResponseBad;
- break;
- }
-
- if (responseLength == iscsiAuthChapResponseLength) {
- debugStatus = iscsiAuthClientChapComputeResponse(
- client, TRUE, client->sendChapIdentifier,
- client->sendChapChallenge.largeBinary,
- client->sendChapChallenge.length, myResponseData);
-
- /*
- * Check if the same CHAP secret is being used for
- * authentication in both directions.
- */
- if (debugStatus == iscsiAuthDebugStatusNotSet &&
- bcmp(myResponseData, responseData,
- iscsiAuthChapResponseLength) == 0) {
-
- client->remoteState =
- iscsiAuthRemoteStateError;
- client->debugStatus =
- iscsiAuthDebugStatusPasswordIdentical;
- break;
- }
- }
-
- (void) iscsiAuthClientStringCopy(client->chapUsername,
- chapUsernameKeyValue, iscsiAuthStringMaxLength);
-
- /* To verify the target's response. */
- status = iscsiAuthClientChapAuthRequest(
- client, client->chapUsername, client->sendChapIdentifier,
- client->sendChapChallenge.largeBinary,
- client->sendChapChallenge.length, responseData,
- responseLength);
-
- if (status == iscsiAuthStatusInProgress) {
- iscsiAuthClientGlobalStats.requestSent++;
- client->remoteState = iscsiAuthRemoteStateAuthRequest;
- break;
- }
-
- client->remoteAuthStatus = (IscsiAuthStatus) status;
- client->authResponseFlag = TRUE;
-
- /* FALLTHRU */
-
- case iscsiAuthRemoteStateAuthRequest:
- /*
- * client->remoteAuthStatus already set
- */
- if (client->authServerErrorFlag) {
- client->remoteAuthStatus = iscsiAuthStatusFail;
- client->debugStatus =
- iscsiAuthDebugStatusAuthServerError;
- } else if (client->remoteAuthStatus == iscsiAuthStatusPass) {
- client->debugStatus = iscsiAuthDebugStatusAuthPass;
- } else if (client->remoteAuthStatus == iscsiAuthStatusFail) {
- client->debugStatus = iscsiAuthDebugStatusAuthFail;
- } else {
- client->remoteAuthStatus = iscsiAuthStatusFail;
- client->debugStatus = iscsiAuthDebugStatusAuthStatusBad;
- }
- client->remoteState = iscsiAuthRemoteStateDone;
-
- /* FALLTHRU */
-
- case iscsiAuthRemoteStateDone:
- break;
-
- case iscsiAuthRemoteStateError:
- default:
- client->phase = iscsiAuthPhaseError;
- }
-}
-
-
-static void
-iscsiAuthClientHandshake(IscsiAuthClient * client)
-{
- if (client->phase == iscsiAuthPhaseDone) {
- /*
- * Should only happen if authentication
- * protocol error occured.
- */
- return;
- }
-
- if (client->remoteState == iscsiAuthRemoteStateAuthRequest) {
- /*
- * Defer until authentication response received
- * from internal authentication service.
- */
- return;
- }
-
- if (client->nodeType == iscsiAuthNodeTypeInitiator) {
-
- /*
- * Target should only have set T bit on response if
- * initiator set it on previous message.
- */
- if (client->recvKeyBlock.transitBit &&
- client->transitBitSentFlag == 0) {
- client->remoteAuthStatus = iscsiAuthStatusFail;
- client->phase = iscsiAuthPhaseDone;
- client->debugStatus =
- iscsiAuthDebugStatusTbitSetIllegal;
- return;
- }
- }
-
- if (client->phase == iscsiAuthPhaseNegotiate) {
- /*
- * Should only happen if waiting for peer
- * to send AuthMethod key or set Transit Bit.
- */
- if (client->nodeType == iscsiAuthNodeTypeInitiator) {
- client->sendKeyBlock.transitBit = TRUE;
- }
- return;
- }
-
- if (client->remoteState == iscsiAuthRemoteStateRecvResponse ||
- client->remoteState == iscsiAuthRemoteStateDone) {
-
- if (client->nodeType == iscsiAuthNodeTypeInitiator) {
- if (client->recvKeyBlock.transitBit) {
- if (client->remoteState !=
- iscsiAuthRemoteStateDone) {
- goto recvTransitBitError;
- }
- iscsiAuthClientNextPhase(client);
- } else {
- client->sendKeyBlock.transitBit = TRUE;
- }
- } else {
- if (client->remoteState == iscsiAuthRemoteStateDone &&
- client->remoteAuthStatus != iscsiAuthStatusPass) {
-
- /*
- * Authentication failed, don't
- * do T bit handshake.
- */
- iscsiAuthClientNextPhase(client);
- } else {
-
- /*
- * Target can only set T bit on response if
- * initiator set it on current message.
- */
- if (client->recvKeyBlock.transitBit) {
- client->sendKeyBlock.transitBit = TRUE;
- iscsiAuthClientNextPhase(client);
- }
- }
- }
- } else {
- if (client->nodeType == iscsiAuthNodeTypeInitiator) {
- if (client->recvKeyBlock.transitBit) {
- goto recvTransitBitError;
- }
- }
- }
-
- return;
-
-recvTransitBitError:
- /*
- * Target set T bit on response but
- * initiator was not done with authentication.
- */
- client->remoteAuthStatus = iscsiAuthStatusFail;
- client->phase = iscsiAuthPhaseDone;
- client->debugStatus = iscsiAuthDebugStatusTbitSetPremature;
-}
-
-
-static int
-iscsiAuthClientRecvEndStatus(IscsiAuthClient * client)
-{
- int authStatus;
- int keyType;
-
- if (client->phase == iscsiAuthPhaseError) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase == iscsiAuthPhaseDone) {
-
- /*
- * Perform sanity check against configured parameters.
- */
-
- if (client->authRemote && !client->authResponseFlag &&
- client->remoteAuthStatus == iscsiAuthStatusPass) {
-
- client->remoteAuthStatus = iscsiAuthStatusFail;
- client->debugStatus =
- iscsiAuthDebugStatusAuthPassNotValid;
- }
-
- authStatus = client->remoteAuthStatus;
- } else if (client->remoteState == iscsiAuthRemoteStateAuthRequest) {
- authStatus = iscsiAuthStatusInProgress;
- } else {
- authStatus = iscsiAuthStatusContinue;
- }
-
- if (authStatus != iscsiAuthStatusInProgress) {
- client->recvInProgressFlag = FALSE;
- }
-
- if (authStatus == iscsiAuthStatusContinue ||
- authStatus == iscsiAuthStatusPass) {
- if (client->sendKeyBlock.duplicateSet) {
- client->remoteAuthStatus = iscsiAuthStatusFail;
- client->phase = iscsiAuthPhaseDone;
- client->debugStatus =
- iscsiAuthDebugStatusSendDuplicateSetKeyValue;
- authStatus = iscsiAuthStatusFail;
- } else if (client->sendKeyBlock.stringTooLong) {
- client->remoteAuthStatus = iscsiAuthStatusFail;
- client->phase = iscsiAuthPhaseDone;
- client->debugStatus =
- iscsiAuthDebugStatusSendStringTooLong;
- authStatus = iscsiAuthStatusFail;
- } else if (client->sendKeyBlock.tooMuchData) {
- client->remoteAuthStatus = iscsiAuthStatusFail;
- client->phase = iscsiAuthPhaseDone;
- client->debugStatus =
- iscsiAuthDebugStatusSendTooMuchData;
- authStatus = iscsiAuthStatusFail;
- } else {
- /*
- * Check that all incoming keys have been processed.
- */
- for (keyType = iscsiAuthKeyTypeFirst;
- keyType < iscsiAuthKeyTypeMaxCount; keyType++) {
- if (client->recvKeyBlock.key[keyType].present &&
- client->recvKeyBlock.key[keyType].
- processed == 0) {
- break;
- }
- }
-
- if (keyType < iscsiAuthKeyTypeMaxCount) {
- client->remoteAuthStatus = iscsiAuthStatusFail;
- client->phase = iscsiAuthPhaseDone;
- client->debugStatus =
- iscsiAuthDebugStatusUnexpectedKeyPresent;
- authStatus = iscsiAuthStatusFail;
- }
- }
- }
-
- if (authStatus != iscsiAuthStatusPass &&
- authStatus != iscsiAuthStatusContinue &&
- authStatus != iscsiAuthStatusInProgress) {
- int authMethodKeyPresent = FALSE;
- int chapAlgorithmKeyPresent = FALSE;
-
- /*
- * Suppress send keys on error, except
- * for AuthMethod and CHAP_A.
- */
- if (client->nodeType == iscsiAuthNodeTypeTarget) {
- if (iscsiAuthClientGetKeyValue(&client->sendKeyBlock,
- iscsiAuthKeyTypeAuthMethod)) {
- authMethodKeyPresent = TRUE;
- } else if (iscsiAuthClientGetKeyValue(
- &client->sendKeyBlock,
- iscsiAuthKeyTypeChapAlgorithm)) {
- chapAlgorithmKeyPresent = TRUE;
- }
- }
-
- iscsiAuthClientInitKeyBlock(&client->sendKeyBlock);
-
- if (client->nodeType == iscsiAuthNodeTypeTarget) {
- if (authMethodKeyPresent &&
- client->negotiatedAuthMethod ==
- iscsiAuthOptionReject) {
- iscsiAuthClientSetKeyValue(
- &client->sendKeyBlock,
- iscsiAuthKeyTypeAuthMethod,
- client->rejectOptionName);
- } else if (chapAlgorithmKeyPresent &&
- client->negotiatedChapAlgorithm ==
- iscsiAuthOptionReject) {
- iscsiAuthClientSetKeyValue(
- &client->sendKeyBlock,
- iscsiAuthKeyTypeChapAlgorithm,
- client->rejectOptionName);
- }
- }
- }
-
- return (authStatus);
-}
-
-
-int
-iscsiAuthClientRecvBegin(IscsiAuthClient * client)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase == iscsiAuthPhaseError) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase == iscsiAuthPhaseDone) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- if (client->recvInProgressFlag) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- client->recvInProgressFlag = TRUE;
-
- if (client->phase == iscsiAuthPhaseConfigure) {
- iscsiAuthClientNextPhase(client);
- }
-
- client->transitBitSentFlag = client->sendKeyBlock.transitBit;
-
- iscsiAuthClientInitKeyBlock(&client->recvKeyBlock);
- iscsiAuthClientInitKeyBlock(&client->sendKeyBlock);
-
- return (iscsiAuthStatusNoError);
-}
-
-
-int
-iscsiAuthClientRecvEnd(IscsiAuthClient * client,
- IscsiAuthClientCallback * callback, void *userHandle, void *messageHandle)
-{
- int nextPhaseFlag = FALSE;
-
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase == iscsiAuthPhaseError) {
- return (iscsiAuthStatusError);
- }
-
- if (!callback || !client->recvInProgressFlag) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- if (client->recvEndCount > iscsiAuthRecvEndMaxCount) {
- client->remoteAuthStatus = iscsiAuthStatusFail;
- client->phase = iscsiAuthPhaseDone;
- client->debugStatus =
- iscsiAuthDebugStatusRecvMessageCountLimit;
- } else if (client->recvKeyBlock.duplicateSet) {
- client->remoteAuthStatus = iscsiAuthStatusFail;
- client->phase = iscsiAuthPhaseDone;
- client->debugStatus =
- iscsiAuthDebugStatusRecvDuplicateSetKeyValue;
- } else if (client->recvKeyBlock.stringTooLong) {
- client->remoteAuthStatus = iscsiAuthStatusFail;
- client->phase = iscsiAuthPhaseDone;
- client->debugStatus = iscsiAuthDebugStatusRecvStringTooLong;
- } else if (client->recvKeyBlock.tooMuchData) {
- client->remoteAuthStatus = iscsiAuthStatusFail;
- client->phase = iscsiAuthPhaseDone;
- client->debugStatus = iscsiAuthDebugStatusRecvTooMuchData;
- }
-
- client->recvEndCount++;
-
- client->callback = callback;
- client->userHandle = userHandle;
- client->messageHandle = messageHandle;
-
- switch (client->phase) {
- case iscsiAuthPhaseNegotiate:
- iscsiAuthClientCheckAuthMethodKey(client);
-
- if (client->authMethodValidNegRole ==
- iscsiAuthNegRoleResponder) {
- if (client->negotiatedAuthMethod ==
- iscsiAuthOptionNotPresent) {
- if (client->authRemote ||
- client->recvKeyBlock.transitBit == 0) {
- /*
- * No AuthMethod key from peer
- * on first message, try moving
- * the process along by sending
- * the AuthMethod key.
- */
-
- client->authMethodValidNegRole =
- iscsiAuthNegRoleOriginator;
-
- iscsiAuthClientSetAuthMethodKey(client,
- client->authMethodValidCount,
- client->authMethodValidList);
- break;
- }
-
- /*
- * Special case if peer sent no
- * AuthMethod key, but did set Transit
- * Bit, allowing this side to do a
- * null authentication, and compelete
- * the iSCSI security phase without
- * either side sending the AuthMethod
- * key.
- */
- } else {
- /*
- * Send response to AuthMethod key.
- */
-
- iscsiAuthClientSetAuthMethodKey(client, 1,
- &client->negotiatedAuthMethod);
- }
-
- if (client->nodeType == iscsiAuthNodeTypeInitiator) {
- iscsiAuthClientNextPhase(client);
- } else {
- nextPhaseFlag = TRUE;
- }
-
- } else {
- if (client->negotiatedAuthMethod ==
- iscsiAuthOptionNotPresent) {
- client->remoteAuthStatus = iscsiAuthStatusFail;
- client->phase = iscsiAuthPhaseDone;
- client->debugStatus =
- iscsiAuthDebugStatusAuthMethodExpected;
- break;
- }
-
- iscsiAuthClientNextPhase(client);
- }
- break;
-
- case iscsiAuthPhaseAuthenticate:
- case iscsiAuthPhaseDone:
- break;
-
- default:
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- switch (client->phase) {
- case iscsiAuthPhaseNegotiate:
- if (nextPhaseFlag) {
- iscsiAuthClientNextPhase(client);
- }
- break;
-
- case iscsiAuthPhaseAuthenticate:
- /*
- * Must call iscsiAuthClientLocalAuthentication()
- * before iscsiAuthClientRemoteAuthentication()
- * to insure processing of the CHAP algorithm key,
- * and to avoid leaving an in progress request to the
- * authentication service.
- */
- iscsiAuthClientLocalAuthentication(client);
-
- if (client->localState != iscsiAuthLocalStateError) {
- iscsiAuthClientRemoteAuthentication(client);
- }
-
- if (client->localState == iscsiAuthLocalStateError ||
- client->remoteState == iscsiAuthRemoteStateError) {
-
- client->remoteAuthStatus = iscsiAuthStatusFail;
- client->phase = iscsiAuthPhaseDone;
- /*
- * client->debugStatus should already be set.
- */
- }
- break;
-
- case iscsiAuthPhaseDone:
- break;
-
- default:
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- iscsiAuthClientHandshake(client);
-
- return (iscsiAuthClientRecvEndStatus(client));
-}
-
-
-#ifdef notused
-void
-iscsiAuthClientAuthResponse(IscsiAuthClient * client, int authStatus)
-{
- iscsiAuthClientGlobalStats.responseReceived++;
-
- if (!client || client->signature != iscsiAuthClientSignature) {
- return;
- }
-
- if (!client->recvInProgressFlag ||
- client->phase != iscsiAuthPhaseAuthenticate ||
- client->remoteState != iscsiAuthRemoteStateAuthRequest) {
-
- client->phase = iscsiAuthPhaseError;
- return;
- }
-
- client->remoteAuthStatus = (IscsiAuthStatus) authStatus;
- client->authResponseFlag = TRUE;
-
- iscsiAuthClientRemoteAuthentication(client);
-
- iscsiAuthClientHandshake(client);
-
- authStatus = iscsiAuthClientRecvEndStatus(client);
-
- client->callback(client->userHandle, client->messageHandle, authStatus);
-}
-#endif
-
-
-const char *
-iscsiAuthClientGetKeyName(int keyType)
-{
- if (keyType < iscsiAuthKeyTypeFirst || keyType > iscsiAuthKeyTypeLast) {
- return (0);
- }
- return (iscsiAuthClientKeyInfo[keyType].name);
-}
-
-
-int
-iscsiAuthClientGetNextKeyType(int *pKeyType)
-{
- int keyType = *pKeyType;
-
- if (keyType >= iscsiAuthKeyTypeLast) {
- return (iscsiAuthStatusError);
- }
-
- if (keyType < iscsiAuthKeyTypeFirst) {
- keyType = iscsiAuthKeyTypeFirst;
- } else {
- keyType++;
- }
-
- *pKeyType = keyType;
-
- return (iscsiAuthStatusNoError);
-}
-
-
-#ifdef notused
-int
-iscsiAuthClientKeyNameToKeyType(const char *keyName)
-{
- int keyType = iscsiAuthKeyTypeNone;
-
- while (iscsiAuthClientGetNextKeyType(&keyType) ==
- iscsiAuthStatusNoError) {
- const char *keyName2 = iscsiAuthClientGetKeyName(keyType);
-
- if (!keyName2) {
- return (iscsiAuthKeyTypeNone);
- }
-
- if (strcmp(keyName, keyName2) == 0) {
- return (keyType);
- }
- }
-
- return (iscsiAuthKeyTypeNone);
-}
-#endif
-
-
-int
-iscsiAuthClientRecvKeyValue(IscsiAuthClient * client, int keyType,
- const char *userKeyValue)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseNegotiate &&
- client->phase != iscsiAuthPhaseAuthenticate) {
-
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- if (keyType < iscsiAuthKeyTypeFirst || keyType > iscsiAuthKeyTypeLast) {
-
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- if (keyType == iscsiAuthKeyTypeChapChallenge) {
- client->recvChapChallenge.length =
- iscsiAuthLargeBinaryMaxLength;
- client->recvChapChallengeStatus =
- iscsiAuthClientTextToData(userKeyValue,
- client->recvChapChallenge.largeBinary,
- &client->recvChapChallenge.length);
- userKeyValue = "";
- }
-
- iscsiAuthClientSetKeyValue(&client->recvKeyBlock,
- keyType, userKeyValue);
-
- return (iscsiAuthStatusNoError);
-}
-
-
-int
-iscsiAuthClientSendKeyValue(IscsiAuthClient * client, int keyType,
- int *keyPresent, char *userKeyValue, unsigned int maxLength)
-{
- const char *keyValue;
-
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseConfigure &&
- client->phase != iscsiAuthPhaseNegotiate &&
- client->phase != iscsiAuthPhaseAuthenticate &&
- client->phase != iscsiAuthPhaseDone) {
-
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- if (keyType < iscsiAuthKeyTypeFirst || keyType > iscsiAuthKeyTypeLast) {
-
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- keyValue = iscsiAuthClientGetKeyValue(&client->sendKeyBlock, keyType);
- if (keyValue) {
- if (keyType == iscsiAuthKeyTypeChapChallenge) {
- if (iscsiAuthClientDataToText(client->base64,
- client->sendChapChallenge.largeBinary,
- client->sendChapChallenge.length,
- userKeyValue, maxLength)) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
- } else {
- if (iscsiAuthClientStringCopy(userKeyValue,
- keyValue, maxLength)) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
- }
- *keyPresent = TRUE;
- } else {
- *keyPresent = FALSE;
- }
-
- return (iscsiAuthStatusNoError);
-}
-
-
-int
-iscsiAuthClientRecvTransitBit(IscsiAuthClient * client, int value)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseNegotiate &&
- client->phase != iscsiAuthPhaseAuthenticate) {
-
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- if (value) {
- client->recvKeyBlock.transitBit = TRUE;
- } else {
- client->recvKeyBlock.transitBit = FALSE;
- }
-
- return (iscsiAuthStatusNoError);
-}
-
-
-int
-iscsiAuthClientSendTransitBit(IscsiAuthClient * client, int *value)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseConfigure &&
- client->phase != iscsiAuthPhaseNegotiate &&
- client->phase != iscsiAuthPhaseAuthenticate &&
- client->phase != iscsiAuthPhaseDone) {
-
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- *value = client->sendKeyBlock.transitBit;
-
- return (iscsiAuthStatusNoError);
-}
-
-
-int
-iscsiAuthClientInit(int nodeType, int bufferDescCount,
- IscsiAuthBufferDesc * bufferDesc)
-{
- IscsiAuthClient *client;
- IscsiAuthStringBlock *recvStringBlock;
- IscsiAuthStringBlock *sendStringBlock;
- IscsiAuthLargeBinary *recvChapChallenge;
- IscsiAuthLargeBinary *sendChapChallenge;
- int valueList[2];
-
- if (bufferDescCount != 5 ||
- bufferDesc == 0) {
- return (iscsiAuthStatusError);
- }
-
- if (!bufferDesc[0].address ||
- bufferDesc[0].length != sizeof (*client)) {
- return (iscsiAuthStatusError);
- }
- client = (IscsiAuthClient *) bufferDesc[0].address;
-
- if (bufferDesc[1].address == 0 ||
- bufferDesc[1].length != sizeof (*recvStringBlock)) {
- return (iscsiAuthStatusError);
- }
- recvStringBlock = (IscsiAuthStringBlock *) bufferDesc[1].address;
-
- if (bufferDesc[2].address == 0 ||
- bufferDesc[2].length != sizeof (*sendStringBlock)) {
- return (iscsiAuthStatusError);
- }
- sendStringBlock = (IscsiAuthStringBlock *) bufferDesc[2].address;
-
- if (bufferDesc[3].address == 0 ||
- bufferDesc[3].length != sizeof (*recvChapChallenge)) {
- return (iscsiAuthStatusError);
- }
- recvChapChallenge = (IscsiAuthLargeBinary *) bufferDesc[3].address;
-
- if (bufferDesc[4].address == 0 ||
- bufferDesc[4].length != sizeof (*sendChapChallenge)) {
- return (iscsiAuthStatusError);
- }
- sendChapChallenge = (IscsiAuthLargeBinary *) bufferDesc[4].address;
-
- bzero(client, sizeof (*client));
- bzero(recvStringBlock, sizeof (*recvStringBlock));
- bzero(sendStringBlock, sizeof (*sendStringBlock));
- bzero(recvChapChallenge, sizeof (*recvChapChallenge));
- bzero(sendChapChallenge, sizeof (*sendChapChallenge));
-
- client->recvKeyBlock.stringBlock = recvStringBlock->stringBlock;
- client->sendKeyBlock.stringBlock = sendStringBlock->stringBlock;
- client->recvChapChallenge.largeBinary = recvChapChallenge->largeBinary;
- client->sendChapChallenge.largeBinary = sendChapChallenge->largeBinary;
-
- if (iscsiAuthClientCheckNodeType(nodeType)) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- client->signature = iscsiAuthClientSignature;
- client->nodeType = (IscsiAuthNodeType) nodeType;
- /* Assume bi-directional authentication enabled. */
- client->authRemote = TRUE;
- client->passwordPresent = FALSE;
- client->version = iscsiAuthVersionRfc;
- client->chapChallengeLength = iscsiAuthChapResponseLength;
- client->ipSec = TRUE;
- client->base64 = FALSE;
-
- client->phase = iscsiAuthPhaseConfigure;
- client->negotiatedAuthMethod = iscsiAuthOptionNotPresent;
- client->negotiatedChapAlgorithm = iscsiAuthOptionNotPresent;
-
- if (client->nodeType == iscsiAuthNodeTypeInitiator) {
- client->authMethodNegRole = iscsiAuthNegRoleOriginator;
- } else {
- /*
- * Initial value ignored for Target.
- */
- client->authMethodNegRole = iscsiAuthNegRoleResponder;
- }
-
- /* All supported authentication methods */
- valueList[0] = iscsiAuthMethodChap;
- valueList[1] = iscsiAuthOptionNone;
-
- /*
- * Must call after setting authRemote, password,
- * version and authMethodNegRole
- */
- if (iscsiAuthClientSetAuthMethodList(client, 2, valueList) !=
- iscsiAuthStatusNoError) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- valueList[0] = iscsiAuthChapAlgorithmMd5;
-
- if (iscsiAuthClientSetChapAlgorithmList(client, 1, valueList) !=
- iscsiAuthStatusNoError) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- return (iscsiAuthStatusNoError);
-}
-
-
-#ifdef notused
-int
-iscsiAuthClientFinish(IscsiAuthClient * client)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- iscsiAuthClientChapAuthCancel(client);
-
- bzero(client, sizeof (*client));
-
- return (iscsiAuthStatusNoError);
-}
-#endif
-
-
-static int
-iscsiAuthClientSetOptionList(IscsiAuthClient * client,
- unsigned int optionCount,
- const int *optionList,
- unsigned int *clientOptionCount,
- int *clientOptionList,
- unsigned int optionMaxCount,
- int (*checkOption) (int),
- int (*checkList) (unsigned int optionCount, const int *optionList))
-{
- unsigned int i;
- unsigned int j;
-
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseConfigure ||
- optionCount > optionMaxCount) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- for (i = 0; i < optionCount; i++) {
- if ((*checkOption) (optionList[i])) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
- }
-
- /*
- * Check for duplicate entries.
- */
- for (i = 0; i < optionCount; i++) {
- for (j = 0; j < optionCount; j++) {
- if (j == i)
- continue;
- if (optionList[i] == optionList[j]) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
- }
- }
-
- /*
- * Check for key specific constraints.
- */
- if (checkList) {
- if ((*checkList) (optionCount, optionList)) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
- }
-
- for (i = 0; i < optionCount; i++) {
- clientOptionList[i] = optionList[i];
- }
-
- *clientOptionCount = optionCount;
-
- return (iscsiAuthStatusNoError);
-}
-
-
-static void
-iscsiAuthClientSetAuthMethodValid(IscsiAuthClient * client)
-{
- static const char rejectOptionNameDraft8[] = "reject";
- static const char rejectOptionNameRfc[] = "Reject";
- static const char noneOptionNameDraft8[] = "none";
- static const char noneOptionNameRfc[] = "None";
- unsigned int i;
- unsigned int j = 0;
- int option = 0;
-
- if (client->version == iscsiAuthVersionDraft8) {
- client->rejectOptionName = rejectOptionNameDraft8;
- client->noneOptionName = noneOptionNameDraft8;
- } else {
- client->rejectOptionName = rejectOptionNameRfc;
- client->noneOptionName = noneOptionNameRfc;
- }
-
- /*
- * Following checks may need to be revised if
- * authentication options other than CHAP and none
- * are supported.
- */
-
- if (client->nodeType == iscsiAuthNodeTypeInitiator) {
-
- if (client->authRemote) {
- /*
- * If initiator doing authentication,
- * don't offer authentication option none.
- */
- option = 1;
- } else if (!client->passwordPresent) {
- /*
- * If initiator password not set,
- * only offer authentication option none.
- */
- option = 2;
- }
- }
-
- if (client->nodeType == iscsiAuthNodeTypeTarget) {
-
- if (client->authRemote) {
- /*
- * If target doing authentication,
- * don't accept authentication option none.
- */
- option = 1;
- } else {
- /*
- * If target not doing authentication,
- * only accept authentication option none.
- */
- option = 2;
- }
- }
-
- for (i = 0; i < client->authMethodCount; i++) {
-
- if (option == 1) {
- if (client->authMethodList[i] == iscsiAuthOptionNone) {
- continue;
- }
- } else if (option == 2) {
- if (client->authMethodList[i] != iscsiAuthOptionNone) {
- continue;
- }
- }
-
- client->authMethodValidList[j++] = client->authMethodList[i];
- }
-
- client->authMethodValidCount = j;
-
- iscsiAuthClientInitKeyBlock(&client->sendKeyBlock);
-
- if (client->nodeType == iscsiAuthNodeTypeInitiator) {
- if (client->authRemote) {
- /*
- * Initiator wants to authenticate target,
- * always send AuthMethod key.
- */
- client->sendKeyBlock.transitBit = FALSE;
- client->authMethodValidNegRole =
- iscsiAuthNegRoleOriginator;
- } else {
- client->sendKeyBlock.transitBit = TRUE;
- client->authMethodValidNegRole =
- client->authMethodNegRole;
- }
- } else {
- client->sendKeyBlock.transitBit = FALSE;
- client->authMethodValidNegRole = iscsiAuthNegRoleResponder;
- }
-
- if (client->authMethodValidNegRole == iscsiAuthNegRoleOriginator) {
- iscsiAuthClientSetAuthMethodKey(client,
- client->authMethodValidCount,
- client->authMethodValidList);
- } else {
- int value = iscsiAuthOptionNotPresent;
- iscsiAuthClientSetAuthMethodKey(client, 1, &value);
- }
-}
-
-
-static int
-iscsiAuthClientCheckAuthMethodList(unsigned int optionCount,
- const int *optionList)
-{
- unsigned int i;
-
- if (!optionList || optionCount < 2) {
- return (TRUE);
- }
-
- if (optionList[optionCount - 1] != iscsiAuthOptionNone) {
- return (TRUE);
- }
-
- for (i = 0; i < (optionCount - 1); i++) {
- if (optionList[i] != iscsiAuthOptionNone) {
- return (FALSE);
- }
- }
-
- return (FALSE);
-}
-
-
-int
-iscsiAuthClientSetAuthMethodList(IscsiAuthClient * client,
- unsigned int optionCount, const int *optionList)
-{
- int status;
-
- status = iscsiAuthClientSetOptionList(
- client, optionCount, optionList, &client->authMethodCount,
- client->authMethodList, iscsiAuthMethodMaxCount,
- iscsiAuthClientCheckAuthMethodOption,
- iscsiAuthClientCheckAuthMethodList);
-
- if (status != iscsiAuthStatusNoError) {
- return (status);
- }
-
- /*
- * Setting authMethod affects authMethodValid.
- */
- iscsiAuthClientSetAuthMethodValid(client);
-
- return (iscsiAuthStatusNoError);
-}
-
-#ifdef notused
-int
-iscsiAuthClientSetAuthMethodNegRole(IscsiAuthClient * client, int negRole)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseConfigure ||
- iscsiAuthClientCheckNegRole(negRole) ||
- client->nodeType != iscsiAuthNodeTypeInitiator) {
-
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- client->authMethodNegRole = (IscsiAuthNegRole) negRole;
-
- /*
- * Setting negRole affects authMethodValid.
- */
- iscsiAuthClientSetAuthMethodValid(client);
-
- return (iscsiAuthStatusNoError);
-}
-#endif
-
-
-static int
-iscsiAuthClientCheckChapAlgorithmList(unsigned int optionCount,
- const int *optionList)
-{
- if (!optionList || optionCount < 1) {
- return (TRUE);
- }
-
- return (FALSE);
-}
-
-
-int
-iscsiAuthClientSetChapAlgorithmList(IscsiAuthClient * client,
- unsigned int optionCount, const int *optionList)
-{
- return (iscsiAuthClientSetOptionList(client,
- optionCount,
- optionList,
- &client->chapAlgorithmCount,
- client->chapAlgorithmList,
- iscsiAuthChapAlgorithmMaxCount,
- iscsiAuthClientCheckChapAlgorithmOption,
- iscsiAuthClientCheckChapAlgorithmList));
-}
-
-
-int
-iscsiAuthClientSetUsername(IscsiAuthClient * client, const char *username)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseConfigure ||
- iscsiAuthClientCheckString(username, iscsiAuthStringMaxLength, 0)) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- if (iscsiAuthClientStringCopy(client->username, username,
- iscsiAuthStringMaxLength)) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- return (iscsiAuthStatusNoError);
-}
-
-
-int
-iscsiAuthClientSetPassword(IscsiAuthClient * client,
- const unsigned char *passwordData, unsigned int passwordLength)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseConfigure ||
- passwordLength > iscsiAuthStringMaxLength) {
-
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- bcopy(passwordData, client->passwordData, passwordLength);
- client->passwordLength = passwordLength;
- if (client->passwordLength > 0) {
- client->passwordPresent = TRUE;
- } else {
- client->passwordPresent = FALSE;
- }
-
- /*
- * Setting password may affect authMethodValid.
- */
- iscsiAuthClientSetAuthMethodValid(client);
-
- return (iscsiAuthStatusNoError);
-}
-
-
-int
-iscsiAuthClientSetAuthRemote(IscsiAuthClient * client, int authRemote)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseConfigure) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- client->authRemote = authRemote;
-
- /*
- * Setting authRemote may affect authMethodValid.
- */
- iscsiAuthClientSetAuthMethodValid(client);
-
- return (iscsiAuthStatusNoError);
-}
-
-#ifdef notused
-int
-iscsiAuthClientSetGlueHandle(IscsiAuthClient * client, void *glueHandle)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseConfigure &&
- client->phase != iscsiAuthPhaseNegotiate &&
- client->phase != iscsiAuthPhaseAuthenticate) {
-
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- client->glueHandle = glueHandle;
-
- return (iscsiAuthStatusNoError);
-}
-
-int
-iscsiAuthClientSetMethodListName(IscsiAuthClient *client,
- const char *methodListName)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseConfigure ||
- iscsiAuthClientCheckString(methodListName,
- iscsiAuthStringMaxLength, 0)) {
-
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- if (iscsiAuthClientStringCopy(client->methodListName, methodListName,
- iscsiAuthStringMaxLength)) {
-
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- return (iscsiAuthStatusNoError);
-}
-#endif
-
-
-int
-iscsiAuthClientSetVersion(IscsiAuthClient * client, int version)
-{
- if (client == 0 ||
- client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseConfigure ||
- iscsiAuthClientCheckVersion(version)) {
-
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- client->version = (IscsiAuthVersion) version;
-
- iscsiAuthClientSetAuthMethodValid(client);
-
- return (iscsiAuthStatusNoError);
-}
-
-
-int
-iscsiAuthClientSetIpSec(IscsiAuthClient * client, int ipSec)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseConfigure) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- client->ipSec = ipSec;
-
- return (iscsiAuthStatusNoError);
-}
-
-#ifdef notused
-int
-iscsiAuthClientSetBase64(IscsiAuthClient * client, int base64)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseConfigure) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- client->base64 = base64;
-
- return (iscsiAuthStatusNoError);
-}
-
-int
-iscsiAuthClientSetChapChallengeLength(IscsiAuthClient * client,
- unsigned int chapChallengeLength)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseConfigure ||
- chapChallengeLength < iscsiAuthChapResponseLength ||
- chapChallengeLength > iscsiAuthLargeBinaryMaxLength) {
-
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- client->chapChallengeLength = chapChallengeLength;
-
- return (iscsiAuthStatusNoError);
-}
-
-
-int
-iscsiAuthClientCheckPasswordNeeded(IscsiAuthClient *client, int *passwordNeeded)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseConfigure) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- if (client->nodeType == iscsiAuthNodeTypeInitiator) {
- if (client->authRemote && !client->passwordPresent) {
- *passwordNeeded = TRUE;
- } else {
- *passwordNeeded = FALSE;
- }
- } else {
- *passwordNeeded = FALSE;
- }
-
- return (iscsiAuthStatusNoError);
-}
-
-
-int
-iscsiAuthClientGetAuthPhase(IscsiAuthClient * client, int *value)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- *value = client->phase;
-
- return (iscsiAuthStatusNoError);
-}
-
-
-int
-iscsiAuthClientGetAuthStatus(IscsiAuthClient * client, int *value)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseDone) {
-
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- *value = client->remoteAuthStatus;
-
- return (iscsiAuthStatusNoError);
-}
-
-
-int
-iscsiAuthClientAuthStatusPass(int authStatus)
-{
- if (authStatus == iscsiAuthStatusPass) {
- return (TRUE);
- }
-
- return (FALSE);
-}
-
-
-int
-iscsiAuthClientGetAuthMethod(IscsiAuthClient * client, int *value)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseDone &&
- client->phase != iscsiAuthPhaseAuthenticate) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- *value = client->negotiatedAuthMethod;
-
- return (iscsiAuthStatusNoError);
-}
-
-
-int
-iscsiAuthClientGetChapAlgorithm(IscsiAuthClient * client, int *value)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseDone) {
-
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- *value = client->negotiatedChapAlgorithm;
-
- return (iscsiAuthStatusNoError);
-}
-
-
-int
-iscsiAuthClientGetChapUsername(IscsiAuthClient * client,
- char *value, unsigned int maxLength)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseDone) {
-
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- if (iscsiAuthClientStringCopy(value, client->chapUsername, maxLength)) {
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- return (iscsiAuthStatusNoError);
-}
-
-
-int
-iscsiAuthClientSendStatusCode(IscsiAuthClient * client, int *statusCode)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseConfigure &&
- client->phase != iscsiAuthPhaseNegotiate &&
- client->phase != iscsiAuthPhaseAuthenticate &&
- client->phase != iscsiAuthPhaseDone) {
-
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseDone) {
- *statusCode = 0x0000;
- return (iscsiAuthStatusNoError);
- }
-
- switch (client->remoteAuthStatus) {
- case iscsiAuthStatusPass:
- *statusCode = 0x0000; /* no error */
- break;
-
- case iscsiAuthStatusFail:
- switch (client->debugStatus) {
- case iscsiAuthDebugStatusAuthFail:
- /*
- * Authentication error with peer.
- */
- if (client->nodeType == iscsiAuthNodeTypeInitiator) {
- *statusCode = 0x0300;
- /*
- * iSCSI Target error
- */
- } else {
- *statusCode = 0x0201;
- /*
- * iSCSI Initiator error
- */
- }
- break;
-
- case iscsiAuthDebugStatusAuthMethodExpected:
- case iscsiAuthDebugStatusChapAlgorithmExpected:
- case iscsiAuthDebugStatusChapIdentifierExpected:
- case iscsiAuthDebugStatusChapChallengeExpected:
- case iscsiAuthDebugStatusChapResponseExpected:
- case iscsiAuthDebugStatusChapUsernameExpected:
- /*
- * Missing parameter with peer.
- */
- if (client->nodeType == iscsiAuthNodeTypeInitiator) {
- *statusCode = 0x0300;
- /*
- * iSCSI Target error
- */
- } else {
- *statusCode = 0x0207;
- /*
- * iSCSI Initiator error
- */
- }
- break;
-
- case iscsiAuthDebugStatusAuthMethodNotPresent:
- case iscsiAuthDebugStatusAuthMethodReject:
- case iscsiAuthDebugStatusAuthMethodNone:
- case iscsiAuthDebugStatusChapAlgorithmReject:
- case iscsiAuthDebugStatusChapChallengeReflected:
- case iscsiAuthDebugStatusPasswordIdentical:
- /*
- * Could not authenticate with peer.
- */
- if (client->nodeType == iscsiAuthNodeTypeInitiator) {
- *statusCode = 0x0300;
- /*
- * iSCSI Target error
- */
- } else {
- *statusCode = 0x0201;
- /*
- * iSCSI Initiator error
- */
- }
- break;
-
- case iscsiAuthDebugStatusLocalPasswordNotSet:
- /*
- * Local password not set.
- */
- if (client->nodeType == iscsiAuthNodeTypeInitiator) {
- *statusCode = 0x0200;
- /*
- * iSCSI Initiator error
- */
- } else {
- *statusCode = 0x0201;
- /*
- * iSCSI Target error
- */
- }
- break;
-
- case iscsiAuthDebugStatusChapIdentifierBad:
- case iscsiAuthDebugStatusChapChallengeBad:
- case iscsiAuthDebugStatusChapResponseBad:
- case iscsiAuthDebugStatusUnexpectedKeyPresent:
- case iscsiAuthDebugStatusTbitSetIllegal:
- case iscsiAuthDebugStatusTbitSetPremature:
- case iscsiAuthDebugStatusRecvMessageCountLimit:
- case iscsiAuthDebugStatusRecvDuplicateSetKeyValue:
- case iscsiAuthDebugStatusRecvStringTooLong:
- case iscsiAuthDebugStatusRecvTooMuchData:
- /*
- * Other error with peer.
- */
- if (client->nodeType == iscsiAuthNodeTypeInitiator) {
- *statusCode = 0x0300;
- /*
- * iSCSI Target error
- */
- } else {
- *statusCode = 0x0200;
- /*
- * iSCSI Initiator error
- */
- }
- break;
-
- case iscsiAuthDebugStatusNotSet:
- case iscsiAuthDebugStatusAuthPass:
- case iscsiAuthDebugStatusAuthRemoteFalse:
- case iscsiAuthDebugStatusAuthMethodBad:
- case iscsiAuthDebugStatusChapAlgorithmBad:
- case iscsiAuthDebugStatusPasswordDecryptFailed:
- case iscsiAuthDebugStatusPasswordTooShortWithNoIpSec:
- case iscsiAuthDebugStatusAuthServerError:
- case iscsiAuthDebugStatusAuthStatusBad:
- case iscsiAuthDebugStatusAuthPassNotValid:
- case iscsiAuthDebugStatusSendDuplicateSetKeyValue:
- case iscsiAuthDebugStatusSendStringTooLong:
- case iscsiAuthDebugStatusSendTooMuchData:
- default:
- /*
- * Error on this side.
- */
- if (client->nodeType == iscsiAuthNodeTypeInitiator) {
- *statusCode = 0x0200;
- /*
- * iSCSI Initiator error
- */
- } else {
- *statusCode = 0x0300;
- /*
- * iSCSI Target error
- */
- }
-
- }
- break;
-
- case iscsiAuthStatusNoError:
- case iscsiAuthStatusError:
- case iscsiAuthStatusContinue:
- case iscsiAuthStatusInProgress:
- default:
- /*
- * Bad authStatus
- */
- if (client->nodeType == iscsiAuthNodeTypeInitiator) {
- *statusCode = 0x0200;
- /*
- * iSCSI Initiator error
- */
- } else {
- *statusCode = 0x0300;
- /*
- * iSCSI Target error
- */
- }
- }
-
- return (iscsiAuthStatusNoError);
-}
-#endif
-
-
-int
-iscsiAuthClientGetDebugStatus(IscsiAuthClient * client, int *value)
-{
- if (!client || client->signature != iscsiAuthClientSignature) {
- return (iscsiAuthStatusError);
- }
-
- if (client->phase != iscsiAuthPhaseDone) {
-
- client->phase = iscsiAuthPhaseError;
- return (iscsiAuthStatusError);
- }
-
- *value = client->debugStatus;
-
- return (iscsiAuthStatusNoError);
-}
-
-
-const char *
-iscsiAuthClientDebugStatusToText(int debugStatus)
-{
- const char *s;
-
- switch (debugStatus) {
- case iscsiAuthDebugStatusNotSet:
- s = "Debug status not set";
- break;
-
- case iscsiAuthDebugStatusAuthPass:
- s = "Authentication request passed";
- break;
-
- case iscsiAuthDebugStatusAuthRemoteFalse:
- s = "Authentication not enabled";
- break;
-
- case iscsiAuthDebugStatusAuthFail:
- s = "Authentication request failed";
- break;
-
- case iscsiAuthDebugStatusAuthMethodBad:
- s = "AuthMethod bad";
- break;
-
- case iscsiAuthDebugStatusChapAlgorithmBad:
- s = "CHAP algorithm bad";
- break;
-
- case iscsiAuthDebugStatusPasswordDecryptFailed:
- s = "Decrypt password failed";
- break;
-
- case iscsiAuthDebugStatusPasswordTooShortWithNoIpSec:
- s = "Local password too short with no IPSec";
- break;
-
- case iscsiAuthDebugStatusAuthServerError:
- s = "Unexpected error from authentication server";
- break;
-
- case iscsiAuthDebugStatusAuthStatusBad:
- s = "Authentication request status bad";
- break;
-
- case iscsiAuthDebugStatusAuthPassNotValid:
- s = "Authentication pass status not valid";
- break;
-
- case iscsiAuthDebugStatusSendDuplicateSetKeyValue:
- s = "Same key set more than once on send";
- break;
-
- case iscsiAuthDebugStatusSendStringTooLong:
- s = "Key value too long on send";
- break;
-
- case iscsiAuthDebugStatusSendTooMuchData:
- s = "Too much data on send";
- break;
-
- case iscsiAuthDebugStatusAuthMethodExpected:
- s = "AuthMethod key expected";
- break;
-
- case iscsiAuthDebugStatusChapAlgorithmExpected:
- s = "CHAP algorithm key expected";
- break;
-
- case iscsiAuthDebugStatusChapIdentifierExpected:
- s = "CHAP identifier expected";
- break;
-
- case iscsiAuthDebugStatusChapChallengeExpected:
- s = "CHAP challenge expected";
- break;
-
- case iscsiAuthDebugStatusChapResponseExpected:
- s = "CHAP response expected";
- break;
-
- case iscsiAuthDebugStatusChapUsernameExpected:
- s = "CHAP username expected";
- break;
-
- case iscsiAuthDebugStatusAuthMethodNotPresent:
- s = "AuthMethod key not present";
- break;
-
- case iscsiAuthDebugStatusAuthMethodReject:
- s = "AuthMethod negotiation failed";
- break;
-
- case iscsiAuthDebugStatusAuthMethodNone:
- s = "AuthMethod negotiated to none";
- break;
-
- case iscsiAuthDebugStatusChapAlgorithmReject:
- s = "CHAP algorithm negotiation failed";
- break;
-
- case iscsiAuthDebugStatusChapChallengeReflected:
- s = "CHAP challange reflected";
- break;
-
- case iscsiAuthDebugStatusPasswordIdentical:
- s = "Local password same as remote";
- break;
-
- case iscsiAuthDebugStatusLocalPasswordNotSet:
- s = "Local password not set";
- break;
-
- case iscsiAuthDebugStatusChapIdentifierBad:
- s = "CHAP identifier bad";
- break;
-
- case iscsiAuthDebugStatusChapChallengeBad:
- s = "CHAP challenge bad";
- break;
-
- case iscsiAuthDebugStatusChapResponseBad:
- s = "CHAP response bad";
- break;
-
- case iscsiAuthDebugStatusUnexpectedKeyPresent:
- s = "Unexpected key present";
- break;
-
- case iscsiAuthDebugStatusTbitSetIllegal:
- s = "T bit set on response, but not on previous message";
- break;
-
- case iscsiAuthDebugStatusTbitSetPremature:
- s = "T bit set on response, but authenticaton not complete";
- break;
-
- case iscsiAuthDebugStatusRecvMessageCountLimit:
- s = "Message count limit reached on receive";
- break;
-
- case iscsiAuthDebugStatusRecvDuplicateSetKeyValue:
- s = "Same key set more than once on receive";
- break;
-
- case iscsiAuthDebugStatusRecvStringTooLong:
- s = "Key value too long on receive";
- break;
-
- case iscsiAuthDebugStatusRecvTooMuchData:
- s = "Too much data on receive";
- break;
-
- default:
- s = "Unknown error";
- }
-
- return (s);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/iscsi_authglue.c b/usr/src/cmd/iscsi/iscsitgtd/iscsi_authglue.c
deleted file mode 100644
index 870707b187..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_authglue.c
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2000 by Cisco Systems, Inc. All rights reserved.
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- *
- * iSCSI Pseudo HBA Driver
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <sys/random.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <sys/socket.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <strings.h>
-#include <unistd.h>
-
-#include <sys/iscsi_protocol.h>
-#include <sys/iscsi_authclient.h>
-#include <sys/types.h>
-#include <iscsitgt_impl.h>
-#include "radius.h"
-#include "queue.h"
-#include "iscsi_sess.h"
-#include "target.h"
-
-#define DEFAULT_RADIUS_PORT 1812
-
-boolean_t
-persistent_radius_get(iscsi_radius_props_t *radius)
-{
- Boolean_t bRadiusAccess = False;
- char *szRadiusServer = NULL;
- char *szRadiusSecret = NULL;
- char *szRadiusPort = NULL;
- int ret = 0;
- struct addrinfo *res;
-
- bzero(radius, sizeof (radius));
- radius->r_radius_config_valid = B_FALSE;
-
- /* Load RADIUS access option: enable/disable */
- if (tgt_find_value_boolean(main_config, XML_ELEMENT_RAD_ACCESS,
- &bRadiusAccess) == False) {
- return (B_FALSE);
- }
- if (bRadiusAccess == False) {
- return (B_FALSE);
- }
-
- /* Load RADIUS server: ipaddr[:port] */
- if (tgt_find_value_str(main_config, XML_ELEMENT_RAD_SERV,
- &szRadiusServer) == False) {
- return (B_FALSE);
- }
-
- szRadiusPort = strchr(szRadiusServer, ':');
- if (szRadiusPort == NULL) {
- radius->r_port = DEFAULT_RADIUS_PORT;
- } else {
- radius->r_port = strtoul(szRadiusPort + 1, NULL, 0);
- if (radius->r_port == 0) {
- radius->r_port = DEFAULT_RADIUS_PORT;
- }
- *szRadiusPort = '\0';
- }
-
- ret = getaddrinfo(szRadiusServer, NULL, NULL, &res);
- free(szRadiusServer);
- if (ret != 0) {
- return (B_FALSE);
- }
- if (res->ai_family == PF_INET) {
- struct sockaddr_in sa_tmp;
-
- bcopy(res->ai_addr, &sa_tmp, sizeof (sa_tmp));
- radius->r_insize = sizeof (in_addr_t);
- radius->r_addr.u_in4 = sa_tmp.sin_addr;
- }
- /*
- * We don't handle IPV6 currently.
- */
-
- /* Load RADIUS shared secret */
- if (tgt_find_value_str(main_config, XML_ELEMENT_RAD_SECRET,
- &szRadiusSecret) == False) {
- freeaddrinfo(res);
- return (B_FALSE);
- }
- (void) strncpy((char *)radius->r_shared_secret, szRadiusSecret,
- MAX_RAD_SHARED_SECRET_LEN);
- radius->r_shared_secret_len = strlen((char *)radius->r_shared_secret);
- free(szRadiusSecret);
- freeaddrinfo(res);
-
- /* Set RADIUS config flag */
- radius->r_radius_access = B_TRUE;
- radius->r_radius_config_valid = B_TRUE;
- return (B_TRUE);
-}
-
-/*
- * Authenticate a target's CHAP response.
- *
- * username - Incoming username from the the target.
- * responseData - Incoming response data from the target.
- */
-int
-iscsiAuthClientChapAuthRequest(IscsiAuthClient *client,
- char *username, unsigned int id, uchar_t *challengeData,
- unsigned int challengeLength, uchar_t *responseData,
- unsigned int responseLength)
-{
- iscsi_sess_t *isp = (iscsi_sess_t *)client->userHandle;
- IscsiAuthMd5Context context;
- iscsi_radius_props_t p_radius_cfg;
- uchar_t verifyData[iscsiAuthChapResponseLength];
- char debug[128];
-
- if (isp == NULL) {
- return (iscsiAuthStatusFail);
- }
-
- /*
- * the expected credentials are in the session
- */
- if (isp->sess_auth.username_in == NULL) {
- (void) snprintf(debug, sizeof (debug),
- "SES%x iscsi session(%u) failed authentication, "
- "no incoming username configured to authenticate initiator",
- isp->s_num);
-
- queue_str(isp->s_mgmtq, Q_SESS_ERRS, msg_log, debug);
- return (iscsiAuthStatusFail);
- }
- if (strcmp(username, isp->sess_auth.username_in) != 0) {
- (void) snprintf(debug, sizeof (debug),
- "SES%x iscsi session(%u) failed authentication, "
- "received incorrect username from initiator",
- isp->s_num);
- queue_str(isp->s_mgmtq, Q_SESS_ERRS, msg_log, debug);
- return (iscsiAuthStatusFail);
- }
-
- /* Check if RADIUS access is enabled */
- if (persistent_radius_get(&p_radius_cfg) == B_TRUE &&
- p_radius_cfg.r_radius_access == B_TRUE) {
- chap_validation_status_type chap_valid_status;
- int authStatus;
- RADIUS_CONFIG radius_cfg;
-
- if (p_radius_cfg.r_radius_config_valid == B_FALSE) {
- /*
- * Radius enabled but configuration invalid -
- * invalid condition
- */
- return (iscsiAuthStatusFail);
- }
-
- /* Use RADIUS server to authentication target */
- if (p_radius_cfg.r_insize == sizeof (in_addr_t)) {
- /* IPv4 */
- radius_cfg.rad_svr_addr.i_addr.in4.s_addr =
- p_radius_cfg.r_addr.u_in4.s_addr;
- radius_cfg.rad_svr_addr.i_insize
- = sizeof (in_addr_t);
- } else if (p_radius_cfg.r_insize == sizeof (in6_addr_t)) {
- /* IPv6 */
- bcopy(p_radius_cfg.r_addr.u_in6.s6_addr,
- radius_cfg.rad_svr_addr.i_addr.in6.s6_addr,
- 16);
- radius_cfg.rad_svr_addr.i_insize = sizeof (in6_addr_t);
- } else {
- return (iscsiAuthStatusFail);
- }
-
- radius_cfg.rad_svr_port = p_radius_cfg.r_port;
- bcopy(p_radius_cfg.r_shared_secret,
- radius_cfg.rad_svr_shared_secret,
- MAX_RAD_SHARED_SECRET_LEN);
- radius_cfg.rad_svr_shared_secret_len =
- p_radius_cfg.r_shared_secret_len;
-
- chap_valid_status = radius_chap_validate(
- isp->sess_auth.username_in,
- isp->sess_auth.username,
- challengeData,
- challengeLength,
- responseData,
- responseLength,
- id,
- radius_cfg.rad_svr_addr,
- radius_cfg.rad_svr_port,
- radius_cfg.rad_svr_shared_secret,
- radius_cfg.rad_svr_shared_secret_len);
-
-
- switch (chap_valid_status) {
- case CHAP_VALIDATION_PASSED:
- authStatus = iscsiAuthStatusPass;
- break;
- case CHAP_VALIDATION_INVALID_RESPONSE:
- authStatus = iscsiAuthStatusFail;
- break;
- case CHAP_VALIDATION_DUP_SECRET:
- authStatus = iscsiAuthStatusFail;
- break;
- case CHAP_VALIDATION_RADIUS_ACCESS_ERROR:
- authStatus = iscsiAuthStatusFail;
- break;
- case CHAP_VALIDATION_BAD_RADIUS_SECRET:
- authStatus = iscsiAuthStatusFail;
- break;
- default:
- authStatus = iscsiAuthStatusFail;
- break;
- }
- return (authStatus);
- } else {
- /* Use target secret (if defined) to authenticate target */
- if ((isp->sess_auth.password_length_in < 1) ||
- (isp->sess_auth.password_in == NULL) ||
- (isp->sess_auth.password_in[0] == '\0')) {
- /* No target secret defined - invalid condition */
- return (iscsiAuthStatusFail);
- }
-
- /*
- * challenge length is I->T, and shouldn't need to
- * be checked
- */
- if (responseLength != sizeof (verifyData)) {
- (void) snprintf(debug, sizeof (debug),
- "SES%x iscsi session(%u) failed "
- "authentication, received incorrect CHAP response "
- "from initiator", isp->s_num);
- queue_str(isp->s_mgmtq, Q_SESS_ERRS, msg_log, debug);
- return (iscsiAuthStatusFail);
- }
-
- iscsiAuthMd5Init(&context);
-
- /*
- * id byte
- */
- verifyData[0] = id;
- iscsiAuthMd5Update(&context, verifyData, 1);
-
- /*
- * shared secret
- */
- iscsiAuthMd5Update(&context,
- (uchar_t *)isp->sess_auth.password_in,
- isp->sess_auth.password_length_in);
-
- /*
- * challenge value
- */
- iscsiAuthMd5Update(&context,
- (uchar_t *)challengeData,
- challengeLength);
-
- iscsiAuthMd5Final(verifyData, &context);
-
- if (bcmp(responseData, verifyData,
- sizeof (verifyData)) == 0) {
- return (iscsiAuthStatusPass);
- }
-
- (void) snprintf(debug, sizeof (debug),
- "SES%x iscsi session(%u) failed authentication, "
- "received incorrect CHAP response from initiator",
- isp->s_num);
- queue_str(isp->s_mgmtq, Q_SESS_ERRS, msg_log, debug);
- }
- return (iscsiAuthStatusFail);
-}
-
-int
-iscsiAuthClientTextToNumber(const char *text, unsigned long *pNumber)
-{
- char *pEnd;
- unsigned long number;
-
- number = strtoul(text, &pEnd, 0);
- if (*text != '\0' && *pEnd == '\0') {
- *pNumber = number;
- return (0); /* No error */
- } else {
- return (1); /* Error */
- }
-}
-
-/* ARGSUSED */
-void
-iscsiAuthClientNumberToText(unsigned long number, char *text,
- unsigned int length)
-{
- (void) snprintf(text, length, "%lu", number);
-}
-
-
-void
-iscsiAuthRandomSetData(uchar_t *data, unsigned int length)
-{
- int fd;
- fd = open("/dev/random", O_RDONLY);
- if (fd == -1)
- return;
- (void) read(fd, data, length);
- (void) close(fd);
-}
-
-
-void
-iscsiAuthMd5Init(IscsiAuthMd5Context * context)
-{
- MD5Init(context);
-}
-
-
-void
-iscsiAuthMd5Update(IscsiAuthMd5Context *context, uchar_t *data,
- unsigned int length)
-{
- MD5Update(context, data, length);
-}
-
-
-void
-iscsiAuthMd5Final(uchar_t *hash, IscsiAuthMd5Context *context)
-{
- MD5Final(hash, context);
-}
-
-
-int
-iscsiAuthClientData(uchar_t *outData, unsigned int *outLength,
- uchar_t *inData, unsigned int inLength)
-{
- if (*outLength < inLength) {
- return (1); /* error */
- }
- bcopy(inData, outData, inLength);
- *outLength = inLength;
- return (0); /* no error */
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/iscsi_cmd.c b/usr/src/cmd/iscsi/iscsitgtd/iscsi_cmd.c
deleted file mode 100644
index a02d131be8..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_cmd.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <stdio.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <syslog.h>
-#include <synch.h>
-#include <sys/time.h>
-#include <sys/asynch.h>
-#include <umem.h>
-#include <strings.h>
-
-#include "iscsi_conn.h"
-#include "iscsi_cmd.h"
-#include "target.h"
-#include "utility.h"
-
-static pthread_mutex_t cmd_mutex;
-static int cmd_ttt;
-
-/*
- * []----
- * | iscsi_cmd_init -- called at the beginning of time to initialize locks
- * []----
- */
-void
-iscsi_cmd_init()
-{
- (void) pthread_mutex_init(&cmd_mutex, NULL);
- cmd_ttt = 0;
-}
-
-/*
- * []----
- * | iscsi_cmd_alloc -- allocate space for new command
- * []----
- */
-iscsi_cmd_t *
-iscsi_cmd_alloc(iscsi_conn_t *c, int op)
-{
- iscsi_cmd_t *cmd = umem_cache_alloc(iscsi_cmd_cache, UMEM_DEFAULT);
-
- if (cmd == NULL) {
- queue_prt(mgmtq, Q_CONN_ERRS, "Failed to get command buf\n");
- return (NULL);
- }
-
- bzero(cmd, sizeof (*cmd));
- (void) pthread_mutex_lock(&cmd_mutex);
- cmd->c_ttt = cmd_ttt++;
- (void) pthread_mutex_unlock(&cmd_mutex);
-
- (void) pthread_mutex_lock(&c->c_mutex);
- cmd->c_opcode = op;
- cmd->c_statsn = c->c_statsn;
- cmd->c_state = CmdAlloc;
- if (c->c_cmd_head == NULL) {
- c->c_cmd_head = cmd;
- assert(c->c_cmd_tail == NULL);
- c->c_cmd_tail = cmd;
- } else {
- c->c_cmd_tail->c_next = cmd;
- cmd->c_prev = c->c_cmd_tail;
- c->c_cmd_tail = cmd;
- }
- cmd->c_allegiance = c;
- cmd->c_t_start = gethrtime();
- c->c_cmds_active++;
- (void) pthread_mutex_unlock(&c->c_mutex);
-
- return (cmd);
-}
-
-/*
- * []----
- * | iscsi_cmd_find -- search for a specific command and return it
- * |
- * | XXX Need to switch to use an AVL tree.
- * []----
- */
-iscsi_cmd_t *
-iscsi_cmd_find(iscsi_conn_t *c, uint32_t val, find_type_t type)
-{
- iscsi_cmd_t *cmd = NULL;
-
- (void) pthread_mutex_lock(&c->c_mutex);
- for (cmd = c->c_cmd_head; cmd; cmd = cmd->c_next) {
-
- /*
- * Depending on type determine correct matching value.
- * Only return a hit if the command hasn't already been
- * freed.
- */
- if ((((type == FindTTT) && (cmd->c_ttt == val)) ||
- ((type == FindITT) && (cmd->c_itt == val))) &&
- (cmd->c_state != CmdFree))
- break;
- }
- (void) pthread_mutex_unlock(&c->c_mutex);
-
- return (cmd);
-}
-
-/*
- * []----
- * | iscsi_cmd_free -- mark a command as freed.
- * []----
- */
-void
-iscsi_cmd_free(iscsi_conn_t *c, iscsi_cmd_t *cmd)
-{
- hrtime_t h = gethrtime();
-
- assert(cmd->c_state != CmdFree);
- cmd->c_state = CmdFree;
- cmd->c_t_completion = h - cmd->c_t_start;
- c->c_cmds_avg_sum += cmd->c_t_completion;
- c->c_cmds_avg_cnt++;
- /* decrement active count here */
- c->c_cmds_active--;
-}
-
-/*
- * Find all duplicated t10_cmd and shoot an event
- */
-void
-iscsi_cancel_dups(iscsi_cmd_t *cmd, t10_cmd_event_t e)
-{
- t10_cmd_t *c2free;
- t10_cmd_t *nc;
-
- /* Run the list */
- c2free = cmd->c_t10_cmd;
- while (c2free != NULL) {
- nc = c2free->c_cmd_next;
- t10_cmd_shoot_event(c2free, e);
- c2free = nc;
- }
-}
-
-/*
- * []----
- * | iscsi_cmd_cancel -- mark a command as canceled
- * |
- * | We don't actually stop commands in flight. We only prevent the canceled
- * | commands from returning status and/or data to the initiator. At the
- * | connection layer if a command is canceled nothing will be sent on the
- * | wire and at that point the command is marked CmdFree so that future calls
- * | to cmd_remove will actually free the space.
- * |
- * | NOTE: connection mutex must be held during this call.
- * []----
- */
-void
-iscsi_cmd_cancel(iscsi_conn_t *c, iscsi_cmd_t *cmd)
-{
- assert(pthread_mutex_trylock(&c->c_mutex) != 0);
- if (cmd->c_state == CmdAlloc) {
- cmd->c_state = CmdCanceled;
- if (cmd->c_t10_cmd != NULL) {
- if (cmd->c_t10_dup)
- iscsi_cancel_dups(cmd, T10_Cmd_T6);
- else
- t10_cmd_shoot_event(cmd->c_t10_cmd, T10_Cmd_T6);
- }
- }
-}
-
-/*
- * []----
- * | iscsi_cmd_remove -- actually free space allocated to commands
- * |
- * | According to the iSCSI specification the target must kept resources
- * | around until the initiator sends a command with a status serial
- * | number higher than the held resource. This is so that an initiator
- * | can request data again if needed. During the processing of each new
- * | command this routine is called to free old commands.
- * []----
- */
-void
-iscsi_cmd_remove(iscsi_conn_t *c, uint32_t statsn)
-{
- iscsi_cmd_t *cmd, *n;
- iscsi_cmd_t *cmd_free = NULL;
-
- (void) pthread_mutex_lock(&c->c_mutex);
- for (cmd = c->c_cmd_head; cmd; ) {
- /*
- * If the StatusSN for this command is less than the incoming
- * StatusSN and the command has been freed remove it from
- * list. Don't bother with commands that are in the state of
- * CmdCanceled. Once the I/O has been completed the command
- * is passed back to the connection handler where the state
- * will be noticed and then the command will be freed. At that
- * point the next incoming command with a valid expected
- * status serial number will free the memory.
- */
- if (sna_lt(cmd->c_statsn, statsn)) {
- if (cmd->c_state == CmdFree) {
- if (c->c_cmd_head == cmd) {
- c->c_cmd_head = cmd->c_next;
- if (c->c_cmd_head == NULL)
- c->c_cmd_tail = NULL;
- } else {
- n = cmd->c_prev;
- n->c_next = cmd->c_next;
- if (cmd->c_next != NULL)
- cmd->c_next->c_prev = n;
- else {
- assert(c->c_cmd_tail == cmd);
- c->c_cmd_tail = n;
- }
- }
-
- /*
- * Place on local command free list, to free
- * once mutex is released
- */
- n = cmd->c_next;
- cmd->c_next = cmd_free;
- cmd_free = cmd;
- cmd = n;
- } else {
- cmd = cmd->c_next;
- }
- } else {
- break;
- }
- }
- (void) pthread_mutex_unlock(&c->c_mutex);
-
- /*
- * Deallocate command free list
- */
- cmd = cmd_free;
- while (cmd != NULL) {
- n = cmd->c_next;
- if (cmd->c_scb_extended)
- free(cmd->c_scb_extended);
- if (cmd->c_data_alloc == True) {
- free(cmd->c_data);
- cmd->c_data = NULL;
- }
- umem_cache_free(iscsi_cmd_cache, cmd);
- cmd = n;
- }
-}
-
-/*
- * []----
- * | iscsi_cmd_window -- return the number of available commands
- * |
- * | There are currently 7 different places where this routine is called.
- * | In some cases and command is allocated which will be freed shortly and
- * | in others no command is held. This is why the number of commands found
- * | will be decremented if larger than 0. Since the daemon doesn't have
- * | any hard limits on the number of commands being supported this is more
- * | arbitrary and the command window size is used for debugging other
- * | initiators.
- * |
- * | NOTE: connection mutex must be held during this call.
- * []----
- */
-int
-iscsi_cmd_window(iscsi_conn_t *c)
-{
- int cnt;
-
- assert(pthread_mutex_trylock(&c->c_mutex) != 0);
- if (c->c_cmds_avg_cnt == 0) {
-
- /*
- * If there are no outstanding commands clear the averages
- * so that the initiator can start again.
- */
- c->c_cmds_avg_sum = 0;
- c->c_cmds_avg_cnt = 0;
- cnt = c->c_maxcmdsn - c->c_cmds_active;
-
- } else if ((c->c_cmds_avg_sum / c->c_cmds_avg_cnt) >= NANOSEC) {
-
- /*
- * It would appear things are taking a real long time to
- * complete on our end. Close down the command window to
- * prevent the initiator from timing out commands.
- */
- cnt = (c->c_cmds_active >= c->c_maxcmdsn) ? 0 :
- (c->c_maxcmdsn - c->c_cmds_active) / 2;
-
- } else {
- cnt = (c->c_cmds_active >= c->c_maxcmdsn) ? 0 :
- c->c_maxcmdsn - c->c_cmds_active;
- }
-
- return (cnt);
-}
-
-void
-iscsi_cmd_delayed_store(iscsi_cmd_t *cmd, t10_cmd_t *t)
-{
- iscsi_delayed_t *d, *n;
- iscsi_delayed_t *l = NULL;
-
- if ((d = (iscsi_delayed_t *)calloc(1, sizeof (*d))) == NULL) {
- syslog(LOG_ERR, "Failed to allocate space for delayed I/O");
- queue_prt(cmd->c_allegiance->c_mgmtq, Q_CONN_ERRS,
- "CON%x Failed calloc for delayed I/O",
- cmd->c_allegiance->c_num);
- t10_cmd_shoot_event(t, T10_Cmd_T5);
- return;
- }
-
- d->id_offset = T10_DATA_OFFSET(t);
- d->id_t10_cmd = t;
-
- for (n = cmd->c_t10_delayed; n; n = n->id_next) {
- l = n;
- if (d->id_offset < n->id_offset) {
- if (n->id_prev == NULL) {
- d->id_next = n;
- n->id_prev = d;
- cmd->c_t10_delayed = d;
- } else {
- d->id_prev = n->id_prev;
- d->id_prev->id_next = d;
- n->id_prev = d;
- d->id_next = n;
- }
- return;
- }
- }
-
- if (l == NULL) {
- cmd->c_t10_delayed = d;
- } else {
- l->id_next = d;
- d->id_prev = l;
- }
-}
-
-void
-iscsi_cmd_delayed_remove(iscsi_cmd_t *cmd, iscsi_delayed_t *d)
-{
- if (cmd->c_t10_delayed == d) {
- cmd->c_t10_delayed = d->id_next;
- if (d->id_next)
- d->id_next->id_prev = NULL;
- } else {
- d->id_prev->id_next = d->id_next;
- if (d->id_next != NULL)
- d->id_next->id_prev = d->id_prev;
- }
- free(d);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/iscsi_cmd.h b/usr/src/cmd/iscsi/iscsitgtd/iscsi_cmd.h
deleted file mode 100644
index 86e09e738a..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_cmd.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _TARGET_CMD_H
-#define _TARGET_CMD_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Block comment which describes the contents of this file.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <sys/types.h>
-#include <sys/avl.h>
-#include <aio.h>
-
-#include <iscsitgt_impl.h>
-#include "t10.h"
-
-#define CMD_MAXOUTSTANDING 16
-
-typedef enum {
- FindTTT,
- FindITT
-} find_type_t;
-
-typedef enum {
- CmdAlloc,
- CmdCanceled,
- CmdFree
-} cmd_state_t;
-
-typedef struct iscsi_delayed {
- struct iscsi_delayed *id_prev,
- *id_next;
- t10_cmd_t *id_t10_cmd;
- size_t id_offset;
-} iscsi_delayed_t;
-
-typedef struct iscsi_cmd {
- struct iscsi_cmd *c_next;
- struct iscsi_cmd *c_prev;
-
- /*
- * Always kept in network byte order since we only
- * store this field
- */
- uint32_t c_itt;
-
- uint32_t c_opcode;
- uint32_t c_ttt;
- uint32_t c_cmdsn;
- uint32_t c_datasn;
- uint32_t c_statsn;
- uint32_t c_dlen_expected;
-
- Boolean_t c_writeop;
- uint32_t c_lun;
-
- /*
- * Default storage for SCB which is the most common size to day.
- */
- uint8_t c_scb_default[16];
-
- /*
- * If the CDB is larger than 16 bytes an Alternate Header Segment
- * is used and memory allocated which is pointed to by the following
- */
- uint8_t *c_scb_extended;
-
- /*
- * Points at the appropriate memory area for the SCB
- */
- uint8_t *c_scb;
- uint32_t c_scb_len;
-
- cmd_state_t c_state;
- uint32_t c_status;
-
- /*
- * When ImmediateData==Yes it'll be read in to a buffer
- * allocated by the connection. This will be free'd when the
- * callback is done which means the SAM-3 layer is finished with
- * the data.
- */
- char *c_data;
- size_t c_data_len;
- off_t c_offset_out;
-
- /*
- * Arrange for the PDUs to always be sent in order. If DataPDUInOrder
- * is True this is a *must* according to the specification. There's
- * also a need that the final flag bit not be sent unless all other
- * packets have been, regardless of order. Without keeping a complicated
- * bitmap of which packets have been sent for this second case we
- * just order things always.
- */
- off_t c_offset_in;
- iscsi_delayed_t *c_t10_delayed;
-
- Boolean_t c_data_alloc;
-
- void (*c_dataout_cb)(t10_cmd_t *cmd, char *data,
- size_t *xfer);
-
- /*
- * Used to hold the interface pointer when we've got an R2T
- * for this command. This is needed because memory is allocated
- * normally by the emulation layer and we can copy directly to that
- * instead of allocating our own buffer.
- */
- t10_cmd_t *c_t10_cmd;
- uint32_t c_t10_dup;
-
- /*
- * Used by the session layer to send packets out the same
- * connection.
- */
- struct iscsi_conn *c_allegiance;
-
- hrtime_t c_t_start,
- c_t_completion;
-
-} iscsi_cmd_t;
-
-
-void iscsi_cmd_init();
-iscsi_cmd_t *iscsi_cmd_alloc(struct iscsi_conn *c, int opcode);
-iscsi_cmd_t *iscsi_cmd_find(struct iscsi_conn *c, uint32_t x,
- find_type_t type);
-void iscsi_cmd_free(struct iscsi_conn *c, iscsi_cmd_t *cmd);
-void iscsi_cmd_cancel(struct iscsi_conn *c, iscsi_cmd_t *cmd);
-void iscsi_cmd_remove(struct iscsi_conn *c, uint32_t statsn);
-int iscsi_cmd_window(struct iscsi_conn *c);
-void iscsi_cmd_delayed_store(iscsi_cmd_t *cmd, t10_cmd_t *t);
-void iscsi_cmd_delayed_remove(iscsi_cmd_t *cmd, iscsi_delayed_t *d);
-void iscsi_cancel_dups(iscsi_cmd_t *, t10_cmd_event_t);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _TARGET_CMD_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/iscsi_conn.c b/usr/src/cmd/iscsi/iscsitgtd/iscsi_conn.c
deleted file mode 100644
index 53d24613dd..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_conn.c
+++ /dev/null
@@ -1,1591 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <signal.h>
-#include <pthread.h>
-#include <assert.h>
-#include <sys/select.h>
-#include <stdlib.h>
-#include <poll.h>
-#include <strings.h>
-#include <sys/filio.h>
-#include <errno.h>
-#include <utility.h>
-#include <unistd.h>
-#include <sys/stropts.h>
-#include <syslog.h>
-#include <sys/iscsi_protocol.h>
-
-#include <iscsitgt_impl.h>
-#include "iscsi_conn.h"
-#include "iscsi_sess.h"
-#include "iscsi_login.h"
-#include "iscsi_ffp.h"
-#include "iscsi_provider_impl.h"
-#include "utility.h"
-#include "target.h"
-#include "port.h"
-#include "t10.h"
-
-/*
- * defined here so that pad_text is initialized to zero's. It's
- * never modified.
- */
-static const char pad_text[ISCSI_PAD_WORD_LEN] = { 0 };
-
-static void iscsi_conn_data_rqst(t10_cmd_t *cmd);
-static void iscsi_conn_cmdcmplt(t10_cmd_t *cmd);
-static void iscsi_conn_data_in(t10_cmd_t *);
-static void iscsi_conn_pkt(iscsi_conn_t *c, iscsi_rsp_hdr_t *in);
-
-static void send_datain_pdu(iscsi_conn_t *c, t10_cmd_t *cmd,
- uint8_t final_flag);
-static void send_scsi_rsp(iscsi_conn_t *c, t10_cmd_t *cmd);
-static void queue_noop_in(iscsi_conn_t *c);
-static char *state_to_str(iscsi_state_t s);
-static void send_async_logout(iscsi_conn_t *c);
-static void send_async_scsi(iscsi_conn_t *c, int key, int asc, int ascq);
-
-void *
-conn_poller(void *v)
-{
- iscsi_conn_t *c = (iscsi_conn_t *)v;
- int nbytes;
- int pval;
- nfds_t nfds = 1;
- struct pollfd fds[1];
- iscsi_state_t state;
- target_queue_t *mgmtq = c->c_mgmtq;
- Boolean_t one_time_noop = False;
-
- fds[0].fd = c->c_fd;
- fds[0].events = POLLIN;
-
- util_title(c->c_mgmtq, Q_CONN_LOGIN, c->c_num, "Start Poller");
- while ((pval = poll(fds, nfds, 30 * 1000)) >= 0) {
-
- /*
- * The true asynchronous events are when we're in S5_LOGGED_IN
- * state. In the iscsi_full_feature() code the state is
- * locked and checked before sending any messages along. The
- * mutex is grabbed here only to prevent a collision between
- * some thread setting the state and our reading of the value.
- * There's no harm in us grabbing the state which might
- * change right after we unlock the mutex.
- */
- (void) pthread_mutex_lock(&c->c_state_mutex);
- state = c->c_state;
- (void) pthread_mutex_unlock(&c->c_state_mutex);
-
- switch (state) {
- case S1_FREE:
- /*
- * If we moved to the free state. The session
- * was sent a message to shutdown. Once it
- * completes it will reply with a shutdown
- * response which will close the main
- * connection thread. So, this thread just
- * returns a stop processing incoming packets.
- */
- goto error;
-
- case S3_XPT_UP:
- if (ioctl(c->c_fd, FIONREAD, &nbytes) < 0) {
- queue_message_set(c->c_dataq, 0, msg_shutdown,
- 0);
- goto error;
- }
-
- /*
- * To be fully compliant the code should use
- * ioctl(fd, I_PEEK, (struct strpeek v)); and
- * look to see if the header is indeed a login
- * packet. If not, just close the connection.
- */
- if (nbytes < sizeof (iscsi_login_hdr_t)) {
- queue_message_set(c->c_dataq, 0,
- msg_shutdown, 0);
- goto error;
- } else {
- /*
- * Change the state to S4_IN_LOGIN.
- * Since we haven't touched the data
- * waiting on the stream when the
- * sema_post() occurs below the poller
- * will find data again and send
- * another packet ready message at
- * which point we deal with the
- * login.
- */
- conn_state(c, T4);
- }
- break;
-
- case S4_IN_LOGIN:
- if (iscsi_handle_login_pkt(c) == False)
- goto error;
- break;
-
- case S7_LOGOUT_REQUESTED:
- case S5_LOGGED_IN:
- if (fds[0].revents & POLLIN) {
-
- if (iscsi_full_feature(c) == False)
- goto error;
-
- } else {
- /*
- * Being S5_LOGGED_IN, and POLLIN not set,
- * means the that the poll(,,timer) went off.
- * If the session is normal, then queue a single
- * NOOP request, but only once per connection.
- */
- if (c->c_sess->s_type == SessionNormal) {
- if (one_time_noop == False) {
- queue_noop_in(c);
- one_time_noop = True;
- }
- }
- }
- break;
-
- case S6_IN_LOGOUT:
- goto error;
-
- case S8_CLEANUP_WAIT:
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "Haven't handled state S8\n");
- queue_message_set(c->c_dataq, 0,
- msg_shutdown_rsp, 0);
- goto error;
- }
-
- }
-
-error:
- /*
- * Only when we're logged in would we have an active session
- * which needs to be shut down. In the case of S4_IN_LOGIN we could
- * transition to either S1_FREE in which case a shutdown message
- * was sent to the session which in turn will reply with a shutdown
- * response causing the conn_process to exit.
- */
- if (c->c_state == S5_LOGGED_IN)
- conn_state(c, T8);
-
- /*
- * If a msg_conn_lost was already sent it's invalid to reference
- * the management queue from the connection structure at this point.
- */
- util_title(mgmtq, Q_CONN_LOGIN, c->c_num, "End Poller");
-
- if (pval == -1)
- queue_message_set(c->c_dataq, 0, msg_conn_lost, 0);
- return (NULL);
-}
-
-/*
- * conn_process -- thread which runs a connection
- */
-void *
-conn_process(void *v)
-{
- iscsi_conn_t *c = (iscsi_conn_t *)v;
- iscsi_cmd_t *cmd;
- Boolean_t process = True;
- Boolean_t is_last = False;
- msg_t *m;
- void *thr_status;
- int i;
- mgmt_request_t *mgmt;
- char debug[80];
- time_t tval = time((time_t *)0);
- Boolean_t drop_t10_cmds = False;
-
- c->c_dataq = queue_alloc();
- c->c_maxcmdsn = CMD_MAXOUTSTANDING;
-
- if (sema_init(&c->c_datain, 0, USYNC_THREAD, NULL) != 0) {
- port_conn_remove(c);
- free(c);
- return (NULL);
- }
-
- util_title(c->c_mgmtq, Q_CONN_LOGIN, c->c_num, "Start Receiver");
- util_title(c->c_mgmtq, Q_CONN_LOGIN, c->c_num,
- ctime_r(&tval, debug, sizeof (debug)));
-
- c->c_thr_id_process = pthread_self();
-
- assert(c->c_state == S1_FREE);
- conn_state(c, T3);
-
- (void) pthread_create(&c->c_thr_id_poller, NULL,
- conn_poller, (void *)c);
-
- do {
- m = queue_message_get(c->c_dataq);
- switch (m->msg_type) {
- case msg_mgmt_rqst:
- mgmt = (mgmt_request_t *)m->msg_data;
- if (c->c_state == S5_LOGGED_IN) {
- if (mgmt->m_request == mgmt_logout) {
- conn_state(c, T11);
- queue_message_set(mgmt->m_q, 0,
- msg_mgmt_rply, 0);
- } else {
- queue_message_set(c->c_sessq, 0,
- msg_mgmt_rqst, m->msg_data);
- }
- } else {
- /*
- * Corner case which can occur when the
- * connection has just started and is in the
- * process of logging in and we get a
- * mangement request. There's no session
- * information or even a queue setup. Just
- * show an empty connection.
- *
- * For the mgmt_logout, it's possible that
- * we sent the T11 state change causing the
- * connection to enter the S7 state. If we
- * get a logout request again the specification
- * says to just drop the connection.
- */
- if (mgmt->m_request == mgmt_logout)
- conn_state(c, T18);
- else {
- (void) pthread_mutex_lock(
- &mgmt->m_resp_mutex);
- tgt_buf_add(mgmt->m_u.m_resp,
- "connection", NULL);
- (void) pthread_mutex_unlock(
- &mgmt->m_resp_mutex);
- }
- queue_message_set(mgmt->m_q, 0,
- msg_mgmt_rply, 0);
- }
- m->msg_data = NULL;
- break;
-
- case msg_conn_lost:
- queue_prt(c->c_mgmtq, Q_CONN_LOGIN,
- "CON%x Shutdown: connection\n", c->c_num);
-
- if (c->c_state == S5_LOGGED_IN)
- conn_state(c, T8);
- break;
-
- case msg_shutdown_rsp:
- if (c->c_state == S6_IN_LOGOUT)
- conn_state(c, T13);
- (void) pthread_join(c->c_thr_id_poller, &thr_status);
- is_last = (Boolean_t)m->msg_data;
- m->msg_data = NULL;
- process = False;
- break;
-
- case msg_shutdown:
- if (c->c_state == S5_LOGGED_IN) {
- conn_state(c, T8);
- } else if (c->c_state == S4_IN_LOGIN) {
- conn_state(c, T7);
- } else {
- (void) pthread_join(c->c_thr_id_poller,
- &thr_status);
- process = False;
- }
- break;
-
- case msg_targ_inventory_change:
- if (c->c_state == S5_LOGGED_IN) {
- send_async_scsi(c, KEY_UNIT_ATTENTION, 0x3f,
- 0x0e);
- }
- break;
-
- case msg_send_pkt:
- iscsi_conn_pkt(c, (iscsi_rsp_hdr_t *)m->msg_data);
- break;
-
- case msg_cmd_data_rqst:
- /*
- * The STE needs more data to complete
- * the write command.
- */
- if (!drop_t10_cmds) {
- iscsi_conn_data_rqst((t10_cmd_t *)m->msg_data);
- }
- break;
-
- case msg_cmd_data_in:
- /*
- * Data is available to satisfy the READ command
- */
- if (!drop_t10_cmds) {
- iscsi_conn_data_in((t10_cmd_t *)m->msg_data);
- }
- break;
-
- case msg_cmd_cmplt:
- /*
- * Status is available for a previous STEOut.
- * The status may be good and the previous STEOut data
- * wasn't sent so we phase collapse.
- */
- if (!drop_t10_cmds) {
- iscsi_conn_cmdcmplt((t10_cmd_t *)m->msg_data);
- }
- break;
-
- case msg_wait_for_destroy: {
- t10_conn_shutdown_t *t_c_s;
-
- /*
- * Handshake through private queues with
- * message sender. Acknowledge receipt of
- * the msg which indicates the start of t10
- * cmd destroy, wait for a reply indicating
- * the completion of cmd destroy handling,
- * ack that, then drop any subsequent t10 cmd
- * messages as they've already been canceled
- * and freed.
- */
- t_c_s = (t10_conn_shutdown_t *)m->msg_data;
- queue_message_set(t_c_s->conn_to_t10_q, 0, 1,
- (void *)NULL);
- queue_message_free(queue_message_get(
- t_c_s->t10_to_conn_q));
- queue_message_set(t_c_s->conn_to_t10_q, 0, 1,
- (void *)NULL);
- drop_t10_cmds = True;
- break;
- }
-
- default:
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "CON%x Didn't handle msg_type %d\n", c->c_num,
- m->msg_type);
- break;
- }
-
- queue_message_free(m);
- } while (process == True);
-
- /*
- * Free any resources used.
- */
- if (c->c_text_area)
- free(c->c_text_area);
- if (c->c_fd != -1)
- (void) close(c->c_fd);
-
- /*
- * It's possible, but very unlikely that c_sessq is NULL at this
- * point. I saw one case where the system had problems causing the
- * poller routine to exit real early so that the session was never
- * setup causing the daemon to get a SEGV in queue_free when a NULL
- * was passed in.
- */
- if ((is_last == True) && (c->c_sessq != NULL))
- queue_free(c->c_sessq, sess_queue_data_remove);
-
- /*
- * See if there are any commands outstanding and free them.
- * NOTE: Should walk through the data_ptr list and find data structure
- * who have alligence to this connection and free them as well.
- */
- (void) pthread_mutex_lock(&c->c_mutex);
- (void) pthread_mutex_lock(&c->c_state_mutex);
-
- for (i = 0, cmd = c->c_cmd_head; cmd; i++)
- cmd = cmd->c_next; /* debug count of lost ttt's */
-
- (void) snprintf(debug, sizeof (debug), "CON%x %d Lost TTTs: ",
- c->c_num, i);
-
- for (i = 0, cmd = c->c_cmd_head; cmd; i++) {
- iscsi_cmd_t *n = cmd->c_next;
- if (cmd->c_state != CmdCanceled) {
- (void) snprintf(debug + strlen(debug),
- sizeof (debug) - strlen(debug),
- "0x%x ", cmd->c_ttt);
- }
-
- /*
- * Make sure to free the resources that the T10
- * layer still has allocated. These are commands which
- * the T10 layer couldn't release directly during it's
- * shutdown.
- */
- if (cmd->c_t10_cmd) {
- if (cmd->c_t10_dup) {
- iscsi_cancel_dups(cmd, T10_Cmd_T8);
- } else {
- t10_cmd_shoot_event(cmd->c_t10_cmd, T10_Cmd_T8);
- }
- }
-
- /*
- * Perform the final clean up which is done during
- * cmd_remove().
- */
- if (cmd->c_scb_extended)
- free(cmd->c_scb_extended);
- if (cmd->c_data_alloc == True)
- free(cmd->c_data);
-
- umem_cache_free(iscsi_cmd_cache, cmd);
- cmd = n;
- }
- (void) pthread_mutex_unlock(&c->c_state_mutex);
- (void) pthread_mutex_unlock(&c->c_mutex);
-
- if (i) {
- /*
- * If there where lost commands found send a message indicating
- * which ones. This message is purely for information
- * and is not indicative of an error.
- */
- queue_prt(c->c_mgmtq, Q_CONN_LOGIN, debug);
- }
-
- if (c->c_cmds_avg_cnt != 0)
- queue_prt(c->c_mgmtq, Q_CONN_LOGIN,
- "CON%x Average completion %lldms\n", c->c_num,
- (c->c_cmds_avg_sum / c->c_cmds_avg_cnt) / (1000 * 1000));
-
- (void) sema_destroy(&c->c_datain);
- if (c->c_targ_alias)
- free(c->c_targ_alias);
-
- util_title(c->c_mgmtq, Q_CONN_LOGIN, c->c_num, "End Receiver");
-
- queue_message_set(c->c_mgmtq, 0, msg_pthread_join,
- (void *)(uintptr_t)pthread_self());
- /*
- * Remove this connection from linked list of current connections.
- * This will also free the connection queue. Must not hold the
- * q here because port_conn_remove-->queue_free->conn_queue_data
- * will possible grab the mutex.
- */
- port_conn_remove(c);
- free(c);
- return (NULL);
-}
-
-/*
- * []----
- * | iscsi_conn_pkt -- send out PDU from receive thread
- * |
- * | (1) This PDU could be either:
- * | (a) A NOP request was sent from the initiator which the recieve
- * | side processed and is requesting to be sent back.
- * | (b) Nothing has been received in N seconds and we're looking
- * | to see if the connection is still alive.
- * | (c) A task management request was processed by the receive side
- * | and the response must be sent.
- * | (2) Fields to be filled in
- * | Need to delay filling in several of the fields until
- * | now to avoid using sequence number which would be out of
- * | order.
- * []----
- */
-static void
-iscsi_conn_pkt(iscsi_conn_t *c, iscsi_rsp_hdr_t *in)
-{
- if (c->c_state != S5_LOGGED_IN) {
- free(in);
- return;
- }
-
- (void) pthread_mutex_lock(&c->c_mutex);
- /*
- * Make any final per command adjustments.
- */
- switch (in->opcode & ISCSI_OPCODE_MASK) {
- case ISCSI_OP_NOOP_IN:
- in->statsn = htonl(c->c_statsn);
- /*
- * RFC 3720 section 10.19. specifies:
- * - ITT is different from 0xffffffff in NOP-In when responding
- * to incomming NOP-Out; and set to 0xffffffff otherwise
- * - StatSN is not advanced for ITT set to 0xffffffff
- */
- if (((iscsi_nop_in_hdr_t *)in)->itt != ISCSI_RSVD_TASK_TAG)
- c->c_statsn++;
- break;
- }
- (void) pthread_mutex_lock(&c->c_sess->s_mutex);
- in->expcmdsn = htonl(c->c_sess->s_seencmdsn + 1);
- in->maxcmdsn = htonl(iscsi_cmd_window(c) + c->c_sess->s_seencmdsn);
-
- if (ISCSI_NOP_SEND_ENABLED() || ISCSI_TASK_RESPONSE_ENABLED()) {
- uiscsiproto_t info;
-
- info.uip_target_addr = &c->c_target_sockaddr;
- info.uip_initiator_addr = &c->c_initiator_sockaddr;
-
- info.uip_target = c->c_sess->s_t_name;
- info.uip_initiator = c->c_sess->s_i_name;
- info.uip_lun = 0;
-
- info.uip_itt = in->itt;
- info.uip_ttt = ISCSI_RSVD_TASK_TAG;
-
- info.uip_cmdsn = ntohl(in->expcmdsn);
- info.uip_statsn = ntohl(in->statsn);
- info.uip_datasn = 0;
-
- info.uip_datalen = ntoh24(in->dlength);
- info.uip_flags = in->flags;
-
- switch (in->opcode & ISCSI_OPCODE_MASK) {
- case ISCSI_OP_NOOP_IN:
- ISCSI_NOP_SEND(&info);
- break;
- case ISCSI_OP_SCSI_TASK_MGT_RSP:
- ISCSI_TASK_RESPONSE(&info);
- break;
- default:
- assert(0);
- }
- }
-
- (void) pthread_mutex_unlock(&c->c_sess->s_mutex);
- (void) pthread_mutex_unlock(&c->c_mutex);
-
- send_iscsi_pkt(c, (iscsi_hdr_t *)in, 0);
- free(in);
-}
-
-/*
- * []----
- * | iscsi_conn_data_rqst -- request that data be sent from the initiator
- * []----
- */
-static void
-iscsi_conn_data_rqst(t10_cmd_t *t)
-{
- iscsi_cmd_t *cmd = T10_TRANS_ID(t);
- iscsi_conn_t *c;
- iscsi_rtt_hdr_t rtt;
-
- bzero(&rtt, sizeof (rtt));
-
- c = cmd->c_allegiance;
- (void) pthread_mutex_lock(&c->c_mutex);
- (void) pthread_mutex_lock(&c->c_state_mutex);
- if ((c->c_state != S5_LOGGED_IN) ||
- (cmd->c_state == CmdCanceled)) {
- t10_cmd_shoot_event(t, T10_Cmd_T5);
- (void) pthread_mutex_unlock(&c->c_state_mutex);
- (void) pthread_mutex_unlock(&c->c_mutex);
- return;
- }
- (void) pthread_mutex_unlock(&c->c_state_mutex);
-
- /*
- * Save the data pointer from the emulation code. It's their
- * responsibility to allocate space for the data which the
- * initiator will return. When we receive a DATAOUT packet
- * we'll copy data from the socket directly to this buffer.
- */
- cmd->c_data = T10_DATA(t);
-
- /*
- * RFC3270.10.8.3
- * The statsn field will contain the next statsn. The statsn for this
- * connection is not advanced after this PDU is sent.
- */
- rtt.statsn = htonl(c->c_statsn);
-
- rtt.opcode = ISCSI_OP_RTT_RSP;
- rtt.flags = ISCSI_FLAG_FINAL;
- rtt.itt = cmd->c_itt;
- rtt.ttt = cmd->c_ttt;
- rtt.data_offset = htonl(T10_DATA_OFFSET(t));
- rtt.data_length = htonl(MIN(T10_DATA_LEN(t), c->c_max_burst_len));
- rtt.rttsn = htonl(cmd->c_datasn++);
-
- (void) pthread_mutex_lock(&c->c_sess->s_mutex);
- rtt.maxcmdsn = htonl(iscsi_cmd_window(c) + c->c_sess->s_seencmdsn);
- rtt.expcmdsn = htonl(c->c_sess->s_seencmdsn + 1);
- (void) pthread_mutex_unlock(&c->c_sess->s_mutex);
-
-#ifdef FULL_DEBUG
- queue_prt(c->c_mgmtq, Q_CONN_IO,
- "CON%x R2T TTT 0x%x offset 0x%x, len 0x%x\n",
- c->c_num, cmd->c_ttt, T10_DATA_OFFSET(t), T10_DATA_LEN(t));
-#endif
-
- t10_cmd_shoot_event(t, T10_Cmd_T7);
- (void) pthread_mutex_unlock(&c->c_mutex);
-
- if (ISCSI_DATA_REQUEST_ENABLED()) {
- uiscsiproto_t info;
-
- info.uip_target_addr = &c->c_target_sockaddr;
- info.uip_initiator_addr = &c->c_initiator_sockaddr;
-
- info.uip_target = c->c_sess->s_t_name;
- info.uip_initiator = c->c_sess->s_i_name;
- info.uip_lun = cmd->c_lun;
-
- info.uip_itt = rtt.itt;
- info.uip_ttt = rtt.ttt;
-
- info.uip_cmdsn = ntohl(rtt.expcmdsn);
- info.uip_statsn = c->c_statsn;
- info.uip_datasn = 0;
-
- info.uip_datalen = 0;
- info.uip_flags = rtt.flags;
-
- ISCSI_DATA_REQUEST(&info);
- }
-
- send_iscsi_pkt(c, (iscsi_hdr_t *)&rtt, 0);
-}
-
-/*
- * []----
- * | iscsi_conn_data_in -- Send data to initiator
- * []----
- */
-void
-iscsi_conn_data_in(t10_cmd_t *t)
-{
- iscsi_cmd_t *cmd = (iscsi_cmd_t *)T10_TRANS_ID(t);
- iscsi_conn_t *c;
-
- c = cmd->c_allegiance;
- (void) pthread_mutex_lock(&c->c_mutex);
- (void) pthread_mutex_lock(&c->c_state_mutex);
- if ((c->c_state != S5_LOGGED_IN) ||
- (cmd->c_state == CmdCanceled)) {
-
- t10_cmd_shoot_event(t, T10_Cmd_T5);
- while (cmd->c_t10_delayed) {
- t10_cmd_shoot_event(cmd->c_t10_delayed->id_t10_cmd,
- T10_Cmd_T5);
- iscsi_cmd_delayed_remove(cmd, cmd->c_t10_delayed);
- }
- (void) pthread_mutex_unlock(&c->c_state_mutex);
- (void) pthread_mutex_unlock(&c->c_mutex);
- return;
- }
- (void) pthread_mutex_unlock(&c->c_state_mutex);
-
- /*
- * Need to deal with out of order data PDUs. RFC3720 allows
- * the initiator to indicate if it can handle out-of-order
- * PDUs.
- */
- if ((c->c_data_pdu_in_order == True) &&
- (cmd->c_offset_in != T10_DATA_OFFSET(t))) {
- iscsi_cmd_delayed_store(cmd, t);
- (void) pthread_mutex_unlock(&c->c_mutex);
- return;
- }
-
- while (t != NULL) {
- cmd->c_offset_in += T10_DATA_LEN(t);
- if (T10_CMD_LAST(t) == True) {
- if (cmd->c_offset_in == cmd->c_dlen_expected) {
- send_datain_pdu(c, t,
- ISCSI_FLAG_FINAL | ISCSI_FLAG_DATA_STATUS);
- } else {
- /*
- * Normally the target only sends a SCSI
- * Response PDU for DataOut operations since
- * the it indicates successful completion
- * in the last DataIn PDU per the spec.
- * There are cases where the initiator asks
- * for more data then we send, for example
- * an INQUIRY command usually returns less
- * data then asked for. So, in this case we
- * send the DataIn PDU with the appropriate
- * amount, followed by a SCSI Response
- * indicating the difference between what the
- * initiator expected and we're sending.
- */
-
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "CON%x Underflow occurred\n", c->c_num);
- send_datain_pdu(c, t, 0);
- send_scsi_rsp(c, t);
- }
- iscsi_cmd_free(c, cmd);
- } else {
- send_datain_pdu(c, t, 0);
- }
- t10_cmd_shoot_event(t, T10_Cmd_T5);
-
- if (cmd->c_t10_delayed &&
- (cmd->c_t10_delayed->id_offset == cmd->c_offset_in)) {
- t = cmd->c_t10_delayed->id_t10_cmd;
- iscsi_cmd_delayed_remove(cmd, cmd->c_t10_delayed);
- } else {
- t = NULL;
- }
- }
- (void) pthread_mutex_unlock(&c->c_mutex);
-}
-
-/*
- * []----
- * | iscsi_conn_cmdcmplt -- Send out appropriate completion PDU
- * []----
- */
-static void
-iscsi_conn_cmdcmplt(t10_cmd_t *t)
-{
- iscsi_cmd_t *cmd = (iscsi_cmd_t *)T10_TRANS_ID(t);
- iscsi_conn_t *c;
-
- c = cmd->c_allegiance;
- (void) pthread_mutex_lock(&c->c_mutex);
- (void) pthread_mutex_lock(&c->c_state_mutex);
- if ((c->c_state != S5_LOGGED_IN) ||
- (cmd->c_state == CmdCanceled)) {
-
- t10_cmd_shoot_event(t, T10_Cmd_T5);
- (void) pthread_mutex_unlock(&c->c_state_mutex);
- (void) pthread_mutex_unlock(&c->c_mutex);
- return;
- }
- (void) pthread_mutex_unlock(&c->c_state_mutex);
-
- if (T10_SENSE_LEN(t) || (T10_DATA(t) == 0)) {
-
- /*
- * If d_sense_len is set there's a problem and we need to send
- * a SCSI response packet. Or if there's no data buffer then
- * this is an acknowledgement that a SCSI Write completed
- * successfully.
- */
- send_scsi_rsp(c, t);
-
- } else {
-
- /*
- * send data out with final bit. Last packet of a SCSI
- * READ Op and we'll send it out with the final/status
- * bits set.
- */
- send_datain_pdu(c, t,
- ISCSI_FLAG_FINAL | ISCSI_FLAG_DATA_STATUS);
-
- }
-
- t10_cmd_shoot_event(t, T10_Cmd_T5);
-
- if (cmd->c_scb_extended != NULL)
- free(cmd->c_scb_extended);
- iscsi_cmd_free(c, cmd);
- (void) pthread_mutex_unlock(&c->c_mutex);
-}
-
-/*
- * []----
- * | send_datain_pdu -- Send DataIn PDU with READ data
- * |
- * | If this is the last read operation and it completed successfully
- * | the final flag will be set along with the status bit which indicates
- * | successful completion. This is known as a phase collapse for iSCSI.
- * |
- * | NOTE: connection mutex must be held.
- * []----
- */
-static void
-send_datain_pdu(iscsi_conn_t *c, t10_cmd_t *t, uint8_t final_flag)
-{
- iscsi_cmd_t *cmd = (iscsi_cmd_t *)T10_TRANS_ID(t);
- iscsi_data_rsp_hdr_t rsp;
-
- assert(pthread_mutex_trylock(&c->c_mutex) != 0);
- bzero(&rsp, sizeof (rsp));
-
- rsp.opcode = ISCSI_OP_SCSI_DATA_RSP;
- rsp.flags = final_flag;
- rsp.cmd_status = cmd->c_status;
- rsp.itt = cmd->c_itt;
- rsp.ttt = ISCSI_RSVD_TASK_TAG;
- rsp.datasn = htonl(cmd->c_datasn++);
- rsp.offset = htonl(T10_DATA_OFFSET(t));
- rsp.lun[1] = (uint8_t)cmd->c_lun;
-
- hton24(rsp.dlength, T10_DATA_LEN(t));
-
- /*
- * The statsn is only incremented when the Status bit is set
- * for a DataIn PDU. This must be done *after* the value
- * was stored in the PDU.
- */
- if (final_flag & ISCSI_FLAG_DATA_STATUS) {
- rsp.statsn = htonl(c->c_statsn);
- c->c_statsn++;
- } else
- rsp.statsn = 0;
-
- (void) pthread_mutex_lock(&c->c_sess->s_mutex);
- rsp.maxcmdsn = htonl(iscsi_cmd_window(c) + c->c_sess->s_seencmdsn);
- rsp.expcmdsn = htonl(c->c_sess->s_seencmdsn + 1);
- (void) pthread_mutex_unlock(&c->c_sess->s_mutex);
-
- if (ISCSI_DATA_SEND_ENABLED()) {
- uiscsiproto_t info;
-
- info.uip_target_addr = &c->c_target_sockaddr;
- info.uip_initiator_addr = &c->c_initiator_sockaddr;
-
- info.uip_target = c->c_sess->s_t_name;
- info.uip_initiator = c->c_sess->s_i_name;
- info.uip_lun = cmd->c_lun;
-
- info.uip_itt = rsp.itt;
- info.uip_ttt = rsp.ttt;
-
- info.uip_cmdsn = ntohl(rsp.expcmdsn);
- info.uip_statsn = ntohl(rsp.statsn);
- info.uip_datasn = ntohl(rsp.datasn);
-
- info.uip_datalen = T10_DATA_LEN(t);
- info.uip_flags = rsp.flags;
-
- ISCSI_DATA_SEND(&info);
- }
-
- send_iscsi_pkt(c, (iscsi_hdr_t *)&rsp, T10_DATA(t));
-}
-
-/*
- * []----
- * | send_scsi_rsp -- Send SCSI reponse PDU
- * |
- * | NOTE: connection mutex must be held.
- * []----
- */
-static void
-send_scsi_rsp(iscsi_conn_t *c, t10_cmd_t *t)
-{
- iscsi_cmd_t *cmd = (iscsi_cmd_t *)T10_TRANS_ID(t);
- iscsi_scsi_rsp_hdr_t rsp;
- void *auto_sense = NULL;
-
- assert(pthread_mutex_trylock(&c->c_mutex) != 0);
- bzero(&rsp, sizeof (rsp));
-
- rsp.opcode = ISCSI_OP_SCSI_RSP;
- rsp.flags = ISCSI_FLAG_FINAL;
- rsp.itt = cmd->c_itt;
- rsp.statsn = htonl(c->c_statsn++);
- (void) pthread_mutex_lock(&c->c_sess->s_mutex);
- rsp.expcmdsn = htonl(c->c_sess->s_seencmdsn + 1);
- rsp.maxcmdsn = htonl(iscsi_cmd_window(c) + c->c_sess->s_seencmdsn);
- (void) pthread_mutex_unlock(&c->c_sess->s_mutex);
- rsp.cmd_status = T10_CMD_STATUS(t);
-
- if (cmd->c_writeop == True) {
- if (cmd->c_offset_out != cmd->c_dlen_expected)
- rsp.flags |= ISCSI_FLAG_CMD_OVERFLOW;
- rsp.residual_count = htonl(cmd->c_dlen_expected -
- cmd->c_offset_out);
- } else {
- if (cmd->c_offset_in != cmd->c_dlen_expected)
- rsp.flags |= ISCSI_FLAG_CMD_UNDERFLOW;
- rsp.residual_count = htonl(cmd->c_dlen_expected -
- cmd->c_offset_in);
- }
-
- if (rsp.cmd_status) {
- rsp.response = ISCSI_STATUS_CMD_COMPLETED;
- rsp.residual_count = htonl(T10_CMD_RESID(t));
-
- if (T10_SENSE_LEN(t) != 0) {
- /*
- * Need to handle autosense stuff. The data should
- * be store in the d_sense area
- */
- auto_sense = (void *)T10_SENSE_DATA(t);
- hton24(rsp.dlength, T10_SENSE_LEN(t));
- }
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "CON%x SCSI Error Status: %d\n",
- c->c_num, rsp.cmd_status);
- } else {
- rsp.response = ISCSI_STATUS_CMD_COMPLETED;
- rsp.expdatasn = htonl(cmd->c_datasn);
- }
-
- if (ISCSI_SCSI_RESPONSE_ENABLED()) {
- uiscsiproto_t info;
-
- info.uip_target_addr = &c->c_target_sockaddr;
- info.uip_initiator_addr = &c->c_initiator_sockaddr;
-
- info.uip_target = c->c_sess->s_t_name;
- info.uip_initiator = c->c_sess->s_i_name;
- info.uip_lun = cmd->c_lun;
-
- info.uip_itt = rsp.itt;
- info.uip_ttt = ISCSI_RSVD_TASK_TAG;
-
- info.uip_cmdsn = ntohl(rsp.expcmdsn);
- info.uip_statsn = ntohl(rsp.statsn);
- info.uip_datasn = ntohl(rsp.expdatasn);
-
- info.uip_datalen = T10_DATA_LEN(t);
- info.uip_flags = rsp.flags;
-
- ISCSI_SCSI_RESPONSE(&info);
- }
-
- send_iscsi_pkt(c, (iscsi_hdr_t *)&rsp, auto_sense);
-}
-
-static void
-send_async_scsi(iscsi_conn_t *c, int key, int asc, int ascq)
-{
- iscsi_async_evt_hdr_t a;
- struct scsi_extended_sense s;
- char *buf;
- int dlen = sizeof (s) + 2;
-
- bzero(&a, sizeof (a));
- bzero(&s, sizeof (s));
-
- s.es_class = CLASS_EXTENDED_SENSE;
- s.es_code = CODE_FMT_FIXED_CURRENT;
- s.es_key = key;
- s.es_valid = 1;
- s.es_add_code = asc;
- s.es_qual_code = ascq;
-
- if ((buf = malloc(sizeof (s) + 2)) == NULL)
- return;
-
- buf[0] = (sizeof (s) >> 8) & 0xff;
- buf[1] = sizeof (s) & 0xff;
- bcopy(&s, &buf[2], sizeof (s));
-
- hton24(a.dlength, dlen);
- a.opcode = ISCSI_OP_ASYNC_EVENT;
- a.flags = ISCSI_FLAG_FINAL;
- a.async_event = ISCSI_ASYNC_EVENT_SCSI_EVENT;
- (void) pthread_mutex_lock(&c->c_mutex);
- a.statsn = htonl(c->c_statsn++);
- (void) pthread_mutex_lock(&c->c_sess->s_mutex);
- a.expcmdsn = htonl(c->c_sess->s_seencmdsn + 1);
- a.maxcmdsn = htonl(iscsi_cmd_window(c) + c->c_sess->s_seencmdsn);
- (void) pthread_mutex_unlock(&c->c_sess->s_mutex);
- (void) pthread_mutex_unlock(&c->c_mutex);
-
- queue_prt(c->c_mgmtq, Q_CONN_NONIO,
- "CON%x Sending async scsi sense\n", c->c_num);
-
- if (ISCSI_ASYNC_SEND_ENABLED()) {
- uiscsiproto_t info;
-
- info.uip_target_addr = &c->c_target_sockaddr;
- info.uip_initiator_addr = &c->c_initiator_sockaddr;
-
- info.uip_target = c->c_sess->s_t_name;
- info.uip_initiator = c->c_sess->s_i_name;
- info.uip_lun = 0;
-
- info.uip_itt = ISCSI_RSVD_TASK_TAG;
- info.uip_ttt = ISCSI_RSVD_TASK_TAG;
-
- info.uip_cmdsn = ntohl(a.expcmdsn);
- info.uip_statsn = ntohl(a.statsn);
- info.uip_datasn = 0;
-
- info.uip_datalen = dlen;
- info.uip_flags = a.flags;
-
- ISCSI_ASYNC_SEND(&info);
- }
-
- send_iscsi_pkt(c, (iscsi_hdr_t *)&a, buf);
-}
-
-/*
- * []----
- * | send_async_logout -- request logout from initiator
- * []----
- */
-static void
-send_async_logout(iscsi_conn_t *c)
-{
- iscsi_async_evt_hdr_t a;
-
- bzero(&a, sizeof (a));
-
- a.opcode = ISCSI_OP_ASYNC_EVENT;
- a.flags = ISCSI_FLAG_FINAL;
- a.async_event = ISCSI_ASYNC_EVENT_REQUEST_LOGOUT;
- (void) pthread_mutex_lock(&c->c_mutex);
- a.statsn = htonl(c->c_statsn++);
- (void) pthread_mutex_lock(&c->c_sess->s_mutex);
- a.expcmdsn = htonl(c->c_sess->s_seencmdsn + 1);
- a.maxcmdsn = htonl(iscsi_cmd_window(c) + c->c_sess->s_seencmdsn);
- a.param3 = htons(ASYNC_LOGOUT_TIMEOUT);
- a.rsvd4[0] = 0xff;
- a.rsvd4[1] = 0xff; /* According to the spec these four */
- a.rsvd4[2] = 0xff; /* values must be 0xff */
- a.rsvd4[3] = 0xff;
- (void) pthread_mutex_unlock(&c->c_sess->s_mutex);
- (void) pthread_mutex_unlock(&c->c_mutex);
-
- queue_prt(c->c_mgmtq, Q_CONN_NONIO,
- "CON%x Sending async logout request\n", c->c_num);
-
- if (ISCSI_ASYNC_SEND_ENABLED()) {
- uiscsiproto_t info;
-
- info.uip_target_addr = &c->c_target_sockaddr;
- info.uip_initiator_addr = &c->c_initiator_sockaddr;
-
- info.uip_target = c->c_sess->s_t_name;
- info.uip_initiator = c->c_sess->s_i_name;
- info.uip_lun = 0;
-
- info.uip_itt = ISCSI_RSVD_TASK_TAG;
- info.uip_ttt = ISCSI_RSVD_TASK_TAG;
-
- info.uip_cmdsn = ntohl(a.expcmdsn);
- info.uip_statsn = ntohl(a.statsn);
- info.uip_datasn = 0;
-
- info.uip_datalen = 0;
- info.uip_flags = a.flags;
-
- ISCSI_ASYNC_SEND(&info);
- }
-
- send_iscsi_pkt(c, (iscsi_hdr_t *)&a, 0);
-}
-
-/*
- * []----
- * | queue_noop_in -- generate a NOP request and queue it to be sent.
- * []----
- */
-static void
-queue_noop_in(iscsi_conn_t *c)
-{
- iscsi_nop_in_hdr_t *in;
- iscsi_cmd_t *cmd = iscsi_cmd_alloc(c, ISCSI_OP_NOOP_IN);
-
- if (cmd == NULL)
- return;
-
- in = (iscsi_nop_in_hdr_t *)calloc(sizeof (*in), 1);
- if (in == NULL)
- return;
-
- /*
- * Immediate flag is reserved in nop-in command. RFC-3720 10.19.
- * See CR 6597310.
- */
- in->opcode = ISCSI_OP_NOOP_IN;
- in->flags = ISCSI_FLAG_FINAL;
- in->ttt = cmd->c_ttt;
- in->itt = ISCSI_RSVD_TASK_TAG;
-
- (void) pthread_mutex_lock(&c->c_mutex);
- iscsi_cmd_free(c, cmd);
- (void) pthread_mutex_unlock(&c->c_mutex);
- queue_message_set(c->c_dataq, 0, msg_send_pkt, (void *)in);
-}
-
-void
-iscsi_capacity_change(char *targ_name, int lun)
-{
- iscsi_conn_t *conn;
- extern pthread_mutex_t port_mutex;
-
- /*
- * SBC-2 revision 16, section 4.6 -- Initialization
- * Any time the parameter data returned by the READ CAPACITY(10)
- * (see 5.10) or the READ CAPACITY(16) command (see 5.11) changes,
- * the device server should establish a unit attention condition for
- * the initiator port associated with each I_T nexus.
- * Since the transport knows which initiators are currently accessing
- * the target the message will be sent from here.
- */
- (void) pthread_mutex_lock(&port_mutex);
- for (conn = conn_head; conn; conn = conn->c_next) {
- (void) pthread_mutex_lock(&conn->c_state_mutex);
- if ((conn->c_state == S5_LOGGED_IN) &&
- (conn->c_sess->s_type == SessionNormal) &&
- (strcmp(conn->c_sess->s_t_name, targ_name) == 0)) {
-
- queue_message_set(conn->c_sessq, 0,
- msg_lu_capacity_change, (void *)(uintptr_t)lun);
- }
- (void) pthread_mutex_unlock(&conn->c_state_mutex);
- }
- (void) pthread_mutex_unlock(&port_mutex);
-}
-
-/*
- * []----
- * | iscsi_inventory_change -- Send notice to initiator that something changed.
- * []----
- */
-void
-iscsi_inventory_change(char *targ_name)
-{
- iscsi_conn_t *c;
- extern pthread_mutex_t port_mutex;
-
- /*
- * SPC-3 revision 21c, Section 6.21 REPORT_LUNS
- * If the logical unit inventory changes for any reason
- * (e.g. completion of initialization, removal of a logical unit,
- * or create of a logical unit), then the device server shall generate
- * a unit attention condition for all I_T nexuses, with the additional
- * sense code set to REPORTED LUNS DATA HAS CHANGED.
- */
- (void) pthread_mutex_lock(&port_mutex);
- for (c = conn_head; c; c = c->c_next) {
- (void) pthread_mutex_lock(&c->c_state_mutex);
- if ((c->c_state == S5_LOGGED_IN) &&
- (c->c_sess->s_type == SessionNormal) &&
- (strcmp(c->c_sess->s_t_name, targ_name) == 0)) {
-
- queue_prt(c->c_mgmtq, Q_CONN_NONIO,
- "CON%x Sending Inventory change out\n", c->c_num);
- /*
- * Send a message indicating that the logical unit
- * inventory has changed. 1) This message is sent
- * to the session level which will pass it onto
- * the SAM layer causing a UNIT_ATTENTION during
- * the next command. 2) This message is also sent
- * directly to the outgoing side of the connection
- * which will send an asynchronous event message
- * to the initiator.
- */
- queue_message_set(c->c_sessq, 0,
- msg_targ_inventory_change, 0);
- queue_message_set(c->c_dataq, 0,
- msg_targ_inventory_change, 0);
- }
- (void) pthread_mutex_unlock(&c->c_state_mutex);
- }
- (void) pthread_mutex_unlock(&port_mutex);
-}
-
-/*
- * []----
- * | state_to_str -- return string for given state, used for debug
- * []----
- */
-static char *
-state_to_str(iscsi_state_t s)
-{
- switch (s) {
- case S1_FREE: return ("FREE");
- case S3_XPT_UP: return ("XPT_UP");
- case S4_IN_LOGIN: return ("IN_LOGIN");
- case S5_LOGGED_IN: return ("LOGGED_IN");
- case S6_IN_LOGOUT: return ("IN_LOGOUT");
- case S7_LOGOUT_REQUESTED: return ("LOGOUT_REQUEST");
- case S8_CLEANUP_WAIT: return ("CLEANUP_WAIT");
- }
- return ("Unknown");
-}
-
-/*
- * []----
- * | event_to_str -- return string for given event, used for debug
- * []----
- */
-static char *
-event_to_str(iscsi_transition_t t)
-{
- switch (t) {
- case T3: return ("T3");
- case T4: return ("T4");
- case T5: return ("T5");
- case T6: return ("T6");
- case T7: return ("T7");
- case T8: return ("T8");
- case T9: return ("T9");
- case T10: return ("T10");
- case T11: return ("T11");
- case T12: return ("T12");
- case T13: return ("T13");
- case T15: return ("T15");
- case T16: return ("T16");
- case T17: return ("T17");
- case T18: return ("T18");
- }
- return ("Unknown");
-}
-
-/*
- * []----
- * | conn_state -- Attempt to change from one state to the next
- * []----
- */
-void
-conn_state(iscsi_conn_t *c, iscsi_transition_t t)
-{
- iscsi_state_t old_state = c->c_state;
- Boolean_t lock = False;
-
- (void) pthread_mutex_lock(&c->c_state_mutex);
- lock = True;
-
- switch (c->c_state) {
- case S1_FREE:
- switch (t) {
- case T3:
- c->c_state = S3_XPT_UP;
- break;
-
- }
- break;
-
- case S3_XPT_UP:
- switch (t) {
- case T6:
- c->c_state = S1_FREE;
- break;
-
- case T4:
- c->c_statsn = 0;
- c->c_state = S4_IN_LOGIN;
- break;
-
- }
- break;
-
- case S4_IN_LOGIN:
- switch (t) {
- case T7:
- /*
- * When there's a session a shutdown messages is
- * sent giving the opportunity to free resources
- * used by the session code and STE. Very early
- * on a session might not exist when a failure
- * occurs like getting a bad opcode. The connection
- * process routine is going to sit around waiting
- * for a message which will never come so fake
- * a completion message here if there's no session.
- */
- if (c->c_sessq == NULL) {
- queue_message_set(c->c_dataq, 0,
- msg_shutdown_rsp, (void *)True);
- } else {
- queue_message_set(c->c_sessq, 0, msg_shutdown,
- (void *)c);
- }
- c->c_state = S1_FREE;
- break;
- case T5:
- c->c_state = S5_LOGGED_IN;
- if (strncmp(c->c_sess->s_i_name,
- "iqn.1991-05.com.microsoft",
- strlen("iqn.1991-05.com.microsoft")) == 0)
- c->c_sess->s_cmdsn++;
- break;
- }
- break;
-
- case S5_LOGGED_IN:
- switch (t) {
- case T8:
- c->c_state = S1_FREE;
- queue_message_set(c->c_sessq, 0, msg_shutdown,
- (void *)c);
- break;
- case T9:
- queue_message_set(c->c_sessq, 0, msg_shutdown,
- (void *)c);
- c->c_state = S6_IN_LOGOUT;
- break;
- case T11:
- c->c_state = S7_LOGOUT_REQUESTED;
- /*
- * need to unlock here conn_state may get
- * call again, which can create deadlock
- */
- (void) pthread_mutex_unlock(&c->c_state_mutex);
- lock = False;
- send_async_logout(c);
- break;
- case T15:
- c->c_state = S8_CLEANUP_WAIT;
- break;
- }
- break;
-
- case S6_IN_LOGOUT:
- switch (t) {
- case T13:
- if (c->c_last_pkg) {
- iscsi_logout_rsp_hdr_t *rsp =
- (iscsi_logout_rsp_hdr_t *)c->c_last_pkg;
- assert(rsp->opcode == ISCSI_OP_LOGOUT_RSP);
-
- if (ISCSI_LOGOUT_RESPONSE_ENABLED()) {
- uiscsiproto_t info;
- char nil = '\0';
-
- info.uip_target_addr =
- &c->c_target_sockaddr;
- info.uip_initiator_addr =
- &c->c_initiator_sockaddr;
- info.uip_target = &nil;
-
- info.uip_initiator =
- c->c_sess->s_i_name;
- info.uip_lun = 0;
-
- info.uip_itt = rsp->itt;
- info.uip_ttt = ISCSI_RSVD_TASK_TAG;
-
- info.uip_cmdsn = ntohl(rsp->expcmdsn);
- info.uip_statsn = ntohl(rsp->statsn);
- info.uip_datasn = 0;
-
- info.uip_datalen = ntoh24(rsp->dlength);
- info.uip_flags = rsp->flags;
-
- ISCSI_LOGOUT_RESPONSE(&info);
- }
-
- /*
- * need to unlock here conn_state may get
- * call again, which can create deadlock
- */
- (void) pthread_mutex_unlock(&c->c_state_mutex);
- lock = False;
- send_iscsi_pkt(c, c->c_last_pkg, NULL);
- free(c->c_last_pkg);
- }
- c->c_state = S1_FREE;
- break;
- case T17:
- c->c_state = S8_CLEANUP_WAIT;
- break;
- }
- break;
-
- case S7_LOGOUT_REQUESTED:
- switch (t) {
- case T18:
- c->c_state = S1_FREE;
- queue_message_set(c->c_sessq, 0, msg_shutdown,
- (void *)c);
- break;
- case T10:
- queue_message_set(c->c_sessq, 0, msg_shutdown,
- (void *)c);
- c->c_state = S6_IN_LOGOUT;
- break;
- case T12:
- c->c_state = S7_LOGOUT_REQUESTED;
- break;
- case T16:
- c->c_state = S8_CLEANUP_WAIT;
- break;
- }
- break;
-
- case S8_CLEANUP_WAIT:
- default:
- break;
- }
- queue_prt(c->c_mgmtq, Q_CONN_NONIO, "CON%x ---- %s(%s) -> %s\n",
- c->c_num, state_to_str(old_state), event_to_str(t),
- state_to_str(c->c_state));
- if (lock)
- (void) pthread_mutex_unlock(&c->c_state_mutex);
-}
-
-/*
- * []----
- * | send_iscsi_pkt -- output PDU header, data, and alignment bytes if needed
- * |
- * | NOTE: This routine may be called with the connection mutex held. This
- * | is done to prevent a state change being made to a command pointer. This
- * | routine is currently written so that it doesn't need to have this mutex
- * | held or calls a routine which needs it to be held.
- * []----
- */
-void
-send_iscsi_pkt(iscsi_conn_t *c, iscsi_hdr_t *h, char *opt_text)
-{
- int dlen = ntoh24(h->dlength);
- int pad_len;
- uint32_t crc;
-
-#ifdef ETHEREAL_DEBUG
- uint32_t alen;
- char *abuf;
-
- /*
- * For ethereal to correctly show the entire PDU and data everything
- * must be written once else the Solaris TCP stack will send this
- * out in multiple packets. Normally this isn't a problem, but when
- * attempting to debug certain interactions between an initiator
- * and this target is extremely benefical to have ethereal correctly
- * decode the SCSI payload for non I/O type packets.
- */
- if (dlen < 512) {
- /*
- * Find out how many pad bytes we need to send out.
- */
- pad_len = (ISCSI_PAD_WORD_LEN -
- (dlen & (ISCSI_PAD_WORD_LEN - 1))) &
- (ISCSI_PAD_WORD_LEN - 1);
- alen = sizeof (*h) + dlen + pad_len;
- if ((abuf = malloc(alen)) == NULL) {
- conn_state(c, T8);
- return;
- }
- bzero(abuf, alen);
- bcopy(h, abuf, sizeof (*h));
- if (opt_text)
- bcopy(opt_text, abuf + sizeof (*h), dlen);
- if (write(c->c_fd, abuf, alen) != alen) {
- conn_state(c, T8);
- free(abuf);
- return;
- }
- free(abuf);
-#ifdef FULL_DEBUG
- queue_prt(c->c_mgmtq, Q_CONN_IO,
- "CON%x Response(0x%x), Data: len=0x%x addr=0x%llx\n",
- c->c_num, h->opcode, dlen, opt_text);
-#endif
- return;
- }
-#endif
-
- /*
- * Sanity check. If there's a length in the header we must
- * have text to send or if the length is zero there better not
- * be any text.
- */
- if (((dlen == 0) && (opt_text != NULL)) ||
- ((dlen != 0) && (opt_text == NULL)))
- return;
-
- if (write(c->c_fd, h, sizeof (*h)) < 0) {
- if (errno == EPIPE) {
-
- /*
- * For some reason the initiator has closed the
- * socket on us. This is most likely caused because
- * of some network related condition
- * (e.g. broken cable). We'll shutdown our side and
- * wait for a reconnect from the initiator.
- */
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "CON%x iscsi_pkt -- initiator closed socket\n",
- c->c_num);
- } else {
-
- /*
- * This is not good.
- */
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "CON%x iscsi_pkt write failed, errno %d\n",
- c->c_num, errno);
- }
- conn_state(c, T8);
- return;
- }
-
- /*
- * Only start generating digest values once we've completed the
- * login phase. If the state is not checked here and during login
- * header or data digests have been enabled we would generate
- * a digest value during the Login RSP PDU which the initiator
- * is not expecting.
- */
- if ((c->c_state == S5_LOGGED_IN) && (c->c_header_digest == True)) {
- crc = iscsi_crc32c((void *)h, sizeof (*h));
- if (write(c->c_fd, &crc, sizeof (crc)) != sizeof (crc)) {
- conn_state(c, T8);
- return;
- }
- }
-
- if (dlen) {
- if (write(c->c_fd, opt_text, dlen) != dlen) {
- conn_state(c, T8);
- return;
- }
-
- /*
- * Find out how many pad bytes we need to send out.
- */
- pad_len = (ISCSI_PAD_WORD_LEN -
- (dlen & (ISCSI_PAD_WORD_LEN - 1))) &
- (ISCSI_PAD_WORD_LEN - 1);
- if (pad_len) {
- if (write(c->c_fd, pad_text, pad_len) != pad_len) {
- conn_state(c, T8);
- return;
- }
- }
-
- if ((c->c_state == S5_LOGGED_IN) &&
- (c->c_data_digest == True)) {
-
- crc = iscsi_crc32c((void *)opt_text,
- (unsigned long)dlen);
-
- /*
- * Include the pad information in the calculation of
- * the CRC for the data.
- */
- crc = iscsi_crc32c_continued((void *)pad_text,
- (unsigned long)pad_len, crc);
-
- if (write(c->c_fd, &crc, sizeof (crc)) !=
- sizeof (crc)) {
- conn_state(c, T8);
- return;
- }
- }
- }
-#ifdef FULL_DEBUG
- if (dlen != 0) {
- queue_prt(c->c_mgmtq, Q_CONN_IO,
- "CON%x Response(0x%x), Data: len=0x%x addr=0x%llx\n",
- c->c_num, h->opcode, dlen, opt_text);
- }
-#endif
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/iscsi_conn.h b/usr/src/cmd/iscsi/iscsitgtd/iscsi_conn.h
deleted file mode 100644
index 851757200d..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_conn.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _TARGET_CONN_H
-#define _TARGET_CONN_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Block comment which describes the contents of this file.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <sys/iscsi_protocol.h>
-#include <sys/socket.h>
-#include "queue.h"
-#include "iscsi_sess.h"
-#include "iscsi_cmd.h"
-
-#define LBUFSIZE 80
-
-#define TARGET_LOCATION "targets"
-/*
- * Currently I'm having some problems with network reads/write when the
- * data size is larger than 8k. To work around this problem I set the
- * various negotiation parameters during login to limit things to 8k.
- */
-
-#define NETWORK_SNDRCV 65536
-#define NETWORK_SNDRCV_STR "65536"
-
-typedef enum iscsi_state {
- S1_FREE,
- /* S2_XPT_WAIT, Not possible for target */
- S3_XPT_UP,
- S4_IN_LOGIN,
- S5_LOGGED_IN,
- S6_IN_LOGOUT,
- S7_LOGOUT_REQUESTED,
- S8_CLEANUP_WAIT
-} iscsi_state_t;
-
-typedef enum iscsi_transition {
- T3, T4, T5, T6, T7, T8,
- T9, T10, T11, T12, T13, T15,
- T16, T17, T18
-} iscsi_transition_t;
-
-/*
- * When grabbing mutex's make sure to grab c_mutex before c_mutex_state
- * if you need to grab both.
- */
-typedef struct iscsi_conn {
- int c_fd;
-
- /*
- * This is a linked list of all connections. Not just the connections
- * associated with a particular session.
- */
- struct iscsi_conn *c_next,
- *c_prev;
-
- target_queue_t *c_mgmtq;
-
- /*
- * Time as reported by time(2) when this connection was started.
- */
- time_t c_up_at;
-
- /*
- * This queue is used to accept notification that incoming packets
- * are available and command completion status from Session.
- */
- target_queue_t *c_dataq;
-
- /*
- * Messages are sent to Session, and from there onto STE, using
- * this queue.
- */
- target_queue_t *c_sessq;
-
- iscsi_sess_t *c_sess;
-
- pthread_mutex_t c_state_mutex;
- iscsi_state_t c_state;
-
- /*
- * Protected by c_mutex
- */
- int c_statsn;
-
- int c_cid;
-
- /*
- * Pointer to data buffer used to store text messages which have
- * the 'C' bit set. Since the text data separates name/value pairs
- * with a '\0' strlen can't be used to determine the amount of space
- * used so we keep the length in c_text_len;
- */
- char *c_text_area;
- int c_text_len;
- int c_text_sent;
-
- sema_t c_datain;
- pthread_t c_thr_id_poller,
- c_thr_id_process;
-
- pthread_mutex_t c_mutex;
- iscsi_cmd_t *c_cmd_head;
- iscsi_cmd_t *c_cmd_tail;
-
- struct sockaddr_storage c_initiator_sockaddr;
- struct sockaddr_storage c_target_sockaddr;
-
- int c_num;
-
- int c_auth_pass : 1;
-
- int c_cmds_active;
-
- /*
- * A performance issue has been found when the backing store
- * is UFS. Because of the indirect blocks used by UFS large files
- * (many GBs in size) perform poorly. This in turn can cause the
- * initiator to issue commands which don't complete in time. So,
- * we'll monitor the completion times for commands if if it's
- * increasing the command window will be reduced.
- * The avg_sum is in nanoseconds. This will wrap once every 584
- * years.
- */
- uint64_t c_cmds_avg_cnt;
- hrtime_t c_cmds_avg_sum;
-
- /*
- * During an orderly shutdown the logout response is created when
- * we receive the logout request. We must however wait for all I/O
- * to complete before processing the data else we'll loose data
- * which the initiator believes was successfully transferred.
- * Once the STE and sessions have closed they will send a shutdown
- * complete message. At that point the transmit side of the connection
- * will set the state to T13 which pushes this message out.
- * Unfortunately we need information from the Logout Request PDU
- * to create the Logout Response PDU. Otherwise the response could
- * be generated on the fly in the T13 state handler. By creating
- * the response PDU and saving a pointer gives us some flexibility
- * in the future if the final outgoing packet needs to change.
- * Otherwise, storing that one bit of information from the request
- * PDU might become dated.
- */
- iscsi_hdr_t *c_last_pkg;
-
- /*
- * Connection parameters
- */
- Boolean_t c_header_digest,
- c_data_digest,
- c_ifmarker,
- c_ofmarker,
- c_initialR2T,
- c_immediate_data,
- c_data_pdu_in_order,
- c_data_sequence_in_order;
- int c_tpgt,
- c_maxcmdsn,
- c_max_recv_data,
- c_default_time_2_wait,
- c_default_time_2_retain,
- c_erl,
- c_max_burst_len,
- c_first_burst_len,
- c_max_outstanding_r2t,
- c_max_connections;
- char *c_targ_alias,
- *auth_text;
- int auth_text_length;
-
-} iscsi_conn_t;
-
-void *conn_process(void *v);
-void conn_state(iscsi_conn_t *c, iscsi_transition_t t);
-void send_iscsi_pkt(iscsi_conn_t *c, iscsi_hdr_t *h, char *opt_text);
-int read_retry(int fd, char *buf, int count);
-void iscsi_inventory_change(char *targ_name);
-void iscsi_capacity_change(char *targ_name, int lun);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _TARGET_CONN_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/iscsi_crc.c b/usr/src/cmd/iscsi/iscsitgtd/iscsi_crc.c
deleted file mode 100644
index ba5736f294..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_crc.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2000 by Cisco Systems, Inc. All rights reserved.
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- *
- * This file contains CRC-32C code use to verify
- * iSCSI HeaderDigests and DataDigests.
- */
-
-#include <sys/types.h> /* standard types */
-#include <sys/iscsi_protocol.h> /* contains prototypes */
-#include <hd_crc.h>
-
-/*
- * This is the CRC-32C table
- * Generated with:
- * width = 32 bits
- * poly = 0x1EDC6F41
- * reflect input bytes = true
- * reflect output bytes = true
- */
-
-uint32_t iscsi_crc32c_table[256] =
-{
- 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
- 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
- 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
- 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
- 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
- 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
- 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
- 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
- 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
- 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
- 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
- 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
- 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
- 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
- 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
- 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
- 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
- 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
- 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
- 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
- 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
- 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
- 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
- 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
- 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
- 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
- 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
- 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
- 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
- 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
- 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
- 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
- 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
- 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
- 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
- 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
- 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
- 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
- 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
- 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
- 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
- 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
- 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
- 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
- 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
- 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
- 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
- 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
- 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
- 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
- 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
- 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
- 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
- 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
- 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
- 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
- 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
- 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
- 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
- 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
- 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
- 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
- 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
- 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
-};
-
-/*
- * -1 - uninitialized
- * 0 - applicable
- * others - NA
- */
-static int iscsi_crc32_hd = -1;
-
-/*
- * iscsi_crc32c - Steps through buffer one byte at at time, calculates
- * reflected crc using table.
- */
-uint32_t
-iscsi_crc32c(void *address, unsigned long length)
-{
- uint8_t *buffer = address;
- uint32_t crc = 0xffffffff, result;
-#ifdef _BIG_ENDIAN
- uint8_t byte0, byte1, byte2, byte3;
-#endif
-
- if (iscsi_crc32_hd == -1) {
- if (hd_crc32_avail((uint32_t *)iscsi_crc32c_table) == B_TRUE) {
- iscsi_crc32_hd = 0;
- } else {
- iscsi_crc32_hd = 1;
- }
- }
- if (iscsi_crc32_hd == 0)
- return (HW_CRC32(buffer, length, crc));
-
- while (length--) {
- crc = iscsi_crc32c_table[(crc ^ *buffer++) & 0xFFL] ^
- (crc >> 8);
- }
- result = crc ^ 0xffffffff;
-
-#ifdef _BIG_ENDIAN
- byte0 = (uint8_t)(result & 0xFF);
- byte1 = (uint8_t)((result >> 8) & 0xFF);
- byte2 = (uint8_t)((result >> 16) & 0xFF);
- byte3 = (uint8_t)((result >> 24) & 0xFF);
- result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
-#endif /* _BIG_ENDIAN */
-
- return (result);
-}
-
-
-/*
- * iscsi_crc32c_continued - Continues stepping through buffer one
- * byte at at time, calculates reflected crc using table.
- */
-uint32_t
-iscsi_crc32c_continued(void *address, unsigned long length, uint32_t crc)
-{
- uint8_t *buffer = address;
- uint32_t result;
-#ifdef _BIG_ENDIAN
- uint8_t byte0, byte1, byte2, byte3;
-#endif
-
- if (iscsi_crc32_hd == -1) {
- if (hd_crc32_avail((uint32_t *)iscsi_crc32c_table) == B_TRUE) {
- iscsi_crc32_hd = 0;
- } else {
- iscsi_crc32_hd = 1;
- }
- }
- if (iscsi_crc32_hd == 0)
- return (HW_CRC32_CONT(buffer, length, crc));
-
-#ifdef _BIG_ENDIAN
- byte0 = (uint8_t)((crc >> 24) & 0xFF);
- byte1 = (uint8_t)((crc >> 16) & 0xFF);
- byte2 = (uint8_t)((crc >> 8) & 0xFF);
- byte3 = (uint8_t)(crc & 0xFF);
- crc = ((byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0);
-#endif
-
- crc = crc ^ 0xffffffff;
- while (length--) {
- crc = iscsi_crc32c_table[(crc ^ *buffer++) & 0xFFL] ^
- (crc >> 8);
- }
- result = crc ^ 0xffffffff;
-
-#ifdef _BIG_ENDIAN
- byte0 = (uint8_t)(result & 0xFF);
- byte1 = (uint8_t)((result >> 8) & 0xFF);
- byte2 = (uint8_t)((result >> 16) & 0xFF);
- byte3 = (uint8_t)((result >> 24) & 0xFF);
- result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
-#endif
- return (result);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/iscsi_ffp.c b/usr/src/cmd/iscsi/iscsitgtd/iscsi_ffp.c
deleted file mode 100644
index 92387b2c7c..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_ffp.c
+++ /dev/null
@@ -1,1129 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * This file contains methods to handle the iSCSI Full Feature Phase aspects
- * of the protocol.
- */
-
-#include <unistd.h>
-#include <poll.h>
-#include <strings.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <utility.h>
-#include <netinet/in.h>
-#include <inttypes.h>
-#include <sys/socket.h>
-#include <sys/iscsi_protocol.h>
-
-#include <arpa/inet.h>
-
-#include "iscsi_ffp.h"
-#include "iscsi_cmd.h"
-#include "t10_spc.h"
-#include "utility.h"
-#include "iscsi_provider_impl.h"
-
-static Boolean_t handle_text_msg(iscsi_conn_t *, iscsi_hdr_t *, char *, int);
-static Boolean_t handle_logout_msg(iscsi_conn_t *, iscsi_hdr_t *, char *, int);
-static Boolean_t handle_scsi_cmd(iscsi_conn_t *, iscsi_hdr_t *, char *, int);
-static Boolean_t handle_noop_cmd(iscsi_conn_t *, iscsi_hdr_t *, char *, int);
-static Boolean_t handle_scsi_data(iscsi_conn_t *, iscsi_hdr_t *, char *, int);
-static Boolean_t handle_task_mgt(iscsi_conn_t *, iscsi_hdr_t *, char *, int);
-static Boolean_t dataout_delayed(iscsi_cmd_t *cmd, msg_type_t type);
-void dataout_callback(t10_cmd_t *t, char *data, size_t *xfer);
-
-Boolean_t
-iscsi_full_feature(iscsi_conn_t *c)
-{
- iscsi_hdr_t h;
- Boolean_t rval = False;
- char debug[128];
- char *ahs = NULL;
- int cc;
- int ahslen;
-
- if ((cc = recv(c->c_fd, &h, sizeof (h), MSG_WAITALL)) != sizeof (h)) {
- if (errno == ECONNRESET) {
- (void) snprintf(debug, sizeof (debug),
- "CON%x full_feature -- initiator reset socket\n",
- c->c_num);
- } else {
- (void) snprintf(debug, sizeof (debug),
- "CON%x full_feature(got-%d, expect-%d), errno=%d\n",
- c->c_num, cc, sizeof (h), errno);
- }
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug);
- conn_state(c, T8);
- return (False);
- }
-
- /*
- * Look to see if there's an Additional Header Segment available.
- * If so, read it in.
- */
- if ((ahslen = (h.hlength * sizeof (uint32_t))) != 0) {
- if ((ahs = malloc(ahslen)) == NULL)
- return (False);
- if (recv(c->c_fd, ahs, ahslen, MSG_WAITALL) != ahslen) {
- (void) snprintf(debug, sizeof (debug),
- "CON%x Failed to read in AHS", c->c_num);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug);
- free(ahs);
- return (False);
- }
- }
-
- (void) pthread_mutex_lock(&c->c_state_mutex);
- if (c->c_state != S5_LOGGED_IN && c->c_state != S7_LOGOUT_REQUESTED) {
- (void) snprintf(debug, sizeof (debug),
- "CON%x full_feature -- not in S5_LOGGED_IN state\n",
- c->c_num);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug);
- if (ahs != NULL)
- free(ahs);
- (void) pthread_mutex_unlock(&c->c_state_mutex);
- return (False);
- }
- (void) pthread_mutex_unlock(&c->c_state_mutex);
-
- if (c->c_header_digest == True) {
- uint32_t crc_actual;
- uint32_t crc_calculated;
-
- (void) recv(c->c_fd, (char *)&crc_actual,
- sizeof (crc_actual), MSG_WAITALL);
- crc_calculated = iscsi_crc32c((void *)&h, sizeof (h));
- if (ahslen)
- crc_calculated = iscsi_crc32c_continued(ahs,
- ahslen, crc_calculated);
- if (crc_actual != crc_calculated) {
- (void) snprintf(debug, sizeof (debug),
- "CON%x CRC error: actual 0x%x v. calc 0x%x",
- c->c_num, crc_actual, crc_calculated);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug);
- if (ahs != NULL)
- free(ahs);
- return (False);
- }
- }
-
- if (c->c_sess->s_type == SessionDiscovery) {
- switch (h.opcode & ISCSI_OPCODE_MASK) {
- default:
- /*
- * Need to handle the error case here.
- */
- (void) snprintf(debug, sizeof (debug),
- "CON%x Wrong opcode for Discovery, %d",
- c->c_num, h.opcode & ISCSI_OPCODE_MASK);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug);
- rval = False;
- break;
-
- case ISCSI_OP_LOGOUT_CMD:
- /*
- * This will transition from S5_LOGGED_IN
- * to S6_IN_LOGOUT to S1_FREE;
- */
- rval = handle_logout_msg(c, &h, ahs, ahslen);
- break;
-
- case ISCSI_OP_TEXT_CMD:
- rval = handle_text_msg(c, &h, ahs, ahslen);
- break;
- }
- } else {
- iscsi_cmd_remove(c, ntohl(h.expstatsn));
- switch (h.opcode & ISCSI_OPCODE_MASK) {
- case ISCSI_OP_NOOP_OUT:
- rval = handle_noop_cmd(c, &h, ahs, ahslen);
- break;
-
- case ISCSI_OP_SCSI_CMD:
- rval = handle_scsi_cmd(c, &h, ahs, ahslen);
- break;
-
- case ISCSI_OP_SCSI_TASK_MGT_MSG:
- rval = handle_task_mgt(c, &h, ahs, ahslen);
- break;
-
- case ISCSI_OP_LOGIN_CMD:
- /*
- * This is an illegal state transition. Should
- * we drop the connection?
- */
- break;
-
- case ISCSI_OP_TEXT_CMD:
- rval = handle_text_msg(c, &h, ahs, ahslen);
- break;
-
- case ISCSI_OP_SCSI_DATA:
- rval = handle_scsi_data(c, &h, ahs, ahslen);
- break;
-
- case ISCSI_OP_LOGOUT_CMD:
- /*
- * This will transition from S5_LOGGED_IN
- * to S6_IN_LOGOUT.
- */
- rval = handle_logout_msg(c, &h, ahs, ahslen);
- break;
-
- case ISCSI_OP_SNACK_CMD:
- default:
- (void) snprintf(debug, sizeof (debug),
- "CON%x Opcode: %d not handled",
- c->c_num, h.opcode & ISCSI_OPCODE_MASK);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug);
- conn_state(c, T8);
- rval = True;
- break;
- }
- }
-
- if (ahs != NULL)
- free(ahs);
- return (rval);
-}
-
-/*ARGSUSED*/
-static Boolean_t
-handle_task_mgt(iscsi_conn_t *c, iscsi_hdr_t *p, char *ahs, int ahslen)
-{
- iscsi_scsi_task_mgt_hdr_t *hp = (iscsi_scsi_task_mgt_hdr_t *)p;
- iscsi_scsi_task_mgt_rsp_hdr_t *rsp;
- iscsi_cmd_t *cmd;
- uint32_t lun;
- Boolean_t lu_reset = False;
-
- if (spc_decode_lu_addr(&hp->lun[0], 8, &lun) == False)
- return (False);
-
- if (ISCSI_TASK_COMMAND_ENABLED()) {
- uiscsiproto_t info;
-
- info.uip_target_addr = &c->c_target_sockaddr;
- info.uip_initiator_addr = &c->c_initiator_sockaddr;
-
- info.uip_target = c->c_sess->s_t_name;
- info.uip_initiator = c->c_sess->s_i_name;
- info.uip_lun = lun;
-
- info.uip_itt = hp->itt;
- info.uip_ttt = hp->itt;
-
- info.uip_cmdsn = ntohl(hp->cmdsn);
- info.uip_statsn = ntohl(hp->expstatsn);
- info.uip_datasn = ntohl(hp->expdatasn);
-
- info.uip_datalen = ntoh24(hp->dlength);
- info.uip_flags = 0;
-
- ISCSI_TASK_COMMAND(&info);
- }
-
- if ((rsp = calloc(1, sizeof (*rsp))) == NULL)
- return (False);
-
- rsp->opcode = ISCSI_OP_SCSI_TASK_MGT_RSP;
- rsp->flags = ISCSI_FLAG_FINAL;
- rsp->itt = hp->itt;
-
- (void) pthread_mutex_lock(&c->c_mutex);
- rsp->statsn = htonl(c->c_statsn++);
- (void) pthread_mutex_unlock(&c->c_mutex);
-
- (void) pthread_mutex_lock(&c->c_sess->s_mutex);
- if (ntohl(hp->cmdsn) > c->c_sess->s_seencmdsn)
- c->c_sess->s_seencmdsn = ntohl(hp->cmdsn);
- (void) pthread_mutex_unlock(&c->c_sess->s_mutex);
-
- queue_prt(c->c_mgmtq, Q_CONN_NONIO,
- "CON%x PDU(Task Mgt): %s, cmdsn 0x%x\n",
- c->c_num,
- task_to_str(hp->function & ISCSI_FLAG_TASK_MGMT_FUNCTION_MASK),
- ntohl(hp->cmdsn));
-
- switch (hp->function & ISCSI_FLAG_TASK_MGMT_FUNCTION_MASK) {
- case ISCSI_TM_FUNC_ABORT_TASK:
- queue_prt(c->c_mgmtq, Q_CONN_NONIO,
- "CON%x Abort ITT 0x%x\n", c->c_num, hp->rtt);
- if ((cmd = iscsi_cmd_find(c, hp->rtt, FindITT)) == NULL) {
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "CON%x Invalid AbortTask rtt 0x%x\n",
- c->c_num, hp->rtt);
- rsp->response = SCSI_TCP_TM_RESP_NO_TASK;
- } else {
- (void) pthread_mutex_lock(&c->c_mutex);
- iscsi_cmd_cancel(c, cmd);
- (void) pthread_mutex_unlock(&c->c_mutex);
- rsp->response = SCSI_TCP_TM_RESP_COMPLETE;
- }
- break;
-
- case ISCSI_TM_FUNC_ABORT_TASK_SET:
- /* ---- This is actually "Function not support" ---- */
- rsp->response = SCSI_TCP_TM_RESP_IN_PRGRESS;
- break;
-
- case ISCSI_TM_FUNC_CLEAR_ACA:
- /* ---- This is actually "Function not support" ---- */
- rsp->response = SCSI_TCP_TM_RESP_IN_PRGRESS;
- break;
-
- case ISCSI_TM_FUNC_CLEAR_TASK_SET:
- /* ---- This is actually "Function not support" ---- */
- rsp->response = SCSI_TCP_TM_RESP_IN_PRGRESS;
- break;
-
- case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
- lu_reset = True;
- /*FALLTHRU*/
- case ISCSI_TM_FUNC_TARGET_WARM_RESET:
- (void) pthread_mutex_lock(&c->c_mutex);
- for (cmd = c->c_cmd_head; cmd; cmd = cmd->c_next) {
- if (((hp->function &
- ISCSI_FLAG_TASK_MGMT_FUNCTION_MASK) ==
- ISCSI_TM_FUNC_TARGET_WARM_RESET) ||
- (lun == cmd->c_lun)) {
- iscsi_cmd_cancel(c, cmd);
-
- }
- }
- (void) pthread_mutex_unlock(&c->c_mutex);
-
- if (lu_reset == True)
- queue_message_set(c->c_sessq, 0, msg_reset_lu,
- (void *)(uintptr_t)lun);
- else
- queue_message_set(c->c_sessq, 0, msg_reset_targ, 0);
- rsp->response = SCSI_TCP_TM_RESP_COMPLETE;
- break;
-
- case ISCSI_TM_FUNC_TARGET_COLD_RESET:
- /*
- * According to the specification a cold reset should
- * close *all* connections on the target, not just those
- * for this current session.
- */
- queue_message_set(c->c_sessq, 0, msg_reset_targ, (void *)1);
- conn_state(c, T8);
- break;
-
- case ISCSI_TM_FUNC_TASK_REASSIGN:
- default:
- /* ---- This is actually "Function not support" ---- */
- rsp->response = SCSI_TCP_TM_RESP_IN_PRGRESS;
- break;
- }
-
- (void) pthread_mutex_lock(&c->c_state_mutex);
- if (c->c_state == S5_LOGGED_IN)
- queue_message_set(c->c_dataq,
- hp->opcode & ISCSI_OP_IMMEDIATE ? Q_HIGH : 0,
- msg_send_pkt, rsp);
- (void) pthread_mutex_unlock(&c->c_state_mutex);
- return (True);
-}
-
-/*ARGSUSED*/
-static Boolean_t
-handle_noop_cmd(iscsi_conn_t *c, iscsi_hdr_t *p, char *ahs, int ahslen)
-{
- iscsi_nop_out_hdr_t *hp = (iscsi_nop_out_hdr_t *)p;
- iscsi_nop_in_hdr_t *in;
-
- if (ISCSI_NOP_RECEIVE_ENABLED()) {
- uiscsiproto_t info;
-
- info.uip_target_addr = &c->c_target_sockaddr;
- info.uip_initiator_addr = &c->c_initiator_sockaddr;
-
- info.uip_target = c->c_sess->s_t_name;
- info.uip_initiator = c->c_sess->s_i_name;
- info.uip_lun = 0;
-
- info.uip_itt = hp->itt;
- info.uip_ttt = hp->ttt;
-
- info.uip_cmdsn = ntohl(hp->cmdsn);
- info.uip_statsn = ntohl(hp->expstatsn);
- info.uip_datasn = 0;
-
- info.uip_datalen = ntoh24(hp->dlength);
- info.uip_flags = hp->flags;
-
- ISCSI_NOP_RECEIVE(&info);
- }
-
- /*
- * Just an answer to our ping
- */
- if (hp->ttt != ISCSI_RSVD_TASK_TAG)
- return (True);
-
- if ((in = calloc(1, sizeof (*in))) == NULL) {
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "CON%x NopIn -- failed to malloc space for header",
- c->c_num);
- return (False);
- }
-
- in->opcode = ISCSI_OP_NOOP_IN;
- in->flags = ISCSI_FLAG_FINAL;
- /*
- * Need to handle possible data associated with NOP-Out
- */
- bcopy(hp->lun, in->lun, 8);
- in->itt = hp->itt;
- in->ttt = ISCSI_RSVD_TASK_TAG;
- (void) pthread_mutex_lock(&c->c_sess->s_mutex);
- if (ntohl(hp->cmdsn) > c->c_sess->s_seencmdsn)
- c->c_sess->s_seencmdsn = ntohl(hp->cmdsn);
- (void) pthread_mutex_unlock(&c->c_sess->s_mutex);
-
- (void) pthread_mutex_lock(&c->c_state_mutex);
- if (c->c_state == S5_LOGGED_IN)
- queue_message_set(c->c_dataq,
- hp->opcode & ISCSI_OP_IMMEDIATE ? Q_HIGH : 0,
- msg_send_pkt, in);
- (void) pthread_mutex_unlock(&c->c_state_mutex);
- return (True);
-}
-
-/*ARGSUSED*/
-static Boolean_t
-handle_scsi_data(iscsi_conn_t *c, iscsi_hdr_t *p, char *ahs, int ahslen)
-{
- iscsi_data_hdr_t *hp = (iscsi_data_hdr_t *)p;
- int dlen = ntoh24(hp->dlength);
- iscsi_cmd_t *cmd;
-
- if (ISCSI_DATA_RECEIVE_ENABLED()) {
- uiscsiproto_t info;
-
- info.uip_target_addr = &c->c_target_sockaddr;
- info.uip_initiator_addr = &c->c_initiator_sockaddr;
-
- info.uip_target = c->c_sess->s_t_name;
- info.uip_initiator = c->c_sess->s_i_name;
- info.uip_lun = 0;
-
- info.uip_itt = hp->itt;
- info.uip_ttt = hp->itt;
-
- info.uip_cmdsn = 0;
- info.uip_statsn = ntohl(hp->expstatsn);
- info.uip_datasn = ntohl(hp->datasn);
-
- info.uip_datalen = dlen;
- info.uip_flags = hp->flags;
-
- ISCSI_DATA_RECEIVE(&info);
- }
-
- if ((cmd = iscsi_cmd_find(c, hp->ttt, FindTTT)) == NULL) {
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "CON%x failed to find ttt 0x%x\n", c->c_num, hp->ttt);
- /*
- * Need to handle error case.
- */
- return (False);
- }
- cmd->c_opcode = hp->opcode & ISCSI_OPCODE_MASK;
-
- /*
- * assert(cmd->c_lun == hp->lun[1]);
- * Previously this check was done, but is caused a problem with
- * the RedHat initiator. There was a discussion on the IPS alias
- * around this very topic. Even though section 10.7.4 states:
- * "If the Target Transfer Tag is provided, then the LUN field
- * MUST hold a valid value and be consistent with whatever was
- * specified with the command; otherwise, the LUN field is
- * reserved."
- * Everyone agreed though that for a DataOut command the LUN field
- * wasn't required to be valid because the TTT gives the Target
- * enough information to complete the command.
- */
- assert(cmd->c_allegiance == c);
- assert(cmd->c_itt == hp->itt);
-
- cmd->c_offset_out = ntohl(hp->offset);
- cmd->c_data_len = dlen;
- (void) pthread_mutex_lock(&c->c_mutex);
- (void) pthread_mutex_lock(&c->c_state_mutex);
- if (c->c_state == S5_LOGGED_IN) {
- if (cmd->c_state != CmdCanceled) {
- t10_cmd_shoot_event(cmd->c_t10_cmd, T10_Cmd_T4);
- }
- }
- (void) pthread_mutex_unlock(&c->c_state_mutex);
- (void) pthread_mutex_unlock(&c->c_mutex);
-
-#ifdef FULL_DEBUG
- queue_prt(c->c_mgmtq, Q_CONN_IO,
- "CON%x PDU(DataOut) TTT 0x%x, offset=0x%x, len=0x%x\n",
- c->c_num, cmd->c_ttt, cmd->c_t10_cmd->c_offset, dlen);
-#endif
-
- return (dataout_delayed(cmd, msg_cmd_data_out));
-}
-
-static Boolean_t
-handle_scsi_cmd(iscsi_conn_t *c, iscsi_hdr_t *p, char *ahs, int ahslen)
-{
- iscsi_scsi_cmd_hdr_t *hp = (iscsi_scsi_cmd_hdr_t *)p;
- int dlen = ntoh24(hp->dlength);
- iscsi_cmd_t *cmd;
-
- (void) pthread_mutex_lock(&c->c_sess->s_mutex);
- if (ntohl(hp->cmdsn) > c->c_sess->s_seencmdsn)
- c->c_sess->s_seencmdsn = ntohl(hp->cmdsn);
- (void) pthread_mutex_unlock(&c->c_sess->s_mutex);
-
- if ((cmd = iscsi_cmd_alloc(c, hp->opcode & ISCSI_OPCODE_MASK)) == NULL)
- return (False);
-
- bcopy(hp->scb, cmd->c_scb_default, sizeof (cmd->c_scb_default));
- cmd->c_scb = cmd->c_scb_default;
- cmd->c_scb_len = sizeof (cmd->c_scb_default);
- cmd->c_data_len = dlen;
-
- if (ahslen) {
-
- /*
- * Additional Header Section ----
- *
- * For Object Storage Devices the SCB is quite large. On
- * the order of 140 bytes which means the data must be
- * found in the AHS.
- */
- uint16_t hslen;
- uint16_t next_seg;
- uint8_t hstyp;
-
- do {
- /*
- * Find this header segment's length and type
- */
- bcopy(ahs, &hslen, sizeof (hslen));
- hslen = ntohs(hslen);
- hstyp = ahs[2];
-
- switch (hstyp) {
- /* ---- Extended CDB ---- */
- case 1:
- /*
- * The hslen accounts for the reserved
- * data byte in the segment. So the first
- * sixteen bytes are in hp->scb with the
- * remainder here. By only adding 15 bytes
- * we allocate the correct amount of space
- */
- cmd->c_scb_extended = malloc(hslen + 15);
- cmd->c_scb_len = hslen + 15;
- if (cmd->c_scb_extended == NULL)
- return (False);
-
- /*
- * First 16 bytes of extended SCB are
- * found in the normal location.
- */
- bcopy(hp->scb, cmd->c_scb_extended, 16);
- bcopy(&ahs[4], &cmd->c_scb_extended[16],
- hslen - 16);
- cmd->c_scb = cmd->c_scb_extended;
- break;
-
- /* ---- Expected bidirectional read data len ---- */
- case 2:
- /*
- * We shouldn't need this since we're
- * not prealloc'ing resources. If that should
- * change or the need for error checking
- * here's the spot to locate the data.
- */
- break;
- }
-
- /*
- * hslen contains the effective length in bytes of
- * segment, excluding type and length (not including
- * padding). Each segment is padded to a 4 byte
- * boundary.
- */
- next_seg = ((hslen + sizeof (hslen) +
- sizeof (hstyp) + 3) & ~3);
- ahs += next_seg;
- ahslen -= next_seg;
-
- } while (ahslen);
- }
-
- /*
- * XXX Need to handle error case better.
- */
- if (spc_decode_lu_addr(&hp->lun[0], sizeof (hp->lun), &cmd->c_lun) ==
- False) {
- return (False);
- }
-
- if (ISCSI_SCSI_COMMAND_ENABLED()) {
- uiscsiproto_t info;
- uiscsicmd_t uc;
-
- info.uip_target_addr = &c->c_target_sockaddr;
- info.uip_initiator_addr = &c->c_initiator_sockaddr;
-
- info.uip_target = c->c_sess->s_t_name;
- info.uip_initiator = c->c_sess->s_i_name;
- info.uip_lun = cmd->c_lun;
-
- info.uip_itt = hp->itt;
- info.uip_ttt = ISCSI_RSVD_TASK_TAG;
-
- info.uip_cmdsn = ntohl(hp->cmdsn);
- info.uip_statsn = ntohl(hp->expstatsn);
- info.uip_datasn = 0;
-
- info.uip_datalen = dlen;
- info.uip_flags = hp->flags;
-
- uc.uic_len = cmd->c_scb_len;
- uc.uic_cdb = cmd->c_scb;
-
- ISCSI_SCSI_COMMAND(&info, &uc);
- }
-
- cmd->c_itt = hp->itt;
- cmd->c_cmdsn = ntohl(hp->cmdsn);
- cmd->c_dlen_expected = ntohl(hp->data_length);
- cmd->c_writeop = hp->flags & ISCSI_FLAG_CMD_WRITE ?
- True : False;
-
-#ifdef FULL_DEBUG
- queue_prt(c->c_mgmtq, Q_CONN_IO,
- "CON%x PDU(SCSI Cmd, TA=%d) CmdSN 0x%x ITT 0x%x TTT 0x%x "
- "LUN[%02x] id=%p\n", c->c_num,
- hp->flags & ISCSI_FLAG_CMD_ATTR_MASK, cmd->c_cmdsn, cmd->c_itt,
- cmd->c_ttt, cmd->c_lun, cmd);
-#endif
-
- if (dlen && (hp->flags & ISCSI_FLAG_CMD_WRITE)) {
- /*
- * NOTE: This should only occur if ImmediateData==Yes.
- * We can handle this even if the initiator violates
- * the specification so no need to worry. Use the rule
- * of "Be strict in what is sent, but lenient in what
- * is accepted."
- */
- return (dataout_delayed(cmd, msg_cmd_send));
- } else {
- (void) pthread_mutex_lock(&c->c_state_mutex);
- if (c->c_state == S5_LOGGED_IN)
- queue_message_set(c->c_sessq, 0,
- msg_cmd_send, (void *)cmd);
- (void) pthread_mutex_unlock(&c->c_state_mutex);
- return (True);
- }
-}
-
-/*
- * []----
- * | handle_text_msg -- process incoming test parameters
- * |
- * | NOTE: Need to handle continuation packets sent by the initiator.
- * []----
- */
-/*ARGSUSED*/
-static Boolean_t
-handle_text_msg(iscsi_conn_t *c, iscsi_hdr_t *p, char *ahs, int ahslen)
-{
- iscsi_text_rsp_hdr_t rsp;
- iscsi_text_hdr_t *hp = (iscsi_text_hdr_t *)p;
- char *text = NULL;
- int text_length = 0;
- Boolean_t release_at_end = False;
- int dlen = ntoh24(hp->dlength);
-
- if (ISCSI_TEXT_COMMAND_ENABLED()) {
- uiscsiproto_t info;
- char nil = '\0';
-
- info.uip_initiator = c->c_sess->s_i_name;
- info.uip_target_addr = &c->c_target_sockaddr;
- info.uip_initiator_addr = &c->c_initiator_sockaddr;
-
- info.uip_target = c->c_sess->s_t_name;
- info.uip_initiator = c->c_sess->s_i_name;
- info.uip_target = &nil;
- info.uip_lun = 0;
-
- info.uip_itt = hp->itt;
- info.uip_ttt = hp->ttt;
-
- info.uip_cmdsn = ntohl(hp->cmdsn);
- info.uip_statsn = ntohl(hp->expstatsn);
- info.uip_datasn = 0;
-
- info.uip_datalen = dlen;
- info.uip_flags = hp->flags;
-
- ISCSI_TEXT_COMMAND(&info);
- }
-
- bzero(&rsp, sizeof (rsp));
- rsp.opcode = ISCSI_OP_TEXT_RSP;
- rsp.itt = hp->itt;
-
- queue_prt(c->c_mgmtq, Q_CONN_NONIO, "CON%x PDU(Text Message)\n",
- c->c_num);
-
- /*
- * Need to determine if this incoming text PDU is an initial message
- * or a continuation.
- */
- if (hp->ttt == ISCSI_RSVD_TASK_TAG) {
-
- /* ---- Initial text PDU, so parse the incoming data ---- */
- if (parse_text(c, dlen, &text, &text_length, NULL) == False) {
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "Failed to parse Text\n");
- if (text) {
- /*
- * It's possible that we started to create
- * a response, but yet an error occurred.
- * Release the partial text response if that
- * occurred.
- */
- free(text);
- }
- return (False);
- }
-
- /*
- * 10.11.4 --
- * When the target receives a Text Request with the Target
- * Transfer Tag set to the reserved value of 0xffffffff, it
- * resets its internal information (resets state) associated
- * with the given Initiator Task Tag (restarts the negotiation).
- */
- if (c->c_text_area != NULL)
- free(c->c_text_area);
-
- c->c_text_area = text;
- if (text_length > c->c_max_recv_data) {
-
- /*
- * Too much data to send at once, break it up into
- * multiple transfers.
- */
- rsp.flags = ISCSI_FLAG_TEXT_CONTINUE;
- rsp.ttt = 1;
- c->c_text_len = text_length;
- text_length = c->c_max_recv_data;
- c->c_text_sent = text_length;
- } else {
- rsp.flags = ISCSI_FLAG_FINAL;
- rsp.ttt = ISCSI_RSVD_TASK_TAG;
- release_at_end = True;
- }
- } else {
-
- /* ---- Continuation of previous text request ---- */
- text_length = c->c_text_len - c->c_text_sent;
- text = c->c_text_area + c->c_text_sent;
- if (text_length > c->c_max_recv_data) {
- rsp.flags = ISCSI_FLAG_TEXT_CONTINUE;
- rsp.ttt = 1;
- text_length = c->c_max_recv_data;
- c->c_text_sent += text_length;
- } else {
- rsp.flags = ISCSI_FLAG_FINAL;
- rsp.ttt = ISCSI_RSVD_TASK_TAG;
- release_at_end = True;
- }
- }
-
- queue_prt(c->c_mgmtq, Q_CONN_NONIO,
- "CON%x Text PDU: flags=0x%02x, ttt=0x%08x, len=%d\n",
- c->c_num, rsp.flags, rsp.ttt, text_length);
-
- hton24(rsp.dlength, text_length);
- (void) pthread_mutex_lock(&c->c_mutex);
- rsp.statsn = htonl(c->c_statsn++);
- (void) pthread_mutex_lock(&c->c_sess->s_mutex);
- if (ntohl(hp->cmdsn) > c->c_sess->s_seencmdsn)
- c->c_sess->s_seencmdsn = ntohl(hp->cmdsn);
- rsp.maxcmdsn = htonl(iscsi_cmd_window(c) + c->c_sess->s_seencmdsn);
- rsp.expcmdsn = htonl(c->c_sess->s_seencmdsn + 1);
- (void) pthread_mutex_unlock(&c->c_sess->s_mutex);
- (void) pthread_mutex_unlock(&c->c_mutex);
-
- if (ISCSI_TEXT_RESPONSE_ENABLED()) {
- uiscsiproto_t info;
- char nil = '\0';
-
- info.uip_target_addr = &c->c_target_sockaddr;
- info.uip_initiator_addr = &c->c_initiator_sockaddr;
-
- info.uip_target = c->c_sess->s_t_name;
- info.uip_initiator = c->c_sess->s_i_name;
- info.uip_initiator = c->c_sess->s_i_name;
- info.uip_target = &nil;
- info.uip_lun = 0;
-
- info.uip_itt = rsp.itt;
- info.uip_ttt = rsp.ttt;
-
- info.uip_cmdsn = ntohl(rsp.expcmdsn);
- info.uip_statsn = ntohl(rsp.statsn);
- info.uip_datasn = 0;
-
- info.uip_datalen = text_length;
- info.uip_flags = rsp.flags;
-
- ISCSI_TEXT_RESPONSE(&info);
- }
-
- send_iscsi_pkt(c, (iscsi_hdr_t *)&rsp, text);
-
- if (release_at_end == True) {
- free(c->c_text_area);
- c->c_text_area = NULL;
- }
- return (True);
-}
-
-/*ARGSUSED*/
-static Boolean_t
-handle_logout_msg(iscsi_conn_t *c, iscsi_hdr_t *p, char *ahs, int ahslen)
-{
- iscsi_logout_rsp_hdr_t *rsp;
- iscsi_logout_hdr_t *hp = (iscsi_logout_hdr_t *)p;
- char debug[80];
-
- if (ISCSI_LOGOUT_COMMAND_ENABLED()) {
- uiscsiproto_t info;
- char nil = '\0';
-
- info.uip_target_addr = &c->c_target_sockaddr;
- info.uip_initiator_addr = &c->c_initiator_sockaddr;
-
- info.uip_target = c->c_sess->s_t_name;
- info.uip_initiator = c->c_sess->s_i_name;
- info.uip_initiator = c->c_sess->s_i_name;
- info.uip_target = &nil;
- info.uip_lun = 0;
-
- info.uip_itt = hp->itt;
- info.uip_ttt = ISCSI_RSVD_TASK_TAG;
-
- info.uip_cmdsn = ntohl(hp->cmdsn);
- info.uip_statsn = ntohl(hp->expstatsn);
- info.uip_datasn = 0;
-
- info.uip_datalen = ntoh24(hp->dlength);
- info.uip_flags = hp->flags;
-
- ISCSI_LOGOUT_COMMAND(&info);
- }
-
- if ((rsp = calloc(1, sizeof (*rsp))) == NULL)
- return (False);
-
- (void) snprintf(debug, sizeof (debug),
- "CON%x PDU(Logout Request)", c->c_num);
- queue_str(c->c_mgmtq, Q_CONN_NONIO, msg_log, debug);
-
- (void) pthread_mutex_lock(&c->c_mutex);
- (void) pthread_mutex_lock(&c->c_sess->s_mutex);
- if (hp->cmdsn > c->c_sess->s_seencmdsn)
- c->c_sess->s_seencmdsn = htonl(hp->cmdsn);
- rsp->expcmdsn = htonl(c->c_sess->s_seencmdsn + 1);
- rsp->maxcmdsn = htonl(iscsi_cmd_window(c) +
- c->c_sess->s_seencmdsn);
- (void) pthread_mutex_unlock(&c->c_sess->s_mutex);
- (void) pthread_mutex_unlock(&c->c_mutex);
-
- rsp->opcode = ISCSI_OP_LOGOUT_RSP;
- rsp->flags = ISCSI_FLAG_FINAL;
- rsp->itt = hp->itt;
- (void) pthread_mutex_lock(&c->c_mutex);
- rsp->statsn = htonl(c->c_statsn++);
- (void) pthread_mutex_unlock(&c->c_mutex);
-
- c->c_last_pkg = (iscsi_hdr_t *)rsp;
-
- /*
- * Call the state transition last. This will send out
- * an asynchronous message to shutdown the session and STE.
- * Once that's complete a shutdown reply will be sent to
- * the transmit connection thread. That will cause another
- * transition to T13 which expects to send out this logout
- * response.
- */
- if (c->c_state == S7_LOGOUT_REQUESTED)
- conn_state(c, T10);
- else
- conn_state(c, T9);
-
- return (True);
-}
-
-/*
- * dataout_delayed -- possibly copy data from initiator
- *
- * If DataDigests are enabled copy the data from the socket into a buffer
- * and perform the CRC check now.
- *
- * If MaxConnections==1 don't copy the data now and wait until the STE is
- * ready to copy the data directly from the socket to it's final location.
- * This is extremely beneficial when using mmap'd data.
- * NOTE:
- * (1) For this to work we must not use the queues and instead
- * call the STE functions directly. If the queues are used
- * this routine must pause until STE processes the data to
- * prevent this thread from attempting to read data from
- * the socket as if it's the next PDU header.
- * (2) Currently we don't call STE directly. To prevent a performance
- * issue we'll have the code in place to support calling
- * STE directly, but any time MaxConnections is greater than 0
- * we'll copy the buffer. This will be removed at some future
- * point.
- */
-static Boolean_t
-dataout_delayed(iscsi_cmd_t *cmd, msg_type_t type)
-{
- iscsi_conn_t *c = cmd->c_allegiance;
- int dlen = cmd->c_data_len;
- int cc;
- uint32_t crc_calc;
- uint32_t crc_actual;
- char pad_buf[ISCSI_PAD_WORD_LEN - 1];
- char pad_len;
- char debug[80];
-
- cmd->c_dataout_cb = dataout_callback;
-
- if (cmd->c_data == NULL) {
- if ((cmd->c_data = (char *)malloc(dlen)) == NULL) {
- (void) pthread_mutex_lock(&c->c_mutex);
- t10_cmd_shoot_event(cmd->c_t10_cmd, T10_Cmd_T5);
- iscsi_cmd_free(c, cmd);
- (void) pthread_mutex_unlock(&c->c_mutex);
- return (False);
- }
- cmd->c_data_alloc = True;
- }
-
- if ((cc = recv(c->c_fd, cmd->c_data, dlen, MSG_WAITALL)) != dlen) {
- if (errno == ECONNRESET) {
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "CON%x dataout_delayed -- "
- "initiator reset socket\n", c->c_num);
- } else {
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "CON%x recv(got-%d, expect-%d), errno=%d\n",
- c->c_num, cc, dlen, errno);
- }
-
- (void) pthread_mutex_lock(&c->c_mutex);
- t10_cmd_shoot_event(cmd->c_t10_cmd, T10_Cmd_T5);
- iscsi_cmd_free(c, cmd);
- (void) pthread_mutex_unlock(&c->c_mutex);
- conn_state(c, T8);
- return (True);
- }
-
- pad_len = ((ISCSI_PAD_WORD_LEN -
- (dlen & (ISCSI_PAD_WORD_LEN - 1))) & (ISCSI_PAD_WORD_LEN - 1));
-
- if (pad_len) {
- if (recv(c->c_fd, pad_buf, pad_len, MSG_WAITALL) != pad_len) {
- if (errno == ECONNRESET) {
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "CON%x dataout_delayed -- "
- "initiator reset socket\n", c->c_num);
- } else {
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "CON%x Pad Word read errno=%d\n", c->c_num,
- errno);
- }
-
- (void) pthread_mutex_lock(&c->c_mutex);
- t10_cmd_shoot_event(cmd->c_t10_cmd, T10_Cmd_T5);
- iscsi_cmd_free(c, cmd);
- (void) pthread_mutex_unlock(&c->c_mutex);
- conn_state(c, T8);
- return (True);
- }
- }
-
- if (c->c_data_digest == True) {
- if (recv(c->c_fd, (char *)&crc_actual, sizeof (crc_actual),
- MSG_WAITALL) != sizeof (crc_actual)) {
- if (errno == ECONNRESET) {
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "CON%x dataout_delayed -- "
- "initiator reset socket\n", c->c_num);
- } else {
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "CON%x CRC32 read errno=%d\n", c->c_num,
- errno);
- }
-
- (void) pthread_mutex_lock(&c->c_mutex);
- t10_cmd_shoot_event(cmd->c_t10_cmd, T10_Cmd_T5);
- iscsi_cmd_free(c, cmd);
- (void) pthread_mutex_unlock(&c->c_mutex);
- conn_state(c, T8);
- return (True);
- }
- crc_calc = iscsi_crc32c((void *)cmd->c_data, dlen);
- if (crc_calc != crc_actual) {
-
- (void) snprintf(debug, sizeof (debug),
- "CON%x CRC Error: actual %x vs. calc 0x%x",
- c->c_num, crc_actual, crc_calc);
-
- /*
- * NOTE: Need to think about this one some more.
- * Just because we get a data error doesn't mean
- * we should drop the connection. Look at the
- * spec and determine what's the appropriate
- * error recovery for this issue.
- */
- (void) pthread_mutex_lock(&c->c_mutex);
- t10_cmd_shoot_event(cmd->c_t10_cmd, T10_Cmd_T5);
- iscsi_cmd_free(c, cmd);
- (void) pthread_mutex_unlock(&c->c_mutex);
- conn_state(c, T8);
- return (True);
- }
- }
-
- /*
- * We'll update the offset with the amount of data that
- * has been received. During a SCSI response PDU this value
- * will be used to determine if there's an overrun condition.
- */
- cmd->c_offset_out += dlen;
-
- (void) pthread_mutex_lock(&c->c_mutex);
- (void) pthread_mutex_lock(&c->c_state_mutex);
- if (c->c_state == S5_LOGGED_IN) {
- if ((cmd->c_state == CmdCanceled) &&
- (type == msg_cmd_data_out))
- t10_cmd_shoot_event(cmd->c_t10_cmd, T10_Cmd_T5);
- else
- queue_message_set(c->c_sessq, 0, type, (void *)cmd);
- } else if (cmd->c_state == CmdCanceled) {
- t10_cmd_shoot_event(cmd->c_t10_cmd, T10_Cmd_T5);
- }
- (void) pthread_mutex_unlock(&c->c_state_mutex);
- (void) pthread_mutex_unlock(&c->c_mutex);
-
- /*
- * The else case here is if we're calling STE directly and the data
- * will be read from the socket when STE is ready for it.
- */
-
- return (True);
-}
-
-/*
- * []----
- * | dataout_callback -- copy data from socket to emulation buffer
- * []----
- */
-void
-dataout_callback(t10_cmd_t *t, char *data, size_t *xfer)
-{
- iscsi_cmd_t *cmd = (iscsi_cmd_t *)T10_TRANS_ID(t);
- iscsi_conn_t *c = cmd->c_allegiance;
- int dlen = cmd->c_data_len;
- int cc;
- char pad_buf[ISCSI_PAD_WORD_LEN - 1];
- char pad_len = 0;
-
- pad_len = ((ISCSI_PAD_WORD_LEN -
- (dlen & (ISCSI_PAD_WORD_LEN - 1))) &
- (ISCSI_PAD_WORD_LEN - 1));
-
-
- if (T10_DATA(t) != NULL) {
- assert(T10_DATA(t) == cmd->c_data);
- assert(cmd->c_data_alloc == True);
- free(T10_DATA(t));
- T10_DATA(t) = NULL;
- cmd->c_data = NULL;
- cmd->c_data_alloc = False;
- return;
- }
-
- if ((cc = recv(c->c_fd, data, dlen, MSG_WAITALL)) != dlen) {
- if (errno == ECONNRESET) {
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "CON%x data_callback -- initiator reset socket\n",
- c->c_num);
- } else {
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "CON%x recv(got-%d, expect-%d) errno=%d",
- c->c_num, cc, dlen, errno);
- }
-
- conn_state(c, T8);
- goto finish;
- }
-
- if (pad_len) {
- if (recv(c->c_fd, pad_buf, pad_len, MSG_WAITALL) != pad_len) {
- if (errno == ECONNRESET) {
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "CON%x data_callback -- "
- "initiator reset socket\n", c->c_num);
- } else {
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "CON%x data_callback -- "
- "pad read errno=%d\n", c->c_num, errno);
- }
- conn_state(c, T8);
- goto finish;
- }
- }
-
-finish:
- *xfer = cc;
- /* ---- Send msg that receive side of the connection can go ---- */
- (void) sema_post(&c->c_datain);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/iscsi_ffp.h b/usr/src/cmd/iscsi/iscsitgtd/iscsi_ffp.h
deleted file mode 100644
index 3b17fd3e9c..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_ffp.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _FEATURE_H
-#define _FEATURE_H
-
-#include <sys/types.h>
-#include "iscsi_conn.h"
-
-/*
- * The number of seconds that an initiator has to respond to our
- * asynchronous logout request before we just drop the connection.
- */
-#define ASYNC_LOGOUT_TIMEOUT 10
-
-Boolean_t iscsi_full_feature(iscsi_conn_t *c);
-
-uint32_t iscsi_crc32c(void *address, unsigned long length);
-uint32_t iscsi_crc32c_continued(void *address, unsigned long length,
- uint32_t crc);
-
-#endif /* _FEATURE_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/iscsi_login.c b/usr/src/cmd/iscsi/iscsitgtd/iscsi_login.c
deleted file mode 100644
index 1ca201fc40..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_login.c
+++ /dev/null
@@ -1,949 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <stdio.h>
-#include <strings.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <syslog.h>
-#include <sys/iscsi_protocol.h>
-#include <arpa/inet.h>
-#include <iscsitgt_impl.h>
-#include "queue.h"
-#include "iscsi_conn.h"
-#include "iscsi_sess.h"
-#include "iscsi_login.h"
-#include "iscsi_provider_impl.h"
-#include "utility.h"
-#include "target.h"
-#include "isns_client.h"
-
-typedef enum auth_action {
- LOGIN_NO_AUTH,
- LOGIN_AUTH,
- LOGIN_DROP
-} auth_action_t;
-
-/*
- * Forward declarations
- */
-static iscsi_login_rsp_hdr_t *make_login_response(iscsi_conn_t *c,
- iscsi_login_hdr_t *lhp);
-static void send_login_reject(iscsi_conn_t *c, iscsi_login_hdr_t *lhp,
- int err_code);
-static Boolean_t check_for_valid_I_T(iscsi_conn_t *c);
-static auth_action_t login_set_auth(iscsi_sess_t *s);
-
-/*
- * iscsi_null_callback - This callback may be used under certain
- * conditions when authenticating a target, but I'm not sure what
- * we need to do here.
- */
-/* ARGSUSED */
-static void
-iscsi_null_callback(void *user_handle, void *message_handle, int auth_status)
-{
-}
-
-/*
- * iscsi_find_key_value -
- */
-static int
-iscsi_find_key_value(char *param, char *ihp, char *pdu_end,
- char **value_start, char **value_end)
-{
- char *str = param;
- char *text = ihp;
- char *value = NULL;
-
- if (value_start)
- *value_start = NULL;
- if (value_end)
- *value_end = NULL;
-
- /*
- * make sure they contain the same bytes
- */
- while (*str) {
- if (text >= pdu_end) {
- return (0);
- }
- if (*text == '\0') {
- return (0);
- }
- if (*str != *text) {
- return (0);
- }
- str++;
- text++;
- }
-
- if ((text >= pdu_end) ||
- (*text == '\0') ||
- (*text != ISCSI_TEXT_SEPARATOR)) {
- return (0);
- }
-
- /*
- * find the value
- */
- value = text + 1;
-
- /*
- * find the end of the value
- */
- while ((text < pdu_end) && (*text))
- text++;
-
- if (value_start)
- *value_start = value;
- if (value_end)
- *value_end = text;
-
- return (1);
-}
-
-Boolean_t
-iscsi_handle_login_pkt(iscsi_conn_t *c)
-{
- iscsi_login_hdr_t lh;
- iscsi_login_rsp_hdr_t *rsp = NULL;
- Boolean_t rval = False;
- IscsiAuthClient *auth_client = NULL;
- char *text = NULL;
- char *end = NULL;
- char *text_rsp = NULL;
- char debug[128];
- int debug_status = 0;
- int errcode = 0;
- int text_length = 0;
- int keytype = 0;
- int transit = 0;
- int rc = 0;
- auth_action_t auth_action = LOGIN_DROP;
- tgt_node_t *tnode = NULL;
-
- if (read(c->c_fd, &lh, sizeof (lh)) != sizeof (lh)) {
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log,
- "Header to small");
- return (False);
- }
-
- if ((lh.opcode & ISCSI_OPCODE_MASK) != ISCSI_OP_LOGIN_CMD) {
- (void) snprintf(debug, sizeof (debug),
- "CON%x Wrong OP code for state (Got 0x%x, Expected 0x%x)",
- c->c_num, lh.opcode, ISCSI_OP_LOGIN_CMD);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug);
- send_login_reject(c, &lh,
- (ISCSI_STATUS_CLASS_INITIATOR_ERR << 8) |
- ISCSI_LOGIN_STATUS_INVALID_REQUEST);
- conn_state(c, T7);
- return (True);
- }
-
- if (ISCSI_LOGIN_COMMAND_ENABLED()) {
- uiscsiproto_t info;
- char nil = '\0';
-
- info.uip_target_addr = &c->c_target_sockaddr;
- info.uip_initiator_addr = &c->c_initiator_sockaddr;
-
- info.uip_target = &nil;
- info.uip_initiator = &nil;
- info.uip_lun = 0;
-
- info.uip_itt = lh.itt;
- info.uip_ttt = ISCSI_RSVD_TASK_TAG;
-
- info.uip_cmdsn = ntohl(lh.cmdsn);
- info.uip_statsn = ntohl(lh.expstatsn);
- info.uip_datasn = 0;
-
- info.uip_datalen = ntoh24(lh.dlength);
- info.uip_flags = lh.flags;
-
- ISCSI_LOGIN_COMMAND(&info);
- }
-
- if ((rval = session_alloc(c, lh.isid)) == False) {
- conn_state(c, T7);
- return (True);
- }
-
- connection_parameters_default(c);
-
- c->c_cid = ntohl(lh.cid);
- c->c_statsn = ntohl(lh.expstatsn);
-
- (void) pthread_mutex_lock(&c->c_sess->s_mutex);
- c->c_sess->s_cmdsn = ntohl(lh.cmdsn);
- c->c_sess->s_seencmdsn = ntohl(lh.cmdsn);
- (void) pthread_mutex_unlock(&c->c_sess->s_mutex);
-
- /*
- * Is this a new session or an attempt to add a connection to
- * an existing session.
- */
- if (ntohs(lh.tsid) != 0) {
-
- /* Multiple connections per session not handled right now */
- conn_state(c, T7);
- return (True);
- }
-
- if ((rsp = make_login_response(c, &lh)) == NULL) {
- (void) snprintf(debug, sizeof (debug),
- "CON%x Failed make_login_response", c->c_num);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug);
- return (False);
- }
- /* default is ISCSI_FLAG_LOGIN_TRANSIT, not good for login */
- rsp->flags = 0;
-
- if ((rsp->active_version < lh.min_version) ||
- (rsp->active_version > lh.max_version)) {
- (void) snprintf(debug, sizeof (debug),
- "CON%x Version: Active %d, min %d, max %d", c->c_num,
- rsp->active_version, lh.min_version, lh.max_version);
- send_login_reject(c, &lh,
- (ISCSI_STATUS_CLASS_INITIATOR_ERR << 8) |
- ISCSI_LOGIN_STATUS_NO_VERSION);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug);
- conn_state(c, T7);
- free(rsp);
- return (True);
- }
-
- if (lh.flags & ISCSI_FLAG_LOGIN_CONTINUE) {
- (void) snprintf(debug, sizeof (debug),
- "CON%x Continuation pkt", c->c_num);
- queue_str(c->c_mgmtq, Q_CONN_LOGIN, msg_log, debug);
- }
-
- auth_client =
- (c->c_sess->sess_auth.auth_buffers &&
- c->c_sess->sess_auth.num_auth_buffers) ?
- (IscsiAuthClient *) c->c_sess->sess_auth.auth_buffers[0].address :
- NULL;
-
- if (c->auth_text != NULL)
- free(c->auth_text);
- c->auth_text_length = 0;
-
- transit = lh.flags & ISCSI_FLAG_LOGIN_TRANSIT;
-
- switch (ISCSI_LOGIN_CURRENT_STAGE(lh.flags)) {
- case ISCSI_SECURITY_NEGOTIATION_STAGE:
-
- /*
- * Grab the parameters and create the response
- * text.
- */
- rval = parse_text(c, ntoh24(lh.dlength),
- &text_rsp, &text_length, &errcode);
- if (rval == False) {
- send_login_reject(c, &lh, errcode);
- (void) snprintf(debug, sizeof (debug),
- "CON%x SecurityNegotiation: parse_text"
- " failed", c->c_num);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug);
- conn_state(c, T7);
- break;
- }
-
- if ((rval = check_for_valid_I_T(c)) == False) {
- send_login_reject(c, &lh,
- (ISCSI_STATUS_CLASS_INITIATOR_ERR << 8) |
- ISCSI_LOGIN_STATUS_INIT_ERR);
- (void) snprintf(debug, sizeof (debug),
- "CON%x SecurityNegotiation: invalid I "
- "or T", c->c_num);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug);
- conn_state(c, T7);
- break;
- }
-
- auth_action = login_set_auth(c->c_sess);
-
- if (auth_action == LOGIN_NO_AUTH) {
- rsp->flags |= ISCSI_FLAG_LOGIN_TRANSIT;
- rsp->flags |= ISCSI_OP_PARMS_NEGOTIATION_STAGE;
- rval = add_text(&text_rsp, &text_length, "AuthMethod",
- "None");
- if (rval == False) {
- send_login_reject(c, &lh,
- (ISCSI_STATUS_CLASS_TARGET_ERR << 8) |
- ISCSI_LOGIN_STATUS_TARGET_ERROR);
- (void) snprintf(debug, sizeof (debug),
- "CON%x Norm: Failed to add AuthMethod=None",
- c->c_num);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log,
- debug);
- conn_state(c, T7);
- }
- break;
- }
-
- if (auth_action == LOGIN_DROP) {
- send_login_reject(c, &lh,
- (ISCSI_STATUS_CLASS_INITIATOR_ERR << 8) |
- ISCSI_LOGIN_STATUS_TGT_FORBIDDEN);
- (void) snprintf(debug, sizeof (debug),
- "CON%x SecurityNegotiation: access denied",
- c->c_num);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug);
- conn_state(c, T7);
- rval = False;
- break;
- }
-
- if (iscsiAuthClientRecvBegin(auth_client) !=
- iscsiAuthStatusNoError) {
- (void) snprintf(debug, sizeof (debug), "CON%x "
- "login failed - authentication receive failed",
- c->c_num);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug);
- break;
- }
-
- if (iscsiAuthClientRecvTransitBit(auth_client,
- transit) != iscsiAuthStatusNoError) {
- (void) snprintf(debug, sizeof (debug),
- "iscsi connection(%u) login failed - "
- "authentication transmit failed", c->c_num);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug);
- break;
- }
-
- /*
- * scan the text data
- */
- text = c->auth_text;
- end = text + c->auth_text_length;
-more_text:
- while (text && (text < end)) {
- char *value = NULL;
- char *value_end = NULL;
- keytype = iscsiAuthKeyTypeNone;
-
- /*
- * skip any NULs separating each text key=value pair
- */
- while ((text < end) && (*text == '\0')) {
- text++;
- }
- if (text >= end) {
- break;
- }
-
- while (iscsiAuthClientGetNextKeyType(&keytype) ==
- iscsiAuthStatusNoError) {
- char *key =
- (char *)iscsiAuthClientGetKeyName(keytype);
- if ((key) &&
- (iscsi_find_key_value(key, text, end,
- &value, &value_end))) {
- (void) snprintf(debug, sizeof (debug),
- "%s=%s", key, value);
- queue_str(c->c_mgmtq, Q_CONN_ERRS,
- msg_log, debug);
- if (iscsiAuthClientRecvKeyValue(
- auth_client, keytype, value)
- != iscsiAuthStatusNoError) {
- (void) snprintf(debug,
- sizeof (debug),
- "iscsi connection(%u) login"
- "failed - can't accept "
- "%s in security stage",
- c->c_num, text);
- queue_str(c->c_mgmtq,
- Q_CONN_ERRS,
- msg_log, debug);
- }
- text = value_end;
- goto more_text;
- }
- }
- }
-
- switch (iscsiAuthClientRecvEnd(auth_client, iscsi_null_callback,
- (void *)c->c_sess, NULL)) {
- case iscsiAuthStatusContinue:
- /*
- * continue sending PDUs
- */
- break;
-
- case iscsiAuthStatusPass:
- c->c_auth_pass = 1;
- break;
-
- case iscsiAuthStatusInProgress:
- /*
- * this should only occur if we were authenticating the
- * target, which we don't do yet, so treat this as an
- * error.
- */
- case iscsiAuthStatusNoError:
- /*
- * treat this as an error, since we should get a
- * different code
- */
- case iscsiAuthStatusError:
- case iscsiAuthStatusFail:
- default:
- debug_status = 0;
-
- (void) iscsiAuthClientGetDebugStatus(auth_client,
- &debug_status);
- (void) snprintf(debug, sizeof (debug),
- "iscsi connection(%u) authentication failed (%s)",
- c->c_num, iscsiAuthClientDebugStatusToText(
- debug_status));
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug);
-
- send_login_reject(c, &lh,
- (ISCSI_STATUS_CLASS_INITIATOR_ERR << 8) |
- ISCSI_LOGIN_STATUS_AUTH_FAILED);
- conn_state(c, T7);
- rval = False;
- break;
- }
-
- if (rval == False)
- break;
-
- keytype = iscsiAuthKeyTypeNone;
- rc = iscsiAuthClientSendTransitBit(auth_client, &transit);
-
- /*
- * see if we're ready for a stage change
- */
- if (rc == iscsiAuthStatusNoError) {
- if (transit) {
- rsp->flags = lh.flags;
- }
-
- } else {
- send_login_reject(c, &lh,
- (ISCSI_STATUS_CLASS_INITIATOR_ERR << 8) |
- ISCSI_LOGIN_STATUS_AUTH_FAILED);
- (void) snprintf(debug, sizeof (debug),
- "CON%x SecurityNegotiation: wants", c->c_num);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug);
- conn_state(c, T7);
- rval = False;
- }
-
- /*
- * enumerate all the keys the auth code might want to send
- */
- while (iscsiAuthClientGetNextKeyType(&keytype) ==
- iscsiAuthStatusNoError) {
- int present = 0;
- char *key = (char *)iscsiAuthClientGetKeyName(keytype);
- int key_length = key ? strlen(key) : 0;
- int pdu_length = ntoh24(rsp->dlength);
- char *auth_value = NULL;
- unsigned int max_length = ISCSI_DEFAULT_MAX_XMIT_SEG_LEN
- - (pdu_length + key_length + 1); /* FIXME: check */
-
- /*
- * add the key/value pairs the auth code wants to
- * send directly to the PDU, since they could in
- * theory be large.
- */
- if ((auth_value = (char *)malloc(max_length)) ==
- NULL) {
- send_login_reject(c, &lh,
- (ISCSI_STATUS_CLASS_TARGET_ERR << 8) |
- ISCSI_LOGIN_STATUS_TARGET_ERROR);
-
- (void) snprintf(debug, sizeof (debug),
- "CON%x Norm: Failed alloc auth_key %S=%s",
- c->c_num, key, auth_value);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log,
- debug);
- conn_state(c, T7);
- rval = False;
- break;
- }
- rc = iscsiAuthClientSendKeyValue(auth_client, keytype,
- &present, auth_value, max_length);
- if ((rc == iscsiAuthStatusNoError) && present) {
- (void) snprintf(debug, sizeof (debug),
- "key:%s, auth_value:%s\n", key, auth_value);
- queue_str(c->c_mgmtq, Q_CONN_LOGIN, msg_log,
- debug);
-
- rval = add_text(&text_rsp, &text_length,
- key, auth_value);
- if (rval == False) {
- send_login_reject(c, &lh,
- (ISCSI_STATUS_CLASS_TARGET_ERR <<
- 8) |
- ISCSI_LOGIN_STATUS_TARGET_ERROR);
- (void) snprintf(debug, sizeof (debug),
- "CON%x Norm: Failed to add %S=%s",
- c->c_num, key, auth_value);
- queue_str(c->c_mgmtq, Q_CONN_ERRS,
- msg_log, debug);
- conn_state(c, T7);
- }
- }
- if (auth_value != NULL)
- free(auth_value);
- }
-
- break;
-
- case ISCSI_OP_PARMS_NEGOTIATION_STAGE:
-
- /*
- * Gather up the parameters sent across and build a response
- * based on any selection required.
- */
- if ((rval = parse_text(c, ntoh24(lh.dlength), &text_rsp,
- &text_length, &errcode)) == False) {
-
- send_login_reject(c, &lh, errcode);
- (void) snprintf(debug, sizeof (debug),
- "CON%x Norm: parse_text failed", c->c_num);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug);
- conn_state(c, T7);
- break;
- }
-
- /*
- * If the connection hasn't passed authentication and
- * it's a normal session see if this connection MUST
- * have gone through authentication first. If the
- * initiator has a CHAP secret stored that means we
- * want to validate.
- */
- if ((c->c_auth_pass == 0) &&
- (c->c_sess->s_type == SessionNormal)) {
- if ((tnode = find_target_node(c->c_sess->s_t_name)) ==
- NULL) {
- send_login_reject(c, &lh,
- (ISCSI_STATUS_CLASS_TARGET_ERR << 8) |
- ISCSI_LOGIN_STATUS_TARGET_ERROR);
- (void) snprintf(debug, sizeof (debug),
- "CON%x No target node in login",
- c->c_num);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log,
- debug);
- conn_state(c, T7);
- }
-
- /*
- * check_access will return True if the initiator
- * is required to use CHAP authentication. So if
- * true and we're here it means that the initiator
- * is trying to skip the authentication step.
- */
- if (check_access(tnode, c->c_sess->s_i_name, True) ==
- False) {
- send_login_reject(c, &lh,
- (ISCSI_STATUS_CLASS_INITIATOR_ERR << 8) |
- ISCSI_LOGIN_STATUS_AUTH_FAILED);
- (void) snprintf(debug, sizeof (debug),
- "CON%x Authentication required for %s",
- c->c_num, c->c_sess->s_i_name);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log,
- debug);
- conn_state(c, T7);
- }
- }
-
- if ((rval = check_for_valid_I_T(c)) == False) {
- send_login_reject(c, &lh,
- (ISCSI_STATUS_CLASS_INITIATOR_ERR << 8) |
- ISCSI_LOGIN_STATUS_INIT_ERR);
-
- (void) snprintf(debug, sizeof (debug),
- "CON%x Norm: bad I or T", c->c_num);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug);
- conn_state(c, T7);
- break;
- }
-
- /*
- * We accept transition and stage information as is
- * and echo it back because at this point there's no need
- * to send a parameter to the Initiator and expect a
- * reply.
- */
- rsp->flags = lh.flags;
-
- break;
-
- case ISCSI_FULL_FEATURE_PHASE:
- /* can't jump directly to full feature phase */
- (void) snprintf(debug, sizeof (debug),
- "CON%x Protocol error: wrong stage", c->c_num);
- queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug);
- send_login_reject(c, &lh,
- (ISCSI_STATUS_CLASS_INITIATOR_ERR << 8) |
- ISCSI_LOGIN_STATUS_INIT_ERR);
- conn_state(c, T7);
- rval = False;
- break;
-
- default:
- /* just drop the connection since we don't know what's up */
- rval = False;
- break;
- }
-
- hton24(rsp->dlength, text_length);
- if ((rval == True) && (session_validate(c->c_sess) == True)) {
-
- if (ISCSI_LOGIN_RESPONSE_ENABLED()) {
- uiscsiproto_t info;
- char nil = '\0';
-
- info.uip_target_addr = &c->c_target_sockaddr;
- info.uip_initiator_addr = &c->c_initiator_sockaddr;
-
- info.uip_target = &nil;
- info.uip_initiator = c->c_sess->s_i_name;
- info.uip_lun = 0;
-
- info.uip_itt = rsp->itt;
- info.uip_ttt = ISCSI_RSVD_TASK_TAG;
-
- info.uip_cmdsn = ntohl(rsp->expcmdsn);
- info.uip_statsn = ntohl(rsp->statsn);
- info.uip_datasn = 0;
-
- info.uip_datalen = text_length;
- info.uip_flags = rsp->flags;
-
- ISCSI_LOGIN_RESPONSE(&info);
- }
-
- send_iscsi_pkt(c, (iscsi_hdr_t *)rsp, text_rsp);
-
- if ((lh.flags & ISCSI_FLAG_LOGIN_TRANSIT) &&
- (ISCSI_LOGIN_NEXT_STAGE(lh.flags) ==
- ISCSI_FULL_FEATURE_PHASE)) {
-
- conn_state(c, T5);
-
- /*
- * At this point we've completed the negotiation
- * of all login parameters. Now we need to perform
- * some quick boundary checks and then send a couple
- * pieces of information to STE for it's use.
- */
- c->c_max_burst_len = MIN(c->c_max_burst_len,
- c->c_max_recv_data);
- }
- }
-
- if (text_rsp != NULL)
- free(text_rsp);
- if (rsp != NULL)
- free(rsp);
-
- return (rval);
-}
-
-/*
- * check_for_valid_I_T -- check to see if we have valid names
- *
- * This routine checks to see if we have received a valid InitiatorName
- * and TargetName which is the bare minimum which an Initiator must send
- * across during the login phase.
- */
-static Boolean_t
-check_for_valid_I_T(iscsi_conn_t *c)
-{
- iscsi_sess_t *s = c->c_sess;
- if (s->s_type == SessionDiscovery)
- return (s->s_i_name == NULL || strlen(s->s_i_name) == 0) ?
- False : True;
- else
- return (s->s_t_name == NULL || strlen(s->s_t_name) == 0) ||
- (s->s_i_name == NULL || strlen(s->s_i_name) == 0) ?
- False : True;
-}
-
-static iscsi_login_rsp_hdr_t *
-make_login_response(iscsi_conn_t *c, iscsi_login_hdr_t *lhp)
-{
- iscsi_login_rsp_hdr_t *r;
-
- if (lhp->tsid != 0)
- /* don't except existing sessions for now */
- return (NULL);
-
- r = (iscsi_login_rsp_hdr_t *)calloc(sizeof (*r), sizeof (char));
- if (r == NULL)
- return (NULL);
-
- bcopy(lhp->isid, r->isid, 6); /* 6 is defined by protocol */
- r->opcode = ISCSI_OP_LOGIN_RSP;
- r->flags = ISCSI_FLAG_LOGIN_TRANSIT;
- r->max_version = ISCSI_MAX_VERSION;
- r->active_version = ISCSI_MIN_VERSION;
- r->itt = lhp->itt;
-
- /*
- * As per section 10.13.3 of iSCSI RFC (3720), For a new session,
- * the target MUST generate a non-zero TSIH and ONLY return it
- * in the Login Final-Response
- */
- if ((lhp->flags & ISCSI_FLAG_LOGIN_TRANSIT) &&
- (ISCSI_LOGIN_NEXT_STAGE(lhp->flags) ==
- ISCSI_FULL_FEATURE_PHASE))
- /*
- * If this is the final Login Response, send the target
- * calculated TSIH
- */
- r->tsid = htons(c->c_sess->s_tsid);
- else
- /*
- * If this is not the final Login Response, send the TSIH value
- * provided by the initiator.
- */
- r->tsid = lhp->tsid;
-
- (void) pthread_mutex_lock(&c->c_mutex);
- r->statsn = htonl(c->c_statsn++);
- (void) pthread_mutex_unlock(&c->c_mutex);
- if (c->c_sess != NULL) {
- (void) pthread_mutex_lock(&c->c_sess->s_mutex);
- /* ---- cmdsn is not advanced during login ---- */
- r->expcmdsn = htonl(c->c_sess->s_seencmdsn);
- r->maxcmdsn = htonl(CMD_MAXOUTSTANDING +
- c->c_sess->s_seencmdsn);
- (void) pthread_mutex_unlock(&c->c_sess->s_mutex);
- }
-
- return (r);
-}
-
-static void
-send_login_reject(iscsi_conn_t *c, iscsi_login_hdr_t *lhp, int err_code)
-{
- iscsi_login_rsp_hdr_t *r;
-
- if ((r = make_login_response(c, lhp)) == NULL)
- return;
-
- r->status_class = (err_code >> 8) & 0xff;
- r->status_detail = err_code & 0xff;
-
- if (ISCSI_LOGIN_RESPONSE_ENABLED()) {
- uiscsiproto_t info;
- char nil = '\0';
-
- info.uip_target_addr = &c->c_target_sockaddr;
- info.uip_initiator_addr = &c->c_initiator_sockaddr;
-
- info.uip_target = &nil;
- info.uip_initiator = &nil;
- info.uip_lun = 0;
-
- info.uip_itt = r->itt;
- info.uip_ttt = ISCSI_RSVD_TASK_TAG;
-
- info.uip_cmdsn = ntohl(r->expcmdsn);
- info.uip_statsn = ntohl(r->statsn);
- info.uip_datasn = 0;
-
- info.uip_datalen = ntoh24(r->dlength);
- info.uip_flags = r->flags;
-
- ISCSI_LOGIN_RESPONSE(&info);
- }
-
- (void) write(c->c_fd, r, sizeof (*r));
- free(r);
-}
-
-static auth_action_t
-login_set_auth(iscsi_sess_t *s)
-{
- tgt_node_t *xnInitiator = NULL;
- tgt_node_t *xnTarget = NULL;
- tgt_node_t *xnAcl = NULL;
- char *szIniAlias = NULL;
- char *szIscsiName = NULL;
- char *szChapName = NULL;
- char *szChapSecret = NULL;
- char *possible = NULL;
- iscsi_auth_t *sess_auth = &(s->sess_auth);
- int comp = 0;
- int username_len = 0;
-
- bzero(sess_auth->username_in, sizeof (sess_auth->username_in));
- bzero(sess_auth->password_in, sizeof (sess_auth->password_in));
- sess_auth->password_length_in = 0;
-
- /* Load alias, iscsi-name, chap-name, chap-secret from config file */
- while ((xnInitiator = tgt_node_next_child(main_config, XML_ELEMENT_INIT,
- xnInitiator)) != NULL) {
-
- (void) tgt_find_value_str(xnInitiator, XML_ELEMENT_INIT,
- &szIniAlias);
-
- if (tgt_find_value_str(xnInitiator, XML_ELEMENT_INAME,
- &szIscsiName) == True) {
-
- comp = strcmp(s->s_i_name, szIscsiName);
- free(szIscsiName);
- szIscsiName = NULL;
-
- if (comp == 0) {
-
- if (tgt_find_value_str(xnInitiator,
- XML_ELEMENT_CHAPNAME,
- &szChapName) == True) {
- /*CSTYLED*/
- (void) strcpy(
- (char *)sess_auth->username_in,
- szChapName);
- username_len = strlen(szChapName);
- free(szChapName);
- }
-
- if (tgt_find_value_str(xnInitiator,
- XML_ELEMENT_CHAPSECRET,
- &szChapSecret) == True) {
- /*CSTYLED*/
- (void) strcpy(
- (char *)sess_auth->password_in,
- szChapSecret);
- sess_auth->password_length_in =
- strlen(szChapSecret);
- free(szChapSecret);
- }
- break;
- }
- }
- }
-
- if (s->s_type == SessionDiscovery) {
- return (LOGIN_NO_AUTH);
- }
-
- if (s->s_t_name == NULL) {
- /*
- * Should not happen for non-discovery session
- */
- return (LOGIN_DROP);
- }
-
- /*
- * If iSNS enabled set LOGIN_AUTH
- */
- if (isns_enabled() == True) {
- if (username_len == 0)
- return (LOGIN_NO_AUTH);
- return (LOGIN_AUTH);
- }
-
- /*
- * If no acc_list for current target
- * If no CHAP secret for the initiator, transit.
- * If CHAP secret exists for the initiator, it must be authed.
- * If acc_list exists for the target, and
- * If the initiator not in the list, drop it.
- * If the initiator in the list, and
- * If no CHAP name for the initiator, transit.
- * If a CHAP name exists for the initiator, it must be authed.
- */
-
- while ((xnTarget = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
- xnTarget)) != NULL) {
-
- if ((tgt_find_value_str(xnTarget, XML_ELEMENT_INAME,
- &szIscsiName) == False) || (szIscsiName == NULL)) {
- return (LOGIN_DROP);
- }
-
- comp = strcmp(szIscsiName, s->s_t_name);
- free(szIscsiName);
- szIscsiName = NULL;
-
- if (comp == 0) {
-
- if ((xnAcl = tgt_node_next(xnTarget,
- XML_ELEMENT_ACLLIST, 0)) == NULL) {
- /*
- * No acl_list found, return auth or no auth
- */
- if (username_len == 0)
- return (LOGIN_NO_AUTH);
- return (LOGIN_AUTH);
- }
-
- /*
- * This target has an access_list. Now compare
- * those entries against the initiator who started
- * this session.
- */
- xnInitiator = NULL;
- while ((xnInitiator = tgt_node_next(xnAcl,
- XML_ELEMENT_INIT, xnInitiator)) != NULL) {
-
- if ((tgt_find_value_str(xnInitiator,
- XML_ELEMENT_INIT, &possible) == False) ||
- (possible == NULL))
- continue;
-
- if (strcmp(szIniAlias, possible) == 0) {
- /*
- * Found the initiator in acl-list,
- * authentication needed
- */
- free(possible);
- if (username_len == 0)
- return (LOGIN_NO_AUTH);
- else
- return (LOGIN_AUTH);
- }
-
- free(possible);
- possible = NULL;
- }
- /*
- * Acl-list exists, while the initiator is not found in
- * the list, we should drop the connection
- */
- return (LOGIN_DROP);
- }
- }
-
- /* False means Need authentication */
- return (LOGIN_AUTH);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/iscsi_login.h b/usr/src/cmd/iscsi/iscsitgtd/iscsi_login.h
deleted file mode 100644
index 846b23521e..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_login.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _LOGIN_H
-#define _LOGIN_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-Boolean_t iscsi_handle_login_pkt(iscsi_conn_t *c);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _LOGIN_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/iscsi_provider.d b/usr/src/cmd/iscsi/iscsitgtd/iscsi_provider.d
deleted file mode 100644
index 66eeaa03e2..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_provider.d
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-typedef struct uiscsiproto {
- int dummy;
-} uiscsiproto_t;
-
-typedef struct conninfo {
- int dummy;
-} conninfo_t;
-
-typedef struct iscsiinfo {
- int dummy;
-} iscsiinfo_t;
-
-translator conninfo_t < uiscsiproto_t *P > {
- dummy = P->dummy;
-};
-
-translator iscsiinfo_t < uiscsiproto_t *P > {
- dummy = P->dummy;
-};
-
-typedef struct uiscsicmd {
- int dummy;
-} uiscsicmd_t;
-
-typedef struct iscsicmd {
- int dummy;
-} iscsicmd_t;
-
-translator iscsicmd_t < uiscsicmd_t *P > {
- dummy = P->dummy;
-};
-
-provider iscsi {
- probe async__send(uiscsiproto_t *i) :
- (conninfo_t *i, iscsiinfo_t *i);
-
- probe login__command(uiscsiproto_t *i) :
- (conninfo_t *i, iscsiinfo_t *i);
- probe login__response(uiscsiproto_t *i) :
- (conninfo_t *i, iscsiinfo_t *i);
-
- probe logout__command(uiscsiproto_t *i) :
- (conninfo_t *i, iscsiinfo_t *i);
- probe logout__response(uiscsiproto_t *i) :
- (conninfo_t *i, iscsiinfo_t *i);
-
- probe data__receive(uiscsiproto_t *i) :
- (conninfo_t *i, iscsiinfo_t *i);
- probe data__request(uiscsiproto_t *i) :
- (conninfo_t *i, iscsiinfo_t *i);
- probe data__send(uiscsiproto_t *i) :
- (conninfo_t *i, iscsiinfo_t *i);
-
- probe nop__receive(uiscsiproto_t *i) :
- (conninfo_t *i, iscsiinfo_t *i);
- probe nop__send(uiscsiproto_t *i) :
- (conninfo_t *i, iscsiinfo_t *i);
-
- probe scsi__command(uiscsiproto_t *i, uiscsicmd_t *c) :
- (conninfo_t *i, iscsiinfo_t *i, iscsicmd_t *c);
- probe scsi__response(uiscsiproto_t *i) :
- (conninfo_t *i, iscsiinfo_t *i);
-
- probe task__command(uiscsiproto_t *i) :
- (conninfo_t *i, iscsiinfo_t *i);
- probe task__response(uiscsiproto_t *i) :
- (conninfo_t *i, iscsiinfo_t *i);
-
- probe text__command(uiscsiproto_t *i) :
- (conninfo_t *i, iscsiinfo_t *i);
- probe text__response(uiscsiproto_t *i) :
- (conninfo_t *i, iscsiinfo_t *i);
-};
-
-#pragma D attributes Evolving/Evolving/ISA provider iscsi provider
-#pragma D attributes Private/Private/Unknown provider iscsi module
-#pragma D attributes Private/Private/Unknown provider iscsi function
-#pragma D attributes Private/Private/ISA provider iscsi name
-#pragma D attributes Evolving/Evolving/ISA provider iscsi args
diff --git a/usr/src/cmd/iscsi/iscsitgtd/iscsi_provider_impl.h b/usr/src/cmd/iscsi/iscsitgtd/iscsi_provider_impl.h
deleted file mode 100644
index c7e41d68cd..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_provider_impl.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _ISCSI_PROVIDER_IMPL_H
-#define _ISCSI_PROVIDER_IMPL_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <sys/socket_impl.h>
-#include <sys/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct sockaddr_storage uiscsicn_t;
-
-typedef struct uiscsiproto {
- struct sockaddr_storage *uip_target_addr; /* target address */
- struct sockaddr_storage *uip_initiator_addr; /* initiator address */
- char *uip_target; /* target IQN */
- char *uip_initiator; /* initiator IQN */
- uint64_t uip_lun; /* target logical unit number */
-
- uint32_t uip_itt; /* initiator task tag */
- uint32_t uip_ttt; /* target transfer tag */
-
- uint32_t uip_cmdsn; /* command sequence number */
- uint32_t uip_statsn; /* status sequence number */
- uint32_t uip_datasn; /* data sequence number */
-
- uint32_t uip_datalen; /* length of data payload */
- uint32_t uip_flags; /* probe-specific flags */
-} uiscsiproto_t;
-
-typedef struct uiscsicmd {
- uint64_t uic_len; /* CDB length */
- uint8_t *uic_cdb; /* CDB data */
-} uiscsicmd_t;
-
-#ifdef __cplusplus
-}
-#endif
-
-#include "iscsi_provider.h"
-
-#endif /* _ISCSI_PROVIDER_IMPL_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/iscsi_sess.c b/usr/src/cmd/iscsi/iscsitgtd/iscsi_sess.c
deleted file mode 100644
index 63a14288c8..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_sess.c
+++ /dev/null
@@ -1,785 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <stdio.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <syslog.h>
-
-#include <iscsitgt_impl.h>
-#include "iscsi_conn.h"
-#include "iscsi_sess.h"
-#include "t10.h"
-#include "utility.h"
-#include "target.h"
-
-pthread_mutex_t sess_mutex;
-/*
- * This value is used as the TSIH which must be non-zero.
- */
-int sess_num = 1;
-iscsi_sess_t *sess_head;
-
-static void session_free(struct iscsi_sess *s);
-static void sess_set_auth(iscsi_sess_t *isp);
-static void *sess_from_t10(void *v);
-static void *sess_process(void *v);
-
-/*
- * []----
- * | session_init -- initialize global variables and mutexs
- * []----
- */
-void
-session_init()
-{
- (void) pthread_mutex_init(&sess_mutex, NULL);
-}
-
-/*
- * []----
- * | session_alloc -- create a new session attached to the lead connection
- * []----
- */
-Boolean_t
-session_alloc(iscsi_conn_t *c, uint8_t *isid)
-{
- iscsi_sess_t *s, *n;
-
- if (c->c_sess != NULL)
- return (True);
-
- s = (iscsi_sess_t *)calloc(sizeof (iscsi_sess_t), 1);
- if (s == NULL)
- return (False);
-
- bcopy(isid, s->s_isid, 6);
-
- (void) pthread_mutex_init(&s->s_mutex, NULL);
- c->c_sess = s;
- s->s_conn_head = c;
- s->s_sessq = queue_alloc();
- s->s_t10q = queue_alloc();
- c->c_sessq = s->s_sessq;
- s->s_mgmtq = c->c_mgmtq;
- s->s_type = SessionNormal;
-
- sess_set_auth(s);
-
- (void) pthread_mutex_lock(&sess_mutex);
- s->s_num = sess_num++;
- s->s_tsid = s->s_num;
- s->s_state = SS_STARTED;
-
- if (sess_head == NULL)
- sess_head = s;
- else {
- for (n = sess_head; n->s_next; n = n->s_next)
- ;
- n->s_next = s;
- }
- (void) pthread_mutex_unlock(&sess_mutex);
-
- (void) pthread_create(&s->s_thr_id_t10, NULL, sess_from_t10, s);
- (void) pthread_create(&s->s_thr_id_conn, NULL, sess_process, s);
-
- util_title(s->s_mgmtq, Q_SESS_LOGIN, s->s_num, "Start Session");
-
- return (True);
-}
-
-/*
- * []----
- * | session_free -- remove connection from session
- * []----
- */
-static void
-session_free(iscsi_sess_t *s)
-{
- iscsi_sess_t *n;
-
- /*
- * Early errors in connection setup can still call this routine
- * which means the session hasn't been called.
- */
- if (s == NULL)
- return;
-
- (void) pthread_mutex_lock(&sess_mutex);
- if (s->s_i_name)
- free(s->s_i_name);
- if (s->s_t_name)
- free(s->s_t_name);
- if (s->s_i_alias)
- free(s->s_i_alias);
-
- if (sess_head == s)
- sess_head = s->s_next;
- else {
- for (n = sess_head; n; n = n->s_next) {
- if (n->s_next == s) {
- n->s_next = s->s_next;
- break;
- }
- }
- if (n == NULL) {
- queue_prt(s->s_mgmtq, Q_SESS_ERRS,
- "SES%x NOT IN SESSION LIST!\n", s->s_num);
- }
- }
- (void) pthread_mutex_unlock(&sess_mutex);
-}
-
-/*
- * []----
- * | session_remove_connection -- removes conn from sess list
- * |
- * | Returns True if this was the last connection which is always the case
- * | for now. In the future with multiple connections per session it'll be
- * | different.
- * []----
- */
-/*ARGSUSED*/
-static Boolean_t
-session_remove_connection(iscsi_sess_t *s, iscsi_conn_t *c)
-{
- bzero(s->s_isid, 6);
- return (True);
-}
-
-/*
- * []----
- * | convert_i_local -- Return a local name for the initiator if avilable.
- * |
- * | NOTE: If this routine returns true, it's the callers responsibility
- * | to free the memory.
- * []----
- */
-Boolean_t
-convert_i_local(char *ip, char **rtn)
-{
- tgt_node_t *inode = NULL;
- char *iname, *name;
-
- while ((inode = tgt_node_next_child(main_config, XML_ELEMENT_INIT,
- inode)) != NULL) {
- if (tgt_find_value_str(inode, XML_ELEMENT_INAME, &iname) ==
- False) {
- continue;
- }
- if (strcmp(iname, ip) == 0) {
- if (tgt_find_value_str(inode, XML_ELEMENT_INIT,
- &name) == False) {
- free(iname);
- return (False);
- } else
- free(iname);
- *rtn = name;
- return (True);
- } else
- free(iname);
- }
- return (False);
-}
-
-/*
- * []----
- * | sess_from_t10 -- handle messages from the T10 layer
- * []----
- */
-void *
-sess_from_t10(void *v)
-{
- iscsi_sess_t *s = (iscsi_sess_t *)v;
- msg_t *m;
- Boolean_t process = True;
- t10_conn_shutdown_t t_c_s;
- Boolean_t sent_wait_for_destroy = False;
-
- t_c_s.t10_to_conn_q = NULL;
- t_c_s.conn_to_t10_q = NULL;
-
- while (process == True) {
- m = queue_message_get(s->s_t10q);
- switch (m->msg_type) {
- case msg_cmd_data_rqst:
- queue_message_set(s->s_conn_head->c_dataq, 0,
- msg_cmd_data_rqst, m->msg_data);
- break;
-
- case msg_cmd_data_in:
- queue_message_set(s->s_conn_head->c_dataq, 0,
- msg_cmd_data_in, m->msg_data);
- break;
-
- case msg_cmd_cmplt:
- queue_message_set(s->s_conn_head->c_dataq, 0,
- msg_cmd_cmplt, m->msg_data);
- break;
-
- case msg_shutdown_rsp:
-
- if (s->s_t10) {
- if (!sent_wait_for_destroy) {
- if (t_c_s.t10_to_conn_q == NULL) {
- t_c_s.t10_to_conn_q =
- queue_alloc();
- if (t_c_s.t10_to_conn_q
- == NULL) {
- queue_message_set(
- s->s_t10q, 0,
- msg_shutdown_rsp,
- m->msg_data);
- break;
- }
- }
- if (t_c_s.conn_to_t10_q == NULL) {
- t_c_s.conn_to_t10_q =
- queue_alloc();
- if (t_c_s.conn_to_t10_q ==
- NULL) {
- queue_message_set(
- s->s_t10q, 0,
- msg_shutdown_rsp,
- m->msg_data);
- break;
- }
- }
- queue_message_set(
- s->s_conn_head->c_dataq, 0,
- msg_wait_for_destroy,
- (void *)&t_c_s);
- queue_message_free(queue_message_get(
- t_c_s.conn_to_t10_q));
- sent_wait_for_destroy = True;
- }
-
- if (t10_handle_destroy(s->s_t10, False) != 0) {
- /*
- * Destroy couldn't complete,
- * put the message back on our
- * own queue to be picked up
- * later and tried again.
- */
- queue_message_set(s->s_t10q, 0,
- msg_shutdown_rsp,
- m->msg_data);
- break;
- }
- s->s_t10 = NULL;
- queue_message_set(t_c_s.t10_to_conn_q,
- 0, 1, (void *)NULL);
- queue_message_free(queue_message_get(
- t_c_s.conn_to_t10_q));
- queue_free(t_c_s.t10_to_conn_q, NULL);
- queue_free(t_c_s.conn_to_t10_q, NULL);
- sent_wait_for_destroy = False;
- }
-
- (void) pthread_mutex_lock(&s->s_mutex);
- s->s_state = SS_SHUTDOWN_CMPLT;
- (void) pthread_mutex_unlock(&s->s_mutex);
-
- session_free(s);
-
- /*
- * Let the connection, which is the last, know
- * about our completion of the shutdown.
- */
- queue_message_set(s->s_conn_head->c_dataq, 0,
- msg_shutdown_rsp, (void *)True);
- process = False;
- s->s_state = SS_FREE;
- break;
-
- default:
- queue_prt(s->s_mgmtq, Q_SESS_ERRS,
- "SES%x Unknown msg type (%d) from T10\n",
- s->s_num, m->msg_type);
- queue_message_set(s->s_conn_head->c_dataq, 0,
- m->msg_type, m->msg_data);
- break;
- }
- queue_message_free(m);
- }
- queue_message_set(s->s_mgmtq, 0, msg_pthread_join,
- (void *)(uintptr_t)pthread_self());
- queue_free(s->s_t10q, NULL);
- util_title(s->s_mgmtq, Q_SESS_LOGIN, s->s_num, "End Session");
- free(s);
- return (NULL);
-}
-
-/*
- * []----
- * | sess_process -- handle messages from the connection(s)
- * []----
- */
-static void *
-sess_process(void *v)
-{
- iscsi_sess_t *s = (iscsi_sess_t *)v;
- iscsi_conn_t *c;
- iscsi_cmd_t *cmd;
- msg_t *m;
- Boolean_t process = True;
- mgmt_request_t *mgmt;
- name_request_t *nr;
- t10_cmd_t *t10_cmd;
- char **buf, local_buf[16];
- int lun;
- extern void dataout_callback(t10_cmd_t *t, char *data, size_t *xfer);
-
- (void) pthread_mutex_lock(&s->s_mutex);
- s->s_state = SS_RUNNING;
- (void) pthread_mutex_unlock(&s->s_mutex);
- do {
- m = queue_message_get(s->s_sessq);
- switch (m->msg_type) {
- case msg_cmd_send:
- cmd = (iscsi_cmd_t *)m->msg_data;
- if (s->s_t10 == NULL) {
-
- /*
- * The value of 0x960 comes from T10.
- * See SPC-4, revision 1a, section 6.4.2,
- * table 87
- *
- * XXX Need to rethink how I should do
- * the callback.
- */
- s->s_t10 = t10_handle_create(
- s->s_t_name, s->s_i_name, T10_TRANS_ISCSI,
- s->s_conn_head->c_tpgt,
- s->s_conn_head->c_max_burst_len,
- s->s_t10q, dataout_callback);
- }
- if (t10_cmd_create(s->s_t10, cmd->c_lun, cmd->c_scb,
- cmd->c_scb_len, (transport_t)cmd,
- &t10_cmd) == False) {
-
- /*
- * If the command create failed, the T10 layer
- * will attempt to create a sense buffer
- * telling the initiator what went wrong. If
- * that layer was unable to accomplish that
- * things are really bad and we need to just
- * close the connection.
- */
- if (t10_cmd != NULL) {
- queue_message_set(
- cmd->c_allegiance->c_dataq,
- 0, msg_cmd_cmplt, t10_cmd);
- } else {
- queue_prt(s->s_mgmtq, Q_SESS_ERRS,
- "SES%x FAILED to create cmd\n",
- s->s_num);
- conn_state(cmd->c_allegiance, T11);
- }
- } else {
- (void) pthread_mutex_lock(
- &cmd->c_allegiance->c_mutex);
- if (cmd->c_state != CmdCanceled) {
- cmd->c_t10_cmd = t10_cmd;
- (void) t10_cmd_send(s->s_t10,
- cmd->c_t10_cmd, cmd->c_data,
- cmd->c_data_len);
- } else {
- t10_cmd_shoot_event(t10_cmd,
- T10_Cmd_T6);
- }
- (void) pthread_mutex_unlock(
- &cmd->c_allegiance->c_mutex);
- }
- break;
-
- case msg_cmd_data_out:
- cmd = (iscsi_cmd_t *)m->msg_data;
- if (s->s_t10 != NULL)
- (void) t10_cmd_data(s->s_t10, cmd->c_t10_cmd,
- cmd->c_offset_out, cmd->c_data,
- cmd->c_data_len);
- break;
-
- case msg_targ_inventory_change:
- if (s->s_t10 != NULL)
- (void) t10_task_mgmt(s->s_t10, InventoryChange,
- 0, 0);
- break;
-
- case msg_lu_capacity_change:
- lun = (int)(uintptr_t)m->msg_data;
- if (s->s_t10 != NULL)
- (void) t10_task_mgmt(s->s_t10, CapacityChange,
- lun, 0);
- break;
-
- case msg_reset_targ:
- if (s->s_t10 != NULL)
- (void) t10_task_mgmt(s->s_t10, ResetTarget,
- 0, 0);
- break;
-
- case msg_reset_lu:
- if (s->s_t10 != NULL)
- (void) t10_task_mgmt(s->s_t10, ResetLun,
- (int)(uintptr_t)m->msg_data, 0);
- break;
-
- case msg_shutdown:
- (void) pthread_mutex_lock(&s->s_mutex);
- s->s_state = SS_SHUTDOWN_START;
- (void) pthread_mutex_unlock(&s->s_mutex);
-
- /*
- * Shutdown rquest comming from a connection. Only
- * shutdown the STE if this is the last connection
- * for this session.
- */
- c = (iscsi_conn_t *)m->msg_data;
- if (session_remove_connection(s, c) == True) {
- queue_prt(s->s_mgmtq, Q_SESS_NONIO,
- "SES%x Starting shutdown\n", s->s_num);
-
- /*
- * If this is the last connection for this
- * session send a message to the SAM-3 layer to
- * shutdown.
- */
- if (s->s_t10 != NULL) {
- t10_handle_disable(s->s_t10);
- }
- /*
- * Do all work using the session pointer before
- * sending the shutdown response msg. The
- * session struct can get freed by the thread
- * that picks up and handles the shutdown
- * response.
- */
- queue_message_set(s->s_mgmtq, 0,
- msg_pthread_join,
- (void *)(uintptr_t)pthread_self());
- queue_message_set(s->s_t10q, 0,
- msg_shutdown_rsp, 0);
- process = False;
- } else {
-
- /*
- * Since this isn't the last connection for
- * the session, acknowledge the connection
- * request now since it's references from
- * this session have been removed.
- */
- queue_message_set(c->c_dataq, 0,
- msg_shutdown_rsp, (void *)False);
- }
- break;
-
- case msg_initiator_name:
- nr = (name_request_t *)m->msg_data;
- s->s_i_name = strdup(nr->nr_name);
-
- /*
- * Acknowledge the request by sending back an empty
- * message.
- */
- queue_message_set(nr->nr_q, 0, msg_initiator_name, 0);
- break;
-
- case msg_initiator_alias:
- nr = (name_request_t *)m->msg_data;
- s->s_i_alias = strdup(nr->nr_name);
-
- /*
- * Acknowledge the request by sending back an empty
- * message.
- */
- queue_message_set(nr->nr_q, 0, msg_initiator_alias, 0);
- break;
-
- case msg_target_name:
- nr = (name_request_t *)m->msg_data;
- s->s_t_name = strdup(nr->nr_name);
-
- /*
- * Acknowledge the request by sending back an empty
- * message.
- */
- queue_message_set(nr->nr_q, 0, msg_target_name, 0);
- break;
-
- case msg_mgmt_rqst:
- mgmt = (mgmt_request_t *)m->msg_data;
- m->msg_data = NULL;
-
- (void) pthread_mutex_lock(&mgmt->m_resp_mutex);
- buf = mgmt->m_u.m_resp;
-
- if ((s->s_type == SessionNormal) &&
- (mgmt->m_request == mgmt_full_phase_statistics) &&
- (strcmp(s->s_t_name, mgmt->m_targ_name) == 0)) {
-
- tgt_buf_add_tag(buf, XML_ELEMENT_CONN,
- Tag_Start);
- tgt_buf_add_tag(buf, s->s_i_name, Tag_String);
- if (s->s_i_alias != NULL) {
- tgt_buf_add(buf, XML_ELEMENT_ALIAS,
- s->s_i_alias);
- }
-
- /*
- * Need to loop through the connections
- * and create one time_connected tag for
- * each. This will be needed once MC/S support
- * is added.
- */
- (void) snprintf(local_buf, sizeof (local_buf),
- "%d",
- mgmt->m_time - s->s_conn_head->c_up_at);
- tgt_buf_add(buf, XML_ELEMENT_TIMECON,
- local_buf);
-
- tgt_buf_add_tag(buf, XML_ELEMENT_STATS,
- Tag_Start);
-
- t10_targ_stat(s->s_t10, buf);
-
- tgt_buf_add_tag(buf, XML_ELEMENT_STATS,
- Tag_End);
- tgt_buf_add_tag(buf, XML_ELEMENT_CONN, Tag_End);
- }
-
- (void) pthread_mutex_unlock(&mgmt->m_resp_mutex);
-
- queue_message_set(mgmt->m_q, 0, msg_mgmt_rply, 0);
-
- break;
-
- default:
- queue_prt(s->s_mgmtq, Q_SESS_ERRS,
- "SES%x Unknown msg type (%d) from Connection\n",
- s->s_num, m->msg_type);
- break;
- }
- queue_message_free(m);
- } while (process == True);
-
- queue_message_set(mgmtq, 0, msg_pthread_join,
- (void *)(uintptr_t)pthread_self());
- return (NULL);
-}
-
-/*
- * []----
- * | session_validate -- do what the name says
- * |
- * | At this point the connection has processed the login command so that
- * | we have InitiatorName and ISID at a minimum. Check to see if there
- * | are other sessions which match. If so, log that one out and proceed with
- * | this session. If nothing matches, then link this into a global list.
- * |
- * | Once we support multiple connections per session need to scan list
- * | to see if other connection have the same CID. If so, log out that
- * | connection.
- * []----
- */
-Boolean_t
-session_validate(iscsi_sess_t *s)
-{
- iscsi_sess_t *check;
-
- queue_prt(s->s_mgmtq, Q_SESS_NONIO,
- "SES%x %s ISID[%02x%02x%02x%02x%02x%02x]\n",
- s->s_num, s->s_i_alias == NULL ? s->s_i_name : s->s_i_alias,
- s->s_isid[0], s->s_isid[1], s->s_isid[2],
- s->s_isid[3], s->s_isid[4], s->s_isid[5]);
-
-
- /*
- * SessionType=Discovery which means no target name and therefore
- * this is okay.
- */
- if (s->s_t_name == NULL)
- return (True);
-
- (void) pthread_mutex_lock(&sess_mutex);
- for (check = sess_head; check; check = check->s_next) {
- /*
- * Ignore ourselves in this check.
- */
- if (check == s)
- continue;
- if ((check->s_t_name == NULL) ||
- (strcmp(check->s_t_name, s->s_t_name) != 0))
- continue;
- if (strcmp(check->s_i_name, s->s_i_name) != 0)
- continue;
- if (check->s_conn_head->c_tpgt != s->s_conn_head->c_tpgt)
- continue;
- /*
- * Section 5.3.5
- * Session reinstatement is the process of the initiator
- * logging in with an ISID that is possible active from
- * the target's perspective. Thus implicitly logging out
- * the session that corresponds to the ISID and
- * reinstating a new iSCSI session in its place (with the
- * same ISID).
- */
- if (bcmp(check->s_isid, s->s_isid, 6) == 0) {
- queue_prt(s->s_mgmtq, Q_SESS_NONIO,
- "SES%x Implicit shutdown\n", check->s_num);
- if (check->s_conn_head->c_state == S5_LOGGED_IN)
- conn_state(check->s_conn_head, T8);
- else
- conn_state(check->s_conn_head, T7);
- break;
- }
- }
- (void) pthread_mutex_unlock(&sess_mutex);
-
- return (True);
-}
-
-/*
- * []----
- * | static iscsi_sess_set_auth -
- * []----
- */
-static void
-sess_set_auth(iscsi_sess_t *isp)
-{
- IscsiAuthClient *auth_client = NULL;
- tgt_node_t *node = NULL;
-
- if (isp == (iscsi_sess_t *)NULL)
- return;
-
- /* Zero out the session authentication structure */
- bzero(&isp->sess_auth, sizeof (iscsi_auth_t));
- isp->sess_auth.auth_enabled = B_TRUE;
-
- /* Load CHAP name */
- node = tgt_node_next_child(main_config, XML_ELEMENT_CHAPNAME, NULL);
- if (node != NULL && node->x_value != NULL) {
- (void) strcpy(isp->sess_auth.username, node->x_value);
- }
-
- /* Load CHAP secret */
- node = tgt_node_next_child(main_config, XML_ELEMENT_CHAPSECRET, NULL);
- if (node != NULL && node->x_value != NULL) {
- (void) strcpy((char *)isp->sess_auth.password, node->x_value);
- isp->sess_auth.password_length = strlen(node->x_value);
- }
-
- /*
- * Set up authentication buffers always. We don't know if
- * initiator will request CHAP until later.
- */
- isp->sess_auth.num_auth_buffers = 5;
- isp->sess_auth.auth_buffers[0].address =
- &(isp->sess_auth.auth_client_block);
- isp->sess_auth.auth_buffers[0].length =
- sizeof (isp->sess_auth.auth_client_block);
- isp->sess_auth.auth_buffers[1].address =
- &(isp->sess_auth.auth_recv_string_block);
- isp->sess_auth.auth_buffers[1].length =
- sizeof (isp->sess_auth.auth_recv_string_block);
- isp->sess_auth.auth_buffers[2].address =
- &(isp->sess_auth.auth_send_string_block);
- isp->sess_auth.auth_buffers[2].length =
- sizeof (isp->sess_auth.auth_send_string_block);
- isp->sess_auth.auth_buffers[3].address =
- &(isp->sess_auth.auth_recv_binary_block);
- isp->sess_auth.auth_buffers[3].length =
- sizeof (isp->sess_auth.auth_recv_binary_block);
- isp->sess_auth.auth_buffers[4].address =
- &(isp->sess_auth.auth_send_binary_block);
- isp->sess_auth.auth_buffers[4].length =
- sizeof (isp->sess_auth.auth_send_binary_block);
-
- if (isp->sess_auth.auth_buffers &&
- isp->sess_auth.num_auth_buffers) {
-
- auth_client = (IscsiAuthClient *)isp->
- sess_auth.auth_buffers[0].address;
-
- /*
- * prepare for authentication
- */
- if (iscsiAuthClientInit(iscsiAuthNodeTypeTarget,
- isp->sess_auth.num_auth_buffers,
- isp->sess_auth.auth_buffers) !=
- iscsiAuthStatusNoError) {
- syslog(LOG_ERR, "iscsi connection login failed - "
- "unable to initialize authentication\n");
- return;
- }
-
- if (iscsiAuthClientSetVersion(auth_client,
- iscsiAuthVersionRfc) != iscsiAuthStatusNoError) {
- syslog(LOG_ERR, "iscsi connection login failed - "
- "unable to set version\n");
- return;
- }
-
- if (isp->sess_auth.username &&
- (iscsiAuthClientSetUsername(auth_client,
- isp->sess_auth.username) !=
- iscsiAuthStatusNoError)) {
- syslog(LOG_ERR, "iscsi connection login failed - "
- "unable to set username\n");
- return;
- }
-
- if (isp->sess_auth.password &&
- (iscsiAuthClientSetPassword(auth_client,
- isp->sess_auth.password, isp->sess_auth.password_length) !=
- iscsiAuthStatusNoError)) {
- syslog(LOG_ERR, "iscsi connection login failed - "
- "unable to set password\n");
- return;
- }
-
- /*
- * FIXME: we disable the minimum size check for now
- */
- if (iscsiAuthClientSetIpSec(auth_client, 1) !=
- iscsiAuthStatusNoError) {
- syslog(LOG_ERR, "iscsi connection login failed - "
- "unable to set ipsec\n");
- return;
- }
-
- if (iscsiAuthClientSetAuthRemote(auth_client,
- isp->sess_auth.auth_enabled) != iscsiAuthStatusNoError) {
- syslog(LOG_ERR, "iscsi connection login failed - "
- "unable to set remote authentication\n");
- return;
- }
- }
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/iscsi_sess.h b/usr/src/cmd/iscsi/iscsitgtd/iscsi_sess.h
deleted file mode 100644
index 4426046117..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_sess.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _SESSION_H
-#define _SESSION_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Block comment which describes the contents of this file.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <sys/types.h>
-#include <sys/iscsi_authclient.h>
-#include "iscsi_cmd.h"
-#include "t10.h"
-
-/*
- * iSCSI Auth Information
- */
-typedef struct iscsi_auth {
- IscsiAuthStringBlock auth_recv_string_block;
- IscsiAuthStringBlock auth_send_string_block;
- IscsiAuthLargeBinary auth_recv_binary_block;
- IscsiAuthLargeBinary auth_send_binary_block;
- IscsiAuthClient auth_client_block;
- int num_auth_buffers;
- IscsiAuthBufferDesc auth_buffers[5];
-
- /*
- * To indicate if authentication is enabled.
- * 0 means authentication disabled.
- * 1 means authentication enabled.
- */
- int auth_enabled;
-
- /* Initiator's authentication information. */
- char username[iscsiAuthStringMaxLength];
- uint8_t password[iscsiAuthStringMaxLength];
- int password_length;
-
- /* Target's authentication information. */
- char username_in[iscsiAuthStringMaxLength];
- uint8_t password_in[iscsiAuthStringMaxLength];
- int password_length_in;
-} iscsi_auth_t;
-
-typedef enum iscsi_session_type {
- SessionDiscovery, SessionNormal
-} iscsi_session_type_t;
-
-typedef enum iscsi_session_state {
- SS_FREE, SS_STARTED, SS_RUNNING, SS_SHUTDOWN_START, SS_SHUTDOWN_CMPLT
-} iscsi_sess_state_t;
-
-typedef struct iscsi_sess {
- struct iscsi_sess *s_next;
-
- iscsi_sess_state_t s_state;
-
- /*
- * Set during login
- * mutex isn't held.
- */
- char *s_i_name,
- *s_i_alias,
- *s_t_name;
- uint8_t s_isid[6];
- /*
- * This is the highest packet number we've seen and is
- * used during replies.
- */
- int s_seencmdsn;
-
- /*
- * To keep the correct order of PDU's submitted to the SCSI
- * layer we check that the incoming cmdsn matches this value.
- * Otherwise, we're missing a packet and need to wait. This
- * is particularly important with multiple connections per
- * session.
- */
- int s_cmdsn;
-
- iscsi_session_type_t s_type;
-
- /*
- * Set during allocation of this struct and only referenced
- */
- int s_tsid;
-
- target_queue_t *s_sessq,
- *s_t10q,
- *s_mgmtq;
-
- t10_targ_handle_t s_t10;
-
- struct iscsi_conn *s_conn_head;
-
- int s_num;
-
- pthread_mutex_t s_mutex;
- iscsi_auth_t sess_auth;
- pthread_t s_thr_id_conn,
- s_thr_id_t10;
-} iscsi_sess_t;
-
-void session_init();
-Boolean_t session_alloc(struct iscsi_conn *c, uint8_t *isid);
-Boolean_t session_validate(struct iscsi_sess *s);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SESSION_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/iscsi_target.xml b/usr/src/cmd/iscsi/iscsitgtd/iscsi_target.xml
deleted file mode 100644
index b594134b5b..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_target.xml
+++ /dev/null
@@ -1,116 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
-<!--
- Copyright 2007 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
-
- ident "%Z%%M% %I% %E% SMI"
-
-
- NOTE: This service manifest is not editable; its contents will
- be overwritten by package or patch operations, including
- operating system upgrade. Make customizations in a different
- file.
--->
-
-<service_bundle type='manifest' name='SUNWiscsitgtu:iscsitgt'>
-
-<service
- name='system/iscsitgt'
- type='service'
- version='1'>
-
- <create_default_instance enabled='false' />
-
- <single_instance/>
-
- <!-- We need name resolution and full filesystem access -->
- <dependency
- name='milestone'
- grouping='require_all'
- restart_on='none'
- type='service'>
- <service_fmri value='svc:/milestone/multi-user' />
- </dependency>
-
-
- <exec_method
- type='method'
- name='start'
- exec='/lib/svc/method/svc-iscsitgt %m'
- timeout_seconds='60'>
- <method_context>
- <method_credential
- user='root'
- group='sys'
- privileges='basic,sys_config,net_rawaccess,sys_mount,file_dac_write,sys_devices,proc_setid' />
- </method_context>
- </exec_method>
-
- <exec_method
- type='method'
- name='stop'
- exec='/lib/svc/method/svc-iscsitgt %m %{restarter/contract}'
- timeout_seconds='60'>
- <method_context>
- <method_credential
- user='root'
- group='sys'
- privileges='basic,sys_config,net_rawaccess,sys_mount,file_dac_write,sys_devices,proc_setid' />
- </method_context>
- </exec_method>
-
- <property_group name='general' type='framework'>
- <propval name='action_authorization' type='astring'
- value='solaris.smf.manage.iscsitgt' />
- <!-- To read and modify protected properties -->
- <propval name='read_authorization' type='astring'
- value='solaris.smf.read.iscsitgt' />
- <propval name='value_authorization' type='astring'
- value='solaris.smf.value.iscsitgt' />
- <propval name='modify_authorization' type='astring'
- value='solaris.smf.modify.iscsitgt' />
- </property_group>
-
- <property_group name='application' type='framework'>
- <stability value='Unstable' />
- <propval name='auto_enable' type='boolean' value='true' />
- </property_group>
-
- <stability value='Unstable' />
-
- <template>
- <common_name>
- <loctext xml:lang='C'>
- iSCSI Target
- </loctext>
- </common_name>
- <documentation>
- <manpage title='iscsitgtd' section='1M'
- manpath='/usr/share/man' />
- <manpage title='iscsitadm' section='1M'
- manpath='/usr/share/man' />
- </documentation>
- </template>
-</service>
-
-</service_bundle>
diff --git a/usr/src/cmd/iscsi/iscsitgtd/isns.c b/usr/src/cmd/iscsi/iscsitgtd/isns.c
deleted file mode 100644
index c5548f4ac1..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/isns.c
+++ /dev/null
@@ -1,702 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 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/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <syslog.h>
-#include <ctype.h>
-#include <pthread.h>
-#include <netdb.h>
-#include <libintl.h>
-#include <errno.h>
-#include <assert.h>
-#include <fcntl.h>
-#include <sys/byteorder.h>
-
-#include "isns_protocol.h"
-#include "isns_client.h"
-#include "queue.h"
-
-extern target_queue_t *mgmtq;
-
-static uint16_t xid = 0;
-static pthread_mutex_t xid_lock = PTHREAD_MUTEX_INITIALIZER;
-
-/*
- * more than 1 processes can accessing get_xid
- */
-static uint16_t
-get_xid()
-{
- uint16_t tmp;
-
- (void) pthread_mutex_lock(&xid_lock);
- tmp = xid++;
- (void) pthread_mutex_unlock(&xid_lock);
- return (tmp);
-}
-
-void
-ntoh_tlv(isns_tlv_t *tlv)
-{
- uint32_t val;
-
- tlv->attr_id = ntohl(tlv->attr_id);
- tlv->attr_len = ntohl(tlv->attr_len);
-
- switch (tlv->attr_id) {
- case ISNS_DELIMITER_ATTR_ID:
- break;
- case ISNS_ISCSI_NAME_ATTR_ID:
- case ISNS_EID_ATTR_ID:
- case ISNS_ISCSI_ALIAS_ATTR_ID:
- case ISNS_PORTAL_NAME_ATTR_ID:
- case ISNS_PG_ISCSI_NAME_ATTR_ID:
- break;
-
- case ISNS_PORTAL_IP_ADDR_ATTR_ID:
- case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID:
- bcopy(tlv->attr_value, &val, 4);
- *tlv->attr_value = ntohl(val);
- break;
-
- default:
- switch (tlv->attr_len) {
- case 4:
- val = ntohl(
- (uint32_t)(*tlv->attr_value));
- bcopy(&val, tlv->attr_value, 4);
- break;
- default:
- break;
- }
- break;
- }
-}
-
-/*
- * print_ntoh_tlv print network byte order tag-length-value attribute
- */
-void
-print_ntoh_tlv(isns_tlv_t *tlv)
-{
- uint32_t tag, len, val, pf_type;
- char buf[256];
- struct sockaddr_in6 sin6;
-
- tag = ntohl(tlv->attr_id);
- len = ntohl(tlv->attr_len);
-
- if (len == 0) {
- queue_prt(mgmtq, Q_ISNS_DBG, "Zero length tag: %d\n", tag);
- return;
- }
-
- switch (tag) {
- case ISNS_DELIMITER_ATTR_ID:
- break;
- case ISNS_ISCSI_NAME_ATTR_ID:
- case ISNS_EID_ATTR_ID:
- case ISNS_ISCSI_ALIAS_ATTR_ID:
- case ISNS_PORTAL_NAME_ATTR_ID:
- case ISNS_PG_ISCSI_NAME_ATTR_ID:
- queue_prt(mgmtq, Q_ISNS_DBG,
- "Tag %d: Value: %s\n", tag, tlv->attr_value);
- break;
-
- case ISNS_PORTAL_IP_ADDR_ATTR_ID:
- case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID:
- bcopy(tlv->attr_value, &pf_type, 4);
- pf_type = ntohl(pf_type);
- pf_type = (pf_type == sizeof (in6_addr_t))
- ? PF_INET6 : PF_INET;
- switch (pf_type) {
- case PF_INET:
- /* RFC2372 IPv4 mapped IPv6 address */
- if (inet_ntop(pf_type,
- (void *)&tlv->attr_value[12],
- buf, 256) == NULL) {
- syslog(LOG_ERR,
- "inet_ntop failed");
- break;
- }
- queue_prt(mgmtq, Q_ISNS_DBG,
- "IP_ADDR %s\n", buf);
- break;
- case PF_INET6:
- bcopy(tlv->attr_value, &sin6,
- sizeof (struct sockaddr_in6));
- (void) inet_ntop(pf_type,
- (void *)&sin6.sin6_addr,
- buf, 256);
- break;
- default:
- queue_prt(mgmtq, Q_ISNS_DBG,
- "unknown pf_type\n");
- break;
- }
- break;
-
- default:
- switch (len) {
- case 4:
- bcopy(tlv->attr_value, &val, 4);
- val = ntohl(val);
- queue_prt(mgmtq, Q_ISNS_DBG,
- "Tag: %d Value: %ld\n", tag, val);
- break;
- default:
- break;
- }
- break;
- }
-}
-
-void
-print_attr(isns_tlv_t *attr, void *pval, uint32_t ival)
-{
- uint32_t tag = ntohl(attr->attr_id);
- uint32_t len = ntohl(attr->attr_len);
- uint32_t pf_type;
- char buf[256];
-
- queue_prt(mgmtq, Q_ISNS_DBG, "Tag: %d Length: %d\n", tag, len);
- switch (tag) {
- case ISNS_DELIMITER_ATTR_ID:
- break;
-
- case ISNS_ISCSI_NAME_ATTR_ID:
- case ISNS_EID_ATTR_ID:
- case ISNS_ISCSI_ALIAS_ATTR_ID:
- case ISNS_PORTAL_NAME_ATTR_ID:
- case ISNS_PG_ISCSI_NAME_ATTR_ID:
- if (len && pval != NULL) {
- queue_prt(mgmtq, Q_ISNS_DBG, "Value: %s\n",
- attr->attr_value);
- }
- break;
-
- case ISNS_PORTAL_IP_ADDR_ATTR_ID:
- case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID:
- if (len) {
- pf_type = (ival == sizeof (in6_addr_t))
- ? PF_INET6 : PF_INET;
- (void) inet_ntop(pf_type, pval, buf, 256);
- queue_prt(mgmtq, Q_ISNS_DBG, "IP_ADDR %s\n",
- buf);
- }
- break;
-
- default:
- switch (len) {
- case 4:
- queue_prt(mgmtq, Q_ISNS_DBG,
- "Value: %d\n",
- ntohl(*attr->attr_value));
- break;
- default:
- break;
- }
- break;
- }
-}
-
-void
-print_isns_hdr(isns_hdr_t *hdr)
-{
- queue_prt(mgmtq, Q_ISNS_DBG, "hdr->version %d\n", hdr->version);
- queue_prt(mgmtq, Q_ISNS_DBG, "hdr->func_id %x\n", hdr->func_id);
- queue_prt(mgmtq, Q_ISNS_DBG, "hdr->pdu_len %d\n", hdr->pdu_len);
- queue_prt(mgmtq, Q_ISNS_DBG, "hdr->flags %x\n", hdr->flags);
- queue_prt(mgmtq, Q_ISNS_DBG, "hdr->xid %d\n", hdr->xid);
- queue_prt(mgmtq, Q_ISNS_DBG, "hdr->seqid %d\n", hdr->seqid);
-}
-
-void
-ntoh_isns_hdr(isns_hdr_t *hdr)
-{
- hdr->version = ntohs(hdr->version);
- hdr->func_id = ntohs(hdr->func_id);
- hdr->pdu_len = ntohs(hdr->pdu_len);
- hdr->flags = ntohs(hdr->flags);
- hdr->xid = ntohs(hdr->xid);
- hdr->seqid = ntohs(hdr->seqid);
-}
-
-int
-isns_append_attr(isns_pdu_t *pdu, uint32_t tag, uint32_t len,
- void *pval, uint32_t ival)
-{
- uint32_t val;
- uint32_t pad_len;
- uint16_t pdu_len;
- isns_tlv_t *attr;
- char *tlv;
-
- if (pdu == NULL) {
- syslog(LOG_ALERT, "NULL PDU\n");
- return (-1);
- }
-
- /* get current pdu payload length */
- pdu_len = ntohs(pdu->payload_len);
-
- /* pad 4 bytes alignment */
- pad_len = PAD4(len);
-
- if ((pdu_len + pad_len) > MAX_PDU_PAYLOAD_SZ) {
- syslog(LOG_ALERT, "Exceeded PDU size\n");
- return (-1);
- }
-
- if ((attr = (isns_tlv_t *)malloc(ISNS_ATTR_SZ(pad_len))) == NULL) {
- syslog(LOG_ALERT, "Malloc error");
- return (-1);
- }
- bzero(attr, ISNS_ATTR_SZ(pad_len));
- attr->attr_id = htonl(tag);
- attr->attr_len = htonl(pad_len);
-
- switch (tag) {
- case ISNS_DELIMITER_ATTR_ID:
- break;
-
- case ISNS_ISCSI_NAME_ATTR_ID:
- case ISNS_EID_ATTR_ID:
- case ISNS_ISCSI_ALIAS_ATTR_ID:
- case ISNS_PORTAL_NAME_ATTR_ID:
- case ISNS_PG_ISCSI_NAME_ATTR_ID:
- if (len && pval != NULL) {
- bcopy(pval, attr->attr_value, len);
- }
- break;
-
- case ISNS_PORTAL_IP_ADDR_ATTR_ID:
- case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID:
- if (len && ival == sizeof (in_addr_t)) {
- /* IPv4 */
- attr->attr_value[10] = 0xFF;
- attr->attr_value[11] = 0xFF;
- bcopy(pval, ((attr->attr_value) + 12), ival);
- } else if (len && ival == sizeof (in6_addr_t)) {
- /* IPv6 */
- bcopy(pval, attr->attr_value, ival);
- }
- break;
-
- default:
- switch (len) {
- case 4:
- val = htonl(ival);
- bcopy(&val, attr->attr_value, 4);
- break;
- default:
- break;
- }
- break;
- }
-
- /* copy attribute to pdu */
- tlv = (char *)pdu + ISNSP_HEADER_SIZE + pdu_len;
- bcopy(attr, tlv, ISNS_ATTR_SZ(pad_len));
- pdu->payload_len = htons(pdu_len + ISNS_ATTR_SZ(pad_len));
-
- /* debug only */
- print_ntoh_tlv(attr);
-
- free(attr);
- return (0);
-}
-
-int
-isns_create_pdu(uint16_t func_id, uint32_t flags, isns_pdu_t **pdu)
-{
- size_t pdu_sz = MAX_PDU_SZ;
-
- if ((*pdu = (isns_pdu_t *)malloc(pdu_sz)) == NULL) {
- syslog(LOG_ERR, "isns_create_pdu malloc failure");
- return (-1);
- }
-
- bzero(*pdu, pdu_sz);
- (*pdu)->payload_len = 0;
- (*pdu)->seq = 0;
- (*pdu)->xid = htons(get_xid());
- (*pdu)->version = htons((uint16_t)ISNSP_VERSION);
- (*pdu)->func_id = htons((uint16_t)(func_id));
- (*pdu)->flags = htons((uint16_t)(flags | ISNS_FLAG_CLIENT |
- ISNS_FLAG_FIRST_PDU | ISNS_FLAG_LAST_PDU));
- return (0);
-}
-
-void
-isns_free_pdu(void *pdu)
-{
- free(pdu);
-}
-
-/*
- * Desc: Open connection to the isns server
- * Args: isns server name or isns server ip-addr
- * Return: -1 if open failed, descriptor to socket if open succeeded
- */
-int
-isns_open(char *server)
-{
- struct addrinfo hints, *ai, *aip;
- struct sockaddr *sa;
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
- size_t sa_len;
- int so;
- int ret;
- fd_set rfdset;
- fd_set wfdset;
- fd_set errfdset;
- struct timeval timeout;
- Boolean_t shouldsockblock = False;
- int socket_ready = 0;
- timeout.tv_sec = 5; /* 5 Secs Timeout */
- timeout.tv_usec = 0; /* 0 uSecs Timeout */
-
- if (server == NULL) {
- syslog(LOG_ERR, "ISNS server ID required");
- return (-1);
- }
-
- bzero(&hints, sizeof (struct addrinfo));
- hints.ai_family = AF_UNSPEC;
- if ((ret = getaddrinfo(server, NULL, NULL, &ai)) != 0) {
- syslog(LOG_ALERT, "getaddrinfo failed on server %s: %s", server,
- gai_strerror(ret));
- return (-1);
- }
-
- aip = ai;
- do {
- so = socket(aip->ai_family, SOCK_STREAM, 0);
- if (so != -1) {
-
- /* set it to non blocking so connect wont hang */
- if (setsocknonblocking(so) == -1) {
- (void) close(so);
- continue;
- }
-
- sa_len = aip->ai_addrlen;
- switch (aip->ai_family) {
- case PF_INET:
- bzero(&sin,
- sizeof (struct sockaddr_in));
- sa = (struct sockaddr *)&sin;
- bcopy(aip->ai_addr, sa, sa_len);
- sin.sin_port = htons(
- ISNS_DEFAULT_SERVER_PORT);
- break;
- case PF_INET6:
- bzero(&sin6,
- sizeof (struct sockaddr_in6));
- sa = (struct sockaddr *)&sin6;
- bcopy(aip->ai_addr, sa, sa_len);
- sin6.sin6_port =
- htons(ISNS_DEFAULT_SERVER_PORT);
- break;
- default:
- syslog(LOG_ALERT, "Bad protocol");
- (void) close(so);
- continue;
- }
-
- ret = connect(so, sa, sa_len);
- if (ret == 0) {
- /*
- * connection succeeded with out
- * blocking
- */
- shouldsockblock = True;
- }
-
- if (ret < 0) {
- if (errno == EINPROGRESS) {
- FD_ZERO(&rfdset);
- FD_ZERO(&wfdset);
- FD_ZERO(&errfdset);
- FD_SET(so, &rfdset);
- FD_SET(so, &wfdset);
- FD_SET(so, &errfdset);
- socket_ready =
- select(so + 1, &rfdset, &wfdset,
- &errfdset, &timeout);
- if (socket_ready < 0) {
- syslog(LOG_ALERT,
- "failed to connect with"
- " isns, err=%d", errno);
- (void) close(so);
- } else if (socket_ready == 0) {
- syslog(LOG_ALERT,
- "time out failed"
- " to connect with isns");
- (void) close(so);
- } else { /* Socket is ready */
- /*
- * Check if socket is ready
- */
- if (is_socket_ready(so,
- &rfdset, &wfdset,
- &errfdset) == True)
- shouldsockblock = True;
- else
- (void) close(so);
- }
- } else {
- syslog(LOG_WARNING,
- "Connect failed no progress");
- (void) close(so);
- }
- }
-
- if (shouldsockblock == True) {
- if (-1 == setsockblocking(so)) {
- (void) close(so);
- shouldsockblock = False;
- } else {
- freeaddrinfo(ai);
- return (so);
- }
- }
-
- }
- } while ((aip = aip->ai_next) != NULL);
-
- if (ai != NULL)
- freeaddrinfo(ai);
- return (-1);
-}
-
-/*
- * According to:
- * UNIX Network Programming Volume 1, Third Edition:
- * The Sockets Networking APIBOOK:
- *
- * When the connection completes successfully, the descriptor becomes
- * writable (p. 531 of TCPv2).
- * When the connection establishment encounters an error, the descriptor
- * becomes both readable and writable (p. 530 of TCPv2).
- */
-Boolean_t
-is_socket_ready(int so, fd_set *rfdset, fd_set *wfdset,
- fd_set *errfdset)
-{
- if ((FD_ISSET(so, wfdset) &&
- FD_ISSET(so, rfdset)) ||
- FD_ISSET(so, errfdset)) {
- return (False);
- } else {
- return (True);
- }
-}
-
-int
-setsocknonblocking(int so)
-{
- int flags;
- /* set it to non blocking */
- if (-1 == (flags = fcntl(so, F_GETFL, 0))) {
- syslog(LOG_WARNING,
- "Failed to get socket flags. Blocking..");
- return (-1);
- }
-
- if (fcntl(so, F_SETFL, flags | O_NONBLOCK) == -1) {
- syslog(LOG_WARNING,
- "Failed to set socket in non blocking mode");
- return (-1);
- }
- return (0);
-}
-
-int
-setsockblocking(int so)
-{
- int flags;
- /* set it to non blocking */
- if (-1 == (flags = fcntl(so, F_GETFL, 0))) {
- syslog(LOG_WARNING, " Failed to get flags on socket..");
- return (-1);
- }
-
- flags &= ~O_NONBLOCK;
- if (fcntl(so, F_SETFL, flags) == -1) {
- syslog(LOG_WARNING, " failed to set socket to blocking");
- return (-1);
- }
- return (0);
-}
-
-
-void
-isns_close(int so)
-{
- if (so) {
- (void) close(so);
- }
-}
-
-/*
- * isns_send allocated pdu, caller needs to free pdu when done processing
- */
-int
-isns_send(int so, isns_pdu_t *pdu)
-{
- size_t len;
-
- assert(pdu != NULL);
-
- len = ISNSP_HEADER_SIZE + ntohs(pdu->payload_len);
- if (send(so, pdu, len, 0) == -1) {
- syslog(LOG_ALERT, "isns_send failure");
- return (-1);
- }
- return (0);
-}
-
-/*
- * Desc: isns_recv malloc memory for the isns response message, user needs
- * to isns_free() memory after process the response message. The
- * isns header is converted to host byte order, the remaining TLV
- * attributes can be converted using ntoh_tlv()
- */
-int
-isns_recv(int so, isns_rsp_t **pdu)
-{
- isns_hdr_t hdr, hdr1;
- isns_rsp_t *rsp;
- uint8_t *ptr;
- size_t total_pdu_len;
- int len;
- uint16_t xid_x, func_id_x, seqid_x;
- boolean_t done;
-
- *pdu = NULL;
- total_pdu_len = 0;
- seqid_x = 0;
- done = FALSE;
-
- do {
- /* read pdu header 1st */
- do {
- len = recv(so, &hdr1, ISNSP_HEADER_SIZE, MSG_WAITALL);
- } while ((len == -1) && (errno == EINTR));
-
- if (len != ISNSP_HEADER_SIZE) {
- syslog(LOG_ALERT, "isns_recv fail to read header");
- return (-1);
- }
-
- /* normalize the pdu header for processing */
- bcopy(&hdr1, &hdr, sizeof (isns_hdr_t));
- ntoh_isns_hdr(&hdr);
-
- if (IS_1ST_PDU(hdr.flags)) {
- if (hdr.seqid != 0) {
- syslog(LOG_ALERT, "ISNS out of sequence");
- return (-1);
- }
- xid_x = hdr.xid;
- func_id_x = hdr.func_id;
- }
-
- if (IS_LAST_PDU(hdr.flags)) {
- done = TRUE;
- }
-
- /* verify seq, xid, func_id */
- if (seqid_x != hdr.seqid) {
- syslog(LOG_ALERT, "ISNS out of sequence");
- return (-1);
- }
- if (xid_x != hdr.xid || func_id_x != hdr.func_id) {
- syslog(LOG_ALERT, "Non matching xid or func_id");
- return (-1);
- }
-
- ++seqid_x; /* next expected seqid */
-
- /* malloc size + previous payload length */
- if ((ptr = malloc(ISNSP_HEADER_SIZE + hdr.pdu_len
- + total_pdu_len)) == NULL) {
- syslog(LOG_ALERT, "Malloc failure");
- return (-1);
- }
- bzero(ptr, ISNSP_HEADER_SIZE + hdr.pdu_len);
-
- if (hdr.seqid == 0) {
- *pdu = (void *)ptr;
- bcopy(&hdr1, ptr, ISNSP_HEADER_SIZE);
- ptr += ISNSP_HEADER_SIZE;
- if ((len = recv(so, ptr, hdr.pdu_len, MSG_WAITALL))
- != hdr.pdu_len) {
- syslog(LOG_ERR,
- "isns_recv fail to read 1st payload");
- free(*pdu);
- *pdu = NULL;
- return (-1);
- }
- } else {
- /* merge the pdu */
- bcopy(*pdu, ptr, ISNSP_HEADER_SIZE + total_pdu_len);
- free(*pdu);
- *pdu = (void *)ptr;
- ptr += (ISNSP_HEADER_SIZE + total_pdu_len);
- if (recv(so, ptr, hdr.pdu_len, MSG_WAITALL)
- != hdr.pdu_len) {
- syslog(LOG_ERR,
- "isns_recv fail to read payload");
- free(*pdu);
- *pdu = NULL;
- return (-1);
- }
- }
- total_pdu_len += hdr.pdu_len;
-
- } while (done == FALSE);
-
- /* normalize the response status */
- rsp = (isns_rsp_t *)*pdu;
- rsp->pdu_len = htons(total_pdu_len);
- ntoh_isns_hdr((isns_hdr_t *)rsp);
-
- return (0);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/isns_client.c b/usr/src/cmd/iscsi/iscsitgtd/isns_client.c
deleted file mode 100644
index 02b5da645b..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/isns_client.c
+++ /dev/null
@@ -1,1830 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <syslog.h>
-#include <netdb.h>
-#include <pthread.h>
-#include <signal.h>
-#include <errno.h>
-#include <netinet/in.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-
-#include <iscsitgt_impl.h>
-
-#include "isns_protocol.h"
-#include "isns_client.h"
-#include "target.h"
-#include "queue.h"
-
-
-typedef struct {
- uint32_t pf_family;
- uint32_t ip_len;
- uint32_t ai_addrlen;
- union {
- in_addr_t in;
- in6_addr_t in6;
- } ip_adr;
-} ip_t;
-
-#define ISNS_TGT_LOGOUT 54321
-
-extern target_queue_t *mgmtq;
-
-/*
- * Global
- * Parameters for ESI/SCN processing.
- * scn_port: ESI/SCN port to receive ISNS_ESI & ISNS_SCN messages
- * isns_args:
- * eid_ip: Entity IP info
- */
-static int scn_port = 0;
-static esi_scn_arg_t isns_args = {{0}, {0}, 0};
-static ip_t eid_ip;
-static int num_reg = 0;
-static pthread_t scn_tid = 0;
-static pthread_t isns_tid = 0;
-static Boolean_t isns_shutdown = True;
-static Boolean_t connection_thr_bail_out = False;
-static int ISNS_SLEEP_SECS = 20;
-Boolean_t isns_server_connection_thr_running = False;
-target_queue_t *mgmtq = NULL;
-
-static int get_ip_addr(char *node, ip_t *sa);
-static int isns_op_all(uint16_t);
-static int append_tpgt(tgt_node_t *, isns_pdu_t *);
-static void process_esi(int, isns_pdu_t *);
-static void process_scn(int, isns_pdu_t *);
-static void *esi_scn_thr(void *);
-static int process_rsp(isns_pdu_t *, isns_rsp_t *);
-static int isns_dev_attr_reg(int, tgt_node_t *, char *, char *);
-static int isns_dev_attr_dereg(int, char *);
-static int isns_scn_reg(int, char *);
-static int isns_scn_dereg(int so, char *node);
-static tgt_node_t *find_tgt_by_name(char *, char **);
-static tgt_node_t *find_next_tgt(tgt_node_t *, char **);
-static int isns_populate_and_update_server_info(Boolean_t state);
-static int get_addr_family(char *node);
-
-/*
- * find_tgt_by_name searches DB by iscsi name or local name, if found
- * returns tgt_node_t. iname needs to be free by caller.
- */
-static tgt_node_t *
-find_tgt_by_name(char *targ, char **iname)
-{
- tgt_node_t *tgt = NULL;
-
- while ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
- tgt)) != NULL) {
- if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, iname)
- == FALSE) {
- syslog(LOG_ALERT, "ISNS: Missing iscsi name\n");
- break;
- }
- /* match either iscsi name or local name */
- if (strcmp(targ, tgt->x_value) == 0 ||
- strcmp(targ, *iname) == 0) {
- return (tgt);
- }
- free(*iname);
- }
- return (NULL);
-}
-
-static tgt_node_t *
-find_next_tgt(tgt_node_t *tgt, char **iname)
-{
- while ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
- tgt)) != NULL) {
- if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, iname)
- == FALSE) {
- continue;
- }
- return (tgt);
- }
- return (NULL);
-}
-
-/*
- * Find ip-addr associated with TPGT, don't send if no ip-addr is
- * found for a TPGT
- */
-static int
-append_tpgt(tgt_node_t *tgt, isns_pdu_t *cmd)
-{
- tgt_node_t *t, *x;
- tgt_node_t *pgt = NULL;
- tgt_node_t *iplist = NULL;
- tgt_node_t *tpgt = NULL;
- ip_t eid;
-
- /* Always add the default TPGT (1) */
- (void) isns_append_attr(cmd, ISNS_PG_TAG_ATTR_ID, ISNS_PG_TAG_SZ, NULL,
- 1);
- if (isns_append_attr(cmd, ISNS_PG_PORTAL_IP_ADDR_ATTR_ID,
- eid_ip.ai_addrlen, (void *)&eid_ip.ip_adr,
- eid_ip.ip_len) != 0) {
- return (-1);
- }
- if (isns_append_attr(cmd, ISNS_PG_PORTAL_PORT_ATTR_ID,
- ISNS_PORT_SZ, NULL, iscsi_port) != 0) {
- return (-1);
- }
-
- /* Get the remainning TPGT-LIST */
- if ((t = tgt_node_next(tgt, XML_ELEMENT_TPGTLIST, NULL))
- != NULL) {
- /* find tgpt from tpgt-list */
- while ((pgt = tgt_node_next(t, XML_ELEMENT_TPGT, pgt))
- != NULL) {
- /* update isns only if TPGT contains ip_addr */
- while ((tpgt = tgt_node_next_child(main_config,
- XML_ELEMENT_TPGT, tpgt)) != NULL) {
- if (strcmp(pgt->x_value, tpgt->x_value) != 0)
- continue;
- if ((iplist = tgt_node_next(tpgt,
- XML_ELEMENT_IPADDRLIST, NULL)) != NULL)
- break;
- }
- if (tpgt == NULL || iplist == NULL)
- continue;
- if (isns_append_attr(cmd, ISNS_PG_TAG_ATTR_ID,
- ISNS_PG_TAG_SZ, NULL,
- strtol(pgt->x_value, NULL, 0)) != 0) {
- return (-1);
- }
-
- /* get ip-addr & port */
- for (x = iplist->x_child; x; x = x->x_sibling) {
- if (get_ip_addr(x->x_value, &eid) < 0)
- continue;
- if (isns_append_attr(cmd,
- ISNS_PG_PORTAL_IP_ADDR_ATTR_ID,
- eid.ai_addrlen, (void *)&eid.ip_adr,
- eid.ip_len) != 0) {
- return (-1);
- }
- if (isns_append_attr(cmd,
- ISNS_PG_PORTAL_PORT_ATTR_ID,
- ISNS_PORT_SZ, NULL, iscsi_port) != 0) {
- return (-1);
- }
- }
- }
- }
-
- return (0);
-}
-
-/*
- * process_scn()
- * -Added/Updated object: nop, initiator is verified during connect
- *
- * -Removed object: logout_targ if still connected
- *
- * RFC 4171 section 5.6.5.9
- * destination attribute is always the 1st attribute in the SCN message,
- * then follows by SCN_BITMAP(35) & Source_Attribute(32)
- */
-static void
-process_scn(int so, isns_pdu_t *scn)
-{
- uint8_t *ptr = scn->payload;
- isns_tlv_t *tlv;
- uint16_t cnt = 0;
- uint32_t got_dest = 0;
- uint32_t got_source = 0;
- uint32_t bitmap = 0;
- uint32_t got_bitmap = 0;
- char dest[MAXNAMELEN];
- char source[MAXNAMELEN];
-
- queue_prt(mgmtq, Q_ISNS_DBG, "PROCESS_SCN %u\n",
- scn->payload_len);
-
- if (scn->payload_len < TAG_LEN_SZ) {
- syslog(LOG_ALERT, "ISNS SCN message error\n");
- return;
- }
-
- while (cnt < scn->payload_len) {
- /* LINTED */
- tlv = (isns_tlv_t *)ptr;
- tlv->attr_id = ntohl(tlv->attr_id);
- tlv->attr_len = ntohl(tlv->attr_len);
- queue_prt(mgmtq, Q_ISNS_DBG, "PROCESS_SCN %u %u\n",
- tlv->attr_id, tlv->attr_len);
- /*
- * devAttrQry the source attribute, process if node_type
- * is initiator
- */
- switch (tlv->attr_id) {
- case ISNS_ISCSI_NAME_ATTR_ID:
- if (got_dest == 0) {
- bcopy(tlv->attr_value, dest,
- tlv->attr_len);
- queue_prt(mgmtq, Q_ISNS_DBG,
- "PROCESS_SCN dest %s\n", dest);
- got_dest = 1;
- } else {
- bcopy(tlv->attr_value, source,
- tlv->attr_len);
- queue_prt(mgmtq, Q_ISNS_DBG,
- "PROCESS_SCN source %s\n", source);
- got_source = 1;
- }
- break;
- case ISNS_ISCSI_SCN_BITMAP_ATTR_ID:
- bcopy(tlv->attr_value, &bitmap, tlv->attr_len);
- bitmap = ntohl(bitmap);
- queue_prt(mgmtq, Q_ISNS_DBG,
- "PROCESS_SCN bitmap %u\n", bitmap);
- got_bitmap = 1;
- break;
- default:
- queue_prt(mgmtq, Q_ISNS_DBG,
- "PROCESS_SCN DEFAULT\n");
- break;
- }
-
- if (got_source && !got_bitmap) {
- queue_prt(mgmtq, Q_ISNS_DBG,
- "process_scn: message out-of-order\n");
- return;
- }
-
- if (got_source && got_bitmap) {
- switch (bitmap) {
- case ISNS_OBJ_ADDED:
- case ISNS_OBJ_UPDATED:
- queue_prt(mgmtq, Q_ISNS_DBG,
- "PROCESS_SCN OBJ ADDED");
- (void) isns_update();
- break;
- case ISNS_OBJ_REMOVED:
- queue_prt(mgmtq, Q_ISNS_DBG,
- "PROCESS_SCN OBJ REMOVED");
- /* logout target */
- if (got_dest == 0) {
- syslog(LOG_ALERT,
- "ISNS protocol error\n");
- continue;
- }
- logout_targ(dest);
- break;
- default:
- break;
- }
-
- /* clear got_xxx */
- got_source = 0;
- got_bitmap = 1;
- }
-
- /* next attribute */
- cnt += ISNS_ATTR_SZ(tlv->attr_len);
- ptr += ISNS_ATTR_SZ(tlv->attr_len);
- }
- queue_prt(mgmtq, Q_ISNS_DBG, "DONE PROCESS_SCN\n");
-}
-
-/*
- * Process ESI requires a success response only
- */
-static void
-process_esi(int so, isns_pdu_t *esi)
-{
- isns_rsp_t *cmd;
- int pl_len;
-
- if (isns_create_pdu(ISNS_ESI_RSP, 0, (isns_pdu_t **)&cmd) != 0) {
- return;
- }
-
- pl_len = esi->payload_len + ISNS_STATUS_SZ;
- if (pl_len > MAX_PDU_PAYLOAD_SZ) {
- syslog(LOG_ALERT, "process_esi: payload size exceeded");
- isns_free_pdu(cmd);
- return;
- }
-
- /* change the xid to the request xid */
- cmd->xid = htons(esi->xid);
- cmd->status = htonl(ISNS_RSP_SUCCESSFUL);
-
- /* copy original data */
- bcopy(esi->payload, cmd->data, esi->payload_len);
- cmd->pdu_len = htons(pl_len);
-
- if (isns_send(so, (isns_pdu_t *)cmd) < 0) {
- syslog(LOG_ALERT, "process_esi failed to isns_send");
- }
-
- isns_free_pdu(cmd);
-}
-
-static int
-is_isns_server_up(char *server) {
- int so;
- socklen_t len;
- struct sockaddr sa;
-
- /* no server specified */
- if (server == NULL) {
- return (-1);
- }
- /*
- * open isns server connect and determine which PF_INET to use
- */
- if ((so = isns_open(server)) < 0) {
- syslog(LOG_ERR,
- "isns server %s not found",
- server);
- return (-1);
- }
- len = sizeof (sa);
- if (getsockname(so, &sa, &len) < 0) {
- isns_close(so);
- syslog(LOG_ALERT,
- "isns getsockname failed");
- return (-1);
- }
- isns_close(so);
-
- if (sa.sa_family != PF_INET &&
- sa.sa_family != PF_INET6) {
- syslog(LOG_ERR,
- "isns unknown domain type");
- return (-1);
- }
- return (0);
-}
-
-/*
- * This thread sit's in a loop and ensures that it keeps checking for
- * connection to isns_server. Once the connection works it registers
- * with the isns and bails out.
- * We expect the isns server to be fault taulerant and has persistence
- * for the registered entries.
- */
-static void *
-isns_server_connection_thr(void *arg)
-{
- Boolean_t registered_targets = False;
- char server[MAXHOSTNAMELEN + 1] = {0};
-
- while (isns_shutdown == False &&
- connection_thr_bail_out == False) {
- /* current server */
- (void) strcpy(server, isns_args.server);
-
- if (is_isns_server_up(server) == 0) {
- if (registered_targets == False) {
- /*
- * register all targets, what happens if
- * no targets are created yet? this should
- * not be a failure, when new target gets
- * created, update gets call. what if SCN
- * register fails?
- */
- if (isns_reg_all() == 0) {
- /* scn register all targets */
- if (isns_op_all(ISNS_SCN_REG) != 0) {
- syslog(LOG_ERR,
- "SCN registrations"
- " failed\n");
- (void) isns_op_all(
- ISNS_DEV_DEREG);
- registered_targets = False;
- } else {
- registered_targets = True;
- break;
- }
- }
- }
- } else {
- syslog(LOG_INFO,
- "isns server %s is not reachable",
- server);
- registered_targets = False;
- }
- (void) sleep(ISNS_SLEEP_SECS);
- /* If isns was disabled, deregister and close the thread */
- if (isns_enabled() == False) {
- syslog(LOG_INFO,
- "isns server is disabled, dergister target");
- isns_fini();
- break;
- }
-
- }
- queue_message_set(mgmtq, 0, msg_pthread_join,
- (void *)(uintptr_t)pthread_self());
-
- return (NULL);
-}
-
-/*
- * esi_scn_thr() is the thread creates an end point to receive and process
- * ESI & SCN messages. This thread is created when isns_access is enabled
- * and for the duration of the iscsi daemon
- */
-static void *
-esi_scn_thr(void *arg)
-{
- struct sockaddr sa, *ai;
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
- int so, fd, pf;
- socklen_t len;
- char strport[NI_MAXSERV];
- isns_pdu_t *scn = NULL;
- struct timeval timeout;
- fd_set fdset;
- int socket_ready = 0;
-
- pf = get_addr_family(isns_args.entity);
- if (pf == PF_INET) {
- bzero(&sin, sizeof (sin));
- sin.sin_family = PF_INET;
- sin.sin_port = htons(0);
- sin.sin_addr.s_addr = INADDR_ANY;
- ai = (struct sockaddr *)&sin;
- len = sizeof (sin);
- } else if (pf == PF_INET6) {
- bzero(&sin6, sizeof (sin6));
- sin6.sin6_family = PF_INET6;
- sin6.sin6_port = htons(0);
- sin6.sin6_addr = in6addr_any;
- ai = (struct sockaddr *)&sin6;
- len = sizeof (sin6);
- } else {
- syslog(LOG_ERR, "Bad address family. Exit esi_scn_thr");
- return (NULL);
- }
-
- /*
- * create and bind SCN socket
- * save the scn port info
- */
- if ((so = socket(pf, SOCK_STREAM, 0)) == -1) {
- syslog(LOG_ALERT, "create isns socket failed");
- return (NULL);
- }
-
- (void) setsockopt(so, SOL_SOCKET, SO_REUSEADDR, 0, 0);
-
- if (bind(so, ai, len) < 0) {
- syslog(LOG_ALERT, "esi_scn_thr: bind failed");
- (void) close(so);
- return (NULL);
- }
-
- /* get scn port info */
- len = sizeof (sa);
- if (getsockname(so, &sa, &len) < 0) {
- syslog(LOG_ALERT, "isns getsockname failed");
- (void) close(so);
- return (NULL);
- }
- if (getnameinfo(&sa, len, NULL, 0, strport, NI_MAXSERV,
- NI_NUMERICSERV) != 0) {
- syslog(LOG_ALERT, "isns getnameinfo failed");
- (void) close(so);
- return (NULL);
- }
- scn_port = atoi(strport);
-
-
- if (listen(so, 5) < 0) {
- syslog(LOG_ALERT, "esi_scn_thr: failed listen");
- (void) close(so);
- return (NULL);
- }
-
- /* listen for esi or scn messages */
- while (isns_shutdown == False) {
- /* ISNS_ESI_INTERVAL_ATTR_ID is set to 10s */
- timeout.tv_sec = 10;
- timeout.tv_usec = 0;
- FD_ZERO(&fdset);
- FD_SET(so, &fdset);
-
- socket_ready = select(so + 1, &fdset, NULL, NULL, &timeout);
-
- /* If disabled bail out, dont care about packets */
- if (isns_enabled() == False) {
- syslog(LOG_INFO,
- "isns server is disabled, dergister target");
- isns_fini();
- (void) close(so);
- return (NULL);
- }
-
- if (socket_ready < 0) {
- syslog(LOG_ERR,
- "esi_scn_thr: select failed, retrying.");
- continue;
- } else if (socket_ready == 0) { /* timeout */
- continue;
- } else {
- /* Socket is ready */
- if ((fd = accept(so, &sa, &len)) < 0) {
- syslog(LOG_ALERT, "esi_scn_thr: failed accept");
- continue;
- }
- }
- if (isns_recv(fd, (isns_rsp_t **)&scn) == 0) {
- /* Just return success for ESI */
- switch (scn->func_id) {
- case ISNS_ESI:
- process_esi(fd, scn);
- break;
- case ISNS_SCN:
- /* call the SCN process function */
- process_scn(fd, scn);
- break;
- default:
- syslog(LOG_ERR,
- "esi_scn_thr: Invalid funcid %d\n",
- scn->func_id);
- break;
- }
- /* free response resource */
- isns_free_pdu(scn);
- } else {
- syslog(LOG_ALERT, "esi_scn_thr fails isns_recv ");
- }
-
- (void) close(fd);
- }
- (void) close(so);
- return (NULL);
-}
-
-/*
- * Perform operation on all targets
- */
-static int
-isns_op_all(uint16_t op)
-{
- int so;
- tgt_node_t *tgt = NULL;
- char *iname;
-
- if (isns_server_connection_thr_running == False) {
- syslog(LOG_ERR,
- "isns_op_all: iSNS discovery is not running."
- " Check the previous iSNS initialization error.");
- return (-1);
- }
-
- if ((so = isns_open(isns_args.server)) == -1) {
- syslog(LOG_ERR, "isns_op_all: failed to open isns server %s",
- isns_args.server);
- return (-1);
- }
-
- while ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
- tgt)) != NULL) {
- if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, &iname)
- == FALSE) {
- continue;
- }
-
- switch (op) {
- case ISNS_DEV_DEREG:
- if (isns_dev_attr_dereg(so, iname) == -1) {
- syslog(LOG_ERR,
- "ISNS de-register failed\n");
- }
- num_reg = 0;
- break;
- case ISNS_SCN_DEREG:
- if (isns_scn_dereg(so, iname) == -1) {
- syslog(LOG_ERR,
- "ISNS SCN de-register failed\n");
- }
- break;
- case ISNS_SCN_REG:
- if (isns_scn_reg(so, iname) == -1) {
- syslog(LOG_ERR,
- "ISNS SCN register failed\n");
- }
- break;
- case ISNS_TGT_LOGOUT:
- logout_targ(iname);
- break;
- default:
- break;
- }
-
- free(iname);
- }
- isns_close(so);
- return (0);
-}
-
-static int
-isns_populate_and_update_server_info(Boolean_t update) {
- char *isns_srv, *isns_port;
- int retcode = 0;
-
- /* get isns server info */
- (void) tgt_find_value_str(main_config, XML_ELEMENT_ISNS_SERV,
- &isns_srv);
- if (isns_srv == NULL) {
- syslog(LOG_INFO,
- "The server has not been setup, "
- "but enabling the isns access");
- retcode = -1;
- return (retcode);
- }
- isns_port = strchr(isns_srv, ':');
- if (isns_port == NULL) {
- isns_args.isns_port = ISNS_DEFAULT_SERVER_PORT;
- } else {
- isns_args.isns_port = strtoul(isns_port + 1, NULL, 0);
- if (isns_args.isns_port == 0) {
- isns_args.isns_port = ISNS_DEFAULT_SERVER_PORT;
- }
- *isns_port = '\0';
- }
-
- if (update == True) {
- /* isns_server changed */
- if (strcmp(isns_srv, isns_args.server) != 0) {
- /* de-reg from old iSNS server if it is setup */
- syslog(LOG_INFO,
- "Detected a new isns server, deregistering"
- " %s", isns_args.server);
- (void) isns_dereg_all();
- (void) strcpy(isns_args.server, isns_srv);
- /* Register with the new server */
- if (isns_reg_all() == 0) {
- /* scn register all targets */
- if (isns_op_all(ISNS_SCN_REG) != 0) {
- syslog(LOG_ERR,
- "SCN registrations failed\n");
- (void) isns_op_all(ISNS_DEV_DEREG);
- retcode = -1;
- }
- }
- }
- } else {
- (void) strcpy(isns_args.server, isns_srv);
- }
- free(isns_srv);
- return (retcode);
-}
-
-/*
- * isns_init() needs to be call before all ISNS operations.
- * Save the isns_server & entity name.
- * Start esi_scn_thr to receive ESI & SCN messages
- */
-int
-isns_init(target_queue_t *q)
-{
- if (q != NULL)
- mgmtq = q;
-
- if (isns_enabled() == False)
- return (0);
-
- /* get local hostname for entity usage */
- if ((gethostname(isns_args.entity, MAXHOSTNAMELEN) < 0) ||
- (get_ip_addr(isns_args.entity, &eid_ip) < 0)) {
- syslog(LOG_ERR, "isns_init: failed to get host name or host ip"
- " address for ENTITY properties");
- return (-1);
- }
-
- isns_shutdown = False;
-
- (void) isns_populate_and_update_server_info(False);
- if (pthread_create(&scn_tid, NULL,
- esi_scn_thr, (void *)&isns_args) !=
- 0) {
- syslog(LOG_ALERT, "isns_init failed to pthread_create");
- (void) pthread_kill(isns_tid, SIGKILL);
- return (-1);
- }
-
- if (pthread_create(&isns_tid, NULL, isns_server_connection_thr,
- (void *)NULL) != 0) {
- syslog(LOG_ALERT,
- "isns_init failed to create the "
- "isns connection thr");
- return (-1);
- }
-
- isns_server_connection_thr_running = True;
- return (0);
-}
-
-/*
- * isns_update gets call on modify_admin, this is changes to
- * isns access and/or isns server
- */
-int
-isns_update()
-{
- Boolean_t is_isns_enabled = isns_enabled();
- /*
- * If the isns thread was not started before and we are going
- * enabled from disabled start the threads.
- */
- if (isns_server_connection_thr_running == False) {
- if (is_isns_enabled == True) {
- if (isns_init(NULL) != 0) {
- return (-1);
- } else {
- return (0);
- }
- } else {
- syslog(LOG_INFO,
- "isns_update: isns is disabled");
- }
- } else {
- /*
- * isns is disabled after enabled,
- * log off all targets and fini isns service
- */
- if (is_isns_enabled == False) {
- isns_shutdown = True;
- /* pthread_join for the isns thread */
- (void) pthread_join(isns_tid, NULL);
- (void) pthread_join(scn_tid, NULL);
- isns_server_connection_thr_running = False;
- } else {
- /*
- * Incase the original thread is still running
- * we should reap it
- */
- connection_thr_bail_out = True;
- (void) pthread_join(isns_tid, NULL);
- connection_thr_bail_out = False;
-
- /*
- * Read the configuration file incase the server
- * has changed.
- */
- if (isns_populate_and_update_server_info(True) == -1) {
- return (-1);
- }
- }
- }
- return (0);
-}
-
-/*
- * isns_fini is called when isns access is disabled
- */
-void
-isns_fini()
-{
- /*
- * de-register all targets 1st, this prevents initiator from
- * logging back in
- */
- (void) isns_op_all(ISNS_SCN_DEREG);
- (void) isns_op_all(ISNS_DEV_DEREG);
-
- /* log off all targets */
- (void) isns_op_all(ISNS_TGT_LOGOUT);
-}
-
-static int
-get_addr_family(char *node) {
- struct addrinfo *ai = NULL;
- int ret;
-
- if ((ret = getaddrinfo(node, NULL, NULL, &ai)) != 0) {
- syslog(LOG_ALERT, "get_addr_family: server %s not found : %s",
- node, gai_strerror(ret));
- return (-1);
- }
- ret = ai->ai_family;
- freeaddrinfo(ai);
- return (ret);
-}
-
-static int
-get_ip_addr(char *node, ip_t *sa)
-{
- struct addrinfo *ai = NULL, *aip;
- struct sockaddr_in *sin;
- struct sockaddr_in6 *sin6;
- int ret;
-
- if ((ret = getaddrinfo(node, NULL, NULL, &ai)) != 0) {
- syslog(LOG_ALERT, "get_ip_addr: %s not found : %s",
- node, gai_strerror(ret));
- return (-1);
- }
-
- bzero(sa, sizeof (ip_t));
- aip = ai;
- do {
- sa->ai_addrlen = aip->ai_addrlen;
- sa->pf_family = aip->ai_family;
- switch (aip->ai_family) {
- case PF_INET:
- /* LINTED */
- sin = (struct sockaddr_in *)aip->ai_addr;
- sa->ip_len = sizeof (in_addr_t);
- bcopy(&sin->sin_addr, (void *)&sa->ip_adr.in,
- sa->ip_len);
- freeaddrinfo(ai);
- return (0);
- case PF_INET6:
- /* LINTED */
- sin6 = (struct sockaddr_in6 *)aip->ai_addr;
- sa->ip_len = sizeof (in6_addr_t);
- bcopy(&sin6->sin6_addr, &sa->ip_adr.in6,
- sa->ip_len);
- freeaddrinfo(ai);
- return (0);
- default:
- continue;
- }
- } while ((aip = aip->ai_next) != NULL);
-
- freeaddrinfo(ai);
- return (-1);
-}
-
-/*
- * Process isns response, need to verify same transaction id, func_id
- * as the isns command, the isns command is in network byte order,
- * the isns response is in host byte order
- */
-static int
-process_rsp(isns_pdu_t *cmd, isns_rsp_t *rsp)
-{
- queue_prt(mgmtq, Q_ISNS_DBG, "PROCESS_RSP");
- /*
- * Process responses:
- * -verify sucessful response
- * -verify match xid
- * -process operating attributes
- * For DevAttrReg & DevAttrQry and most isns command,
- * the response func_id is command_func_id | 0x8000.
- */
- rsp->status = ntohl(rsp->status);
- if (rsp->status != ISNS_RSP_SUCCESSFUL ||
- rsp->xid != ntohs(cmd->xid) ||
- rsp->func_id != (ntohs(cmd->func_id) | 0x8000)) {
- queue_prt(mgmtq, Q_ISNS_DBG,
- "cmd failed with: status= %d xid= %d %d "\
- "response attribute %x\n", rsp->status, rsp->xid,\
- ntohs(cmd->xid), rsp->func_id);
- return (-1);
- }
-
- return (0);
-}
-
-/*
- * DevAttrDereg
- */
-static int
-isns_dev_attr_dereg(int so, char *node)
-{
- isns_pdu_t *cmd = NULL;
- isns_rsp_t *rsp = NULL;
- uint32_t flags = 0;
- int ret = -1;
-
- queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_DEV_ATTR_DEREG");
-
- if (isns_create_pdu(ISNS_DEV_DEREG, flags, &cmd) != 0) {
- return (-1);
- }
-
- /* add source attribute */
- if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
- STRLEN(node), node, 0) != 0) {
- goto error;
- }
-
- /* add delimiter */
- if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) != 0) {
- goto error;
- }
-
- /* add operation attributes */
- if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
- STRLEN(node), node, 0) != 0) {
- goto error;
- }
-
- /* send pdu */
- if (isns_send(so, cmd) == -1) {
- syslog(LOG_ERR, "isns_dev_attr_dereg fails isns_send");
- goto error;
- }
-
- /* get isns response */
- if (isns_recv(so, &rsp) == -1) {
- syslog(LOG_ERR, "isns_dev_attr_dereg fails isns_recv ");
- goto error;
- }
-
- /* process response */
- if (process_rsp(cmd, rsp) == 0) {
- /*
- * Keep the num_reg to a non-negative number.
- * num_reg is used to keep track of whether there was
- * any registration occurred or not. Deregstration should
- * be followed by registration but in case dereg occurs
- * and somehow it is succeeded keeping num_reg to 0 prevent
- * any negative effect on subsequent registration.
- */
- if (num_reg > 0) num_reg--;
- ret = 0;
- }
-
-error:
- /* Free all resouces here */
- if (cmd)
- isns_free_pdu(cmd);
- if (rsp)
- isns_free_pdu(rsp);
- return (ret);
-}
-
-/*
- * Register a new node, need to find another node that is already registered
- * DevAttrReg
- * RFC 4171 Section 5.6.5.5 indicated SCN-port-tag (23) needed to be
- * included in the registration
- * Also need to register ESI-port-tag (20) see Section 6.3.5
- */
-static int
-isns_dev_attr_reg(int so, tgt_node_t *tgt, char *node, char *alias)
-{
- isns_pdu_t *cmd = NULL;
- isns_rsp_t *rsp = NULL;
- uint32_t flags = 0;
- int ret = 0;
- Boolean_t found = False;
- tgt_node_t *src = NULL;
- char *src_nm = NULL;
-
- queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_DEV_ATTR_REG");
-
- if ((so = isns_open(isns_args.server)) == -1) {
- return (-1);
- }
-
- if (num_reg == 0) {
- flags |= ISNS_FLAG_REPLACE_REG;
- }
-
- if (isns_create_pdu(ISNS_DEV_ATTR_REG, flags, &cmd) != 0) {
- return (-1);
- }
-
- if (num_reg == 0) {
- /* add new node to source attribute */
- if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
- STRLEN(node), node, 0) != 0) {
- goto error;
- }
- } else {
- /* find a registered node to use */
- do {
- src = find_next_tgt(src, &src_nm);
- if (src == NULL) {
- syslog(LOG_ALERT, "ISNS out of sync\n");
- goto error;
- }
- if (tgt == src) {
- free(src_nm);
- src_nm = NULL;
- continue;
- } else {
- found = True;
- }
- } while (found == False);
-
- if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
- STRLEN(src_nm), src_nm, 0) != 0) {
- goto error;
- }
- }
-
- /* add message key attribute */
- if (isns_append_attr(cmd, ISNS_EID_ATTR_ID,
- STRLEN(isns_args.entity), isns_args.entity, 0) != 0) {
- goto error;
- }
-
- /* add delimiter */
- if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) != 0) {
- goto error;
- }
-
- /* add operation attributes */
-
- /* entity id */
- if (isns_append_attr(cmd, ISNS_EID_ATTR_ID,
- STRLEN(isns_args.entity), isns_args.entity, 0) != 0) {
- goto error;
- }
-
- /* entity type */
- if (isns_append_attr(cmd, ISNS_ENTITY_PROTOCOL_ATTR_ID,
- ISNS_ENTITY_TYP_SZ, NULL, ISNS_ENTITY_PROTOCOL_ISCSI) != 0) {
- goto error;
- }
-
- /*
- * Register entity portal properties the 1st time
- */
- if (num_reg == 0) {
- /* portal ip-addr */
- if (isns_append_attr(cmd, ISNS_PORTAL_IP_ADDR_ATTR_ID,
- eid_ip.ai_addrlen, (void *)&eid_ip.ip_adr,
- eid_ip.ip_len) != 0) {
- goto error;
- }
-
- /* portal port */
- if (isns_append_attr(cmd, ISNS_PORTAL_PORT_ATTR_ID,
- ISNS_PORT_SZ, NULL, iscsi_port) != 0) {
- goto error;
- }
-
- /* ESI interval */
- if (isns_append_attr(cmd, ISNS_ESI_INTERVAL_ATTR_ID,
- ISNS_ESI_TICK_SZ, NULL, 10) != 0) {
- goto error;
- }
-
- /* scn port */
- if (isns_append_attr(cmd, ISNS_SCN_PORT_ATTR_ID,
- ISNS_PORT_SZ, NULL, scn_port) != 0) {
- goto error;
- }
-
- /* esi port */
- if (isns_append_attr(cmd, ISNS_ESI_PORT_ATTR_ID,
- ISNS_PORT_SZ, NULL, scn_port) != 0) {
- goto error;
- }
- }
-
- /* iscsi node name */
- if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
- STRLEN(node), node, 0) != 0) {
- goto error;
- }
-
- /* iscsi node type */
- if (isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID,
- ISNS_NODE_TYP_SZ, NULL, ISNS_TARGET_NODE_TYPE) != 0) {
- goto error;
- }
-
- /* iscsi node alias */
- if (isns_append_attr(cmd, ISNS_ISCSI_ALIAS_ATTR_ID,
- STRLEN(alias), alias, 0) != 0) {
- goto error;
- }
-
- /* PGT */
- if (append_tpgt(tgt, cmd) != 0) {
- goto error;
- }
-
- /* send pdu */
- if (isns_send(so, cmd) == -1) {
- goto error;
- }
-
- /* get isns response */
- if (isns_recv(so, &rsp) == -1) {
- goto error;
- }
-
- /* process response */
- if ((ret = process_rsp(cmd, rsp)) == 0) {
- num_reg++;
- }
-
-error:
- /* Free all resouces here */
- if (cmd)
- isns_free_pdu(cmd);
- if (rsp)
- isns_free_pdu(rsp);
- if (src_nm)
- free(src_nm);
- return (ret);
-}
-
-/*
- * DevAttrQry for iscsi initiator
- * See RFC 4171 Sect. 5.6.5.2 for query detail
- */
-static int
-isns_dev_attr_qry(int so, char *target, char *initiator)
-{
- isns_pdu_t *cmd;
- isns_rsp_t *rsp;
- uint32_t flags = 0;
- int ret = -1;
- size_t remain;
- isns_tlv_t *tlv;
- uint8_t *ptr;
-
- queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_DEV_ATTR_QRY");
-
- if (isns_create_pdu(ISNS_DEV_ATTR_QRY, flags, &cmd) != 0) {
- return (-1);
- }
-
- /* source attribute */
- if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
- STRLEN(target), target, 0) == -1) {
- goto error;
- }
-
- /* message key attribute */
- /* iscsi initiator node type */
- if (isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID,
- ISNS_NODE_TYP_SZ, NULL, ISNS_INITIATOR_NODE_TYPE) == -1) {
- goto error;
- }
-
- /* delimiter */
- if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) == -1) {
- goto error;
- }
-
- /*
- * operating attributes
- * Query Iscsi initiator with zero length TLV operating
- * attribute
- */
-
- /* iscsi name */
- if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
- 0, NULL, 0) != 0) {
- goto error;
- }
-
- if (isns_send(so, cmd) == -1) {
- syslog(LOG_ERR, "isns_dev_attr_qry fails isns_send");
- goto error;
- }
-
- /* recv response */
- if (isns_recv(so, &rsp) == -1) {
- syslog(LOG_ERR, "isns_dev_attr_qry fails isns_recv ");
- goto error;
- }
-
- /* process response */
- if ((ret = process_rsp(cmd, rsp)) == 0) {
- /* compare initiator name to the response, success if found */
- /* subtract out status word */
- remain = rsp->pdu_len - ISNS_STATUS_SZ;
- ptr = rsp->data;
-
- while (remain > 0) {
- /* LINTED */
- tlv = (isns_tlv_t *)ptr;
-
- /* debug only */
- print_ntoh_tlv(tlv);
-
- /* process tag-len-value */
- ntoh_tlv(tlv);
- /*
- * let's process the data, only interested
- * in iscsi name, skip everything else for
- * now.
- */
- if (tlv->attr_id == ISNS_ISCSI_NAME_ATTR_ID) {
- if (strncmp((char *)tlv->attr_value, initiator,
- tlv->attr_len) == 0) {
- break;
- }
- }
- /* next tlv */
- remain -= ISNS_ATTR_SZ(tlv->attr_len);
- ptr += ISNS_ATTR_SZ(tlv->attr_len);
- }
- ret = (remain > 0) ? 1 : 0;
- }
-
-error:
- if (cmd)
- isns_free_pdu(cmd);
- if (rsp)
- isns_free_pdu(rsp);
- return (ret);
-}
-
-/*
- * SCNReg
- * See RFC 4171 Section 5.6.5.5
- */
-static int
-isns_scn_reg(int so, char *node)
-{
- isns_pdu_t *cmd;
- isns_rsp_t *rsp;
- uint32_t flags = 0;
- uint32_t bitmap = 0;
- int ret = -1;
-
- queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_SCN_REG");
-
- if (isns_create_pdu(ISNS_SCN_REG, flags, &cmd) != 0) {
- return (-1);
- }
-
- /* source attribute */
- if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
- STRLEN(node), node, 0) == -1) {
- goto error;
- }
-
- /* message key attribute */
- /* iscsi initiator node name */
- if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
- STRLEN(node), node, 0) != 0) {
- goto error;
- }
-
- /* delimiter */
- if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) == -1) {
- goto error;
- }
-
- /* SCN bitmap */
- bitmap = ISNS_INIT_SELF_INFO_ONLY | ISNS_OBJ_REMOVED |
- ISNS_OBJ_ADDED | ISNS_OBJ_UPDATED;
- if (isns_append_attr(cmd, ISNS_ISCSI_SCN_BITMAP_ATTR_ID,
- ISNS_SCN_BITMAP_SZ, NULL, bitmap) == -1) {
- goto error;
- }
-
- if (isns_send(so, cmd) == -1) {
- syslog(LOG_ERR, "isns_scn_reg fails isns_send");
- goto error;
- }
-
- if (isns_recv(so, &rsp) == -1) {
- syslog(LOG_ERR, "isns_scn_reg fails isns_recv ");
- goto error;
- }
-
- /* process response */
- if (process_rsp(cmd, rsp) == 0) {
- ret = 0;
- }
-
-error:
- if (cmd)
- isns_free_pdu(cmd);
- if (rsp)
- isns_free_pdu(rsp);
- return (ret);
-}
-
-
-/*
- * SCNDereg
- */
-static int
-isns_scn_dereg(int so, char *node)
-{
- isns_pdu_t *cmd = NULL;
- isns_rsp_t *rsp = NULL;
- uint32_t flags = 0;
- int ret = -1;
-
- queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_SCN_DEREG");
-
- if (isns_create_pdu(ISNS_SCN_DEREG, flags, &cmd) != 0) {
- return (-1);
- }
-
- /* source attribute */
- if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
- STRLEN(node), node, 0) == -1) {
- goto error;
- }
-
- /* message key attribute */
- /* iscsi initiator node name */
- if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
- STRLEN(node), node, 0) != 0) {
- goto error;
- }
-
- if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) == -1) {
- goto error;
- }
-
- if (isns_send(so, cmd) == -1) {
- syslog(LOG_ERR, "isns_scn_reg fails isns_send");
- goto error;
- }
-
- if (isns_recv(so, &rsp) == -1) {
- syslog(LOG_ERR, "isns_scn_reg fails isns_recv ");
- goto error;
- }
-
- /* process response */
- if (process_rsp(cmd, rsp) == 0) {
- ret = 0;
- }
-
-error:
- if (cmd)
- isns_free_pdu(cmd);
- if (rsp)
- isns_free_pdu(rsp);
- return (ret);
-}
-
-/*
- * isns_reg is called to register new target
- */
-int
-isns_reg(char *targ)
-{
- int so;
- tgt_node_t *tgt;
- char *iqn = NULL;
-
- if (isns_server_connection_thr_running == False) {
- syslog(LOG_ERR,
- "isns_reg: iSNS discovery is not running."
- " Check the previous iSNS initialization error.");
- return (-1);
- }
-
- if ((so = isns_open(isns_args.server)) == -1) {
- syslog(LOG_ERR, "isns_reg failed with server: %s",
- isns_args.server);
- return (-1);
- }
-
- /*
- * Open targets_config and devAttrReg all nodes
- */
- if ((tgt = find_tgt_by_name(targ, &iqn)) != NULL) {
- if (isns_dev_attr_reg(so, tgt, iqn, tgt->x_value) != 0) {
- syslog(LOG_ALERT, "ISNS registration failed %s\n",
- tgt->x_value);
- goto error;
- }
- if (isns_scn_reg(so, iqn) == -1) {
- syslog(LOG_ERR, "ISNS SCN register failed\n");
- }
- }
-
-error:
- if (iqn)
- free(iqn);
- isns_close(so);
- return (0);
-}
-
-
-/*
- * Register all iscsi target nodes from the XML database
- * Alway use the ISNS_FLAG_REPLACE_REG flag
- */
-int
-isns_reg_all()
-{
- int so;
- uint32_t flags = ISNS_FLAG_REPLACE_REG;
- isns_pdu_t *cmd = NULL;
- isns_rsp_t *rsp = NULL;
- char *n = NULL;
- char *a = NULL;
- char alias[MAXNAMELEN];
- char iname[MAXNAMELEN];
- tgt_node_t *tgt = NULL;
- int ret = -1;
- int tgt_cnt = 0;
-
- if (isns_server_connection_thr_running == False) {
- syslog(LOG_ERR,
- "isns_reg_all: iSNS discovery is not running."
- " Check the previous iSNS initialization error.");
- return (-1);
- }
-
- /*
- * get the 1st target and use it for the source attribute
- */
- if ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, tgt))
- == NULL) {
- return (0);
- }
- if (tgt->x_value == NULL) {
- syslog(LOG_ALERT, "ISNS: target with NULL local name\n");
- return (-1);
- }
- if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, &n)
- == FALSE) {
- syslog(LOG_ALERT, "ISNS: no XML_ELEMENT_INAME found\n");
- return (-1);
- }
- (void) strcpy(iname, n);
- free(n);
- if ((so = isns_open(isns_args.server)) == -1) {
- syslog(LOG_ALERT, "ISNS: fails to connect to %s\n",
- isns_args.server);
- return (-1);
- }
-
- if (isns_create_pdu(ISNS_DEV_ATTR_REG, flags, &cmd) != 0) {
- goto error;
- }
-
- /* source attribute */
- if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
- STRLEN(iname), iname, 0) != 0) {
- goto error;
- }
-
- /* add message key attribute */
- if (isns_append_attr(cmd, ISNS_EID_ATTR_ID,
- STRLEN(isns_args.entity), isns_args.entity, 0) != 0) {
- goto error;
- }
-
- /* add delimiter */
- if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) != 0) {
- goto error;
- }
-
- /* entity id */
- if (isns_append_attr(cmd, ISNS_EID_ATTR_ID,
- STRLEN(isns_args.entity), isns_args.entity, 0) != 0) {
- goto error;
- }
-
- /* entity type */
- if (isns_append_attr(cmd, ISNS_ENTITY_PROTOCOL_ATTR_ID,
- ISNS_ENTITY_TYP_SZ, NULL, ISNS_ENTITY_PROTOCOL_ISCSI) != 0) {
- goto error;
- }
-
- /* portal ip-addr */
- if (isns_append_attr(cmd, ISNS_PORTAL_IP_ADDR_ATTR_ID,
- eid_ip.ai_addrlen, (void *)&eid_ip.ip_adr,
- eid_ip.ip_len) != 0) {
- goto error;
- }
-
- /* portal port */
- if (isns_append_attr(cmd, ISNS_PORTAL_PORT_ATTR_ID,
- ISNS_PORT_SZ, NULL, iscsi_port) != 0) {
- goto error;
- }
-
- /* ESI interval */
- if (isns_append_attr(cmd, ISNS_ESI_INTERVAL_ATTR_ID,
- ISNS_ESI_TICK_SZ, NULL, 10) != 0) {
- goto error;
- }
-
-
- /* scn port */
- if (isns_append_attr(cmd, ISNS_SCN_PORT_ATTR_ID,
- ISNS_PORT_SZ, NULL, scn_port) != 0) {
- goto error;
- }
-
- /* esi port */
- if (isns_append_attr(cmd, ISNS_ESI_PORT_ATTR_ID,
- ISNS_PORT_SZ, NULL, scn_port) != 0) {
- goto error;
- }
-
- /*
- * Open targets_config and devAttrReg all nodes
- */
- tgt = NULL;
- while ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
- tgt)) != NULL) {
- if (tgt->x_value == NULL) {
- syslog(LOG_ALERT, "ISNS: target with NULL name\n");
- continue;
- }
- /* use this value as alias if alias is not set */
- (void) strcpy(alias, tgt->x_value);
-
- if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, &n)
- == FALSE) {
- continue;
- }
- (void) strcpy(iname, n);
- free(n);
-
- /* find alias */
- if (tgt_find_value_str(tgt, XML_ELEMENT_ALIAS, &a)
- == TRUE) {
- (void) strcpy(alias, a);
- free(a);
- }
-
- tgt_cnt++; /* increment target count */
-
- /* operation attributes */
- if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
- STRLEN(iname), iname, 0) != 0) {
- goto error;
- }
- if (isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID,
- 4, NULL, ISNS_TARGET_NODE_TYPE) != 0) {
- goto error;
- }
- if (isns_append_attr(cmd, ISNS_ISCSI_ALIAS_ATTR_ID,
- STRLEN(alias), alias, 0) != 0) {
- goto error;
- }
-
- if (append_tpgt(tgt, cmd) != 0) {
- goto error;
- }
-
- }
-
- /* send pdu */
- if (isns_send(so, cmd) == -1) {
- goto error;
- }
-
- /* get isns response */
- if (isns_recv(so, &rsp) == -1) {
- goto error;
- }
-
- /* process response */
- if (process_rsp(cmd, rsp) == 0) {
- ret = 0;
- num_reg = tgt_cnt;
- queue_prt(mgmtq, Q_ISNS_DBG, "DevAttrRegAll successful");
- } else {
- syslog(LOG_ALERT, "DevAttrReg failed");
- }
-
-error:
- if (cmd)
- isns_free_pdu(cmd);
- if (rsp)
- isns_free_pdu(rsp);
- isns_close(so);
- return (ret);
-}
-
-/*
- * Deregister an iscsi target node
- */
-int
-isns_dereg(char *name)
-{
- int so;
- int ret;
-
- if (isns_server_connection_thr_running == False) {
- syslog(LOG_ERR,
- "isns_dereg: iSNS discovery is not running."
- " Check the previous iSNS initialization error.");
- return (-1);
- }
-
- if ((so = isns_open(isns_args.server)) == -1) {
- return (-1);
- }
-
- ret = isns_dev_attr_dereg(so, name);
-
- isns_close(so);
- return (ret);
-}
-
-/*
- * Update an existing iscsi target property
- */
-int
-isns_dev_update(char *targ, uint32_t mods)
-{
- int so;
- int flags = 0; /* update only */
- char *iname = NULL;
- char *dummy = NULL;
- char alias[MAXNAMELEN];
- tgt_node_t *tgt = NULL;
- isns_pdu_t *cmd;
- isns_rsp_t *rsp;
- int ret = -1;
-
- if (mods == 0)
- return (0);
-
- if (isns_server_connection_thr_running == False) {
- syslog(LOG_ERR,
- "isns_dev_update: iSNS discovery is not running."
- " Check the previous iSNS initialization error.");
- return (-1);
- }
-
- if ((tgt = find_tgt_by_name(targ, &iname)) != NULL) {
- if (tgt_find_value_str(tgt, XML_ELEMENT_ALIAS, &dummy) ==
- True) {
- (void) strcpy(alias, dummy);
- free(dummy);
- } else
- (void) strcpy(alias, tgt->x_value);
-
- if ((so = isns_open(isns_args.server)) < 0) {
- goto error;
- }
-
- if (isns_create_pdu(ISNS_DEV_ATTR_REG, flags, &cmd)) {
- goto error;
- }
- /* source attr, msg key, delimiter */
- if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
- STRLEN(iname), iname, 0) != 0) {
- goto error;
- }
- if (isns_append_attr(cmd, ISNS_EID_ATTR_ID,
- STRLEN(isns_args.entity), isns_args.entity, 0) != 0) {
- goto error;
- }
- if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0)
- != 0) {
- goto error;
- }
-
- /*
- * get current operating attributes, alias & portal group
- * objects, these should be the only things that get change
- */
- (void) isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
- STRLEN(iname), iname, 0);
- (void) isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID,
- ISNS_NODE_TYP_SZ, NULL, ISNS_TARGET_NODE_TYPE);
-
- if (mods & ISNS_MOD_ALIAS)
- if (isns_append_attr(cmd, ISNS_ISCSI_ALIAS_ATTR_ID,
- STRLEN(alias), alias, 0) != 0) {
- goto error;
- }
-
- if (mods & ISNS_MOD_TPGT)
- if (append_tpgt(tgt, cmd) != 0) {
- goto error;
- }
-
- if (isns_send(so, (isns_pdu_t *)cmd) < 0) {
- goto error;
- }
-
- if (isns_recv(so, &rsp) == -1) {
- goto error;
- }
-
- /* process response, if failed do a isns_reg_all */
- if ((ret = process_rsp(cmd, rsp)) == -1) {
- if (isns_reg_all() != 0 || isns_scn_reg_all() != 0) {
- syslog(LOG_ALERT, "ISNS register failed\n");
- goto error;
- }
- ret = 0;
- } else {
- if (isns_scn_reg(so, iname) == -1) {
- syslog(LOG_ERR, "ISNS SCN register failed\n");
- goto error;
- }
- ret = 0;
- }
- } else {
- syslog(LOG_ERR, "ISNS: fails to update target %s\n", alias);
- }
-
-error:
- if (cmd)
- isns_free_pdu(cmd);
- if (rsp)
- isns_free_pdu(rsp);
- if (iname)
- free(iname);
- isns_close(so);
- return (ret);
-}
-
-
-/*
- * Deregister all iscsi target nodes from the XML database
- */
-int
-isns_dereg_all()
-{
- return (isns_op_all(ISNS_DEV_DEREG));
-}
-
-int
-isns_scn_reg_all()
-{
- return (isns_op_all(ISNS_SCN_REG));
-}
-
-int
-isns_scn_dereg_all()
-{
- return (isns_op_all(ISNS_SCN_DEREG));
-}
-
-/*
- * Query an iscsi initiator node
- */
-Boolean_t
-isns_qry_initiator(char *target, char *initiator)
-{
- int so;
- int ret;
-
- if (isns_server_connection_thr_running == False) {
- syslog(LOG_ERR,
- "isns_qry_initiator: iSNS discovery is not running"
- " Check the previous iSNS initialization error.");
- return (-1);
- }
-
- if ((so = isns_open(isns_args.server)) == -1) {
- syslog(LOG_ERR, "isns_qry failed");
- return (-1);
- }
-
- ret = isns_dev_attr_qry(so, target, initiator);
-
- isns_close(so);
- return (ret == 1 ? True : False);
-}
-
-Boolean_t
-isns_enabled()
-{
- Boolean_t isns_access = False;
- char *isns_srv = NULL;
-
- (void) tgt_find_value_boolean(main_config, XML_ELEMENT_ISNS_ACCESS,
- &isns_access);
- /* get isns server info */
- if (isns_access == True) {
- if (tgt_find_value_str(main_config, XML_ELEMENT_ISNS_SERV,
- &isns_srv) == True) {
- free(isns_srv);
- return (True);
- }
- }
- return (False);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/isns_client.h b/usr/src/cmd/iscsi/iscsitgtd/isns_client.h
deleted file mode 100644
index 8affb91b0f..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/isns_client.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _ISNS_CLIENT_H
-#define _ISNS_CLIENT_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <netdb.h>
-#include "queue.h"
-
-#include "isns_protocol.h"
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-/* isns update bitmap */
-#define ISNS_MOD_ALIAS 0x1
-#define ISNS_MOD_TPGT 0x2
-
-/* iscsi isns protocol */
-
-/*
- * Attribute size
- */
-#define ISNS_ISCSI_TYPE_SZ (4)
-#define ISNS_SCN_BITMAP_SZ (4)
-#define ISNS_PORT_SZ (4)
-#define ISNS_ESI_TICK_SZ (4)
-#define ISNS_PG_TAG_SZ (4)
-#define ISNS_ENTITY_TYP_SZ (4)
-#define ISNS_NODE_TYP_SZ (4)
-
-/*
- * iSNS attribute length: See RFC 4171 Section 6.1
- * iSCSI Name = 4-224
- * iSCSI Alias = 4-256
- */
-#define ISCSI_MAX_NAME 224
-#define ISCSI_MAX_ALIAS 256
-
-/*
- * Default pdu payload size, this is derived from a typical DevAttrReg
- * request, this should be sufficient for all requests.
- */
-#define MAX_PDU_SZ (16384)
-#define MAX_PDU_PAYLOAD_SZ (MAX_PDU_SZ - ISNSP_HEADER_SIZE)
-#define TAG_LEN_SZ (8)
-
-/* various isns data size */
-#define ISNS_STATUS_SZ (4)
-#define ISNS_ATTR_SZ(attr_len) (attr_len + TAG_LEN_SZ)
-
-/*
- * PDU length is 4 bytes aligned. See RFC 4171 Section 5.1.3
- */
-#define PAD4(a) ((a%4) ? ((4-a%4)+a) : a)
-
-/*
- * Macro to check 1st and last pdu
- */
-#define IS_1ST_PDU(x) ((x & ISNS_FLAG_FIRST_PDU) ? 1 : 0)
-#define IS_LAST_PDU(x) ((x & ISNS_FLAG_LAST_PDU) ? 1 : 0)
-
-/* RFC 4171 section 6 - null is included in strlen */
-#define STRLEN(x) (strlen(x) + 1)
-
-typedef struct esi_scn_arg {
- char entity[MAXHOSTNAMELEN + 1]; /* iscsi target entity */
- char server[MAXHOSTNAMELEN + 1]; /* isns server */
- int isns_port; /* isns server port */
-} esi_scn_arg_t;
-
-/*
- * ISNS message header
- * See RFC 4171 Section 5.0 & 5.1
- */
-typedef struct isns_hdr {
- uint16_t version;
- uint16_t func_id;
- uint16_t pdu_len;
- uint16_t flags;
- uint16_t xid;
- uint16_t seqid;
-} isns_hdr_t;
-
-/*
- * ISNS attribute, the attribute is in Tag-Length_Value format
- * attr_len: NULLs are included in the length
- * attr_value: is variable size and it is 4 bytes aligned
- */
-#if 0
-typedef struct isns_attr {
- uint32_t tag;
- uint32_t len;
- uint8_t val[1];
-} isns_attr_t;
-#endif
-
-typedef struct isns_rsp {
- uint16_t version;
- uint16_t func_id;
- uint16_t pdu_len;
- uint16_t flags;
- uint16_t xid;
- uint16_t seqid;
- uint32_t status;
- uint8_t data[1];
-} isns_rsp_t;
-
-/* Function prototype */
-int isns_init(target_queue_t *q);
-int isns_update();
-void isns_fini();
-Boolean_t isns_qry_initiator(char *, char *);
-int isns_reg(char *);
-int isns_reg_all();
-int isns_dereg(char *);
-int isns_dereg_all();
-int isns_scn_reg_all();
-int isns_scn_dereg_all();
-int isns_dev_update(char *, uint32_t);
-Boolean_t isns_enabled();
-void isns_tpgt_update();
-int isns_open(char *);
-void isns_close(int);
-int isns_append_attr(isns_pdu_t *, uint32_t, uint32_t, void *,
- uint32_t);
-int isns_create_pdu(uint16_t, uint32_t, isns_pdu_t **);
-void isns_free_pdu(void *);
-int isns_send(int, isns_pdu_t *);
-int isns_recv(int, isns_rsp_t **);
-void ntoh_isns_hdr(isns_hdr_t *);
-void ntoh_tlv(isns_tlv_t *);
-void print_ntoh_tlv(isns_tlv_t *);
-void print_attr(isns_tlv_t *attr, void *pval, uint32_t ival);
-void print_isns_hdr(isns_hdr_t *);
-int setsocknonblocking(int so);
-int setsockblocking(int so);
-Boolean_t is_socket_ready(int so,
- fd_set *rfdset, fd_set *wfdset, fd_set *errfdset);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ISNS_CLIENT_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/isns_protocol.h b/usr/src/cmd/iscsi/iscsitgtd/isns_protocol.h
deleted file mode 100644
index 1b8b0298d0..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/isns_protocol.h
+++ /dev/null
@@ -1,200 +0,0 @@
-
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _ISNS_PROTOCOL_H
-#define _ISNS_PROTOCOL_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-
-#define ISNSP_VERSION (0x01)
-
-#define ISNS_DEFAULT_SERVER_PORT (3205)
-
-#define ISNSP_HEADER_SIZE (12)
-#define ISNSP_MAX_PAYLOAD_SIZE (65532)
-#define ISNSP_MAX_PDU_SIZE (ISNSP_HEADER_SIZE + \
- ISNSP_MAX_PAYLOAD_SIZE)
-
-#define ISNS_TLV_ATTR_ID_LEN (4)
-#define ISNS_TLV_ATTR_LEN_LEN (4)
-#define MAX_ISNS_MESG_ATTR_ENTRIES (8)
-#define MAX_ISNS_OPER_ATTR_ENTRIES (32)
-
-/* iSNS Entity Protocol, iSNS Draft - section 6.2.2. */
-#define ISNS_ENTITY_PROTOCOL_NO (1)
-#define ISNS_ENTITY_PROTOCOL_ISCSI (2)
-#define ISNS_ENTITY_PROTOCOL_FCP (3)
-
-/* iSNS Function IDs, iSNS Draft - section 4.1.3. */
-#define ISNS_DEV_ATTR_REG (0x0001)
-#define ISNS_DEV_ATTR_QRY (0x0002)
-#define ISNS_DEV_GET_NEXT (0x0003)
-#define ISNS_DEV_DEREG (0x0004)
-#define ISNS_SCN_REG (0x0005)
-#define ISNS_SCN_DEREG (0x0006)
-#define ISNS_SCN (0x0008)
-#define ISNS_ESI (0x000D)
-#define ISNS_HEARTBEAT (0x000E)
-#define ISNS_DEV_ATTR_REG_RSP (0x8001)
-#define ISNS_DEV_ATTR_QRY_RSP (0x8002)
-#define ISNS_DEV_DEREG_RSP (0x8004)
-#define ISNS_SCN_REG_RSP (0x8005)
-#define ISNS_SCN_DEREG_RSP (0x8006)
-#define ISNS_SCN_RSP (0x8008)
-#define ISNS_ESI_RSP (0x800D)
-
-/* iSNS Flags, iSNS Draft - section 5.1.4. */
-#define ISNS_FLAG_FIRST_PDU (0x0400)
-#define ISNS_FLAG_LAST_PDU (0x0800)
-#define ISNS_FLAG_REPLACE_REG (0x1000)
-#define ISNS_FLAG_AUTH_BLK_PRESENTED (0x2000)
-#define ISNS_FLAG_SERVER (0x4000)
-#define ISNS_FLAG_CLIENT (0x8000)
-
-/* iSNS Response Status, iSNS Draft - section 5.4 */
-#define ISNS_RSP_SUCCESSFUL (0x0000)
-#define ISNS_RSP_UNKNOWN_ERROR (0x0001)
-#define ISNS_RSP_MSG_FORMAT_ERROR (0x0002)
-#define ISNS_RSP_INVALID_REGIS (0x0003)
-#define ISNS_RSP_INVALID_QRY (0x0005)
-#define ISNS_RSP_SRC_UNKNOWN (0x0006)
-#define ISNS_RSP_SRC_ABSENT (0x0007)
-#define ISNS_RSP_SRC_UNAUTHORIZED (0x0008)
-#define ISNS_RSP_NO_SUCH_ENTRY (0x0009)
-#define ISNS_RSP_VER_NOT_SUPPORTED (0X0010)
-#define ISNS_RSP_INTERNAL_ERROR (0x0011)
-#define ISNS_RSP_BUSY (0x0012)
-#define ISNS_RSP_OPTION_NOT_UNDERSTOOD (0x0013)
-#define ISNS_RSP_INVALID_UPDATE (0x0014)
-#define ISNS_RSP_MSG_NOT_SUPPORTED (0x0015)
-#define ISNS_RSP_SCN_EVENT_REJECTED (0X0016)
-#define ISNS_RSP_SCN_REGIS_REJECTED (0x0017)
-#define ISNS_RSP_ATTR_NOT_IMPL (0x0018)
-#define ISNS_RSP_ESI_NOT_AVAILABLE (0x0021)
-#define ISNS_RSP_INVALID_DEREGIS (0x0022)
-#define ISNS_RSP_REGIS_NOT_SUPPORTED (0x0023)
-
-/* iSCSI Node Type, iSNS Draft - section 6.4.2. */
-#define ISNS_TARGET_NODE_TYPE (0x0001)
-#define ISNS_INITIATOR_NODE_TYPE (0x0002)
-#define ISNS_CONTROL_NODE_TYPE (0x0004)
-
-/* iSCSI Node SCN Bitmap, iSNS Draft - section 6.4.4. */
-#define ISNS_INIT_SELF_INFO_ONLY (0x0080) /* Bit 24 */
-#define ISNS_TARGET_SELF_INFO_ONLY (0x0040) /* Bit 25 */
-#define ISNS_MGMT_REG (0x0020) /* Bit 26 */
-#define ISNS_OBJ_REMOVED (0x0010) /* Bit 27 */
-#define ISNS_OBJ_ADDED (0x0008) /* Bit 28 */
-#define ISNS_OBJ_UPDATED (0x0004) /* Bit 29 */
-#define ISNS_OBJ_MEMBER_REMOVED (0x0002) /* Bit 30 */
-#define ISNS_OBJ_MEMBER_ADDED (0x0001) /* Bit 31 */
-
-/* iSNS Attribute IDs, iSNS Draft - section 6.1. */
-#define ISNS_DELIMITER_ATTR_ID (0)
-#define ISNS_EID_ATTR_ID (1)
-#define ISNS_ENTITY_PROTOCOL_ATTR_ID (2)
-#define ISNS_TIMESTAMP_ATTR_ID (4)
-#define ISNS_PORTAL_IP_ADDR_ATTR_ID (16)
-#define ISNS_PORTAL_PORT_ATTR_ID (17)
-#define ISNS_PORTAL_NAME_ATTR_ID (18)
-#define ISNS_ESI_INTERVAL_ATTR_ID (19)
-#define ISNS_ESI_PORT_ATTR_ID (20)
-#define ISNS_SCN_PORT_ATTR_ID (23)
-#define ISNS_ISCSI_NAME_ATTR_ID (32)
-#define ISNS_ISCSI_NODE_TYPE_ATTR_ID (33)
-#define ISNS_ISCSI_ALIAS_ATTR_ID (34)
-#define ISNS_ISCSI_SCN_BITMAP_ATTR_ID (35)
-#define ISNS_PG_ISCSI_NAME_ATTR_ID (48)
-#define ISNS_PG_PORTAL_IP_ADDR_ATTR_ID (49)
-#define ISNS_PG_PORTAL_PORT_ATTR_ID (50)
-#define ISNS_PG_TAG_ATTR_ID (51)
-#define ISNS_PG_INDEX_ATTR_ID (52)
-
-/* iSNS Defaults */
-#define ISNS_DEFAULT_SERVER_PORT (3205)
-
-typedef struct isns_tlv {
- uint32_t attr_id;
- uint32_t attr_len;
- uint8_t attr_value[1];
-} isns_tlv_t;
-
-typedef struct isns_packet_data {
- uint16_t version;
- uint16_t func_id;
- uint16_t payload_len;
- uint16_t flags;
- uint16_t xid;
- uint16_t seq;
-
- int num_of_tlvs;
- isns_tlv_t tlvs[MAX_ISNS_OPER_ATTR_ENTRIES];
-} isns_packet_data_t;
-
-typedef struct isns_reg_mesg {
- isns_tlv_t src_attr;
- int num_of_mesg_attrs;
- isns_tlv_t *mesg_attrs[MAX_ISNS_MESG_ATTR_ENTRIES];
- isns_tlv_t delimiter_attr;
- isns_tlv_t *operating_attrs[MAX_ISNS_OPER_ATTR_ENTRIES];
-} isns_reg_mesg_t;
-
-typedef struct isns_resp_mesg {
- uint8_t status[4];
- isns_tlv_t messages_attrs[MAX_ISNS_MESG_ATTR_ENTRIES];
- isns_tlv_t delimiter_attr;
- isns_tlv_t operating_attrs[MAX_ISNS_OPER_ATTR_ENTRIES];
-} isns_resp_mesg_t;
-
-typedef struct isns_pdu {
- uint16_t version;
- uint16_t func_id;
- uint16_t payload_len;
- uint16_t flags;
- uint16_t xid;
- uint16_t seq;
- uint8_t payload[1];
-} isns_pdu_t;
-
-typedef struct isns_resp {
- uint32_t status;
- uint8_t data[1];
-} isns_resp_t;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ISNS_PROTOCOL_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/main.c b/usr/src/cmd/iscsi/iscsitgtd/main.c
deleted file mode 100644
index caf8355ccf..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/main.c
+++ /dev/null
@@ -1,940 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-
-#define FD_SETSIZE 65536
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <time.h>
-#include <unistd.h>
-#include <pthread.h>
-#include <sys/conf.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdint.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <errno.h>
-#include <door.h>
-#include <signal.h>
-#include <siginfo.h>
-#include <sys/ethernet.h>
-#include <libscf.h>
-#include <syslog.h>
-#include <synch.h>
-#include <libxml/xmlreader.h>
-#include <sys/resource.h>
-#include <syslog.h>
-#include <sys/select.h>
-#include <iscsitgt_impl.h>
-#include <umem.h>
-
-#include "queue.h"
-#include "port.h"
-#include "iscsi_conn.h"
-#include "target.h"
-#include "utility.h"
-#include "iscsi_ffp.h"
-#include "errcode.h"
-#include "t10.h"
-#include "mgmt_scf.h"
-
-#include "isns_client.h"
-
-#define EMPTY_CONFIG "<config version='1.0'>\n</config>\n"
-
-/* ---- Forward declarations ---- */
-static void variable_handler(tgt_node_t *, target_queue_t *, target_queue_t *,
- ucred_t *);
-
-
-/* ---- Global configuration data. ---- */
-char *target_basedir = NULL;
-char *target_log = DEFAULT_TARGET_LOG;
-char *config_file = DEFAULT_CONFIG_LOCATION;
-char *pgr_basedir = NULL;
-int iscsi_port = 3260, /* defined by the spec */
- dbg_lvl = 0,
- door_min_space;
-tgt_node_t *main_config,
- *targets_config;
-Boolean_t enforce_strict_guid = True,
- thin_provisioning = False,
- disable_tpgs = False,
- dbg_timestamps = False,
- pgr_persist = True;
-int targets_vers_maj,
- targets_vers_min,
- main_vers_maj,
- main_vers_min;
-pthread_rwlock_t targ_config_mutex;
-umem_cache_t *iscsi_cmd_cache,
- *t10_cmd_cache,
- *queue_cache;
-
-typedef struct var_table {
- char *v_name;
- int *v_value;
-} var_table_t;
-
-typedef struct cmd_table {
- char *c_name;
- void (*c_func)(tgt_node_t *, target_queue_t *, target_queue_t *,
- ucred_t *);
-} cmd_table_t;
-
-admin_table_t admin_prop_list[] = {
- {XML_ELEMENT_BASEDIR, update_basedir, NULL},
- {XML_ELEMENT_CHAPSECRET, 0, NULL},
- {XML_ELEMENT_CHAPNAME, 0, NULL},
- {XML_ELEMENT_RAD_ACCESS, 0, NULL},
- {XML_ELEMENT_RAD_SERV, valid_radius_srv, NULL},
- {XML_ELEMENT_RAD_SECRET, 0, NULL},
- {XML_ELEMENT_ISNS_ACCESS, 0, NULL},
- {XML_ELEMENT_ISNS_SERV, valid_isns_srv, NULL},
- {XML_ELEMENT_FAST, 0, NULL},
- {XML_ELEMENT_DELETE_CHAPSECRET, 0, XML_ELEMENT_CHAPSECRET},
- {XML_ELEMENT_DELETE_CHAPNAME, 0, XML_ELEMENT_CHAPNAME},
- {XML_ELEMENT_DELETE_RAD_SECRET, 0, XML_ELEMENT_RAD_SECRET},
- {XML_ELEMENT_DELETE_RAD_SERV, 0, XML_ELEMENT_RAD_SERV},
- {0, 0}
-};
-
-/*
- * Global variables which can be set via the management XML interface
- * with the syntax of "<variable><dbg_lvl>0x033</dbg_lvl></variable>"
- */
-var_table_t var_table[] = {
- { "dbg_lvl", &dbg_lvl },
- { "qlog_lvl", &qlog_lvl },
- /* ---- End of Table marker ---- */
- { NULL, 0 }
-};
-
-/*
- * Commands which are run via the management XML interface
- */
-cmd_table_t cmd_table[] = {
- { "variable", variable_handler },
- { "create", create_func },
- { "modify", modify_func },
- { "delete", remove_func },
- { "list", list_func },
- /* ---- End of Table marker ---- */
- { NULL, NULL }
-};
-
-/*
- * []----
- * | process_config -- parse the main configuration file
- * |
- * | Everything in the configuratin file is optional. That's because
- * | the management CLI can set the value to everything and update
- * | the configuration.
- * []----
- */
-static Boolean_t
-process_config()
-{
- tgt_node_t *node = NULL;
-
-#ifndef lint
- LIBXML_TEST_VERSION;
-#endif
-
- if (mgmt_get_main_config(&node) == False) {
- return (False);
- }
-
- main_vers_maj = XML_VERS_MAIN_MAJ;
- main_vers_min = XML_VERS_MAIN_MIN;
- if (validate_version(node, &main_vers_maj, &main_vers_min) ==
- False) {
- syslog(LOG_ERR, "Target main config invalid");
- return (False);
- }
-
- /*
- * The base directory is optional in the sense that the daemon
- * can start without it, but the daemon can't really do
- * anything until the administrator sets the value.
- */
- (void) tgt_find_value_str(node, XML_ELEMENT_BASEDIR,
- &target_basedir);
-
- /*
- * These are optional settings for the target. Each of
- * these has a default value which can be overwritten in
- * the configuration.
- */
- (void) tgt_find_value_str(node, XML_ELEMENT_TARGLOG,
- &target_log);
- (void) tgt_find_value_int(node, XML_ELEMENT_ISCSIPORT,
- &iscsi_port);
- (void) tgt_find_value_intchk(node, XML_ELEMENT_DBGLVL, &dbg_lvl);
- (void) tgt_find_value_boolean(node, XML_ELEMENT_ENFORCE,
- &enforce_strict_guid);
- (void) tgt_find_value_boolean(node, XML_ELEMENT_THIN_PROVO,
- &thin_provisioning);
- (void) tgt_find_value_boolean(node, XML_ELEMENT_DISABLE_TPGS,
- &disable_tpgs);
- (void) tgt_find_value_boolean(node, XML_ELEMENT_TIMESTAMPS,
- &dbg_timestamps);
- (void) tgt_find_value_boolean(node, XML_ELEMENT_PGR_PERSIST,
- &pgr_persist);
- (void) tgt_find_value_str(node, XML_ELEMENT_PGR_BASEDIR,
- &pgr_basedir);
- if (tgt_find_value_intchk(node, XML_ELEMENT_LOGLVL,
- &qlog_lvl) == True)
- queue_log(True);
-
- main_config = node;
- targets_config = node;
-
- return (True);
-}
-
-/*
- * []----
- * | logout_cleanup -- see if the initiator did what was requested
- * |
- * | When a target issues an asynchrouns event with the code set to
- * | "logout requested" the initiator is supposed to respond with
- * | a LogoutRequested PDU within a certain amount of time. If it
- * | fails to do so, it's the targets responsibility to clean up.
- * | We will check logout status in a 1 second interval, if the
- * | initiators responded to the logout request then logout is
- * | conpleted, if ASYNC_LOGOUT_TIMEOUT seconds (currently 10)
- * | is reached then we will reissue the management request to
- * | to logout which will cause the connections to close.
- * []----
- */
-static void *
-logout_cleanup(void *v)
-{
- int msg_sent, i;
- char *targ = (char *)v;
- mgmt_request_t m;
- iscsi_conn_t *conn;
- extern pthread_mutex_t port_mutex;
- Boolean_t logout = False;
-
- bzero(&m, sizeof (m));
- m.m_request = mgmt_logout;
- m.m_q = queue_alloc();
- msg_sent = 0;
-
- /*
- * The for loop is to manage the wait time for the
- * logout request to complete, if logout completed
- * before ASYNC_LOGOUT_TIMEOUT then done
- */
- for (i = 0; i < ASYNC_LOGOUT_TIMEOUT; i++) {
- logout = True;
- (void) pthread_mutex_lock(&port_mutex);
- for (conn = conn_head; conn; conn = conn->c_next) {
- if ((conn->c_state == S7_LOGOUT_REQUESTED) &&
- (strcmp(conn->c_sess->s_t_name, targ) == 0)) {
- logout = False;
- break;
- }
- }
- (void) pthread_mutex_unlock(&port_mutex);
- if (logout)
- break;
- else
- (void) sleep(1);
- }
-
- /*
- * Logout did not complete, queue message to shutdown
- * connection.
- */
- if (logout == False) {
- (void) pthread_mutex_lock(&port_mutex);
- for (conn = conn_head; conn; conn = conn->c_next) {
- if ((conn->c_state == S7_LOGOUT_REQUESTED) &&
- (strcmp(conn->c_sess->s_t_name, targ) == 0)) {
- queue_message_set(conn->c_dataq, 0,
- msg_mgmt_rqst, &m);
- msg_sent++;
- }
- }
- (void) pthread_mutex_unlock(&port_mutex);
- }
-
- /*
- * Wait to see if they received the message.
- */
- for (i = 0; i < msg_sent; i++)
- queue_message_free(queue_message_get(m.m_q));
- queue_free(m.m_q, NULL);
- free(targ);
-
- queue_message_set(mgmtq, 0, msg_pthread_join,
- (void *)(uintptr_t)pthread_self());
- return ((void *)0);
-}
-
-void
-logout_targ(char *targ)
-{
- mgmt_request_t m;
- iscsi_conn_t *conn;
- int i, msg_sent;
- pthread_t junk;
- extern pthread_mutex_t port_mutex;
-
- /*
- * Now we look for connections to this target and issue
- * a request to asynchronously logout.
- */
- bzero(&m, sizeof (m));
- m.m_request = mgmt_logout;
- m.m_q = queue_alloc();
- msg_sent = 0;
-
- (void) pthread_mutex_lock(&port_mutex);
- for (conn = conn_head; conn; conn = conn->c_next) {
- if (conn->c_state != S5_LOGGED_IN)
- continue;
- if (conn->c_sess->s_type == SessionDiscovery)
- continue;
-
- if (strcmp(conn->c_sess->s_t_name, targ) == 0) {
- queue_message_set(conn->c_dataq, 0, msg_mgmt_rqst, &m);
- msg_sent++;
- }
- }
- (void) pthread_mutex_unlock(&port_mutex);
-
- /* ---- Wait to see if they received the message. ---- */
- for (i = 0; i < msg_sent; i++)
- queue_message_free(queue_message_get(m.m_q));
-
- queue_free(m.m_q, NULL);
-
- /* ---- Start housecleaning thread ---- */
- (void) pthread_create(&junk, NULL, logout_cleanup,
- (void *)strdup(targ));
-}
-
-/*
- * [] ---- XML Management Handlers ---- []
- */
-
-/*
- * []----
- * | variable_handler -- used to set a couple of internal global variables
- * []----
- */
-/*ARGSUSED*/
-void
-variable_handler(tgt_node_t *x, target_queue_t *reply, target_queue_t *mgmt,
- ucred_t *cred)
-{
- char *reply_buf = NULL;
- var_table_t *v;
- tgt_node_t *c;
-
- if (check_auth_modify(cred) != True) {
- xml_rtn_msg(&reply_buf, ERR_NO_PERMISSION);
- queue_str(reply, 0, msg_mgmt_rply, reply_buf);
- return;
- }
- for (c = x->x_child; c; c = c->x_sibling) {
-
- for (v = var_table; v->v_name; v++) {
- if (strcmp(c->x_name, v->v_name) == 0) {
- *v->v_value = strtol(c->x_value, NULL, 0);
- if (strcmp(v->v_name, "qlog_lvl") == 0)
- queue_log(True);
- xml_rtn_msg(&reply_buf, ERR_SUCCESS);
- break;
- }
- }
- if (v->v_name == NULL)
- xml_rtn_msg(&reply_buf, ERR_NO_MATCH);
-
- queue_str(reply, 0, msg_mgmt_rply, reply_buf);
- }
-}
-
-/*
- * []----
- * | parse_xml -- incoming management requests are sent here for processing
- * []----
- */
-static void
-parse_xml(tgt_node_t *x, target_queue_t *reply, target_queue_t *mgmt,
- ucred_t *cred)
-{
- char *reply_msg = NULL;
- cmd_table_t *c;
-
- if ((x->x_name == NULL) || (x->x_state == NodeFree)) {
- xml_rtn_msg(&reply_msg, ERR_SYNTAX_EMPTY);
- queue_message_set(reply, 0, msg_mgmt_rply, reply_msg);
- return;
- }
-
- for (c = cmd_table; c->c_name != NULL; c++)
- if (strcmp(c->c_name, x->x_name) == 0)
- break;
- if (c->c_name == NULL) {
- xml_rtn_msg(&reply_msg, ERR_INVALID_COMMAND);
- queue_message_set(reply, 0, msg_mgmt_rply, reply_msg);
- } else {
- (c->c_func)(x, reply, mgmt, cred);
- }
-}
-
-/*
- * space_message -- create a message indicating the amount of space needed.
- *
- * This code could have been inline in the server_for_door function, but
- * at system startup we'll determine the minimum amount of space needed for
- * a door call return pointer. This minimum amount of space will be either
- * a "need more space" or a "success" message. So, have this code as a function
- * reduces any duplication.
- */
-static void
-space_message(char **buf, int size)
-{
- char lbuf[16];
- tgt_buf_add_tag_and_attr(buf, XML_ELEMENT_ERROR, "version='1.0'");
- (void) snprintf(lbuf, sizeof (lbuf), "%d", size);
- tgt_buf_add(buf, XML_ELEMENT_MORESPACE, lbuf);
- tgt_buf_add_tag(buf, XML_ELEMENT_ERROR, Tag_End);
-}
-
-/*ARGSUSED*/
-static void
-server_for_door(void *cookie, char *argp, size_t arg_size, door_desc_t *dp,
- uint_t n_desc)
-{
- target_queue_t *mgmtq = (target_queue_t *)cookie;
- mgmt_request_t m;
- msg_t *msg = NULL;
- tgt_node_t *node = NULL;
- xmlTextReaderPtr r;
- char *err_rply = NULL;
- ucred_t *uc = NULL;
- size_t cur_space;
-
- /*
- * A well written application will always give us enough space
- * to send either a "success" message or a "more space needed".
- * If the minimum amount of space isn't given then just return
- * with a NULL pointer.
- */
- if (arg_size < door_min_space) {
- (void) door_return(NULL, 0, NULL, 0);
- return;
- }
-
- /*
- * Pick up the user credentials of the client application. Used to
- * validate that the effective user ID is either root or the process
- * has the privilege to complete the operation.
- */
- if (door_ucred(&uc) != 0) {
- xml_rtn_msg(&err_rply, ERR_BAD_CREDS);
- (void) strlcpy(argp, err_rply, arg_size);
- free(err_rply);
- (void) door_return(argp, strlen(argp) + 1, NULL, 0);
- return;
- }
-
- if (validate_xml(argp) != True) {
- xml_rtn_msg(&err_rply, ERR_INVALID_XML_REQUEST);
- (void) strlcpy(argp, err_rply, arg_size);
- free(err_rply);
- (void) door_return(argp, strlen(argp) + 1, NULL, 0);
- return;
- }
-
- bzero(&m, sizeof (m));
-
- if ((r = (xmlTextReaderPtr)xmlReaderForMemory(argp, strlen(argp),
- NULL, NULL, 0)) != NULL) {
- while (xmlTextReaderRead(r)) {
- if (tgt_node_process(r, &node) == False)
- break;
- }
- if (node != NULL) {
- m.m_q = queue_alloc();
- m.m_request = mgmt_parse_xml;
- m.m_time = time(NULL);
- m.m_targ_name = NULL;
- m.m_u.m_node = node;
- m.m_cred = uc;
-
- queue_message_set(mgmtq, 0, msg_mgmt_rqst, &m);
- if ((msg = queue_message_get(m.m_q)) == NULL) {
- (void) xmlFreeTextReader(r);
- (void) xmlCleanupParser();
- (void) ucred_free(uc);
- tgt_node_free(node);
- if (m.m_q != NULL)
- queue_free(m.m_q, NULL);
- (void) door_return("", 1, NULL, 0);
- return;
- }
-
- /*
- * Check to see if the response can fit into the
- * incoming argument buffer. If so, copy the response
- * to that buffer so that we can free the data.
- * If it's not big enough we'll request an updated
- * space message, then delete the current data, allowing
- * the request to be requeued again.
- */
- if ((cur_space = strlen(msg->msg_data)) < arg_size) {
- (void) strlcpy(argp, msg->msg_data, arg_size);
- } else {
- /*
- * err_rply will be copied to argp at the end
- */
- space_message(&err_rply, cur_space + 1);
- }
- free(msg->msg_data);
- queue_message_free(msg);
- } else {
- xml_rtn_msg(&err_rply, ERR_NULL_XML_MESSAGE);
- }
-
- xmlFreeTextReader(r);
- xmlCleanupParser();
-
- } else {
- xml_rtn_msg(&err_rply, ERR_INIT_XML_READER_FAILED);
- }
-
- if (node != NULL)
- tgt_node_free(node);
- if (err_rply != NULL) {
- (void) strlcpy(argp, err_rply, arg_size);
- free(err_rply);
- }
- if (m.m_q != NULL)
- queue_free(m.m_q, NULL);
-
- ucred_free(uc);
- (void) door_return(argp, strlen(argp) + 1, NULL, 0);
-}
-
-/*
- * []----
- * | setup_door -- Create a door portal for management requests
- * |
- * | First check to see if another daemon is already running by attempting
- * | to send an empty request to the door. If successful it means this
- * | daemon should exit.
- * []----
- */
-static void
-setup_door(target_queue_t *q, char *door_name)
-{
- int did, fd;
- struct stat s;
- door_arg_t d;
- char *msg = NULL;
-
- /*
- * Figure out what the minimum amount of space required to send back
- * either a success message or a need more space one.
- *
- * Commands fall into one of three categories.
- * (1) Idempotent commands, like list operations, which can
- * return large ammounts of data. If there's not enough room
- * the client is informed and the command is run again with a
- * larger buffer.
- * (2) Create, modify, or delete operations that fail. These
- * commands may return an error message which is larger than
- * the incoming request buffer. If so, the client is informed
- * that a larger buffer is needed and the command is rerun. This
- * time it'll recieve the full error message. So, these commands
- * are idempotent because no state changes occur on failure.
- * (3) Create, modify, or delete operations which are successful.
- * Since successful completion means state has change the daemon
- * must always be able to report success, other wise a second
- * attempt with a larger buffer would then fail, where the first
- * one actually succeeded.
- */
- xml_rtn_msg(&msg, ERR_SUCCESS);
- door_min_space = strlen(msg);
- free(msg);
- msg = NULL;
- /*
- * Use an impossibly big number which will create the longest string
- */
- space_message(&msg, 0x80000000);
- door_min_space = MAX(door_min_space, strlen(msg));
- free(msg);
-
- door_min_space++; /* add 1 for the NULL byte */
-
- /*
- * DOOR_MIN_SPACE will be the amount used by the library as the default.
- * Currently this will be set to 128 (check iscsitgt_impl.h for value).
- * Since this will be a compiled value and the "success" or "more space"
- * messages could grown we need to detect if there will be a problem.
- * By failing here consistently, SMF will put the daemon in maintenance
- * state and this will be caught during testing. Otherwise the library
- * would receive a NULL back, but not know how much space is really
- * required.
- */
- if (door_min_space > DOOR_MIN_SPACE) {
- syslog(LOG_ERR,
- "Calculated min space (%d) is larger than default (%d)",
- door_min_space, DOOR_MIN_SPACE);
- assert(0);
- }
-
- if ((fd = open(door_name, 0)) >= 0) {
-
- /*
- * There's at least a file with the same name as our
- * door. Let's see if someone is currently answering
- * by sending an empty XML request.
- */
- d.data_ptr = "<config></config>";
- d.data_size = strlen(d.data_ptr) + 1;
- d.desc_ptr = NULL;
- d.desc_num = 0;
- d.rbuf = NULL;
- d.rsize = 0;
-
- if (door_call(fd, &d) == 0) {
-
- /*
- * If the door_call succeeds that means another
- * daemon is already running so let's just exit.
- */
- exit(0);
- }
- (void) close(fd);
- }
-
- if ((did = door_create(server_for_door, (void *)q, 0)) < 0) {
- syslog(LOG_ERR, "door_create");
- exit(1);
- }
-
- if (stat(door_name, &s) < 0) {
- int newfd;
- if ((newfd = creat(door_name, 0666)) < 0) {
- syslog(LOG_ERR, "creat failed");
- exit(1);
- }
- (void) close(newfd);
- }
- (void) fdetach(door_name);
-
- /*
- * Open the door for general access. As the calls come in we'll
- * get the credentials and validate within each operation as to the
- * required privileges.
- */
- (void) chmod(door_name, 0666);
-
- if (fattach(did, door_name) < 0) {
- syslog(LOG_ERR, "fattach failed errno=%d", errno);
- exit(2);
- }
-}
-
-/*ARGSUSED*/
-void
-exit_after_door_setup(int sig, siginfo_t *sip, void *v)
-{
- exit(SMF_EXIT_OK);
-}
-
-int
-main(int argc, char **argv)
-{
- char c, *p, *door_name;
- msg_t *msg;
- target_queue_t *q;
- port_args_t port1, port2;
- Boolean_t mgmt_up = False;
- Boolean_t daemonize = True;
- Boolean_t console_output = True;
- pthread_t junk;
- mgmt_request_t *mgmt;
- struct sigaction act;
- struct rlimit rl;
- void *thr_status;
-
- door_name = ISCSI_TARGET_MGMT_DOOR;
-
- while ((c = getopt(argc, argv, "c:d:")) != EOF) {
- switch (c) {
- case 'c':
- config_file = optarg;
- break;
- case 'd':
- door_name = optarg;
- break;
- }
- }
-
- /*
- * If the initiator closes the socket because of a protocol error
- * or bad digest on the header packet we'll receive a SIGPIPE if we're
- * in the middle of a write operation. There's no need to receive
- * a signal when a -1 from the write will handle things correctly.
- * So, ignore SIGPIPE's.
- */
- (void) sigignore(SIGPIPE);
-
- /*
- * Setup memory caches
- */
- if ((iscsi_cmd_cache = umem_cache_create("iSCSI conn cmds",
- sizeof (iscsi_cmd_t), 8, NULL, NULL, NULL, NULL, NULL, 0)) ==
- NULL) {
- perror("cache create");
- exit(SMF_EXIT_ERR_CONFIG);
- }
- if ((t10_cmd_cache = umem_cache_create("T10 cmds",
- sizeof (t10_cmd_t), 8, NULL, NULL, NULL, NULL, NULL, 0)) == NULL) {
- perror("cache create");
- exit(SMF_EXIT_ERR_CONFIG);
- }
- if ((queue_cache = umem_cache_create("Queue messages",
- sizeof (msg_t), 8, NULL, NULL, NULL, NULL, NULL, 0)) == NULL) {
- perror("cache create");
- exit(SMF_EXIT_ERR_CONFIG);
- }
-
- /*
- * Look at the function lu_buserr_handler() in t10_sam.c to see the
- * details of why we need to handle segmentation violations.
- */
- bzero(&act, sizeof (act));
- act.sa_sigaction = lu_buserr_handler;
- act.sa_flags = SA_SIGINFO;
-
- if (sigaction(SIGBUS, &act, NULL) == -1) {
- perror("sigaction");
- exit(SMF_EXIT_ERR_CONFIG);
- }
-
-
- if (mgmt_convert_conf() == CONVERT_FAIL)
- exit(SMF_EXIT_ERR_CONFIG);
-
- if (process_config() == False)
- exit(SMF_EXIT_ERR_CONFIG);
-
- /*
- * During the normal corse of events 'target_basedir' will be
- * free when the administrator changes the base directory. Instead
- * of trying to check for the initial case of this value being set
- * to some static string, always allocate that string.
- * NOTE: This must be done *after* process_config() is called since
- * it's possible and very likely that this value will be set at that
- * time.
- */
- if (target_basedir == NULL)
- target_basedir = strdup(DEFAULT_TARGET_BASEDIR);
-
- (void) tgt_find_value_boolean(main_config, XML_ELEMENT_DBGDAEMON,
- &daemonize);
-
- q = queue_alloc();
- if (daemonize == True) {
- closefrom(0);
-
- /*
- * Set up a signal handler to catch SIGUSR2. Once the child
- * has setup the door, it will signal the parent that it's
- * safe to exit. Without doing this it's possible that the
- * daemon will start and the parent exit before the child has
- * setup the door. If that happens 'zfs share -a iscsi' which
- * is run from svc-iscsitgt will fail to open the door and try
- * to wait for the iscsitgt service to come online. Since
- * the zfs command is part of the service start, the service
- * will not come online and we'll fail to share any ZVOLs.
- */
- bzero(&act, sizeof (act));
- act.sa_sigaction = exit_after_door_setup;
- act.sa_flags = SA_SIGINFO;
- if (sigaction(SIGUSR2, &act, NULL) == -1) {
- perror("sigaction");
- exit(SMF_EXIT_ERR_CONFIG);
- }
-
- switch (fork()) {
- case 0:
- /*
- * As the child process, setup the door and then
- * signal the parent that it can exit since the child
- * is now ready to start accepting requests on the
- * door.
- */
- setup_door(q, door_name);
- (void) kill(getppid(), SIGUSR2);
- break;
-
- case -1:
- /* ---- Failed to fork!. Trouble ---- */
- exit(SMF_EXIT_ERR_CONFIG);
-
- default:
- /*
- * If pause() returns with an error something
- * interrupted the process which was not a SIGUSR2.
- * Exit with an error code such that SMF can flag
- * this problem.
- */
- if (pause() == -1)
- exit(SMF_EXIT_ERR_CONFIG);
- }
- } else {
-
- /*
- * The daemon is working in debug mode, so go ahead and
- * setup the door now.
- */
- setup_door(q, door_name);
- }
-
- /*
- * Initialize the various subsystems. In most cases these are
- * just initializing mutexs.
- */
- (void) pthread_rwlock_init(&targ_config_mutex, NULL);
- iscsi_cmd_init();
- session_init();
- t10_init(q);
- port_init();
- queue_init();
- util_init();
- (void) isns_init(q);
-
- /*
- * If there's no MAC address currently available don't worry about
- * it. The first time an initiator connects the SAM-3 layer will
- * attempt to create a GUID and force another look for a MAC address.
- */
- if (if_find_mac(q) == False)
- queue_prt(q, Q_GEN_DETAILS, "MAIN: No MAC address available");
-
- /*
- * At a minimum we need two file descriptors for each target, one for
- * the socket and one for the backing store. If there's more than one
- * initiator attached to a given target than that number goes up by 1.
- * Once we have multiple sessions per connection that to will cause
- * an increase.
- */
- if ((getrlimit(RLIMIT_NOFILE, &rl) == 0) &&
- (rl.rlim_cur < TARGET_NOFILE)) {
- rl.rlim_cur = TARGET_NOFILE;
- if (setrlimit(RLIMIT_NOFILE, &rl) != 0)
- syslog(LOG_NOTICE,
- "Can't set new limit for open files");
- }
-
- port1.port_mgmtq = q;
- port1.port_num = iscsi_port;
- (void) pthread_create(&junk, NULL, port_watcher, &port1);
-
- if ((tgt_find_value_int(main_config, XML_ELEMENT_MGMTPORT,
- &port2.port_num) == True) && (port2.port_num != -1)) {
- port2.port_mgmtq = q;
- port2.port_dataq = queue_alloc();
- (void) pthread_create(&junk, NULL, port_management, &port2);
- }
-
- do {
- msg = queue_message_get(q);
-
- switch (msg->msg_type) {
- case msg_pthread_join:
- (void) pthread_join((pthread_t)(uintptr_t)msg->msg_data,
- &thr_status);
- if (thr_status != 0)
- queue_prt(q, Q_GEN_ERRS,
- "Thread %d exit with %d",
- msg->msg_data, thr_status);
- msg->msg_data = NULL;
- break;
-
- case msg_log:
- if ((p = strchr(msg->msg_data, '\n')) != NULL)
- *p = '\0';
- p = (char *)msg->msg_data;
- if ((msg->msg_pri_level & dbg_lvl) == 0)
- break;
-
- if (mgmt_up == True)
- queue_str(port2.port_dataq, Q_GEN_DETAILS,
- msg_log, p);
- if (console_output == True)
- (void) printf("%s\n", p);
- break;
-
- case msg_mgmt_rqst:
- mgmt = (mgmt_request_t *)msg->msg_data;
- if (mgmt->m_request == mgmt_parse_xml)
- parse_xml(mgmt->m_u.m_node, mgmt->m_q, q,
- mgmt->m_cred);
- msg->msg_data = NULL;
- break;
-
- case msg_status:
- p = (char *)msg->msg_data;
- /*
- * NOTE:
- * These are real error conditons being sent from
- * the other threads and should be logged in
- * some manner, either syslog() or using a FMA
- * interface.
- */
- (void) printf("STATUS: %s\n", p);
- break;
-
- default:
- break;
- }
-
- if (msg->msg_data != NULL)
- free(msg->msg_data);
- queue_message_free(msg);
- /*CONSTANTCONDITION*/
- } while (1);
-
- return (0);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/mgmt.c b/usr/src/cmd/iscsi/iscsitgtd/mgmt.c
deleted file mode 100644
index e0af446b8e..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <stdio.h>
-#include <unistd.h>
-#include <strings.h>
-#include <stdlib.h>
-#include <poll.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <netinet/in.h>
-#include <sys/filio.h>
-#include <utility.h>
-#include <synch.h>
-#include <sys/stropts.h>
-#include <libxml/xmlreader.h>
-#include <iscsitgt_impl.h>
-
-#include "queue.h"
-#include "port.h"
-#include "utility.h"
-
-static void
-mgmt_monitor_queue(port_args_t *p)
-{
- target_queue_t *in = p->port_dataq;
- msg_t *m;
- int process = True;
- char *data,
- *output;
-
- do {
- m = queue_message_get(in);
- switch (m->msg_type) {
- case msg_conn_lost:
- process = False;
- break;
-
- case msg_log:
- data = (char *)m->msg_data;
- output = NULL;
- tgt_buf_add(&output, "log", data);
- (void) write(p->port_socket, output, strlen(output));
- free(output);
- break;
-
- case msg_mgmt_rply:
- data = (char *)m->msg_data;
- output = NULL;
- tgt_buf_add(&output, "mgmt", data);
- (void) write(p->port_socket, output, strlen(output));
- free(output);
- free(data);
- m->msg_data = NULL;
- break;
-
- default:
- break;
- }
-
- if (m->msg_data)
- free(m->msg_data);
- queue_message_free(m);
-
- } while (process == True);
-}
-
-static void *
-mgmt_process(void *v)
-{
- port_args_t *p = (port_args_t *)v;
- int nbytes,
- nmsgs,
- pval,
- ret;
- char *buf;
- nfds_t nfds = 1;
- struct pollfd fds[1];
- xmlTextReaderPtr r;
- tgt_node_t *node = NULL;
- mgmt_request_t m;
-
- fds[0].fd = p->port_socket;
- fds[0].events = POLLIN;
-
- m.m_q = p->port_dataq;
- m.m_request = mgmt_parse_xml;
- m.m_time = time(NULL);
- m.m_targ_name = NULL;
-
- while ((pval = poll(fds, nfds, -1)) != -1) {
- if ((nmsgs = ioctl(p->port_socket, FIONREAD, &nbytes)) == -1) {
-
- queue_message_set(p->port_dataq, 0, msg_conn_lost, 0);
- break;
-
- } else if ((nmsgs == 0) && (nbytes == 0)) {
-
- queue_message_set(p->port_dataq, 0, msg_conn_lost, 0);
- break;
-
- } else if ((buf = malloc(nbytes)) == NULL) {
-
- queue_message_set(p->port_dataq, 0, msg_conn_lost, 0);
- break;
-
- } else if (read(p->port_socket, buf, nbytes) != nbytes) {
-
- queue_message_set(p->port_dataq, 0, msg_conn_lost, 0);
- break;
-
- }
-
- buf[nbytes] = '\0';
- r = (xmlTextReaderPtr)xmlReaderForMemory(buf, nbytes,
- NULL, NULL, 0);
- if (r != NULL) {
- ret = xmlTextReaderRead(r);
- while (ret == 1) {
- if (tgt_node_process(r, &node) == False)
- break;
- ret = xmlTextReaderRead(r);
- }
- if (node != NULL) {
- m.m_u.m_node = node;
- queue_message_set(p->port_mgmtq, 0,
- msg_mgmt_rqst, &m);
- }
- xmlFreeTextReader(r);
- tgt_node_free(node);
- node = NULL;
- }
-
- }
-
- if (pval == -1)
- queue_message_set(p->port_dataq, 0, msg_conn_lost, 0);
- (void) close(p->port_socket);
- p->port_socket = -1;
- return (NULL);
-}
-
-void *
-port_management(void *v)
-{
- int s,
- fd,
- on = 1;
- struct sockaddr_in sin_ip;
- struct sockaddr_in6 sin6_ip;
- socklen_t fromlen;
- struct sockaddr_storage from;
- port_args_t *p = (port_args_t *)v;
- target_queue_t *q = p->port_mgmtq;
- int l;
- pthread_t junk;
- char debug[80];
-
- if ((s = socket(PF_INET6, SOCK_STREAM, 0)) == -1) {
- if ((s = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
- queue_str(q, Q_GEN_ERRS, msg_status,
- "Can't open socket");
- return (NULL);
- } else {
-
- bzero(&sin_ip, sizeof (sin_ip));
- sin_ip.sin_family = AF_INET;
- sin_ip.sin_port = htons(p->port_num);
- sin_ip.sin_addr.s_addr = INADDR_ANY;
-
- (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
- (char *)&on, sizeof (on));
-
- if ((bind(s, (struct sockaddr *)&sin_ip,
- sizeof (sin_ip))) < 0) {
- (void) snprintf(debug, sizeof (debug),
- "bind on port %d failed\n", p->port_num);
- queue_str(q, Q_GEN_ERRS, msg_status, debug);
- return (NULL);
- }
- }
- } else {
-
- bzero(&sin6_ip, sizeof (sin6_ip));
- sin6_ip.sin6_family = AF_INET6;
- sin6_ip.sin6_port = htons(p->port_num);
- sin6_ip.sin6_addr = in6addr_any;
-
- (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
- sizeof (on));
-
- if ((bind(s, (struct sockaddr *)&sin6_ip, sizeof (sin6_ip)))
- < 0) {
- (void) snprintf(debug, sizeof (debug),
- "bind on port %d failed\n",
- p->port_num);
- queue_str(q, Q_GEN_ERRS, msg_status, debug);
- return (NULL);
- }
- }
-
- if (listen(s, 5) < 0) {
- queue_str(q, Q_GEN_ERRS, msg_status, "listen failed");
- return (NULL);
- }
-
- /*CONSTANTCONDITION*/
- while (1) {
- fromlen = sizeof (from);
- if ((fd = accept(s, (struct sockaddr *)&from,
- &fromlen)) < 0) {
- queue_str(q, Q_GEN_ERRS, msg_status, "accept failed");
- return (NULL);
- }
-
- l = 128 * 1024;
- if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&l,
- sizeof (l)) < 0)
- queue_str(q, Q_GEN_ERRS, msg_status,
- "setsockopt failed");
-
- if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&l,
- sizeof (l)) < 0)
- queue_str(q, Q_GEN_ERRS, msg_status,
- "setsockopt failed");
-
-
- p->port_socket = fd;
- (void) pthread_create(&junk, NULL, mgmt_process, p);
-
- mgmt_monitor_queue(p);
- }
- return (NULL);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c b/usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c
deleted file mode 100644
index fffd6e99df..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c
+++ /dev/null
@@ -1,1447 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <ctype.h>
-#include <sys/types.h>
-#include <time.h>
-#include <sys/utsname.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
-#include <errno.h>
-#include <strings.h>
-#include <sys/vtoc.h>
-#include <sys/efi_partition.h>
-#include <uuid/uuid.h>
-#include <sys/scsi/impl/uscsi.h>
-#include <sys/scsi/generic/commands.h>
-#include <sys/scsi/impl/commands.h>
-#include <libzfs.h>
-#include <syslog.h>
-#include <priv.h>
-
-#include <iscsitgt_impl.h>
-#include "queue.h"
-#include "target.h"
-#include "iscsi_cmd.h"
-#include "utility.h"
-#include "errcode.h"
-#include "t10_spc.h"
-#include "isns_client.h"
-#include "mgmt_scf.h"
-
-extern char *getfullrawname();
-
-static char *create_target(tgt_node_t *);
-static char *create_initiator(tgt_node_t *);
-static char *create_tpgt(tgt_node_t *);
-static char *create_zfs(tgt_node_t *, ucred_t *);
-static Boolean_t create_target_dir(char *targ_name, char *local_name);
-static char *create_node_name(char *local_nick, char *alias);
-static Boolean_t create_lun(char *targ_name, char *local_name, char *type,
- int lun, char *size_str, char *backing, err_code_t *code);
-static Boolean_t create_lun_common(char *targ_name, char *local_name, int lun,
- uint64_t size, err_code_t *code);
-static Boolean_t setup_disk_backing(err_code_t *code, char *path, char *backing,
- tgt_node_t *n, uint64_t *size);
-static Boolean_t setup_raw_backing(err_code_t *code, char *path, char *backing,
- uint64_t *size);
-
-/*
- * []----
- * | create_func -- Branch out to appropriate object create function
- * []----
- */
-/*ARGSUSED*/
-void
-create_func(tgt_node_t *p, target_queue_t *reply, target_queue_t *mgmt,
- ucred_t *cred)
-{
- tgt_node_t *x;
- char msgbuf[80];
- char *reply_msg = NULL;
-
- x = p->x_child;
-
- /*
- * create_zfs() does not affect SMF data
- * therefore it is not covered by auth check
- */
- if (x == NULL) {
- xml_rtn_msg(&reply_msg, ERR_SYNTAX_MISSING_OBJECT);
- } else if (strcmp(x->x_name, XML_ELEMENT_ZFS) == 0) {
- reply_msg = create_zfs(x, cred);
- } else if (check_auth_addremove(cred) != True) {
- xml_rtn_msg(&reply_msg, ERR_NO_PERMISSION);
- } else {
- if (x->x_name == NULL) {
- xml_rtn_msg(&reply_msg, ERR_SYNTAX_MISSING_OBJECT);
- } else if (strcmp(x->x_name, XML_ELEMENT_TARG) == 0) {
- reply_msg = create_target(x);
- } else if (strcmp(x->x_name, XML_ELEMENT_INIT) == 0) {
- reply_msg = create_initiator(x);
- } else if (strcmp(x->x_name, XML_ELEMENT_TPGT) == 0) {
- reply_msg = create_tpgt(x);
- } else {
- (void) snprintf(msgbuf, sizeof (msgbuf),
- "Unknown object '%s' for create element",
- x->x_name);
- xml_rtn_msg(&reply_msg, ERR_INVALID_OBJECT);
- }
- }
- queue_message_set(reply, 0, msg_mgmt_rply, reply_msg);
-}
-
-/*
- * create_target -- an administrative request to create a target
- */
-static char *
-create_target(tgt_node_t *x)
-{
- char *msg = NULL;
- char *name = NULL;
- char *alias = NULL;
- char *size = NULL;
- char *type = NULL;
- char *backing = NULL;
- char *node_name = NULL;
- char path[MAXPATHLEN];
- int lun = 0; /* default to LUN 0 */
- int i;
- tgt_node_t *n, *c, *l;
- err_code_t code;
-
- (void) pthread_rwlock_wrlock(&targ_config_mutex);
- (void) tgt_find_value_str(x, XML_ELEMENT_BACK, &backing);
- (void) tgt_find_value_str(x, XML_ELEMENT_ALIAS, &alias);
- if (tgt_find_value_intchk(x, XML_ELEMENT_LUN, &lun) == False) {
- xml_rtn_msg(&msg, ERR_LUN_INVALID_RANGE);
- goto error;
- }
-
- /*
- * We've got to have a name element or all bets are off.
- */
- if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
- goto error;
- }
-
- /*
- * RFC3722 states that names must be one of:
- * (1) a..z
- * (2) A..Z
- * (3) 0-9
- * or
- * (4) ':', '.', '-'
- * If it's an upper case character is must be made lower
- * case.
- */
- for (i = 0; i < strlen(name); i++) {
- if (!isalnum(name[i]) &&
- (name[i] != ':') && (name[i] != '.') && (name[i] != '-')) {
- xml_rtn_msg(&msg, ERR_SYNTAX_INVALID_NAME);
- goto error;
- } else if (isupper(name[i]))
- name[i] = tolower(name[i]);
- }
-
- if (tgt_find_value_str(x, XML_ELEMENT_TYPE, &type) == False) {
- /*
- * If a type hasn't been specified default to disk emulation.
- * We use strdup() since at the end of this routine the code
- * is expecting to free 'type' along with other strings.
- */
- type = strdup(TGT_TYPE_DISK);
- }
-
- if ((strcmp(type, "raw") == 0) && (backing == NULL)) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_BACKING_STORE);
- goto error;
- }
-
- if (tgt_find_value_str(x, XML_ELEMENT_SIZE, &size) == False) {
- if (backing != NULL) {
-
- /*
- * If a backing store has been provided we don't
- * need the size since we can determine that from
- * a READ_CAPACITY command which everyone issues.
- *
- * NOTE: strdup is used here, since at the end
- * of this routine any of the string pointers which
- * are non-NULL get freed.
- */
- size = strdup("0");
- } else {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_SIZE);
- goto error;
- }
- }
- if ((lun < 0) || (lun > T10_MAX_LUNS)) {
- xml_rtn_msg(&msg, ERR_LUN_INVALID_RANGE);
- goto error;
- }
-
- /*
- * See if we already have a local target name created. If so,
- * the user is most likely wanting to create another LUN for this
- * target. Checking to see if there's a duplicate LUN will be
- * done later.
- */
- for (n = main_config->x_child; n; n = n->x_sibling) {
- if (strcmp(n->x_value, name) == 0)
- break;
- }
-
- if (n == NULL) {
- if (lun != 0) {
- xml_rtn_msg(&msg, ERR_LUN_ZERO_NOT_FIRST);
- goto error;
- }
- if ((node_name = create_node_name(name, alias)) == NULL) {
- xml_rtn_msg(&msg, ERR_CREATE_NAME_TOO_LONG);
- goto error;
- }
- if (create_target_dir(node_name, name) == False) {
- xml_rtn_msg(&msg, ERR_CREATE_TARGET_DIR_FAILED);
- goto error;
- }
- n = tgt_node_alloc(XML_ELEMENT_TARG, String, name);
- c = tgt_node_alloc(XML_ELEMENT_INAME, String, node_name);
- tgt_node_add(n, c);
- c = tgt_node_alloc(XML_ELEMENT_LUNLIST, String, "");
- l = tgt_node_alloc(XML_ELEMENT_LUN, Int, &lun);
- tgt_node_add(c, l);
- tgt_node_add(n, c);
- if (alias != NULL) {
- c = tgt_node_alloc(XML_ELEMENT_ALIAS, String, alias);
- tgt_node_add(n, c);
- }
- tgt_node_add(targets_config, n);
-
- } else {
- if (tgt_find_value_str(n, XML_ELEMENT_INAME,
- &node_name) == False) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_INAME);
- goto error;
- }
- if ((c = tgt_node_next(n, XML_ELEMENT_LUNLIST, NULL)) == NULL) {
- xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
- goto error;
- }
- l = tgt_node_alloc(XML_ELEMENT_LUN, Int, &lun);
- tgt_node_add(c, l);
- }
-
- if (create_lun(node_name, name, type, lun, size, backing, &code)
- == True) {
- if (mgmt_config_save2scf() == False) {
- xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
- goto error;
- }
-
- /* Only isns register on the 1st creation of the target */
- if (lun == 0 && isns_enabled() == True) {
- if (isns_reg(node_name) != 0) {
- xml_rtn_msg(&msg, ERR_ISNS_ERROR);
- goto error;
- }
- }
-
- } else if ((lun == 0) && (code != ERR_LUN_EXISTS)) {
-
- /*
- * The first LU will have created the directory and
- * symbolic link. Remove those on error.
- */
- (void) snprintf(path, sizeof (path), "%s/%s",
- target_basedir, node_name);
- (void) rmdir(path);
- (void) snprintf(path, sizeof (path), "%s/%s",
- target_basedir, name);
- (void) unlink(path);
- (void) tgt_node_remove(targets_config, n, MatchBoth);
- } else
- (void) tgt_node_remove(c, l, MatchBoth);
-
- xml_rtn_msg(&msg, code);
-
-error:
- if (name != NULL)
- free(name);
- if (size != NULL)
- free(size);
- if (alias != NULL)
- free(alias);
- if (backing != NULL)
- free(backing);
- if (node_name != NULL)
- free(node_name);
- if (type != NULL)
- free(type);
-
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (msg);
-}
-
-static char *
-create_initiator(tgt_node_t *x)
-{
- char *msg = NULL;
- char *name = NULL;
- char *iscsi_name = NULL;
- tgt_node_t *inode = NULL;
- tgt_node_t *n, *c;
-
- (void) pthread_rwlock_wrlock(&targ_config_mutex);
- if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
- goto error;
- }
- if (tgt_find_value_str(x, XML_ELEMENT_INAME, &iscsi_name) == False) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_INAME);
- goto error;
- }
- if (strlen(iscsi_name) >= ISCSI_MAX_NAME_LEN) {
- xml_rtn_msg(&msg, ERR_NAME_TOO_LONG);
- goto error;
- }
-
- while ((inode = tgt_node_next_child(main_config, XML_ELEMENT_INIT,
- inode)) != NULL) {
- if (strcmp(inode->x_value, name) == 0) {
- xml_rtn_msg(&msg, ERR_INIT_EXISTS);
- goto error;
- }
- }
-
- n = tgt_node_alloc(XML_ELEMENT_INIT, String, name);
- c = tgt_node_alloc(XML_ELEMENT_INAME, String, iscsi_name);
- tgt_node_add(n, c);
- tgt_node_add(main_config, n);
-
- if (mgmt_config_save2scf() == True)
- xml_rtn_msg(&msg, ERR_SUCCESS);
- else
- xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
-
-error:
- if (name)
- free(name);
- if (iscsi_name)
- free(iscsi_name);
-
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (msg);
-}
-
-static char *
-create_tpgt(tgt_node_t *x)
-{
- char *msg = NULL;
- char *tpgt = NULL;
- char *extra = NULL;
- tgt_node_t *tnode = NULL;
- tgt_node_t *n;
- int tpgt_val;
-
- (void) pthread_rwlock_wrlock(&targ_config_mutex);
- if (tgt_find_value_str(x, XML_ELEMENT_NAME, &tpgt) == False) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
- goto error;
- }
-
- /* ---- Validation checks ---- */
- tpgt_val = strtol(tpgt, &extra, 0);
- if ((extra && (*extra != '\0')) ||
- (tpgt_val < TPGT_MIN) || (tpgt_val > TPGT_MAX)) {
- xml_rtn_msg(&msg, ERR_INVALID_TPGT);
- goto error;
- }
-
- while ((tnode = tgt_node_next_child(main_config, XML_ELEMENT_TPGT,
- tnode)) != NULL) {
- if (strcmp(tnode->x_value, tpgt) == 0) {
- xml_rtn_msg(&msg, ERR_TPGT_EXISTS);
- goto error;
- }
- }
-
- n = tgt_node_alloc(XML_ELEMENT_TPGT, String, tpgt);
- tgt_node_add(main_config, n);
-
- if (mgmt_config_save2scf() == True)
- xml_rtn_msg(&msg, ERR_SUCCESS);
- else
- xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
-
-error:
- if (tpgt)
- free(tpgt);
-
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (msg);
-}
-
-/*
- * create_zfs -- given a dataset, export it through the iSCSI protocol
- *
- * This function is called when someone uses the libiscsitgt function
- * iscsitgt_zfs_share(char *dataset)
- */
-static char *
-create_zfs(tgt_node_t *x, ucred_t *cred)
-{
- char *msg = NULL;
- char *dataset = NULL;
- char *cptr = NULL;
- char path[MAXPATHLEN];
- tgt_node_t *n = NULL;
- tgt_node_t *c;
- tgt_node_t *l;
- uint64_t size;
- int status;
-
- (void) pthread_rwlock_wrlock(&targ_config_mutex);
- /*
- * Extract the dataset name from the arguments passed in
- */
- if (tgt_find_value_str(x, XML_ELEMENT_NAME, &dataset) == False) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
- goto error;
- }
-
- /*
- * Since this is a create, assure that an existing dataset with the
- * same name does not exists
- */
- c = NULL;
- while ((c = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, c))) {
- if (strcmp(c->x_value, dataset) == 0) {
- xml_rtn_msg(&msg, ERR_LUN_EXISTS);
- goto error;
- }
- }
-
- /*
- * See if this is a re-create of a previously create ZVOL target
- * If no shareiscsi properties exists, create a new set of properties
- */
- status = get_zfs_shareiscsi(dataset, &n, &size, cred);
- if ((status != ERR_SUCCESS) && (status != ERR_NULL_XML_MESSAGE)) {
- xml_rtn_msg(&msg, status);
- goto error;
- } else if (status == ERR_NULL_XML_MESSAGE) {
-
- char *name;
- int lun = 0;
- int guid = 0;
- int rpm = DEFAULT_RPM;
- int heads = DEFAULT_HEADS;
- int cylinders = DEFAULT_CYLINDERS;
- int spt = DEFAULT_SPT;
- int bytes_sect = DEFAULT_BYTES_PER;
- int interleave = DEFAULT_INTERLEAVE;
-
- n = tgt_node_alloc(XML_ELEMENT_TARG, String, NULL);
- c = tgt_node_alloc(XML_ELEMENT_INCORE, String, XML_VALUE_TRUE);
- tgt_node_add_attr(n, c);
-
- if (name = create_node_name(NULL, NULL)) {
- c = tgt_node_alloc(XML_ELEMENT_INAME, String, name);
- tgt_node_add(n, c);
- free(name);
- } else {
- xml_rtn_msg(&msg, ERR_CREATE_NAME_TOO_LONG);
- goto error;
- }
-
- c = tgt_node_alloc(XML_ELEMENT_LUNLIST, String, "");
- tgt_node_add(n, c);
-
- l = tgt_node_alloc(XML_ELEMENT_LUN, Int, &lun);
- tgt_node_add(c, l);
-
- c = tgt_node_alloc(XML_ELEMENT_VERS, String, "1.0");
- tgt_node_add_attr(l, c);
-
- c = tgt_node_alloc(XML_ELEMENT_GUID, Int, &guid);
- tgt_node_add(l, c);
-
- c = tgt_node_alloc(XML_ELEMENT_PID, String, DEFAULT_PID);
- tgt_node_add(l, c);
-
- c = tgt_node_alloc(XML_ELEMENT_VID, String, DEFAULT_VID);
- tgt_node_add(l, c);
-
- c = tgt_node_alloc(XML_ELEMENT_DTYPE, String, TGT_TYPE_DISK);
- tgt_node_add(l, c);
-
- create_geom(size, &cylinders, &heads, &spt);
-
- c = tgt_node_alloc(XML_ELEMENT_RPM, Int, &rpm);
- tgt_node_add(l, c);
-
- c = tgt_node_alloc(XML_ELEMENT_HEADS, Int, &heads);
- tgt_node_add(l, c);
-
- c = tgt_node_alloc(XML_ELEMENT_CYLINDERS, Int, &cylinders);
- tgt_node_add(l, c);
-
- c = tgt_node_alloc(XML_ELEMENT_SPT, Int, &spt);
- tgt_node_add(l, c);
-
- c = tgt_node_alloc(XML_ELEMENT_BPS, Int, &bytes_sect);
- tgt_node_add(l, c);
-
- c = tgt_node_alloc(XML_ELEMENT_INTERLEAVE, Int, &interleave);
- tgt_node_add(l, c);
-
- c = tgt_node_alloc(XML_ELEMENT_STATUS, String,
- TGT_STATUS_ONLINE);
- tgt_node_add(l, c);
-
- /*
- * Set the ZFS persisted shareiscsi options
- */
- if ((status = put_zfs_shareiscsi(dataset, n)) != ERR_SUCCESS) {
- xml_rtn_msg(&msg, status);
- goto error;
- }
- } else {
- /*
- * If the was a recreate of a ZVOL iSCSI Target, 'n' is expected
- * to contain the properties for this iSCSI target node
- *
- * Make sure these properties have the "in-core" attribute
- */
- if (tgt_find_attr_str(n, XML_ELEMENT_INCORE, &cptr) == True) {
- if (strcmp(cptr, "true") != 0) {
- free(cptr);
- xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
- goto error;
- }
- free(cptr);
- }
- }
-
- /*
- * Pick up the LU node from the LU List which hangs off of the target
- * node. If either is NULL there's an internal error someplace.
- */
- if (((l = tgt_node_next(n, XML_ELEMENT_LUNLIST, NULL)) == NULL) ||
- ((l = tgt_node_next(l, XML_ELEMENT_LUN, NULL)) == NULL)) {
- xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
- goto error;
- }
-
- /*
- * With ZVOLS, some elements can change everytime we share the dataset.
- * The TargetAlias and backing store can change since these are based on
- * the dataset and the size of the volume. Therefore, these pieces of
- * information are not stored as part of the iscsioptions properity, but
- * are retained in the in-core targets_config
- */
- (void) tgt_update_value_str(n, XML_ELEMENT_TARG, dataset);
- c = tgt_node_alloc(XML_ELEMENT_ALIAS, String, dataset);
- tgt_node_add(n, c);
-
- (void) snprintf(path, sizeof (path), "%s%s", ZVOL_PATH, dataset);
- c = tgt_node_alloc(XML_ELEMENT_BACK, String, path);
- tgt_node_add(l, c);
-
- size /= 512LL;
- c = tgt_node_alloc(XML_ELEMENT_SIZE, Uint64, &size);
- tgt_node_add(l, c);
-
- cptr = NULL;
- if (tgt_find_value_str(n, XML_ELEMENT_INAME, &cptr) != True) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_INAME);
- goto error; /* xml node contruction has an issue. */
- }
-
- /*
- * Add ZVOL target to config of all targets
- */
- tgt_node_add(targets_config, n);
- n = NULL; /* don't remove the node from the targets_config. */
-
- /* register with iSNS */
- if (isns_enabled() == True) {
- if (isns_reg(cptr) != 0) {
- xml_rtn_msg(&msg, ERR_ISNS_ERROR);
- goto error;
- }
- }
-
- xml_rtn_msg(&msg, ERR_SUCCESS);
-
-error:
- if (cptr)
- free(cptr);
- if (dataset)
- free(dataset);
- if (n)
- tgt_node_free(n);
-
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (msg);
-}
-
-/*
- * []------------------------------------------------------------------[]
- * | Utility functions used by the routines above. |
- * []------------------------------------------------------------------[]
- */
-
-/*
- * []----
- * | create_node_name -- Creates the IQN that adhears to RFC3270
- * []----
- */
-static char *
-create_node_name(char *local_nick, char *alias)
-{
- uuid_t id;
- char id_str[37];
- char *p;
- char *anp; /* alias or nick pointer */
-
- if ((p = (char *)malloc(ISCSI_MAX_NAME_LEN)) == NULL)
- return (NULL);
-
- /*
- * Originally we we going to use the machines MAC address and
- * timestamp in hex format. This would be consistent with the
- * Solaris iSCSI initiator and NAS5310. Unfortunately, someone
- * pointed out that there's no requirement that the network
- * interfaces be plumbed before someone attempts to create
- * targets. If the networks aren't plumbed there are no MAC
- * addresses available and we can't use 0 for the MAC address
- * since that would introduce the probability of non-unique
- * IQN names.
- */
- uuid_generate(id);
- uuid_unparse(id, id_str);
- if (snprintf(p, ISCSI_MAX_NAME_LEN, "iqn.1986-03.com.sun:%02d:%s",
- TARGET_NAME_VERS, id_str) > ISCSI_MAX_NAME_LEN) {
- free(p);
- return (NULL);
- }
- if (local_nick || alias) {
- anp = (alias != NULL) ? alias : local_nick;
-
- /*
- * Make sure we still have room to add the alias or
- * local nickname, a '.', and NULL character to the
- * buffer.
- */
- if ((strlen(p) + strlen(anp) + 2) > ISCSI_MAX_NAME_LEN) {
- free(p);
- return (NULL);
- }
- (void) strcat(p, ".");
- (void) strcat(p, anp);
- }
-
- return (p);
-}
-
-/*
- * []----
- * | create_target_dir -- create the target directory
- * []----
- */
-static Boolean_t
-create_target_dir(char *targ_name, char *local_name)
-{
- char path[MAXPATHLEN];
- char sympath[MAXPATHLEN];
-
- if ((mkdir(target_basedir, 0777) == -1) && (errno != EEXIST))
- return (False);
-
- (void) snprintf(path, sizeof (path), "%s/%s", target_basedir,
- targ_name);
- (void) snprintf(sympath, sizeof (sympath), "%s/%s", target_basedir,
- local_name);
-
- if ((mkdir(path, 0777) == -1) && (errno != EEXIST))
- return (False);
-
- /*
- * This symbolic link is here for convenience and nothing more, so if
- * if fails. Oh well.
- */
- (void) symlink(path, sympath);
- return (True);
-}
-
-/*
- * []----
- * | create_lun -- given type, lun, size, backing create LU and params
- * []----
- */
-static Boolean_t
-create_lun(char *targ_name, char *local_name, char *type, int lun,
- char *size_str, char *backing, err_code_t *code)
-{
- uint64_t size, ssize;
- int fd = -1;
- int rpm = DEFAULT_RPM;
- int heads = DEFAULT_HEADS;
- int cylinders = DEFAULT_CYLINDERS;
- int spt = DEFAULT_SPT;
- int bytes_sect = DEFAULT_BYTES_PER;
- int interleave = DEFAULT_INTERLEAVE;
- char *vid = DEFAULT_VID;
- char *pid = DEFAULT_PID;
- char path[MAXPATHLEN];
- tgt_node_t *n = NULL;
- tgt_node_t *pn = NULL;
-
- /*
- * after calling stroll_multipler it's an error for size to be
- * 0, if and only if, the size_str doesn't equal "0". The administrator
- * may want the code to determine the size. This would be the case
- * when the administrator has provide a backing store which exists.
- */
- if ((strtoll_multiplier(size_str, &size) == False) ||
- ((size == 0) && (size_str != NULL) && strcmp(size_str, "0"))) {
- *code = ERR_INVALID_SIZE;
- return (False);
- }
-
- if ((size % 512) != 0) {
- *code = ERR_SIZE_MOD_BLOCK;
- return (False);
- }
-
- /*
- * Make sure we're not trying to recreate an existing LU.
- */
- (void) snprintf(path, sizeof (path), "%s/%s/%s%d", target_basedir,
- targ_name, LUNBASE, lun);
- if (access(path, F_OK) == 0) {
- *code = ERR_LUN_EXISTS;
- return (False);
- }
-
- n = tgt_node_alloc(XML_ELEMENT_PARAMS, String, NULL);
-
- pn = tgt_node_alloc(XML_ELEMENT_VERS, String, "1.0");
- tgt_node_add_attr(n, pn);
-
- pn = tgt_node_alloc(XML_ELEMENT_GUID, String, "0");
- tgt_node_add(n, pn);
- pn = tgt_node_alloc(XML_ELEMENT_PID, String, pid);
- tgt_node_add(n, pn);
- pn = tgt_node_alloc(XML_ELEMENT_VID, String, vid);
- tgt_node_add(n, pn);
- pn = tgt_node_alloc(XML_ELEMENT_DTYPE, String, type);
- tgt_node_add(n, pn);
-
- if (strcmp(type, TGT_TYPE_DISK) == 0) {
-
- (void) snprintf(path, sizeof (path), "%s/%s/lun.%d",
- target_basedir, targ_name, lun);
- if (setup_disk_backing(code, path, backing, n, &size) == False)
- goto error;
-
- create_geom(size, &cylinders, &heads, &spt);
-
- pn = tgt_node_alloc(XML_ELEMENT_RPM, Int, &rpm);
- tgt_node_add(n, pn);
- pn = tgt_node_alloc(XML_ELEMENT_HEADS, Int, &heads);
- tgt_node_add(n, pn);
- pn = tgt_node_alloc(XML_ELEMENT_CYLINDERS, Int, &cylinders);
- tgt_node_add(n, pn);
- pn = tgt_node_alloc(XML_ELEMENT_SPT, Int, &spt);
- tgt_node_add(n, pn);
- pn = tgt_node_alloc(XML_ELEMENT_BPS, Int, &bytes_sect);
- tgt_node_add(n, pn);
- pn = tgt_node_alloc(XML_ELEMENT_INTERLEAVE, Int, &interleave);
- tgt_node_add(n, pn);
- pn = tgt_node_alloc(XML_ELEMENT_STATUS, String,
- TGT_STATUS_OFFLINE);
- tgt_node_add(n, pn);
-
- } else if (strcmp(type, TGT_TYPE_TAPE) == 0) {
-#ifndef _LP64
- *code = ERR_TAPE_NOT_SUPPORTED_IN_32BIT;
- goto error;
-#else
- pn = tgt_node_alloc(XML_ELEMENT_STATUS, String,
- TGT_STATUS_OFFLINE);
- tgt_node_add(n, pn);
-
- (void) snprintf(path, sizeof (path), "%s/%s/lun.%d",
- target_basedir, targ_name, lun);
- if (setup_disk_backing(code, path, backing, n, &size) == False)
- goto error;
-#endif
-
- } else if (strcmp(type, TGT_TYPE_RAW) == 0) {
-
- pn = tgt_node_alloc(XML_ELEMENT_STATUS, String,
- TGT_STATUS_ONLINE);
- tgt_node_add(n, pn);
-
- backing = getfullrawname(backing);
- if (setup_raw_backing(code, path, backing, &size) == False)
- goto error;
-
- pn = tgt_node_alloc(XML_ELEMENT_MMAP_LUN, String, "false");
- tgt_node_add(n, pn);
-
- (void) snprintf(path, sizeof (path), "%s/%s/lun.%d",
- target_basedir, targ_name, lun);
- if (symlink(backing, path)) {
- *code = ERR_CREATE_SYMLINK_FAILED;
- goto error;
- }
-
- iscsi_inventory_change(targ_name);
-
- } else if (strcmp(type, TGT_TYPE_OSD) == 0) {
-
- (void) snprintf(path, sizeof (path), "%s/%s/%s%d",
- target_basedir, targ_name, OSDBASE, lun);
- if (mkdir(path, 0700) != 0)
- goto error;
- }
-
-
- /*
- * Wait to set the size until here because it may be unknown until
- * the possible backing store has been setup.
- */
- ssize = size / 512LL;
- pn = tgt_node_alloc(XML_ELEMENT_SIZE, Uint64, &ssize);
- tgt_node_add(n, pn);
-
- if (backing != NULL) {
- pn = tgt_node_alloc(XML_ELEMENT_BACK, String, backing);
- tgt_node_add(n, pn);
- }
-
- (void) mgmt_param_save2scf(n, local_name, lun);
-
- if ((strcmp(type, TGT_TYPE_DISK) == 0) ||
- (strcmp(type, TGT_TYPE_TAPE) == 0)) {
- if (create_lun_common(targ_name, local_name, lun, size,
- code) == False)
- goto error;
- }
-
- tgt_node_free(n);
-
- *code = ERR_SUCCESS;
- return (True);
-
-error:
- /* Free node n */
- tgt_node_free(n);
-
- (void) snprintf(path, sizeof (path), "%s/%s/%s%d", target_basedir,
- targ_name, PARAMBASE, lun);
- (void) unlink(path);
- if (fd == -1)
- (void) close(fd);
- return (False);
-}
-
-/*
- * []----
- * | create_lun_common -- create LU and start provisioning if needed
- * |
- * | This function is common to both the tape and disk emulation
- * | code.
- * []----
- */
-static Boolean_t
-create_lun_common(char *targ_name, char *local_name, int lun, uint64_t size,
- err_code_t *code)
-{
- struct stat s;
- int fd = -1;
- char path[MAXPATHLEN];
- char buf[512];
- struct statvfs fs;
- tgt_node_t *node = NULL;
- tgt_node_t *c;
-
- /*
- * Touch the last block of the file which will cause file systems
- * to understand the intent of the file to be a certain size. The
- * space isn't allocated, but the daemon can then mmap in this file
- * and start writing to it.
- */
- (void) snprintf(path, sizeof (path), "%s/%s/%s%d",
- target_basedir, targ_name, LUNBASE, lun);
- if ((fd = open(path, O_RDWR|O_CREAT|O_LARGEFILE, 0600)) < 0)
- goto error;
-
- (void) lseek(fd, size - 512LL, 0);
- bzero(buf, sizeof (buf));
- if (write(fd, buf, sizeof (buf)) != sizeof (buf)) {
- (void) unlink(path);
- if (errno == EFBIG)
- *code = ERR_FILE_TOO_BIG;
- else
- *code = ERR_FAILED_TO_CREATE_LU;
- goto error;
- }
- (void) close(fd);
-
- /*
- * Set the fd back to -1 so that if an error occurs we don't
- * attempt to close this device twice. This could be an issue
- * if another thread opened a file right after we closed this
- * one and the system reused the file descriptor. During an
- * error we would then close another threads file which would
- * be ugly, not to mention difficult to track down.
- */
- fd = -1;
-
- if (stat(path, &s) != 0) {
- *code = ERR_FAILED_TO_CREATE_LU;
- goto error;
- }
-
- /*
- * If the backing store is a regular file and the default is
- * used which initializes the file instead of sparse allocation
- * go ahead a set things up.
- */
- if ((thin_provisioning == False) && ((s.st_mode & S_IFMT) == S_IFREG)) {
- thick_provo_t *tp;
- pthread_t junk;
-
- /*
- * Attempt to see if there is enough space currently
- * for the LU. The initialization might still fail
- * with "out of space" because someone else is
- * consuming space while the initialization is occuring.
- * Nothing we can do about that.
- */
- if (statvfs(path, &fs) != 0) {
- queue_prt(mgmtq, Q_GEN_ERRS,
- "GEN statvfs failed for %s", path);
- *code = ERR_FAILED_TO_CREATE_LU;
- goto error;
- } else if ((fs.f_frsize * fs.f_bfree) < size) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "GEN Not enough space for LU");
- *code = ERR_FILE_TOO_BIG;
- goto error;
- }
-
- /*
- * Run the initialization thread in the background so that
- * the administrator doesn't have to wait which for UFS could
- * be a long time on a large LU.
- */
- if ((tp = calloc(1, sizeof (*tp))) != NULL) {
- tp->targ_name = strdup(targ_name);
- tp->lun = lun;
- tp->q = queue_alloc();
- (void) pthread_create(&junk, NULL,
- thick_provo_start, tp);
-
- /*
- * As soon as the thread starts it will send a simple
- * ACK to it's own queue that we can look for. When
- * we see this message we know that the thread has
- * started and it's been added to the provisioning
- * list. If this were not done it's possible for someone
- * to create and delete a target within a script and
- * have the delete run and fail to find the provision
- * thread in the list.
- */
- queue_message_free(queue_message_get(tp->q));
- }
- } else {
- (void) mgmt_get_param(&node, local_name, lun);
-
- c = tgt_node_alloc(XML_ELEMENT_STATUS, String,
- TGT_STATUS_ONLINE);
- tgt_node_replace(node, c, MatchName);
- tgt_node_free(c);
-
- if (mgmt_param_save2scf(node, local_name, lun) == False) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "GEN%d failed to dump out params", lun);
- goto error;
- }
- iscsi_inventory_change(targ_name);
- tgt_node_free(node);
- }
-
- return (True);
-
-error:
- if (fd != -1)
- (void) close(fd);
- if (node)
- tgt_node_free(node);
- return (False);
-}
-
-static Boolean_t
-readvtoc(int fd, struct extvtoc *v, int *slice)
-{
- if ((*slice = read_extvtoc(fd, v)) >= 0)
- return (True);
- else
- return (False);
-}
-
-static Boolean_t
-readefi(int fd, struct dk_gpt **efi, int *slice)
-{
- if ((*slice = efi_alloc_and_read(fd, efi)) >= 0)
- return (True);
- else
- return (False);
-}
-
-/*
- * []----
- * | setup_alt_backing -- use backing store link for regular file lun
- * |
- * | If the size is zero, then the administrator MUST have
- * | specified a backing store to use.
- * | If the size is non-zero and the backing store doesn't exist it will
- * | be created. Also a tag will be added indicating that during removal
- * | the backing store should be deleted as well.
- * []----
- */
-static Boolean_t
-setup_disk_backing(err_code_t *code, char *path, char *backing, tgt_node_t *n,
- uint64_t *size)
-{
- struct stat s;
- char *raw_name, buf[512];
- struct extvtoc extvtoc;
- struct dk_gpt *efi;
- int slice, fd;
- tgt_node_t *pn;
-
- /*
- * Error checking regarding size and backing store has already
- * been done. If the backing store is null at this point everything
- * is okay so just return True.
- */
- if (backing == NULL)
- return (True);
-
- if (stat(backing, &s) == -1) {
- if (*size == 0) {
- *code = ERR_STAT_BACKING_FAILED;
- return (False);
- } else {
- pn = tgt_node_alloc(XML_ELEMENT_DELETE_BACK, String,
- "true");
- tgt_node_add(n, pn);
- if ((fd = open(backing, O_RDWR|O_CREAT|O_LARGEFILE,
- 0600)) < 0) {
- *code = ERR_FAILED_TO_CREATE_LU;
- return (False);
- }
- (void) lseek(fd, *size - 512LL, 0);
- bzero(buf, sizeof (buf));
- (void) write(fd, buf, sizeof (buf));
- (void) close(fd);
- }
- } else if (*size != 0) {
- *code = ERR_DISK_BACKING_SIZE_OR_FILE;
- return (False);
- } else if (((s.st_mode & S_IFMT) == S_IFCHR) ||
- ((s.st_mode & S_IFMT) == S_IFBLK)) {
- raw_name = getfullrawname(backing);
- if ((raw_name == NULL) ||
- ((fd = open(raw_name, O_NONBLOCK|O_RDONLY)) < 0)) {
- *code = ERR_DISK_BACKING_NOT_VALID_RAW;
- (void) close(fd);
- if (raw_name)
- free(raw_name);
- return (False);
- }
- free(raw_name);
- if (readvtoc(fd, &extvtoc, &slice) == True) {
- *size = extvtoc.v_part[slice].p_size * 512;
-
- } else if (readefi(fd, &efi, &slice) == True) {
- *size = efi->efi_parts[slice].p_size * 512;
- efi_free(efi);
- } else {
- *code = ERR_DISK_BACKING_NOT_VALID_RAW;
- (void) close(fd);
- return (False);
- }
- (void) close(fd);
-
- } else if ((s.st_mode & S_IFMT) == S_IFREG) {
- *size = s.st_size;
- } else {
- *code = ERR_DISK_BACKING_MUST_BE_REGULAR_FILE;
- return (False);
- }
-
- if (symlink(backing, path)) {
- *code = ERR_CREATE_SYMLINK_FAILED;
- return (False);
- }
-
- return (True);
-}
-
-/*
- * []----
- * | validate_raw_backing -- check that device is full partition
- * |
- * | The size of the device will be returned in rtn_size in bytes.
- * |
- * | Need to guarantee that the backing store for a raw device is:
- * | (a) character device
- * | (b) Not buffered
- * | Don't want this host to have data which is not flushed
- * | out during a write since a multiple path access to
- * | the backing store would be possible meaning we'd have
- * | cache issue.
- * | (c) read/write will access entire device.
- * | To speed things up we use asynchronous I/O which means
- * | the path has to have access to the entire device through
- * | the partition table. If not, some client will issue a
- * | READ_CAPACITY command, but not be able to access all of
- * | the data.
- * []----
- */
-static Boolean_t
-setup_raw_backing(err_code_t *code, char *path, char *backing,
- uint64_t *rtn_size)
-{
- struct stat s;
- char buf[512];
- int fd;
- uint64_t size;
- struct uscsi_cmd u;
- struct scsi_extended_sense sense;
- union scsi_cdb cdb;
- struct scsi_capacity cap;
- struct scsi_capacity_16 cap16;
- int cap_len = sizeof (cap16);
- size_t cc;
- Boolean_t rval = False;
-
- if (stat(backing, &s) == -1) {
- *code = ERR_ACCESS_RAW_DEVICE_FAILED;
- return (False);
- } else if (((s.st_mode & S_IFMT) != S_IFCHR) &&
- ((s.st_mode & S_IFMT) != S_IFBLK)) {
- *code = ERR_DISK_BACKING_NOT_VALID_RAW;
- return (False);
- }
-
- if ((backing == NULL) ||
- ((fd = open(backing, O_NDELAY|O_RDONLY|O_LARGEFILE)) < 0)) {
- *code = ERR_DISK_BACKING_NOT_VALID_RAW;
- (void) close(fd);
- return (False);
- }
-
- bzero(&u, sizeof (u));
- bzero(&cdb, sizeof (cdb));
- bzero(&cap, sizeof (cap));
- bzero(&sense, sizeof (sense));
-
- cdb.scc_cmd = 0x25; /* ---- READ_CAPACITY(10) ---- */
-
- u.uscsi_cdb = (caddr_t)&cdb;
- u.uscsi_cdblen = CDB_GROUP1;
- u.uscsi_bufaddr = (caddr_t)&cap;
- u.uscsi_buflen = sizeof (cap);
- u.uscsi_flags = USCSI_READ | USCSI_RQENABLE;
- u.uscsi_rqbuf = (char *)&sense;
- u.uscsi_rqlen = sizeof (sense);
-
- if ((ioctl(fd, USCSICMD, &u) != 0) || (u.uscsi_status != 0)) {
- queue_prt(mgmtq, Q_GEN_DETAILS, "GEN0 uscsi(READ_CAP) failed");
- *code = ERR_DISK_BACKING_NOT_VALID_RAW;
- rval = False;
- goto error;
- }
-
- if (cap.capacity == 0xffffffff) {
-
- bzero(&u, sizeof (u));
- bzero(&cdb, sizeof (cdb));
- bzero(&sense, sizeof (sense));
- /*
- * The device is to large for the 10byte CDB.
- * Using the larger 16byte read capacity command
- */
- cdb.scc_cmd = 0x9E;
- cdb.g4_reladdr = 0x10;
- cdb.g4_count3 = hibyte(hiword(cap_len));
- cdb.g4_count2 = lobyte(hiword(cap_len));
- cdb.g4_count1 = hibyte(loword(cap_len));
- cdb.g4_count0 = lobyte(loword(cap_len));
-
- u.uscsi_cdb = (caddr_t)&cdb;
- u.uscsi_cdblen = CDB_GROUP4;
- u.uscsi_bufaddr = (caddr_t)&cap16;
- u.uscsi_buflen = sizeof (cap16);
- u.uscsi_flags = USCSI_READ | USCSI_RQENABLE;
- u.uscsi_rqbuf = (char *)&sense;
- u.uscsi_rqlen = sizeof (sense);
-
- if ((ioctl(fd, USCSICMD, &u) != 0) || (u.uscsi_status != 0)) {
- queue_prt(mgmtq, Q_GEN_DETAILS,
- "GEN0 uscsi(READ_CAP16) failed");
- *code = ERR_DISK_BACKING_NOT_VALID_RAW;
- rval = False;
- goto error;
- }
-
- size = ntohll(cap16.sc_capacity) - 1;
- } else
- size = (uint64_t)ntohl(cap.capacity) - 1;
-
- if ((cc = pread(fd, buf, sizeof (buf), size * 512LL)) != sizeof (buf)) {
- queue_prt(mgmtq, Q_GEN_DETAILS,
- "GEN0 Partition size != capacity(0x%llx), cc=%d, errno=%d",
- size, cc, errno);
- *code = ERR_RAW_PART_NOT_CAP;
- rval = False;
- goto error;
- } else {
- *rtn_size = size * 512LL;
- rval = True;
- }
-
-error:
- (void) close(fd);
- return (rval);
-}
-
-/*
- * get_zfs_shareiscsi -- given a dataset, get the ZFS properties
- *
- * This function is called when "set shareiscsi=on" calles into libiscsitgt,
- * such that the iSCSI Target can get the ZFS_PROP_ISCSIOPTIONS. This is in
- * lieu of properties being stored in SCF.
- */
-int
-get_zfs_shareiscsi(char *dataset, tgt_node_t **n, uint64_t *size, ucred_t *cred)
-{
- libzfs_handle_t *zh;
- zfs_handle_t *zfsh;
- const priv_set_t *eset;
- tgt_node_t *c;
- char *prop = NULL;
- char *cp; /* current pair */
- char *np; /* next pair */
- char *vp; /* value pointer */
- int status = ERR_SUCCESS;
-
- if (((zh = libzfs_init()) == NULL) ||
- ((zfsh = zfs_open(zh, dataset, ZFS_TYPE_DATASET)) == NULL)) {
- status = ERR_INTERNAL_ERROR;
- goto error;
- }
-
- if (((eset = ucred_getprivset(cred, PRIV_EFFECTIVE)) != NULL)
- ? !priv_ismember(eset, PRIV_SYS_CONFIG)
- : ucred_geteuid(cred) != 0) {
- /*
- * See if user has ZFS dataset permissions to do operation
- */
- if (zfs_iscsi_perm_check(zh, dataset, cred) != 0) {
- status = ERR_NO_PERMISSION;
- goto error;
- }
- }
-
- /*
- * Get the current size of the volume, return to caller
- */
- *size = zfs_prop_get_int(zfsh, ZFS_PROP_VOLSIZE);
-
- /*
- * Allocate a local buffer to read the ZFS properties into
- */
- if ((prop = malloc(ZFS_PROP_SIZE)) == NULL) {
- status = ERR_INTERNAL_ERROR;
- goto error;
- }
-
- /*
- * Get the shareiscsi property
- */
- *prop = '\0';
- if (zfs_prop_get(zfsh, ZFS_PROP_SHAREISCSI, prop, ZFS_PROP_SIZE, NULL,
- NULL, 0, B_TRUE)) {
- status = ERR_INTERNAL_ERROR;
- goto error;
- }
-
- /*
- * The options property is a string with name/value pairs separated
- * by comma characters. Stand alone values of 'on' and 'off' are
- * also permitted, but having the property set to off when share()
- * is called is an error.
- * Currently we only look for 'type=<value>' and ignore others.
- */
-
- for (cp = prop; cp; cp = np) {
- if (np = strchr(cp, ','))
- *np++ = '\0';
- if (strcmp(cp, "on") == 0) {
- cp = np;
- continue;
- }
- if (strcmp(cp, "off") == 0) {
- status = ERR_ZFS_ISCSISHARE_OFF;
- goto error;
- }
- if (vp = strchr(cp, '='))
- *vp++ = '\0';
- /*
- * Only support 'disk' emulation at this point.
- */
- if ((strcmp(cp, "type") == 0) && (strcmp(vp, "disk") != 0)) {
- status = ERR_INTERNAL_ERROR;
- goto error;
- }
- }
-
- /*
- * Now get the ZFS persisted shareiscsi options
- */
- *prop = '\0';
- if (zfs_prop_get(zfsh, ZFS_PROP_ISCSIOPTIONS, prop, ZFS_PROP_SIZE, NULL,
- NULL, 0, B_TRUE) && (status != ERR_ZFS_ISCSISHARE_OFF)) {
- status = ERR_INTERNAL_ERROR;
- goto error;
- }
-
- /*
- * Now move the ZFS persisted shareiscsi options into XML, then into
- * iSCSI Target properties
- */
- if (strlen(prop)) {
- xmlTextReaderPtr xml_ptr = (xmlTextReaderPtr)xmlReaderForMemory(
- prop, strlen(prop), NULL, NULL, 0);
-
- if (xml_ptr != NULL) {
- *n = NULL;
- while (xmlTextReaderRead(xml_ptr)) {
- if (tgt_node_process(xml_ptr, n) == False) {
- break;
- }
- }
-
- /* Cleanup XML data */
- (void) xmlTextReaderClose(xml_ptr);
- xmlFreeTextReader(xml_ptr);
- xmlCleanupParser();
-
- /* Assure these XML elements are tagged as in-core */
- if (tgt_find_attr_str(*n, XML_ELEMENT_INCORE, &cp)
- == False) {
- c = tgt_node_alloc(XML_ELEMENT_INCORE, String,
- XML_VALUE_TRUE);
- tgt_node_add_attr(*n, c);
- } else {
- free(cp);
- }
-
- } else {
- status = ERR_NULL_XML_MESSAGE;
- }
- } else {
- status = ERR_NULL_XML_MESSAGE;
- }
-
-error:
- if (prop)
- free(prop);
- if (zh) {
- if (zfsh)
- zfs_close(zfsh);
- libzfs_fini(zh);
- }
- return (status);
-}
-
-/*
- * put_zfs_shareiscsi -- given a dataset, put the ZFS properties
- *
- * This function is called whenever persistence is needed to the set of
- * iSCSI Target properties stored in ZFS_PROP_ISCSIOPTIONS. This is in lieu
- * of properties being stored in SCF.
- */
-int
-put_zfs_shareiscsi(char *dataset, tgt_node_t *n)
-{
- libzfs_handle_t *zh;
- zfs_handle_t *zfsh;
- char *prop = NULL;
- int status;
-
- if (((zh = libzfs_init()) == NULL) ||
- ((zfsh = zfs_open(zh, dataset, ZFS_TYPE_DATASET)) == NULL)) {
- status = ERR_INTERNAL_ERROR;
- goto error;
- }
-
- /*
- * Now store this information on the ZVOL property so that
- * next time we get a shareiscsi request the same data will be
- * used.
- */
- tgt_dump2buf(n, &prop);
- if (zfs_prop_set(zfsh, zfs_prop_to_name(ZFS_PROP_ISCSIOPTIONS), prop)) {
- status = ERR_INTERNAL_ERROR;
- } else {
- status = ERR_SUCCESS;
- }
-
-error:
- if (prop)
- free(prop);
- if (zh) {
- if (zfsh)
- zfs_close(zfsh);
- libzfs_fini(zh);
- }
- return (status);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/mgmt_list.c b/usr/src/cmd/iscsi/iscsitgtd/mgmt_list.c
deleted file mode 100644
index c3f621ac7d..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_list.c
+++ /dev/null
@@ -1,508 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 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/stat.h>
-#include <time.h>
-#include <sys/utsname.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <strings.h>
-#include <dirent.h>
-#include <priv.h>
-#include <syslog.h>
-
-#include <iscsitgt_impl.h>
-#include "utility.h"
-#include "queue.h"
-#include "target.h"
-#include "iscsi_cmd.h"
-#include "iscsi_conn.h"
-#include "port.h"
-#include "errcode.h"
-#include "mgmt_scf.h"
-#include "isns_client.h"
-
-static char *list_targets(tgt_node_t *x);
-static char *list_initiator(tgt_node_t *x);
-static char *list_tpgt(tgt_node_t *x);
-static char *list_admin(tgt_node_t *x);
-static void target_info(char **msg, char *targ_name, tgt_node_t *tnode);
-static void target_stat(char **msg, char *iname, mgmt_type_t type);
-
-/*ARGSUSED*/
-void
-list_func(tgt_node_t *p, target_queue_t *reply, target_queue_t *mgmt,
- ucred_t *cred)
-{
- tgt_node_t *x;
- char msgbuf[80];
- char *reply_msg = NULL;
-
- if (p->x_child == NULL) {
- xml_rtn_msg(&reply_msg, ERR_SYNTAX_MISSING_OBJECT);
- } else {
- x = p->x_child;
-
- if (x->x_name == NULL) {
- xml_rtn_msg(&reply_msg, ERR_SYNTAX_MISSING_OBJECT);
- } else if (strcmp(x->x_name, XML_ELEMENT_TARG) == 0) {
- reply_msg = list_targets(x);
- } else if (strcmp(x->x_name, XML_ELEMENT_INIT) == 0) {
- reply_msg = list_initiator(x);
- } else if (strcmp(x->x_name, XML_ELEMENT_TPGT) == 0) {
- reply_msg = list_tpgt(x);
- } else if (strcmp(x->x_name, XML_ELEMENT_ADMIN) == 0) {
- reply_msg = list_admin(x);
- } else {
- (void) snprintf(msgbuf, sizeof (msgbuf),
- "Unknown object '%s' for list element",
- x->x_name);
- xml_rtn_msg(&reply_msg, ERR_INVALID_OBJECT);
- }
- }
- queue_message_set(reply, 0, msg_mgmt_rply, reply_msg);
-}
-
-/*ARGSUSED*/
-static char *
-list_targets(tgt_node_t *x)
-{
- char *msg = NULL;
- char *prop = NULL;
- char *iname = NULL;
- tgt_node_t *targ = NULL;
- Boolean_t luninfo = False;
- Boolean_t dostat = False;
-
- /*
- * It's okay to not supply a "name" element. That just means the
- * administrator wants a complete list of targets. However if a
- * "name" is supplied then there must be a value for that element.
- */
- if ((tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == True) &&
- (prop == NULL)) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
- return (msg);
- }
-
- /* ---- optional arguments ---- */
- (void) tgt_find_value_boolean(x, XML_ELEMENT_LUNINFO, &luninfo);
- (void) tgt_find_value_boolean(x, XML_ELEMENT_IOSTAT, &dostat);
-
- tgt_buf_add_tag_and_attr(&msg, XML_ELEMENT_RESULT, "version='1.0'");
- while ((targ = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
- targ)) != NULL) {
- if (targ->x_value == NULL) {
- tgt_buf_add(&msg, XML_ELEMENT_TARG,
- "bogus entry");
- continue;
- }
- if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &iname) ==
- False) {
- tgt_buf_add(&msg, XML_ELEMENT_TARG,
- "missing iscsi-name");
- continue;
- }
- if (prop != NULL) {
- if (strcmp(prop, targ->x_value) == 0) {
- tgt_buf_add_tag(&msg, XML_ELEMENT_TARG,
- Tag_Start);
- tgt_buf_add_tag(&msg, targ->x_value,
- Tag_String);
- tgt_buf_add(&msg, XML_ELEMENT_INAME, iname);
- if (luninfo == True)
- target_info(&msg, iname, targ);
- if (dostat == True)
- target_stat(&msg, iname,
- mgmt_full_phase_statistics);
- tgt_buf_add_tag(&msg, XML_ELEMENT_TARG,
- Tag_End);
- }
- } else {
- tgt_buf_add_tag(&msg, XML_ELEMENT_TARG, Tag_Start);
- tgt_buf_add_tag(&msg, targ->x_value, Tag_String);
- tgt_buf_add(&msg, XML_ELEMENT_INAME, iname);
- if (dostat == True)
- target_stat(&msg, iname,
- mgmt_full_phase_statistics);
- if (luninfo == True)
- target_info(&msg, iname, targ);
- tgt_buf_add_tag(&msg, XML_ELEMENT_TARG, Tag_End);
- }
- free(iname);
- }
- tgt_buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End);
- free(prop);
-
- return (msg);
-}
-
-/*ARGSUSED*/
-static char *
-list_initiator(tgt_node_t *x)
-{
- char *msg = NULL;
- char *attr = NULL;
- char *prop = NULL;
- Boolean_t verbose = False;
- tgt_node_t *init = NULL;
-
- /* ---- Optional arguments ---- */
- if ((tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == True) &&
- (prop == NULL)) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
- return (msg);
- }
- (void) tgt_find_value_boolean(x, XML_ELEMENT_VERBOSE, &verbose);
-
- tgt_buf_add_tag_and_attr(&msg, XML_ELEMENT_RESULT, "version='1.0'");
- while ((init = tgt_node_next_child(main_config, XML_ELEMENT_INIT, init))
- != NULL) {
- if ((prop == NULL) ||
- ((prop != NULL) && (strcmp(prop, init->x_value) == 0))) {
-
- tgt_buf_add_tag(&msg, XML_ELEMENT_INIT, Tag_Start);
- tgt_buf_add_tag(&msg, init->x_value, Tag_String);
-
- if (tgt_find_value_str(init, XML_ELEMENT_INAME,
- &attr) == True) {
- tgt_buf_add(&msg, XML_ELEMENT_INAME, attr);
- free(attr);
- }
-
- if (tgt_find_value_str(init, XML_ELEMENT_CHAPSECRET,
- &attr) == True) {
- tgt_buf_add(&msg, XML_ELEMENT_CHAPSECRET,
- "Set");
- free(attr);
- }
-
- if (tgt_find_value_str(init, XML_ELEMENT_CHAPNAME,
- &attr) == True) {
- tgt_buf_add(&msg, XML_ELEMENT_CHAPNAME, attr);
- free(attr);
- }
-
- tgt_buf_add_tag(&msg, XML_ELEMENT_INIT, Tag_End);
- }
- }
-
- if (prop != NULL)
- free(prop);
-
- tgt_buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End);
-
- return (msg);
-}
-
-/*ARGSUSED*/
-static char *
-list_tpgt(tgt_node_t *x)
-{
- char *msg = NULL;
- char *prop = NULL;
- Boolean_t verbose = False;
- tgt_node_t *tpgt = NULL;
- tgt_node_t *ip = NULL;
-
- /* ---- Optional arguments ---- */
- if ((tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == True) &&
- (prop == NULL)) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
- return (msg);
- }
- (void) tgt_find_value_boolean(x, XML_ELEMENT_VERBOSE, &verbose);
-
- tgt_buf_add_tag_and_attr(&msg, XML_ELEMENT_RESULT, "version='1.0'");
- while ((tpgt = tgt_node_next_child(main_config, XML_ELEMENT_TPGT, tpgt))
- != NULL) {
- if ((prop == NULL) ||
- ((prop != NULL) && (strcmp(prop, tpgt->x_value) == 0))) {
-
- tgt_buf_add_tag(&msg, XML_ELEMENT_TPGT, Tag_Start);
- tgt_buf_add_tag(&msg, tpgt->x_value, Tag_String);
-
- while ((ip = tgt_node_next(tpgt, XML_ELEMENT_IPADDR,
- ip)) != NULL) {
- tgt_buf_add(&msg, ip->x_name, ip->x_value);
- }
-
- tgt_buf_add_tag(&msg, XML_ELEMENT_TPGT, Tag_End);
- }
- }
- tgt_buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End);
-
- if (prop != NULL)
- free(prop);
- return (msg);
-}
-
-/*ARGSUSED*/
-static char *
-list_admin(tgt_node_t *x)
-{
- char *msg = NULL;
- admin_table_t *p;
- tgt_node_t *node = NULL;
- tgt_node_t *isns_srv_node = NULL;
- Boolean_t enabled = False;
-
- tgt_buf_add_tag_and_attr(&msg, XML_ELEMENT_RESULT, "version='1.0'");
- tgt_buf_add_tag(&msg, XML_ELEMENT_ADMIN, Tag_Start);
-
- node = NULL;
- for (p = admin_prop_list; p->name != NULL; p++) {
- node = tgt_node_next_child(main_config, p->name, NULL);
- if (node) {
- if (strcmp(p->name, XML_ELEMENT_CHAPSECRET) == 0) {
- tgt_buf_add(&msg, p->name, "Set");
- } else if (strcmp(p->name, XML_ELEMENT_ISNS_ACCESS)
- == 0) {
- tgt_buf_add(&msg, p->name, node->x_value);
- /* check the isns discovery */
- if (node->x_value &&
- strcmp(node->x_value, "true") == 0) {
- enabled = True;
- }
- } else if (strcmp(p->name, XML_ELEMENT_ISNS_SERV)
- == 0) {
- tgt_buf_add(&msg, p->name, node->x_value);
- /*
- * check the state of isns server connection.
- */
- if (node->x_value != NULL) {
- isns_srv_node = node;
- }
- } else {
- tgt_buf_add(&msg, p->name, node->x_value);
- }
- }
- }
-
- /*
- * check the state of isns server connection and add the node.
- * the conncection state is dynamic so it doesn't get stored in
- * incore config.
- */
- if (enabled && isns_srv_node) {
- if (isns_open(isns_srv_node->x_value) == -1) {
- tgt_buf_add(&msg, XML_ELEMENT_ISNS_SERVER_STATUS,
- "Unavailable");
- } else {
- tgt_buf_add(&msg, XML_ELEMENT_ISNS_SERVER_STATUS,
- "Available");
- }
- } else {
- tgt_buf_add(&msg, XML_ELEMENT_ISNS_SERVER_STATUS,
- "Not applicable");
- }
-
- tgt_buf_add_tag(&msg, XML_ELEMENT_ADMIN, Tag_End);
- tgt_buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End);
-
- return (msg);
-}
-
-static void
-target_stat(char **msg, char *targ_name, mgmt_type_t type)
-{
- iscsi_conn_t *c;
- msg_t *m;
- target_queue_t *q = queue_alloc();
- mgmt_request_t mgmt_rqst;
- int msg_sent;
- int i;
- extern pthread_mutex_t port_mutex;
-
- mgmt_rqst.m_q = q;
- mgmt_rqst.m_u.m_resp = msg;
- mgmt_rqst.m_time = time(NULL);
- mgmt_rqst.m_request = type;
- (void) pthread_mutex_init(&mgmt_rqst.m_resp_mutex, NULL);
-
- (void) pthread_mutex_lock(&port_mutex);
- mgmt_rqst.m_targ_name = targ_name;
- msg_sent = 0;
- for (c = conn_head; c; c = c->c_next) {
- if (c->c_state == S5_LOGGED_IN) {
- /*
- * Only send requests for statistics to
- * connections that are up. Could even
- * go further and only look at connections
- * which are S5_LOGGED_IN, but there may
- * be statistics, such as connection time,
- * which we'd like to have.
- */
- queue_message_set(c->c_dataq, 0, msg_mgmt_rqst,
- &mgmt_rqst);
- msg_sent++;
- }
- }
- (void) pthread_mutex_unlock(&port_mutex);
-
- /*
- * Comment: main.c:list_targets:1
- * We wait for the responses without the port_mutex
- * being held. There is a small window between when the
- * connection last listens for a message and when the
- * queue is freed. During that time the connection will
- * attempt to grab the port_mutex lock so that it
- * can unlink itself and call queueu_free(). If we sent
- * the message with the lock held and then wait for a response
- * it's possible that the connection will deadlock waiting
- * to get the port_mutex.
- */
- for (i = 0; i < msg_sent; i++) {
- m = queue_message_get(q);
- queue_message_free(m);
- }
- queue_free(q, NULL);
-}
-
-static void
-target_info(char **msg, char *targ_name, tgt_node_t *tnode)
-{
- char lun_buf[16];
- char *prop;
- char *local_name = NULL;
- tgt_node_t *lnode; /* list node */
- tgt_node_t *lnp; /* list node pointer */
- tgt_node_t *lun;
- tgt_node_t *params;
- int lun_num;
- Boolean_t incore;
- struct stat s;
-
- if ((lnode = tgt_node_next(tnode, XML_ELEMENT_ACLLIST, NULL)) !=
- NULL) {
- lnp = NULL;
- tgt_buf_add_tag(msg, XML_ELEMENT_ACLLIST, Tag_Start);
- while ((lnp = tgt_node_next(lnode, XML_ELEMENT_INIT, lnp)) !=
- NULL)
- tgt_buf_add(msg, XML_ELEMENT_INIT, lnp->x_value);
- tgt_buf_add_tag(msg, XML_ELEMENT_ACLLIST, Tag_End);
- }
-
- if ((lnode = tgt_node_next(tnode, XML_ELEMENT_TPGTLIST, NULL)) !=
- NULL) {
- lnp = NULL;
- tgt_buf_add_tag(msg, XML_ELEMENT_TPGTLIST, Tag_Start);
- while ((lnp = tgt_node_next(lnode, XML_ELEMENT_TPGT, lnp)) !=
- NULL)
- tgt_buf_add(msg, XML_ELEMENT_TPGT, lnp->x_value);
- tgt_buf_add_tag(msg, XML_ELEMENT_TPGTLIST, Tag_End);
- }
-
- if ((lnode = tgt_node_next(tnode, XML_ELEMENT_ALIAS, NULL)) != NULL)
- tgt_buf_add(msg, XML_ELEMENT_ALIAS, lnode->x_value);
-
- if ((lnode = tgt_node_next(tnode, XML_ELEMENT_MAXRECV, NULL)) != NULL)
- tgt_buf_add(msg, XML_ELEMENT_MAXRECV, lnode->x_value);
-
- if ((lnode = tgt_node_next(tnode, XML_ELEMENT_LUNLIST, NULL)) == NULL)
- return;
-
- if (tgt_find_attr_str(tnode, XML_ELEMENT_INCORE, &prop) == True) {
- if (strcmp(prop, "true") == 0)
- incore = True;
- else
- incore = False;
- free(prop);
- } else
- incore = False;
-
- tgt_buf_add_tag(msg, XML_ELEMENT_LUNINFO, Tag_Start);
- lun = NULL;
- while ((lun = tgt_node_next(lnode, XML_ELEMENT_LUN, lun)) != NULL) {
- if ((tgt_find_value_int(lun, XML_ELEMENT_LUN, &lun_num)) ==
- False)
- continue;
- if (incore == False) {
- local_name = get_local_name(targ_name);
- if (local_name != NULL) {
- (void) mgmt_get_param(&params, local_name,
- lun_num);
- free(local_name);
- } else {
- continue;
- }
- } else {
- params = lun;
- }
-
- tgt_buf_add_tag(msg, XML_ELEMENT_LUN, Tag_Start);
- (void) snprintf(lun_buf, sizeof (lun_buf), "%d", lun_num);
- tgt_buf_add_tag(msg, lun_buf, Tag_String);
-
- if (tgt_find_value_str(params, XML_ELEMENT_GUID, &prop) ==
- True) {
- tgt_buf_add(msg, XML_ELEMENT_GUID, prop);
- free(prop);
- }
- if (tgt_find_value_str(params, XML_ELEMENT_VID, &prop) ==
- True) {
- tgt_buf_add(msg, XML_ELEMENT_VID, prop);
- free(prop);
- }
- if (tgt_find_value_str(params, XML_ELEMENT_PID, &prop) ==
- True) {
- tgt_buf_add(msg, XML_ELEMENT_PID, prop);
- free(prop);
- }
- if (tgt_find_value_str(params, XML_ELEMENT_DTYPE, &prop) ==
- True) {
- tgt_buf_add(msg, XML_ELEMENT_DTYPE, prop);
- free(prop);
- }
- if (tgt_find_value_str(params, XML_ELEMENT_SIZE, &prop) ==
- True) {
- tgt_buf_add(msg, XML_ELEMENT_SIZE, prop);
- free(prop);
- }
- if (tgt_find_value_str(params, XML_ELEMENT_BACK, &prop) ==
- True) {
- tgt_buf_add(msg, XML_ELEMENT_BACK, prop);
- if (stat(prop, &s) == 0) {
- tgt_buf_add(msg, XML_ELEMENT_STATUS,
- TGT_STATUS_ONLINE);
- } else {
- tgt_buf_add(msg, XML_ELEMENT_STATUS,
- strerror(errno));
- }
- free(prop);
- }
- tgt_buf_add_tag(msg, XML_ELEMENT_LUN, Tag_End);
-
- if (incore == False)
- tgt_node_free(params);
- }
- tgt_buf_add_tag(msg, XML_ELEMENT_LUNINFO, Tag_End);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/mgmt_modify.c b/usr/src/cmd/iscsi/iscsitgtd/mgmt_modify.c
deleted file mode 100644
index 4dfc6a1b61..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_modify.c
+++ /dev/null
@@ -1,1191 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <sys/types.h>
-#include <time.h>
-#include <sys/utsname.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <strings.h>
-#include <assert.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <libgen.h>
-#include <libzfs.h>
-#include <syslog.h>
-
-#include <iscsitgt_impl.h>
-#include "queue.h"
-#include "utility.h"
-#include "iscsi_cmd.h"
-#include "target.h"
-#include "errcode.h"
-#include "isns_client.h"
-#include "mgmt_scf.h"
-
-static char *modify_target(tgt_node_t *x, ucred_t *cred);
-static char *modify_initiator(tgt_node_t *x);
-static char *modify_admin(tgt_node_t *x);
-static char *modify_tpgt(tgt_node_t *x);
-static char *modify_zfs(tgt_node_t *x, ucred_t *cred);
-static char *validate_zfs_iscsitgt(tgt_node_t *x);
-static Boolean_t modify_element(char *, char *, tgt_node_t *, match_type_t);
-static Boolean_t delete_element(char *, tgt_node_t *, match_type_t);
-
-/*
- * []----
- * | modify_func -- dispatch routine for objects
- * []----
- */
-/*ARGSUSED*/
-void
-modify_func(tgt_node_t *p, target_queue_t *reply, target_queue_t *mgmt,
- ucred_t *cred)
-{
- tgt_node_t *x;
- char *reply_msg = NULL;
-
- x = p->x_child;
-
- if (p->x_child == NULL) {
- xml_rtn_msg(&reply_msg, ERR_SYNTAX_MISSING_OBJECT);
- } else if (strcmp(x->x_name, XML_ELEMENT_ZFS) == 0) {
- reply_msg = modify_zfs(x, cred);
- } else if (check_auth_modify(cred) != True) {
- xml_rtn_msg(&reply_msg, ERR_NO_PERMISSION);
- } else {
- if (x->x_name == NULL) {
- xml_rtn_msg(&reply_msg, ERR_SYNTAX_MISSING_OBJECT);
- } else if (strcmp(x->x_name, XML_ELEMENT_TARG) == 0) {
- reply_msg = modify_target(x, cred);
- } else if (strcmp(x->x_name, XML_ELEMENT_INIT) == 0) {
- reply_msg = modify_initiator(x);
- } else if (strcmp(x->x_name, XML_ELEMENT_ADMIN) == 0) {
- reply_msg = modify_admin(x);
- } else if (strcmp(x->x_name, XML_ELEMENT_TPGT) == 0) {
- reply_msg = modify_tpgt(x);
- } else {
- xml_rtn_msg(&reply_msg, ERR_INVALID_OBJECT);
- }
- }
- queue_message_set(reply, 0, msg_mgmt_rply, reply_msg);
-}
-
-/*
- * []----
- * | modify_target -- updates one or more properties for a target
- * []----
- */
-static char *
-modify_target(tgt_node_t *x, ucred_t *cred)
-{
- char *msg = NULL;
- char *name = NULL;
- char iscsi_path[MAXPATHLEN];
- char targ_name[64];
- char *iscsi = NULL;
- char *prop = NULL;
- char path[MAXPATHLEN];
- char *m;
- char buf[512]; /* one sector size block */
- tgt_node_t *t = NULL;
- tgt_node_t *list = NULL;
- tgt_node_t *c = NULL;
- tgt_node_t *node = NULL;
- tgt_node_t *tpgt = NULL;
- Boolean_t change_made = False;
- int lun = 0;
- int fd;
- uint64_t val, new_lu_size, cur_lu_size;
- struct stat st;
- uint32_t isns_mods = 0;
-
- (void) pthread_rwlock_wrlock(&targ_config_mutex);
- if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
- goto error;
- }
-
- while ((t = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
- t)) != NULL) {
- if (strcmp(t->x_value, name) == 0) {
- break;
- }
- }
- if (t == NULL) {
- free(name);
- xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND);
- goto error;
- }
-
- if (tgt_find_attr_str(t, XML_ELEMENT_INCORE, &m) == True) {
- if (strcmp(m, "true") == 0) {
- free(m);
- free(name);
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (modify_zfs(x, cred));
- }
- free(m);
- }
-
- /*
- * Under base dir, file 'target name' is a symbolic link
- * to the real directory 'IQN name' which stores params and back
- * storage. Therefore we can easily get IQN name from target
- * name by read the symbolic link content.
- */
- (void) snprintf(path, sizeof (path), "%s/%s", target_basedir, name);
- bzero(iscsi_path, sizeof (iscsi_path));
- (void) readlink(path, iscsi_path, sizeof (iscsi_path));
- iscsi = basename(iscsi_path);
-
- /* ---- Finished with these so go ahead and release the memory ---- */
- (void) strncpy(targ_name, name, sizeof (targ_name));
- free(name);
-
- /*
- * Grow the LU. We currently do not support shrinking the LU and
- * that is only because it's unknown if any applications could support
- * that type of data loss. To support shrinking all that would be
- * needed is to remove the new/old size check and perform a truncation.
- * The actually truncation request should be shipped off to the T10
- * layer so that the LU thread can remap the smaller size without
- * anyone accessing the data.
- */
- if (tgt_find_value_str(x, XML_ELEMENT_SIZE, &prop) == True) {
- if (prop == NULL) {
- xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_TPGT);
- goto error;
- }
- if (strtoll_multiplier(prop, &new_lu_size) == False) {
- free(prop);
- xml_rtn_msg(&msg, ERR_INVALID_SIZE);
- goto error;
- }
- free(prop);
- if ((new_lu_size % 512LL) != 0) {
- xml_rtn_msg(&msg, ERR_SIZE_MOD_BLOCK);
- goto error;
- }
- new_lu_size /= 512LL;
-
- /* ---- default to LUN 0 ---- */
- (void) tgt_find_value_int(x, XML_ELEMENT_LUN, &lun);
-
- /* ---- read in current parameters ---- */
- if (mgmt_get_param(&node, targ_name, lun) == False) {
- xml_rtn_msg(&msg, ERR_OPEN_PARAM_FILE_FAILED);
- goto error;
- }
-
- /* ---- validate that we're indeed growing the LU ---- */
- if (tgt_find_value_str(node, XML_ELEMENT_SIZE, &prop) ==
- False) {
- xml_rtn_msg(&msg, ERR_INIT_XML_READER_FAILED);
- goto error;
- }
- if (strtoll_multiplier(prop, &cur_lu_size) == False) {
- free(prop);
- xml_rtn_msg(&msg, ERR_INVALID_SIZE);
- goto error;
- }
- free(prop);
-
- if (new_lu_size < cur_lu_size) {
- xml_rtn_msg(&msg, ERR_CANT_SHRINK_LU);
- goto error;
- }
-
- /* ---- check that this LU is of type 'disk' or 'tape' ---- */
- if (tgt_find_value_str(node, XML_ELEMENT_DTYPE, &prop) ==
- False) {
- xml_rtn_msg(&msg, ERR_INIT_XML_READER_FAILED);
- goto error;
- }
- if ((strcmp(prop, TGT_TYPE_DISK) != 0) &&
- (strcmp(prop, TGT_TYPE_TAPE) != 0)) {
- xml_rtn_msg(&msg, ERR_RESIZE_WRONG_DTYPE);
- free(prop);
- goto error;
- }
- free(prop);
-
- /* ---- validate the backing store is a regular file ---- */
- (void) snprintf(path, sizeof (path), "%s/%s/%s%d",
- target_basedir, iscsi, LUNBASE, lun);
- if (stat(path, &st) == -1) {
- xml_rtn_msg(&msg, ERR_STAT_BACKING_FAILED);
- goto error;
- }
- if ((st.st_mode & S_IFMT) != S_IFREG) {
- xml_rtn_msg(&msg,
- ERR_DISK_BACKING_MUST_BE_REGULAR_FILE);
- goto error;
- }
-
- /* ---- update the parameter node with new size ---- */
- if ((c = tgt_node_alloc(XML_ELEMENT_SIZE, Uint64, &new_lu_size))
- == NULL) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- goto error;
- }
- tgt_node_replace(node, c, MatchName);
- tgt_node_free(c);
-
- /* ---- now update params file ---- */
- (void) mgmt_param_save2scf(node, targ_name, lun);
-
- /* ---- grow lu backing store ---- */
- (void) snprintf(path, sizeof (path), "%s/%s/%s%d",
- target_basedir, iscsi, LUNBASE, lun);
- if ((fd = open(path, O_RDWR|O_CREAT|O_LARGEFILE, 0600)) < 0) {
- xml_rtn_msg(&msg, ERR_LUN_NOT_FOUND);
- goto error;
- }
- (void) lseek(fd, (new_lu_size * 512LL) - 512LL, 0);
- bzero(buf, sizeof (buf));
- if (write(fd, buf, sizeof (buf)) != sizeof (buf)) {
- xml_rtn_msg(&msg, ERR_LUN_NOT_GROWN);
- (void) close(fd);
- goto error;
- }
- (void) close(fd);
-
- /* ---- send updates to current initiators via ASC/ASCQ ---- */
- iscsi_capacity_change(iscsi, lun);
-
- prop = NULL;
- tgt_node_free(node);
- node = NULL;
- change_made = True;
- }
-
- if (tgt_find_value_str(x, XML_ELEMENT_TPGT, &prop) == True) {
- if (prop == NULL) {
- xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_TPGT);
- goto error;
- }
-
- /*
- * Validate that the Target Portal Group Tag is reasonable.
- */
- val = strtoll(prop, &m, 0);
- if ((val < TPGT_MIN) || (val > TPGT_MAX) ||
- ((m != NULL) && (*m != '\0'))) {
- xml_rtn_msg(&msg, ERR_INVALID_TPGT);
- free(prop);
- goto error;
- }
-
- /* update isns only if TPGT contains ip_addr */
- tpgt = NULL;
- while ((tpgt = tgt_node_next_child(main_config,
- XML_ELEMENT_TPGT, tpgt)) != NULL) {
- if (strcmp(prop, tpgt->x_value) != 0)
- continue;
- if (tgt_node_next(tpgt, XML_ELEMENT_IPADDR, NULL)
- != NULL) {
- isns_mods |= ISNS_MOD_TPGT;
- break;
- } else {
- xml_rtn_msg(&msg, ERR_TPGT_NO_IPADDR);
- free(prop);
- goto error;
- }
- }
-
- if ((c = tgt_node_alloc(XML_ELEMENT_TPGT, String, prop)) ==
- NULL) {
- free(prop);
- xml_rtn_msg(&msg, ERR_NO_MEM);
- goto error;
- }
-
- if ((list = tgt_node_next(t, XML_ELEMENT_TPGTLIST,
- NULL)) != NULL) {
- tgt_node_replace(list, c, MatchBoth);
- /*
- * tgt_node_replace will duplicate the child node
- * tgt_node_add which is used below just links it
- * into the tree.
- */
- tgt_node_free(c);
- } else {
- list = tgt_node_alloc(XML_ELEMENT_TPGTLIST, String, "");
- if (list == NULL) {
- free(prop);
- xml_rtn_msg(&msg, ERR_NO_MEM);
- goto error;
- }
- tgt_node_add(list, c);
- tgt_node_add(t, list);
- }
-
- free(prop);
- prop = NULL;
- change_made = True;
- }
-
- if (tgt_find_value_str(x, XML_ELEMENT_ACL, &prop) == True) {
- if (prop == NULL) {
- xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ACL);
- goto error;
- }
-
- c = tgt_node_alloc(XML_ELEMENT_INIT, String, prop);
- if (c == NULL) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- free(prop);
- goto error;
- }
- if ((list = tgt_node_next(t, XML_ELEMENT_ACLLIST,
- NULL)) != NULL) {
- tgt_node_replace(list, c, MatchBoth);
- /* ---- See above usage ---- */
- tgt_node_free(c);
- } else {
- list = tgt_node_alloc(XML_ELEMENT_ACLLIST, String, "");
- if (list == NULL) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- free(prop);
- goto error;
- }
- tgt_node_add(list, c);
- tgt_node_add(t, list);
- }
- free(prop);
- prop = NULL;
- change_made = True;
- }
-
- if (tgt_find_value_str(x, XML_ELEMENT_ALIAS, &prop) == True) {
- if (prop == NULL) {
- xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ALIAS);
- goto error;
- }
-
- if (modify_element(XML_ELEMENT_ALIAS, prop, t, MatchName) ==
- False) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- free(prop);
- goto error;
- }
- free(prop);
- prop = NULL;
- isns_mods |= ISNS_MOD_ALIAS;
- change_made = True;
- }
-
- if (tgt_find_value_str(x, XML_ELEMENT_MAXRECV, &prop) == True) {
- if (prop == NULL) {
- xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_MAXRECV);
- goto error;
- }
-
- if ((strtoll_multiplier(prop, &val) == False) ||
- (val < MAXRCVDATA_MIN) || (val > MAXRCVDATA_MAX)) {
- free(prop);
- xml_rtn_msg(&msg, ERR_INVALID_MAXRECV);
- goto error;
- }
- free(prop);
- if ((prop = malloc(32)) == NULL) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- goto error;
- }
- (void) snprintf(prop, 32, "%d", val);
-
- if (modify_element(XML_ELEMENT_MAXRECV, prop, t, MatchName) ==
- False) {
- free(prop);
- xml_rtn_msg(&msg, ERR_NO_MEM);
- goto error;
- }
- free(prop);
- prop = NULL;
- change_made = True;
- }
-
- if (change_made == True) {
- if (mgmt_config_save2scf() == False) {
- xml_rtn_msg(&msg, ERR_UPDATE_TARGCFG_FAILED);
- goto error;
- }
- if (isns_enabled() == True) {
- if (isns_dev_update(t->x_value, isns_mods) != 0) {
- xml_rtn_msg(&msg, ERR_ISNS_ERROR);
- goto error;
- }
- }
- xml_rtn_msg(&msg, ERR_SUCCESS);
- } else {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND);
- }
-
-error:
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- if (node)
- tgt_node_free(node);
- return (msg);
-}
-
-/*
- * []----
- * | modify_initiator -- store the CHAP information for an initiator
- * []----
- */
-static char *
-modify_initiator(tgt_node_t *x)
-{
- char *msg = NULL;
- char *name = NULL;
- char *prop = NULL;
- tgt_node_t *inode = NULL;
- Boolean_t changes_made = False;
-
- (void) pthread_rwlock_wrlock(&targ_config_mutex);
- if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
- goto error;
- }
-
- while ((inode = tgt_node_next_child(main_config, XML_ELEMENT_INIT,
- inode)) != NULL) {
- if (strcmp(inode->x_value, name) == 0)
- break;
- }
-
- /*
- * We no longer need the name since we should have found the node
- * it refers to and this way we don't have to worry about freeing
- * the storage later.
- */
- free(name);
-
- if (inode == NULL) {
- xml_rtn_msg(&msg, ERR_INIT_NOT_FOUND);
- goto error;
- }
-
- if (tgt_find_value_str(x, XML_ELEMENT_CHAPSECRET, &prop) == True) {
- if (prop == NULL) {
- xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_CHAPSECRET);
- goto error;
- }
-
- if (modify_element(XML_ELEMENT_CHAPSECRET, prop, inode,
- MatchName) == False) {
- free(prop);
- xml_rtn_msg(&msg, ERR_NO_MEM);
- goto error;
- }
- free(prop);
- changes_made = True;
- }
-
- if (tgt_find_value_str(x, XML_ELEMENT_DELETE_CHAPSECRET,
- &prop) == True) {
- if (prop == NULL || strcmp(prop, XML_VALUE_TRUE) != 0) {
- if (prop != NULL)
- free(prop);
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND);
- goto error;
- }
- free(prop);
-
- if (delete_element(XML_ELEMENT_CHAPSECRET, inode,
- MatchName) == False) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- goto error;
- }
- changes_made = True;
- }
-
- if (tgt_find_value_str(x, XML_ELEMENT_CHAPNAME, &prop) == True) {
- if (prop == NULL) {
- xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_CHAPNAME);
- goto error;
- }
-
- if (modify_element(XML_ELEMENT_CHAPNAME, prop, inode,
- MatchName) == False) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- free(prop);
- goto error;
- }
- free(prop);
- changes_made = True;
- }
-
- if (tgt_find_value_str(x, XML_ELEMENT_DELETE_CHAPNAME, &prop) == True) {
- if (prop == NULL || strcmp(prop, XML_VALUE_TRUE) != 0) {
- if (prop != NULL)
- free(prop);
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND);
- goto error;
- }
- free(prop);
-
-
- if (delete_element(XML_ELEMENT_CHAPNAME, inode,
- MatchName) == False) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- goto error;
- }
- changes_made = True;
- }
-
- if (changes_made == True) {
- if (mgmt_config_save2scf() == True) {
- xml_rtn_msg(&msg, ERR_SUCCESS);
- } else {
- xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
- }
- } else {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND);
- }
-
-error:
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (msg);
-}
-
-/*
- * []----
- * | modify_admin -- modify one or more of the admin related props
- * []----
- */
-static char *
-modify_admin(tgt_node_t *x)
-{
- char *msg = NULL;
- char *prop;
- Boolean_t changes_made = False;
- Boolean_t update_isns = False;
- admin_table_t *ap;
-
- for (ap = admin_prop_list; ap->name; ap++) {
- if (tgt_find_value_str(x, ap->name, &prop) == True) {
-
- if ((prop == NULL) || (strlen(prop) == 0))
- break;
-
- /*
- * Do the function call first if it exists which
- * will allow possible checking to be done first.
- */
- if (ap->func) {
- msg = (*ap->func)(ap->name, prop);
- if (msg != NULL) {
- free(prop);
- return (msg);
- }
- }
-
- (void) pthread_rwlock_wrlock(&targ_config_mutex);
- if (ap->delete_name == NULL) {
- if (modify_element(ap->name, prop, main_config,
- MatchName) == False) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- free(prop);
- (void) pthread_rwlock_unlock(
- &targ_config_mutex);
- return (msg);
- }
- } else {
- if (strcmp(prop, XML_VALUE_TRUE) != 0) {
- xml_rtn_msg(&msg,
- ERR_SYNTAX_MISSING_OPERAND);
- free(prop);
- (void) pthread_rwlock_unlock(
- &targ_config_mutex);
- return (msg);
- }
- if (delete_element(ap->delete_name,
- main_config, MatchName) == False) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- free(prop);
- (void) pthread_rwlock_unlock(
- &targ_config_mutex);
- return (msg);
- }
- }
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- if (0 == strcmp(ap->name, XML_ELEMENT_ISNS_ACCESS) ||
- 0 == strcmp(ap->name, XML_ELEMENT_ISNS_SERV)) {
- update_isns = True;
- }
- free(prop);
- changes_made = True;
- }
- }
-
- if (changes_made == True) {
- /* isns_update updates isns_access & isns server name */
- if (update_isns == True) {
- if (isns_update() != 0) {
- xml_rtn_msg(&msg, ERR_ISNS_ERROR);
- return (msg);
- }
- }
- if (mgmt_config_save2scf() == True) {
- xml_rtn_msg(&msg, ERR_SUCCESS);
- } else {
- xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
- }
- } else {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND);
- }
-
- return (msg);
-}
-
-/*
- * []----
- * | modify_tpgt -- add an IP-address to a target portal group
- * []----
- */
-static char *
-modify_tpgt(tgt_node_t *x)
-{
- struct addrinfo *res = NULL;
- char *msg = NULL;
- char *name = NULL;
- char *ip_str = NULL;
- tgt_node_t *tnode = NULL;
- tgt_node_t *list = NULL;
-
- (void) pthread_rwlock_wrlock(&targ_config_mutex);
- if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
- goto error;
- }
- if (tgt_find_value_str(x, XML_ELEMENT_IPADDR, &ip_str) == False) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_IPADDR);
- goto error;
- }
- if ((getaddrinfo(ip_str, NULL, NULL, &res) != 0) || (res == NULL)) {
- xml_rtn_msg(&msg, ERR_INVALID_IP);
- goto error;
- }
- while ((tnode = tgt_node_next_child(main_config, XML_ELEMENT_TPGT,
- tnode)) != NULL) {
- if (strcmp(tnode->x_value, name) == 0)
- break;
- }
- if (tnode == NULL) {
- xml_rtn_msg(&msg, ERR_TPGT_NOT_FOUND);
- goto error;
- }
-
- if ((list = tgt_node_next(tnode, XML_ELEMENT_IPADDRLIST, NULL))
- == NULL) {
- list = tgt_node_alloc(XML_ELEMENT_IPADDRLIST, String, "");
- if (list == NULL) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- goto error;
- }
- tgt_node_add(tnode, list);
- }
- if (modify_element(XML_ELEMENT_IPADDR, ip_str, list, MatchBoth) ==
- False) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- goto error;
- }
-
- if (mgmt_config_save2scf() == True) {
- xml_rtn_msg(&msg, ERR_SUCCESS);
- } else {
- /* tpgt change should be updated to smf */
- xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
- }
-
- /*
- * Re-register all targets, currently there's no method to
- * update TPGT for individual target
- */
- if (isns_enabled() == True) {
- (void) isns_reg_all();
- }
-
-error:
- if (name)
- free(name);
- if (ip_str)
- free(ip_str);
- if (res)
- freeaddrinfo(res);
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (msg);
-}
-
-/*
- * modify_zfs -- test for the existence of a certain dataset being shared
- *
- * Called when someone uses the iscsitgt_is_shared() function from libiscsitgt.
- * All that
- */
-static char *
-modify_zfs(tgt_node_t *x, ucred_t *cred)
-{
- char *msg = NULL;
- char *dataset = NULL;
- char *prop;
- char *m;
- tgt_node_t *n = NULL;
- tgt_node_t *t = NULL;
- tgt_node_t *list = NULL;
- tgt_node_t *c1, *c2;
- Boolean_t change_made = False;
- uint64_t size;
- int status;
- int val;
- char *tru = "true";
-
- (void) pthread_rwlock_wrlock(&targ_config_mutex);
- if (tgt_find_value_str(x, XML_ELEMENT_NAME, &dataset) == False) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
- goto error;
- }
-
- /*
- * Validate request
- */
- if (tgt_find_value_str(x, XML_ELEMENT_VALIDATE, &tru)) {
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- if (tru)
- free(tru);
- free(dataset);
- return (validate_zfs_iscsitgt(x));
- }
-
- /*
- * Check for existance of ZFS shareiscsi properties
- */
- status = get_zfs_shareiscsi(dataset, &n, &size, cred);
- if ((status != ERR_SUCCESS) && (status != ERR_NULL_XML_MESSAGE)) {
- xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND);
- goto error;
- }
-
- while ((t = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, t))
- != NULL) {
- if (strcmp(t->x_value, dataset) == 0)
- break;
- }
- if (t == NULL) {
- xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND);
- goto error;
- }
-
- if (tgt_find_value_str(x, XML_ELEMENT_TPGT, &prop) == True) {
- if (prop == NULL) {
- xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_TPGT);
- goto error;
- }
-
- /*
- * Validate that the Target Portal Group Tag is reasonable.
- */
- val = strtoll(prop, &m, 0);
- if ((val < TPGT_MIN) || (val > TPGT_MAX) ||
- ((m != NULL) && (*m != '\0'))) {
- xml_rtn_msg(&msg, ERR_INVALID_TPGT);
- goto error;
- }
-
- if ((c1 = tgt_node_alloc(XML_ELEMENT_TPGT, String, prop)) ==
- NULL) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- goto error;
- }
-
- /*
- * Due to the fact that the targets_config differs from the
- * ZVOL properties stored in zfs_shareiscsi, two lists need to
- * be updated
- */
- c2 = tgt_node_dup(c1);
- if ((list = tgt_node_next(t, XML_ELEMENT_TPGTLIST, NULL))
- != NULL) {
- /*
- * tgt_node_replace will duplicate the child node
- * tgt_node_add which is used below just links it
- * into the tree.
- */
- tgt_node_replace(list, c1, MatchBoth);
- tgt_node_free(c1);
- } else {
- list = tgt_node_alloc(XML_ELEMENT_TPGTLIST, String, "");
- if (list == NULL) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- goto error;
- }
- tgt_node_add(list, c1);
- tgt_node_add(t, list);
- }
- if ((list = tgt_node_next(n, XML_ELEMENT_TPGTLIST, NULL))
- != NULL) {
- /*
- * tgt_node_replace will duplicate the child node
- * tgt_node_add which is used below just links it
- * into the tree.
- */
- tgt_node_replace(list, c2, MatchBoth);
- tgt_node_free(c2);
- } else {
- list = tgt_node_alloc(XML_ELEMENT_TPGTLIST, String, "");
- if (list == NULL) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- goto error;
- }
- tgt_node_add(list, c2);
- tgt_node_add(n, list);
- }
- change_made = True;
- }
-
- if (tgt_find_value_str(x, XML_ELEMENT_ACL, &prop) == True) {
- if (prop == NULL) {
- xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ACL);
- goto error;
- }
-
- c1 = tgt_node_alloc(XML_ELEMENT_INIT, String, prop);
- if (c1 == NULL) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- goto error;
- }
-
- /*
- * Due to the fact that the targets_config differs from the
- * ZVOL properties stored in zfs_shareiscsi, two lists need to
- * be updated
- */
- c2 = tgt_node_dup(c1);
- if ((list = tgt_node_next(t, XML_ELEMENT_ACLLIST, NULL))
- != NULL) {
- /*
- * tgt_node_replace will duplicate the child node
- * tgt_node_add which is used below just links it
- * into the tree.
- */
- tgt_node_replace(list, c1, MatchBoth);
- tgt_node_free(c1);
- } else {
- list = tgt_node_alloc(XML_ELEMENT_ACLLIST, String, "");
- if (list == NULL) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- goto error;
- }
- tgt_node_add(list, c1);
- tgt_node_add(t, list);
- }
- if ((list = tgt_node_next(n, XML_ELEMENT_ACLLIST, NULL))
- != NULL) {
- /*
- * tgt_node_replace will duplicate the child node
- * tgt_node_add which is used below just links it
- * into the tree.
- */
- tgt_node_replace(list, c2, MatchBoth);
- tgt_node_free(c2);
- } else {
- list = tgt_node_alloc(XML_ELEMENT_ACLLIST, String, "");
- if (list == NULL) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- goto error;
- }
- tgt_node_add(list, c2);
- tgt_node_add(n, list);
- }
-
- change_made = True;
- }
-
- if (change_made == True) {
- status = put_zfs_shareiscsi(dataset, n);
- if (status != ERR_SUCCESS) {
- xml_rtn_msg(&msg, status);
- goto error;
- } else {
- xml_rtn_msg(&msg, ERR_SUCCESS);
- }
- } else {
- xml_rtn_msg(&msg, ERR_SUCCESS);
- }
-
-error:
- if (n)
- tgt_node_free(n);
- if (dataset)
- free(dataset);
-
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (msg);
-}
-
-/*
- * Just checking the existance of the given target. Here we check whether
- * both zfs and iscsitarget aware of the given target/volume. It neither
- * care about the credentials nor SHAREISCSI properties.
- */
-static char *
-validate_zfs_iscsitgt(tgt_node_t *x)
-{
- char *msg = NULL;
- char *prop = NULL;
- char *dataset = NULL;
- libzfs_handle_t *zh = NULL;
- zfs_handle_t *zfsh = NULL;
- tgt_node_t *n = NULL;
-
- if (tgt_find_value_str(x, XML_ELEMENT_NAME, &dataset) == False) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
- return (msg);
- }
-
- if (((zh = libzfs_init()) == NULL) ||
- ((zfsh = zfs_open(zh, dataset, ZFS_TYPE_DATASET)) == NULL)) {
- xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND);
- goto error;
- }
-
- while ((n = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, n)) !=
- NULL) {
- if (strcmp(n->x_value, dataset) == 0)
- break;
- }
- if (n == NULL) {
- xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND);
- goto error;
- }
-
- xml_rtn_msg(&msg, ERR_SUCCESS);
-
-error:
- if (zfsh)
- zfs_close(zfsh);
- if (prop)
- free(prop);
- if (zh)
- libzfs_fini(zh);
- if (dataset)
- free(dataset);
-
- return (msg);
-
-}
-
-
-/*
- * []----
- * | modify_element -- helper function to create node and add it to parent
- * |
- * | A False return value indicates a failure to allocate enough memory.
- * []----
- */
-static Boolean_t
-modify_element(char *name, char *value, tgt_node_t *p, match_type_t m)
-{
- tgt_node_t *c;
-
-
- if ((c = tgt_node_alloc(name, String, value)) == NULL) {
- return (False);
- } else {
- tgt_node_replace(p, c, m);
- tgt_node_free(c);
- return (True);
- }
-}
-
-/*
- * []----
- * | delete_element -- helper function to remove a node from a parent
- * |
- * | A False return value indicates a failure to allocate enough memory.
- * []----
- */
-static Boolean_t
-delete_element(char *name, tgt_node_t *p, match_type_t m)
-{
- tgt_node_t *c;
-
- if ((c = tgt_node_alloc(name, String, NULL)) == NULL) {
- return (False);
- }
- (void) tgt_node_remove(p, c, m);
- tgt_node_free(c);
- return (True);
-}
-
-/*
- * []----
- * | update_basedir -- update the global target directory
- * |
- * | Most of the properties when updated require no futher processing. The
- * | target base directory however must be updated if it hasn't been set.
- * | On a new system the daemon will not have any location to place the
- * | backing store and target configuration files. On a live system we would
- * | screw things up if we changed the global variable if it was already
- * | in use, so we only allow the updating to occur if there are no targets.
- * []----
- */
-/*ARGSUSED*/
-char *
-update_basedir(char *name, char *prop)
-{
- tgt_node_t *targ = NULL;
- char *msg = NULL;
- char *v;
-
- if ((prop == NULL) || (strlen(prop) == 0) || (prop[0] != '/')) {
- xml_rtn_msg(&msg, ERR_INVALID_BASEDIR);
- return (msg);
- }
-
- while ((targ = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
- targ)) != NULL) {
- /*
- * Traverse the list of configured targets, serching for any
- * target that is using the current base-directory. Fail the
- * update if found.
- *
- * The only targets that do not use the base-directory at this
- * time are those targets persisted in ZFS.
- */
- if (tgt_find_attr_str(targ, XML_ELEMENT_INCORE, &v) == True) {
- if (v != NULL) {
- if (strcmp(v, XML_VALUE_TRUE) == 0) {
- free(v);
- continue;
- }
- free(v);
- }
- }
-
- /*
- * Found at least one target, so fail
- */
- xml_rtn_msg(&msg, ERR_VALID_TARG_EXIST);
- return (msg);
- }
-
- if (target_basedir) {
- free(target_basedir);
- }
- target_basedir = strdup(prop);
- if ((mkdir(target_basedir, 0700) != 0) && (errno != EEXIST)) {
- xml_rtn_msg(&msg, ERR_CREATE_TARGET_DIR_FAILED);
- free(target_basedir);
- target_basedir = NULL;
- }
- return (msg);
-}
-
-/*
- * []----
- * | validate_radius -- validate that server[:port] are valid
- * []----
- */
-char *
-valid_radius_srv(char *name, char *prop)
-{
- struct addrinfo *res = NULL;
- char *msg = NULL;
- char *sp, *p;
- int port;
-
- if ((sp = strdup(prop)) == NULL) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- return (msg);
- } else if ((p = strrchr(sp, ':')) != NULL) {
- *p++ = '\0';
- port = atoi(p);
- if ((port < 1) || (port > 65535)) {
- xml_rtn_msg(&msg, ERR_INVALID_RADSRV);
- free(sp);
- return (msg);
- }
- }
- if ((getaddrinfo(sp, NULL, NULL, &res) != 0) || (res == NULL))
- xml_rtn_msg(&msg, ERR_INVALID_RADSRV);
- else
- freeaddrinfo(res);
- free(sp);
- return (msg);
-}
-
-/*
- * []----
- * | validate_isns_server -- validate that server[:port] are valid
- * []----
- */
-char *
-valid_isns_srv(char *name, char *prop)
-{
- char *msg = NULL;
- char *sp, *p;
- int so;
- int port;
-
- if (strlen(prop) > MAXHOSTNAMELEN) {
- xml_rtn_msg(&msg, ERR_INVALID_ISNS_SRV);
- return (msg);
- }
-
- if ((sp = strdup(prop)) == NULL) {
- xml_rtn_msg(&msg, ERR_NO_MEM);
- return (msg);
- }
- if ((p = strrchr(sp, ':')) != NULL) {
- *p++ = '\0';
- port = atoi(p);
- if ((port < 1) || (port > 65535)) {
- xml_rtn_msg(&msg, ERR_INVALID_ISNS_SRV);
- free(sp);
- return (msg);
- }
- }
-
- so = isns_open(sp);
- if (so < 0) {
- if (isns_enabled() == True) {
- xml_rtn_msg(&msg, ERR_INVALID_ISNS_SRV);
- } else { /* Just print a warning and accept the server */
- syslog(LOG_ALERT,
- "Check if the server:%s is valid", sp);
- }
- } else {
- isns_close(so);
- }
- free(sp);
- return (msg);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c b/usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c
deleted file mode 100644
index 90757a0d0c..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c
+++ /dev/null
@@ -1,555 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * This file deals with XML data for removing various configuration data.
- */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <errno.h>
-#include <strings.h>
-#include <unistd.h>
-#include <priv.h>
-#include <syslog.h>
-#include <libzfs.h>
-
-#include <iscsitgt_impl.h>
-#include "utility.h"
-#include "queue.h"
-#include "target.h"
-#include "iscsi_cmd.h"
-#include "errcode.h"
-#include "isns_client.h"
-#include "mgmt_scf.h"
-
-static char *remove_target(tgt_node_t *x, ucred_t *cred);
-static char *remove_initiator(tgt_node_t *x);
-static char *remove_tpgt(tgt_node_t *x);
-static char *remove_zfs(tgt_node_t *x, ucred_t *cred);
-
-
-/*ARGSUSED*/
-void
-remove_func(tgt_node_t *p, target_queue_t *reply, target_queue_t *mgmt,
- ucred_t *cred)
-{
- tgt_node_t *x;
- char msgbuf[80];
- char *reply_msg = NULL;
-
- x = p->x_child;
-
- /*
- * remove_zfs() does not affect SMF data
- * therefore it is not covered by auth check
- */
- if (x == NULL) {
- xml_rtn_msg(&reply_msg, ERR_SYNTAX_MISSING_OBJECT);
- } else if (strcmp(x->x_name, XML_ELEMENT_ZFS) == 0) {
- reply_msg = remove_zfs(x, cred);
- } else if (check_auth_addremove(cred) != True) {
- xml_rtn_msg(&reply_msg, ERR_NO_PERMISSION);
- } else {
- if (x->x_name == NULL) {
- xml_rtn_msg(&reply_msg, ERR_SYNTAX_MISSING_OBJECT);
- } else if (strcmp(x->x_name, XML_ELEMENT_TARG) == 0) {
- reply_msg = remove_target(x, cred);
- } else if (strcmp(x->x_name, XML_ELEMENT_INIT) == 0) {
- reply_msg = remove_initiator(x);
- } else if (strcmp(x->x_name, XML_ELEMENT_TPGT) == 0) {
- reply_msg = remove_tpgt(x);
- } else {
- (void) snprintf(msgbuf, sizeof (msgbuf),
- "Unknown object '%s' for delete element",
- x->x_name);
- xml_rtn_msg(&reply_msg, ERR_INVALID_OBJECT);
- }
- }
- queue_message_set(reply, 0, msg_mgmt_rply, reply_msg);
-}
-
-/*
- * remove_zfs -- remove a ZFS property, or the entire ZVOL
- */
-static char *
-remove_zfs(tgt_node_t *x, ucred_t *cred)
-{
- char *msg = NULL;
- char *dataset = NULL;
- char *prop = NULL;
- tgt_node_t *n = NULL;
- tgt_node_t *t = NULL;
- tgt_node_t *list = NULL;
- tgt_node_t *c;
- Boolean_t change_made = False;
- uint64_t size;
- int status;
-
- (void) pthread_rwlock_wrlock(&targ_config_mutex);
- if (tgt_find_value_str(x, XML_ELEMENT_NAME, &dataset) == False) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
- goto error;
- }
-
- /*
- * Check for existance of ZFS shareiscsi properties
- */
- status = get_zfs_shareiscsi(dataset, &n, &size, cred);
-
- if ((status != ERR_SUCCESS) && (status != ERR_ZFS_ISCSISHARE_OFF) &&
- (status != ERR_NULL_XML_MESSAGE)) {
- xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND);
- goto error;
- }
-
- while ((t = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, t))
- != NULL) {
- if (strcmp(t->x_value, dataset) == 0)
- break;
- }
-
- if (t == NULL) {
- if (status == ERR_ZFS_ISCSISHARE_OFF) {
- /*
- * This is iscsishare=off request from zfs on a target
- * which is already unshared. In that case, zfs expects
- * "success" result.
- */
- xml_rtn_msg(&msg, ERR_SUCCESS);
- } else {
- xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND);
- }
- goto error;
- }
-
- if (tgt_find_value_str(x, XML_ELEMENT_TPGT, &prop) == True) {
- if (prop == NULL) {
- xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_TPGT);
- goto error;
- }
- if (status == ERR_ZFS_ISCSISHARE_OFF) {
- xml_rtn_msg(&msg, status);
- goto error;
- }
-
- /*
- * Due to the fact that the targets_config differs from the
- * ZVOL properties stored in zfs_shareiscsi, two lists need to
- * be updated
- */
- c = tgt_node_alloc(XML_ELEMENT_TPGT, String, prop);
- if ((list = tgt_node_next(t, XML_ELEMENT_TPGTLIST, NULL)) !=
- NULL) {
- (void) tgt_node_remove(list, c, MatchBoth);
- if (list->x_child == NULL)
- (void) tgt_node_remove(t, list, MatchName);
- }
- if ((list = tgt_node_next(n, XML_ELEMENT_TPGTLIST, NULL)) !=
- NULL) {
- (void) tgt_node_remove(list, c, MatchBoth);
- if (list->x_child == NULL)
- (void) tgt_node_remove(n, list, MatchName);
- }
- tgt_node_free(c);
-
- /* update isns */
- if (isns_enabled()) {
- if (isns_dev_update(t->x_value, ISNS_MOD_TPGT) != 0)
- syslog(LOG_ALERT, "ISNS register failed\n");
- }
- free(prop);
- prop = NULL;
- change_made = True;
- }
-
- if (tgt_find_value_str(x, XML_ELEMENT_ACL, &prop) == True) {
- if (prop == NULL) {
- xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ACL);
- goto error;
- }
- if (status == ERR_ZFS_ISCSISHARE_OFF) {
- xml_rtn_msg(&msg, status);
- goto error;
- }
- /*
- * Due to the fact that the targets_config differs from the
- * ZVOL properties stored in zfs_shareiscsi, two lists need to
- * be updated
- */
- c = tgt_node_alloc(XML_ELEMENT_INIT, String, prop);
- if ((list = tgt_node_next(t, XML_ELEMENT_ACLLIST, NULL)) !=
- NULL) {
- (void) tgt_node_remove(list, c, MatchBoth);
- if (list->x_child == NULL)
- (void) tgt_node_remove(t, list, MatchName);
- }
- if ((list = tgt_node_next(n, XML_ELEMENT_ACLLIST, NULL)) !=
- NULL) {
- (void) tgt_node_remove(list, c, MatchBoth);
- if (list->x_child == NULL)
- (void) tgt_node_remove(n, list, MatchName);
- }
- tgt_node_free(c);
- free(prop);
- prop = NULL;
- change_made = True;
- }
-
- if (change_made == False) {
- if (tgt_find_value_str(t, XML_ELEMENT_INAME, &prop) == False) {
- xml_rtn_msg(&msg, ERR_TARGCFG_MISSING_INAME);
- goto error;
- }
-
- /* deregister zovl target from iSNS server. */
- if (isns_enabled() == True) {
- if (isns_dereg(prop) != 0)
- syslog(LOG_INFO, "ISNS dereg failed\n");
- }
-
- (void) tgt_node_remove(targets_config, t, MatchBoth);
-
- /*
- * Wait until here to issue a logout to any initiators that
- * might be logged into the target. Certain initiators are
- * sneaky in that if asked to logout they will, but turn right
- * around and log back into the target. By waiting here to issue
- * the logout we'll have removed reference to the target such
- * that this can't happen.
- */
- logout_targ(prop);
- thick_provo_stop(prop, 0);
-
- xml_rtn_msg(&msg, ERR_SUCCESS);
- } else {
- status = put_zfs_shareiscsi(dataset, n);
- if (status != ERR_SUCCESS) {
- xml_rtn_msg(&msg, status);
- goto error;
- } else {
- xml_rtn_msg(&msg, ERR_SUCCESS);
- }
- }
-
-error:
- if (prop)
- free(prop);
- if (n)
- tgt_node_free(n);
- if (dataset)
- free(dataset);
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (msg);
-}
-
-static char *
-remove_target(tgt_node_t *x, ucred_t *cred)
-{
- char *msg = NULL;
- char *prop = NULL;
- tgt_node_t *targ = NULL;
- tgt_node_t *list;
- tgt_node_t *c = NULL;
- Boolean_t change_made = False;
- int lun_num;
-
- (void) pthread_rwlock_wrlock(&targ_config_mutex);
- if (tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
- goto error;
- }
-
- while ((targ = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
- targ)) != NULL) {
- if (strcmp(targ->x_value, prop) == 0)
- break;
- }
- free(prop);
- prop = NULL;
- if (targ == NULL) {
- xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND);
- goto error;
- }
-
- if (tgt_find_attr_str(targ, XML_ELEMENT_INCORE, &prop) == True) {
- if (strcmp(prop, "true") == 0) {
- free(prop);
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (remove_zfs(x, cred));
- }
- free(prop);
- }
-
- if (tgt_find_value_str(x, XML_ELEMENT_ACL, &prop) == True) {
- if (prop == NULL) {
- xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ACL);
- goto error;
- }
- if ((list = tgt_node_next(targ, XML_ELEMENT_ACLLIST, NULL)) ==
- NULL) {
- xml_rtn_msg(&msg, ERR_ACL_NOT_FOUND);
- goto error;
- }
- c = tgt_node_alloc(XML_ELEMENT_INIT, String, prop);
- if (tgt_node_remove(list, c, MatchBoth) == False) {
- xml_rtn_msg(&msg, ERR_INIT_NOT_FOUND);
- goto error;
- }
- tgt_node_free(c);
- if (list->x_child == NULL)
- (void) tgt_node_remove(targ, list, MatchName);
- free(prop);
- change_made = True;
- }
- if (tgt_find_value_str(x, XML_ELEMENT_TPGT, &prop) == True) {
- if (prop == NULL) {
- xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_TPGT);
- goto error;
- }
- if ((list = tgt_node_next(targ, XML_ELEMENT_TPGTLIST, NULL)) ==
- NULL) {
- xml_rtn_msg(&msg, ERR_TPGT_NOT_FOUND);
- goto error;
- }
- c = tgt_node_alloc(XML_ELEMENT_TPGT, String, prop);
- if (tgt_node_remove(list, c, MatchBoth) == False) {
- xml_rtn_msg(&msg, ERR_TPGT_NOT_FOUND);
- goto error;
- }
- tgt_node_free(c);
- if (list->x_child == NULL)
- (void) tgt_node_remove(targ, list, MatchName);
-
- /* update isns */
- if (isns_enabled()) {
- if (isns_dev_update(targ->x_value, ISNS_MOD_TPGT) != 0)
- syslog(LOG_ALERT, "ISNS register failed\n");
- }
-
- free(prop);
- prop = NULL;
- change_made = True;
- }
- if (tgt_find_value_int(x, XML_ELEMENT_LUN, &lun_num) == True) {
-
- if (tgt_find_value_intchk(x, XML_ELEMENT_LUN, &lun_num) ==
- False) {
- xml_rtn_msg(&msg, ERR_LUN_INVALID_RANGE);
- goto error;
- }
-
- /*
- * Save the iscsi-name which we'll need to remove LUNs.
- */
- if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &prop) ==
- False) {
- xml_rtn_msg(&msg, ERR_TARGCFG_MISSING_INAME);
- goto error;
- }
-
- logout_targ(prop);
- thick_provo_stop(prop, lun_num);
-
- remove_target_common(targ->x_value, lun_num, &msg);
- if (msg != NULL)
- goto error;
-
- /* ISNS de-register target if it's the last lun */
- if (lun_num == 0 && isns_enabled() == True) {
- if (isns_dereg(prop) != 0)
- syslog(LOG_INFO, "ISNS dereg failed\n");
- }
-
- iscsi_inventory_change(prop);
- free(prop);
- change_made = True;
- }
-
- if (change_made == True) {
- if (mgmt_config_save2scf() == True) {
- xml_rtn_msg(&msg, ERR_SUCCESS);
- } else {
- xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
- }
- } else {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND);
- }
-
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (msg);
-
-error:
- if (c != NULL)
- tgt_node_free(c);
- if (prop != NULL)
- free(prop);
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (msg);
-}
-
-static char *
-remove_initiator(tgt_node_t *x)
-{
- char *msg = NULL;
- char *name;
- tgt_node_t *node = NULL;
-
- (void) pthread_rwlock_wrlock(&targ_config_mutex);
- if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (msg);
- }
- while ((node = tgt_node_next_child(main_config, XML_ELEMENT_INIT, node))
- != NULL) {
- if (strcmp(node->x_value, name) == 0)
- break;
- }
- free(name);
- if (node == NULL) {
- xml_rtn_msg(&msg, ERR_INIT_NOT_FOUND);
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (msg);
- }
- if (tgt_find_value_str(x, XML_ELEMENT_ALL, &name) == False) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_ALL);
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (msg);
- }
- (void) tgt_node_remove(main_config, node, MatchBoth);
-
- if (mgmt_config_save2scf() == True) {
- xml_rtn_msg(&msg, ERR_SUCCESS);
- } else {
- xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
- }
-
- free(name);
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (msg);
-}
-
-static char *
-remove_tpgt(tgt_node_t *x)
-{
- char *msg = NULL;
- char *prop = NULL;
- tgt_node_t *targ = NULL;
- tgt_node_t *lnode = NULL;
- tgt_node_t *lnp = NULL;
- tgt_node_t *node = NULL;
- tgt_node_t *c = NULL;
- tgt_node_t *list = NULL;
- Boolean_t change_made = False;
-
- (void) pthread_rwlock_wrlock(&targ_config_mutex);
- if (tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (msg);
- }
- while ((node = tgt_node_next_child(main_config, XML_ELEMENT_TPGT, node))
- != NULL) {
- if (strcmp(node->x_value, prop) == 0)
- break;
- }
- if (node == NULL) {
- xml_rtn_msg(&msg, ERR_TPGT_NOT_FOUND);
- free(prop);
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (msg);
- }
- while ((targ = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
- targ)) != NULL) {
- if ((lnode = tgt_node_next(targ, XML_ELEMENT_TPGTLIST,
- NULL)) != NULL) {
- lnp = NULL;
- while ((lnp = tgt_node_next_child(lnode, XML_ELEMENT_TPGT,
- lnp)) != NULL)
- if (strcmp(lnp->x_value, prop) == 0) {
- xml_rtn_msg(&msg, ERR_TPGT_IN_USE);
- free(prop);
- (void) pthread_rwlock_unlock(
- &targ_config_mutex);
- return (msg);
- }
- }
- }
- free(prop);
- if (tgt_find_value_str(x, XML_ELEMENT_IPADDR, &prop) == True) {
- if (prop == NULL) {
- xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_IPADDR);
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (msg);
- }
- if ((list = tgt_node_next(node, XML_ELEMENT_IPADDRLIST, NULL))
- == NULL) {
- xml_rtn_msg(&msg, ERR_TPGT_NO_IPADDR);
- goto error;
- }
- c = tgt_node_alloc(XML_ELEMENT_IPADDR, String, prop);
- if (tgt_node_remove(list, c, MatchBoth) == False) {
- xml_rtn_msg(&msg, ERR_INVALID_IP);
- goto error;
- }
- tgt_node_free(c);
- free(prop);
- if (list->x_child == NULL)
- (void) tgt_node_remove(node, list, MatchName);
- change_made = True;
- }
- if ((change_made != True) &&
- (tgt_find_value_str(x, XML_ELEMENT_ALL, &prop) == True)) {
- (void) tgt_node_remove(main_config, node, MatchBoth);
- change_made = True;
- free(prop);
- }
-
- if (change_made == True) {
- /* Isns re-register all target */
- if (isns_enabled() == True)
- (void) isns_reg_all();
- if (mgmt_config_save2scf() == True) {
- xml_rtn_msg(&msg, ERR_SUCCESS);
- } else {
- xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
- }
- } else {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND);
- }
-
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (msg);
-
-error:
- if (c != NULL)
- tgt_node_free(c);
- if (prop != NULL)
- free(prop);
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (msg);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/mgmt_scf.c b/usr/src/cmd/iscsi/iscsitgtd/mgmt_scf.c
deleted file mode 100644
index 11b316eb35..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_scf.c
+++ /dev/null
@@ -1,1647 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <time.h>
-#include <unistd.h>
-#include <pthread.h>
-#include <sys/conf.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <errno.h>
-#include <signal.h>
-#include <siginfo.h>
-#include <libscf.h>
-#include <syslog.h>
-#include <synch.h>
-#include <libxml/xmlreader.h>
-#include <sys/resource.h>
-#include <sys/select.h>
-#include <iscsitgt_impl.h>
-#include <umem.h>
-#include <priv.h>
-#include <libgen.h>
-#include <ctype.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <auth_attr.h>
-#include <sasl/saslutil.h>
-#include <sys/wait.h>
-
-#include "mgmt_scf.h"
-#include "port.h"
-#include "iscsi_conn.h"
-#include "target.h"
-#include "utility.h"
-#include "iscsi_ffp.h"
-#include "errcode.h"
-#include "t10.h"
-
-static Boolean_t create_pg(targ_scf_t *h, char *pgname, char *prop);
-static void new_property(targ_scf_t *h, tgt_node_t *n);
-static void new_value_list(targ_scf_t *h, tgt_node_t *p);
-static int isnumber(char *s);
-static void backup(char *file, char *ext);
-static pthread_mutex_t scf_conf_mutex;
-static pthread_mutex_t scf_param_mutex;
-
-static void pgname_encode(char *instr, char *outstr, int max_len);
-static void pgname_decode(char *instr);
-
-Boolean_t
-mgmt_scf_init()
-{
- (void) pthread_mutex_init(&scf_conf_mutex, NULL);
- (void) pthread_mutex_init(&scf_param_mutex, NULL);
- return (True);
-}
-
-void
-mgmt_scf_fini()
-{
- (void) pthread_mutex_destroy(&scf_conf_mutex);
- (void) pthread_mutex_destroy(&scf_param_mutex);
-}
-
-void
-mgmt_handle_fini(targ_scf_t *h)
-{
- if (h != NULL) {
- int unbind = 0;
- if (h->t_scope != NULL) {
- unbind = 1;
- scf_scope_destroy(h->t_scope);
- h->t_scope = NULL;
- }
- if (h->t_instance != NULL) {
- scf_instance_destroy(h->t_instance);
- h->t_instance = NULL;
- }
- if (h->t_service != NULL) {
- scf_service_destroy(h->t_service);
- h->t_service = NULL;
- }
- if (h->t_pg != NULL) {
- scf_pg_destroy(h->t_pg);
- h->t_pg = NULL;
- }
- if (h->t_handle != NULL) {
- if (unbind)
- (void) scf_handle_unbind(h->t_handle);
- scf_handle_destroy(h->t_handle);
- h->t_handle = NULL;
- }
- free(h);
- h = NULL;
- }
-}
-
-targ_scf_t *
-mgmt_handle_init(void)
-{
- targ_scf_t *h;
-
- h = calloc(1, sizeof (targ_scf_t));
- if (h == NULL)
- return (NULL);
-
- h->t_handle = scf_handle_create(SCF_VERSION);
- if (h->t_handle != NULL) {
- if (scf_handle_bind(h->t_handle) == 0) {
- h->t_scope = scf_scope_create(h->t_handle);
- h->t_service = scf_service_create(h->t_handle);
- h->t_pg = scf_pg_create(h->t_handle);
- h->t_instance = scf_instance_create(h->t_handle);
- if (scf_handle_get_scope(h->t_handle, SCF_SCOPE_LOCAL,
- h->t_scope) == 0) {
- if (scf_scope_get_service(h->t_scope,
- SA_TARGET_SVC_NAME, h->t_service) != 0)
- goto error;
-
- } else {
- syslog(LOG_ERR,
- "Got local scope which is wrong\n");
- goto error;
- }
- } else
- goto error;
- } else {
- free(h);
- h = NULL;
- syslog(LOG_ERR,
- "iscsitgt could not access SMF repository: %s\n",
- scf_strerror(scf_error()));
- }
-
- return (h);
-error:
- mgmt_handle_fini(h);
- free(h);
- syslog(LOG_ERR, "iscsitgt SMF initialization problem: %s\n",
- scf_strerror(scf_error()));
- return (NULL);
-}
-
-/*
- * This function starts a transaction with name of a property group
- * and name of its property. If the property group does not exist
- * this function will create an empty property group.
- */
-Boolean_t
-mgmt_transaction_start(targ_scf_t *h, char *pg, char *prop)
-{
- Boolean_t ret = True;
-
- h->t_trans = scf_transaction_create(h->t_handle);
- if (h->t_trans != NULL) {
- if ((create_pg(h, pg, prop) == False) ||
- (scf_transaction_start(h->t_trans, h->t_pg) != 0)) {
- scf_transaction_destroy(h->t_trans);
- h->t_trans = NULL;
- ret = False;
- syslog(LOG_ERR, "transaction_start start: %s\n",
- scf_strerror(scf_error()));
- }
- } else {
- syslog(LOG_ERR, "transaction_start create: %s\n",
- scf_strerror(scf_error()));
- ret = False;
- }
- return (ret);
-}
-
-Boolean_t
-mgmt_transaction_end(targ_scf_t *h)
-{
- Boolean_t ret = True;
-
- if (scf_transaction_commit(h->t_trans) < 0)
- ret = False;
- (void) scf_pg_update(h->t_pg);
- (void) scf_transaction_destroy_children(h->t_trans);
- (void) scf_transaction_destroy(h->t_trans);
- h->t_trans = NULL;
- return (ret);
-}
-
-void
-mgmt_transaction_abort(targ_scf_t *h)
-{
- if (h->t_trans != NULL) {
- scf_transaction_reset_all(h->t_trans);
- scf_transaction_destroy_children(h->t_trans);
- scf_transaction_destroy(h->t_trans);
- h->t_trans = NULL;
- }
-}
-
-/*
- * process property group name first
- * a reasonable buf to receive encoded pgname is double size of pgname
- */
-#define PG_FACTOR 2
-static Boolean_t
-create_pg(targ_scf_t *h, char *pgname, char *prop)
-{
- int len;
- char *buf = NULL;
-
- len = strlen(pgname);
- buf = (char *)calloc(1, len * PG_FACTOR);
- if (buf == NULL)
- return (False);
-
- pgname_encode(pgname, buf, len * PG_FACTOR);
-
- if (scf_service_get_pg(h->t_service, buf, h->t_pg) != 0) {
- if (scf_service_add_pg(h->t_service, buf,
- prop, 0, h->t_pg) != 0) {
- free(buf);
- return (False);
- }
- }
- free(buf);
- return (True);
-}
-
-/*
- * Manage allocating dynamic memory for a string that is stored in
- * the SCF database.
- *
- * scf_limit(3SCF) is called in order to compute the maximum length of
- * the type of string specified by the 'limit' argument. malloc()
- * is then called to allocate the memory.
- *
- * If the function returns True, then the by-reference arguments will
- * be updated to hold the length and address of the memory chunk.
- */
-static Boolean_t
-alloc_scf_element(uint32_t limit, ssize_t *max_len, void **buf)
-{
- ssize_t max_name_len;
- void *name_buf;
- Boolean_t status = False;
-
- /*
- * Dynamically compute the maximum length of the specified type
- * of string so that our algorithms do not use an arbitrary,
- * statically-defined value.
- */
- if ((max_name_len = scf_limit(limit)) >= 0) {
- /*
- * scf_limit's return value knows nothing about a C-string's
- * trailing NULL byte; increment the count to allow for it.
- */
- max_name_len++;
-
- if ((name_buf = malloc(max_name_len)) != NULL) {
- *max_len = max_name_len;
- *buf = name_buf;
- status = True;
- }
- }
-
- return (status);
-}
-
-/*
- * Allocate dynamic memory for a string containing a NAME that is stored in
- * the SCF database.
- */
-static Boolean_t
-alloc_scf_name(ssize_t *max_len, void **buf)
-{
- return (alloc_scf_element(SCF_LIMIT_MAX_NAME_LENGTH, max_len, buf));
-}
-
-/*
- * Allocate dynamic memory for a string containing a VALUE that is stored in
- * the SCF database.
- */
-static Boolean_t
-alloc_scf_value(ssize_t *max_len, void **buf)
-{
- return (alloc_scf_element(SCF_LIMIT_MAX_VALUE_LENGTH, max_len, buf));
-}
-
-/*
- * mgmt_get_main_config() loads main configuration
- * from scf into a node tree.
- * Main configuration includes: admin/target/tpgt/initiator info.
- * admin info is stored in "iscsitgt" property group
- * target info is stored in "target_<name>" property group
- * initiator info is stored in "initiator_<name>" property group
- * tpgt info is stored in "tpgt_<number>" property group
- */
-Boolean_t
-mgmt_get_main_config(tgt_node_t **node)
-{
- targ_scf_t *h = NULL;
- scf_property_t *prop = NULL;
- scf_value_t *value = NULL;
- scf_iter_t *iter = NULL;
- scf_iter_t *iter_v = NULL;
- scf_iter_t *iter_pv = NULL;
- char *pname = NULL;
- char *valuebuf = NULL;
- ssize_t max_name_len;
- ssize_t max_value_len;
- char passcode[32];
- unsigned int outlen;
- tgt_node_t *n;
- tgt_node_t *pn;
- tgt_node_t *vn;
- Boolean_t status = False;
-
- h = mgmt_handle_init();
-
- if (h == NULL)
- return (status);
-
- prop = scf_property_create(h->t_handle);
- value = scf_value_create(h->t_handle);
- iter = scf_iter_create(h->t_handle);
-
- if ((alloc_scf_name(&max_name_len, (void *)&pname) == False) ||
- (alloc_scf_value(&max_value_len, (void *)&valuebuf) == False)) {
- goto error;
- }
-
- (void) pthread_mutex_lock(&scf_conf_mutex);
-
- /* Basic Information is stored in iscsitgt pg */
- if (scf_service_get_pg(h->t_service, "iscsitgt", h->t_pg) == -1) {
- goto error;
- }
-
- *node = NULL;
- *node = tgt_node_alloc("main_config", String, NULL);
- if (*node == NULL)
- goto error;
-
- if (scf_iter_pg_properties(iter, h->t_pg) == -1) {
- goto error;
- }
-
- while (scf_iter_next_property(iter, prop) > 0) {
- (void) scf_property_get_value(prop, value);
- (void) scf_value_get_as_string(value, valuebuf, max_value_len);
- (void) scf_property_get_name(prop, pname, max_name_len);
-
- /* avoid load auth to incore data */
- if (strcmp(pname, ISCSI_READ_AUTHNAME) == 0 ||
- strcmp(pname, ISCSI_MODIFY_AUTHNAME) == 0 ||
- strcmp(pname, ISCSI_VALUE_AUTHNAME) == 0)
- continue;
-
- n = tgt_node_alloc(pname, String, valuebuf);
- if (n == NULL)
- goto error;
-
- /* put version info into root node's attr */
- if (strcmp(pname, XML_ELEMENT_VERS) == 0) {
- tgt_node_add_attr(*node, n);
- } else {
- /* add other basic info into root node */
- tgt_node_add(*node, n);
- }
- }
-
- /*
- * targets/initiators/tpgt information is
- * stored as type "configuration" in scf
- * each target's param is stored as type "parameter"
- */
- if (scf_iter_service_pgs_typed(iter, h->t_service, "configuration")
- == -1) {
- goto error;
- }
-
- while (scf_iter_next_pg(iter, h->t_pg) > 0) {
- char *iname;
-
- (void) scf_pg_get_name(h->t_pg, pname, max_name_len);
- pgname_decode(pname);
- iname = strchr(pname, '_');
- if (iname == NULL) {
- /* the pg found here is not a tgt/initiator/tpgt */
- continue;
- }
- *iname = '\0';
- iname++;
- /*
- * now pname is "target" or "initiator" or "tpgt"
- * meanwhile iname is the actual name of the item
- */
-
- n = tgt_node_alloc(pname, String, iname);
- if (n == NULL)
- goto error;
-
- iter_v = scf_iter_create(h->t_handle);
- if (scf_iter_pg_properties(iter_v, h->t_pg) == -1) {
- goto error;
- }
- while (scf_iter_next_property(iter_v, prop) > 0) {
- /* there may be many values in one property */
- char *vname;
-
- (void) scf_property_get_name(prop, pname,
- max_name_len);
- /* avoid load auth to incore data */
- if (strcmp(pname, ISCSI_READ_AUTHNAME) == 0 ||
- strcmp(pname, ISCSI_MODIFY_AUTHNAME) == 0 ||
- strcmp(pname, ISCSI_VALUE_AUTHNAME) == 0)
- continue;
-
- vname = strstr(pname, "-list");
- if (vname == NULL) {
- (void) scf_property_get_value(prop, value);
- (void) scf_value_get_as_string(value, valuebuf,
- max_value_len);
-
- pn = tgt_node_alloc(pname, String, valuebuf);
- if (pn == NULL)
- goto error;
- tgt_node_add(n, pn);
- } else {
- pn = tgt_node_alloc(pname, String, NULL);
- if (pn == NULL)
- goto error;
- tgt_node_add(n, pn);
- *vname = '\0';
-
- iter_pv = scf_iter_create(h->t_handle);
- (void) scf_iter_property_values(iter_pv, prop);
- while (scf_iter_next_value(iter_pv, value)
- > 0) {
- (void) scf_value_get_as_string(
- value, valuebuf, max_value_len);
- /*
- * map 'acl' to 'initiator' since that
- * is what used inside the acl-list.
- */
- if (strcmp(pname, XML_ELEMENT_ACL)
- == 0) {
- vn = tgt_node_alloc(
- XML_ELEMENT_INIT,
- String, valuebuf);
- } else {
- vn = tgt_node_alloc(
- pname, String, valuebuf);
- }
- if (vn == NULL)
- goto error;
- tgt_node_add(pn, vn);
- }
- scf_iter_destroy(iter_pv);
- iter_pv = NULL;
- }
- }
- tgt_node_add(*node, n);
- scf_iter_destroy(iter_v);
- iter_v = NULL;
- }
-
- /* chap-secrets are stored in "passwords" pgroup as "application" */
- if (scf_service_get_pg(h->t_service, "passwords", h->t_pg) == 0) {
- if (scf_iter_pg_properties(iter, h->t_pg) == -1) {
- goto error;
- }
-
- while (scf_iter_next_property(iter, prop) > 0) {
- (void) scf_property_get_value(prop, value);
- (void) scf_value_get_as_string(value, valuebuf,
- max_value_len);
- (void) scf_property_get_name(prop, pname,
- max_name_len);
-
- /* avoid load auth to incore data */
- if (strcmp(pname, ISCSI_READ_AUTHNAME) == 0 ||
- strcmp(pname, ISCSI_MODIFY_AUTHNAME) == 0 ||
- strcmp(pname, ISCSI_VALUE_AUTHNAME) == 0)
- continue;
-
- /* max length of decoded passwd is 16B */
- (void) sasl_decode64(valuebuf, strlen(valuebuf),
- passcode, sizeof (passcode), &outlen);
-
- if (strcmp(pname, "radius") == 0) {
- pn = tgt_node_alloc(XML_ELEMENT_RAD_SECRET,
- String, passcode);
- tgt_node_add(*node, pn);
- } else if (strcmp(pname, "main") == 0) {
- pn = tgt_node_alloc(XML_ELEMENT_CHAPSECRET,
- String, passcode);
- tgt_node_add(*node, pn);
- } else {
- /* find corresponding initiator */
- n = NULL;
- while (n = tgt_node_next_child(*node,
- XML_ELEMENT_INIT, n)) {
- if (strcmp(pname + 2, n->x_value) != 0)
- continue;
- pn = tgt_node_alloc(
- XML_ELEMENT_CHAPSECRET,
- String, passcode);
- tgt_node_add(n, pn);
- }
- }
- }
- }
-
- status = True;
-error:
- if ((status != True) && (*node != NULL))
- tgt_node_free(*node);
- (void) pthread_mutex_unlock(&scf_conf_mutex);
- if (iter_pv != NULL)
- scf_iter_destroy(iter_pv);
- if (iter_v != NULL)
- scf_iter_destroy(iter_v);
-
- free(valuebuf);
- free(pname);
-
- scf_iter_destroy(iter);
- scf_value_destroy(value);
- scf_property_destroy(prop);
- mgmt_handle_fini(h);
- return (status);
-}
-
-static int
-isnumber(char *s)
-{
- register int c;
-
- if (!s || !(*s))
- return (0);
- while ((c = *(s++)) != '\0') {
- if (!isdigit(c))
- return (0);
- }
- return (1);
-}
-
-static void
-new_property(targ_scf_t *h,
- tgt_node_t *n)
-{
- scf_transaction_entry_t *e = NULL;
- scf_value_t *v = NULL;
- scf_type_t type;
-
- assert(n != NULL);
-
- e = scf_entry_create(h->t_handle);
- v = scf_value_create(h->t_handle);
-
- if (strcmp(n->x_value, "true") == 0 ||
- strcmp(n->x_value, "false") == 0) {
- type = SCF_TYPE_BOOLEAN;
- } else if (strcmp(n->x_name, "main") == 0 ||
- strcmp(n->x_name, "radius") == 0) {
- type = SCF_TYPE_ASTRING;
- } else if (strncmp(n->x_name, "I_", 2) == 0) {
- type = SCF_TYPE_ASTRING;
- } else if (strcmp(n->x_name, XML_ELEMENT_VERS) == 0) {
- type = SCF_TYPE_ASTRING;
- } else if (isnumber(n->x_value)) {
- type = SCF_TYPE_COUNT;
- } else {
- type = SCF_TYPE_ASTRING;
- }
- if ((scf_transaction_property_new(h->t_trans, e, n->x_name, type)
- == 0)) {
- (void) scf_value_set_from_string(v, type, n->x_value);
- (void) scf_entry_add_value(e, v);
- } else {
- scf_entry_destroy(e);
- scf_value_destroy(v);
- }
-}
-
-static void
-new_value_list(targ_scf_t *h,
- tgt_node_t *p)
-{
- scf_transaction_entry_t *e = NULL;
- scf_value_t *v = NULL;
- tgt_node_t *c;
- char *name;
-
- assert(p != NULL);
-
- name = p->x_name;
- e = scf_entry_create(h->t_handle);
- (void) scf_transaction_property_new(h->t_trans, e, name,
- SCF_TYPE_ASTRING);
-
- for (c = p->x_child; c; c = c->x_sibling) {
- v = scf_value_create(h->t_handle);
- (void) scf_value_set_astring(v, c->x_value);
- (void) scf_entry_add_value(e, v);
- }
-}
-
-/*
- * mgmt_config_save2scf() saves main configuration to scf
- * See also : mgmt_get_main_config()
- */
-Boolean_t
-mgmt_config_save2scf()
-{
- targ_scf_t *h = NULL;
- scf_property_t *prop = NULL;
- scf_value_t *value = NULL;
- scf_iter_t *iter = NULL;
- char *pgname = NULL;
- ssize_t max_name_len;
- char passcode[32];
- char *incore = NULL;
- unsigned int outlen;
- tgt_node_t *n = NULL;
- tgt_node_t *pn = NULL;
- tgt_node_t *tn = NULL;
- scf_transaction_t *tx = NULL;
- secret_list_t *sl_head;
- secret_list_t *sl_tail;
- Boolean_t status = False;
-
- h = mgmt_handle_init();
-
- if (h == NULL)
- return (status);
-
- prop = scf_property_create(h->t_handle);
- value = scf_value_create(h->t_handle);
- iter = scf_iter_create(h->t_handle);
-
- if (alloc_scf_name(&max_name_len, (void *)&pgname) == False) {
- goto error;
- }
-
- (void) pthread_mutex_lock(&scf_conf_mutex);
-
- if (mgmt_transaction_start(h, "iscsitgt", "basic") == True) {
- (void) scf_pg_delete(h->t_pg);
- (void) mgmt_transaction_end(h);
- }
-
- if (mgmt_transaction_start(h, "passwords", "application") == True) {
- (void) scf_pg_delete(h->t_pg);
- (void) mgmt_transaction_end(h);
- }
-
- if (scf_iter_service_pgs_typed(iter, h->t_service, "configuration")
- == -1) {
- goto error;
- }
-
- tx = scf_transaction_create(h->t_handle);
- while (scf_iter_next_pg(iter, h->t_pg) > 0) {
- (void) scf_transaction_start(tx, h->t_pg);
- (void) scf_pg_delete(h->t_pg);
- (void) scf_transaction_commit(tx);
- }
- scf_transaction_reset(tx);
- scf_transaction_destroy(tx);
-
- sl_head = (secret_list_t *)calloc(1, sizeof (secret_list_t));
- sl_tail = sl_head;
-
- if (mgmt_transaction_start(h, "iscsitgt", "basic") == True) {
- for (n = main_config->x_child; n; n = n->x_sibling) {
- if ((tgt_find_attr_str(n, XML_ELEMENT_INCORE, &incore))
- == True) {
- if (strcmp(incore, "true") == 0) {
- /*
- * Ignore in core only elements.
- * zvol target is the only one with
- * incore attr as of now.
- */
- free(incore);
- continue;
- }
- /* if incore is false continue on */
- free(incore);
- }
- if (strcmp(n->x_name,
- XML_ELEMENT_CHAPSECRET) == 0) {
- sl_tail->next = (secret_list_t *)
- calloc(1, sizeof (secret_list_t));
- sl_tail = sl_tail->next;
- sl_tail->name = strdup("main");
- sl_tail->secret = strdup(n->x_value);
- continue;
- }
- /* so does the radius server secret */
- if (strcmp(n->x_name,
- XML_ELEMENT_RAD_SECRET) == 0) {
- sl_tail->next = (secret_list_t *)
- calloc(1, sizeof (secret_list_t));
- sl_tail = sl_tail->next;
- sl_tail->name = strdup("radius");
- sl_tail->secret = strdup(n->x_value);
- continue;
- }
- if (n->x_child == NULL) {
- new_property(h, n);
- }
- }
- new_property(h, main_config->x_attr);
- n = tgt_node_alloc(ISCSI_MODIFY_AUTHNAME, String,
- ISCSI_AUTH_MODIFY);
- new_property(h, n);
- tgt_node_free(n);
- n = tgt_node_alloc(ISCSI_VALUE_AUTHNAME, String,
- ISCSI_AUTH_VALUE);
- new_property(h, n);
- tgt_node_free(n);
- (void) mgmt_transaction_end(h);
- }
-
- /* now update target/initiator/tpgt information */
- for (n = main_config->x_child; n; n = n->x_sibling) {
- if (n->x_child == NULL)
- continue;
-
- if ((tgt_find_attr_str(n, XML_ELEMENT_INCORE, &incore))
- == True) {
- if (strcmp(incore, "true") == 0) {
- /*
- * Ignore in core only elements.
- * zvol target is the only one with
- * incore attr as of now.
- */
- free(incore);
- continue;
- }
- /* if incore is false continue on */
- free(incore);
- }
-
- (void) snprintf(pgname, max_name_len, "%s_%s", n->x_name,
- n->x_value);
-
- if (mgmt_transaction_start(h, pgname, "configuration")
- == True) {
- for (pn = n->x_child; pn; pn = pn->x_sibling) {
- if (strcmp(pn->x_name,
- XML_ELEMENT_CHAPSECRET) == 0) {
- sl_tail->next = (secret_list_t *)
- calloc(1, sizeof (secret_list_t));
- sl_tail = sl_tail->next;
- sl_tail->name = (char *)
- calloc(1, strlen(n->x_value) + 3);
- (void) snprintf(sl_tail->name,
- strlen(n->x_value) + 3,
- "I_%s", n->x_value);
- sl_tail->secret = strdup(pn->x_value);
- continue;
- }
- if (pn->x_child == NULL) {
- /* normal property */
- new_property(h, pn);
- } else {
- /* pn -> xxx-list */
- new_value_list(h, pn);
- }
- tn = tgt_node_alloc(ISCSI_MODIFY_AUTHNAME,
- String, ISCSI_AUTH_MODIFY);
- new_property(h, tn);
- tgt_node_free(tn);
- tn = tgt_node_alloc(ISCSI_VALUE_AUTHNAME,
- String, ISCSI_AUTH_VALUE);
- new_property(h, tn);
- tgt_node_free(tn);
- }
- (void) mgmt_transaction_end(h);
- } else
- goto error;
- }
-
- if (mgmt_transaction_start(h, "passwords", "application") == True) {
- while (sl_head != NULL) {
- /* Here we use sl_tail as a temporari var */
- sl_tail = sl_head->next;
- if (sl_head->name) {
- /* max length of encoded passwd is 24B */
- (void) sasl_encode64(sl_head->secret,
- strlen(sl_head->secret), passcode,
- sizeof (passcode), &outlen);
-
- n = tgt_node_alloc(sl_head->name, String,
- passcode);
- new_property(h, n);
- tgt_node_free(n);
- }
- if (sl_head->name)
- free(sl_head->name);
- if (sl_head->secret)
- free(sl_head->secret);
- free(sl_head);
- sl_head = sl_tail;
- }
- n = tgt_node_alloc(ISCSI_READ_AUTHNAME, String,
- ISCSI_AUTH_READ);
- new_property(h, n);
- tgt_node_free(n);
- n = tgt_node_alloc(ISCSI_VALUE_AUTHNAME, String,
- ISCSI_AUTH_VALUE);
- new_property(h, n);
- tgt_node_free(n);
- n = tgt_node_alloc(ISCSI_MODIFY_AUTHNAME, String,
- ISCSI_AUTH_MODIFY);
- new_property(h, n);
- tgt_node_free(n);
- (void) mgmt_transaction_end(h);
- }
-
- if (smf_refresh_instance(SA_TARGET_SVC_INSTANCE_FMRI) != 0)
- goto error;
-
- status = True;
-error:
- (void) pthread_mutex_unlock(&scf_conf_mutex);
- free(pgname);
- scf_iter_destroy(iter);
- scf_value_destroy(value);
- scf_property_destroy(prop);
- mgmt_handle_fini(h);
- return (status);
-}
-
-Boolean_t
-mgmt_param_save2scf(tgt_node_t *node, char *target_name, int lun)
-{
- targ_scf_t *h = NULL;
- char *pgname = NULL;
- ssize_t max_name_len;
- tgt_node_t *n = NULL;
- Boolean_t status = False;
-
- h = mgmt_handle_init();
-
- if (h == NULL)
- return (status);
-
- if (alloc_scf_name(&max_name_len, (void *)&pgname) == False) {
- goto error;
- }
-
- (void) snprintf(pgname, max_name_len, "param_%s_%d", target_name,
- lun);
-
- (void) pthread_mutex_lock(&scf_param_mutex);
-
- if (mgmt_transaction_start(h, pgname, "parameter") == True) {
- (void) scf_pg_delete(h->t_pg);
- (void) mgmt_transaction_end(h);
- }
-
- if (mgmt_transaction_start(h, pgname, "parameter") == True) {
- for (n = node->x_child; n; n = n->x_sibling) {
- if (n->x_child == NULL) {
- /* now n is node of basic property */
- new_property(h, n);
- }
- }
- new_property(h, node->x_attr);
- n = tgt_node_alloc(ISCSI_VALUE_AUTHNAME, String,
- ISCSI_AUTH_VALUE);
- new_property(h, n);
- tgt_node_free(n);
- n = tgt_node_alloc(ISCSI_MODIFY_AUTHNAME, String,
- ISCSI_AUTH_MODIFY);
- new_property(h, n);
- tgt_node_free(n);
- (void) mgmt_transaction_end(h);
- }
-
- status = True;
-error:
- (void) pthread_mutex_unlock(&scf_param_mutex);
- free(pgname);
- mgmt_handle_fini(h);
- return (status);
-}
-
-/*
- * mgmt_get_param() get parameter of a specific LUN from scf
- * Args:
- * node - the node which parameters will be stored in mem
- * target_name - the local target name
- * lun - the LUN number
- * See also : mgmt_param_save2scf()
- */
-Boolean_t
-mgmt_get_param(tgt_node_t **node, char *target_name, int lun)
-{
- targ_scf_t *h = NULL;
- scf_property_t *prop = NULL;
- scf_value_t *value = NULL;
- scf_iter_t *iter = NULL;
- char *pname = NULL;
- char *expgname = NULL;
- char *pgname = NULL;
- char *valuebuf = NULL;
- ssize_t max_name_len;
- ssize_t expg_max_name_len;
- ssize_t max_value_len;
- tgt_node_t *n;
- Boolean_t status = False;
-
- /* Set NULL as default output value */
- *node = NULL;
- h = mgmt_handle_init();
-
- if (h == NULL)
- return (status);
-
- prop = scf_property_create(h->t_handle);
- value = scf_value_create(h->t_handle);
- iter = scf_iter_create(h->t_handle);
-
- if ((alloc_scf_name(&max_name_len, (void *)&pname) == NULL) ||
- (alloc_scf_name(&max_name_len, (void *)&pgname) == NULL) ||
- (alloc_scf_value(&max_value_len, (void *)&valuebuf) == NULL)) {
- goto error;
- }
-
- /*
- * Allocate memory for an "expanded" (or "decoded") Property Group
- * name.
- */
- expg_max_name_len = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) * PG_FACTOR
- + 1;
- if ((expgname = malloc(expg_max_name_len)) == NULL) {
- goto error;
- }
-
- (void) snprintf(pgname, max_name_len, "param_%s_%d", target_name,
- lun);
- pgname_encode(pgname, expgname, max_name_len);
-
- (void) pthread_mutex_lock(&scf_param_mutex);
-
- if (scf_service_get_pg(h->t_service, expgname, h->t_pg) == -1) {
- goto error;
- }
-
- *node = tgt_node_alloc(XML_ELEMENT_PARAMS, String, NULL);
- if (*node == NULL)
- goto error;
-
- if (scf_iter_pg_properties(iter, h->t_pg) == -1) {
- goto error;
- }
-
- while (scf_iter_next_property(iter, prop) > 0) {
- (void) scf_property_get_value(prop, value);
- (void) scf_value_get_as_string(value, valuebuf, max_value_len);
- (void) scf_property_get_name(prop, pname, max_name_len);
-
- /* avoid load auth to incore data */
- if (strcmp(pname, ISCSI_READ_AUTHNAME) == 0 ||
- strcmp(pname, ISCSI_MODIFY_AUTHNAME) == 0 ||
- strcmp(pname, ISCSI_VALUE_AUTHNAME) == 0)
- continue;
-
- n = tgt_node_alloc(pname, String, valuebuf);
- if (n == NULL)
- goto error;
-
- /* put version info into root node's attr */
- if (strcmp(pname, XML_ELEMENT_VERS) == 0) {
- tgt_node_add_attr(*node, n);
- } else {
- /* add other basic info into root node */
- tgt_node_add(*node, n);
- }
- }
-
- status = True;
-error:
- (void) pthread_mutex_unlock(&scf_param_mutex);
-
- free(valuebuf);
- free(expgname);
- free(pgname);
- free(pname);
-
- scf_iter_destroy(iter);
- scf_value_destroy(value);
- scf_property_destroy(prop);
- mgmt_handle_fini(h);
- return (status);
-}
-
-Boolean_t
-mgmt_param_remove(char *target_name, int lun)
-{
- targ_scf_t *h = NULL;
- char *pgname = NULL;
- ssize_t max_name_len;
- Boolean_t status = False;
-
- h = mgmt_handle_init();
- if (h == NULL)
- return (status);
-
- if (alloc_scf_name(&max_name_len, (void *)&pgname) == NULL) {
- goto error;
- }
-
- (void) snprintf(pgname, max_name_len, "param_%s_%d", target_name,
- lun);
-
- if (mgmt_transaction_start(h, pgname, "parameter") == True) {
- (void) scf_pg_delete(h->t_pg);
- (void) mgmt_transaction_end(h);
- status = True;
- }
-error:
- free(pgname);
- mgmt_handle_fini(h);
- return (status);
-}
-
-/*
- * mgmt_convert_param() converts legacy params file of each LUN
- * to scf data. It will convert LUNs under one target each time.
- * Args:
- * dir - string of directory where param file is stored
- * tnode - node tree which contains to a target
- */
-Boolean_t
-mgmt_convert_param(char *dir, tgt_node_t *tnode)
-{
- Boolean_t ret = False;
- char path[MAXPATHLEN];
- int xml_fd = -1;
- int n;
- int lun_num;
- tgt_node_t *lun = NULL;
- tgt_node_t *params = NULL;
- xmlTextReaderPtr r;
-
- while ((lun = tgt_node_next(tnode, XML_ELEMENT_LUN, lun)) != NULL) {
- if ((tgt_find_value_int(lun, XML_ELEMENT_LUN, &lun_num)) ==
- False)
- continue;
- (void) snprintf(path, sizeof (path), "%s/%s%d",
- dir, PARAMBASE, lun_num);
- if ((xml_fd = open(path, O_RDONLY)) < 0)
- continue;
- if ((r = (xmlTextReaderPtr)xmlReaderForFd(xml_fd,
- NULL, NULL, 0)) == NULL)
- continue;
-
- n = xmlTextReaderRead(r);
- while (n == 1) {
- if (tgt_node_process(r, &params) == False) {
- break;
- }
- n = xmlTextReaderRead(r);
- }
- if (n < 0) {
- ret = False;
- break;
- }
-
- if (mgmt_param_save2scf(params, tnode->x_value, lun_num)
- != True) {
- ret = False;
- break;
- } else {
- backup(path, tnode->x_value);
- ret = True;
- }
- params = NULL;
- (void) close(xml_fd);
- (void) xmlTextReaderClose(r);
- xmlFreeTextReader(r);
- }
-
- if (ret == False)
- syslog(LOG_ERR, "Converting target %s params failed", dir);
- return (ret);
-}
-
-/*
- * Convert legacy (XML) configuration files into an equivalent SCF
- * representation.
- *
- * Read the XML from disk, translate the XML into a tree of nodes of
- * type tgt_node_t, and write the in-memory tree to SCF's persistent
- * data-store using mgmt_config_save2scf().
- *
- * Return Values:
- * CONVERT_OK: successfully converted
- * CONVERT_INIT_NEW: configuration files don't exist; created an SCF entry
- * CONVERT_FAIL: some conversion error occurred; no SCF entry created.
- * In this case, user has to manually check files and try
- * conversion again.
- */
-convert_ret_t
-mgmt_convert_conf()
-{
- targ_scf_t *h = NULL;
- xmlTextReaderPtr r;
- convert_ret_t ret = CONVERT_FAIL;
- int xml_fd = -1;
- int n;
- tgt_node_t *node = NULL;
- tgt_node_t *next = NULL;
- char path[MAXPATHLEN];
- char *target = NULL;
-
- h = mgmt_handle_init();
- if (h == NULL)
- return (CONVERT_FAIL);
-
- /*
- * Check if the "iscsitgt" PropertyGroup has already been added
- * to the "iscsitgt" SMF Service. If so, then we have already
- * converted the legacy configuration files (and there is no work
- * to do).
- */
- if (scf_service_get_pg(h->t_service, "iscsitgt", h->t_pg) == 0) {
- ret = CONVERT_OK;
- goto done;
- }
-
- if (access(config_file, R_OK) != 0) {
- /*
- * then the Main Config file is not present; initialize
- * SCF Properties to default values.
- */
- if (mgmt_transaction_start(h, "iscsitgt", "basic") == True) {
- ret = CONVERT_INIT_NEW;
-
- node = tgt_node_alloc(XML_ELEMENT_VERS, String, "1.0");
- new_property(h, node);
- tgt_node_free(node);
- /* "daemonize" is set to true by default */
- node = tgt_node_alloc(XML_ELEMENT_DBGDAEMON, String,
- "true");
- new_property(h, node);
- tgt_node_free(node);
- node = NULL;
- node = tgt_node_alloc(ISCSI_MODIFY_AUTHNAME, String,
- ISCSI_AUTH_MODIFY);
- new_property(h, node);
- tgt_node_free(node);
- node = tgt_node_alloc(ISCSI_VALUE_AUTHNAME, String,
- ISCSI_AUTH_VALUE);
- new_property(h, node);
- tgt_node_free(node);
- (void) mgmt_transaction_end(h);
- } else {
- syslog(LOG_ERR, "Creating empty entry failed");
- ret = CONVERT_FAIL;
- goto done;
- }
- if (mgmt_transaction_start(h, "passwords", "application") ==
- True) {
- node = tgt_node_alloc(ISCSI_READ_AUTHNAME, String,
- ISCSI_AUTH_READ);
- new_property(h, node);
- tgt_node_free(node);
- node = tgt_node_alloc(ISCSI_MODIFY_AUTHNAME, String,
- ISCSI_AUTH_MODIFY);
- new_property(h, node);
- tgt_node_free(node);
- node = tgt_node_alloc(ISCSI_VALUE_AUTHNAME, String,
- ISCSI_AUTH_VALUE);
- new_property(h, node);
- tgt_node_free(node);
- (void) mgmt_transaction_end(h);
- } else {
- syslog(LOG_ERR, "Creating empty entry failed");
- ret = CONVERT_FAIL;
- }
- goto done;
- }
-
- if ((xml_fd = open(config_file, O_RDONLY)) >= 0)
- r = (xmlTextReaderPtr)xmlReaderForFd(xml_fd, NULL, NULL, 0);
-
- if (r != NULL) {
- int is_target_config;
-
- n = xmlTextReaderRead(r);
- while (n == 1) {
- if (tgt_node_process(r, &node) == False) {
- break;
- }
- n = xmlTextReaderRead(r);
- }
- if (n < 0) {
- syslog(LOG_ERR, "Parsing main config failed");
- ret = CONVERT_FAIL;
- goto done;
- }
-
- main_config = node;
-
- /*
- * Initialize the Base Directory (global) variable by
- * using the value specified in the XML_ELEMENT_BASEDIR
- * XML tag. If a tag is not specified, use a default.
- */
- (void) tgt_find_value_str(node, XML_ELEMENT_BASEDIR,
- &target_basedir);
-
- if (target_basedir == NULL)
- target_basedir = strdup(DEFAULT_TARGET_BASEDIR);
-
- if (xml_fd != -1) {
- (void) close(xml_fd);
- xml_fd = -1;
- }
- (void) xmlTextReaderClose(r);
- xmlFreeTextReader(r);
- xmlCleanupParser();
-
- /*
- * If a Target Config file is present, read and translate
- * its XML representation into a tree of tgt_node_t.
- * Merge that tree with the tree of tgt_node_t rooted at
- * 'main_config'. The merged tree will then be archived
- * using an SCF representation.
- */
- (void) snprintf(path, MAXPATHLEN, "%s/%s",
- target_basedir, "config.xml");
-
- if ((xml_fd = open(path, O_RDONLY)) >= 0) {
- is_target_config = 1;
- r = (xmlTextReaderPtr)xmlReaderForFd(xml_fd,
- NULL, NULL, 0);
- } else {
- is_target_config = 0;
- r = NULL;
- }
-
- if (r != NULL) {
- /* then the Target Config file is available. */
-
- node = NULL;
-
- /*
- * Create a tree of tgt_node_t rooted at 'node' by
- * processing each XML Tag in the file.
- */
- n = xmlTextReaderRead(r);
- while (n == 1) {
- if (tgt_node_process(r, &node) == False) {
- break;
- }
- n = xmlTextReaderRead(r);
- }
- if (n < 0) {
- syslog(LOG_ERR, "Parsing target conf failed");
- ret = CONVERT_FAIL;
- goto done;
- }
-
- /*
- * Merge the tree at 'node' into the tree rooted at
- * 'main_config'.
- */
- if (node != NULL) {
- next = NULL;
- while ((next = tgt_node_next(node,
- XML_ELEMENT_TARG, next)) != NULL) {
- tgt_node_add(main_config,
- tgt_node_dup(next));
- }
- tgt_node_free(node);
- }
- }
-
- /*
- * Iterate over the in-memory tree rooted at 'main_config'
- * and write a representation of the appropriate nodes to
- * SCF's persistent data-store.
- */
- if (mgmt_config_save2scf() != True) {
- syslog(LOG_ERR, "Converting config failed");
- if (xml_fd != -1) {
- (void) close(xml_fd);
- xml_fd = -1;
- }
- (void) xmlTextReaderClose(r);
- xmlFreeTextReader(r);
- xmlCleanupParser();
- ret = CONVERT_FAIL;
- goto done;
- }
-
- /*
- * Move the configuration files into a well-known backup
- * directory. This allows a user to restore their
- * configuration, if they choose.
- */
- (void) snprintf(path, sizeof (path), "%s/backup",
- target_basedir);
- if ((mkdir(path, 0755) == -1) && (errno != EEXIST)) {
- syslog(LOG_ERR, "Creating backup dir failed");
- ret = CONVERT_FAIL;
- goto done;
- }
- /* Save the Main Config file. */
- backup(config_file, NULL);
-
- /* Save the Target Config file, if it was present. */
- if (is_target_config != 0) {
- (void) snprintf(path, MAXPATHLEN, "%s/%s",
- target_basedir, "config.xml");
- backup(path, NULL);
- }
-
- /*
- * For each tgt_node_t node in 'main_config' whose value is
- * an iSCSI Name as defined in the RFC (3720) standard (eg,
- * "iqn.1986..."), read its XML-encoded attributes from a
- * flat-file and write an equivalent representation to SCF's
- * data-store.
- */
- while ((next = tgt_node_next(main_config,
- XML_ELEMENT_TARG, next)) != NULL) {
- if (tgt_find_value_str(next, XML_ELEMENT_INAME,
- &target) == False) {
- continue;
- }
- (void) snprintf(path, MAXPATHLEN, "%s/%s",
- target_basedir, target);
- if (mgmt_convert_param(path, next)
- != True) {
- ret = CONVERT_FAIL;
- goto done;
- }
- free(target);
- }
-
- ret = CONVERT_OK;
- syslog(LOG_NOTICE, "Conversion succeeded");
-
- (void) xmlTextReaderClose(r);
- xmlFreeTextReader(r);
- xmlCleanupParser();
- } else {
- syslog(LOG_ERR, "Reading main config failed");
- ret = CONVERT_FAIL;
- goto done;
- }
-
-done:
- if (xml_fd != -1)
- (void) close(xml_fd);
- mgmt_handle_fini(h);
- return (ret);
-}
-
-/*
- * backup() moves configuration xml files into backup directory
- * under base-directory. It is called once when converting legacy
- * xml data into scf data.
- * Param files will be renamed as params.<lun#>.<initiatorname>
- */
-static void
-backup(char *file, char *ext)
-{
- char dest[MAXPATHLEN];
- char *bname;
-
- bname = basename(file);
- if (ext) {
- (void) snprintf(dest, sizeof (dest), "%s/backup/%s.%s",
- target_basedir, bname, ext);
- } else {
- (void) snprintf(dest, sizeof (dest), "%s/backup/%s",
- target_basedir, bname);
- }
-
- if (fork() == 0) {
- (void) execl("/bin/mv", "mv", file, dest, (char *)0);
- exit(0);
- }
-}
-
-/*
- * check_auth() checks if a given cred has
- * the authorization to create/remove targets/initiators/tpgt
- * cred is from the door call.
- */
-Boolean_t
-check_auth_addremove(ucred_t *cred)
-{
- targ_scf_t *h = NULL;
- Boolean_t ret = False;
- int exit_code = 1;
- uid_t uid;
- gid_t gid;
- pid_t pid;
- const priv_set_t *eset;
-
- pid = fork();
-
- switch (pid) {
- case 0:
- /* Child process to check authorization */
- uid = ucred_geteuid(cred);
- if (seteuid(uid) != 0) {
- syslog(LOG_ERR, "not priviliged\n");
- exit(-1);
- }
-
- gid = ucred_getegid(cred);
- if (setegid(gid) != 0) {
- syslog(LOG_ERR, "not priviliged\n");
- exit(-1);
- }
-
- eset = ucred_getprivset(cred, PRIV_EFFECTIVE);
- (void) setppriv(PRIV_ON, PRIV_EFFECTIVE, eset);
-
- h = mgmt_handle_init();
-
- if (h == NULL) {
- exit(1);
- }
- if (mgmt_transaction_start(h, "dummy", "dummy") == True) {
- (void) scf_pg_delete(h->t_pg);
- (void) mgmt_transaction_end(h);
- exit_code = 0;
- } else {
- exit_code = 1;
- }
- mgmt_handle_fini(h);
- exit(exit_code);
- break;
- case -1:
- /* Fail to fork */
- exit(SMF_EXIT_ERR_CONFIG);
- default:
- (void) wait(&exit_code);
- exit_code = exit_code >> 8;
- if (exit_code == 0)
- ret = True;
- else
- ret = False;
- break;
- }
-
- return (ret);
-}
-/*
- * check_auth_modify() checks if a given cred has
- * the authorization to add/change/remove configuration values.
- * cred is from the door call.
- */
-Boolean_t
-check_auth_modify(ucred_t *cred)
-{
- targ_scf_t *h = NULL;
- Boolean_t ret = False;
- int exit_code = -1;
- uid_t uid;
- gid_t gid;
- pid_t pid;
- tgt_node_t *n = NULL;
- scf_transaction_entry_t *ent = NULL;
- const priv_set_t *eset;
-
- pid = fork();
-
- switch (pid) {
- case 0:
- /* Child process to check authorization */
- uid = ucred_geteuid(cred);
- if (seteuid(uid) != 0) {
- syslog(LOG_ERR, "not priviliged\n");
- exit(-1);
- }
-
- gid = ucred_getegid(cred);
- if (setegid(gid) != 0) {
- syslog(LOG_ERR, "not priviliged\n");
- exit(-1);
- }
-
- eset = ucred_getprivset(cred, PRIV_EFFECTIVE);
- (void) setppriv(PRIV_ON, PRIV_EFFECTIVE, eset);
-
- h = mgmt_handle_init();
-
- if (h == NULL) {
- exit(-1);
- }
- if (mgmt_transaction_start(h, "iscsitgt", "basic") == True) {
- n = tgt_node_alloc("dummy", String, "dummy");
- new_property(h, n);
- tgt_node_free(n);
- if (mgmt_transaction_end(h) == True) {
- exit_code = 0;
- } else {
- exit_code = -1;
- }
- } else {
- exit_code = -1;
- }
- if (exit_code != 0) {
- mgmt_handle_fini(h);
- exit(exit_code);
- }
- if (mgmt_transaction_start(h, "iscsitgt", "basic") == True) {
- ent = scf_entry_create(h->t_handle);
- if (ent) {
- (void) scf_transaction_property_delete(
- h->t_trans, ent, "dummy");
- }
- }
- (void) mgmt_transaction_end(h);
-
- mgmt_handle_fini(h);
- exit(exit_code);
- break;
- case -1:
- /* Fail to fork */
- exit(SMF_EXIT_ERR_CONFIG);
- default:
- (void) wait(&exit_code);
- exit_code = exit_code >> 8;
- if (exit_code == 0)
- ret = True;
- else
- ret = False;
- break;
- }
-
- return (ret);
-}
-
-/*
- * Following two functions replace ':' and '.' in target/initiator
- * names into '__2' and '__1' when write to SMF, and do a reverse
- * replacement when read from SMF.
- * pgname_encode's buffers are allocated by caller.
- * see CR 6626684
- */
-#define SMF_COLON "__2"
-#define SMF_DOT "__1"
-
-static void
-pgname_encode(char *instr, char *outstr, int max_len)
-{
- int i = 0;
-
- assert(instr != NULL && outstr != NULL);
- for (; *instr != '\0'; instr++) {
- switch (*instr) {
- case ':':
- (void) strcpy(outstr + i, SMF_COLON);
- i += 3;
- break;
- case '.':
- (void) strcpy(outstr + i, SMF_DOT);
- i += 3;
- break;
- default:
- *(outstr + i) = *instr;
- i ++;
- break;
- }
- /* in case of next possible ':' or '.', we cease on len-3 */
- if (i >= max_len - 3)
- break;
- }
- outstr[i] = '\0';
-}
-
-/*
- * pgname_decode use original buffer, since it reduces string length
- */
-static void
-pgname_decode(char *instr)
-{
- char *buf;
- char *rec;
-
- assert(instr != NULL);
- buf = strdup(instr);
-
- if (buf == NULL)
- return;
-
- rec = buf;
- for (; *buf != '\0'; buf++) {
- if (*buf == '_') {
- if (memcmp(buf, SMF_COLON, strlen(SMF_COLON)) == 0) {
- *instr = ':';
- buf += 2;
- } else if (memcmp(buf, SMF_DOT, strlen(SMF_DOT)) == 0) {
- *instr = '.';
- buf += 2;
- } else {
- *instr = *buf;
- }
- } else {
- *instr = *buf;
- }
- instr ++;
- }
- *instr = '\0';
- free(rec);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/mgmt_scf.h b/usr/src/cmd/iscsi/iscsitgtd/mgmt_scf.h
deleted file mode 100644
index 4dc93fd8ef..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_scf.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _MGMT_SCF_H
-#define _MGMT_SCF_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef _cplusplus
-extern "C" {
-#endif
-
-#include <libscf.h>
-#include <iscsitgt_impl.h>
-#include <ucred.h>
-
-#define SA_TARGET_SVC_NAME "system/iscsitgt"
-#define SA_TARGET_SVC_INSTANCE_FMRI "svc:/system/iscsitgt:default"
-
-#define ISCSI_READ_AUTHNAME "read_authorization"
-#define ISCSI_MODIFY_AUTHNAME "modify_authorization"
-#define ISCSI_VALUE_AUTHNAME "value_authorization"
-
-#define ISCSI_AUTH_READ "solaris.smf.read.iscsitgt"
-#define ISCSI_AUTH_MANAGE "solaris.smf.manage.iscsitgt"
-#define ISCSI_AUTH_MODIFY "solaris.smf.modify.iscsitgt"
-#define ISCSI_AUTH_VALUE "solaris.smf.value.iscsitgt"
-
-typedef enum {
- CONVERT_OK = 0,
- CONVERT_INIT_NEW,
- CONVERT_FAIL
-} convert_ret_t;
-
-typedef struct {
- scf_handle_t *t_handle;
- scf_scope_t *t_scope;
- scf_service_t *t_service;
- scf_propertygroup_t *t_pg;
- scf_instance_t *t_instance;
- scf_transaction_t *t_trans;
-} targ_scf_t;
-
-typedef struct secret_list {
- char *name;
- char *secret;
- struct secret_list *next;
-} secret_list_t;
-
-Boolean_t mgmt_scf_init();
-void mgmt_scf_fini();
-
-targ_scf_t *mgmt_handle_init(void);
-Boolean_t mgmt_transaction_start(targ_scf_t *h, char *pg, char *prop);
-Boolean_t mgmt_transaction_end(targ_scf_t *h);
-void mgmt_transaction_abort(targ_scf_t *h);
-
-Boolean_t mgmt_get_main_config(tgt_node_t **node);
-Boolean_t mgmt_config_save2scf();
-
-Boolean_t mgmt_param_save2scf(tgt_node_t *node, char *target_name, int lun);
-Boolean_t mgmt_get_param(tgt_node_t **node, char *target_name, int lun);
-Boolean_t mgmt_param_remove(char *target_name, int lun);
-convert_ret_t mgmt_convert_conf();
-
-Boolean_t check_auth_modify(ucred_t *cred);
-Boolean_t check_auth_addremove(ucred_t *cred);
-
-int get_zfs_shareiscsi(char *, tgt_node_t **, uint64_t *, ucred_t *);
-int put_zfs_shareiscsi(char *, tgt_node_t *);
-#define ZFS_PROP_SIZE (2 * 1024)
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _MGMT_SCF_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/port.h b/usr/src/cmd/iscsi/iscsitgtd/port.h
deleted file mode 100644
index e1cc377fee..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/port.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef PORT_H
-#define PORT_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "iscsi_conn.h"
-
-typedef struct port_args {
- target_queue_t *port_mgmtq, /* management queue */
- *port_dataq; /* incoming data for thread */
- int port_num, /* port number to monitor */
- port_socket;
-} port_args_t;
-
-void port_init();
-void *port_watcher(void *v);
-void *port_management(void *v);
-void port_conn_remove(iscsi_conn_t *c);
-
-extern iscsi_conn_t *conn_head;
-
-#endif /* PORT_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/queue.h b/usr/src/cmd/iscsi/iscsitgtd/queue.h
deleted file mode 100644
index df5576a06e..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/queue.h
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _TARGET_QUEUE_H
-#define _TARGET_QUEUE_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <pthread.h>
-#include <sys/time.h>
-#include <stdarg.h>
-#include <synch.h>
-#include <door.h>
-
-#include <iscsitgt_impl.h>
-
-/* Connections */
-#define Q_CONN_ERRS 0x00000001
-#define Q_CONN_LOGIN 0x00000002
-#define Q_CONN_NONIO 0x00000004
-#define Q_CONN_IO 0x00000008
-
-/* Sessions */
-#define Q_SESS_ERRS 0x00000010
-#define Q_SESS_LOGIN 0x00000020
-#define Q_SESS_NONIO 0x00000040
-#define Q_SESS_IO 0x00000080
-
-/* SCSI Target Emulation */
-#define Q_STE_ERRS 0x00000100
-#define Q_STE_NONIO 0x00000200
-#define Q_STE_IO 0x00000400
-
-/* General Errors */
-#define Q_GEN_ERRS 0x00001000
-#define Q_GEN_DETAILS 0x00002000
-
-/* ISCSI Debugging */
-#define Q_ISNS_DBG 0x00004000
-
-/* Persistent Reservations */
-#define Q_PR_ERRS 0x00010000
-#define Q_PR_NONIO 0x00020000
-#define Q_PR_IO 0x00040000
-
-/*
- * When used the queue request will be place at the head of the queue.
- */
-#define Q_HIGH 0x80000000
-
-extern int qlog_lvl;
-
-typedef enum {
- /*
- * []----------------------------------------------------------------
- * | Messages internal to the SAM-3 portion. When the transport calls
- * | the SAM-3 interfaces messages are enqueued to the LU. The LU
- * | thread then dequeues these messages and calls the appropriate
- * | function for the emulator.
- */
-
- /* ---- from transport ---- */
- msg_cmd_send,
- msg_cmd_data_out,
-
- /* ---- from emulation ---- */
- msg_cmd_data_in,
- msg_cmd_data_rqst,
- msg_cmd_cmplt,
-
- /* ---- Internal SAM-3 messages ---- */
- msg_lu_add,
- msg_lu_remove,
- msg_lu_online,
- msg_lu_aio_done,
-
- /*
- * | End of SAM-3 messages
- * []----------------------------------------------------------------
- */
-
- msg_reset_lu,
- msg_reset_targ,
- msg_targ_inventory_change,
- msg_lu_capacity_change,
-
- /*
- * The ConnectionReader will send packet ready messages when
- * data is available. If the socket has an error or is closed
- * a conn_lost message will be sent. Packet ready will have the
- * number of bytes currently available on the connection. Don't
- * free.
- */
- msg_conn_lost,
- msg_packet_ready,
-
- /*
- * Shutdowns happen from the bottom up. The replies are in place
- * so that threads can wait for the top end to disappear, at least
- * they must no longer reference any common structures such as
- * message queues.
- */
- msg_drain_complete,
- msg_shutdown,
- msg_shutdown_rsp,
-
- /*
- * Here's a special error condition for STE. When using mmap
- * to access the backing store of a LUN which is larger than
- * the underlying storage it's possible to run out of room
- * on the device (no duh). When that happens the OS will send
- * the daemon a SIGSBUS. The STE thread catches that signal,
- * sends a UNIT ATTENTION to the other side, and closes down
- * the STE thread in a special manner. The transport layer
- * can then restart another STE thread with the same queues
- * which mean outstanding I/O restarts.
- */
- msg_ste_media_error,
-
- /*
- * A NopIn request could be sent on the connection receive thread
- * except for one little issue. Since both the receive and transmit
- * threads could be issuing packets and data to the socket at the
- * same time we must protect those writes so that all of the data
- * for a single PDU (hdr, checksum, data, checksum) go out together.
- * It's possible for the socket to receive so much incoming data
- * that writes will be blocked until some of that data has been
- * read. If the transmit grabs the lock, attempts to write, and is
- * blocked we find a condition where the receiver is also blocked
- * processing a nop command because it can't get the lock. So, instead
- * we build up the packet and queue it.
- *
- * This will also occur with Task Management Requests.
- */
- msg_send_pkt,
-
- /*
- * During login when the TargetName name/value pair is processed
- * the value will be sent to STE through the session layer.
- * STE can use the information however it sees fit.
- * The InitiatorName will also be sent which STE can use to
- * validate login properties.
- */
- msg_target_name,
- msg_initiator_name,
- msg_initiator_alias,
-
- /*
- * Issued when causing full allocation of backing store.
- * This is an internal message used by t10_sam.c
- */
- msg_thick_provo,
-
- /*
- * ---------------- Debug/Management type messages ----------------
- */
- /*
- * When a thread shutdowns someone must call pthread_join else
- * the thread will remain in a zombie state taking up some
- * amount of memory.
- */
- msg_pthread_join,
-
- /*
- * Requests from and replys to the management host will be done using
- * these messages.
- */
- msg_mgmt_rqst,
- msg_mgmt_rply,
-
- /*
- * General debug messages.
- */
- msg_log,
-
- /*
- * Problem message by some of the auxiliary threads indication
- * problems.
- */
- msg_status,
-
- msg_wait_for_destroy
-
-} msg_type_t;
-
-typedef struct msg {
- struct msg *msg_next,
- *msg_prev;
- struct msg *msg_all_next;
-
- msg_type_t msg_type;
- void *msg_data;
-
- /*
- * This can be used either to insert a message higher into the queue
- * or as debug level flags.
- */
- uint32_t msg_pri_level;
-} msg_t;
-
-typedef struct target_queue {
- msg_t *q_head,
- *q_tail;
- pthread_mutex_t q_mutex;
- sema_t q_sema;
- int q_num;
-} target_queue_t;
-
-typedef enum mgmt_type {
- mgmt_full_phase_statistics,
- mgmt_discovery_statistics,
- mgmt_lun_information,
- mgmt_parse_xml,
- mgmt_logout
-} mgmt_type_t;
-
-typedef struct mgmt_request {
- target_queue_t *m_q;
- mgmt_type_t m_request;
- time_t m_time;
- char *m_targ_name;
- ucred_t *m_cred;
-
- /*
- * This mutex protects the m_buf pointer from multiple connections
- * attempting to update the response at the same time. One management
- * request structure is sent to possible multiple connections when
- * gathering statistics. The connections/sessions will lock access
- * to the buffer.
- */
- pthread_mutex_t m_resp_mutex;
- union {
- char **m_resp;
- tgt_node_t *m_node;
- } m_u;
-} mgmt_request_t;
-
-typedef struct name_request {
- target_queue_t *nr_q;
- char *nr_name;
-} name_request_t;
-
-void queue_init();
-target_queue_t *queue_alloc();
-void queue_message_set(target_queue_t *, uint32_t lvl, msg_type_t, void *);
-msg_t *queue_message_get(target_queue_t *);
-msg_t *queue_message_try_get(target_queue_t *q);
-void queue_message_free(msg_t *);
-void queue_walker_free(target_queue_t *q,
- Boolean_t (*func)(msg_t *, void *v), void *v1);
-void queue_free(target_queue_t *, void (*free_func)(msg_t *));
-void queue_reset(target_queue_t *q);
-void queue_prt(target_queue_t *q, int type, char *fmt, ...);
-void queue_str(target_queue_t *, uint32_t lvl, msg_type_t, char *);
-void queue_log(Boolean_t on_off);
-void ste_queue_data_remove(msg_t *m);
-void conn_queue_data_remove(msg_t *m);
-void sess_queue_data_remove(msg_t *m);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _TARGET_QUEUE_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/radius.c b/usr/src/cmd/iscsi/iscsitgtd/radius.c
deleted file mode 100644
index a6432ae451..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/radius.c
+++ /dev/null
@@ -1,514 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <sys/random.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
-#include <strings.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-#include <netinet/in.h>
-#include <sys/socket.h>
-
-#include <md5.h>
-#include "target.h"
-#include "radius.h"
-
-/* Forward declaration */
-
-/*
- * Encode a CHAP-Password attribute. This function basically prepends
- * the identifier in front of chap_passwd and copy the results to
- * *result.
- */
-static
-void
-encode_chap_password(int identifier,
- int chap_passwd_len,
- uint8_t *chap_passwd,
- uint8_t *result);
-
-int
-snd_radius_request(int sd,
- iscsi_ipaddr_t rsvr_ip_addr,
- uint32_t rsvr_port,
- radius_packet_data_t *req_data);
-
-int
-rcv_radius_response(int sd,
- uint8_t *shared_secret,
- uint32_t shared_secret_len,
- uint8_t *req_authenticator,
- radius_packet_data_t *resp_data);
-
-/*
- * Annotate the radius_attr_t objects with authentication data.
- */
-static
-void
-set_radius_attrs(radius_packet_data_t *req,
- char *target_chap_name,
- unsigned char *target_response,
- uint32_t responseLength,
- uint8_t *challenge,
-uint32_t challengeLength);
-
-/*
- * See radius_auth.h.
- */
-/* ARGSUSED */
-chap_validation_status_type
-radius_chap_validate(char *target_chap_name,
- char *initiator_chap_name,
- uint8_t *challenge,
- uint32_t challengeLength,
- uint8_t *target_response,
- uint32_t responseLength,
- uint8_t identifier,
- iscsi_ipaddr_t rad_svr_ip_addr,
- uint32_t rad_svr_port,
- uint8_t *rad_svr_shared_secret,
- uint32_t rad_svr_shared_secret_len)
-{
- chap_validation_status_type validation_status;
- int rcv_status;
- int sd;
- int rc;
- struct sockaddr_in sockaddr;
- radius_packet_data_t req;
- radius_packet_data_t resp;
- MD5_CTX context;
- uint8_t md5_digest[16]; /* MD5 digest length 16 */
- uint8_t random_number[16];
- int fd;
-
- if (rad_svr_shared_secret_len == 0) {
- /* The secret must not be empty (section 3, RFC 2865) */
- return (CHAP_VALIDATION_BAD_RADIUS_SECRET);
- }
-
- bzero(&req, sizeof (radius_packet_data_t));
-
- req.identifier = identifier;
- req.code = RAD_ACCESS_REQ;
- set_radius_attrs(&req,
- target_chap_name,
- target_response,
- responseLength,
- challenge,
- challengeLength);
-
- /* Prepare the request authenticator */
- MD5Init(&context);
- bzero(&md5_digest, 16);
- /* First, the shared secret */
- MD5Update(&context, rad_svr_shared_secret, rad_svr_shared_secret_len);
- /* Then a unique number - use a random number */
- fd = open("/dev/random", O_RDONLY);
- if (fd == -1)
- return (CHAP_VALIDATION_INTERNAL_ERROR);
- (void) read(fd, &random_number, sizeof (random_number));
- (void) close(fd);
- MD5Update(&context, random_number, sizeof (random_number));
- MD5Final(md5_digest, &context);
- bcopy(md5_digest, &req.authenticator, RAD_AUTHENTICATOR_LEN);
-
- /* Create UDP socket */
- sd = socket(AF_INET, SOCK_DGRAM, 0);
- if (sd < 0) {
- return (CHAP_VALIDATION_RADIUS_ACCESS_ERROR);
- }
- sockaddr.sin_family = AF_INET;
- sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- sockaddr.sin_port = htons(0);
- rc = bind(sd, (struct sockaddr *)&sockaddr, sizeof (sockaddr));
- if (rc < 0) {
- return (CHAP_VALIDATION_RADIUS_ACCESS_ERROR);
- }
-
- /* Send the authentication access request to the RADIUS server */
- if (snd_radius_request(sd,
- rad_svr_ip_addr,
- rad_svr_port,
- &req) == -1) {
- (void) close(sd);
- return (CHAP_VALIDATION_RADIUS_ACCESS_ERROR);
- }
-
- bzero(&resp, sizeof (radius_packet_data_t));
- /* Analyze the response coming through from the same socket. */
- rcv_status = rcv_radius_response(sd,
- rad_svr_shared_secret,
- rad_svr_shared_secret_len,
- req.authenticator, &resp);
- if (rcv_status == RAD_RSP_RCVD_SUCCESS) {
- if (resp.code == RAD_ACCESS_ACPT) {
- validation_status = CHAP_VALIDATION_PASSED;
- } else if (resp.code == RAD_ACCESS_REJ) {
- validation_status = CHAP_VALIDATION_INVALID_RESPONSE;
- } else {
- validation_status =
- CHAP_VALIDATION_UNKNOWN_RADIUS_CODE;
- }
- } else if (rcv_status == RAD_RSP_RCVD_AUTH_FAILED) {
- validation_status = CHAP_VALIDATION_BAD_RADIUS_SECRET;
- } else {
- validation_status = CHAP_VALIDATION_RADIUS_ACCESS_ERROR;
- }
-
- (void) close(sd);
- return (validation_status);
-}
-
-/* See forward declaration. */
-static void
-set_radius_attrs(radius_packet_data_t *req,
- char *target_chap_name,
- unsigned char *target_response,
- uint32_t responseLength,
- uint8_t *challenge,
- uint32_t challengeLength)
-{
- req->attrs[0].attr_type_code = RAD_USER_NAME;
- (void) strncpy((char *)req->attrs[0].attr_value,
- (const char *)target_chap_name,
- strlen(target_chap_name));
- req->attrs[0].attr_value_len = strlen(target_chap_name);
-
- req->attrs[1].attr_type_code = RAD_CHAP_PASSWORD;
- bcopy(target_response,
- (char *)req->attrs[1].attr_value,
- min(responseLength, sizeof (req->attrs[1].attr_value)));
- /* A target response is an MD5 hash thus its length has to be 16. */
- req->attrs[1].attr_value_len = responseLength;
-
- req->attrs[2].attr_type_code = RAD_CHAP_CHALLENGE;
- bcopy(challenge,
- (char *)req->attrs[2].attr_value,
- min(challengeLength, sizeof (req->attrs[2].attr_value)));
- req->attrs[2].attr_value_len = challengeLength;
-
- /* 3 attributes associated with each RADIUS packet. */
- req->num_of_attrs = 3;
-}
-
-/*
- * See radius_packet.h.
- */
-int
-snd_radius_request(int sd,
- iscsi_ipaddr_t rsvr_ip_addr,
- uint32_t rsvr_port,
- radius_packet_data_t *req_data)
-{
- int i; /* Loop counter. */
- int data_len;
- int len;
- ushort_t total_length; /* Has to be 2 octets in size */
- uint8_t *ptr; /* Pointer to RADIUS packet data */
- uint8_t *length_ptr; /* Points to the Length field of the */
- /* packet. */
- uint8_t *data; /* RADIUS data to be sent */
- radius_attr_t *req_attr; /* Request attributes */
- radius_packet_t *packet; /* Outbound RADIUS packet */
- union {
- struct sockaddr_in s_in4;
- struct sockaddr_in6 s_in6;
- } sa_rsvr; /* Socket address of the server */
-
- /*
- * Create a RADIUS packet with minimal length for now.
- */
- total_length = MIN_RAD_PACKET_LEN;
- data = (uint8_t *)malloc(MAX_RAD_PACKET_LEN);
- packet = (radius_packet_t *)data;
- packet->code = req_data->code;
- packet->identifier = req_data->identifier;
- bcopy(req_data->authenticator, packet->authenticator,
- RAD_AUTHENTICATOR_LEN);
- ptr = packet->data;
-
- /* Loop over all attributes of the request. */
- for (i = 0; i < req_data->num_of_attrs; i++) {
- if (total_length > MAX_RAD_PACKET_LEN) {
- /* The packet has exceed its maximum size. */
- free(data);
- return (-1);
- }
-
- req_attr = &req_data->attrs[i];
- *ptr++ = (req_attr->attr_type_code & 0xFF);
- length_ptr = ptr;
- /* Length is 2 octets - RFC 2865 section 3 */
- *ptr++ = 2;
- total_length += 2;
-
- /* If the attribute is CHAP-Password, encode it. */
- if (req_attr->attr_type_code == RAD_CHAP_PASSWORD) {
- /*
- * Identifier plus CHAP response. RFC 2865
- * section 5.3.
- */
- uint8_t encoded_chap_passwd[RAD_CHAP_PASSWD_STR_LEN +
- RAD_IDENTIFIER_LEN +
- 1];
- encode_chap_password
- (req_data->identifier,
- req_attr->attr_value_len,
- req_attr->attr_value,
- encoded_chap_passwd);
-
- req_attr->attr_value_len = RAD_CHAP_PASSWD_STR_LEN +
- RAD_IDENTIFIER_LEN;
-
- bcopy(encoded_chap_passwd,
- req_attr->attr_value,
- req_attr->attr_value_len);
- }
-
- len = req_attr->attr_value_len;
- *length_ptr += len;
-
- bcopy(req_attr->attr_value, ptr, req_attr->attr_value_len);
- ptr += req_attr->attr_value_len;
-
- total_length += len;
- } /* Done looping over all attributes */
-
- data_len = total_length;
- total_length = htons(total_length);
- bcopy(&total_length, packet->length, sizeof (ushort_t));
-
- /*
- * Send the packet to the RADIUS server.
- */
- bzero((char *)&sa_rsvr, sizeof (sa_rsvr));
- if (rsvr_ip_addr.i_insize == sizeof (in_addr_t)) {
- int ret;
-
- /* IPv4 */
- sa_rsvr.s_in4.sin_family = AF_INET;
- sa_rsvr.s_in4.sin_addr.s_addr =
- rsvr_ip_addr.i_addr.in4.s_addr;
- /*
- * sin_port is of type u_short (or ushort_t - POSIX compliant).
- */
- sa_rsvr.s_in4.sin_port = htons((ushort_t)rsvr_port);
-
- ret = sendto(sd, data, data_len, 0,
- (struct sockaddr *)&sa_rsvr.s_in4,
- sizeof (struct sockaddr_in));
- free(data);
- return (ret);
- } else if (rsvr_ip_addr.i_insize == sizeof (in6_addr_t)) {
- /* IPv6 */
- sa_rsvr.s_in6.sin6_family = AF_INET6;
- bcopy(sa_rsvr.s_in6.sin6_addr.s6_addr,
- rsvr_ip_addr.i_addr.in6.s6_addr, 16);
- /*
- * sin6_port is of type in_port_t (i.e., uint16_t).
- */
- sa_rsvr.s_in6.sin6_port = htons((in_port_t)rsvr_port);
-
- free(data);
- /* No IPv6 support for now. */
- return (-1);
- } else {
- /* Invalid IP address for RADIUS server. */
- free(data);
- return (-1);
- }
-}
-
-/*
- * See radius_packet.h.
- */
-int
-rcv_radius_response(int sd,
- uint8_t *shared_secret,
- uint32_t shared_secret_len,
- uint8_t *req_authenticator,
- radius_packet_data_t *resp_data)
-{
- int poll_cnt = 0;
- int rcv_len = 0;
- radius_packet_t *packet;
- MD5_CTX context;
- uint8_t *tmp_data;
- uint8_t md5_digest[16]; /* MD5 Digest Length 16 */
- uint16_t declared_len = 0;
- ushort_t len;
-
- fd_set fdset;
- struct timeval timeout;
-
- tmp_data = (uint8_t *)malloc(MAX_RAD_PACKET_LEN);
-
- /*
- * Poll and receive RADIUS packet.
- */
- poll_cnt = 0;
- do {
- timeout.tv_sec = RAD_RCV_TIMEOUT;
- timeout.tv_usec = 0;
-
- FD_ZERO(&fdset);
- FD_SET(sd, &fdset);
-
- if (select(sd+1, &fdset, NULL, NULL, &timeout) < 0) {
- free(tmp_data);
- return (RAD_RSP_RCVD_PROTOCOL_ERR);
- }
-
- if (FD_ISSET(sd, &fdset)) {
- rcv_len = recv(sd, tmp_data, MAX_RAD_PACKET_LEN, 0);
- break;
- } else {
- poll_cnt++;
- }
-
- } while (poll_cnt < RAD_RETRY_MAX);
-
- if (poll_cnt >= RAD_RETRY_MAX) {
- free(tmp_data);
- return (RAD_RSP_RCVD_TIMEOUT);
- }
-
- if (rcv_len < 0) {
- /* Socket error. */
- free(tmp_data);
- return (RAD_RSP_RCVD_PROTOCOL_ERR);
- }
-
- packet = (radius_packet_t *)tmp_data;
- bcopy(packet->length, &len, sizeof (ushort_t));
- declared_len = ntohs(len);
-
- /*
- * Check if the received packet length is within allowable range.
- * RFC 2865 section 3.
- */
- if (rcv_len < MIN_RAD_PACKET_LEN) {
- free(tmp_data);
- return (RAD_RSP_RCVD_PROTOCOL_ERR);
- } else if (rcv_len > MAX_RAD_PACKET_LEN) {
- free(tmp_data);
- return (RAD_RSP_RCVD_PROTOCOL_ERR);
- }
-
- /*
- * Check if the declared packet length is within allowable range.
- * RFC 2865 section 3.
- */
- if (declared_len < MIN_RAD_PACKET_LEN) {
- free(tmp_data);
- return (RAD_RSP_RCVD_PROTOCOL_ERR);
- } else if (declared_len > MAX_RAD_PACKET_LEN) {
- free(tmp_data);
- return (RAD_RSP_RCVD_PROTOCOL_ERR);
- }
-
- /*
- * Discard packet with received length shorter than declared
- * length. RFC 2865 section 3.
- */
- if (rcv_len < declared_len) {
- free(tmp_data);
- return (RAD_RSP_RCVD_PROTOCOL_ERR);
- }
-
- /*
- * Authenticate the incoming packet, using the following algorithm
- * (RFC 2865 section 3):
- *
- * MD5(Code+ID+Length+RequestAuth+Attributes+Secret)
- *
- * Code = RADIUS packet code
- * ID = RADIUS packet identifier
- * Length = Declared length of the packet
- * RequestAuth = The request authenticator
- * Attributes = The response attributes
- * Secret = The shared secret
- */
- MD5Init(&context);
- bzero(&md5_digest, 16);
- MD5Update(&context, &packet->code, 1);
- MD5Update(&context, &packet->identifier, 1);
- MD5Update(&context, packet->length, 2);
- MD5Update(&context, req_authenticator, RAD_AUTHENTICATOR_LEN);
- /* Include response attributes only if there is a payload */
- if (declared_len > RAD_PACKET_HDR_LEN) {
- /* Response Attributes */
- MD5Update(&context, packet->data,
- declared_len - RAD_PACKET_HDR_LEN);
- }
- MD5Update(&context, shared_secret, shared_secret_len);
- MD5Final(md5_digest, &context);
-
- if (bcmp(md5_digest, packet->authenticator, RAD_AUTHENTICATOR_LEN)
- != 0) {
- free(tmp_data);
- return (RAD_RSP_RCVD_AUTH_FAILED);
- }
-
- /*
- * If the received length is greater than the declared length,
- * trust the declared length and shorten the packet (i.e., to
- * treat the octets outside the range of the Length field as
- * padding - RFC 2865 section 3).
- */
- if (rcv_len > declared_len) {
- /* Clear the padding data. */
- bzero(tmp_data + declared_len, rcv_len - declared_len);
- rcv_len = declared_len;
- }
-
- /*
- * Annotate the RADIUS packet data with the data we received from
- * the server.
- */
- resp_data->code = packet->code;
- resp_data->identifier = packet->identifier;
-
- free(tmp_data);
- return (RAD_RSP_RCVD_SUCCESS);
-}
-
-static
-void
-encode_chap_password(int identifier,
- int chap_passwd_len,
- uint8_t *chap_passwd,
- uint8_t *result)
-{
- result[0] = (uint8_t)identifier;
- bcopy(chap_passwd, &result[1], chap_passwd_len);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/radius.h b/usr/src/cmd/iscsi/iscsitgtd/radius.h
deleted file mode 100644
index fdb9684475..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/radius.h
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _RADIUS_H
-#define _RADIUS_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <netinet/in.h>
-#include <sys/int_types.h>
-
-/* Packet type. RFC 2865 section 4. */
-#define RAD_ACCESS_REQ 1 /* Authentication Request */
-#define RAD_ACCESS_ACPT 2 /* Authentication Accepted */
-#define RAD_ACCESS_REJ 3 /* Authentication Rejected */
-
-/* RADIUS Attribute Types. RFC 2865 section 5. */
-#define RAD_USER_NAME 1
-#define RAD_CHAP_PASSWORD 3
-#define RAD_CHAP_CHALLENGE 60
-
-/* RFC 2865 Section 3. The Identifier field is one octet. */
-#define RAD_IDENTIFIER_LEN 1
-
-/* RFC 2865 Section 5.3. The String field is 16 octets. */
-#define RAD_CHAP_PASSWD_STR_LEN 16
-
-/* RFC 2865 Section 3. Authenticator field is 16 octets. */
-#define RAD_AUTHENTICATOR_LEN 16
-
-/* RFC 2865 Section 5: 1-253 octets */
-#define MAX_RAD_ATTR_VALUE_LEN 253
-
-/* RFC 2865 Section 3. Minimum length 20 octets. */
-#define MIN_RAD_PACKET_LEN 20
-
-/* RFC 2865 Section 3. Maximum length 4096 octets. */
-#define MAX_RAD_PACKET_LEN 4096
-
-/* Maximum RADIUS shared secret length (in fact there is no defined limit) */
-#define MAX_RAD_SHARED_SECRET_LEN 128
-
-/* RFC 2865 Section 3. Minimum RADIUS shared secret length */
-#define MIN_RAD_SHARED_SECRET_LEN 16
-
-/* Raw RADIUS packet. RFC 2865 section 3. */
-typedef struct radius_packet {
- uint8_t code; /* RADIUS code, section 3, RFC 2865 */
- uint8_t identifier; /* 1 octet in length. RFC 2865 section 3 */
- uint8_t length[2]; /* 2 octets, or sizeof (u_short) */
- uint8_t authenticator[RAD_AUTHENTICATOR_LEN];
- uint8_t data[1];
-} radius_packet_t;
-
-/* Length of a RADIUS packet minus the payload */
-#define RAD_PACKET_HDR_LEN 20
-
-
-typedef enum chap_validation_status_type {
- CHAP_VALIDATION_PASSED, /* CHAP validation passed */
- CHAP_VALIDATION_INVALID_RESPONSE, /* Invalid CHAP response */
- CHAP_VALIDATION_DUP_SECRET, /* Same CHAP secret used */
- /* for authentication in the */
- /* other direction */
- CHAP_VALIDATION_UNKNOWN_AUTH_METHOD, /* Unknown authentication */
- /* method */
- CHAP_VALIDATION_INTERNAL_ERROR, /* MISC internal error */
- CHAP_VALIDATION_RADIUS_ACCESS_ERROR, /* Problem accessing RADIUS */
- CHAP_VALIDATION_BAD_RADIUS_SECRET, /* Invalid RADIUS shared */
- /* secret */
- CHAP_VALIDATION_UNKNOWN_RADIUS_CODE /* Irrelevant or unknown */
- /* RADIUS packet code */
- /* returned */
-} chap_validation_status_type;
-
-typedef enum authentication_method_type {
- RADIUS_AUTHENTICATION,
- DIRECT_AUTHENTICATION
-} authentication_method_type;
-
-typedef struct _IPAddress {
- union {
- struct in_addr in4;
- struct in6_addr in6;
- } i_addr;
- /* i_insize determines which is valid in the union above */
- int i_insize;
-} iscsi_ipaddr_t;
-
-typedef struct radius_config {
- iscsi_ipaddr_t rad_svr_addr; /* IPv6 enabled */
- uint32_t rad_svr_port;
- uint8_t rad_svr_shared_secret[MAX_RAD_SHARED_SECRET_LEN];
- uint32_t rad_svr_shared_secret_len;
-} RADIUS_CONFIG;
-
-/* A total of RAD_RCV_TIMEOUT * RAD_RETRY_MAX seconds timeout. */
-#define RAD_RCV_TIMEOUT 5 /* Timeout for receiving RADIUS packet in */
- /* sec. */
-#define RAD_RETRY_MAX 2 /* Max. # of times to retry receiving */
- /* packet. */
-
-/* Describes a RADIUS attribute */
-typedef struct radius_attr {
- int attr_type_code; /* RADIUS attribute type code, */
- /* e.g. RAD_USER_PASSWORD, etc. */
- int attr_value_len;
- uint8_t attr_value[MAX_RAD_ATTR_VALUE_LEN];
-} radius_attr_t;
-
-/* Describes data fields of a RADIUS packet. */
-typedef struct radius_packet_data {
- uint8_t code; /* RADIUS code, section 3, RFC 2865. */
- uint8_t identifier;
- uint8_t authenticator[RAD_AUTHENTICATOR_LEN];
- int num_of_attrs;
- radius_attr_t attrs[4]; /* For this implementation each */
- /* outbound RADIUS packet will only */
- /* have 3 attributes associated with */
- /* it thus the chosen size should be */
- /* good enough. */
-} radius_packet_data_t;
-
-/*
- * Data in this structure is set by the user agent and consumed by
- * the driver.
- */
-#define MAX_RAD_SHARED_SECRET_LEN 128
-typedef struct radius_props {
- uint32_t r_vers;
- uint32_t r_oid;
- union {
- struct in_addr u_in4;
- struct in6_addr u_in6;
- } r_addr;
- /*
- * r_insize indicates which of the previous structs is valid.
- */
- int r_insize;
-
- uint32_t r_port;
- uint8_t r_shared_secret[MAX_RAD_SHARED_SECRET_LEN];
- boolean_t r_radius_access;
- boolean_t r_radius_config_valid;
- uint32_t r_shared_secret_len;
-} iscsi_radius_props_t;
-
-/*
- * Send a request to a RADIUS server.
- *
- * Returns > 0 on success, <= 0 on failure .
- *
- */
-int
-snd_radius_request(int sd,
- iscsi_ipaddr_t rsvr_ip_addr,
- uint32_t rsvr_port,
- radius_packet_data_t *packet_data);
-
-#define RAD_RSP_RCVD_SUCCESS 0
-#define RAD_RSP_RCVD_NO_DATA 1
-#define RAD_RSP_RCVD_TIMEOUT 2
-#define RAD_RSP_RCVD_PROTOCOL_ERR 3
-#define RAD_RSP_RCVD_AUTH_FAILED 4
-/*
- * Receives a response from a RADIUS server.
- *
- * Return receive status.
- */
-int
-rcv_radius_response(int sd,
- uint8_t *shared_secret,
- uint32_t shared_secret_len,
- uint8_t *req_authenticator,
- radius_packet_data_t *resp_data);
-
-/*
- * Function: radius_chap_validate
- *
- * Description: To validate a target response given the
- * associated challenge via the specified
- * RADIUS server.
- *
- * Arguments:
- * target_chap_name - The CHAP name of the target being authenticated.
- * initiator_chap_name - The CHAP name of the authenticating initiator.
- * challenge - The CHAP challenge to which the target responded.
- * target_response - The target's CHAP response to be validated.
- * identifier - The identifier associated with the CHAP challenge.
- * radius_server_ip_address - The IP address of the RADIUS server.
- * radius_server_port - The port number of the RADIUS server.
- * radius_shared_secret - The shared secret for accessing the RADIUS server.
- * radius_shared_secret_len - The length of the shared secret.
- *
- * Return: See chap_validation_status_type.
- */
-chap_validation_status_type
-radius_chap_validate(char *target_chap_name,
- char *initiator_chap_name,
- uint8_t *challenge,
- uint32_t challengeLength,
- uint8_t *target_response,
- uint32_t responseLength,
- uint8_t identifier,
- iscsi_ipaddr_t rad_svr_ip_addr,
- uint32_t rad_svr_port,
- uint8_t *rad_svr_shared_secret,
- uint32_t rad_svr_shared_secret_len);
-
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _RADIUS_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/sparcv9/Makefile b/usr/src/cmd/iscsi/iscsitgtd/sparcv9/Makefile
deleted file mode 100644
index 69b08dbca6..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/sparcv9/Makefile
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-#ident "%Z%%M% %I% %E% SMI"
-#
-# cmd/iscsi/iscsitgt/sparcv9/Makefile
-
-include ../Makefile.com
-include ../../../Makefile.cmd.64
-
-install: all $(ROOTUSRSBINPROG64)
diff --git a/usr/src/cmd/iscsi/iscsitgtd/svc-iscsitgt b/usr/src/cmd/iscsi/iscsitgtd/svc-iscsitgt
deleted file mode 100644
index 21829d18e0..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/svc-iscsitgt
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/sbin/sh
-#
-# 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 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-. /lib/svc/share/smf_include.sh
-
-case "$1" in
-'start')
- if smf_is_nonglobalzone; then
- /usr/sbin/svcadm disable -t svc:/system/iscsitgt
- echo "The iSCSI target is not supported in a local zone"
- sleep 5 &
- exit $SMF_EXIT_OK
- fi
-
- /usr/sbin/iscsitgtd
-
- if [ $? -ne 0 ]; then
- echo "Failed to start iSCSI daemon"
- exit 1
- fi
-
- if [ -x /usr/sbin/zfs ]; then
- /usr/sbin/zfs share -a iscsi
- fi
-
- ;;
-
-'stop')
- # Kill any processes in the service contract
- smf_kill_contract $2 TERM
- [ $? -ne 0 ] && exit 1
- ;;
-
-*)
- echo "Usage: $0 { start | stop }"
- exit 1
- ;;
-esac
-
-exit $SMF_EXIT_OK
diff --git a/usr/src/cmd/iscsi/iscsitgtd/t10.h b/usr/src/cmd/iscsi/iscsitgtd/t10.h
deleted file mode 100644
index ad0732a5a6..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/t10.h
+++ /dev/null
@@ -1,663 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _T10_H
-#define _T10_H
-
-/*
- * This header file describes the service level between the transport
- * layer and the emulation portion. These procedure calls can be thought
- * of as part of the T10 SAM-3 specification.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Here are the header files which are required to define references found
- * in this file. No other header files are to be included.
- */
-#include <pthread.h>
-#include <sys/avl.h>
-#include <signal.h>
-#include <sys/scsi/generic/sense.h>
-
-#include "queue.h"
-
-#ifdef lint
-/*
- * lints sees aio_return64, but can't find it in the aio structure. To keep
- * lint happy this define is used.
- */
-#define aio_return64 aio_return
-#endif
-
-typedef void *transport_t;
-typedef void *t10_targ_handle_t;
-
-typedef void *t10_lun_handle_t;
-
-typedef void *emul_handle_t;
-typedef void *emul_cmd_t;
-
-typedef enum {
- ClearSet,
- ResetTarget,
- ResetLun,
- InventoryChange,
- CapacityChange,
- DeviceOnline,
- DeviceOffline
-} TaskOp_t;
-
-/*
- * For an explanation of the t10_cmd_state_t and t10_cmd_event_t
- * see t10_sam.c:t10_cmd_state_machine()
- */
-typedef enum {
- T10_Cmd_S1_Free = 1,
- T10_Cmd_S2_In,
- T10_Cmd_S3_Trans,
- T10_Cmd_S4_AIO,
- T10_Cmd_S5_Wait,
- T10_Cmd_S6_Freeing_In,
- T10_Cmd_S7_Freeing_AIO
-} t10_cmd_state_t;
-
-typedef enum {
- T10_Cmd_T1 = 1,
- T10_Cmd_T2,
- T10_Cmd_T3,
- T10_Cmd_T4,
- T10_Cmd_T5,
- T10_Cmd_T6, /* cancel */
- T10_Cmd_T7,
- T10_Cmd_T8 /* shutdown */
-} t10_cmd_event_t;
-
-typedef enum {
- lu_online,
- lu_offline,
- lu_errored
-} t10_lu_state_t;
-
-/*
- * The t10_cmd_t structure bridges the gap between the transport and
- * emulation services. At certain times either the transport or emulation
- * service needs to access the data stored within this structure.
- * For now we'll just use macros which hide the reference, but in the
- * future when the transport and emulation services are loadable modules
- * these macros will become functions so that the structure can change
- * inside of the T10 space and not cause compatibility issues.
- */
-#define T10_MAX_OUT(cmd) (cmd->c_lu->l_targ->s_maxout)
-#define T10_MMAP_AREA(cmd) (cmd->c_lu->l_common->l_mmap)
-#define T10_PARAMS_AREA(cmd) trans_params_area(cmd)
-#define T10_TRANS_ID(cmd) (cmd->c_trans_id)
-#define T10_DATA(cmd) (cmd->c_data)
-#define T10_DATA_LEN(cmd) (cmd->c_data_len)
-#define T10_DATA_OFFSET(cmd) (cmd->c_offset)
-#define T10_CMD_LAST(cmd) (cmd->c_last)
-#define T10_CMD_STATUS(cmd) (cmd->c_cmd_status)
-#define T10_CMD_RESID(cmd) (cmd->c_resid)
-#define T10_SENSE_LEN(cmd) (cmd->c_cmd_sense_len)
-#define T10_SENSE_DATA(cmd) (cmd->c_cmd_sense)
-#define T10_PGR_TNAME(cmd) (cmd->c_lu->l_targ->s_targ_base)
-#define T10_PGR_INAME(cmd) (cmd->c_lu->l_targ->s_i_name)
-
-#define T10_DEFAULT_TPG 1
-
-/*
- * []------------------------------------------------------------------[]
- * | SAM-3 revision 14, section 4.9 -- Logical Unit Numbers |
- * | The specification allows for 64-bit LUNs, but at this point |
- * | most OSes don't support that many. Section 4.9.7, table 9 gives |
- * | the Flat Space Addressing Method which allows for 16,383 LUNs. |
- * | This will be the imposed maximum even though the code can support |
- * | more. Raise this number if needed. |
- * []------------------------------------------------------------------[]
- */
-#define T10_MAX_LUNS 16383
-
-/*
- * SPC-3 Revision 21c, Section 6.4.2 Table 85
- * Version Descriptor Values
- */
-#define T10_TRANS_ISCSI 0x960 /* iSCSI (no version claimed) */
-#define T10_TRANS_FC 0x8c0 /* FCP (no version claimed) */
-
-typedef struct t10_aio {
- /*
- * This must be the first member of the structure. aioread/aiowrite
- * take as one of the arguments an pointer to a aio_result_t
- * structure. When the operation is complete the aio_return and
- * aio_errno of that structure are updated. When aiowait() is
- * called the address of that aio_result_t is returned. By having
- * this structure at the beginning we can pass in the data_ptr
- * structure address. The ste_aio_process thread will get everything
- * it needs from the aiowait to send a message to the correct
- * STE thread. Clear as mud?
- */
- aio_result_t a_aio;
-
- void (*a_aio_cmplt)(emul_cmd_t id);
- emul_cmd_t a_id;
- struct t10_cmd *a_cmd;
-} t10_aio_t;
-
-/*
- * Bidirectional structure used to track requests from the transport
- * and send reponse data from the emulation.
- *
- * The glue logic for t10_send_cmd will allocate this structure, fill in
- * in with the provided data and put it on the LUN queue. The LUN thread
- * will dequeue this request and call the appropriate LUN command interpreter.
- */
-typedef struct t10_cmd {
- /*
- * Transport specific tracking value. If this value is non-zero it
- * means this command was part of a previous command that wasn't
- * completed. Currently this is only used for DATA_OUT (SCSI write op)
- * commands.
- */
- transport_t c_trans_id;
-
- t10_cmd_state_t c_state;
-
- /*
- * Emulation specific tracking value.
- */
- emul_cmd_t c_emul_id;
-
- /*
- * Per I_T_L structure used to determine which command
- * interpreter to call and which transport queue to send the response.
- */
- struct t10_lu_impl *c_lu;
-
- /*
- * Pointer to command buffer. No interpretation of data is
- * done by the glue logic. Interpretation is done by the LUN
- * emulation code.
- */
- uint8_t *c_cdb;
- size_t c_cdb_len;
-
- /*
- * Optional offset into the command. If more than one response
- * is required this value indicates where the data belongs.
- */
- off_t c_offset;
-
- /*
- * Data for transfer.
- */
- char *c_data;
- size_t c_data_len;
- size_t c_resid;
-
- /*
- * Indicates if this response is the last to be sent
- * and will be followed closely by a complete message. Enables
- * transports to phase collapse the final READ data PDU with
- * completion PDU if possible.
- */
- Boolean_t c_last;
-
- /*
- * When the transport is finished sending the data it will
- * call t10_cmd_destroy() which will cause the SAM-3 layer to
- * call the emulation function stored here with this command
- * pointer. The emulation code is responsible for freeing any
- * memory it allocated.
- */
- void (*c_emul_complete)(emul_handle_t id);
-
- /*
- * During transitions from T10 layer to transport one of three
- * messages are sent. The state machine needs access to these
- * values to pass things along so we keep it here.
- */
- msg_type_t c_msg;
-
- /*
- * SCSI sense information.
- */
- int c_cmd_status;
- char *c_cmd_sense;
- size_t c_cmd_sense_len;
-
- /*
- * List of active commands at the ITL level.
- */
- avl_tree_t c_cmd_avl;
-
- struct t10_cmd *c_cmd_next;
-} t10_cmd_t;
-
-/*
- * Each LU has a structure which contains common data for all I_T's who
- * access this LU.
- */
-typedef struct t10_lu_common {
- /*
- * Logic Unit Number
- */
- int l_num;
-
- /*
- * state of device
- */
- t10_lu_state_t l_state;
-
- /*
- * Internal ID which will be unique for all LUs. This will be
- * used for log messages to help tracking details.
- */
- int l_internal_num;
-
- /*
- * Thread ID which is running this logical unit. This is currently
- * used for only one purpose which is to locate this structure
- * in case of a SIGBUS. It's possible for the underlying file system
- * to run out of space for an mmap'd LU. The only means of notification
- * the OS has is to send a SIGBUS. The thread only receives the memory
- * address, so we look for our thread ID amongst all of the LU
- * available.
- */
- pthread_t l_thr_id;
-
- /*
- * If we receive a SIGBUS the initiator needs to be notified that
- * something bad has occurred. This means we need to know which
- * command was being emulated so that we can find the appropriate
- * transport.
- * Special handling needs to be done if the thread is initializing
- * the LU so we need a flag to indicate that fact.
- */
- t10_cmd_t *l_curr;
- Boolean_t l_curr_provo;
-
- /*
- * The implementation uses a 16 byte EUI value for the GUID.
- * Not only is this value used for SCSI INQUIRY data, but it
- * is used to distinquish this common LUN from other LUNs in
- * the AVL tree.
- */
- uint8_t *l_guid;
- size_t l_guid_len;
-
- /*
- * Other common information which is needed for ever device
- * type.
- */
- int l_dtype;
- char *l_pid,
- *l_vid;
-
- /*
- * Each dtype has different parameters that it uses. This
- * is a place holder for storing a pointer to some structure which
- * contains that information.
- */
- void *l_dtype_params;
-
- /*
- * Parameter information in XML format.
- */
- tgt_node_t *l_root;
- Boolean_t l_root_okay_to_free;
-
- /*
- * File descriptor for the open file which is the backing store
- * for this device. This can be a regular file or a character
- * special device if we're acting as a bridge between transports.
- */
- int l_fd;
-
- void *l_mmap;
- off64_t l_size;
-
- Boolean_t l_fast_write_ack;
-
- /*
- * AVL tree containing all I_T_L nexus' which are actively using
- * this LUN.
- */
- avl_tree_t l_all_open;
-
- /*
- * Each I_T will place requests for command emulation on this
- * queue. Common requests are msg_ste_cmd and msg_ste_shutdown
- */
- target_queue_t *l_from_transports;
-
- /*
- * Mutex used to lock access to the AVL tree.
- */
- pthread_mutex_t l_common_mutex;
-
- /*
- * When a target is looking to see if an existing LUN is opened
- * a search of all LUNs needs to be done and will use this
- * AVL node. This field is modified only by the AVL code.
- */
- avl_node_t l_all_luns;
-} t10_lu_common_t;
-
-/*
- * Each I_T_L has a LU structure associated with it.
- */
-typedef struct t10_lu_impl {
- /*
- * pointer to common area of LUN.
- */
- t10_lu_common_t *l_common;
- pthread_mutex_t l_mutex;
-
- /*
- * Mutex to protect access to active commands
- */
- pthread_mutex_t l_cmd_mutex;
- pthread_cond_t l_cmd_cond;
- Boolean_t l_wait_for_drain;
-
- avl_tree_t l_cmds;
-
- /*
- * Queue for sending command results and R2T results back
- * to the transport.
- */
- target_queue_t *l_to_transport;
-
- /*
- * Back pointer to target structure who created this LUN reference.
- */
- struct t10_targ_impl *l_targ;
-
- struct scsi_cmd_table *l_cmd_table;
-
- /*
- * Per LU methods for issuing commands and data to the
- * DTYPE emulator.
- */
- void (*l_cmd)(t10_cmd_t *cmd, uint8_t *cdb,
- size_t cdb_len);
- void (*l_data)(t10_cmd_t *cmd, emul_handle_t e,
- size_t offset, char *data, size_t data_len);
-
- /*
- * AVL node information for all other I_T nexus' who are referencing
- * this LUN. This is used by the AVL code and *not* modified by
- * this daemon directly.
- */
- avl_node_t l_open_lu_node;
-
- /*
- * AVL node information for all LUN's being access by this I_T nexus.
- * This is used by the AVL code and *not* modified by this daemon
- * directly.
- */
- avl_node_t l_open_targ_node;
-
- /*
- * Logical Unit Number. This value is used as the comparision value
- * for the AVL search at the per target level.
- */
- int l_targ_lun;
-
- Boolean_t l_dsense_enabled;
- Boolean_t l_pgr_read;
-
- /*
- * Statistics on a per ITL basis
- */
- uint64_t l_cmds_read,
- l_cmds_write,
- l_sects_read,
- l_sects_write;
-
- /*
- * Each time a command is run the value of l_status is checked.
- * If non-zero the command isn't executed and instead a transport
- * complete message is sent with these values. This is commonly
- * used to send UNIT ATTENTION for things like power on.
- * -- Do we need some sort of stack to push and pop these values?
- */
- int l_status,
- l_asc,
- l_ascq;
-} t10_lu_impl_t;
-
-typedef struct t10_targ_impl {
- char *s_i_name;
- char *s_targ_base;
- int s_targ_num; /* used in log messages */
- avl_tree_t s_open_lu;
- pthread_mutex_t s_mutex;
-
- /*
- * The transport layer will set the maximum output size
- * it's able to deal with during a call to set_create_handle()
- */
- size_t s_maxout;
-
- /*
- * Target Port Set
- */
- int s_tpgt;
-
- /*
- * transport version number to use in standard inquiry data
- */
- int s_trans_vers;
-
- /*
- * Transport response queue. This queue will be stored in each
- * lun that gets created.
- */
- target_queue_t *s_to_transport;
-
- /*
- * During a SCSI WRITE the emulation will call trans_rqst_datain.
- * If the transport indicated data was available by using non-zero
- * values for the optional data and length when t10_send_cmd was
- * called this callback is used when the emulation requests data.
- */
- void (*s_dataout_cb)(t10_cmd_t *, char *data,
- size_t *data_len);
-
-} t10_targ_impl_t;
-
-typedef struct t10_shutdown {
- t10_lu_impl_t *t_lu;
- target_queue_t *t_q;
-} t10_shutdown_t;
-
-typedef struct scsi_cmd_table {
- void (*cmd_start)(struct t10_cmd *, uint8_t *, size_t);
- void (*cmd_data)(struct t10_cmd *, emul_handle_t e,
- size_t offset, char *data, size_t data_len);
- void (*cmd_end)(emul_handle_t e);
- char *cmd_name;
-} scsi_cmd_table_t;
-
-typedef struct sam_device_table {
- Boolean_t (*t_common_init)(t10_lu_common_t *);
- void (*t_common_fini)(t10_lu_common_t *);
- void (*t_per_init)(t10_lu_impl_t *);
- void (*t_per_fini)(t10_lu_impl_t *);
- void (*t_task_mgmt)(t10_lu_common_t *, TaskOp_t);
- char *t_type_name;
-} sam_device_table_t;
-
-typedef struct t10_conn_shutdown {
- target_queue_t *t10_to_conn_q;
- target_queue_t *conn_to_t10_q;
-} t10_conn_shutdown_t;
-
-/*
- * []----
- * | Interfaces
- * []----
- */
-
-extern target_queue_t *mgmtq;
-void t10_init(target_queue_t *q);
-void lu_buserr_handler(int sig, siginfo_t *sip, void *v);
-
-/*
- * []------------------------------------------------------------------[]
- * | Methods called by the transports |
- * []------------------------------------------------------------------[]
- */
-/*
- * t10_handle_create -- create target handle to be used by transports
- */
-t10_targ_handle_t
-t10_handle_create(char *targ, char *init, int trans_vers, int tpg, int max_out,
- target_queue_t *tq, void (*datain_cb)(t10_cmd_t *, char *, size_t *));
-
-/*
- * t10_handle_disable -- drains commands from emulation queues
- */
-void
-t10_handle_disable(t10_targ_handle_t t);
-
-/*
- * t10_handle_destroy -- free resources used by handle
- */
-int
-t10_handle_destroy(t10_targ_handle_t t, Boolean_t wait);
-
-Boolean_t
-t10_cmd_create(t10_targ_handle_t t, int lun_number, uint8_t *cdb,
- size_t cdb_len, transport_t trans_id, t10_cmd_t **);
-
-/*
- * t10_send_cmd -- send a command block to an target/LUN for emulation
- */
-Boolean_t
-t10_cmd_send(t10_targ_handle_t t, t10_cmd_t *cmd,
- char *opt_data, size_t opt_data_len);
-
-Boolean_t
-t10_cmd_data(t10_targ_handle_t t, t10_cmd_t *cmd, size_t offset,
- char *data, size_t data_len);
-
-void
-t10_cmd_done(t10_cmd_t *cmd);
-
-Boolean_t
-t10_task_mgmt(t10_targ_handle_t t, TaskOp_t op, int opt_lun, void *tag);
-
-/*
- * t10_cmd_shoot_event -- perform transition to the state of a T10 command
- */
-void t10_cmd_shoot_event(t10_cmd_t *c, t10_cmd_event_t e);
-
-void t10_targ_stat(t10_targ_handle_t t, char **buf);
-
-/*
- * t10_thick_provision -- management function used when creating a new lun
- */
-Boolean_t t10_thick_provision(char *target, int lun, target_queue_t *q);
-
-/*
- * []------------------------------------------------------------------[]
- * | Methods called by the emulation routines |
- * []------------------------------------------------------------------[]
- */
-
-t10_cmd_t *trans_cmd_dup(t10_cmd_t *cmd);
-
-/*
- * trans_send_datain -- Emulation layer sending data to initiator
- */
-Boolean_t trans_send_datain(t10_cmd_t *cmd, char *data, size_t data_len,
- size_t offset, void (*callback)(emul_handle_t t), Boolean_t last,
- emul_handle_t id);
-
-/*
- * trans_rqst_dataout -- Emulation needs more data to complete request
- */
-Boolean_t trans_rqst_dataout(t10_cmd_t *cmd, char *data, size_t data_len,
- size_t offset, emul_cmd_t emul_id, void (*callback)(emul_handle_t e));
-
-/*
- * trans_send_complete -- Emulation has completed request w/ opt. sense data
- */
-void trans_send_complete(t10_cmd_t *cmd, int t10_status);
-
-/*
- * trans_aiowrite -- asynchronous write and kicks the aio wait thread
- */
-void trans_aiowrite(t10_cmd_t *cmd, char *data, size_t data_len, off_t offset,
- t10_aio_t *taio);
-
-/*
- * trans_aioread -- asynchronous read and kicks the aio wait thread
- */
-void trans_aioread(t10_cmd_t *cmd, char *data, size_t data_len, off_t offset,
- t10_aio_t *taio);
-
-/*
- * trans_params_area -- given a t10_cmd return the dtype params
- */
-void *trans_params_area(t10_cmd_t *cmd);
-
-/*
- * []------------------------------------------------------------------[]
- * | Declaration of emulation entry points |
- * []------------------------------------------------------------------[]
- */
-Boolean_t sbc_common_init(t10_lu_common_t *lu);
-void sbc_common_fini(t10_lu_common_t *lu);
-void sbc_task_mgmt(t10_lu_common_t *lu, TaskOp_t op);
-void sbc_per_init(t10_lu_impl_t *itl);
-void sbc_per_fini(t10_lu_impl_t *itl);
-Boolean_t ssc_common_init(t10_lu_common_t *lu);
-void ssc_common_fini(t10_lu_common_t *lu);
-void ssc_task_mgmt(t10_lu_common_t *lu, TaskOp_t op);
-void ssc_per_init(t10_lu_impl_t *itl);
-void ssc_per_fini(t10_lu_impl_t *itl);
-Boolean_t raw_common_init(t10_lu_common_t *lu);
-void raw_common_fini(t10_lu_common_t *lu);
-void raw_per_init(t10_lu_impl_t *itl);
-void raw_per_fini(t10_lu_impl_t *itl);
-void raw_task_mgmt(t10_lu_common_t *lu, TaskOp_t op);
-Boolean_t osd_common_init(t10_lu_common_t *lu);
-void osd_common_fini(t10_lu_common_t *lu);
-void osd_per_init(t10_lu_impl_t *itl);
-void osd_per_fini(t10_lu_impl_t *itl);
-void osd_task_mgmt(t10_lu_common_t *lu, TaskOp_t op);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _T10_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/t10_osd.c b/usr/src/cmd/iscsi/iscsitgtd/t10_osd.c
deleted file mode 100644
index 793175ed4f..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_osd.c
+++ /dev/null
@@ -1,596 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * []------------------------------------------------------------------[]
- * | Implementation of OSD emulation |
- * | |
- * | NOTE: At this point in time this file is nothing more than a |
- * | place holder for the implementation. As the project evolves we'll |
- * | add more and more functionality. |
- * []------------------------------------------------------------------[]
- */
-#include <sys/types.h>
-#include <aio.h>
-#include <sys/asynch.h>
-#include <sys/mman.h>
-#include <stddef.h>
-#include <strings.h>
-#include <unistd.h>
-#include <assert.h>
-
-#include <sys/scsi/generic/sense.h>
-#include <sys/scsi/generic/status.h>
-#include <sys/scsi/generic/inquiry.h>
-#include <sys/scsi/generic/commands.h>
-#include <sys/scsi/generic/mode.h>
-#include <sys/scsi/generic/dad_mode.h>
-
-#include "t10.h"
-#include "t10_spc.h"
-#include "t10_osd.h"
-#include "utility.h"
-
-/*
- * Forward declarations
- */
-static void osd_cmd(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
-static void osd_data(t10_cmd_t *cmd, emul_handle_t e, size_t offset,
- char *data, size_t data_len);
-static scsi_cmd_table_t osd_table[];
-static void osd_list(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
-
-/*
- * []----
- * | osd_init_common -- Initialize LU data which is common to all I_T_Ls
- * []----
- */
-/*ARGSUSED*/
-Boolean_t
-osd_common_init(t10_lu_common_t *lu)
-{
- osd_params_t *o;
- char *str;
- tgt_node_t *node = lu->l_root;
-
- if ((o = (osd_params_t *)calloc(1, sizeof (*o))) == NULL)
- return (False);
-
- if (tgt_find_value_str(node, XML_ELEMENT_SIZE, &str) == True) {
- o->o_size = strtoll(str, NULL, 0);
- free(str);
- } else {
- free(o);
- return (False);
- }
-
- lu->l_dtype_params = (void *)o;
- return (True);
-}
-
-/*ARGSUSED*/
-void
-osd_common_fini(t10_lu_common_t *lu)
-{
- free(lu->l_dtype_params);
-}
-
-/*
- * []----
- * | osd_init_per -- Initialize per I_T_L information
- * []----
- */
-/*ARGSUSED*/
-void
-osd_per_init(t10_lu_impl_t *itl)
-{
- itl->l_cmd = osd_cmd;
- itl->l_data = osd_data;
- itl->l_cmd_table = osd_table;
-
- /*
- * The first time an I_T nexus connects to a LU it is supposed
- * to receive an unit attention upon the first command sent.
- */
- itl->l_status = KEY_UNIT_ATTENTION;
- itl->l_asc = SPC_ASC_PWR_ON;
- itl->l_ascq = SPC_ASCQ_PWR_ON;
-}
-
-/*ARGSUSED*/
-void
-osd_per_fini(t10_lu_impl_t *itl)
-{
-}
-
-/*ARGSUSED*/
-void
-osd_task_mgmt(t10_lu_common_t *lu, TaskOp_t op)
-{
-}
-
-/*
- * []----
- * | osd_cmd -- start a SCSI command
- * |
- * | This routine is called from within the SAM-3 Task router.
- * []----
- */
-static void
-osd_cmd(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- scsi_cmd_table_t *e;
-
- e = &cmd->c_lu->l_cmd_table[cdb[0]];
-#ifdef FULL_DEBUG
- queue_prt(mgmtq, Q_STE_IO, "SBC%x LUN%d Cmd %s\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- e->cmd_name == NULL ? "(no name)" : e->cmd_name);
-#endif
- (*e->cmd_start)(cmd, cdb, cdb_len);
-}
-
-/*
- * []----
- * | osd_data -- Data phase for command.
- * |
- * | Normally this is only called for the WRITE command. Other commands
- * | that have a data in phase will probably be short circuited when
- * | we call trans_rqst_dataout() and the data is already available.
- * | At least this is true for iSCSI. FC however will need a DataIn phase
- * | for commands like MODE SELECT and PGROUT.
- * []----
- */
-static void
-osd_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset, char *data,
- size_t data_len)
-{
- scsi_cmd_table_t *e;
-
- e = &cmd->c_lu->l_cmd_table[cmd->c_cdb[0]];
-#ifdef FULL_DEBUG
- queue_prt(mgmtq, Q_STE_IO, "SBC%x LUN%d Data %s\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- e->cmd_name);
-#endif
- (*e->cmd_data)(cmd, id, offset, data, data_len);
-}
-
-/*
- * []------------------------------------------------------------------[]
- * | SCSI Object-Based Storage Device Commands |
- * | T10/1355-D |
- * | The following functions implement the emulation of OSD type |
- * | commands. |
- * []------------------------------------------------------------------[]
- */
-static void
-osd_service_action(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- osd_generic_cdb_t *o;
- uint16_t service_action;
-
- /*
- * debug only -- no need to drop core if someone doesn't play right.
- */
- assert(cdb_len == sizeof (*o));
- if (cdb_len != sizeof (*o)) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, SPC_ASCQ_INVALID_CDB);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- o = (osd_generic_cdb_t *)cdb;
- service_action = o->ocdb_basic.b_service_action[0] << 8 |
- o->ocdb_basic.b_service_action[1];
-
- queue_prt(mgmtq, Q_STE_NONIO,
- "OSD%x LUN%d service=0x%x, options=0x%x, specific_opts=0x%x,"
- " fmt=0x%x", cmd->c_lu->l_targ->s_targ_num,
- cmd->c_lu->l_common->l_num, service_action, o->ocdb_options,
- o->ocdb_specific_opts, o->ocdb_fmt);
-
- switch (service_action) {
- case OSD_APPEND:
- case OSD_CREATE:
- case OSD_CREATE_AND_WRITE:
- case OSD_CREATE_COLLECTION:
- case OSD_CREATE_PARTITION:
- case OSD_FLUSH:
- case OSD_FLUSH_COLLECTION:
- case OSD_FLUSH_OSD:
- case OSD_FLUSH_PARTITION:
- case OSD_FORMAT_OSD:
- case OSD_GET_ATTR:
- case OSD_LIST:
- osd_list(cmd, cdb, cdb_len);
- break;
-
- case OSD_LIST_COLLECTION:
- case OSD_PERFORM_SCSI:
- case OSD_TASK_MGMT:
- default:
- spc_unsupported(cmd, cdb, cdb_len);
- break;
- }
-}
-
-/*
- * []----
- * | osd_list -- return a list of objects
- * []----
- */
-static void
-osd_list(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- osd_cmd_list_t *o = (osd_cmd_list_t *)cdb;
- osd_obj_id_t part;
- osd_list_param_t *data;
- uint64_t len, alloc_len;
-
- part = (uint64_t)o->ocdb_partition_id[0] << 56 |
- (uint64_t)o->ocdb_partition_id[1] << 48 |
- (uint64_t)o->ocdb_partition_id[2] << 40 |
- (uint64_t)o->ocdb_partition_id[3] << 32 |
- (uint64_t)o->ocdb_partition_id[4] << 24 |
- (uint64_t)o->ocdb_partition_id[5] << 16 |
- (uint64_t)o->ocdb_partition_id[6] << 8 |
- (uint64_t)o->ocdb_partition_id[7];
- len = (uint64_t)o->ocdb_length[0] << 56 |
- (uint64_t)o->ocdb_length[1] << 48 |
- (uint64_t)o->ocdb_length[2] << 40 |
- (uint64_t)o->ocdb_length[3] << 32 |
- (uint64_t)o->ocdb_length[4] << 24 |
- (uint64_t)o->ocdb_length[5] << 16 |
- (uint64_t)o->ocdb_length[6] << 8 |
- (uint64_t)o->ocdb_length[7];
-
- if (len == 0) {
- trans_send_complete(cmd, STATUS_GOOD);
- return;
- }
-
- queue_prt(mgmtq, Q_STE_NONIO, "part=0x%llx, len=0x%llx", part, len);
- alloc_len = MAX(sizeof (*data), len);
- if ((data = calloc(1, alloc_len)) == NULL) {
- trans_send_complete(cmd, STATUS_BUSY);
- return;
- }
- data->op_length[7] = sizeof (*data) - 8;
- if (part == OSD_PARTITION_ROOT)
- data->op_root = 1;
-
- (void) trans_send_datain(cmd, (char *)data, sizeof (*data), 0, free,
- True, (emul_handle_t)data);
-}
-
-/*
- * []------------------------------------------------------------------[]
- * | Support related functions for OSD |
- * []------------------------------------------------------------------[]
- */
-
-/*
- * []----
- * | Command table for OSD emulation. This is at the end of the file because
- * | it's big and ugly. ;-) To make for fast translation to the appropriate
- * | emulation routine we just have a big command table with all 256 possible
- * | entries. Most will report STATUS_CHECK, unsupport operation. By doing
- * | this we can avoid error checking for command range or the use of a switch
- * | statement.
- * []----
- */
-static scsi_cmd_table_t osd_table[] = {
- /* 0x00 -- 0x0f */
- { spc_tur, NULL, NULL, "TEST_UNIT_READY" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_request_sense, NULL, NULL, "REQUEST_SENSE" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, "READ" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, "WRITE" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x10 -- 0x1f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_inquiry, NULL, NULL, "INQUIRY" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_mselect, spc_mselect_data, NULL, "MODE_SELECT" },
- { spc_unsupported, NULL, NULL, "RESERVE" },
- { spc_unsupported, NULL, NULL, "RELEASE" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, "MODE_SENSE" },
- { spc_unsupported, NULL, NULL, "START_STOP" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_send_diag, NULL, NULL, "SEND_DIAG" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x20 -- 0x2f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, "READ_CAPACITY" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, "READ_G1" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, "WRITE_G1" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x30 -- 0x3f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, "SYNC_CACHE" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x40 -- 0x4f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, "LOG_SENSE" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x50 -- 0x5f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, "PERSISTENT_IN" },
- { spc_unsupported, NULL, NULL, "PERSISTENT_OUT" },
-
- /* 0x60 -- 0x6f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x70 -- 0x7f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { osd_service_action, NULL, NULL, "SERVICE_ACTION" },
-
- /* 0x80 -- 0x8f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, "READ_G4" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, "WRITE_G4" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x90 -- 0x9f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, "SVC_ACTION_G4" },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xa0 - 0xaf */
- { spc_report_luns, NULL, NULL, "REPORT_LUNS" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_report_tpgs, NULL, NULL, "REPORT_TPGS" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xb0 -- 0xbf */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xc0 -- 0xcf */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xd0 -- 0xdf */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xe0 -- 0xef */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xf0 -- 0xff */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-};
diff --git a/usr/src/cmd/iscsi/iscsitgtd/t10_osd.h b/usr/src/cmd/iscsi/iscsitgtd/t10_osd.h
deleted file mode 100644
index 3a6d4d64ef..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_osd.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _T10_OSD_H
-#define _T10_OSD_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Defines and structures for Object-Base Storage Device emulation
- */
-
-/*
- * OSD revision 10, section 4.6.2
- * Partition_ID and User_Object_ID value assignments
- */
-#define OSD_PARTITION_ROOT 0x00LL
-#define OSD_PARTITION_BASE 0x10000LL
-#define OSD_USER_OBJ_ROOT 0x00LL
-#define OSD_USER_OBJ_BASE 0x10000LL
-
-/*
- * OSD revision 10, section 6.1
- * Commands for OSD type devices
- */
-#define OSD_APPEND 0x8807
-#define OSD_CREATE 0x8802
-#define OSD_CREATE_AND_WRITE 0x8812
-#define OSD_CREATE_COLLECTION 0x8815
-#define OSD_CREATE_PARTITION 0x880b
-#define OSD_FLUSH 0x8808
-#define OSD_FLUSH_COLLECTION 0x881a
-#define OSD_FLUSH_OSD 0x881c
-#define OSD_FLUSH_PARTITION 0x881b
-#define OSD_FORMAT_OSD 0x8801
-#define OSD_GET_ATTR 0x880e
-#define OSD_LIST 0x8803
-#define OSD_LIST_COLLECTION 0x8817
-#define OSD_PERFORM_SCSI 0x8f7e
-#define OSD_TASK_MGMT 0x8f7f
-
-typedef uint64_t osd_obj_id_t;
-
-typedef struct osd_params {
- uint64_t o_size;
-} osd_params_t;
-
-/*
- * OSD revision 10, section 5.1
- * OSD CDB Format -- basic OSD CDB
- */
-typedef struct osd_cmd_basic {
- uint8_t b_code,
- b_control,
- b_rsvd[5],
- b_add_cdblen,
- b_service_action[2];
-} osd_cmd_basic_t;
-
-/*
- * OSD revision 10, section 5.2.1
- * OSD service action specific fields
- * The specification doesn't repeat the fields found in the basic OSD CDB,
- * but it's included here so that one structure contains everything.
- */
-typedef struct osd_generic_cdb {
- osd_cmd_basic_t ocdb_basic;
- uint8_t ocdb_options;
-#if defined(_BIT_FIELDS_LTOH)
- uint8_t ocdb_specific_opts : 4,
- ocdb_fmt : 2,
- : 2;
-#elif defined(_BIT_FIELDS_HTOL)
- uint8_t : 2,
- ocdb_fmt : 2,
- ocdb_specific_opts : 4;
-#else
-#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
-#endif
- uint8_t ocdb_ts_control,
- ocdb_rsvd1[3],
- ocdb_partition_id[8],
- ocdb_object_id[8],
- ocdb_rsvd2[4],
- ocdb_length[8],
- ocdb_start_addr[8],
- ocdb_attr_params[28],
- ocdb_capability[80],
- ocdb_security_params[40];
-} osd_generic_cdb_t;
-
-/*
- * []------------------------------------------------------------------[]
- * | OSD revision 10, section 6.13 -- LIST command |
- * []------------------------------------------------------------------[]
- */
-typedef struct osd_cmd_list {
- osd_cmd_basic_t ocdb_basic;
- uint8_t ocdb_rsvd1;
-#if defined(_BIT_FIELDS_LTOH)
- uint8_t ocdb_sort_order : 4,
- ocdb_fmt : 2,
- : 2;
-#elif defined(_BIT_FIELDS_HTOL)
- uint8_t : 2,
- ocdb_fmt : 2,
- ocdb_sort_order : 4;
-#else
-#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
-#endif
- uint8_t ocdb_ts_control,
- ocdb_rsvd2[3],
- ocdb_partition_id[8],
- ocdb_rsvd3[8],
- ocdb_list_id[4],
- ocdb_length[8],
- ocdb_object_id[8],
- ocdb_attr_params[28],
- ocdb_capability[80],
- ocdb_security_params[40];
-} osd_cmd_list_t;
-
-/* ---- Table 66, LIST command parameter data ---- */
-typedef struct osd_list_param {
- uint8_t op_length[8],
- op_cont_obj_id[8],
- op_list_id[4],
- op_rsvd1[3];
-#if defined(_BIT_FIELDS_LTOH)
- uint8_t op_root : 1,
- op_lstchg : 1,
- : 6;
-#elif defined(_BIT_FIELDS_HTOL)
- uint8_t : 6,
- op_lstchg : 1,
- op_root : 1;
-#else
-#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
-#endif
- osd_obj_id_t op_list[1];
-} osd_list_param_t;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _T10_OSD_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/t10_raw_if.c b/usr/src/cmd/iscsi/iscsitgtd/t10_raw_if.c
deleted file mode 100644
index aa123b3cb8..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_raw_if.c
+++ /dev/null
@@ -1,1572 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * []------------------------------------------------------------------[]
- * | Implementation of SBC-2 emulation |
- * []------------------------------------------------------------------[]
- */
-#include <sys/types.h>
-#include <sys/asynch.h>
-#include <sys/mman.h>
-#include <stddef.h>
-#include <strings.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/sysmacros.h>
-
-#include <sys/scsi/generic/sense.h>
-#include <sys/scsi/generic/status.h>
-#include <sys/scsi/generic/inquiry.h>
-#include <sys/scsi/generic/commands.h>
-#include <sys/scsi/generic/mode.h>
-#include <sys/scsi/generic/dad_mode.h>
-#include <sys/scsi/impl/uscsi.h>
-
-#include "t10.h"
-#include "t10_spc.h"
-#include "utility.h"
-#include "target.h"
-
-typedef struct raw_io {
- t10_aio_t r_aio;
- t10_cmd_t *r_cmd;
-
- uint8_t *r_cdb;
- char *r_data;
- size_t r_cdb_len,
- r_data_len;
- uint64_t r_offset,
- r_lba;
- size_t r_lba_cnt;
- uint32_t r_status;
-} raw_io_t;
-
-typedef struct raw_params {
- uint64_t r_size;
- int r_dtype;
-} raw_params_t;
-
-typedef enum { RawDataToDevice, RawDataFromDevice, NoData } raw_direction_t;
-
-/*
- * Forward declarations
- */
-static scsi_cmd_table_t raw_table[];
-static void raw_cmd(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
-static void raw_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset,
- char *data, size_t data_len);
-static void raw_free_io(emul_handle_t id);
-static void do_dataout(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len,
- size_t opt_data_len);
-static raw_io_t *do_datain(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len,
- size_t data_len);
-static int do_uscsi(t10_cmd_t *cmd, raw_io_t *io, raw_direction_t dir);
-static void raw_read_cmplt(emul_handle_t id);
-static void raw_write_cmplt(emul_handle_t e);
-
-/*
- * []----
- * | raw_init_common -- Initialize LU data which is common to all I_T_Ls
- * []----
- */
-Boolean_t
-raw_common_init(t10_lu_common_t *lu)
-{
- tgt_node_t *node = lu->l_root;
- char *str;
- raw_params_t *r;
-
- if ((r = (raw_params_t *)calloc(1, sizeof (*r))) == NULL)
- return (False);
-
- if (tgt_find_value_str(node, XML_ELEMENT_SIZE, &str) == True) {
- r->r_size = strtoll(str, NULL, 0);
- free(str);
- }
- lu->l_dtype_params = (void *)r;
- return (True);
-}
-
-void
-raw_common_fini(t10_lu_common_t *lu)
-{
- free(lu->l_dtype_params);
-}
-
-/*
- * []----
- * | raw_init_per -- Initialize per I_T_L information
- * []----
- */
-void
-raw_per_init(t10_lu_impl_t *itl)
-{
- itl->l_cmd = raw_cmd;
- itl->l_data = raw_data;
- itl->l_cmd_table = raw_table;
-
- /*
- * The first time an I_T nexus connects to a LU it is supposed
- * to receive an unit attention upon the first command sent.
- */
- itl->l_status = KEY_UNIT_ATTENTION;
- itl->l_asc = 0x29;
- itl->l_ascq = 0x01;
-}
-
-/*ARGSUSED*/
-void
-raw_per_fini(t10_lu_impl_t *itl)
-{
-}
-
-/*ARGSUSED*/
-void
-raw_task_mgmt(t10_lu_common_t *t, TaskOp_t op)
-{
-}
-
-/*
- * []----
- * | raw_cmd -- start a SCSI command
- * |
- * | This routine is called from within the SAM-3 Task router.
- * []----
- */
-static void
-raw_cmd(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- scsi_cmd_table_t *e;
-#ifdef FULL_DEBUG
- char debug[80];
-#endif
-
- e = &cmd->c_lu->l_cmd_table[cdb[0]];
-#ifdef FULL_DEBUG
- (void) snprintf(debug, sizeof (debug), "RAW%d Cmd %s\n",
- cmd->c_lu->l_common->l_num,
- e->cmd_name == NULL ? "(no name)" : e->cmd_name);
- queue_str(mgmtq, Q_STE_IO, msg_log, debug);
-#endif
- (*e->cmd_start)(cmd, cdb, cdb_len);
-}
-
-/*
- * []----
- * | raw_data -- Data phase for command.
- * |
- * | Normally this is only called for the WRITE command. Other commands
- * | that have a data in phase will probably be short circuited when
- * | we call trans_rqst_dataout() and the data is already available.
- * | At least this is true for iSCSI. FC however will need a DataIn phase
- * | for commands like MODE SELECT and PGROUT.
- * []----
- */
-static void
-raw_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset, char *data,
- size_t data_len)
-{
- scsi_cmd_table_t *e;
-#ifdef FULL_DEBUG
- char debug[80];
-#endif
-
- e = &cmd->c_lu->l_cmd_table[cmd->c_cdb[0]];
-#ifdef FULL_DEBUG
- (void) snprintf(debug, sizeof (debug), "RAW%d Data %s\n",
- cmd->c_lu->l_common->l_num, e->cmd_name);
- queue_str(mgmtq, Q_STE_IO, msg_log, debug);
-#endif
- (*e->cmd_data)(cmd, id, offset, data, data_len);
-}
-
-/*
- * []------------------------------------------------------------------[]
- * | The following methods handle special case requirements for the |
- * | raw devices. |
- * []------------------------------------------------------------------[]
- */
-
-/*
- * []----
- * | raw_read_tape -- handle SCSI reads from raw tape
- * |
- * | Need to handle reads from SCSI tape differently than LBA devices
- * | for two reasons.
- * | (1) The command block for tape reads is different than for
- * | LBA devices. There's only a count field.
- * | (2) Since tapes have records it's not possible to break up
- * | the read operations in the same manner as LBA devices.
- * | All of the data must first be read in from the device
- * | and then broken up to fit the transport. This is a slower
- * | approach, but nobody expects tapes to be quick. If speed
- * | is needed a better approach would be to create a virtual
- * | tape device and then stage out the data to the device later.
- * []----
- */
-/*ARGSUSED*/
-static void
-raw_read_tape(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- size_t req_len;
- size_t xfer;
- off_t offset = 0;
- raw_io_t *io;
- Boolean_t last;
- t10_cmd_t *c;
-
- req_len = (cdb[2] << 16) | (cdb[3] << 8) | cdb[4];
- if (cdb[1] & 0x1)
- req_len *= 512;
-
- if (((io = do_datain(cmd, cdb, CDB_GROUP0, req_len)) == NULL) ||
- (io->r_status != STATUS_GOOD)) {
- if (io != NULL)
- raw_free_io(io);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- while (offset < io->r_data_len) {
- xfer = min(T10_MAX_OUT(cmd), io->r_data_len - offset);
- last = ((offset + xfer) >= io->r_data_len) ? True : False;
- if (last == True)
- c = cmd;
- else
- c = trans_cmd_dup(cmd);
-
- if (trans_send_datain(c, io->r_data + offset,
- xfer, offset, raw_free_io, last, io) == False) {
- raw_free_io(io);
- spc_sense_create(c, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(c, STATUS_CHECK);
- return;
- }
- offset += xfer;
- }
-}
-
-/*
- * []----
- * | raw_read -- emulation of SCSI READ command
- * []----
- */
-/*ARGSUSED*/
-static void
-raw_read(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- /*LINTED*/
- union scsi_cdb *u = (union scsi_cdb *)cdb;
- diskaddr_t addr;
- off_t offset = 0;
- uint32_t cnt;
- uint32_t min;
- raw_io_t *io;
- uint64_t err_blkno;
- int sense_len;
- char debug[80];
- raw_params_t *r;
- uchar_t addl_sense_len;
- t10_cmd_t *c;
-
- if ((r = (raw_params_t *)T10_PARAMS_AREA(cmd)) == NULL)
- return;
-
- if (r->r_dtype == DTYPE_SEQUENTIAL) {
- raw_read_tape(cmd, cdb, cdb_len);
- return;
- }
-
- switch (u->scc_cmd) {
- case SCMD_READ:
- /*
- * SBC-2 Revision 16, section 5.5
- * Reserve bit checks
- */
- if ((cdb[1] & 0xe0) || (cdb[5] & 0x38)) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, 0x24, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- addr = (diskaddr_t)(uint32_t)GETG0ADDR(u);
- cnt = GETG0COUNT(u);
-
- /*
- * SBC-2 Revision 16
- * Section: 5.5 READ(6) command
- * A TRANSFER LENGTH field set to zero specifies
- * that 256 logical blocks shall be read.
- */
- if (cnt == 0)
- cnt = 256;
- break;
-
- case SCMD_READ_G1:
- /*
- * SBC-2 Revision 16, section 5.6
- * Reserve bit checks.
- */
- if ((cdb[1] & 6) || cdb[6] || (cdb[9] & 0x38)) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, 0x24, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- addr = (diskaddr_t)(uint32_t)GETG1ADDR(u);
- cnt = GETG1COUNT(u);
- break;
-
- case SCMD_READ_G4:
- /*
- * SBC-2 Revision 16, section 5.8
- * Reserve bit checks
- */
- if ((cdb[1] & 0x6) || (cdb[10] & 6) || cdb[14] ||
- (cdb[15] & 0x38)) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, 0x24, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- addr = GETG4LONGADDR(u);
- cnt = GETG4COUNT(u);
- break;
-
- default:
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- if ((addr + cnt) > r->r_size) {
-
- /*
- * request exceed the capacity of disk
- * set error block number to capacity + 1
- */
- err_blkno = r->r_size + 1;
-
- /*
- * XXX: What's SBC-2 say about ASC/ASCQ here. Solaris
- * doesn't care about these values when key is set
- * to KEY_ILLEGAL_REQUEST.
- */
- if (err_blkno > FIXED_SENSE_ADDL_INFO_LEN)
- addl_sense_len = INFORMATION_SENSE_DESCR;
- else
- addl_sense_len = 0;
-
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, addl_sense_len);
- spc_sense_info(cmd, err_blkno);
- spc_sense_ascq(cmd, 0x21, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
-
- (void) snprintf(debug, sizeof (debug),
- "RAW%d READ Illegal sector (0x%llx + 0x%x) > 0x%llx",
- cmd->c_lu->l_common->l_num, addr, cnt, r->r_size);
- queue_str(mgmtq, Q_STE_ERRS, msg_log, debug);
- return;
- }
-
- cmd->c_lu->l_cmds_read++;
- cmd->c_lu->l_sects_read += cnt;
-
- if (cnt == 0) {
- trans_send_complete(cmd, STATUS_GOOD);
- return;
- }
-
- do {
- min = MIN((cnt * 512) - offset, T10_MAX_OUT(cmd));
- if ((offset + min) < (cnt * 512LL))
- c = trans_cmd_dup(cmd);
- else
- c = cmd;
- if ((io = (raw_io_t *)calloc(1, sizeof (*io))) == NULL) {
-
- /*
- * We're pretty much dead in the water. If we can't
- * allocate memory. It's unlikey we'll be able to
- * allocate a sense buffer or queue the command
- * up to be sent back to the transport for delivery.
- */
- spc_sense_create(c, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(c, STATUS_CHECK);
- return;
- }
-
- io->r_cmd = c;
- io->r_lba = addr;
- io->r_lba_cnt = cnt;
- io->r_offset = offset;
- io->r_data_len = min;
- io->r_aio.a_aio_cmplt = raw_read_cmplt;
- io->r_aio.a_id = io;
-
-#ifdef FULL_DEBUG
- (void) snprintf(debug, sizeof (debug),
- "RAW%d blk 0x%llx, cnt %d, offset 0x%llx, size %d",
- c->c_lu->l_common->l_num, addr, cnt, io->r_offset, min);
- queue_str(mgmtq, Q_STE_IO, msg_log, debug);
-#endif
- if ((io->r_data = (char *)malloc(min)) == NULL) {
- err_blkno = addr + ((offset + 511) / 512);
- if (err_blkno > FIXED_SENSE_ADDL_INFO_LEN)
- sense_len = INFORMATION_SENSE_DESCR;
- else
- sense_len = 0;
- spc_sense_create(c, KEY_HARDWARE_ERROR,
- sense_len);
- spc_sense_info(c, err_blkno);
- trans_send_complete(c, STATUS_CHECK);
- return;
- }
- trans_aioread(c, io->r_data, min, (addr * 512LL) +
- (off_t)io->r_offset, &io->r_aio);
- offset += min;
- } while (offset < (off_t)(cnt * 512));
-}
-
-/*
- * []----
- * | raw_read_cmplt -- Once we have the data, need to send it along.
- * []----
- */
-static void
-raw_read_cmplt(emul_handle_t id)
-{
- raw_io_t *io = (raw_io_t *)id;
- int sense_len;
- uint64_t err_blkno;
- t10_cmd_t *cmd = io->r_cmd;
- Boolean_t last;
-
- if (io->r_aio.a_aio.aio_return != io->r_data_len) {
- err_blkno = io->r_lba + ((io->r_offset + 511) / 512);
- cmd->c_resid = (io->r_lba_cnt * 512) - io->r_offset;
- if (err_blkno > FIXED_SENSE_ADDL_INFO_LEN)
- sense_len = INFORMATION_SENSE_DESCR;
- else
- sense_len = 0;
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, sense_len);
- spc_sense_info(cmd, err_blkno);
- trans_send_complete(cmd, STATUS_CHECK);
- raw_free_io(io);
- return;
- }
-
- last = ((io->r_offset + io->r_data_len) < (io->r_lba_cnt * 512LL)) ?
- False : True;
- if (trans_send_datain(cmd, io->r_data, io->r_data_len,
- io->r_offset, raw_free_io, last, io) == False) {
- raw_free_io(io);
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- }
-}
-
-/*ARGSUSED*/
-static void
-raw_write_tape(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- size_t request_len;
- size_t xfer;
- raw_io_t *io;
-
- request_len = (cdb[2] << 16) | (cdb[3] << 8) | cdb[4];
- request_len *= (cdb[1] & 0x1) ? 512 : 1;
-
- if ((io = calloc(1, sizeof (*io))) == NULL) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- if ((io->r_data = malloc(request_len)) == NULL) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- }
- io->r_data_len = request_len;
- io->r_cmd = cmd;
-
- xfer = min(T10_MAX_OUT(cmd), request_len);
- (void) trans_rqst_dataout(cmd, io->r_data, xfer, io->r_offset, io,
- raw_free_io);
-}
-
-/*ARGSUSED*/
-void
-raw_write_tape_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset, char *data,
- size_t data_len)
-{
- raw_io_t *io = (raw_io_t *)id;
- size_t xfer;
-
- if ((io->r_offset + data_len) < io->r_data_len) {
- io->r_offset += data_len;
- xfer = min(T10_MAX_OUT(cmd), io->r_data_len - io->r_offset);
- (void) trans_rqst_dataout(cmd, io->r_data + io->r_offset, xfer,
- io->r_offset, io, raw_free_io);
- return;
- } else {
- trans_send_complete(cmd, do_uscsi(cmd, io, RawDataToDevice));
- }
-}
-
-/*
- * []----
- * | raw_write -- implement a SCSI write command.
- * []----
- */
-/*ARGSUSED*/
-static void
-raw_write(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- /*LINTED*/
- union scsi_cdb *cdbp = (union scsi_cdb *)cdb;
- off_t addr;
- uint64_t err_blkno;
- uint32_t cnt;
- uchar_t addl_sense_len;
- char debug[80]; /* debug */
- raw_params_t *r;
- raw_io_t *io;
- size_t max_out;
-
- if ((r = (raw_params_t *)T10_PARAMS_AREA(cmd)) == NULL)
- return;
-
- if (r->r_dtype == DTYPE_SEQUENTIAL) {
- raw_write_tape(cmd, cdb, cdb_len);
- return;
- }
-
- switch (cdb[0]) {
- case SCMD_WRITE:
- /*
- * SBC-2 revision 16, section 5.24
- * Reserve bit checks.
- */
- if ((cdb[1] & 0xe0) || (cdb[5] & 0x38)) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, 0x24, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- addr = (off_t)cdbp->g0_addr2 << 16 |
- (off_t)cdbp->g0_addr1 << 8 | (off_t)cdbp->g0_addr0;
- cnt = cdbp->g0_count0;
- /*
- * SBC-2 Revision 16/Section 5.24 WRITE(6)
- * A TRANSFER LENGHT of 0 indicates that 256 logical blocks
- * shall be written.
- */
- if (cnt == 0)
- cnt = 256;
- break;
-
- case SCMD_WRITE_G1:
- /*
- * SBC-2 revision 16, section 5.25
- * Reserve bit checks.
- */
- if ((cdb[1] & 0x6) || cdb[6] || (cdb[9] & 0x38)) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, 0x24, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- addr = (off_t)cdbp->g1_addr3 << 24 |
- (off_t)cdbp->g1_addr2 << 16 |
- (off_t)cdbp->g1_addr1 << 8 |
- (off_t)cdbp->g1_addr0;
- cnt = cdbp->g1_count1 << 8 | cdbp->g1_count0;
- break;
-
- case SCMD_WRITE_G4:
- /*
- * SBC-2 revision 16, section 5.27
- * Reserve bit checks.
- */
- if ((cdb[1] & 0x6) || cdb[14] || (cdb[15] & 0x38)) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, 0x24, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- addr = (off_t)(cdbp->g4_addr3 & 0xff) << 56 |
- (off_t)(cdbp->g4_addr2 & 0xff) << 48 |
- (off_t)(cdbp->g4_addr1 & 0xff) << 40 |
- (off_t)(cdbp->g4_addr0 & 0xff) << 32 |
- (off_t)(cdbp->g4_addtl_cdb_data3 & 0xff) << 24 |
- (off_t)(cdbp->g4_addtl_cdb_data2 & 0xff) << 16 |
- (off_t)(cdbp->g4_addtl_cdb_data1 & 0xff) << 8 |
- (off_t)(cdbp->g4_addtl_cdb_data0 & 0xff);
- cnt = cdbp->g4_count3 << 24 | cdbp->g4_count2 << 16 |
- cdbp->g4_count1 << 8 | cdbp->g4_count0;
- break;
-
- default:
- queue_str(mgmtq, Q_STE_ERRS, msg_log,
- "Unprocessed WRITE type");
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, 0x24, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
-
- }
-
- if ((addr < 0) || ((addr + cnt) > r->r_size)) {
-
- /*
- * request exceed the capacity of disk
- * set error block number to capacity + 1
- */
- err_blkno = r->r_size + 1;
-
- /*
- * XXX: What's SBC-2 say about ASC/ASCQ here. Solaris
- * doesn't care about these values when key is set
- * to KEY_ILLEGAL_REQUEST.
- */
- if (err_blkno > FIXED_SENSE_ADDL_INFO_LEN)
- addl_sense_len = INFORMATION_SENSE_DESCR;
- else
- addl_sense_len = 0;
-
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, addl_sense_len);
- spc_sense_info(cmd, err_blkno);
- spc_sense_ascq(cmd, 0x21, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
-
- (void) snprintf(debug, sizeof (debug),
- "RAW%d WRITE Illegal sector (0x%llx + 0x%x) > 0x%llx",
- cmd->c_lu->l_common->l_num, addr, cnt, r->r_size);
- queue_str(mgmtq, Q_STE_ERRS, msg_log, debug);
- return;
- }
-
- if (cnt == 0) {
- trans_send_complete(cmd, STATUS_GOOD);
- return;
- }
-
- io = (raw_io_t *)cmd->c_emul_id;
- if (io == NULL) {
- if ((io = (raw_io_t *)calloc(1, sizeof (*io))) == NULL) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- io->r_lba = addr;
- io->r_lba_cnt = cnt;
- io->r_cmd = cmd;
- io->r_aio.a_aio_cmplt = raw_write_cmplt;
- io->r_aio.a_id = io;
-
- /*
- * Only update the statistics the first time through
- * for this particular command. If the requested transfer
- * is larger than the transport can handle this routine
- * will be called many times.
- */
- cmd->c_lu->l_cmds_write++;
- cmd->c_lu->l_sects_write += cnt;
- }
-
- /*
- * If a transport sets the maximum output value to zero we'll
- * just request the entire amount. Otherwise, transfer no more
- * than the maximum output or the reminder, whichever is less.
- */
- max_out = cmd->c_lu->l_targ->s_maxout;
- io->r_data_len = max_out ? MIN(max_out,
- (cnt * 512) - io->r_offset) : (cnt * 512);
-
-#ifdef FULL_DEBUG
- (void) snprintf(debug, sizeof (debug),
- "RAW%d blk 0x%llx, cnt %d, offset 0x%llx, size %d",
- cmd->c_lu->l_common->l_num, addr, cnt, io->r_offset,
- io->r_data_len);
- queue_str(mgmtq, Q_STE_IO, msg_log, debug);
-#endif
-
- if ((io->r_data = (char *)malloc(io->r_data_len)) == NULL) {
-
- /*
- * NOTE: May need a different ASC code
- */
- err_blkno = addr + ((io->r_offset + 511) / 512);
- if (err_blkno > FIXED_SENSE_ADDL_INFO_LEN)
- addl_sense_len = INFORMATION_SENSE_DESCR;
- else
- addl_sense_len = 0;
-
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, addl_sense_len);
- spc_sense_info(cmd, err_blkno);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
-
- }
- if (trans_rqst_dataout(cmd, io->r_data, io->r_data_len, io->r_offset,
- io, raw_free_io) == False) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- }
-}
-
-/*
- * []----
- * | raw_write_data -- store a chunk of data from the transport
- * []----
- */
-/*ARGSUSED*/
-void
-raw_write_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset, char *data,
- size_t data_len)
-{
- raw_io_t *io = (raw_io_t *)id;
- raw_params_t *r = T10_PARAMS_AREA(cmd);
-
- if (r == NULL)
- return;
-
- if (r->r_dtype == DTYPE_SEQUENTIAL) {
- raw_write_tape_data(cmd, id, offset, data, data_len);
- return;
- }
-
- trans_aiowrite(cmd, data, data_len, (io->r_lba * 512) +
- (off_t)io->r_offset, &io->r_aio);
-}
-
-/*
- * []----
- * | raw_write_cmplt -- deal with end game of write
- * |
- * | See if all of the data for this write operation has been dealt
- * | with. If so, send a final acknowledgement back to the transport.
- * | If not, update the offset, calculate the next transfer size, and
- * | start the process again.
- * []---
- */
-static void
-raw_write_cmplt(emul_handle_t e)
-{
- raw_io_t *io = (raw_io_t *)e;
- t10_cmd_t *cmd = io->r_cmd;
-
- if ((io->r_offset + io->r_data_len) < (io->r_lba_cnt * 512)) {
- free(io->r_data);
-
- io->r_offset += io->r_data_len;
- io->r_data_len = MIN(cmd->c_lu->l_targ->s_maxout,
- (io->r_lba_cnt * 512) - io->r_offset);
- raw_write(cmd, cmd->c_cdb, cmd->c_cdb_len);
- return;
- }
- trans_send_complete(cmd, STATUS_GOOD);
-}
-
-static void
-raw_reserve(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- raw_io_t *io;
-
- if ((io = do_datain(cmd, cdb, CDB_GROUP0, 0)) == NULL) {
- trans_send_complete(cmd, STATUS_CHECK);
- } else {
- trans_send_complete(cmd, io->r_status);
- raw_free_io(io);
- }
-}
-
-static void
-raw_release(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- raw_io_t *io;
-
- if ((io = do_datain(cmd, cdb, CDB_GROUP0, 0)) == NULL) {
- trans_send_complete(cmd, STATUS_CHECK);
- } else {
- trans_send_complete(cmd, io->r_status);
- raw_free_io(io);
- }
-}
-
-static void
-raw_persist_in(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- raw_io_t *io;
- uint32_t len;
-
- len = (cdb[7] << 8) | cdb[8];
- if ((io = do_datain(cmd, cdb, CDB_GROUP1, len)) == NULL) {
- trans_send_complete(cmd, STATUS_CHECK);
- } else {
- if (trans_send_datain(cmd, io->r_data, io->r_data_len, 0,
- raw_free_io, True, io) == False) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- }
- }
-}
-
-static void
-raw_persist_out(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- size_t len;
-
- len = (cdb[5] << 24) | (cdb[6] << 16) | (cdb[7] << 8) | cdb[8];
- do_dataout(cmd, cdb, cdb_len, len);
-}
-
-/*ARGSUSED*/
-static void
-raw_persist_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset, char *data,
- size_t data_len)
-{
- raw_io_t *io = (raw_io_t *)id;
- trans_send_complete(cmd, do_uscsi(cmd, io, RawDataToDevice));
-}
-
-static void
-raw_msense(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- raw_io_t *io;
- int len;
-
- switch (cdb[0]) {
- case SCMD_MODE_SENSE:
- len = cdb[4];
- break;
-
- case SCMD_MODE_SENSE_G1:
- len = (cdb[7] << 8) | cdb[8];
- break;
- }
-
- if (((io = do_datain(cmd, cdb, CDB_GROUP0, len)) == NULL) ||
- (io->r_status != STATUS_GOOD)) {
- if (io != NULL)
- raw_free_io(io);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- if (trans_send_datain(cmd, io->r_data, io->r_data_len, 0,
- raw_free_io, True, io) == False) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- }
-}
-
-static void
-raw_tur(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- raw_io_t *io;
-
- if ((io = do_datain(cmd, cdb, CDB_GROUP0, 0)) == NULL) {
- trans_send_complete(cmd, STATUS_CHECK);
- } else {
- trans_send_complete(cmd, io->r_status);
- raw_free_io(io);
- }
-}
-
-static void
-raw_request_sense(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- raw_io_t *io;
-
- if (((io = do_datain(cmd, cdb, CDB_GROUP0, cdb[4])) == NULL) ||
- (io->r_status != STATUS_GOOD)) {
- if (io != NULL)
- raw_free_io(io);
- trans_send_complete(cmd, STATUS_CHECK);
- } else {
- if (trans_send_datain(cmd, io->r_data, io->r_data_len, 0,
- raw_free_io, True, io) == False) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- }
- }
-}
-
-static void
-raw_inquiry(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- raw_io_t *io;
- uint32_t len;
- struct scsi_inquiry inq;
- raw_params_t *r;
-
- if ((r = (raw_params_t *)T10_PARAMS_AREA(cmd)) == NULL)
- return;
-
- len = (cdb[3] << 8) | cdb[4];
- if (((io = do_datain(cmd, cdb, CDB_GROUP0, len)) == NULL) ||
- (io->r_status != STATUS_GOOD)) {
- if (io != NULL)
- raw_free_io(io);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- if ((cdb[1] & 1) == 0) {
- bcopy(io->r_data, &inq, sizeof (inq));
- r->r_dtype = inq.inq_dtype;
- }
- if (trans_send_datain(cmd, io->r_data, io->r_data_len, 0,
- raw_free_io, True, io) == False) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- }
-}
-
-static void
-raw_mselect(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- int len;
-
- switch (cdb[0]) {
- case SCMD_MODE_SELECT:
- len = cdb[4];
- cdb_len = CDB_GROUP0;
- break;
-
- case SCMD_MODE_SELECT_G1:
- len = (cdb[7] << 8) | cdb[8];
- cdb_len = CDB_GROUP1;
- break;
- }
- do_dataout(cmd, cdb, cdb_len, len);
-}
-
-/*ARGSUSED*/
-static void
-raw_mselect_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset, char *data,
- size_t data_len)
-{
- raw_io_t *io = (raw_io_t *)id;
- trans_send_complete(cmd, do_uscsi(cmd, io, RawDataToDevice));
-}
-
-static void
-raw_startstop(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- raw_io_t *io;
-
- if ((io = do_datain(cmd, cdb, CDB_GROUP0, 0)) == NULL) {
- trans_send_complete(cmd, STATUS_CHECK);
- } else {
- trans_send_complete(cmd, io->r_status);
- raw_free_io(io);
- }
-}
-
-static void
-raw_rewind(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- raw_io_t *io;
-
- if ((io = do_datain(cmd, cdb, CDB_GROUP0, 0)) == NULL) {
- trans_send_complete(cmd, STATUS_CHECK);
- } else {
- trans_send_complete(cmd, io->r_status);
- raw_free_io(io);
- }
-}
-
-static void
-raw_send_diag(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- int len;
-
- len = (cdb[3] << 8) | cdb[4];
- do_dataout(cmd, cdb, CDB_GROUP0, len);
-}
-
-/*ARGSUSED*/
-static void
-raw_send_diag_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset,
- char *data, size_t data_len)
-{
- raw_io_t *io = (raw_io_t *)id;
- trans_send_complete(cmd, do_uscsi(cmd, io, RawDataToDevice));
-}
-
-static void
-raw_recap(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- struct scsi_capacity cap;
- raw_io_t *io;
- raw_params_t *r;
-
- if ((r = (raw_params_t *)T10_PARAMS_AREA(cmd)) == NULL)
- return;
-
- if (((io = do_datain(cmd, cdb, CDB_GROUP1, sizeof (cap))) == NULL) ||
- (io->r_status != STATUS_GOOD)) {
- if (io != NULL)
- raw_free_io(io);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- bcopy(io->r_data, &cap, sizeof (cap));
- /*
- * Currently there's a bug in ZFS which doesn't report a capacity
- * for any of the volumes. This means that when using ZFS the
- * administrator must supply the device size.
- */
- if (cap.capacity != 0)
- r->r_size = cap.capacity;
- if (trans_send_datain(cmd, io->r_data, io->r_data_len, 0,
- raw_free_io, True, io) == False) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- }
-}
-
-static void
-raw_service_actiong4(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- raw_io_t *io;
- uint32_t len;
- struct scsi_capacity_16 cap16;
- raw_params_t *r;
-
- if ((r = (raw_params_t *)T10_PARAMS_AREA(cmd)) == NULL)
- return;
-
- len = (cdb[10] << 24) | (cdb[11] << 16) | (cdb[12] << 8) | cdb[13];
- if (((io = do_datain(cmd, cdb, CDB_GROUP4, len)) == NULL) ||
- (io->r_status != STATUS_GOOD)) {
- if (io != NULL)
- raw_free_io(io);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- bcopy(io->r_data, &cap16, sizeof (cap16));
- /*
- * Currently there's a bug in ZFS which doesn't report a capacity
- * for any of the volumes. This means that when using ZFS the
- * administrator must supply the device size.
- */
- if (cap16.sc_capacity != 0)
- r->r_size = cap16.sc_capacity;
- if (trans_send_datain(cmd, io->r_data, io->r_data_len, 0,
- raw_free_io, True, io) == False) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- }
-}
-
-static void
-raw_synccache(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- raw_io_t *io;
-
- if ((io = do_datain(cmd, cdb, CDB_GROUP1, 0)) == NULL) {
- trans_send_complete(cmd, STATUS_CHECK);
- } else {
- trans_send_complete(cmd, io->r_status);
- raw_free_io(io);
- }
-}
-
-static void
-raw_write_fm(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- raw_io_t *io;
-
- if ((io = do_datain(cmd, cdb, CDB_GROUP0, 0)) == NULL) {
- trans_send_complete(cmd, STATUS_CHECK);
- } else {
- trans_send_complete(cmd, io->r_status);
- raw_free_io(io);
- }
-}
-
-static void
-raw_report_tpgs(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- raw_io_t *io;
- uint32_t len;
-
- len = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
- if (((io = do_datain(cmd, cdb, CDB_GROUP5, len)) == NULL) ||
- (io->r_status != STATUS_GOOD)) {
- if (io != NULL)
- raw_free_io(io);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- if (trans_send_datain(cmd, io->r_data, io->r_data_len, 0,
- raw_free_io, True, io) == False) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- }
-}
-
-static void
-raw_read_limits(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- raw_io_t *io;
-
- /*
- * spec defines this command to return 6 bytes of data
- */
- if (((io = do_datain(cmd, cdb, CDB_GROUP0, 6)) == NULL) ||
- (io->r_status != STATUS_GOOD)) {
- if (io != NULL)
- raw_free_io(io);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- if (trans_send_datain(cmd, io->r_data, io->r_data_len, 0,
- raw_free_io, True, io) == False) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- }
-}
-
-/*
- * []------------------------------------------------------------------[]
- * | Support related functions for raw devices |
- * []------------------------------------------------------------------[]
- */
-
-static void
-do_dataout(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len, size_t opt_data_len)
-{
- char *opt_data = NULL;
- raw_io_t *io;
-
- if ((io = calloc(1, sizeof (*io))) == NULL) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- if ((opt_data_len != 0) &&
- ((opt_data = malloc(opt_data_len)) == NULL)) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- io->r_cdb = cdb;
- io->r_cdb_len = cdb_len;
- io->r_data = opt_data;
- io->r_data_len = opt_data_len;
- if (trans_rqst_dataout(cmd, opt_data, opt_data_len, 0, io,
- raw_free_io) == False) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- }
-}
-
-static raw_io_t *
-do_datain(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len, size_t data_len)
-{
- raw_io_t *io;
-
- if ((io = calloc(1, sizeof (*io))) == NULL) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- return (NULL);
- }
-
- io->r_cdb = cdb;
- io->r_cdb_len = cdb_len;
- io->r_data_len = data_len;
- if ((data_len != 0) && ((io->r_data = malloc(data_len)) == NULL)) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- free(io);
- return (NULL);
- }
- (void) do_uscsi(cmd, io, data_len == 0 ? NoData : RawDataFromDevice);
- return (io);
-}
-
-static int
-do_uscsi(t10_cmd_t *cmd, raw_io_t *io, raw_direction_t dir)
-{
- struct uscsi_cmd u;
- uchar_t sense_buf[128];
-
- bzero(&u, sizeof (u));
- u.uscsi_cdb = (caddr_t)io->r_cdb;
- u.uscsi_cdblen = io->r_cdb_len;
- u.uscsi_bufaddr = io->r_data;
- u.uscsi_buflen = io->r_data_len;
- u.uscsi_flags = ((dir == RawDataToDevice) ? USCSI_WRITE :
- (dir == RawDataFromDevice) ? USCSI_READ : 0) | USCSI_RQENABLE;
- u.uscsi_rqbuf = (char *)sense_buf;
- u.uscsi_rqlen = sizeof (sense_buf);
-
- if ((ioctl(cmd->c_lu->l_common->l_fd, USCSICMD, &u) == 0) &&
- (u.uscsi_status == 0)) {
- io->r_status = 0;
- return (0);
- }
- queue_prt(mgmtq, Q_STE_ERRS,
- "RAW%d LUN%d USCSICMD errno %d, cmd_status %d, rqstatus %d, "
- "rqresid %d",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num, errno,
- u.uscsi_status, u.uscsi_rqstatus, u.uscsi_rqresid);
-
- if ((u.uscsi_rqlen - u.uscsi_rqresid) <
- sizeof (struct scsi_extended_sense)) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "RAW%x LUN%d -- No sense data, got=%d, needed=%d",
- cmd->c_lu->l_targ->s_targ_num,
- cmd->c_lu->l_common->l_num,
- u.uscsi_rqlen - u.uscsi_rqresid,
- sizeof (struct scsi_extended_sense));
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- io->r_status = STATUS_CHECK;
- return (STATUS_CHECK);
- } else {
- spc_sense_raw(cmd, sense_buf, u.uscsi_rqlen - u.uscsi_rqresid);
- io->r_status = u.uscsi_status;
- return (u.uscsi_status);
- }
-}
-
-static void
-raw_free_io(emul_handle_t id)
-{
- raw_io_t *io = (raw_io_t *)id;
-
- if (io->r_data_len)
- free(io->r_data);
- free(io);
-}
-
-/*
- * []----
- * | Command table for LBA emulation. This is at the end of the file because
- * | it's big and ugly. ;-) To make for fast translation to the appropriate
- * | emulation routine we just have a big command table with all 256 possible
- * | entries. Most will report STATUS_CHECK, unsupport operation. By doing
- * | this we can avoid error checking for command range.
- * []----
- */
-static scsi_cmd_table_t raw_table[] = {
- /* 0x00 -- 0x0f */
- { raw_tur, NULL, NULL, "TEST_UNIT_READY" },
- { raw_rewind, NULL, NULL, "REWIND" },
- { spc_unsupported, NULL, NULL, NULL },
- { raw_request_sense, NULL, NULL, "REQUEST_SENSE" },
- { spc_unsupported, NULL, NULL, NULL },
- { raw_read_limits, NULL, NULL, "READ_LIMITS" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { raw_read, NULL, NULL, "READ" },
- { spc_unsupported, NULL, NULL, NULL },
- { raw_write, raw_write_data, NULL, "WRITE" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x10 -- 0x1f */
- { raw_write_fm, NULL, NULL, "WRITE_FILEMARKS" },
- { spc_unsupported, NULL, NULL, NULL },
- { raw_inquiry, NULL, NULL, "INQUIRY" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { raw_mselect, raw_mselect_data, NULL, "MODE_SELECT" },
- { raw_reserve, NULL, NULL, "RESERVE" },
- { raw_release, NULL, NULL, "RELEASE" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { raw_msense, NULL, NULL, "MODE_SENSE" },
- { raw_startstop, NULL, NULL, "START_STOP" },
- { spc_unsupported, NULL, NULL, NULL },
- { raw_send_diag, raw_send_diag_data, NULL, "SEND_DIAG" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x20 -- 0x2f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { raw_recap, NULL, NULL, "READ_CAPACITY" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { raw_read, NULL, NULL, "READ_G1" },
- { spc_unsupported, NULL, NULL, NULL },
- { raw_write, raw_write_data, NULL, "WRITE_G1" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x30 -- 0x3f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { raw_synccache, NULL, NULL, "SYNC_CACHE" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x40 -- 0x4f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x50 -- 0x5f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { raw_mselect, raw_mselect_data, NULL, "MODE_SELECT" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { raw_msense, NULL, NULL, "MODE_SENSE" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { raw_persist_in, NULL, NULL, "PERSISTENT_RESERVE_IN" },
- { raw_persist_out, raw_persist_data, NULL, "PERSISTENT_RESERVE_OUT" },
-
- /* 0x60 -- 0x6f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x70 -- 0x7f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x80 -- 0x8f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { raw_read, NULL, NULL, "READ_G4" },
- { spc_unsupported, NULL, NULL, NULL },
- { raw_write, raw_write_data, NULL, "WRITE_G4" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x90 -- 0x9f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { raw_service_actiong4, NULL, NULL, "SVC_ACTION_G4" },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xa0 - 0xaf */
- { spc_report_luns, NULL, NULL, "REPORT_LUNS" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { raw_report_tpgs, NULL, NULL, "REPORT_TPGS" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xb0 -- 0xbf */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xc0 -- 0xcf */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xd0 -- 0xdf */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xe0 -- 0xef */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xf0 -- 0xff */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-};
diff --git a/usr/src/cmd/iscsi/iscsitgtd/t10_sam.c b/usr/src/cmd/iscsi/iscsitgtd/t10_sam.c
deleted file mode 100644
index a72fbaa946..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_sam.c
+++ /dev/null
@@ -1,2790 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <aio.h>
-#include <sys/aio.h>
-#include <sys/asynch.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <strings.h>
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/statvfs.h>
-#include <sys/avl.h>
-#include <sys/param.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <errno.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/ucontext.h>
-#include <assert.h>
-#include <umem.h>
-#include <time.h>
-#include <syslog.h>
-
-#include <sys/scsi/generic/sense.h>
-#include <sys/scsi/generic/status.h>
-#include <sys/scsi/generic/inquiry.h>
-
-#include "target.h"
-#include "queue.h"
-#include "t10.h"
-#include "t10_spc.h"
-#include "utility.h"
-#include "mgmt_scf.h"
-
-/*
- * []------------------------------------------------------------------[]
- * | This file contains methods which isolate a transport from device |
- * | emulation. The first part of the file contains method which are |
- * | called by the transport to start commands or deliver data. The |
- * | transport does not know anything about what emulation is being |
- * | done. The emulation layer receieves cdb's and nows nothing about |
- * | the transport. This is how it should be. There are a few special |
- * | cases to deal with transports which have a notion of immediate |
- * | data, but we're isolating that from the emulation layer. |
- * []------------------------------------------------------------------[]
- */
-
-#define MAX_AIO_CNT 256
-
-/*
- * Forward declarations
- */
-static Boolean_t t10_find_lun(t10_targ_impl_t *t, int lun, t10_cmd_t *);
-static void *lu_runner(void *v);
-static Boolean_t t10_lu_initialize(t10_lu_common_t *lu, char *basedir);
-static void *t10_aio_done(void *v);
-static Boolean_t lu_remove_cmds(msg_t *m, void *v);
-static void cmd_common_free(t10_cmd_t *cmd);
-static Boolean_t load_params(t10_lu_common_t *lu, char *basedir);
-static Boolean_t fallocate(int fd, off64_t len);
-static t10_cmd_state_t t10_cmd_state_machine(t10_cmd_t *c, t10_cmd_event_t e);
-static void clear_transport(transport_t t, t10_cmd_t *t10c);
-
-#ifdef FULL_DEBUG
-static char *state_to_str(t10_cmd_state_t s);
-#endif
-static char *event_to_str(t10_cmd_event_t e);
-/* ---- These are AVL comparison routines ---- */
-static int find_lu_by_num(const void *v1, const void *v2);
-static int find_lu_by_guid(const void *v1, const void *v2);
-static int find_lu_by_targ(const void *v1, const void *v2);
-static int find_cmd_by_addr(const void *v1, const void *v2);
-static sam_device_table_t sam_emul_table[];
-
-/*
- * Local variables
- */
-static avl_tree_t lu_list;
-static pthread_mutex_t lu_list_mutex;
-static int lu_id;
-target_queue_t *mgmtq;
-static pthread_mutex_t t10_mutex;
-static int t10_num;
-static sema_t t10_sema;
-static sema_t t10_aio_sema;
-
-/*
- * Constants
- */
-static const timespec_t usec = {0, 1000};
-
-/*
- * []----
- * | t10_init -- called once at the beginning of time to initialize globals
- * []----
- */
-void
-t10_init(target_queue_t *q)
-{
- pthread_t junk;
-
- mgmtq = q;
- (void) pthread_mutex_init(&lu_list_mutex, NULL);
- (void) pthread_mutex_init(&t10_mutex, NULL);
- (void) sema_init(&t10_sema, 0, USYNC_THREAD, NULL);
- (void) sema_init(&t10_aio_sema, MAX_AIO_CNT, USYNC_THREAD, NULL);
- avl_create(&lu_list, find_lu_by_guid, sizeof (t10_lu_common_t),
- offsetof(t10_lu_common_t, l_all_luns));
- (void) pthread_create(&junk, NULL, t10_aio_done, NULL);
-}
-
-/*ARGSUSED*/
-static void *
-t10_aio_done(void *v)
-{
- aio_result_t *result;
- t10_aio_t *a;
- t10_lu_impl_t *lu;
-
- do {
- if (sema_wait(&t10_sema) != 0) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "SAM- sema_wait returned error\n");
- continue;
- }
-
- if ((result = aiowait(NULL)) == (aio_result_t *)-1) {
- if (errno == EINVAL) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "SAM- aiowait returned EINVAL\n");
- continue;
- } else
- break;
- } else {
- a = (t10_aio_t *)result;
- (void) sema_post(&t10_aio_sema);
- }
- if ((a != NULL) && (a->a_aio_cmplt != NULL)) {
- lu = a->a_cmd->c_lu;
- (void) pthread_mutex_lock(&lu->l_cmd_mutex);
- if (t10_cmd_state_machine(a->a_cmd, T10_Cmd_T4) !=
- T10_Cmd_S1_Free) {
- (void) pthread_mutex_unlock(&lu->l_cmd_mutex);
- (*a->a_aio_cmplt)(a->a_id);
- } else
- (void) pthread_mutex_unlock(&lu->l_cmd_mutex);
- } else {
- queue_prt(mgmtq, Q_STE_ERRS,
- "SAM aiowait returned results, but is NULL\n");
- }
- /*CONSTANTCONDITION*/
- } while (1);
-
- return (NULL);
-}
-
-/*
- * []------------------------------------------------------------------[]
- * | Methods called by transports to interface with SAM-3 |
- * []------------------------------------------------------------------[]
- */
-
-/*
- * []----
- * | t10_handle_create -- Create the I_T nexus
- * |
- * | NOTES:
- * | max_out can be set to 0 if the transport wishes to wait for all of
- * | the data before receiving a DATAOUT message. Fibre Channel will most
- * | likely set this to 0, whereas iSCSI will set max_out to the value
- * | of MaxRecvDataSegment.
- * | (*datain_cb)() is called, on the LU thread, when the emulation
- * | module needs data *and* t10_send_cmd was called with opt_data_len, but
- * | no opt_data.
- * []----
- */
-t10_targ_handle_t
-t10_handle_create(char *targ, char *init, int trans_vers, int tpg, int max_out,
- target_queue_t *tq, void (*datain_cb)(t10_cmd_t *, char *, size_t *))
-{
- t10_targ_impl_t *t = calloc(1, sizeof (t10_targ_impl_t));
-
- if (t == NULL)
- return (NULL);
-
- (void) pthread_mutex_lock(&t10_mutex);
- t->s_targ_num = t10_num++;
- (void) pthread_mutex_unlock(&t10_mutex);
- t->s_targ_base = strdup(targ);
- t->s_i_name = strdup(init);
- t->s_trans_vers = trans_vers;
- t->s_maxout = max_out;
- t->s_to_transport = tq;
- t->s_dataout_cb = datain_cb;
-
- /*
- * Once we actually support two or more transports it would be
- * possible for a collision between the underlying transports
- * target port group values since one wouldn't necessarily know
- * anything about the other. We'll use the upper bits of the
- * target port group value to separate them.
- * If we were to support many transports and with one then running
- * out of bit space we'd need to change the allocation method. Since
- * these values aren't stored anywhere and just used by initiators
- * to determine relative path numbering there's no issue with changing
- * this later if need be.
- */
- switch (trans_vers) {
- case T10_TRANS_ISCSI:
- t->s_tpgt = 0x0000 | tpg;
- break;
-
- case T10_TRANS_FC:
- t->s_tpgt = 0x8000 | tpg;
- break;
- }
-
- avl_create(&t->s_open_lu, find_lu_by_num, sizeof (t10_lu_impl_t),
- offsetof(t10_lu_impl_t, l_open_targ_node));
-
- (void) pthread_mutex_init(&t->s_mutex, NULL);
- return ((t10_targ_handle_t)t);
-}
-
-void
-t10_handle_disable(t10_targ_handle_t tp)
-{
- t10_targ_impl_t *t = (t10_targ_impl_t *)tp;
- t10_lu_impl_t *l;
- t10_shutdown_t s;
- int lu_per_targ = 0;
-
- (void) pthread_mutex_lock(&t->s_mutex);
- if (avl_numnodes(&t->s_open_lu) != 0) {
- s.t_q = queue_alloc();
- l = avl_first(&t->s_open_lu);
- while (l != NULL) {
-
- s.t_lu = l;
- queue_message_set(l->l_common->l_from_transports, 0,
- msg_shutdown, (void *)&s);
- queue_message_free(queue_message_get(s.t_q));
- lu_per_targ++;
- l = AVL_NEXT(&t->s_open_lu, l);
- }
- queue_prt(mgmtq, Q_STE_NONIO,
- "SAM%x Sent %d shutdown requests for %s\n",
- t->s_targ_num, lu_per_targ, t->s_targ_base);
- queue_free(s.t_q, NULL);
- }
- (void) pthread_mutex_unlock(&t->s_mutex);
-}
-
-int
-t10_handle_destroy(t10_targ_handle_t tp, Boolean_t wait)
-{
- t10_targ_impl_t *t = (t10_targ_impl_t *)tp;
- t10_lu_impl_t *l;
- t10_cmd_t *c;
- t10_cmd_t *c2free;
- int fast_free = 0;
-
- (void) pthread_mutex_lock(&t->s_mutex);
- if (avl_numnodes(&t->s_open_lu) != 0) {
- while ((l = avl_first(&t->s_open_lu)) != NULL) {
-
- (void) pthread_mutex_lock(&l->l_cmd_mutex);
- if (avl_numnodes(&l->l_cmds) != 0) {
- c = avl_first(&l->l_cmds);
- while (c != NULL) {
- c2free = c;
- c = AVL_NEXT(&l->l_cmds, c);
- /*
- * Remove those commands which
- * are waiting for a response from
- * the initiator or have already
- * been canceled by the transport.
- * The initiator response won't
- * arrive since the connection
- * is shutting down. If the
- * backing store is closed, then
- * all the aio requests are
- * canceled by libaio, we can
- * free the t10_cmd in S4 or
- * S7 state.
- *
- * Other commands will be freed as
- * they are processed by the
- * transport layer or AIO.
- */
- if ((c2free->c_state ==
- T10_Cmd_S5_Wait) ||
- (c2free->c_state ==
- T10_Cmd_S6_Freeing_In)) {
- t10_aio_t *a;
-
- a = (t10_aio_t *)
- c2free->c_emul_id;
- if (a != NULL) {
- queue_prt(mgmtq,
- Q_STE_NONIO,
- "SAM%x ... "
- "S5 or S6 Cmd %p, "
- "errno/ret %d/%d\n",
- t->s_targ_num,
- c2free,
- a->a_aio.aio_errno,
- /*CSTYLED*/
- a->a_aio.aio_return);
- }
- fast_free++;
- (void) t10_cmd_state_machine(
- c2free, T10_Cmd_T8);
- } else if ((c2free->c_state ==
- T10_Cmd_S4_AIO) ||
- (c2free->c_state ==
- T10_Cmd_S7_Freeing_AIO)) {
- t10_aio_t *a;
-
- a = (t10_aio_t *)
- c2free->c_emul_id;
- if (a == NULL) {
- continue;
- } else if (a->a_aio.aio_errno ==
- ECANCELED) {
- fast_free++;
- /*
- * Note, using T5 not T8
- * because S4 + T8 = S7
- * not S1, S1 is the
- * desired result.
- */
- /*CSTYLED*/
- (void) t10_cmd_state_machine(c2free, T10_Cmd_T5);
- /*
- * Account for this cmd
- * in aio sema.
- */
- (void) sema_post(
- &t10_aio_sema);
- } else {
- queue_prt(mgmtq,
- Q_STE_NONIO,
- "SAM%x ... "
- "S4 or S7 Cmd %p, "
- "errno/ret %d/%d\n",
- t->s_targ_num,
- c2free,
- a->a_aio.aio_errno,
- /*CSTYLED*/
- a->a_aio.aio_return);
- }
- } else if (c2free->c_state ==
- T10_Cmd_S3_Trans) {
- t10_aio_t *a;
-
- a = (t10_aio_t *)
- c2free->c_emul_id;
- if (a != NULL) {
- queue_prt(mgmtq,
- Q_STE_NONIO,
- "SAM%x ... "
- "S3 Cmd %p, "
- "errno/ret %d/%d\n",
- t->s_targ_num,
- c2free,
- a->a_aio.aio_errno,
- /*CSTYLED*/
- a->a_aio.aio_return);
- }
- fast_free++;
- (void) t10_cmd_state_machine(
- c2free, T10_Cmd_T8);
- }
- }
- queue_prt(mgmtq, Q_STE_NONIO,
- "SAM%x FastFree %d ... "
- "Waiting for %d cmds to drain\n",
- t->s_targ_num, fast_free,
- avl_numnodes(&l->l_cmds));
-
- if (avl_numnodes(&l->l_cmds) != 0) {
- l->l_wait_for_drain = True;
- if (wait) {
- while (l->l_wait_for_drain ==
- True) {
- (void) pthread_cond_wait
- (&l->l_cmd_cond,
- &l->l_cmd_mutex);
- }
- assert(
- avl_numnodes(&l->l_cmds)
- == 0);
- queue_prt(mgmtq, Q_STE_NONIO,
- "SAM%x Commands drained\n",
- t->s_targ_num);
- } else {
- (void) pthread_mutex_unlock(
- &l->l_cmd_mutex);
- (void) pthread_mutex_unlock(
- &t->s_mutex);
- (void) nanosleep(&usec, 0);
- return (1);
- }
- }
- }
- avl_remove(&t->s_open_lu, l);
- avl_destroy(&l->l_cmds);
- (void) pthread_mutex_unlock(&l->l_cmd_mutex);
- free(l);
- }
- }
- avl_destroy(&t->s_open_lu);
- (void) pthread_mutex_unlock(&t->s_mutex);
-
- (void) pthread_mutex_destroy(&t->s_mutex);
- free(t->s_targ_base);
- free(t->s_i_name);
- free(t);
- return (0);
-}
-
-/*
- * []----
- * | t10_cmd_create -- creates a command pointer
- * |
- * | If an error occurs, a sense condition buffer will be created that can
- * | be sent back to the initiator. The only time this should occur is during
- * | LU setup and we've run out of resources like not having enough file
- * | descriptors to open the backing store. If the cmdp is NULL, then there's
- * | not even enough memory to create a command buffer and the transport
- * | should shutdown it's connection a cleanly as possible.
- * []----
- */
-Boolean_t
-t10_cmd_create(t10_targ_handle_t t, int lun_number, uint8_t *cdb,
- size_t cdb_len, transport_t trans_id, t10_cmd_t **cmdp)
-{
- t10_cmd_t *cmd = NULL;
-
- *cmdp = NULL;
- if (t == NULL)
- goto error;
-
- if ((cmd = umem_cache_alloc(t10_cmd_cache, UMEM_DEFAULT)) == NULL)
- goto error;
-
- bzero(cmd, sizeof (*cmd));
- if ((cmd->c_cdb = malloc(cdb_len)) == NULL)
- goto error;
-
- cmd->c_trans_id = trans_id;
- *cmdp = cmd;
- if (t10_find_lun((t10_targ_impl_t *)t, lun_number, cmd) == False)
- goto error;
-
- (void) pthread_mutex_lock(&cmd->c_lu->l_cmd_mutex);
- avl_add(&cmd->c_lu->l_cmds, (void *)cmd);
- cmd->c_state = T10_Cmd_S1_Free;
- (void) pthread_mutex_unlock(&cmd->c_lu->l_cmd_mutex);
- bcopy(cdb, cmd->c_cdb, cdb_len);
- cmd->c_cdb_len = cdb_len;
-
- return (True);
-
-error:
- if (cmd && cmd->c_cdb) {
- free(cmd->c_cdb);
- cmd->c_cdb = NULL;
- }
-
- /*
- * If we haven't set up the argument pointer, then free the memory
- * that had been allocated to the command.
- */
- if (*cmdp == NULL)
- umem_cache_free(t10_cmd_cache, cmd);
- return (False);
-}
-
-/*
- * []----
- * | t10_send_cmd -- send the given command to appropriate LUN emulation
- * |
- * | NOTE: emul_id is only provided for DATA_OUT commands (write ops)
- * | which have multiple phases to complete the request. The emulation
- * | module will provide this value when it requests more data to be
- * | sent.
- * []----
- */
-/*ARGSUSED*/
-Boolean_t
-t10_cmd_send(t10_targ_handle_t t, t10_cmd_t *cmd, char *opt_data,
- size_t opt_data_len)
-{
- if (cmd == NULL)
- return (False);
-
- cmd->c_data = opt_data;
- cmd->c_data_len = opt_data_len;
-
- t10_cmd_shoot_event(cmd, T10_Cmd_T1);
- return (True);
-}
-
-/*ARGSUSED*/
-Boolean_t
-t10_cmd_data(t10_targ_handle_t t, t10_cmd_t *cmd, size_t offset, char *data,
- size_t data_len)
-{
- if (cmd == NULL)
- return (False);
- cmd->c_data = data;
- cmd->c_data_len = data_len;
- cmd->c_offset = offset;
-
- t10_cmd_shoot_event(cmd, T10_Cmd_T4);
- return (True);
-}
-
-void
-t10_cmd_done(t10_cmd_t *cmd)
-{
- if (cmd != NULL)
- t10_cmd_shoot_event(cmd, T10_Cmd_T5);
-}
-
-/*
- * t10_cmd_state_machine -- State machine for T10 commands
- *
- * S1: Free - State on instantiation, or after successful
- * completion of command
- * S2: In - The command is currently being processed
- * by the lu_runner() thread. Memory associated
- * with the command must not be freed. Can't
- * transition directly to Free state from threads
- * other than lu_runner().
- * S3: Trans - Command has been handed off to transport layer
- * S4: AIO - Command has been sent to AIO subsystem for
- * further processing.
- * S5: Wait - Waiting for response from Initiator.
- * S6: Freeing_In - Free command while command in lu_runner.
- * S7: Freeing_AIO - Free command while command is in AIO.
- *
- * The state transition table is as follows:
- *
- * +----------+---+---+---+---+---+----+
- * |S1 |S2 |S3 |S4 |S5 |S6 |S7 |
- * ---+----------+---+---+---+---+--------+
- * S1|T4/5/6/8 |T1 | - | - | - | - | - |
- * ---+----------+---+---+---+---+--------+
- * S2|T5/8 | - |T2 |T3 |T7 |T6 | - |
- * ---+----------+---+---+---+---+--------+
- * S3|T5/8 |T4 | - | - |T7 |T6 | - |
- * ---+----------+---+---+---+---+--------+
- * S4|T5 |T4 | - | - | - | - |T6/8|
- * ---+----------+---+---+---+---+--------+
- * S5|T5/8 | - |T4 | - | - |T6 | - |
- * ---+----------+---+---+---+---+--------+
- * S6|T2/4/5/6/8| - | - | - | - | - |T3 |
- * ---+----------+---+---+---+---+--------+
- * S7|T4/5/8 | - | - | - | - | - |T6 |
- * ---+----------+---+---+---+---+--------+
- *
- * Events definitions:
- * -T1: Command has been placed on LU queue for exection.
- * -T2: Emulation completed to a point where the transport must
- * take over and send data or CDB response out.
- * -T3: Emulation requires data from storage subsystem via asynchronous
- * I/O.
- * -T4: One of the following events has caused the transition:
- * - Response from initiator to R2T request.
- * - Transport has data available to complete dataout request from T10.
- * - AIO has completed read/write op.
- * -T5: Command complete. Free resources.
- * -T6: Cancel command.
- * -T7: Transport has sent command to Initiator.
- * -T8: Shutting down, cancel or complete as appropriate
- */
-static t10_cmd_state_t
-t10_cmd_state_machine(t10_cmd_t *c, t10_cmd_event_t e)
-{
- t10_lu_impl_t *lu = c->c_lu;
-
- /* ---- Callers must already hold the mutex ---- */
- assert(pthread_mutex_trylock(&lu->l_cmd_mutex) != 0);
-
- switch (c->c_state) {
- case T10_Cmd_S1_Free:
- switch (e) {
- case T10_Cmd_T1:
- c->c_state = T10_Cmd_S2_In;
- queue_message_set(c->c_lu->l_common->l_from_transports,
- 0, msg_cmd_send, (void *)c);
- break;
-
- case T10_Cmd_T4:
- case T10_Cmd_T5:
- case T10_Cmd_T6: /* warm reset */
- case T10_Cmd_T8: /* shutdown */
- c->c_state = T10_Cmd_S1_Free;
- cmd_common_free(c);
- return (T10_Cmd_S1_Free);
-
- default:
- queue_prt(mgmtq, Q_STE_ERRS,
- "Illegal event %s on %llx\n", event_to_str(e),
- c->c_trans_id);
- assert(0);
- }
- break;
-
- case T10_Cmd_S2_In:
- switch (e) {
- case T10_Cmd_T2:
- c->c_state = T10_Cmd_S3_Trans;
- queue_message_set(c->c_lu->l_to_transport, 0,
- c->c_msg, (void *)c);
- break;
-
- case T10_Cmd_T3:
- c->c_state = T10_Cmd_S4_AIO;
- (void) sema_post(&t10_sema);
- break;
-
- case T10_Cmd_T5:
- case T10_Cmd_T8: /* shutdown */
- c->c_state = T10_Cmd_S1_Free;
- cmd_common_free(c);
- return (T10_Cmd_S1_Free);
-
- case T10_Cmd_T6:
- c->c_state = T10_Cmd_S6_Freeing_In;
- break;
-
- case T10_Cmd_T7:
- c->c_state = T10_Cmd_S5_Wait;
- break;
-
- default:
- queue_prt(mgmtq, Q_STE_ERRS,
- "SAM: Illegal event %s on %llx\n",
- event_to_str(e), c->c_trans_id);
- assert(0);
- }
- break;
-
- case T10_Cmd_S3_Trans:
- switch (e) {
- case T10_Cmd_T4:
- c->c_state = T10_Cmd_S2_In;
- queue_message_set(lu->l_common->l_from_transports, 0,
- msg_cmd_data_out, (void *)c);
- break;
-
- case T10_Cmd_T5:
- case T10_Cmd_T8: /* shutdown */
- c->c_state = T10_Cmd_S1_Free;
- cmd_common_free(c);
- return (T10_Cmd_S1_Free);
-
- case T10_Cmd_T6:
- c->c_state = T10_Cmd_S6_Freeing_In;
- break;
-
- case T10_Cmd_T7:
- c->c_state = T10_Cmd_S5_Wait;
- break;
-
- default:
- queue_prt(mgmtq, Q_STE_ERRS,
- "Illegal event %s -- %llx\n", event_to_str(e),
- c->c_trans_id);
- assert(0);
- }
- break;
-
- case T10_Cmd_S4_AIO:
- switch (e) {
- case T10_Cmd_T4:
- c->c_state = T10_Cmd_S2_In;
- break;
-
- case T10_Cmd_T5:
- c->c_state = T10_Cmd_S1_Free;
- cmd_common_free(c);
- return (T10_Cmd_S1_Free);
-
- case T10_Cmd_T6:
- case T10_Cmd_T8: /* shutdown */
- c->c_state = T10_Cmd_S7_Freeing_AIO;
- break;
-
- default:
- queue_prt(mgmtq, Q_STE_ERRS,
- "Illegal event %s -- %llx\n", event_to_str(e),
- c->c_trans_id);
- assert(0);
- }
- break;
-
- case T10_Cmd_S5_Wait:
- switch (e) {
- case T10_Cmd_T4:
- c->c_state = T10_Cmd_S3_Trans;
- break;
-
- case T10_Cmd_T5:
- case T10_Cmd_T8: /* shutdown */
- c->c_state = T10_Cmd_S1_Free;
- cmd_common_free(c);
- return (T10_Cmd_S1_Free);
-
- case T10_Cmd_T6:
- c->c_state = T10_Cmd_S6_Freeing_In;
- break;
-
- default:
- queue_prt(mgmtq, Q_STE_ERRS,
- "Illegal event %s -- %llx\n", event_to_str(e),
- c->c_trans_id);
- assert(0);
- }
- break;
-
- case T10_Cmd_S6_Freeing_In:
- switch (e) {
- case T10_Cmd_T2:
- case T10_Cmd_T4: /* AIO complete */
- case T10_Cmd_T5: /* command complete */
- case T10_Cmd_T6: /* warm reset */
- case T10_Cmd_T8: /* shutdown */
- c->c_state = T10_Cmd_S1_Free;
- cmd_common_free(c);
- return (T10_Cmd_S1_Free);
-
- case T10_Cmd_T3:
- c->c_state = T10_Cmd_S7_Freeing_AIO;
- (void) sema_post(&t10_sema);
- break;
-
- default:
- queue_prt(mgmtq, Q_STE_ERRS,
- "Illegal event %s -- %llx\n", event_to_str(e),
- c->c_trans_id);
- assert(0);
- }
- break;
-
- case T10_Cmd_S7_Freeing_AIO:
- switch (e) {
- case T10_Cmd_T4: /* AIO complete */
- case T10_Cmd_T5: /* command complete */
- case T10_Cmd_T8:
- c->c_state = T10_Cmd_S1_Free;
- cmd_common_free(c);
- return (T10_Cmd_S1_Free);
-
- case T10_Cmd_T6: /* warm reset */
- queue_prt(mgmtq, Q_GEN_DETAILS,
- "Event %s in T10_Cmd_S7_Freeing_AIO -- %llx\n",
- event_to_str(e), c->c_trans_id);
- break;
-
- default:
- queue_prt(mgmtq, Q_STE_ERRS,
- "Illegal event %s -- %llx\n", event_to_str(e),
- c->c_trans_id);
- assert(0);
- }
- break;
-
- default:
- assert(0);
- }
- return (c->c_state);
-}
-
-void
-t10_cmd_shoot_event(t10_cmd_t *c, t10_cmd_event_t e)
-{
- t10_lu_impl_t *lu;
-
- /*
- * Since the transport may or may not have called into the T10 layer
- * to allocate a command it's possible that this will be NULL. Instead
- * of requiring every caller of this function to first check if the
- * command pointer is null we'll do the check here.
- */
- if (c == NULL)
- return;
-
- lu = c->c_lu;
-
- /*
- * If t10_cmd_create() fails for some reason other than lack
- * of memory the extended status will be set for the transport
- * to send out. There will not be any LU associated with this
- * command, but the transport will still try to free it.
- */
- if (!lu) {
- assert(e == T10_Cmd_T5);
- cmd_common_free(c);
- return;
- }
-
- (void) pthread_mutex_lock(&lu->l_cmd_mutex);
- (void) t10_cmd_state_machine(c, e);
- (void) pthread_mutex_unlock(&lu->l_cmd_mutex);
-}
-
-/*
- * []----
- * | t10_task_mgmt -- handle SAM-3 task management needs
- * []----
- */
-/*ARGSUSED*/
-Boolean_t
-t10_task_mgmt(t10_targ_handle_t t1, TaskOp_t op, int opt_lun, void *tag)
-{
- t10_targ_impl_t *t = (t10_targ_impl_t *)t1;
- t10_lu_impl_t search;
- t10_lu_impl_t *lu;
-
- switch (op) {
- case InventoryChange:
- (void) pthread_mutex_lock(&t->s_mutex);
- if ((lu = avl_first(&t->s_open_lu)) != NULL) {
- do {
- /*CSTYLED*/
- queue_message_set(lu->l_common->l_from_transports,
- 0, msg_targ_inventory_change, (void *)lu);
- } while ((lu = AVL_NEXT(&t->s_open_lu, lu)) != NULL);
- }
- (void) pthread_mutex_unlock(&t->s_mutex);
- return (True);
-
- case ResetTarget:
- (void) pthread_mutex_lock(&t->s_mutex);
- if ((lu = avl_first(&t->s_open_lu)) != NULL) {
- do {
- /*CSTYLED*/
- queue_message_set(lu->l_common->l_from_transports,
- Q_HIGH, msg_reset_lu, (void *)lu);
- } while ((lu = AVL_NEXT(&t->s_open_lu, lu)) != NULL);
- (void) pthread_mutex_unlock(&t->s_mutex);
- return (True);
- } else {
- (void) pthread_mutex_unlock(&t->s_mutex);
- return (False);
- }
-
- case ResetLun:
- search.l_targ_lun = opt_lun;
- (void) pthread_mutex_lock(&t->s_mutex);
- if ((lu = avl_find(&t->s_open_lu, (void *)&search, NULL)) !=
- NULL) {
- queue_message_set(lu->l_common->l_from_transports,
- Q_HIGH, msg_reset_lu, (void *)lu);
- (void) pthread_mutex_unlock(&t->s_mutex);
- return (True);
- } else {
- (void) pthread_mutex_unlock(&t->s_mutex);
- return (False);
- }
- break;
-
- case CapacityChange:
- search.l_targ_lun = opt_lun;
- (void) pthread_mutex_lock(&t->s_mutex);
- if ((lu = avl_find(&t->s_open_lu, (void *)&search, NULL)) !=
- NULL) {
- queue_message_set(lu->l_common->l_from_transports,
- Q_HIGH, msg_lu_capacity_change,
- (void *)(uintptr_t)opt_lun);
- (void) pthread_mutex_unlock(&t->s_mutex);
- return (True);
- } else {
- (void) pthread_mutex_unlock(&t->s_mutex);
- return (False);
- }
- break;
-
- default:
- return (False);
- }
-}
-
-
-/*
- * []----
- * | t10_targ_stat -- Return stats on each LU associated with target.
- * []----
- */
-void
-t10_targ_stat(t10_targ_handle_t t1, char **buf)
-{
- t10_targ_impl_t *t = (t10_targ_impl_t *)t1;
- t10_lu_impl_t *itl;
- char lb[32];
- char *p;
-
- /*
- * It's possible for the management interfaces to request stats
- * even though a connection is not up and running.
- */
- if (t == NULL)
- return;
-
- (void) pthread_mutex_lock(&t->s_mutex);
- itl = avl_first(&t->s_open_lu);
- while (itl) {
- tgt_buf_add_tag(buf, XML_ELEMENT_LUN, Tag_Start);
- (void) snprintf(lb, sizeof (lb), "%d", itl->l_common->l_num);
- tgt_buf_add_tag(buf, lb, Tag_String);
-
- (void) snprintf(lb, sizeof (lb), "%lld", itl->l_cmds_read);
- tgt_buf_add(buf, XML_ELEMENT_READCMDS, lb);
- (void) snprintf(lb, sizeof (lb), "%lld", itl->l_cmds_write);
- tgt_buf_add(buf, XML_ELEMENT_WRITECMDS, lb);
- (void) snprintf(lb, sizeof (lb), "%lld", itl->l_sects_read);
- tgt_buf_add(buf, XML_ELEMENT_READBLKS, lb);
- (void) snprintf(lb, sizeof (lb), "%lld", itl->l_sects_write);
- tgt_buf_add(buf, XML_ELEMENT_WRITEBLKS, lb);
-
- switch (itl->l_common->l_state) {
- case lu_online:
- p = TGT_STATUS_ONLINE;
- break;
- case lu_offline:
- p = TGT_STATUS_OFFLINE;
- break;
- case lu_errored:
- p = TGT_STATUS_ERRORED;
- break;
- }
- tgt_buf_add(buf, XML_ELEMENT_STATUS, p);
-
- tgt_buf_add_tag(buf, XML_ELEMENT_LUN, Tag_End);
- itl = AVL_NEXT(&t->s_open_lu, itl);
- }
- (void) pthread_mutex_unlock(&t->s_mutex);
-}
-
-/*
- * []----
- * | t10_thick_provision -- fill the backing store with real blocks
- * |
- * | The backing store is initially created as a hole-y file. The only
- * | thing wrong with leaving the files hole-y is that if a system
- * | administrator over provisions the storage at some point a client
- * | will attempt to write to a block and receive an error unless the
- * | administrator adds more backing store before that event. Now, depending
- * | on the client a write error isn't fatal. However, for file systems
- * | like UFS and ZFS, they can not currently deal with getting a write
- * | error when it's their metadata and panic. That's not good. The concept
- * | of "Thin Provisioning" is relatively new so we'll normally preallocate
- * | the space, but have the option of doing the "Thin Provisioning".
- * []----
- */
-Boolean_t
-t10_thick_provision(char *target, int lun, target_queue_t *q)
-{
- t10_targ_handle_t t;
- t10_cmd_t *cmd = NULL;
- uint8_t cdb[16]; /* ---- fake buffer ---- */
- diskaddr_t offset = 0;
- size_t size;
- size_t sync_size;
- msg_t *m = NULL;
- target_queue_t *rq = NULL;
- char path[MAXPATHLEN];
- char *local_name;
- tgt_node_t *n1;
- Boolean_t rval = False;
- struct statvfs fs;
-
- /*
- * To guarantee that everything has been setup correctly
- * we'll just use the standard interfaces. Otherwise we'd need
- * to duplicate the code and therefore offer the chance of
- * having something fixed/change in one location that isn't
- * in another. Obvious right?
- */
- if ((t = t10_handle_create(target, "", 0, 0, 0, q, NULL)) == NULL) {
- queue_prt(mgmtq, Q_STE_ERRS, "STE%x Failed to create handle\n",
- lun);
- return (False);
- }
- if (t10_cmd_create(t, lun, cdb, sizeof (cdb), 0, &cmd) == False) {
- queue_prt(mgmtq, Q_STE_ERRS, "STE%x Failed to create cmd\n",
- lun);
- goto error;
- }
-
- /*
- * Attempt to see if there is enough space currently for the LU.
- * The initialization might still fail with out of space because someone
- * else is consuming space while the initialization is occuring.
- * Nothing we can do about that.
- */
- if (fstatvfs(cmd->c_lu->l_common->l_fd, &fs) != 0) {
- queue_prt(mgmtq, Q_STE_ERRS, "STE%x statvfs failed for LU\n",
- lun);
- goto error;
- } else if ((fs.f_frsize * fs.f_bfree) < cmd->c_lu->l_common->l_size) {
- queue_prt(mgmtq, Q_STE_ERRS, "STE%x Not enough space for LU\n",
- lun);
- goto error;
- }
-
- if (fallocate(cmd->c_lu->l_common->l_fd, cmd->c_lu->l_common->l_size) ==
- False) {
- /*
- * The lu_runner will use this buffer to copy data.
- */
- sync_size = 1024 * 1024;
- if ((cmd->c_data = malloc(sync_size)) == NULL)
- goto error;
-
- while ((offset < cmd->c_lu->l_common->l_size) && (rq == NULL)) {
- size = min(cmd->c_lu->l_common->l_size - offset,
- sync_size);
- cmd->c_offset = offset;
- cmd->c_data_len = size;
- /*CSTYLED*/
- queue_message_set(cmd->c_lu->l_common->l_from_transports, 0,
- msg_thick_provo, (void *)cmd);
- while ((m = queue_message_get(q)) != NULL) {
- switch (m->msg_type) {
- case msg_thick_provo:
- if ((int)(intptr_t)m->msg_data != 0) {
-
- /*
- * An error occurred during
- * initialization which mean we
- * need to remove this target.
- */
- queue_prt(mgmtq, Q_STE_ERRS,
- "STE%x received data "
- "error at 0x%llx\n", lun,
- offset);
- goto error;
- }
- break;
-
- case msg_shutdown:
- queue_prt(mgmtq, Q_STE_NONIO,
- "---- Thick provo got shutdown\n");
- rq = (target_queue_t *)m->msg_data;
- queue_message_free(m);
- continue; /* don't use break */
-
- default:
- assert(0);
- }
- break;
- }
- queue_message_free(m);
- offset += size;
- }
- } else {
- queue_prt(mgmtq, Q_STE_NONIO, "STE%x fallocate worked\n",
- lun);
- }
-
- /*
- * A forced shutdown is still considered a successful completion.
- * Write errors and malloc failures constitute a failure.
- */
- rval = True;
-
- /* ---- Completed successfully ---- */
- if (rq == NULL) {
-
- /*
- * Now that the initialization is complete, update the params
- * file to indicate the status is online. Once done, send a
- * message to the LU thread indicating same.
- */
- (void) snprintf(path, sizeof (path), "%s/%s/%s%d",
- target_basedir, cmd->c_lu->l_targ->s_targ_base, PARAMBASE,
- lun);
-
- cmd->c_lu->l_common->l_state = lu_online;
- if ((n1 = tgt_node_find(cmd->c_lu->l_common->l_root,
- XML_ELEMENT_STATUS)) == NULL) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "STE%x couldn't find <status>\n", lun);
- goto error;
- }
-
- if (tgt_update_value_str(n1, XML_ELEMENT_STATUS,
- TGT_STATUS_ONLINE) == False) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "STE%x Could update <status> to online\n", lun);
- goto error;
- }
-
- local_name = get_local_name(cmd->c_lu->l_targ->s_targ_base);
- if (local_name == NULL)
- goto error;
-
- (void) mgmt_param_save2scf(cmd->c_lu->l_common->l_root,
- local_name, lun);
- free(local_name);
- queue_message_set(cmd->c_lu->l_common->l_from_transports, 0,
- msg_lu_online, 0);
- }
-
-error:
- if (cmd != NULL) {
- if (cmd->c_data != NULL)
- free(cmd->c_data);
- t10_cmd_shoot_event(cmd, T10_Cmd_T5);
- }
- if (t != NULL) {
- t10_handle_disable(t);
- (void) t10_handle_destroy(t, True);
- }
- if (rq != NULL) {
- queue_message_set(rq, 0, msg_shutdown_rsp, 0);
- }
-
- return (rval);
-}
-
-/*
- * []------------------------------------------------------------------[]
- * | Methods called by emulation modules to interface with SAM-3 |
- * []------------------------------------------------------------------[]
- */
-
-/*
- * trans_cmd_dup -- Duplicate a T10 command buffer
- *
- * During read operations with transports that restrict transfer sizes the
- * emulation code has two options.
- * (1) It could transfer a chunk of data and wait until the
- * transport has sent that out. Notification coming through
- * the callback mechanism. If the command structure is not
- * duplicated it would need to wait since the command structure
- * contains the data pointer and offset values which the transport
- * needs.
- * (2) Use this routine to duplicate the command structure such
- * that the emulation layer can send all of the data in chunks
- * without waiting.
- * For obvious performance reasons it's best to send all of the chunks
- * without waiting.
- *
- * It's expected that the emulation layer will not call this routine for the
- * last outgoing packet since the command structure will not be of futher
- * use.
- */
-t10_cmd_t *
-trans_cmd_dup(t10_cmd_t *cmd)
-{
- t10_cmd_t *c;
-
- if ((c = umem_cache_alloc(t10_cmd_cache, UMEM_DEFAULT)) == NULL)
- return (NULL);
- bcopy(cmd, c, sizeof (*c));
- c->c_cmd_next = NULL;
- if ((c->c_cdb = (uint8_t *)malloc(c->c_cdb_len)) == NULL) {
- umem_cache_free(t10_cmd_cache, c);
- return (NULL);
- }
- bcopy(cmd->c_cdb, c->c_cdb, c->c_cdb_len);
-
- (void) pthread_mutex_lock(&cmd->c_lu->l_cmd_mutex);
- c->c_state = T10_Cmd_S2_In;
- avl_add(&c->c_lu->l_cmds, (void *)c);
- (void) pthread_mutex_unlock(&cmd->c_lu->l_cmd_mutex);
-
- return (c);
-}
-
-/*
- * []----
- * | trans_send_datain -- send data to transport
- * |
- * | NOTES:
- * | (1) offset is only valid when a transport has set max_out to a non-zero
- * | value.
- * | (2) The emulation code must free the memory, if it was allocated, when
- * | the transport is finished with it. The callback routine is used
- * | to provide the emulation code the notification. The callback will
- * | not be run on the same thread as the emulation code so appropriate
- * | locking may be required by the emulation code.
- * | (3) If the boolean 'last' is True it means that the transport can
- * | assume the data out is finished with a CMD_SUCCESS and no futher
- * | communication from the emulation layer will occur.
- * []----
- */
-Boolean_t
-trans_send_datain(t10_cmd_t *c, char *data, size_t data_len, size_t offset,
- void (*callback)(emul_handle_t e), Boolean_t last, emul_handle_t id)
-{
-#ifdef FULL_DEBUG
- queue_prt(mgmtq, Q_STE_IO,
- "SAM%x LUN%d DataIn 0x%x, offset 0x%x, Last %s\n",
- c->c_lu->l_targ->s_targ_num, c->c_lu->l_common->l_num,
- data_len, offset, last == True ? "true" : "false");
-#endif
-
- c->c_emul_complete = callback;
- c->c_emul_id = id;
- c->c_data = data;
- c->c_data_len = data_len;
- c->c_offset = offset;
- c->c_last = last;
- c->c_msg = msg_cmd_data_in;
-
- t10_cmd_shoot_event(c, T10_Cmd_T2);
- return (True);
-}
-
-/*
- * []----
- * | trans_rqst_dataout -- Request data from transport for command
- * |
- * | If the transport has indicated that data is immediately available,
- * | which is common for iSCSI, then we'll copy that data into the buffer
- * | and call the emulation modules datain function directly.
- * []----
- */
-Boolean_t
-trans_rqst_dataout(t10_cmd_t *cmd, char *data, size_t data_len, size_t offset,
- emul_cmd_t emul_id, void (*callback)(emul_handle_t e))
-{
- size_t max_xfer;
-
- cmd->c_emul_complete = callback;
- cmd->c_emul_id = emul_id;
-
- /*
- * Transport supports immediate data on writes. Currently
- * on the iSCSI protocol has this feature.
- * XXX Should all of this be done in the transport?
- */
- if (cmd->c_data_len) {
-#ifdef FULL_DEBUG
- queue_prt(mgmtq, Q_STE_IO,
- "SAM%x LUN%d DataOut rqst w/ immed, data_len 0x%x\n",
- cmd->c_lu->l_targ->s_targ_num,
- cmd->c_lu->l_common->l_num, data_len);
-#endif
- if (cmd->c_data == NULL) {
-
- /*
- * When there's data available, but no buffer it
- * means the transport has decided to leave the
- * data on the socket and will read it in
- * when called.
- */
- max_xfer = data_len;
- assert(cmd->c_lu->l_targ->s_dataout_cb != NULL);
- (*cmd->c_lu->l_targ->s_dataout_cb)(cmd, data,
- &max_xfer);
-
- } else {
-
- /*
- * The data is already in the command buffer so
- * we need to copy it out.
- */
- max_xfer = MIN(cmd->c_data_len - cmd->c_resid,
- data_len);
- bcopy(cmd->c_data + cmd->c_resid, data, max_xfer);
- cmd->c_resid = cmd->c_data_len - max_xfer;
-
- /*
- * It's expected since the transport allocated
- * the space, this routine will free the memory
- * instead.
- */
- (*cmd->c_lu->l_targ->s_dataout_cb)(cmd, data,
- &max_xfer);
- cmd->c_data = NULL;
-
- }
- cmd->c_data_len = 0;
- (*cmd->c_lu->l_data)(cmd, emul_id, offset, data, max_xfer);
- return (True);
- }
-
-#ifdef FULL_DEBUG
- queue_prt(mgmtq, Q_STE_IO,
- "SAM%x LUN%d DataOut Rqst data_len 0x%x\n",
- cmd->c_lu->l_targ->s_targ_num,
- cmd->c_lu->l_common->l_num, data_len);
-#endif
-
- assert(cmd->c_data == NULL);
-
- cmd->c_data = data;
- cmd->c_data_len = data_len;
- cmd->c_offset = offset;
- cmd->c_resid = 0;
-
- /*
- * Short cut. There's no reason to call the transport if the
- * emulation code hasn't requested any data. If that's the
- * case just call the emulation codes data function.
- */
- if (data_len == 0)
- (*cmd->c_lu->l_data)(cmd, emul_id, offset, data, max_xfer);
- else {
- cmd->c_msg = msg_cmd_data_rqst;
- t10_cmd_shoot_event(cmd, T10_Cmd_T2);
- }
- return (True);
-}
-
-/*
- * []----
- * | trans_send_complete -- notify transport command has finished.
- * |
- * | This routine is called either for when the emulation has completed
- * | a command which doesn't have a data in phase so we can't use the 'last'
- * | flag or there's been an error.
- * | The sense data is expected to be created by calling spc_create_sense(),
- * | the memory for that sense data will be freed when the transport calls
- * | t10_destroy_cmd().
- * |
- * | NOTE [1]: If the t10_status equals STATUS_BUSY the command queue for this
- * | ITL will be examined. If there are commands in progress the status will
- * | be changed to STATUS_QFULL
- * |
- * | NOTE [2]: Do not access 'cmd' after calling this function. The transport
- * | may receive the command, act on it, and then call
- * | t10_cmd_shoot_state(cmd, T10_Cmd_T5) before this function returns
- * | thereby allowing 'cmd' to be freed and the space reallocated.
- * []----
- */
-void
-trans_send_complete(t10_cmd_t *cmd, int t10_status)
-{
-#ifdef FULL_DEBUG
- struct scsi_extended_sense e;
-#endif
-
- (void) pthread_mutex_lock(&cmd->c_lu->l_cmd_mutex);
- /*
- * XXX Get the exact chapter and verse from the T10 documents.
- * translate a STATUS_BUSY to STATUS_QFULL if there are outstanding
- * commands in the queue.
- */
- if ((t10_status == STATUS_BUSY) &&
- (avl_numnodes(&cmd->c_lu->l_cmds) != 0)) {
- t10_status = STATUS_QFULL;
- }
- (void) pthread_mutex_unlock(&cmd->c_lu->l_cmd_mutex);
-
- cmd->c_cmd_status = t10_status;
- cmd->c_last = True;
- cmd->c_data_len = 0;
- cmd->c_data = 0;
- cmd->c_msg = msg_cmd_cmplt;
-
-#ifdef FULL_DEBUG
- if (t10_status != STATUS_GOOD) {
- if (cmd->c_cmd_sense != NULL) {
- bcopy(&cmd->c_cmd_sense[2], &e, sizeof (e));
- queue_prt(mgmtq, Q_STE_ERRS,
- "SAM%x LUN%d key_sense=0x%x, "
- "ASC=0x%x, ASCQ=0x%x\n",
- cmd->c_lu->l_targ->s_targ_num,
- cmd->c_lu->l_common->l_num,
- e.es_key, e.es_add_code, e.es_qual_code);
- } else {
- queue_prt(mgmtq, Q_STE_ERRS,
- "SAM%x LUN%d key_sense=0x%x\n",
- cmd->c_lu->l_targ->s_targ_num,
- cmd->c_lu->l_common->l_num, t10_status);
- }
- }
-#endif
-
- t10_cmd_shoot_event(cmd, T10_Cmd_T2);
-}
-
-void
-trans_aiowrite(t10_cmd_t *cmd, char *data, size_t data_len, off_t offset,
- t10_aio_t *taio)
-{
- taio->a_cmd = cmd;
-
- (void) sema_wait(&t10_aio_sema);
- (void) pthread_mutex_lock(&cmd->c_lu->l_cmd_mutex);
- if (aiowrite(cmd->c_lu->l_common->l_fd, data, data_len, offset, 0,
- &taio->a_aio) == -1) {
- (void) pthread_mutex_unlock(&cmd->c_lu->l_cmd_mutex);
- (void) sema_post(&t10_aio_sema);
- taio->a_aio.aio_return = -1;
- (*taio->a_aio_cmplt)(taio->a_id);
- } else {
- (void) t10_cmd_state_machine(cmd, T10_Cmd_T3);
- (void) pthread_mutex_unlock(&cmd->c_lu->l_cmd_mutex);
- }
-}
-
-void
-trans_aioread(t10_cmd_t *cmd, char *data, size_t data_len, off_t offset,
- t10_aio_t *taio)
-{
- taio->a_cmd = cmd;
-
- (void) sema_wait(&t10_aio_sema);
- (void) pthread_mutex_lock(&cmd->c_lu->l_cmd_mutex);
- if (aioread(cmd->c_lu->l_common->l_fd, data, data_len, offset, 0,
- &taio->a_aio) == -1) {
- (void) pthread_mutex_unlock(&cmd->c_lu->l_cmd_mutex);
- (void) sema_post(&t10_aio_sema);
- taio->a_aio.aio_return = -1;
- (*taio->a_aio_cmplt)(taio->a_id);
- } else {
- (void) t10_cmd_state_machine(cmd, T10_Cmd_T3);
- (void) pthread_mutex_unlock(&cmd->c_lu->l_cmd_mutex);
- }
-}
-
-/*
- * []----
- * | trans_params_area -- return dtype params using a command pointer
- * |
- * | Lock down the ITL structure from change so that we can cleanly access
- * | the params area. This is needed to deal with the transport closing
- * | a connection while commands are in flight. When those commands finish
- * | cleanup work needs to be done. Yet, the logical unit common area
- * | can already be released since it doesn't know there's something to wait
- * | for.
- * []----
- */
-void *
-trans_params_area(t10_cmd_t *cmd)
-{
- void *p = NULL;
-
- (void) pthread_mutex_lock(&cmd->c_lu->l_mutex);
- if (cmd->c_lu->l_common != NULL)
- p = cmd->c_lu->l_common->l_dtype_params;
- (void) pthread_mutex_unlock(&cmd->c_lu->l_mutex);
- return (p);
-}
-
-/*
- * []------------------------------------------------------------------[]
- * | Support routines for Routing and Task Management |
- * []------------------------------------------------------------------[]
- */
-
-/*
- * []----
- * | t10_find_lun -- Locate a per target LUN structure
- * |
- * | Finds per I_T_L structure. If this is the first time that this structure
- * | has been accessed we allocate the structure and add it to the global
- * | LUN structure. If that structure has never been accessed before it is
- * | created along with a thread to handle the queue.
- * []----
- */
-/*ARGSUSED*/
-static Boolean_t
-t10_find_lun(t10_targ_impl_t *t, int lun, t10_cmd_t *cmd)
-{
- t10_lu_impl_t *l = NULL;
- t10_lu_impl_t search;
- avl_index_t wc = 0; /* where common */
- avl_index_t wt = 0; /* where target */
- char *guid = NULL;
- char *str;
- char *dataset = NULL;
- char *local_name = NULL;
- t10_lu_common_t lc;
- t10_lu_common_t *common = NULL;
- tgt_node_t *n = NULL;
- tgt_node_t *n1;
- tgt_node_t *targ;
- tgt_node_t *ll;
- char path[MAXPATHLEN];
- Boolean_t okay_to_free = True;
-
- bzero(&lc, sizeof (lc));
-
- /*
- * Only l_num is used by the AVL search routines so that's
- * the only thing we'll set.
- */
- search.l_targ_lun = lun;
-
- (void) pthread_mutex_lock(&t->s_mutex);
- if ((l = avl_find(&t->s_open_lu, (void *)&search, &wt)) != NULL) {
-
- /*
- * This should be the normal fast path. At some point it
- * might be good to look at optimizing this even more.
- * If we know for example that the LUN numbers are sequential
- * and there's fewer than 64 an array of pointers would be
- * even faster than an AVL tree and not take up to much space.
- */
- cmd->c_lu = l;
- (void) pthread_mutex_unlock(&t->s_mutex);
- return (True);
- }
- (void) pthread_mutex_unlock(&t->s_mutex);
-
- /*
- * First access for this I_T_L so we need to allocate space for it.
- */
- if ((l = calloc(1, sizeof (*l))) == NULL) {
- cmd->c_cmd_status = STATUS_CHECK;
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- return (False);
- }
-
- /*
- * Initialize the various local fields. Certain fields will not be
- * initialized until we've got the common LUN pointer.
- */
- (void) pthread_mutex_init(&l->l_cmd_mutex, NULL);
- (void) pthread_mutex_init(&l->l_mutex, NULL);
- (void) pthread_cond_init(&l->l_cmd_cond, NULL);
- avl_create(&l->l_cmds, find_cmd_by_addr, sizeof (t10_cmd_t),
- offsetof(t10_cmd_t, c_cmd_avl));
-
- l->l_wait_for_drain = False;
- l->l_to_transport = t->s_to_transport;
- l->l_targ = t;
- l->l_targ_lun = lun;
-
- targ = NULL;
-
- while ((targ = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
- targ)) != NULL) {
- if ((tgt_find_value_str(targ, XML_ELEMENT_INAME, &str) ==
- True) && (strcmp(str, t->s_targ_base) == 0)) {
- local_name = strdup(targ->x_value);
- free(str);
- break;
- } else if (str) {
- free(str);
- str = NULL;
- }
- }
- if (local_name == NULL)
- goto error;
-
- if ((ll = tgt_node_next(targ, XML_ELEMENT_LUNLIST, NULL)) == NULL)
- goto error;
- n = NULL;
- while ((n = tgt_node_next(ll, XML_ELEMENT_LUN, n)) != NULL) {
- if (strtol(n->x_value, NULL, 0) == lun)
- break;
- }
- if (n == NULL) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- /* ---- ACCESS DENIED - INVALID LU IDENTIFIER ---- */
- spc_sense_ascq(cmd, 0x20, 0x9);
- goto error;
- }
-
- (void) pthread_mutex_lock(&lu_list_mutex);
-
- if (tgt_find_value_str(n, XML_ELEMENT_GUID, &guid) == False) {
- /*
- * Set the targ variable back to NULL to indicate that we don't
- * have an incore copy of the information. If the guid is 0,
- * we'll update that value and update the ZFS property if targ
- * is not NULL, otherwise will update parameter file.
- */
- targ = NULL;
-
- /*
- * To locate the common LUN structure we need to find the GUID
- * for this LUN. That's the only parsing this section of code
- * will do to the params file.
- */
-
- if (mgmt_get_param(&n, local_name, lun) == False) {
- (void) pthread_mutex_unlock(&lu_list_mutex);
- /* --- LUN no longer exists --- */
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- goto error;
- }
- okay_to_free = True;
-
- if (tgt_find_value_str(n, XML_ELEMENT_GUID, &guid) == False) {
- (void) pthread_mutex_unlock(&lu_list_mutex);
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- goto error;
- }
-
- } else
- okay_to_free = False;
-
- if ((strcmp(guid, "0") == 0) || (strcmp(guid, "0x0") == 0)) {
- free(guid);
- /*
- * Create the GUID with NAA IEEE Registered Extended
- * designator format.
- */
- if (util_create_guid(&guid, SPC_INQUIRY_ID_TYPE_NAA) == False) {
- (void) pthread_mutex_unlock(&lu_list_mutex);
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- goto error;
- }
- if ((n1 = tgt_node_find(n, XML_ELEMENT_GUID)) == NULL) {
- (void) pthread_mutex_unlock(&lu_list_mutex);
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- goto error;
- }
- if (tgt_update_value_str(n1, XML_ELEMENT_GUID, guid) == False) {
- (void) pthread_mutex_unlock(&lu_list_mutex);
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- goto error;
- }
- if (targ != NULL) {
- /*
- * Get the dataset for this shareiscsi target
- */
- if (tgt_find_value_str(targ, XML_ELEMENT_ALIAS,
- &dataset) == False) {
- (void) pthread_mutex_unlock(&lu_list_mutex);
- goto error;
- }
-
- /*
- * Set the ZFS persisted shareiscsi options
- */
- if (put_zfs_shareiscsi(dataset, targ) != ERR_SUCCESS) {
- (void) pthread_mutex_unlock(&lu_list_mutex);
- goto error;
- }
-
- free(dataset);
- dataset = NULL;
-
- } else if (mgmt_param_save2scf(n, local_name, lun) == False) {
- (void) pthread_mutex_unlock(&lu_list_mutex);
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- goto error;
- }
- }
-
- if (tgt_xml_decode(guid, &lc.l_guid, &lc.l_guid_len) == False) {
- (void) pthread_mutex_unlock(&lu_list_mutex);
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- goto error;
- }
-
- /*
- * See if the common LUN for this GUID already exists.
- */
- wc = 0;
- if ((common = avl_find(&lu_list, (void *)&lc, &wc)) == NULL) {
-
- /*
- * The GUID wasn't found, so create a new LUN structure
- * and thread.
- */
- if ((common = calloc(1, sizeof (*common))) == NULL) {
- (void) pthread_mutex_unlock(&lu_list_mutex);
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- goto error;
- }
-
- common->l_from_transports = queue_alloc();
- common->l_num = lun;
- common->l_internal_num = lu_id++;
- common->l_guid = lc.l_guid;
- common->l_guid_len = lc.l_guid_len;
- common->l_fd = -1; /* not open yet */
- common->l_mmap = MAP_FAILED;
- common->l_root = n;
- common->l_root_okay_to_free = okay_to_free;
- n = NULL;
-
- (void) pthread_mutex_init(&common->l_common_mutex, NULL);
-
- (void) snprintf(path, sizeof (path), "%s/%s", target_basedir,
- t->s_targ_base);
- if (t10_lu_initialize(common, path) == False) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "SAM%x FAILED to initialize LU %d\n",
- t->s_targ_num, lun);
- (void) pthread_mutex_unlock(&lu_list_mutex);
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- goto error;
- }
-
- avl_create(&common->l_all_open, find_lu_by_targ,
- sizeof (t10_lu_impl_t),
- offsetof(t10_lu_impl_t, l_open_lu_node));
-
- avl_insert(&lu_list, (void *)common, wc);
- (void) pthread_create(&common->l_thr_id, NULL, lu_runner,
- (void *)common);
- queue_prt(mgmtq, Q_STE_NONIO,
- "SAM%x LU[%d.%d] Created new LU thread 0x%x\n",
- t->s_targ_num, common->l_internal_num, common->l_num,
- common->l_thr_id);
-
- } else {
-
- /*
- * If there's a common LU structure already we free
- * the guid which was created for the search. If an error
- * occurs the guid space will be freed in the error handling
- * code. If a new LU is created though we don't free the guid
- * since the LU needs the information.
- */
- free(lc.l_guid);
-
- /*
- * A similar condition exists with the xml tree. If there's
- * already a common LU then this node *may* have been created
- * here if it's not a ZVOL. If it is a ZVOL tree then it will
- * have the same address as that found in l_root so don't
- * free it.
- */
- if (okay_to_free == True) {
- tgt_node_free(n);
- n = NULL;
- }
- lc.l_guid = NULL;
- queue_prt(mgmtq, Q_STE_NONIO,
- "SAM%x Found existing LU[%d.%d]\n", t->s_targ_num,
- common->l_internal_num, common->l_num);
- }
- (void) pthread_mutex_lock(&common->l_common_mutex);
- (void) avl_find(&common->l_all_open, (void *)l, &wc);
- avl_insert(&common->l_all_open, (void *)l, wc);
- (void) pthread_mutex_unlock(&common->l_common_mutex);
-
- (void) pthread_mutex_unlock(&lu_list_mutex);
-
- /*
- * Now add this I_T_L to the targets list of open LUNs so that
- * in the future we can get access through the AVL tree.
- * We wait to add the LU to the target list until now so that we don't
- * have to delete the node in case an error occurs.
- */
- (void) pthread_mutex_lock(&t->s_mutex);
- avl_insert(&t->s_open_lu, (void *)l, wt);
- (void) pthread_mutex_unlock(&t->s_mutex);
-
- (void) pthread_mutex_lock(&l->l_mutex);
- l->l_common = common;
- (void) pthread_mutex_unlock(&l->l_mutex);
-
- /*
- * The common LU thread is responsible for filling in the command
- * functions and table.
- */
- queue_message_set(common->l_from_transports, 0, msg_lu_add, (void *)l);
-
- free(guid);
- free(local_name);
-
- cmd->c_lu = l;
- return (True);
-
-error:
- cmd->c_cmd_status = STATUS_CHECK;
- if (guid)
- free(guid);
- if (n)
- tgt_node_free(n);
- if (l)
- free(l);
- if (lc.l_guid)
- free(lc.l_guid);
- if (common)
- free(common);
- if (dataset)
- free(dataset);
- return (False);
-}
-
-static Boolean_t
-t10_lu_initialize(t10_lu_common_t *lu, char *basedir)
-{
- char *str = NULL;
- int dtype;
-
- if (load_params(lu, basedir) == False)
- return (False);
-
- if (tgt_find_value_str(lu->l_root, XML_ELEMENT_DTYPE, &str) == True) {
- for (dtype = 0; sam_emul_table[dtype].t_type_name != NULL;
- dtype++) {
- if (strcmp(sam_emul_table[dtype].t_type_name,
- str) == 0) {
- lu->l_dtype = dtype;
- if ((*sam_emul_table[dtype].t_common_init)(lu)
- == False)
- goto error;
- else
- break;
- }
- }
- free(str);
- } else
- goto error;
-
- return (True);
-error:
- if (str != NULL)
- free(str);
- return (False);
-}
-
-/*
- * []----
- * | lu_runner -- The workhorse for each LU
- * |
- * | This routine is the guts of the Task Router and Task Set for SAM-3.
- * []----
- */
-static void *
-lu_runner(void *v)
-{
- t10_lu_common_t *lu = (t10_lu_common_t *)v;
- msg_t *m;
- t10_lu_impl_t *itl;
- t10_cmd_t *cmd;
- char *data;
- char *path;
- size_t data_len;
- size_t new_size;
- size_t offset;
- ssize_t cc;
- void *provo_err;
- t10_shutdown_t *s;
- t10_aio_t *a;
-
- util_title(mgmtq, Q_STE_NONIO, lu->l_internal_num, "Start LU");
-
- while ((m = queue_message_get(lu->l_from_transports)) != NULL) {
-
- switch (m->msg_type) {
- case msg_cmd_send:
- cmd = (t10_cmd_t *)m->msg_data;
-
- if (cmd->c_lu->l_status) {
- spc_sense_create(cmd, cmd->c_lu->l_status, 0);
- spc_sense_ascq(cmd, cmd->c_lu->l_asc,
- cmd->c_lu->l_ascq);
- /*
- * Clear out the per LU values before
- * calling trans_send_complete(). It's
- * possible for the transport to handle
- * this command and free it before returning.
- */
- cmd->c_lu->l_status = 0;
- cmd->c_lu->l_asc = 0;
- cmd->c_lu->l_ascq = 0;
- trans_send_complete(cmd, STATUS_CHECK);
- } else {
- lu->l_curr = cmd;
- (*cmd->c_lu->l_cmd)
- (cmd, cmd->c_cdb, cmd->c_cdb_len);
- lu->l_curr = NULL;
- }
- break;
-
- case msg_cmd_data_out:
- cmd = (t10_cmd_t *)m->msg_data;
- data = cmd->c_data;
- data_len = cmd->c_data_len;
- offset = cmd->c_offset;
-
- /*
- * We clear the c_data_len here because if the
- * emulation routine processes the data and still
- * needs more it will call trans_rqst_datain()
- * which will look at c_data_len to see if there
- * was immediate data available from the transport.
- * In this case we've already processed the data
- * and need to request more from the transport.
- * c_data is set to NULL because there's an assert
- * in trans_rqst_datain() checking that c_data is
- * indeed null.
- */
- cmd->c_data_len = 0;
- cmd->c_data = NULL;
-
- lu->l_curr = cmd;
- (*cmd->c_lu->l_data)(cmd, cmd->c_emul_id,
- offset, data, data_len);
- lu->l_curr = NULL;
- break;
-
- case msg_lu_aio_done:
- a = (t10_aio_t *)m->msg_data;
- (*a->a_aio_cmplt)(a->a_id);
- break;
-
- case msg_lu_add:
- itl = (t10_lu_impl_t *)m->msg_data;
- (*sam_emul_table[lu->l_dtype].t_per_init)(itl);
- break;
-
- case msg_reset_lu:
- (void) pthread_mutex_lock(&lu->l_common_mutex);
- itl = avl_first(&lu->l_all_open);
- while (itl != NULL) {
- /*
- * The current implementation is that we
- * have a shared queue for each LU. That means
- * if we reset a LU all I_T nexus' must
- * receive a CHECK_CONDITION on their next
- * command.
- */
- (*sam_emul_table[lu->l_dtype].t_per_fini)(itl);
- (*sam_emul_table[lu->l_dtype].t_per_init)(itl);
-
- itl = AVL_NEXT(&lu->l_all_open, itl);
- }
- (void) pthread_mutex_unlock(&lu->l_common_mutex);
- break;
-
- case msg_shutdown:
- s = (t10_shutdown_t *)m->msg_data;
-
- itl = s->t_lu;
- (void) pthread_mutex_lock(&lu_list_mutex);
- (void) pthread_mutex_lock(&lu->l_common_mutex);
- assert(avl_find(&lu->l_all_open, (void *)itl, NULL) !=
- NULL);
- queue_walker_free(lu->l_from_transports,
- lu_remove_cmds, (void *)itl);
- (*sam_emul_table[lu->l_dtype].t_per_fini)(itl);
- avl_remove(&lu->l_all_open, (void *)itl);
-
- if (avl_numnodes(&lu->l_all_open) == 0) {
- /*
- * Close backing store.
- */
- queue_prt(mgmtq, Q_STE_NONIO,
- "LU_%x No remaining targets for LU(%d)\n",
- lu->l_internal_num, lu->l_fd);
- if (lu->l_mmap != MAP_FAILED)
- (void) munmap(lu->l_mmap,
- lu->l_size);
- if (close(lu->l_fd) != 0)
- queue_prt(mgmtq, Q_STE_ERRS,
- "LU_%x Failed to close fd, "
- "errno=%d\n", lu->l_internal_num,
- errno);
- else
- lu->l_fd = -1;
- /*CSTYLED*/
- (*sam_emul_table[lu->l_dtype].t_common_fini)(lu);
-
- avl_remove(&lu_list, (void *)lu);
- util_title(mgmtq, Q_STE_NONIO,
- lu->l_internal_num, "End LU");
- queue_free(lu->l_from_transports, NULL);
- (void) pthread_mutex_unlock(
- &lu->l_common_mutex);
- (void) pthread_mutex_unlock(&lu_list_mutex);
- if (lu->l_root_okay_to_free == True)
- tgt_node_free(lu->l_root);
- free(lu->l_pid);
- free(lu->l_vid);
- free(lu->l_guid);
- free(lu);
- queue_message_free(m);
- queue_message_set(mgmtq, 0, msg_pthread_join,
- (void *)(uintptr_t)pthread_self());
- /*
- * Send the response after all the work here
- * is done.
- */
- queue_message_set(s->t_q, 0, msg_shutdown_rsp,
- (void *)(uintptr_t)itl->l_targ_lun);
- pthread_exit(NULL);
- }
- queue_message_set(s->t_q, 0, msg_shutdown_rsp,
- (void *)(uintptr_t)itl->l_targ_lun);
- (void) pthread_mutex_unlock(&lu->l_common_mutex);
- (void) pthread_mutex_unlock(&lu_list_mutex);
- break;
-
- case msg_targ_inventory_change:
- itl = (t10_lu_impl_t *)m->msg_data;
- itl->l_status = KEY_UNIT_ATTENTION;
- /*
- * SPC-3 revision 21c, section 4.5.6, Table 28
- * When LU inventory changes need to report
- * a REPORTED LUNS DATA HAS CHANGED event.
- */
- itl->l_asc = 0x3f;
- itl->l_ascq = 0x0e;
- queue_prt(mgmtq, Q_STE_NONIO,
- "LU_%x Received InventoryChange for %d\n",
- lu->l_internal_num, itl->l_common->l_num);
- break;
-
- case msg_thick_provo:
- cmd = (t10_cmd_t *)m->msg_data;
- if (lu->l_mmap != MAP_FAILED) {
-
- /*
- * If the file at c_offset is currently
- * unallocated we'll read in that buffer
- * which will be zeros and then write it
- * back out which will force the underlying
- * filesystem to allocate the blocks.
- * If someone has already issued a write
- * to this area we'll then just cause a
- * useless, but safe read/write to occur.
- */
- lu->l_curr = cmd;
- lu->l_curr_provo = True;
- bcopy((char *)lu->l_mmap + cmd->c_offset,
- cmd->c_data, cmd->c_data_len);
- cmd->c_lu->l_cmds_read++;
- cmd->c_lu->l_sects_read +=
- cmd->c_data_len / 512;
- bcopy(cmd->c_data,
- (char *)lu->l_mmap + cmd->c_offset,
- cmd->c_data_len);
- cmd->c_lu->l_cmds_write++;
- cmd->c_lu->l_sects_write +=
- cmd->c_data_len / 512;
- lu->l_curr = NULL;
- lu->l_curr_provo = False;
- provo_err = 0;
-
- } else {
- if ((cc = pread(lu->l_fd, cmd->c_data,
- cmd->c_data_len, cmd->c_offset)) < 0) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "LU_%x pread errno=%d\n",
- lu->l_num, errno);
- } else if (pwrite(lu->l_fd, cmd->c_data, cc,
- cmd->c_offset) != cc) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "LU_%x pwrite errno=%d\n",
- lu->l_num, errno);
- }
- provo_err = (cc == cmd->c_data_len) ?
- (void *)0 : (void *)1;
- }
- /*
- * acknowledge this op and wait for next
- */
- queue_message_set(cmd->c_lu->l_to_transport, 0,
- msg_thick_provo, provo_err);
- break;
-
- case msg_lu_capacity_change:
- new_size = lseek(lu->l_fd, 0, SEEK_END);
- queue_prt(mgmtq, Q_STE_NONIO,
- "LU_%x Capacity Change from 0x%llx to 0x%llx\n",
- lu->l_internal_num, lu->l_size, new_size);
- if ((path = malloc(MAXPATHLEN)) == NULL)
- break;
-
- (void) snprintf(path, MAXPATHLEN, "%s/%s",
- target_basedir, itl->l_targ->s_targ_base);
- (void) load_params(lu, path);
- free(path);
- (*sam_emul_table[lu->l_dtype].t_task_mgmt)(lu,
- CapacityChange);
- (void) pthread_mutex_lock(&lu->l_common_mutex);
- itl = avl_first(&lu->l_all_open);
- while (itl != NULL) {
- itl->l_status = KEY_UNIT_ATTENTION;
- itl->l_asc = SPC_ASC_CAP_CHANGE;
- itl->l_ascq = SPC_ASCQ_CAP_CHANGE;
- itl = AVL_NEXT(&lu->l_all_open, itl);
- }
- (void) pthread_mutex_unlock(&lu->l_common_mutex);
- break;
-
- case msg_lu_online:
- queue_prt(mgmtq, Q_STE_NONIO,
- "LU_%x Received online event\n",
- lu->l_internal_num);
- if ((path = malloc(MAXPATHLEN)) == NULL)
- break;
-
- (void) pthread_mutex_lock(&lu->l_common_mutex);
- itl = avl_first(&lu->l_all_open);
- (void) pthread_mutex_unlock(&lu->l_common_mutex);
- (void) snprintf(path, MAXPATHLEN, "%s/%s",
- target_basedir, itl->l_targ->s_targ_base);
- (void) load_params(lu, path);
- free(path);
- (*sam_emul_table[lu->l_dtype].t_task_mgmt)(lu,
- DeviceOnline);
- (void) pthread_mutex_lock(&lu->l_common_mutex);
- itl = avl_first(&lu->l_all_open);
- while (itl != NULL) {
- (*sam_emul_table[lu->l_dtype].t_per_init)(itl);
- itl = AVL_NEXT(&lu->l_all_open, itl);
- }
- (void) pthread_mutex_unlock(&lu->l_common_mutex);
- break;
-
- }
- queue_message_free(m);
- }
-
- return (NULL);
-}
-
-/*
- * []----
- * | lu_buserr_handler -- deal with SIGBUS on mmap'd files
- * |
- * | Normally SIGBUS's are a real bad thing. With this project, which uses
- * | mmap'd files that start out as hole-y, can represent more space than
- * | the underlying storage has available. This is good and considered a
- * | feature for "Thin Provisioning". However, this means that if the
- * | administrator isn't on the ball the storage can fill up. Because of the
- * | asynchronous nature of writing to a mmap'd file the OS will send a SIGBUS
- * | to the thread which caused the problem. The thread will then locate its
- * | data structure and in turn signal the initiator that a problem occurred.
- * | Since we can't restart we're we left off because the out of space
- * | condition is still present another thread is started to handle other
- * | commands for the logical unit. The current thread will then exit.
- * |
- * | NOTE:
- * | If for any reason this routine doesn't find what's it's expecting to
- * | assert() will be called to create a core. This routine will only recover
- * | from the expected case of a SIGBUS, otherwise something real bad has
- * | happened and we need to see the core.
- * []----
- */
-/*ARGSUSED*/
-void
-lu_buserr_handler(int sig, siginfo_t *sip, void *v)
-{
- t10_lu_common_t *lu;
- pthread_t id = pthread_self();
- char *fa;
-
- if (pthread_mutex_trylock(&lu_list_mutex) != 0) {
- assert(0);
- }
- lu = avl_first(&lu_list);
- while (lu != NULL) {
- if (lu->l_thr_id == id)
- break;
- lu = AVL_NEXT(&lu_list, lu);
- }
- (void) pthread_mutex_unlock(&lu_list_mutex);
-
- if ((lu == NULL) || (lu->l_curr == NULL)) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "SAM%x BUS ERROR and couldn't find logical unit\n",
- lu->l_num);
- assert(0);
-#ifdef NDEBUG
- return;
-#endif
- }
-
- if (lu->l_mmap == MAP_FAILED) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "SAM%x BUS ERROR and device not mmap'd\n", lu->l_num);
- assert(0);
-#ifdef NDEBUG
- return;
-#endif
- }
-
- fa = (char *)sip->__data.__fault.__addr;
- if ((fa < (char *)lu->l_mmap) ||
- (fa > ((char *)lu->l_mmap + lu->l_size))) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "SAM%x BUS ERROR occurred outsize of mmap bounds\n",
- lu->l_num);
- assert(0);
-#ifdef NDEBUG
- return;
-#endif
- }
-
- if (lu->l_curr_provo == True) {
- lu->l_curr_provo = False;
- queue_message_set(lu->l_curr->c_lu->l_to_transport, 0,
- msg_thick_provo, (void *)1);
- } else {
- spc_sense_create(lu->l_curr, KEY_MEDIUM_ERROR, 0);
- spc_sense_ascq(lu->l_curr, SPC_ASC_WRITE_ERROR,
- SPC_ASCQ_WRITE_ERROR);
- trans_send_complete(lu->l_curr, STATUS_CHECK);
- }
-
- queue_prt(mgmtq, Q_STE_ERRS,
- "SAM%x Caught an out-of-space issue\n", lu->l_num);
-
- /*
- * Now restart another thread to pick up where we've left off with
- * processing commands for this logical unit.
- */
- (void) pthread_create(&lu->l_thr_id, NULL, lu_runner, (void *)lu);
- pthread_exit((void *)0);
-}
-
-
-/*
- * []----
- * | lu_remove_cmds -- look for and free commands
- * []----
- */
-static Boolean_t
-lu_remove_cmds(msg_t *m, void *v)
-{
- t10_lu_impl_t *lu = (t10_lu_impl_t *)v;
- t10_cmd_t *c;
-
- switch (m->msg_type) {
- case msg_cmd_send:
- case msg_cmd_data_out:
- c = (t10_cmd_t *)m->msg_data;
- if (lu == NULL) {
- queue_prt(mgmtq, Q_STE_NONIO,
- "SAM%x canceled command during lu_remove\n",
- c->c_lu->l_targ->s_targ_num);
- t10_cmd_shoot_event(c, T10_Cmd_T6);
- return (True);
- }
- if (c->c_lu == lu) {
- queue_prt(mgmtq, Q_STE_NONIO,
- "SAM%x LUN %d, removed command during lu_remove\n",
- c->c_lu->l_targ->s_targ_num, lu->l_common->l_num);
- t10_cmd_shoot_event(c, T10_Cmd_T5);
- return (True);
- }
- break;
- }
- return (False);
-}
-
-/*
- * []----
- * | load_params -- load parameters and open LU backing store
- * |
- * | This routine can be called multiple times and will free and release
- * | previous resources.
- * []----
- */
-static Boolean_t
-load_params(t10_lu_common_t *lu, char *basedir)
-{
- char file[MAXPATHLEN];
- char *str;
- int oflags = O_RDWR|O_LARGEFILE|O_NDELAY;
- Boolean_t mmap_lun = False;
- tgt_node_t *node = NULL;
- int version_maj = XML_VERS_LUN_MAJ;
- int version_min = XML_VERS_LUN_MIN;
-
- /*
- * Clean up from previous call to this function. This occurs if
- * the LU has grown since it was last opened.
- */
- if (lu->l_mmap != MAP_FAILED)
- (void) munmap(lu->l_mmap, lu->l_size);
- if (lu->l_fd != -1) {
- (void) close(lu->l_fd);
- lu->l_fd = -1;
- }
-
- node = lu->l_root;
-
- if (validate_version(node, &version_maj, &version_min) == False)
- (void) fprintf(stderr, "Failed version check\n");
-
- if (tgt_find_value_str(node, XML_ELEMENT_PID, &lu->l_pid) == False)
- goto error;
-
- if (tgt_find_value_str(node, XML_ELEMENT_VID, &lu->l_vid) == False)
- goto error;
-
- /*
- * If there's no <status> tag it just means this is an older param
- * file and there's no need to treat it as an error. Just mark
- * the device as online.
- */
- if (tgt_find_value_str(node, XML_ELEMENT_STATUS, &str) == True) {
- if (strcmp(str, TGT_STATUS_ONLINE) == 0)
- lu->l_state = lu_online;
- else if (strcmp(str, TGT_STATUS_OFFLINE) == 0)
- lu->l_state = lu_offline;
- else if (strcmp(str, TGT_STATUS_ERRORED) == 0)
- lu->l_state = lu_errored;
- free(str);
- } else
- lu->l_state = lu_online;
-
- /*
- * If offline, we need to check to see if there's an initialization
- * thread running for this lun. If not, start one.
- */
- if ((lu->l_state == lu_offline) &&
- (thick_provo_chk_thr(strrchr(basedir, '/') + 1, lu->l_num) ==
- False)) {
- queue_prt(mgmtq, Q_STE_NONIO,
- "LU_%d No initialization thread running\n", lu->l_num);
- if (thin_provisioning == False) {
- thick_provo_t *tp;
- pthread_t junk;
-
- if ((tp = calloc(1, sizeof (*tp))) != NULL) {
- tp->targ_name = strdup(strrchr(basedir, '/')) +
- 1;
- tp->lun = lu->l_num;
- tp->q = queue_alloc();
- (void) pthread_create(&junk, NULL,
- thick_provo_start, tp);
- /* ---- wait for start message ---- */
- queue_message_free(queue_message_get(tp->q));
- }
- }
- }
-
- /*
- * The default is to disable the fast write acknowledgement which
- * can be overridden in a couple of ways. First, see if the global
- * fast-write-ack is enabled, then check the per logical unit flags.
- * The per LU bit is settable via a SCSI command.
- */
- lu->l_fast_write_ack = False;
- (void) tgt_find_value_boolean(main_config, XML_ELEMENT_FAST,
- &lu->l_fast_write_ack);
- (void) tgt_find_value_boolean(node, XML_ELEMENT_FAST,
- &lu->l_fast_write_ack);
- if (lu->l_fast_write_ack == False)
- oflags |= O_SYNC;
-
- /*
- * Object-based Storage Devices currently use directories to
- * represent the partitions and files in those directories to
- * represent user objects and collections. Therefore, there's
- * not just a single file to be opened, but potentially thousands.
- * Therefore, stop here if we've got an OSD dtype.
- */
- if (tgt_find_value_str(node, XML_ELEMENT_DTYPE, &str) == False)
- goto error;
- if (strcmp(str, TGT_TYPE_OSD) == 0) {
- free(str);
- return (True);
- } else
- free(str);
-
- if (tgt_find_value_str(node, XML_ELEMENT_BACK, &str) == True) {
- lu->l_fd = open(str, oflags);
- free(str);
- if (lu->l_fd == -1)
- goto error;
- } else {
- (void) snprintf(file, sizeof (file), "%s/%s%d", basedir,
- LUNBASE, lu->l_num);
- if ((lu->l_fd = open(file, oflags)) == -1)
- goto error;
- }
-
- (void) tgt_find_value_boolean(node, XML_ELEMENT_MMAP_LUN, &mmap_lun);
- if (tgt_find_value_str(node, XML_ELEMENT_SIZE, &str) == True) {
- lu->l_size = strtoll(str, NULL, 0) * 512LL;
- free(str);
- } else
- goto error;
-
- if (mmap_lun == True) {
- /*
- * st_size will be wrong if the device is a block device
- * but that's okay since you can't mmap in a block device.
- * A block device will fall back to using AIO operations.
- */
- lu->l_mmap = mmap(0, lu->l_size, PROT_READ|PROT_WRITE,
- MAP_SHARED|MAP_ALIGN, lu->l_fd, 0);
- } else {
- lu->l_mmap = MAP_FAILED;
- }
- return (True);
-error:
- if (lu->l_pid) {
- free(lu->l_pid);
- lu->l_pid = NULL;
- }
- if (lu->l_vid) {
- free(lu->l_vid);
- lu->l_vid = NULL;
- }
- if (lu->l_fd != -1) {
- (void) close(lu->l_fd);
- lu->l_fd = -1;
- }
- return (False);
-}
-
-/*
- * []----
- * | cmd_common_free -- frees data stored in the cmd
- * |
- * | NOTE: The mutex which protects c_state must be held when this routine
- * | is called if there's a LU associated with this command.
- * []----
- */
-static void
-cmd_common_free(t10_cmd_t *c)
-{
- t10_lu_impl_t *lu = c->c_lu;
-
- if (lu) {
- assert(pthread_mutex_trylock(&lu->l_cmd_mutex) != 0);
- /* command might be removed by t10_handle_destroy */
- if (avl_find(&lu->l_cmds, c, NULL) == NULL)
- return;
- avl_remove(&lu->l_cmds, c);
- }
-
- c->c_state = T10_Cmd_S1_Free;
- c->c_data = 0;
- c->c_data_len = 0;
-
- clear_transport(c->c_trans_id, c);
-
- if (c->c_emul_complete != NULL) {
- (*c->c_emul_complete)(c->c_emul_id);
- c->c_emul_complete = NULL;
- }
- if (c->c_cdb) {
- free(c->c_cdb);
- c->c_cdb = NULL;
- }
- if (c->c_cmd_sense) {
- free(c->c_cmd_sense);
- c->c_cmd_sense = NULL;
- }
- if (lu && (lu->l_wait_for_drain == True) &&
- (avl_numnodes(&lu->l_cmds) == 0)) {
- lu->l_wait_for_drain = False;
- (void) pthread_cond_signal(&lu->l_cmd_cond);
- }
- umem_cache_free(t10_cmd_cache, c);
-}
-
-/*
- * clear_transport -- Remove the transports reference to the T10 command
- *
- * This should be a function pointer stored in the t10_lu_impl structure.
- * The only reason it's not, is I wish to wait until we know a little more
- * about the FC transport. There may be some other callbacks required for that
- * transport and if so, I'll need to define a new method for passing in
- * the callbacks to the t10_create_handle. The easiest way would probably
- * have a structure. I'm concerned about supporting different versions, so
- * wish to think about it some more before implementing.
- *
- * This function can be called on either the transport thread or the t10
- * thread.
- */
-static void
-clear_transport(transport_t t, t10_cmd_t *t10c)
-{
- iscsi_cmd_t *c = (iscsi_cmd_t *)t;
-
- if (c) {
- if (c->c_t10_dup != 0) {
- c->c_t10_dup--;
- }
- if (c->c_t10_cmd != NULL) {
- /*
- * Find and unlink the cmd to be freed.
- * The last entry's next ptr is NULL.
- */
- if (c->c_t10_cmd == t10c) {
- c->c_t10_cmd = t10c->c_cmd_next;
- } else {
- t10_cmd_t *t10cnxt = c->c_t10_cmd;
- while (t10cnxt->c_cmd_next != NULL) {
- if (t10cnxt->c_cmd_next == t10c) {
- t10cnxt->c_cmd_next =
- t10c->c_cmd_next;
- break;
- }
- t10cnxt = t10cnxt->c_cmd_next;
- }
- }
- }
- }
-}
-
-/*
- * []----
- * | fallocate -- allocate blocks for file via file system interface
- * |
- * | This is a faster approach to allocating the blocks for a file.
- * | Instead of reading and then writing each block which will force the
- * | file system to allocate the data we simply ask the file system to
- * | allocate the space. Unfortunately not all file systems support this
- * | feature.
- * []----
- */
-static Boolean_t
-fallocate(int fd, off64_t len)
-{
-#ifdef FALLOCATE_SUPPORTED
-#if defined(_LARGEFILE64_SOURCE) && !defined(_LP64)
- struct flock64 lck;
-
- lck.l_whence = 0;
- lck.l_start = 0;
- lck.l_len = len;
- lck.l_type = F_WRLCK;
-
- if (fcntl(fd, F_ALLOCSP64, &lck) == -1)
- return (False);
- else
- return (True);
-#else
- struct flock lck;
-
- lck.l_whence = 0;
- lck.l_start = 0;
- lck.l_len = len;
- lck.l_type = F_WRLCK;
-
- if (fcntl(fd, F_ALLOCSP, &lck) == -1)
- return (False);
- else
- return (True);
-#endif
-#else
- return (False);
-#endif
-}
-
-/*
- * []----
- * | find_lu_by_num -- AVL comparison which looks at LUN
- * []----
- */
-static int
-find_lu_by_num(const void *v1, const void *v2)
-{
- t10_lu_impl_t *l1 = (t10_lu_impl_t *)v1;
- t10_lu_impl_t *l2 = (t10_lu_impl_t *)v2;
-
- if (l1->l_targ_lun < l2->l_targ_lun)
- return (-1);
- if (l1->l_targ_lun > l2->l_targ_lun)
- return (1);
- return (0);
-}
-
-/*
- * []----
- * | find_lu_by_guid -- AVL comparison which looks at GUID
- * []----
- */
-static int
-find_lu_by_guid(const void *v1, const void *v2)
-{
- t10_lu_common_t *l1 = (t10_lu_common_t *)v1;
- t10_lu_common_t *l2 = (t10_lu_common_t *)v2;
- int i;
-
- if (l1->l_guid_len != l2->l_guid_len) {
- return ((l1->l_guid_len < l2->l_guid_len) ? -1 : 1);
- }
- for (i = 0; i < l1->l_guid_len; i++) {
- if (l1->l_guid[i] != l2->l_guid[i]) {
- return ((l1->l_guid[i] < l2->l_guid[i]) ? -1 : 1);
- }
- }
- return (0);
-}
-
-/*
- * []----
- * | find_lu_by_targ -- AVL comparison which looks at the target
- * |
- * | NOTE:
- * | The target value is the memory address of the per target structure.
- * | Therefore, it's not persistent in any manner, nor can any association
- * | be made between the target value and the initiator. It will be unique
- * | however which is all that we're looking for.
- * []----
- */
-static int
-find_lu_by_targ(const void *v1, const void *v2)
-{
- t10_lu_impl_t *l1 = (t10_lu_impl_t *)v1;
- t10_lu_impl_t *l2 = (t10_lu_impl_t *)v2;
-
- if ((uint64_t)(uintptr_t)l1->l_targ < (uint64_t)(uintptr_t)l2->l_targ)
- return (-1);
- else if ((uint64_t)(uintptr_t)l1->l_targ >
- (uint64_t)(uintptr_t)l2->l_targ)
- return (1);
- else
- return (0);
-}
-
-/*
- * []----
- * | find_cmd_by_addr -- AVL comparison using the simplist of methods
- * []----
- */
-static int
-find_cmd_by_addr(const void *v1, const void *v2)
-{
- uint64_t cmd1 = (uint64_t)(uintptr_t)v1;
- uint64_t cmd2 = (uint64_t)(uintptr_t)v2;
-
- if (cmd1 < cmd2)
- return (-1);
- else if (cmd1 > cmd2)
- return (1);
- else
- return (0);
-}
-
-/*ARGSUSED*/
-static Boolean_t
-sam_common_init(t10_lu_common_t *t)
-{
- assert(0);
- return (False);
-}
-
-/*ARGSUSED*/
-static void
-sam_common_fini(t10_lu_common_t *t)
-{
- assert(0);
-}
-
-#ifdef FULL_DEBUG
-static char *
-state_to_str(t10_cmd_state_t s)
-{
- switch (s) {
- case T10_Cmd_S1_Free: return ("FREE");
- case T10_Cmd_S2_In: return ("IN");
- case T10_Cmd_S3_Trans: return ("TRANS");
- case T10_Cmd_S4_AIO: return ("AIO");
- case T10_Cmd_S5_Wait: return ("WAIT");
- case T10_Cmd_S6_Freeing_In: return ("FREEING_IN");
- case T10_Cmd_S7_Freeing_AIO: return ("FREEING_AIO");
- }
- return ("Invalid State");
-}
-#endif
-
-static char *
-event_to_str(t10_cmd_event_t e)
-{
- switch (e) {
- case T10_Cmd_T1: return ("T1");
- case T10_Cmd_T2: return ("T2");
- case T10_Cmd_T3: return ("T3");
- case T10_Cmd_T4: return ("T4");
- case T10_Cmd_T5: return ("T5");
- case T10_Cmd_T6: return ("T6");
- case T10_Cmd_T7: return ("T7");
- }
- return ("Invalid Event");
-}
-
-/*ARGSUSED*/
-static void
-sam_per_init(t10_lu_impl_t *t)
-{
- assert(0);
-}
-
-/*ARGSUSED*/
-static void
-sam_per_fini(t10_lu_impl_t *t)
-{
- assert(0);
-}
-
-/*ARGSUSED*/
-static void
-sam_task_mgmt(t10_lu_common_t *t, TaskOp_t op)
-{
- assert(0);
-}
-
-static sam_device_table_t sam_emul_table[] = {
- /* 0x00: DTYPE_DIRECT */
- { sbc_common_init, sbc_common_fini, sbc_per_init, sbc_per_fini,
- sbc_task_mgmt, TGT_TYPE_DISK },
- /* 0x01: DTYPE_SEQUENTIAL */
- { ssc_common_init, ssc_common_fini, ssc_per_init, ssc_per_fini,
- ssc_task_mgmt, TGT_TYPE_TAPE },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- /* 0x11: DTYPE_OSD */
- { osd_common_init, osd_common_fini, osd_per_init, osd_per_fini,
- osd_task_mgmt, TGT_TYPE_OSD },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini,
- sam_task_mgmt, TGT_TYPE_INVALID },
- /* 0x1f: DTYPE_UNKNOWN */
- { raw_common_init, raw_common_fini, raw_per_init, raw_per_fini,
- raw_task_mgmt, TGT_TYPE_RAW },
- /* End-of-Table marker */
- { 0, 0, 0, 0, 0, NULL }
-};
diff --git a/usr/src/cmd/iscsi/iscsitgtd/t10_sbc.c b/usr/src/cmd/iscsi/iscsitgtd/t10_sbc.c
deleted file mode 100644
index 33f0da46e2..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_sbc.c
+++ /dev/null
@@ -1,2311 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * []------------------------------------------------------------------[]
- * | Implementation of SBC-2 emulation |
- * []------------------------------------------------------------------[]
- */
-#include <sys/types.h>
-#include <aio.h>
-#include <sys/asynch.h>
-#include <sys/mman.h>
-#include <stddef.h>
-#include <strings.h>
-#include <unistd.h>
-#include <assert.h>
-
-#include <sys/scsi/generic/sense.h>
-#include <sys/scsi/generic/status.h>
-#include <sys/scsi/generic/inquiry.h>
-#include <sys/scsi/generic/commands.h>
-#include <sys/scsi/generic/mode.h>
-#include <sys/scsi/generic/dad_mode.h>
-
-#include "t10.h"
-#include "t10_spc.h"
-#include "t10_spc_pr.h"
-#include "t10_sbc.h"
-#include "utility.h"
-
-/*
- * External declarations
- */
-void sbc_cmd(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
-void spc_cmd_reserve6(t10_cmd_t *, uint8_t *, size_t);
-void spc_cmd_release6(t10_cmd_t *, uint8_t *, size_t);
-void spc_cmd_pr_in(t10_cmd_t *, uint8_t *, size_t);
-void spc_cmd_pr_out(t10_cmd_t *, uint8_t *, size_t);
-void spc_cmd_pr_out_data(t10_cmd_t *, emul_handle_t, size_t, char *, size_t);
-void spc_pr_read(t10_cmd_t *);
-Boolean_t spc_pgr_check(t10_cmd_t *, uint8_t *);
-Boolean_t spc_npr_check(t10_cmd_t *, uint8_t *);
-
-/*
- * Forward declarations
- */
-static int sbc_mmap_overlap(const void *v1, const void *v2);
-static void sbc_overlap_store(disk_io_t *io);
-static void sbc_overlap_free(disk_io_t *io);
-static void sbc_overlap_check(disk_io_t *io);
-static void sbc_overlap_flush(disk_params_t *d);
-static void sbc_data(t10_cmd_t *cmd, emul_handle_t e, size_t offset,
- char *data, size_t data_len);
-static disk_io_t *sbc_io_alloc(t10_cmd_t *c);
-static void sbc_io_free(emul_handle_t e);
-static void sbc_read_cmplt(emul_handle_t e);
-static void sbc_write_cmplt(emul_handle_t e);
-static void sbc_read_capacity16(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
-static char *sense_page3(disk_params_t *d, char *buf, uint8_t pc);
-static char *sense_page4(disk_params_t *d, char *buf, uint8_t pc);
-static char *sense_cache(disk_params_t *d, char *buf, uint8_t pc);
-static char *sense_mode_control(t10_lu_impl_t *lu, char *buf, uint8_t pc);
-static char *sense_info_ctrl(char *buf, uint8_t pc);
-static scsi_cmd_table_t lba_table[];
-
-static long sbc_page_size;
-/*
- * []----
- * | sbc_init_common -- Initialize LU data which is common to all I_T_Ls
- * []----
- */
-Boolean_t
-sbc_common_init(t10_lu_common_t *lu)
-{
- disk_params_t *d;
- tgt_node_t *node = lu->l_root;
-
- sbc_page_size = sysconf(_SC_PAGESIZE);
-
- if ((d = (disk_params_t *)calloc(1, sizeof (*d))) == NULL)
- return (False);
-
- (void) tgt_find_value_int(node, XML_ELEMENT_BPS,
- (int *)&d->d_bytes_sect);
- (void) tgt_find_value_int(node, XML_ELEMENT_HEADS,
- (int *)&d->d_heads);
- (void) tgt_find_value_int(node, XML_ELEMENT_SPT,
- (int *)&d->d_spt);
- (void) tgt_find_value_int(node, XML_ELEMENT_CYLINDERS,
- (int *)&d->d_cyl);
- (void) tgt_find_value_int(node, XML_ELEMENT_RPM,
- (int *)&d->d_rpm);
- (void) tgt_find_value_int(node, XML_ELEMENT_INTERLEAVE,
- (int *)&d->d_interleave);
- d->d_fast_write = lu->l_fast_write_ack;
- d->d_size = lu->l_size / (uint64_t)d->d_bytes_sect;
- d->d_state = lu->l_state;
-
- avl_create(&d->d_mmap_overlaps, sbc_mmap_overlap,
- sizeof (disk_io_t), offsetof(disk_io_t, da_mmap_overlap));
- (void) pthread_mutex_init(&d->d_mutex, NULL);
- (void) pthread_cond_init(&d->d_mmap_cond, NULL);
- (void) pthread_cond_init(&d->d_io_cond, NULL);
- if ((d->d_io_reserved = (disk_io_t *)calloc(1, sizeof (disk_io_t))) ==
- NULL) {
- free(d);
- return (False);
- }
-
- lu->l_dtype_params = (void *)d;
- return (True);
-}
-
-void
-sbc_common_fini(t10_lu_common_t *lu)
-{
- disk_params_t *d = lu->l_dtype_params;
-
- sbc_overlap_flush(d);
- avl_destroy(&d->d_mmap_overlaps);
- free(d->d_io_reserved);
- free(lu->l_dtype_params);
-}
-
-void
-sbc_task_mgmt(t10_lu_common_t *lu, TaskOp_t op)
-{
- disk_params_t *d = (disk_params_t *)lu->l_dtype_params;
-
- switch (op) {
- case CapacityChange:
- d->d_size = lu->l_size / (uint64_t)d->d_bytes_sect;
- break;
-
- case DeviceOnline:
- d->d_state = lu->l_state;
- break;
- }
-}
-
-/*
- * []----
- * | sbc_init_per -- Initialize per I_T_L information
- * []----
- */
-void
-sbc_per_init(t10_lu_impl_t *itl)
-{
- disk_params_t *d = (disk_params_t *)itl->l_common->l_dtype_params;
-
- if (d->d_state == lu_online) {
- itl->l_cmd = sbc_cmd;
- itl->l_pgr_read = False; /* Look for PGR data */
- }
- else
- itl->l_cmd = spc_cmd_offline;
- itl->l_data = sbc_data;
- itl->l_cmd_table = lba_table;
-}
-
-void
-sbc_per_fini(t10_lu_impl_t *itl)
-{
-}
-
-/*
- * []----
- * | sbc_cmd -- start a SCSI command
- * |
- * | This routine is called from within the SAM-3 Task router.
- * []----
- */
-void
-sbc_cmd(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- scsi_cmd_table_t *e;
-
- /*
- * Determine if there is persistent data for this I_T_L Nexus
- */
- if (cmd->c_lu->l_pgr_read == False) {
- spc_pr_read(cmd);
- cmd->c_lu->l_pgr_read = True;
- }
-
- e = &cmd->c_lu->l_cmd_table[cdb[0]];
-#ifdef FULL_DEBUG
- queue_prt(mgmtq, Q_STE_IO, "SBC%x LUN%d Cmd %s id=%p\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- e->cmd_name == NULL ? "(no name)" : e->cmd_name, cmd->c_trans_id);
-#endif
- (*e->cmd_start)(cmd, cdb, cdb_len);
-}
-
-/*
- * []----
- * | sbc_cmd_reserve -- Run commands when another I_T_L has a reservation
- * []----
- */
-void
-sbc_cmd_reserved(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd);
- sbc_reserve_t *res = &p->d_sbc_reserve;
- Boolean_t conflict = False;
-
- /*
- * SPC-3, revision 23, Table 31
- * SPC commands that are allowed in the presence of various reservations
- */
- switch (cdb[0]) {
- case SCMD_INQUIRY:
- case SCMD_LOG_SENSE_G1:
- case SCMD_REPORT_LUNS:
- case SCMD_REQUEST_SENSE:
- case SCMD_MAINTENANCE_IN: /* REPORT TARGET PORT GROUPS (A3h/0Ah) */
- case SCMD_SVC_ACTION_IN_G5: /* READ MEDIA SERIAL NUMBER (ABh) */
- break;
- default:
- (void) pthread_rwlock_rdlock(&res->res_rwlock);
- switch (res->res_type) {
- case RT_NONE:
- /* conflict = False; */
- break;
- case RT_PGR:
- conflict = spc_pgr_check(cmd, cdb);
- break;
- case RT_NPR:
- conflict = spc_npr_check(cmd, cdb);
- break;
- default:
- conflict = True;
- break;
- }
- (void) pthread_rwlock_unlock(&res->res_rwlock);
- }
-
- queue_prt(mgmtq, Q_PR_IO,
- "PGR%x LUN%d CDB:%s - sbc_cmd_reserved(%s:%s)\n",
- cmd->c_lu->l_targ->s_targ_num,
- cmd->c_lu->l_common->l_num,
- cmd->c_lu->l_cmd_table[cmd->c_cdb[0]].cmd_name == NULL
- ? "(no name)"
- : cmd->c_lu->l_cmd_table[cmd->c_cdb[0]].cmd_name,
- res->res_type == RT_PGR ? "PGR" :
- res->res_type == RT_NPR ? "NPR" :
- res->res_type == RT_NONE ? "" : "unknown",
- conflict ? "Conflict" : "Allowed");
-
- /*
- * If no conflict at this point, allow command
- */
- if (conflict == False) {
- sbc_cmd(cmd, cdb, cdb_len);
- } else {
- trans_send_complete(cmd, STATUS_RESERVATION_CONFLICT);
- }
-}
-
-/*
- * []----
- * | sbc_data -- Data phase for command.
- * |
- * | Normally this is only called for the WRITE command. Other commands
- * | that have a data in phase will probably be short circuited when
- * | we call trans_rqst_dataout() and the data is already available.
- * | At least this is true for iSCSI. FC however will need a DataIn phase
- * | for commands like MODE SELECT and PGROUT.
- * []----
- */
-static void
-sbc_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset, char *data,
- size_t data_len)
-{
- scsi_cmd_table_t *e;
-
- e = &cmd->c_lu->l_cmd_table[cmd->c_cdb[0]];
-#ifdef FULL_DEBUG
- queue_prt(mgmtq, Q_STE_IO, "SBC%x LUN%d Data %s id=%p\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- e->cmd_name, cmd->c_trans_id);
-#endif
- if (*e->cmd_data != NULL)
- (*e->cmd_data)(cmd, id, offset, data, data_len);
-}
-
-/*
- * []------------------------------------------------------------------[]
- * | SCSI Block Commands - 2 |
- * | T10/1417-D |
- * | The following functions implement the emulation of SBC-2 type |
- * | commands. |
- * []------------------------------------------------------------------[]
- */
-
-/*
- * []----
- * | sbc_read -- emulation of SCSI READ command
- * []----
- */
-/*ARGSUSED*/
-static void
-sbc_read(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- /*LINTED*/
- union scsi_cdb *u = (union scsi_cdb *)cdb;
- diskaddr_t addr;
- off_t offset = 0;
- uint32_t cnt;
- uint32_t min;
- disk_io_t *io;
- void *mmap_data = T10_MMAP_AREA(cmd);
- uint64_t err_blkno;
- disk_params_t *d;
- uchar_t addl_sense_len;
- t10_cmd_t *c;
- iscsi_cmd_t *iscsi = (iscsi_cmd_t *)T10_TRANS_ID(cmd);
-
- if ((d = (disk_params_t *)T10_PARAMS_AREA(cmd)) == NULL) {
- trans_send_complete(cmd, STATUS_BUSY);
- return;
- }
-
- switch (u->scc_cmd) {
- case SCMD_READ:
- /*
- * SBC-2 Revision 16, section 5.5
- * Reserve bit checks
- */
- if ((cdb[1] & 0xe0) || SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- addr = (diskaddr_t)(uint32_t)GETG0ADDR(u);
- cnt = GETG0COUNT(u);
-
- /*
- * SBC-2 Revision 16
- * Section: 5.5 READ(6) command
- * A TRANSFER LENGTH field set to zero specifies
- * that 256 logical blocks shall be read.
- */
- if (cnt == 0)
- cnt = 256;
- break;
-
- case SCMD_READ_G1:
- /*
- * SBC-2 Revision 16, section 5.6
- * Reserve bit checks.
- */
- if ((cdb[1] & 6) || cdb[6] ||
- SAM_CONTROL_BYTE_RESERVED(cdb[9])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- addr = (diskaddr_t)(uint32_t)GETG1ADDR(u);
- cnt = GETG1COUNT(u);
- break;
-
- case SCMD_READ_G4:
- /*
- * SBC-2 Revision 16, section 5.8
- * Reserve bit checks
- */
- if ((cdb[1] & 0x6) || cdb[14] ||
- SAM_CONTROL_BYTE_RESERVED(cdb[15])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- addr = GETG4LONGADDR(u);
- cnt = GETG4COUNT(u);
- break;
-
- default:
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- if ((addr + cnt) > d->d_size) {
-
- if (addr > d->d_size)
- err_blkno = addr;
- else
- err_blkno = d->d_size;
-
- if (err_blkno > FIXED_SENSE_ADDL_INFO_LEN)
- addl_sense_len = INFORMATION_SENSE_DESCR;
- else
- addl_sense_len = 0;
-
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, addl_sense_len);
- spc_sense_info(cmd, err_blkno);
- spc_sense_ascq(cmd, SPC_ASC_BLOCK_RANGE, SPC_ASCQ_BLOCK_RANGE);
- trans_send_complete(cmd, STATUS_CHECK);
-
- queue_prt(mgmtq, Q_STE_ERRS,
- "SBC%x LUN%d READ Illegal sector "
- "(0x%llx + 0x%x) > 0x%ullx\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- addr, cnt, d->d_size);
- return;
- }
-
- cmd->c_lu->l_cmds_read++;
- cmd->c_lu->l_sects_read += cnt;
-
- if (cnt == 0) {
- trans_send_complete(cmd, STATUS_GOOD);
- return;
- }
-
- do {
- min = MIN((cnt * 512) - offset, T10_MAX_OUT(cmd));
- if ((offset + min) < (cnt * 512LL)) {
- c = trans_cmd_dup(cmd);
- /* dup failed, just finish the original command */
- if (c == NULL) {
- c = cmd;
- offset = (cnt * 512);
- }
- } else {
- c = cmd;
- }
-
- (void) pthread_mutex_lock(&cmd->c_lu->l_cmd_mutex);
- /* dup count include the original cmd */
- iscsi->c_t10_dup++;
-
- /*
- * Add the cmd to the list of t10 cmds for this iscsi cmd.
- * But don't add the original t10 cmd twice.
- */
- if (c != cmd) {
- c->c_cmd_next = iscsi->c_t10_cmd;
- iscsi->c_t10_cmd = c;
- }
- (void) pthread_mutex_unlock(&cmd->c_lu->l_cmd_mutex);
-
- io = sbc_io_alloc(c);
-
- io->da_lba = addr;
- io->da_lba_cnt = cnt;
- io->da_offset = offset;
- io->da_data_len = min;
-
-#ifdef FULL_DEBUG
- queue_prt(mgmtq, Q_STE_IO,
- "SBC%x LUN%d blk 0x%llx, cnt %d, offset 0x%llx, size %d\n",
- c->c_lu->l_targ->s_targ_num, c->c_lu->l_common->l_num,
- addr, cnt, io->da_offset, min);
-#endif
- if (mmap_data != MAP_FAILED) {
-
- io->da_clear_overlap = True;
- io->da_data_alloc = False;
- io->da_aio.a_aio.aio_return = min;
- io->da_data = (char *)mmap_data + (addr * 512LL) +
- io->da_offset;
- sbc_overlap_store(io);
- sbc_read_cmplt((emul_handle_t)io);
-
- } else {
- if ((io->da_data = (char *)malloc(min)) == NULL) {
- trans_send_complete(c, STATUS_BUSY);
- return;
- }
- io->da_clear_overlap = False;
- io->da_data_alloc = True;
- io->da_aio.a_aio_cmplt = sbc_read_cmplt;
- io->da_aio.a_id = io;
- trans_aioread(c, io->da_data, min, (addr * 512LL) +
- (off_t)io->da_offset, &io->da_aio);
- }
- offset += min;
- } while (offset < (off_t)(cnt * 512));
-}
-
-/*
- * []----
- * | sbc_read_cmplt -- Once we have the data, need to send it along.
- * []----
- */
-static void
-sbc_read_cmplt(emul_handle_t id)
-{
- disk_io_t *io = (disk_io_t *)id;
- int sense_len;
- uint64_t err_blkno;
- t10_cmd_t *cmd = io->da_cmd;
- Boolean_t last;
-
- last = (io->da_offset + io->da_data_len) < (io->da_lba_cnt * 512LL) ?
- False : True;
-
- if (io->da_aio.a_aio.aio_return != io->da_data_len) {
- err_blkno = io->da_lba + ((io->da_offset + 511) / 512);
- cmd->c_resid = (io->da_lba_cnt * 512) - io->da_offset;
- if (err_blkno > FIXED_SENSE_ADDL_INFO_LEN)
- sense_len = INFORMATION_SENSE_DESCR;
- else
- sense_len = 0;
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, sense_len);
- spc_sense_info(cmd, err_blkno);
- if (last == True) {
- trans_send_complete(cmd, STATUS_CHECK);
- sbc_io_free(io);
- } else {
- t10_cmd_done(cmd);
- }
- return;
- }
-
- if (trans_send_datain(cmd, io->da_data, io->da_data_len, io->da_offset,
- sbc_io_free, last, io) == False) {
- trans_send_complete(cmd, STATUS_BUSY);
- }
-}
-
-/*
- * []----
- * | sbc_write -- implement a SCSI write command.
- * []----
- */
-/*ARGSUSED*/
-static void
-sbc_write(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- union scsi_cdb *u;
- diskaddr_t addr;
- uint64_t err_blkno;
- uint32_t cnt;
- uchar_t addl_sense_len;
- disk_params_t *d;
- disk_io_t *io;
- size_t max_out;
- void *mmap_area;
-
- if ((d = (disk_params_t *)T10_PARAMS_AREA(cmd)) == NULL) {
- trans_send_complete(cmd, STATUS_BUSY);
- return;
- }
-
- /*LINTED*/
- u = (union scsi_cdb *)cdb;
-
- switch (u->scc_cmd) {
- case SCMD_WRITE:
- /*
- * SBC-2 revision 16, section 5.24
- * Reserve bit checks.
- */
- if ((cdb[1] & 0xe0) || SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- addr = (diskaddr_t)(uint32_t)GETG0ADDR(u);
- cnt = GETG0COUNT(u);
- /*
- * SBC-2 Revision 16/Section 5.24 WRITE(6)
- * A TRANSFER LENGHT of 0 indicates that 256 logical blocks
- * shall be written.
- */
- if (cnt == 0)
- cnt = 256;
- break;
-
- case SCMD_WRITE_G1:
- /*
- * SBC-2 revision 16, section 5.25
- * Reserve bit checks.
- */
- if ((cdb[1] & 0x6) || cdb[6] ||
- SAM_CONTROL_BYTE_RESERVED(cdb[9])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- addr = (diskaddr_t)(uint32_t)GETG1ADDR(u);
- cnt = GETG1COUNT(u);
- break;
-
- case SCMD_WRITE_G4:
- /*
- * SBC-2 revision 16, section 5.27
- * Reserve bit checks.
- */
- if ((cdb[1] & 0x6) || cdb[14] ||
- SAM_CONTROL_BYTE_RESERVED(cdb[15])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- addr = (diskaddr_t)GETG4LONGADDR(u);
- cnt = GETG4COUNT(u);
- break;
-
- default:
- queue_prt(mgmtq, Q_STE_ERRS, "Unprocessed WRITE type\n");
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
-
- }
-
- if ((addr + cnt) > d->d_size) {
-
- if (addr > d->d_size)
- err_blkno = addr;
- else
- err_blkno = d->d_size;
-
- if (err_blkno > FIXED_SENSE_ADDL_INFO_LEN)
- addl_sense_len = INFORMATION_SENSE_DESCR;
- else
- addl_sense_len = 0;
-
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, addl_sense_len);
- spc_sense_info(cmd, err_blkno);
- spc_sense_ascq(cmd, SPC_ASC_BLOCK_RANGE, SPC_ASCQ_BLOCK_RANGE);
- trans_send_complete(cmd, STATUS_CHECK);
-
- queue_prt(mgmtq, Q_STE_ERRS,
- "SBC%x LUN%d WRITE Illegal sector "
- "(0x%llx + 0x%x) > 0x%ullx\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- addr, cnt, d->d_size);
- return;
- }
-
- if (cnt == 0) {
- queue_prt(mgmtq, Q_STE_NONIO,
- "SBC%x LUN%d WRITE zero block count for addr 0x%x\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- addr);
- trans_send_complete(cmd, STATUS_GOOD);
- return;
- }
-
- io = (disk_io_t *)cmd->c_emul_id;
- if (io == NULL) {
- io = sbc_io_alloc(cmd);
- io->da_lba = addr;
- io->da_lba_cnt = cnt;
- io->da_clear_overlap = False;
- io->da_aio.a_aio_cmplt = sbc_write_cmplt;
- io->da_aio.a_id = io;
-
- /*
- * Only update the statistics the first time through
- * for this particular command. If the requested transfer
- * is larger than the transport can handle this routine
- * will be called many times.
- */
- cmd->c_lu->l_cmds_write++;
- cmd->c_lu->l_sects_write += cnt;
-
-#ifdef FULL_DEBUG
- queue_prt(mgmtq, Q_STE_IO,
- "SBC%x LUN%d blk 0x%llx, cnt 0x%x\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- addr, cnt);
-#endif
- }
-
- /*
- * If a transport sets the maximum output value to zero we'll
- * just request the entire amount. Otherwise, transfer no more
- * than the maximum output or the reminder, whichever is less.
- */
- max_out = cmd->c_lu->l_targ->s_maxout;
- io->da_data_len = max_out ? MIN(max_out,
- (cnt * 512) - io->da_offset) : (cnt * 512);
-
- mmap_area = T10_MMAP_AREA(cmd);
- if (mmap_area != MAP_FAILED) {
-
- io->da_data_alloc = False;
- io->da_data = (char *)mmap_area + (addr * 512LL) +
- io->da_offset;
- sbc_overlap_check(io);
-
- } else if ((io->da_data = (char *)malloc(io->da_data_len)) == NULL) {
-
- trans_send_complete(cmd, STATUS_BUSY);
- return;
-
- } else {
-
- io->da_data_alloc = True;
- }
- if (trans_rqst_dataout(cmd, io->da_data, io->da_data_len,
- io->da_offset, io, sbc_io_free) == False) {
- trans_send_complete(cmd, STATUS_BUSY);
- }
-}
-
-/*
- * []----
- * | sbc_write_data -- store a chunk of data from the transport
- * []----
- */
-/*ARGSUSED*/
-void
-sbc_write_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset, char *data,
- size_t data_len)
-{
- disk_io_t *io = (disk_io_t *)id;
- disk_params_t *d;
-
- if (cmd->c_lu->l_common->l_mmap == MAP_FAILED) {
- trans_aiowrite(cmd, data, data_len, (io->da_lba * 512) +
- (off_t)io->da_offset, &io->da_aio);
- } else {
- if ((d = (disk_params_t *)T10_PARAMS_AREA(cmd)) == NULL)
- return;
-
- if (d->d_fast_write == False) {
- uint64_t sa;
- size_t len;
-
- /*
- * msync requires the address to be page aligned.
- * That means we need to account for any alignment
- * loss in the len field and access the full page.
- */
- sa = (uint64_t)(intptr_t)data & ~(sbc_page_size - 1);
- len = (((size_t)data & (sbc_page_size - 1)) +
- data_len + sbc_page_size - 1) &
- ~(sbc_page_size -1);
-
- /*
- * We only need to worry about sync'ing the blocks
- * in the mmap case because if the fast cache isn't
- * enabled for AIO the file will be opened with F_SYNC
- * which performs the correct action.
- */
- if (msync((char *)(intptr_t)sa, len, MS_SYNC) == -1) {
- perror("msync");
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- }
-
- /*
- * Since the data has already been transfered from the
- * transport to the mmap area we just need to call
- * the complete routine.
- */
- sbc_write_cmplt(id);
- }
-}
-
-/*
- * []----
- * | sbc_write_cmplt -- deal with end game of write
- * |
- * | See if all of the data for this write operation has been dealt
- * | with. If so, send a final acknowledgement back to the transport.
- * | If not, update the offset, calculate the next transfer size, and
- * | start the process again.
- * []---
- */
-static void
-sbc_write_cmplt(emul_handle_t e)
-{
- disk_io_t *io = (disk_io_t *)e;
- t10_cmd_t *cmd = io->da_cmd;
- int sense_len;
- uint64_t err_blkno;
-
- if ((cmd->c_lu->l_common->l_mmap == MAP_FAILED) &&
- (io->da_aio.a_aio.aio_return != io->da_data_len)) {
- err_blkno = io->da_lba + ((io->da_offset + 511) / 512);
- cmd->c_resid = (io->da_lba_cnt * 512) - io->da_offset;
- if (err_blkno > FIXED_SENSE_ADDL_INFO_LEN)
- sense_len = INFORMATION_SENSE_DESCR;
- else
- sense_len = 0;
-
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, sense_len);
- spc_sense_info(cmd, err_blkno);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- if ((io->da_offset + io->da_data_len) < (io->da_lba_cnt * 512)) {
- if (io->da_data_alloc == True) {
- io->da_data_alloc = False;
- free(io->da_data);
- }
-
- io->da_offset += io->da_data_len;
- io->da_data_len = MIN(cmd->c_lu->l_targ->s_maxout,
- (io->da_lba_cnt * 512) - io->da_offset);
- sbc_write(cmd, cmd->c_cdb, cmd->c_cdb_len);
- return;
- }
- trans_send_complete(cmd, STATUS_GOOD);
-}
-
-/*ARGSUSED*/
-void
-sbc_startstop(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- /*
- * SBC-2 revision 16, section 5.17
- * Reserve bit checks
- */
- if ((cdb[1] & 0xfe) || cdb[2] || cdb[3] ||
- (cdb[4] & ~(SBC_PWR_MASK|SBC_PWR_LOEJ|SBC_PWR_START)) ||
- SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- /*
- * More reserve bit checks
- */
- switch ((cdb[4] & SBC_PWR_MASK) >> SBC_PWR_SHFT) {
- case SBC_PWR_START_VALID:
- /*
- * It's an error to ask that the media be ejected.
- *
- * NOTE: Look for method to pass the START bit
- * along to underlying storage. If we're asked to
- * stop the drive there's not much that we can do
- * for the virtual storage, but maybe everything else
- * has been requested to stop as well.
- */
- if (cdb[4] & SBC_PWR_LOEJ) {
- goto send_error;
- }
- break;
-
- case SBC_PWR_ACTIVE:
- case SBC_PWR_IDLE:
- case SBC_PWR_STANDBY:
- case SBC_PWR_OBSOLETE:
- break;
-
- case SBC_PWR_LU_CONTROL:
- case SBC_PWR_FORCE_IDLE_0:
- case SBC_PWR_FORCE_STANDBY_0:
- break;
-
- default:
-send_error:
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- if ((cdb[1] & 1) == 0) {
- /*
- * Immediate bit is not set, so go ahead a flush things.
- */
- if (cmd->c_lu->l_common->l_mmap == MAP_FAILED) {
- if (fsync(cmd->c_lu->l_common->l_fd) != 0) {
- spc_sense_create(cmd, KEY_MEDIUM_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- } else {
- if (msync(cmd->c_lu->l_common->l_mmap,
- cmd->c_lu->l_common->l_size, MS_SYNC) == -1) {
- spc_sense_create(cmd, KEY_MEDIUM_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- }
- }
- trans_send_complete(cmd, STATUS_GOOD);
-}
-
-/*
- * []----
- * | sbc_recap -- read capacity of device being emulated.
- * []----
- */
-/*ARGSUSED*/
-void
-sbc_recap(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- uint64_t capacity;
- int len;
- uint32_t lba;
- struct scsi_capacity *cap;
- disk_params_t *d;
- disk_io_t *io;
-
- if ((d = (disk_params_t *)T10_PARAMS_AREA(cmd)) == NULL)
- return;
-
- capacity = d->d_size;
-
- len = sizeof (struct scsi_capacity);
-
- /*
- * SBC-2 Revision 16, section 5.10.1
- * Any of the following conditions will generate an error.
- * (1) PMI bit is zero and LOGICAL block address is non-zero
- * (2) Rserved bytes are not zero
- * (3) Reseved bits are not zero
- * (4) Reserved CONTROL bits are not zero
- */
- if ((((cdb[8] & SBC_CAPACITY_PMI) == 0) &&
- (cdb[2] || cdb[3] || cdb[4] || cdb[5])) ||
- cdb[1] || cdb[6] || cdb[7] || (cdb[8] & ~SBC_CAPACITY_PMI) ||
- SAM_CONTROL_BYTE_RESERVED(cdb[9])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- /*
- * if the device capacity larger than 32 bits then set
- * the capacity of the device to all 0xf's.
- * a device that supports LBAs larger than 32 bits which
- * should be used read_capacity(16) comand to get the capacity.
- * NOTE: the adjustment to subject one from the capacity is
- * done below.
- */
- if (capacity & 0xFFFFFFFF00000000ULL)
- capacity = 0xFFFFFFFF;
-
- io = sbc_io_alloc(cmd);
-
- if ((cap = (struct scsi_capacity *)calloc(1, len)) == NULL) {
- sbc_io_free(io);
- trans_send_complete(cmd, STATUS_BUSY);
- return;
- }
- io->da_data = (char *)cap;
- io->da_data_alloc = True;
- io->da_clear_overlap = False;
- io->da_data_len = len;
-
- if (capacity != 0xFFFFFFFF) {
- /*
- * Look at the PMI information
- */
- if (cdb[8] & SBC_CAPACITY_PMI) {
- lba = cdb[2] << 24 | cdb[3] << 16 |
- cdb[4] << 8 | cdb[5];
- if (lba >= capacity)
- cap->capacity = htonl(0xffffffff);
- else
- cap->capacity = (capacity - 1);
- } else {
- cap->capacity = htonl(capacity - 1);
- }
- } else {
- cap->capacity = htonl(capacity);
- }
- cap->lbasize = htonl(d->d_bytes_sect);
-
- if (trans_send_datain(cmd, io->da_data, io->da_data_len, 0,
- sbc_io_free, True, io) == False) {
- trans_send_complete(cmd, STATUS_BUSY);
- }
-}
-
-/*ARGSUSED*/
-void
-sbc_msense(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- struct mode_header *mode_hdr;
- char *np;
- disk_params_t *d;
- disk_io_t *io;
- int rtn_len;
- uint8_t pc;
- struct block_descriptor bd;
-
- if ((d = (disk_params_t *)T10_PARAMS_AREA(cmd)) == NULL)
- return;
-
- /*
- * SPC-3 Revision 21c section 6.8
- * Reserve bit checks
- */
- if ((cdb[1] & ~SPC_MODE_SENSE_DBD) ||
- SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- /*
- * Zero length causes a simple ack to occur.
- */
- if (cdb[4] == 0) {
- trans_send_complete(cmd, STATUS_GOOD);
- return;
- }
-
- io = sbc_io_alloc(cmd);
-
- /*
- * Make sure that we have enough room in the data buffer. We'll
- * only send back the amount requested though
- */
- io->da_data_len = MAX(cdb[4], sizeof (struct mode_format) +
- sizeof (struct mode_geometry) +
- sizeof (struct mode_control_scsi3) +
- sizeof (struct mode_cache_scsi3) +
- sizeof (struct mode_info_ctrl) + (MODE_BLK_DESC_LENGTH * 5));
- if ((io->da_data = (char *)calloc(1, io->da_data_len)) == NULL) {
- sbc_io_free(io);
- trans_send_complete(cmd, STATUS_BUSY);
- return;
- }
- io->da_clear_overlap = False;
- io->da_data_alloc = True;
- mode_hdr = (struct mode_header *)io->da_data;
-
- /*
- * If DBD flag is set, then we should not send back the block
- * descriptor details
- */
- if (cdb[1] & SPC_MODE_SENSE_DBD) {
- mode_hdr->length = sizeof (struct mode_header) - 1;
- mode_hdr->bdesc_length = 0;
- }
- /*
- * If DBD flag is zero, then we should add block descriptor details
- */
- else {
- /*
- * We subtract one from the length because this value is not
- * supposed to contain it's size.
- */
-
- mode_hdr->length = sizeof (struct mode_header) - 1 +
- MODE_BLK_DESC_LENGTH;
- mode_hdr->bdesc_length = MODE_BLK_DESC_LENGTH;
-
- /*
- * Need to fill in the block size. Some initiators are starting
- * to use this value, which is correct, instead of looking at
- * the page3 data which is starting to become obsolete.
- *
- * We define the space for the structure on the stack and then
- * copy it into the return area to avoid structure alignment
- * issues.
- */
- bzero(&bd, sizeof (bd));
- bd.blksize_hi = lobyte(hiword(d->d_bytes_sect));
- bd.blksize_mid = hibyte(loword(d->d_bytes_sect));
- bd.blksize_lo = lobyte(loword(d->d_bytes_sect));
- bcopy(&bd, io->da_data + sizeof (*mode_hdr), sizeof (bd));
- }
-
- /*
- * cdb[2] contains page code, and page control field. So, we need
- * to mask page control field, while checking for the page code.
- *
- * Page control specifies whether to report the current, changeable
- * default or saved values. This parameter only applies to the
- * mode page data itself. From spc-3 section 6.9.1:
- *
- * "The PC field only affects the mode parameters within the mode
- * pages, however the PS, SPF, PAGE CODE field, SUBPAGE CODE field,
- * and PAGE LENGTH field should return current values (i.e. as if
- * PC is set to 00b). The mode parameter header and mode parameter
- * block descriptor should return current values."
- *
- * Also: "Some SCSI target devices may not distinguish between
- * current and saved mode parameters and report identical values
- * in response to a PC field of either 0 or 3." Our implementation
- * will treat 0 and 3 the same.
- */
- pc = (cdb[2] & SPC_MODE_SENSE_PC_MASK) >> SPC_MODE_SENSE_PC_SHIFT;
-
- switch (cdb[2] & SPC_MODE_SENSE_PAGE_CODE_MASK) {
-
- case MODE_SENSE_PAGE3_CODE:
- if ((d->d_heads == 0) && (d->d_cyl == 0) && (d->d_spt == 0)) {
- sbc_io_free(io);
- spc_unsupported(cmd, cdb, cdb_len);
- return;
- }
- mode_hdr->length += sizeof (struct mode_format);
- (void) sense_page3(d,
- io->da_data + sizeof (*mode_hdr) + mode_hdr->bdesc_length,
- pc);
- break;
-
- case MODE_SENSE_PAGE4_CODE:
- if ((d->d_heads == 0) && (d->d_cyl == 0) && (d->d_spt == 0)) {
- sbc_io_free(io);
- spc_unsupported(cmd, cdb, cdb_len);
- return;
- }
- mode_hdr->length += sizeof (struct mode_geometry);
- (void) sense_page4(d,
- io->da_data + sizeof (*mode_hdr) + mode_hdr->bdesc_length,
- pc);
- break;
-
- case MODE_SENSE_CACHE:
- mode_hdr->length += sizeof (struct mode_cache_scsi3);
- (void) sense_cache(d,
- io->da_data + sizeof (*mode_hdr) + mode_hdr->bdesc_length,
- pc);
- break;
-
- case MODE_SENSE_CONTROL:
- mode_hdr->length += sizeof (struct mode_control_scsi3);
- (void) sense_mode_control(cmd->c_lu,
- io->da_data + sizeof (*mode_hdr) + mode_hdr->bdesc_length,
- pc);
- break;
-
- case MODE_SENSE_INFO_CTRL:
- mode_hdr->length += sizeof (struct mode_info_ctrl);
- (void) sense_info_ctrl(io->da_data + sizeof (*mode_hdr) +
- mode_hdr->bdesc_length, pc);
- break;
-
- case MODE_SENSE_SEND_ALL:
- /*
- * SPC-3 revision 21c
- * Section 6.9.1 Table 97
- * "Return all subpage 00h mode pages in page_0 format"
- */
- mode_hdr->length += sizeof (struct mode_cache_scsi3) +
- sizeof (struct mode_control_scsi3) +
- sizeof (struct mode_info_ctrl);
-
- if (d->d_heads && d->d_cyl && d->d_spt)
- mode_hdr->length += sizeof (struct mode_format) +
- sizeof (struct mode_geometry);
-
- np = io->da_data + sizeof (*mode_hdr) +
- mode_hdr->bdesc_length;
- if (io->da_data_len < (sizeof (struct mode_format) +
- sizeof (struct mode_geometry) +
- sizeof (struct mode_cache_scsi3) +
- sizeof (struct mode_control_scsi3) +
- sizeof (struct mode_info_ctrl))) {
-
- /*
- * Believe it or not, there's an initiator out
- * there which sends a mode sense request for all
- * of the pages, without always sending a data-in
- * size which is large enough.
- * NOTE: Need to check the error key returned
- * here and see if something else should be used.
- */
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- trans_send_complete(cmd, STATUS_CHECK);
-
- } else {
-
- /*
- * If we don't have geometry then don't attempt
- * report that information.
- */
- rtn_len = sizeof (*mode_hdr) + mode_hdr->bdesc_length;
- if (d->d_heads && d->d_cyl && d->d_spt) {
- np = sense_page3(d, np, pc);
- np = sense_page4(d, np, pc);
- }
- np = sense_cache(d, np, pc);
- np = sense_mode_control(cmd->c_lu, np, pc);
- (void) sense_info_ctrl(np, pc);
- }
- break;
-
- case 0x00:
- /*
- * SPC-3 Revision 21c, section 6.9.1
- * Table 97 -- Mode page code usage for all devices
- * Page Code 00 == Vendor specific. We are going to return
- * zeros.
- */
- break;
-
- default:
- queue_prt(mgmtq, Q_STE_ERRS,
- "SBC%x LUN%d Unsupported mode_sense request 0x%x\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- cdb[2]);
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- break;
- }
-
- rtn_len = mode_hdr->length + 1;
- rtn_len = MIN(rtn_len, cdb[4]);
- if (trans_send_datain(cmd, io->da_data, rtn_len, 0, sbc_io_free,
- True, io) == False) {
- trans_send_complete(cmd, STATUS_BUSY);
- }
-}
-
-/*ARGSUSED*/
-void
-sbc_synccache(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- /*
- * SBC-2 revision 16, section 5.18
- * Reserve bit checks
- */
- if ((cdb[1] & ~(SBC_SYNC_CACHE_IMMED|SBC_SYNC_CACHE_NV)) || cdb[6] ||
- SAM_CONTROL_BYTE_RESERVED(cdb[9])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- } else {
- /*
- * SBC-3, revision 16, section 5.18
- * An IMMED bit set to one specifies that the device server
- * shall return status as soon as the CDB has been validated.
- */
- if (cdb[1] & SBC_SYNC_CACHE_IMMED) {
-
- /*
- * Immediately return a status of GOOD. If an error
- * occurs with the fsync/msync the next command will
- * pick up an error.
- */
- trans_send_complete(cmd, STATUS_GOOD);
- if (cmd->c_lu->l_common->l_mmap == MAP_FAILED) {
- if (fsync(cmd->c_lu->l_common->l_fd) == -1) {
- cmd->c_lu->l_status =
- KEY_HARDWARE_ERROR;
- cmd->c_lu->l_asc = 0x00;
- cmd->c_lu->l_ascq = 0x00;
- }
- } else {
- if (msync(cmd->c_lu->l_common->l_mmap,
- cmd->c_lu->l_common->l_size, MS_SYNC) ==
- -1) {
- cmd->c_lu->l_status =
- KEY_HARDWARE_ERROR;
- cmd->c_lu->l_asc = 0x00;
- cmd->c_lu->l_ascq = 0x00;
- }
- }
- } else {
- if (cmd->c_lu->l_common->l_mmap == MAP_FAILED) {
- if (fsync(cmd->c_lu->l_common->l_fd) == -1) {
- spc_sense_create(cmd,
- KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- } else
- trans_send_complete(cmd, STATUS_GOOD);
- } else {
- if (msync(cmd->c_lu->l_common->l_mmap,
- cmd->c_lu->l_common->l_size, MS_SYNC) ==
- -1) {
- spc_sense_create(cmd,
- KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- } else
- trans_send_complete(cmd, STATUS_GOOD);
- }
- }
- }
-}
-
-/*ARGSUSED*/
-void
-sbc_service_actiong4(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- switch (cdb[1] & SPC_GROUP4_SERVICE_ACTION_MASK) {
- case SSVC_ACTION_READ_CAPACITY_G4:
- sbc_read_capacity16(cmd, cdb, cdb_len);
- break;
- default:
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, 0x20, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- break;
- }
-}
-
-/*ARGSUSED*/
-static void
-sbc_read_capacity16(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- uint64_t capacity;
- uint64_t lba;
- int rep_size; /* response data size */
- struct scsi_capacity_16 *cap16;
- disk_params_t *d;
- disk_io_t *io;
-
- if ((d = (disk_params_t *)T10_PARAMS_AREA(cmd)) == NULL)
- return;
-
- capacity = d->d_size;
- /*
- * READ_CAPACITY(16) command
- */
- rep_size = cdb[10] << 24 | cdb[11] << 16 | cdb[12] << 8 | cdb[13];
- if (rep_size == 0) {
-
- /*
- * A zero length field means we're done.
- */
- trans_send_complete(cmd, STATUS_GOOD);
- return;
- }
- rep_size = MIN(rep_size, sizeof (*cap16));
-
- /*
- * Reserve bit checks.
- */
- if ((cdb[1] & ~SPC_GROUP4_SERVICE_ACTION_MASK) ||
- (cdb[14] & ~SBC_CAPACITY_PMI) ||
- SAM_CONTROL_BYTE_RESERVED(cdb[15])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- lba = (uint64_t)cdb[2] << 56 | (uint64_t)cdb[3] << 48 |
- (uint64_t)cdb[4] << 40 | (uint64_t)cdb[5] << 32 |
- (uint64_t)cdb[6] << 24 | (uint64_t)cdb[7] << 16 |
- (uint64_t)cdb[8] << 8 | (uint64_t)cdb[9];
-
- io = sbc_io_alloc(cmd);
-
- /*
- * We'll malloc enough space for the structure so that we can
- * set the values as we place. However, we'll set the transfer
- * length to the minimum of the requested size and our structure.
- * This is per SBC-2 revision 16, section 5.11.1 regarding
- * ALLOCATION LENGTH.
- */
- if ((cap16 = (struct scsi_capacity_16 *)calloc(1, sizeof (*cap16))) ==
- NULL) {
- trans_send_complete(cmd, STATUS_BUSY);
- return;
- }
- io->da_data = (char *)cap16;
- io->da_data_len = rep_size;
- io->da_data_alloc = True;
- io->da_clear_overlap = False;
-
- if (cdb[14] & SBC_CAPACITY_PMI) {
- if (lba >= capacity)
- cap16->sc_capacity = htonll(0xffffffffffffffffULL);
- else
- cap16->sc_capacity = htonll(capacity - 1);
- } else {
- cap16->sc_capacity = htonll(capacity - 1);
- }
- cap16->sc_lbasize = htonl(d->d_bytes_sect);
-
- if (trans_send_datain(cmd, io->da_data, io->da_data_len, 0,
- sbc_io_free, True, io) == False) {
- trans_send_complete(cmd, STATUS_BUSY);
- }
-}
-
-/*ARGSUSED*/
-static void
-sbc_verify(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- /*LINTED*/
- union scsi_cdb *u = (union scsi_cdb *)cdb;
- diskaddr_t addr;
- uint32_t cnt;
- uint32_t chk_size;
- uint64_t sz;
- uint64_t err_blkno;
- Boolean_t bytchk;
- char *chk_block;
- disk_io_t *io;
- disk_params_t *d;
- uchar_t addl_sense_len;
-
- if ((d = (disk_params_t *)T10_PARAMS_AREA(cmd)) == NULL) {
- trans_send_complete(cmd, STATUS_BUSY);
- return;
- }
-
- /*
- * Check the common reserved bits here and check the CONTROL byte
- * in each specific section for the different CDB sizes.
- * NOTE: If the VRPROTECT is non-zero we're required by SBC-3
- * to return an error since our emulation code doesn't have
- * any protection information stored on the media that we can
- * access.
- */
- if ((cdb[1] & ~(SBC_VRPROTECT_MASK|SBC_DPO|SBC_BYTCHK)) ||
- (cdb[1] & SBC_VRPROTECT_MASK)) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- bytchk = cdb[1] & SBC_BYTCHK ? True : False;
-
- switch (u->scc_cmd) {
- case SCMD_VERIFY:
- /*
- * BYTE 6 of the VERIFY(10) contains bits:
- * 0-4: Group number -- not supported must be zero
- * 5-6: Reserved
- * 7 : Restricted for MMC-4
- */
- if (cdb[6] || SAM_CONTROL_BYTE_RESERVED(cdb[9])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- addr = (diskaddr_t)(uint32_t)GETG1ADDR(u);
- cnt = GETG1COUNT(u);
- break;
-
- case SCMD_VERIFY_G4:
- /*
- * See VERIFY(10) above for definitions of what byte 14
- * contains.
- */
- if (cdb[14] || SAM_CONTROL_BYTE_RESERVED(cdb[15])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- addr = GETG4LONGADDR(u);
- cnt = GETG4COUNT(u);
- break;
-
- case SCMD_VERIFY_G5:
- /*
- * See VERIFY(10) above for definitions of what byte 10
- * contains.
- */
- if (cdb[10] || SAM_CONTROL_BYTE_RESERVED(cdb[11])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- addr = (diskaddr_t)GETG5ADDR(u);
- cnt = GETG5COUNT(u);
- break;
-
- default:
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- if ((addr + cnt) > d->d_size) {
-
- if (addr > d->d_size)
- err_blkno = addr;
- else
- err_blkno = d->d_size;
-
- if (err_blkno > FIXED_SENSE_ADDL_INFO_LEN)
- addl_sense_len = INFORMATION_SENSE_DESCR;
- else
- addl_sense_len = 0;
-
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, addl_sense_len);
- spc_sense_info(cmd, err_blkno);
- spc_sense_ascq(cmd, SPC_ASC_BLOCK_RANGE, SPC_ASCQ_BLOCK_RANGE);
- trans_send_complete(cmd, STATUS_CHECK);
-
- queue_prt(mgmtq, Q_STE_ERRS,
- "SBC%x LUN%d WRITE Illegal sector "
- "(0x%llx + 0x%x) > 0x%ullx\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- addr, cnt, d->d_size);
- return;
- }
-
- if (bytchk == False) {
- /*
- * With Byte Check being false all we need to do
- * is make sure that we can read the data off of the
- * media.
- */
- chk_size = 1024 * 1024;
- if ((chk_block = malloc(chk_size)) == NULL) {
- trans_send_complete(cmd, STATUS_BUSY);
- return;
- }
- while (cnt) {
- sz = MIN(chk_size, cnt * 512);
- /*
- * Even if the device is mmap'd in use pread. This
- * way we know directly if a read of the data has
- * failed.
- */
- if (pread(cmd->c_lu->l_common->l_fd, chk_block, sz,
- addr * 512LL) != sz) {
- spc_sense_create(cmd, KEY_MEDIUM_ERROR, 0);
- spc_sense_ascq(cmd, SPC_ASC_DATA_PATH,
- SPC_ASCQ_DATA_PATH);
- trans_send_complete(cmd, STATUS_CHECK);
- free(chk_block);
- return;
- }
- addr += sz / 512LL;
- cnt -= sz / 512;
- }
- free(chk_block);
- trans_send_complete(cmd, STATUS_GOOD);
- } else {
-
- io = cmd->c_emul_id;
- if (io == NULL) {
- io = sbc_io_alloc(cmd);
- io->da_lba = addr;
- io->da_lba_cnt = cnt;
- io->da_clear_overlap = False;
- io->da_aio.a_aio_cmplt = sbc_write_cmplt;
- io->da_aio.a_id = io;
- }
-
- sz = cmd->c_lu->l_targ->s_maxout;
- io->da_data_alloc = True;
- io->da_data_len = sz ? MIN(sz, (cnt * 512) - io->da_offset) :
- (cnt * 512);
-
- /*
- * Since we're going to just check the data we don't wish
- * to possibly change the on disk data. Therefore, even if
- * the backing store is mmap'd in we allocate space for the
- * data out buffer.
- */
- if ((io->da_data = malloc(io->da_data_len)) == NULL) {
- trans_send_complete(cmd, STATUS_BUSY);
- return;
- }
-
- if (trans_rqst_dataout(cmd, io->da_data, io->da_data_len,
- io->da_offset, io, sbc_io_free) == False)
- trans_send_complete(cmd, STATUS_BUSY);
- }
-}
-
-/*ARGSUSED*/
-static void
-sbc_verify_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset, char *data,
- size_t data_len)
-{
- disk_io_t *io = (disk_io_t *)id;
- char *on_disk_buf;
-
- if ((on_disk_buf = malloc(io->da_data_len)) == NULL) {
- trans_send_complete(cmd, STATUS_BUSY);
- }
-
- if (pread(cmd->c_lu->l_common->l_fd, on_disk_buf, io->da_data_len,
- io->da_offset + (io->da_lba * 512LL)) != io->da_data_len) {
- spc_sense_create(cmd, KEY_MISCOMPARE, 0);
- spc_sense_ascq(cmd, SPC_ASC_DATA_PATH, SPC_ASCQ_DATA_PATH);
- trans_send_complete(cmd, STATUS_CHECK);
- free(on_disk_buf);
- sbc_io_free(io);
- return;
- }
- if (bcmp(on_disk_buf, io->da_data, io->da_data_len) != 0) {
- spc_sense_create(cmd, KEY_MISCOMPARE, 0);
- spc_sense_ascq(cmd, SPC_ASC_MISCOMPARE, SPC_ASCQ_MISCOMPARE);
- trans_send_complete(cmd, STATUS_CHECK);
- free(on_disk_buf);
- sbc_io_free(io);
- return;
- }
- free(on_disk_buf);
- io->da_offset += io->da_data_len;
- if (io->da_offset < (io->da_lba_cnt * 512)) {
- if (io->da_data_alloc == True) {
- io->da_data_alloc = False;
- free(io->da_data);
- }
- sbc_verify(cmd, cmd->c_cdb, cmd->c_cdb_len);
- return;
- }
- trans_send_complete(cmd, STATUS_GOOD);
-}
-
-/*
- * []------------------------------------------------------------------[]
- * | Support related functions for SBC-2 |
- * []------------------------------------------------------------------[]
- */
-
-/*
- * []----
- * | sense_page3 -- Create page3 sense code for Disk.
- * |
- * | This is a separate routine because this is called in two different
- * | locations.
- * []----
- */
-static char *
-sense_page3(disk_params_t *d, char *buf, uint8_t pc)
-{
- struct mode_format mode_fmt;
-
- bzero(&mode_fmt, sizeof (mode_fmt));
-
- /* Page code and page length are always set */
- mode_fmt.mode_page.code = MODE_SENSE_PAGE3_CODE;
- mode_fmt.mode_page.length = sizeof (struct mode_format) -
- sizeof (struct mode_page);
-
- /*
- * No modifiable values so we report all zeros for
- * SPC_PC_MODIFIABLE_VALUES and all other page control values
- * result in the same values as SPC_PC_CURRENT_VALUES.
- */
- switch (pc) {
- case SPC_PC_MODIFIABLE_VALUES:
- /* Leave it blank */
- break;
- case SPC_PC_CURRENT_VALUES:
- case SPC_PC_DEFAULT_VALUES:
- case SPC_PC_SAVED_VALUES:
- mode_fmt.data_bytes_sect = htons(d->d_bytes_sect);
- mode_fmt.sect_track = htons(d->d_spt);
- mode_fmt.interleave = htons(d->d_interleave);
- break;
- }
-
- bcopy(&mode_fmt, buf, sizeof (mode_fmt));
-
- return (buf + sizeof (mode_fmt));
-}
-
-/*
- * []----
- * | sense_page4 -- Create page4 sense code for Disk.
- * |
- * | This is a separate routine because this is called in two different
- * | locations.
- * []----
- */
-static char *
-sense_page4(disk_params_t *d, char *buf, uint8_t pc)
-{
- struct mode_geometry mode_geom;
-
- bzero(&mode_geom, sizeof (mode_geom));
-
- /* Page code and page length are always set */
- mode_geom.mode_page.code = MODE_SENSE_PAGE4_CODE;
- mode_geom.mode_page.length =
- sizeof (struct mode_geometry) - sizeof (struct mode_page);
-
- /*
- * No modifiable values so we report all zeros for
- * SPC_PC_MODIFIABLE_VALUES and all other page control values
- * result in the same values as SPC_PC_CURRENT_VALUES.
- */
- switch (pc) {
- case SPC_PC_MODIFIABLE_VALUES:
- /* Leave it blank */
- break;
- case SPC_PC_CURRENT_VALUES:
- case SPC_PC_DEFAULT_VALUES:
- case SPC_PC_SAVED_VALUES:
- mode_geom.heads = d->d_heads;
- mode_geom.cyl_ub = d->d_cyl >> 16;
- mode_geom.cyl_mb = d->d_cyl >> 8;
- mode_geom.cyl_lb = d->d_cyl;
- mode_geom.rpm = htons(d->d_rpm);
- break;
- }
-
- bcopy(&mode_geom, buf, sizeof (mode_geom));
-
- return (buf + sizeof (mode_geom));
-}
-
-static char *
-sense_cache(disk_params_t *d, char *buf, uint8_t pc)
-{
- struct mode_cache_scsi3 mode_cache;
-
- bzero(&mode_cache, sizeof (mode_cache));
-
- /* Page code and page length are always set */
- mode_cache.mode_page.code = MODE_SENSE_CACHE;
- mode_cache.mode_page.length = sizeof (mode_cache) -
- sizeof (struct mode_page);
-
- /*
- * No modifiable values so we report all zeros for
- * SPC_PC_MODIFIABLE_VALUES and all other page control values
- * result in the same values as SPC_PC_CURRENT_VALUES.
- *
- * Technically wce is modifiable but not by using a mode
- * select command.
- */
- switch (pc) {
- case SPC_PC_MODIFIABLE_VALUES:
- /* Leave it blank */
- break;
- case SPC_PC_CURRENT_VALUES:
- case SPC_PC_DEFAULT_VALUES:
- case SPC_PC_SAVED_VALUES:
- mode_cache.wce = d->d_fast_write == True ? 1 : 0;
- break;
- }
-
- bcopy(&mode_cache, buf, sizeof (mode_cache));
-
- return (buf + sizeof (mode_cache));
-}
-
-/*
- * []----
- * | sense_mode_control -- Create mode control page for disk
- * []----
- */
-static char *
-sense_mode_control(t10_lu_impl_t *lu, char *buf, uint8_t pc)
-{
- struct mode_control_scsi3 m;
-
- bzero(&m, sizeof (m));
-
- /* Page code and page length are always set */
- m.mode_page.code = MODE_SENSE_CONTROL;
- m.mode_page.length = sizeof (struct mode_control_scsi3) -
- sizeof (struct mode_page);
-
- /*
- * D_SENSE is modifiable so we need to reflect this in the
- * SPC_PC_MODIFIABLE_VALUES page as well as report the default
- * value of '0' in SPC_PC_DEFAULT_VALUES.
- */
- switch (pc) {
- case SPC_PC_MODIFIABLE_VALUES:
- m.d_sense = 1; /* Modifiable */
- break;
- case SPC_PC_DEFAULT_VALUES:
- m.d_sense = 0; /* Default is disabled */
- m.que_mod = SPC_QUEUE_UNRESTRICTED;
- break;
- case SPC_PC_CURRENT_VALUES:
- case SPC_PC_SAVED_VALUES:
- m.d_sense = (lu->l_dsense_enabled == True) ? 1 : 0;
- m.que_mod = SPC_QUEUE_UNRESTRICTED;
- break;
- }
-
- bcopy(&m, buf, sizeof (m));
-
- return (buf + sizeof (m));
-}
-
-/*
- * []----
- * | sense_info_ctrl -- Create mode information control page
- * []----
- */
-static char *
-sense_info_ctrl(char *buf, uint8_t pc)
-{
- struct mode_info_ctrl info;
-
- bzero(&info, sizeof (info));
-
- /* Page code and page length are always set */
- info.mode_page.code = MODE_SENSE_INFO_CTRL;
- info.mode_page.length = sizeof (struct mode_info_ctrl) -
- sizeof (struct mode_page);
-
- /*
- * No modifiable values so we report all zeros for
- * SPC_PC_MODIFIABLE_VALUES and all other page control values
- * result in the same values as SPC_PC_CURRENT_VALUES.
- */
- switch (pc) {
- case SPC_PC_MODIFIABLE_VALUES:
- /* Leave it blank */
- break;
- case SPC_PC_CURRENT_VALUES:
- case SPC_PC_DEFAULT_VALUES:
- case SPC_PC_SAVED_VALUES:
- break;
- }
-
- bcopy(&info, buf, sizeof (info));
-
- return (buf + sizeof (info));
-}
-
-/*
- * []----
- * | sbc_io_alloc -- return a disk_io_t structure
- * |
- * | If the call to calloc fails we use the structure that was allocate
- * | during the initial common initialization call. This will allow the
- * | daemon to at least make progress.
- * []----
- */
-static disk_io_t *
-sbc_io_alloc(t10_cmd_t *c)
-{
- disk_io_t *io;
- disk_params_t *d = T10_PARAMS_AREA(c);
-
- if ((io = (disk_io_t *)calloc(1, sizeof (*io))) == NULL) {
- (void) pthread_mutex_lock(&d->d_mutex);
- if (d->d_io_used == True) {
- d->d_io_need = True;
- while (d->d_io_used == True)
- (void) pthread_cond_wait(&d->d_io_cond, &d->d_mutex);
- d->d_io_need = False;
- }
- d->d_io_used = True;
- io = d->d_io_reserved;
- (void) pthread_mutex_unlock(&d->d_mutex);
- }
-
- io->da_cmd = c;
- io->da_params = d;
- /* Enable detecting a change in state of the aio operation */
- io->da_aio.a_aio.aio_return = AIO_INPROGRESS;
- /*
- * Save the io pointer in the t10 cmd now rather than later. It's
- * needed during session shutdown processing to find the aio results
- * for determining if libaio has canceled the cmd, in which case
- * the cmd needs to be freed.
- */
- c->c_emul_id = io;
-
- return (io);
-}
-
-/*
- * []----
- * | sbc_io_free -- free local i/o buffers when transport is finished
- * |
- * | If the io structure being free is the preallocated buffer see if
- * | anyone is waiting for the buffer. If so, wake them up.
- * []----
- */
-static void
-sbc_io_free(emul_handle_t e)
-{
- disk_io_t *io = (disk_io_t *)e;
-
- if (io->da_clear_overlap == True)
- sbc_overlap_free(io);
-
- if (io->da_data_alloc == True)
- free(io->da_data);
-
- if (io == io->da_params->d_io_reserved) {
- (void) pthread_mutex_lock(&io->da_params->d_mutex);
- io->da_params->d_io_used = False;
- if (io->da_params->d_io_need == True)
- (void) pthread_cond_signal(&io->da_params->d_io_cond);
- (void) pthread_mutex_unlock(&io->da_params->d_mutex);
- } else {
- free(io);
- }
-}
-
-static int
-sbc_mmap_overlap(const void *v1, const void *v2)
-{
- disk_io_t *d1 = (disk_io_t *)v1;
- disk_io_t *d2 = (disk_io_t *)v2;
-
- if ((d1->da_data + d1->da_data_len) < d2->da_data)
- return (-1);
- if (d1->da_data > (d2->da_data + d2->da_data_len))
- return (1);
- return (0);
-}
-
-static void
-sbc_overlap_store(disk_io_t *io)
-{
- disk_params_t *d = io->da_params;
- avl_index_t where = 0;
-
- assert(d != NULL);
-
- (void) pthread_mutex_lock(&d->d_mutex);
- (void) avl_find(&d->d_mmap_overlaps, (void *)io, &where);
- avl_insert(&d->d_mmap_overlaps, (void *)io, where);
- (void) pthread_mutex_unlock(&d->d_mutex);
-}
-
-static void
-sbc_overlap_free(disk_io_t *io)
-{
- disk_params_t *d = io->da_params;
-
- assert(d != NULL);
-
- (void) pthread_mutex_lock(&d->d_mutex);
- avl_remove(&d->d_mmap_overlaps, (void *)io);
- if (d->d_mmap_paused == True) {
- d->d_mmap_paused = False;
- (void) pthread_cond_signal(&d->d_mmap_cond);
- }
- (void) pthread_mutex_unlock(&d->d_mutex);
-}
-
-static void
-sbc_overlap_check(disk_io_t *io)
-{
- disk_params_t *d = io->da_params;
-
- assert(d != NULL);
-recheck:
- (void) pthread_mutex_lock(&d->d_mutex);
- if (avl_find(&d->d_mmap_overlaps, (void *)io, NULL) != NULL) {
- d->d_mmap_paused = True;
- while (d->d_mmap_paused == True)
- (void) pthread_cond_wait(&d->d_mmap_cond,
- &d->d_mutex);
-
- /*
- * After waiting on the condition variable the link
- * list has changed because someone removed a command.
- * So, drop the lock and reexamine the list.
- */
- (void) pthread_mutex_unlock(&d->d_mutex);
- goto recheck;
- }
- (void) pthread_mutex_unlock(&d->d_mutex);
-}
-
-/*
- * []----
- * | sbc_overlap_flush -- wait until everyone has reported in
- * []----
- */
-static void
-sbc_overlap_flush(disk_params_t *d)
-{
- assert(d != NULL);
-recheck:
- (void) pthread_mutex_lock(&d->d_mutex);
- if (avl_numnodes(&d->d_mmap_overlaps) != 0) {
- d->d_mmap_paused = True;
- while (d->d_mmap_paused == True)
- (void) pthread_cond_wait(&d->d_mmap_cond,
- &d->d_mutex);
-
- /*
- * After waiting on the condition variable the link
- * list has changed because someone removed a command.
- * So, drop the lock and reexamine the list.
- */
- (void) pthread_mutex_unlock(&d->d_mutex);
- goto recheck;
- }
- (void) pthread_mutex_unlock(&d->d_mutex);
-}
-
-/*
- * []----
- * | Command table for LBA emulation. This is at the end of the file because
- * | it's big and ugly. ;-) To make for fast translation to the appropriate
- * | emulation routine we just have a big command table with all 256 possible
- * | entries. Most will report STATUS_CHECK, unsupport operation. By doing
- * | this we can avoid error checking for command range.
- * []----
- */
-static scsi_cmd_table_t lba_table[] = {
- /* 0x00 -- 0x0f */
- { spc_tur, NULL, NULL, "TEST_UNIT_READY" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_request_sense, NULL, NULL, "REQUEST_SENSE" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { sbc_read, NULL, sbc_read_cmplt, "READ" },
- { spc_unsupported, NULL, NULL, NULL },
- { sbc_write, sbc_write_data, sbc_write_cmplt, "WRITE" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x10 -- 0x1f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_inquiry, NULL, NULL, "INQUIRY" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_mselect, spc_mselect_data, NULL, "MODE_SELECT" },
- { spc_cmd_reserve6, NULL, NULL, "RESERVE(6)" },
- { spc_cmd_release6, NULL, NULL, "RELEASE(6)" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { sbc_msense, NULL, NULL, "MODE_SENSE" },
- { sbc_startstop, NULL, NULL, "START_STOP" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_send_diag, NULL, NULL, "SEND_DIAG" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x20 -- 0x2f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { sbc_recap, NULL, NULL, "READ_CAPACITY" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { sbc_read, NULL, sbc_read_cmplt, "READ_G1" },
- { spc_unsupported, NULL, NULL, NULL },
- { sbc_write, sbc_write_data, sbc_write_cmplt, "WRITE_G1" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { sbc_verify, sbc_verify_data, NULL, "VERIFY_G1" },
-
- /* 0x30 -- 0x3f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { sbc_synccache, NULL, NULL, "SYNC_CACHE" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x40 -- 0x4f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, "LOG_SENSE" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x50 -- 0x5f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_cmd_pr_in, NULL, NULL, "PERSISTENT_RESERVE_IN" },
- { spc_cmd_pr_out, spc_cmd_pr_out_data, NULL, "PERSISTENT_RESERVE_OUT" },
-
- /* 0x60 -- 0x6f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x70 -- 0x7f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x80 -- 0x8f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { sbc_read, NULL, sbc_read_cmplt, "READ_G4" },
- { spc_unsupported, NULL, NULL, NULL },
- { sbc_write, sbc_write_data, sbc_write_cmplt, "WRITE_G4" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { sbc_verify, sbc_verify_data, NULL, "VERIFY_G4" },
-
- /* 0x90 -- 0x9f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { sbc_service_actiong4, NULL, NULL, "SVC_ACTION_G4" },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xa0 - 0xaf */
- { spc_report_luns, NULL, NULL, "REPORT_LUNS" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_report_tpgs, NULL, NULL, "REPORT_TPGS" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { sbc_verify, sbc_verify_data, NULL, "VERIFY_G5" },
-
- /* 0xb0 -- 0xbf */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xc0 -- 0xcf */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xd0 -- 0xdf */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xe0 -- 0xef */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xf0 -- 0xff */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-};
diff --git a/usr/src/cmd/iscsi/iscsitgtd/t10_sbc.h b/usr/src/cmd/iscsi/iscsitgtd/t10_sbc.h
deleted file mode 100644
index 2a965b1159..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_sbc.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _T10_SBC_H
-#define _T10_SBC_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * SBC-2 specific structures and defines
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define SBC_CAPACITY_PMI 0x01
-
-#define SBC_SYNC_CACHE_IMMED 0x02
-#define SBC_SYNC_CACHE_NV 0x04
-
-/*
- * SBC-2 revision 16, section 5.20 - VERIFY command.
- * Bits found in the CDB.
- */
-/* --- Bits found in byte 1 --- */
-#define SBC_VRPROTECT_MASK 0xe0
-#define SBC_DPO 0x10
-#define SBC_BYTCHK 0x02
-/* --- Bits found in byte 6 --- */
-#define SBC_GROUP_MASK 0x1f
-
-/*
- * SBC-2 revision 16, section 5.17 START_STOP
- * Table 49 -- POWER CONDITION field
- */
-#define SBC_PWR_MASK 0xf0
-#define SBC_PWR_SHFT 4
-#define SBC_PWR_START_VALID 0x00
-#define SBC_PWR_ACTIVE 0x01
-#define SBC_PWR_IDLE 0x02
-#define SBC_PWR_STANDBY 0x03
-#define SBC_PWR_OBSOLETE 0x05 /* JIST checks this one */
-#define SBC_PWR_LU_CONTROL 0x07
-#define SBC_PWR_FORCE_IDLE_0 0x0a
-#define SBC_PWR_FORCE_STANDBY_0 0x0b
-#define SBC_PWR_LOEJ 0x02
-#define SBC_PWR_START 0x01
-
-typedef struct disk_params {
- /*
- * Size of LUN in blocks
- */
- diskaddr_t d_size;
-
- /*
- * Number of bytes per section. This will probably
- * Become vary important for the T10 Data Integrity
- * Stuff.
- */
- uint32_t d_bytes_sect;
- uint32_t d_heads,
- d_spt,
- d_cyl;
- /*
- * Another bogus values.
- */
- uint32_t d_rpm,
- d_interleave;
-
- /*
- * This lock protects access to both the d_mmap_overlaps AVL tree
- * and use of the reserved disk_io buffer when memory is exhausted.
- */
- pthread_mutex_t d_mutex;
-
- /*
- * When using mmap backing store it's possible for an application
- * to issue a read and a write command of the same block without
- * first waiting for the read to complete. Since we pass the address
- * to the mmap area back to the transport and continue it's possible
- * to start processing the write command which will change the data
- * before the read has completed. To prevent this condition read
- * commands store their data address and length into the avl tree.
- * The write command will see if it's potential address is the same
- * as one of the read commands. If so, the write command will pause
- * until the read completes.
- */
- avl_tree_t d_mmap_overlaps;
- pthread_cond_t d_mmap_cond;
- Boolean_t d_mmap_paused;
-
- pthread_cond_t d_io_cond;
- Boolean_t d_io_need;
- Boolean_t d_io_used;
- struct disk_io *d_io_reserved;
-
- Boolean_t d_fast_write;
- t10_lu_state_t d_state;
- sbc_reserve_t d_sbc_reserve;
-} disk_params_t;
-
-typedef struct disk_io {
- /*
- * This structure needs to be the first member. The first member
- * of this structure is an aio_result_t. If we need to issue
- * an aio request a generic handler is called for all aio requests.
- * To allow this generic handler a means to callback to the appropriate
- * emulation routines a generic header is used. The generic handler
- * can cast the pointer returned from aiowait to a t10_aio_t structure.
- * From there it can determine the call back routine and pass it
- * a specific pointer.
- */
- t10_aio_t da_aio;
-
- /*
- * Communication with the SAM-3 layer requires us to send back this
- * pointer which was passed in at the command start.
- */
- t10_cmd_t *da_cmd;
-
- /*
- * (1) During AIO operations we need to allocate space to hold the
- * data. This pointer represents that data which will be freed
- * from our callback (argument to trans_send_datain) after the
- * transport has finished with it.
- * (2) During mmap ops the memory address of the requested data block
- * will be stored here along with the transfer size. This will
- * be used by the overlap protection to see if we must hold
- * off a write op.
- */
- char *da_data;
- size_t da_data_len;
-
- /*
- * True if da_data has been malloc'd verses mmap and therefore
- * we need to free it when the free routine is called.
- */
- Boolean_t da_data_alloc;
-
- /*
- * True if an overlap value was stored which needs to be cleared.
- */
- Boolean_t da_clear_overlap;
-
- /*
- * If we're breaking up the transfer to comply with max_out
- * then da_offset indicates where in the transfer we're currently
- * at.
- */
- uint64_t da_offset;
-
- /*
- * This is the LBA of a SCSI READ or WRITE command. Once decoded
- * from the cdb we don't want to recompute it each time it's needed
- * in the different phases.
- */
- diskaddr_t da_lba;
- size_t da_lba_cnt;
-
- disk_params_t *da_params;
-
- /*
- * Normal command overlap protection is done by the SAM-3 layer.
- * This overlap is to prevent a write op from changing data before
- * an existing read op has transmitted the data.
- */
- avl_node_t da_mmap_overlap;
-} disk_io_t;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _T10_SBC_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/t10_spc.c b/usr/src/cmd/iscsi/iscsitgtd/t10_spc.c
deleted file mode 100644
index 6910e393a6..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_spc.c
+++ /dev/null
@@ -1,1198 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * []------------------------------------------------------------------[]
- * | SPC-3 Support Functions |
- * | These routines are not directly called by the SAM-3 layer. Those |
- * | who write device emulation modules are free to call these routine |
- * | to carry out housekeeping chores. |
- * []------------------------------------------------------------------[]
- */
-
-#include <sys/types.h>
-#include <sys/asynch.h>
-#include <sys/param.h>
-#include <strings.h>
-#include <unistd.h>
-#include <assert.h>
-
-#include <sys/scsi/generic/sense.h>
-#include <sys/scsi/generic/status.h>
-#include <sys/scsi/generic/inquiry.h>
-#include <sys/scsi/generic/mode.h>
-#include <sys/scsi/generic/commands.h>
-
-#include "t10.h"
-#include "t10_spc.h"
-#include "target.h"
-
-void spc_free(emul_handle_t id);
-
-/*
- * []----
- * | spc_unsupported -- generic routine to indicate we don't support this cmd
- * []----
- */
-/*ARGSUSED*/
-void
-spc_unsupported(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- char debug[80];
-
- (void) snprintf(debug, sizeof (debug),
- "SAM%d LUN%d Command 0x%x (%s) unsupported\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- cdb[0], cmd->c_lu->l_cmd_table[cdb[0]].cmd_name != NULL ?
- cmd->c_lu->l_cmd_table[cdb[0]].cmd_name : "No description");
- queue_str(mgmtq, Q_STE_ERRS, msg_log, debug);
-
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, 0x20, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
-}
-
-/*
- * []----
- * | spc_tur -- test unit ready
- * []----
- */
-/*ARGSUSED*/
-void
-spc_tur(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- /*
- * SPC-3 Revision 21c, section 6.31
- * Reserve bit checks
- */
- if (cdb[1] || cdb[2] || cdb[3] || cdb[4] ||
- SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- } else
- trans_send_complete(cmd, STATUS_GOOD);
-}
-
-/*
- * []----
- * | spc_request_sense --
- * []----
- */
-/*ARGSUSED*/
-void
-spc_request_sense(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- /* ---- Check for reserved bit conditions ---- */
- if ((cdb[1] & 0xfe) || cdb[2] || cdb[3] ||
- SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- } else {
- /*
- * Since we always run with autosense enabled there's
- * no sense data to return. That may change in the future
- * if we decide to add such support, but for now return
- * success always.
- */
- spc_sense_create(cmd, 0, 0);
- trans_send_complete(cmd, STATUS_GOOD);
- }
-}
-
-/*
- * []----
- * | spc_inquiry -- Standard INQUIRY command
- * []----
- */
-/*ARGSUSED*/
-void
-spc_inquiry(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- uint8_t *rsp_buf;
- uint8_t *rbp; /* temporary var */
- uint8_t evpd;
- struct scsi_inquiry *inq;
- uint32_t len;
- uint32_t page83_len;
- uint32_t rqst_len;
- uint32_t rtn_len;
- struct vpd_hdr *vhp;
- struct vpd_desc vd;
- size_t scsi_len;
- t10_lu_common_t *lu = cmd->c_lu->l_common;
- void *v;
- uint16_t *vdv;
- extended_inq_data_t *eid;
-
- /*
- * Information obtained from:
- * SPC-3 Revision 21c
- * Section 6.4.1 INQUIRY command
- * Need to generate a CHECK CONDITION with ILLEGAL REQUEST
- * and INVALID FIELD IN CDB (0x24/0x00) if any of the following is
- * true.
- * (1) If the EVPD bit is not set, then the page code must be zero.
- * (2) If any bit other than EVPD is set.
- * (3) If any of the reserved bits in the CONTROL byte are set.
- */
- /*
- * SPC-3,4 keyword reserved:
- * ...Receipts are not required to check reserved bits, bytes, words
- * or fields for zero values.
- *
- * Ignore the check for reserved fields in the CDB byte 1.
- */
- evpd = cdb[1] & 1;
- if ((evpd == 0 && (cdb[2] != 0)) || SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- rqst_len = cdb[3] << 8 | cdb[4];
- /*
- * Zero length is not an error and we should just acknowledge
- * the operation.
- */
- if (rqst_len == 0) {
- trans_send_complete(cmd, STATUS_GOOD);
- return;
- }
-
- /*
- * We send back a total of six Vital Product Data descriptors
- * plus associated data. Three are EUI values, two are for AULA
- * support being simple 4 byte values, and one is the IQN string.
- * NOTE: The IQN string is just an artifact of when the target
- * was created. Once FC support is added, the t_name would be
- * either a "naa." or "eui." string.
- */
- scsi_len = ((strlen(cmd->c_lu->l_targ->s_targ_base) + 1) + 3) & ~3;
- page83_len = (sizeof (struct vpd_desc) * 6) + scsi_len +
- (lu->l_guid_len * 3) + (sizeof (uint32_t) * 2);
-
- /*
- * We always allocate enough space so that the code can create
- * either the full inquiry data or page 0x83 data.
- */
- len = sizeof (struct vpd_hdr) + page83_len;
- len = max(rqst_len, max(sizeof (*inq), len));
- len = max(len, sizeof (*eid));
-
- /*
- * Allocate space with an alignment that will work for any casting.
- */
- if ((v = memalign(sizeof (void *), len)) == NULL) {
- trans_send_complete(cmd, STATUS_BUSY);
- return;
- }
- bzero(v, len);
- rsp_buf = (uint8_t *)v;
-
- /*
- * EVPD not set returns the standard inquiry data.
- */
- if (evpd == 0) {
- /*
- * Return whatever is the smallest amount between the
- * INQUIRY data or the amount requested.
- * Version descriptor details also should be included
- * with the inquiry response. So, rtn_len should consider
- * version descriptor details in standard inquiry format
- * as per SPC-3 Revision 23, Section 6.4.2 Table 81
- */
-
- rtn_len = min(rqst_len, max(sizeof (*inq),
- (SPC_INQ_VD_IDX + SPC_INQ_VD_LEN)));
-
- inq = (struct scsi_inquiry *)rsp_buf;
- /*
- * SPC-3 Revision 21c, Section 6.4.2 .. Table 82 -- Version
- * This target will comply with T10/1416-D
- */
- inq->inq_ansi = SPC_INQ_VERS_SPC_3;
-
- inq->inq_len = sizeof (*inq) - 4;
- inq->inq_dtype = lu->l_dtype;
- inq->inq_normaca = 0;
- inq->inq_rdf = SPC_INQ_RDF;
- inq->inq_cmdque = 1;
- inq->inq_linked = 0;
-
- /*
- * JIST Requires that we show support for hierarchical
- * support (HiSup).
- */
- inq->inq_hisup = 1;
-
- /*
- * SPC-4, revision 1a, section 6.4.2
- * Stand INQUIRY Data
- * To support MPxIO we enable ALUA support and identify
- * all paths to this device as being active/optimized
- * we defaults to symmertrical devices.
- */
- inq->inq_tpgs = 1;
-
- (void) snprintf(inq->inq_vid,
- sizeof (inq->inq_vid) + sizeof (inq->inq_pid) +
- sizeof (inq->inq_revision), "%-8s%-16s%-4s",
- lu->l_vid, lu->l_pid,
- DEFAULT_REVISION);
-
- /*
- * SPC-3 Revision 21c, section 6.4.2
- * Table 85 -- Version Descriptor values
- * Starting at byte 58 there are up to 8 version
- * descriptors which are 16bits in size.
- *
- * NOTE: The ordering of these values is according
- * to the standard. First comes the architectural
- * version and then followed by: physical transport,
- * SCSI transport, primary command set version, and
- * finally the device type command set.
- */
- vdv = &((uint16_t *)v)[29];
-
- /* SAM-3 T10/1561-D rev 14 */
- *vdv++ = htons(SPC_INQ_VD_SAM3);
-
- /* physical transport code unknown */
- *vdv++ = htons(0x0000);
-
- *vdv++ = htons(cmd->c_lu->l_targ->s_trans_vers);
-
- /* SPC ANSI X3.301:1997 */
- *vdv++ = htons(SPC_INQ_VD_SPC3);
-
- if (lu->l_dtype == DTYPE_DIRECT) {
- /* SBC-2 T10/1417-D rev 5a */
- *vdv++ = htons(SPC_INQ_VD_SBC2);
- } else if (lu->l_dtype == DTYPE_SEQUENTIAL) {
- /* SSC-2 (no version) */
- *vdv++ = htons(SPC_INQ_VD_SSC3);
- } else if (lu->l_dtype == DTYPE_OSD) {
- /* OSD T10/1355-D revision 10 */
- *vdv++ = htons(SPC_INQ_VD_OSD);
- }
-
- } else {
-
- /* ---- Common information returned with all page types ---- */
- rsp_buf[0] = lu->l_dtype;
- rsp_buf[1] = cdb[2];
-
- queue_prt(mgmtq, Q_STE_NONIO, "SPC%d INQUIRY Page%x request\n",
- lu->l_num, cdb[2]);
- switch (cdb[2]) {
- default:
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
-
- case SPC_INQ_PAGE0:
- /*
- * SPC-3 Revision 21c Section 7.6.10
- * EVPD page 0 returns information about which pages
- * are supported. We support page 0x00 and 0x83.
- * NOTE: The value found in byte[3] is the returned
- * page length as defined by (n - 3) where 'n' is
- * the last valid byte. In this case 5.
- */
- rsp_buf[3] = 4;
- rsp_buf[4] = SPC_INQ_PAGE0;
- rsp_buf[5] = SPC_INQ_PAGE80;
- rsp_buf[6] = SPC_INQ_PAGE83;
- rsp_buf[7] = SPC_INQ_PAGE86;
-
- /*
- * Return the smallest amount of data between the
- * requested amount and the size of the Page83 data.
- */
- rtn_len = min(rqst_len, sizeof (struct vpd_hdr) +
- rsp_buf[3]);
- break;
-
- case SPC_INQ_PAGE80:
- /*
- * Return the smallest amount of data between the
- * requested amount and the size of the Page80 data.
- */
- rtn_len = min(rqst_len, sizeof (struct vpd_hdr) + 4);
- rsp_buf[3] = 4;
- rsp_buf[4] = 0x20;
- rsp_buf[5] = 0x20;
- rsp_buf[6] = 0x20;
- rsp_buf[7] = 0x20;
- break;
-
- case SPC_INQ_PAGE83:
- /*
- * Return the smallest amount of data between the
- * requested amount and the size of the Page83 data.
- */
- rtn_len = min(rqst_len, sizeof (struct vpd_hdr) +
- page83_len);
-
- /*
- * Information obtained from:
- * SPC-3 Revision 21c
- * Section 7.6.4.1
- */
-
- /* ---- VPD header ---- */
- vhp = (struct vpd_hdr *)v;
- vhp->device_type = lu->l_dtype;
- vhp->periph_qual = SPC_INQUIRY_PERIPH_CONN;
- vhp->page_code = cdb[2];
- vhp->page_len[0] = hibyte(loword(page83_len));
- vhp->page_len[1] = lobyte(loword(page83_len));
- rbp = (uint8_t *)v + sizeof (*vhp);
-
- /* ---- VPD descriptor ---- */
- /*
- * SPC-4 revision 1a, section 7.6.3.8
- * Target port group designator format
- */
- /* initialize descriptor */
- bzero(&vd, sizeof (vd));
- vd.code_set = SPC_INQUIRY_CODE_SET_BINARY;
- vd.id_type = SPC_INQUIRY_ID_TYPE_TARG_PORT;
- vd.proto_id = SPC_INQUIRY_PROTOCOL_ISCSI;
- vd.association = SPC_INQUIRY_ASSOC_TARGPORT;
- vd.piv = 1;
- vd.len = 4;
- bcopy(&vd, rbp, sizeof (vd));
- rbp += sizeof (vd);
-
- len = SPC_DEFAULT_TPG;
- rbp[2] = hibyte(loword(len));
- rbp[3] = lobyte(loword(len));
- rbp += vd.len;
-
- /* ---- VPD descriptor ---- */
- /*
- * SPC-4, revision 1a, section 7.6.3.7
- * Relative target port designator format
- */
- vd.code_set = SPC_INQUIRY_CODE_SET_BINARY;
- vd.id_type = SPC_INQUIRY_ID_TYPE_RELATIVE;
- vd.proto_id = SPC_INQUIRY_PROTOCOL_ISCSI;
- vd.association = SPC_INQUIRY_ASSOC_TARGPORT;
- vd.piv = 1;
- vd.len = 4;
- bcopy(&vd, rbp, sizeof (vd));
- rbp += sizeof (vd);
-
- rbp[2] = hibyte(loword(cmd->c_lu->l_targ->s_tpgt));
- rbp[3] = lobyte(loword(cmd->c_lu->l_targ->s_tpgt));
- rbp += vd.len;
-
- assert(lu->l_guid != NULL);
- /* ---- VPD descriptor ---- */
- vd.code_set = SPC_INQUIRY_CODE_SET_BINARY;
- vd.id_type = SUN_INQUIRY_ID_TYPE(lu->l_guid);
- vd.proto_id = SPC_INQUIRY_PROTOCOL_ISCSI;
- vd.association = SPC_INQUIRY_ASSOC_LUN;
- /*
- * If the ASSOCIATION field contains a value other
- * than 01b or 10b, then the PIV bit contents are
- * reserved. SPC-4 revision 11 section 7.6.3.1.
- */
- vd.piv = 0;
- vd.len = lu->l_guid_len;
- bcopy(&vd, rbp, sizeof (vd));
- rbp += sizeof (vd);
-
- bcopy(lu->l_guid, &rbp[0], lu->l_guid_len);
- rbp += lu->l_guid_len;
-
- /* ---- VPD descriptor ---- */
- vd.code_set = SPC_INQUIRY_CODE_SET_UTF8;
- vd.id_type = SPC_INQUIRY_ID_TYPE_SCSI;
- vd.proto_id = SPC_INQUIRY_PROTOCOL_ISCSI;
- vd.association = SPC_INQUIRY_ASSOC_TARG;
- vd.piv = 1;
- vd.len = scsi_len;
- bcopy(&vd, rbp, sizeof (vd));
- rbp += sizeof (vd);
-
- /*
- * SPC-3 revision 23, section 7.6.3.11
- * Use the string length and not the scsi_len because
- * we've rounded up the length to a multiple of four
- * as required by the specification.
- */
- bcopy(cmd->c_lu->l_targ->s_targ_base, &rbp[0],
- strlen(cmd->c_lu->l_targ->s_targ_base));
- rbp += vd.len;
-
- /* ---- VPD descriptor ---- */
- vd.code_set = SPC_INQUIRY_CODE_SET_BINARY;
- vd.id_type = SUN_INQUIRY_ID_TYPE(lu->l_guid);
- vd.proto_id = SPC_INQUIRY_PROTOCOL_ISCSI;
- vd.association = SPC_INQUIRY_ASSOC_TARG;
- vd.piv = 1;
- vd.len = lu->l_guid_len;
- bcopy(&vd, rbp, sizeof (vd));
- rbp += sizeof (vd);
-
- /*
- * XXX Is this right XXX
- * Should we be using some other name.
- */
- bcopy(lu->l_guid, &rbp[0], lu->l_guid_len);
- rbp += lu->l_guid_len;
-
- /* ---- VPD descriptor ---- */
- vd.code_set = SPC_INQUIRY_CODE_SET_BINARY;
- vd.id_type = SUN_INQUIRY_ID_TYPE(lu->l_guid);
- vd.proto_id = SPC_INQUIRY_PROTOCOL_ISCSI;
- vd.association = SPC_INQUIRY_ASSOC_TARGPORT;
- vd.piv = 1;
- vd.len = lu->l_guid_len;
- bcopy(&vd, rbp, sizeof (vd));
- rbp += sizeof (vd);
-
- /*
- * XXX Is this right XXX
- * Should we be using some other name.
- */
- bcopy(lu->l_guid, &rbp[0], lu->l_guid_len);
-
- /*
- * rbp is updated here even though nobody will
- * currently use it. Currently is the optertive word
- * here. If for some reason we add another VDP
- * then the pointer will be correct.
- */
- rbp += lu->l_guid_len;
-
- break;
-
- case SPC_INQ_PAGE86:
- /*
- * Return the smallest amount of data between the
- * requested amount and the size of the Page86 data.
- */
- rtn_len = min(rqst_len, sizeof (*eid));
- eid = (extended_inq_data_t *)v;
- eid->ei_hdr.device_type = lu->l_dtype;
- eid->ei_hdr.page_code = cdb[2];
- eid->ei_hdr.page_len[1] = 60; /* defined by spec */
-
- /*
- * At this point in time we don't support any of the
- * extended data attributes. We should support
- * the task management bits though.
- */
- break;
- }
- }
-
- if (trans_send_datain(cmd, (char *)rsp_buf, rtn_len, 0, spc_free,
- True, rsp_buf) == False) {
- trans_send_complete(cmd, STATUS_BUSY);
- }
-}
-
-/*
- * []----
- * | spc_mselect -- Generic MODE SELECT command
- * []----
- */
-/*ARGSUSED*/
-void
-spc_mselect(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- char *buf;
-
- /*
- * SPC-3 revision 21c, section 6.7
- * Reserve bit checks
- */
- if ((cdb[1] & 0xee) || cdb[2] || cdb[3] ||
- SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- if (cdb[4] == 0) {
- trans_send_complete(cmd, STATUS_GOOD);
- return;
- }
-
- if (((buf = (char *)calloc(1, cdb[4])) == NULL) ||
- (trans_rqst_dataout(cmd, buf, cdb[4], 0, buf,
- spc_free) == False)) {
- trans_send_complete(cmd, STATUS_BUSY);
- }
-}
-
-/*
- * []----
- * | spc_mselect_data -- DataIn phase of MODE SELECT command
- * []----
- */
-/*ARGSUSED*/
-void
-spc_mselect_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset, char *data,
- size_t data_len)
-{
- struct mode_control_scsi3 mode_ctl_page;
- struct mode_header hdr;
-
- bcopy(data, &hdr, sizeof (hdr));
- bcopy(data + sizeof (hdr) + hdr.bdesc_length, &mode_ctl_page,
- sizeof (mode_ctl_page));
-
- switch (mode_ctl_page.mode_page.code) {
- case MODE_SENSE_CONTROL:
- /*
- * SPC-3 revision 21c, section 7.4.6
- * Table 239 describes the fields. We're only interested
- * in the descriptor sense bit.
- */
- if (mode_ctl_page.d_sense == 1) {
- cmd->c_lu->l_dsense_enabled = True;
- } else {
- cmd->c_lu->l_dsense_enabled = False;
- }
- break;
-
- default:
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- trans_send_complete(cmd, STATUS_GOOD);
-}
-
-/*
- * []----
- * | spc_report_luns --
- * []----
- */
-/*ARGSUSED*/
-void
-spc_report_luns(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- int expected_data;
- uint8_t *buf = NULL;
- int entries = 0;
- int len;
- int len_network;
- int select;
- int lun_idx;
- int lun_val;
- char *str;
- tgt_node_t *targ;
- tgt_node_t *lun_list;
- tgt_node_t *lun;
-
- /*
- * SPC-3 Revision 21c section 6.21
- * Error checking.
- */
- if (cdb[1] || cdb[3] || cdb[4] ||
- (cdb[2] & ~SPC_RPT_LUNS_SELECT_MASK) || cdb[5] || cdb[10] ||
- SAM_CONTROL_BYTE_RESERVED(cdb[11])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- expected_data = cdb[6] << 24 | cdb[7] << 16 | cdb[8] << 8 | cdb[9];
- if (expected_data < 16) {
- /*
- * The allocation length should be at least 16 according
- * to SPC-3.
- */
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- select = cdb[2];
-
- targ = NULL;
- (void) pthread_rwlock_rdlock(&targ_config_mutex);
- while ((targ = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
- targ)) != NULL) {
- if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &str) ==
- False) {
- goto error;
- }
- if (strcmp(str, cmd->c_lu->l_targ->s_targ_base) == 0) {
- free(str);
- break;
- } else
- free(str);
- }
- if (!targ)
- goto error;
- if ((lun_list = tgt_node_next(targ, XML_ELEMENT_LUNLIST, NULL)) == NULL)
- goto error;
-
- lun = NULL;
- while ((lun = tgt_node_next(lun_list, XML_ELEMENT_LUN, lun)) != NULL)
- entries++;
-
-
- len = entries * SCSI_REPORTLUNS_ADDRESS_SIZE;
- if ((buf = (uint8_t *)calloc(1, MAX(expected_data, len))) == NULL) {
- trans_send_complete(cmd, STATUS_BUSY);
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return;
- }
-
- len_network = htonl(len);
- bcopy(&len_network, buf, sizeof (len_network));
-
- if (expected_data >= (len + SCSI_REPORTLUNS_ADDRESS_SIZE)) {
-
- lun_idx = SCSI_REPORTLUNS_ADDRESS_SIZE;
- lun = NULL;
- while ((lun = tgt_node_next(lun_list, XML_ELEMENT_LUN, lun)) !=
- NULL) {
- if (tgt_find_value_int(lun, XML_ELEMENT_LUN,
- &lun_val) == False)
- goto error;
- if (spc_encode_lu_addr(&buf[lun_idx], select,
- lun_val) == False)
- continue;
- lun_idx += SCSI_REPORTLUNS_ADDRESS_SIZE;
- }
- if (trans_send_datain(cmd, (char *)buf,
- len + SCSI_REPORTLUNS_ADDRESS_SIZE, 0, spc_free, True,
- buf) == False) {
- trans_send_complete(cmd, STATUS_BUSY);
- }
- } else {
- /*
- * This will return the size needed to complete this request
- * and a implicit LUN zero.
- */
- if (trans_send_datain(cmd, (char *)buf, 16, 0, spc_free, True,
- buf) == False) {
- trans_send_complete(cmd, STATUS_BUSY);
- }
- }
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return;
-
-error:
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- if (buf)
- free(buf);
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
-}
-
-/*ARGSUSED*/
-void
-spc_report_tpgs(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- rtpg_hdr_t *r;
- rtpg_desc_t *dp;
- rtpg_targ_desc_t *tp;
- int rqst_len;
- int alloc_len;
- int i;
- t10_lu_common_t *lu = cmd->c_lu->l_common;
- t10_lu_impl_t *lu_per;
-
- if (disable_tpgs == True) {
- spc_unsupported(cmd, cdb, cdb_len);
- return;
- }
-
- /*
- * Reserve bit checks
- */
- if ((cdb[1] & 0xe0) || (cdb[1] & ~SPC_MI_SVC_MASK) ||
- ((cdb[1] & SPC_MI_SVC_MASK) != SPC_MI_SVC_RTPG) ||
- cdb[2] || cdb[3] || cdb[4] || cdb[5] ||
- cdb[10] || SAM_CONTROL_BYTE_RESERVED(cdb[11])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- /*
- * We only have one target port group which it's size is
- * accounted for in rtpg_hdr_t. Take the number of tgts
- * and subtract one since the first is accounted for in
- * rtpg_targ_desc_t
- */
- (void) pthread_mutex_lock(&lu->l_common_mutex);
- alloc_len = ((avl_numnodes(&lu->l_all_open) - 1) *
- sizeof (rtpg_targ_desc_t)) + sizeof (rtpg_hdr_t);
- (void) pthread_mutex_unlock(&lu->l_common_mutex);
-
- /*
- * Make sure that we have enough room to store everything
- * that we want to, but only returned the requested about
- * of data which is why d->d_len is set to the request amount.
- * A client could issue a REPORT_TPGS with a length of 4 bytes
- * which would be just enough to see how much space is actually
- * used.
- */
- rqst_len = cdb[6] << 24 | cdb[7] << 16 |
- cdb[8] << 8 | cdb[9];
-
- if (rqst_len == 0) {
- trans_send_complete(cmd, STATUS_GOOD);
- return;
- }
-
- if ((r = (rtpg_hdr_t *)calloc(1, alloc_len)) == NULL) {
- trans_send_complete(cmd, STATUS_BUSY);
- return;
- }
-
- i = alloc_len - sizeof (r->len);
- r->len[0] = hibyte(hiword(i));
- r->len[1] = lobyte(hiword(i));
- r->len[2] = hibyte(loword(i));
- r->len[3] = lobyte(loword(i));
- dp = &r->desc_list[0];
- (void) pthread_mutex_lock(&lu->l_common_mutex);
- dp->tpg_cnt = avl_numnodes(&lu->l_all_open);
- (void) pthread_mutex_unlock(&lu->l_common_mutex);
- dp->status_code = 0;
- dp->access_state = 0; /* Active/optimized */
- dp->pref = 1;
- dp->t_sup = 1;
- dp->u_sup = 1;
- dp->s_sup = 1;
- dp->an_sup = 0;
- dp->ao_sup = 1;
- i = SPC_DEFAULT_TPG;
- dp->tpg[0] = hibyte(loword(i));
- dp->tpg[1] = lobyte(loword(i));
-
- tp = &dp->targ_list[0];
- (void) pthread_mutex_lock(&lu->l_common_mutex);
- lu_per = avl_first(&lu->l_all_open);
- do {
- tp->rel_tpi[0] = hibyte(loword(lu_per->l_targ->s_tpgt));
- tp->rel_tpi[1] = lobyte(loword(lu_per->l_targ->s_tpgt));
- lu_per = AVL_NEXT(&lu->l_all_open, lu_per);
- tp++;
- } while (lu_per != NULL);
- (void) pthread_mutex_unlock(&lu->l_common_mutex);
-
- if (trans_send_datain(cmd, (char *)r, MIN(rqst_len, alloc_len), 0,
- spc_free, True, (char *)r) == False) {
- trans_send_complete(cmd, STATUS_BUSY);
- }
-}
-
-/*ARGSUSED*/
-void
-spc_send_diag(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- /*
- * SPC-3 Revision 21c, section 6.27
- * Reserve bit checks
- */
- if ((cdb[1] & ~SPC_SEND_DIAG_SELFTEST) || cdb[2] || cdb[3] || cdb[4] ||
- SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- /*
- * There's no diagnostics to be run at this time. So, always
- * return success. If, at some point in the future, it's determined
- * that something can be done which is meaningful then place the
- * code here.
- */
- trans_send_complete(cmd, STATUS_GOOD);
-}
-
-void
-spc_free(emul_handle_t id)
-{
- free(id);
-}
-
-/*
- * []----
- * | spc_cmd_offline -- return IN_PROGRESS for media related commands
- * |
- * | During LU initialization the device is in an offline state. When
- * | offlined only non-media related commands are allowed to proceed.
- * | TEST_UNIT_READY is considered a media command since it must return
- * | a CHECK_CONDITION if a media command would do so.
- * []----
- */
-void
-spc_cmd_offline(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- scsi_cmd_table_t *e;
- int old_dtype;
-
- e = &cmd->c_lu->l_cmd_table[cdb[0]];
-
- switch (cdb[0]) {
- case SCMD_TEST_UNIT_READY:
- case SCMD_START_STOP:
- case SCMD_READ:
- case SCMD_READ_G1:
- case SCMD_READ_G4:
- case SCMD_WRITE:
- case SCMD_WRITE_G1:
- case SCMD_WRITE_G4:
-#ifdef FULL_DEBUG
- queue_prt(mgmtq, Q_STE_IO, "SPC%x LUN%d Cmd %s\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- e->cmd_name == NULL ? "(no name)" : e->cmd_name);
-#endif
- spc_sense_create(cmd, KEY_NOT_READY, 0);
- spc_sense_ascq(cmd, SPC_ASC_IN_PROG, SPC_ASCQ_IN_PROG);
- trans_send_complete(cmd, STATUS_CHECK);
- break;
-
- case SCMD_INQUIRY:
- /*
- * While the device is being initialized any inquiry commands
- * will return an unknown device type. This will cause the
- * transport to hold off further plumbing until the
- * initialization is complete and we send the inventory change
- * notice.
- */
- old_dtype = cmd->c_lu->l_common->l_dtype;
- cmd->c_lu->l_common->l_dtype = 0x1f;
- (*e->cmd_start)(cmd, cdb, cdb_len);
- cmd->c_lu->l_common->l_dtype = old_dtype;
- break;
-
- default:
- (*e->cmd_start)(cmd, cdb, cdb_len);
- break;
- }
-}
-
-/*
- * []----
- * | spc_sense_create -- allocate sense structure
- * |
- * | If additional header sense length is requested and the I_T_Q has
- * | enabled descriptor sense data allocate the space.
- * []----
- */
-void
-spc_sense_create(t10_cmd_t *cmd, int sense_key, int addl_sense_len)
-{
- char *buf;
- int size;
-
- /*
- * It's possible under certain conditions -- namely a malloc error
- * when setting up a command -- that the pointer to the ITL structure
- * isn't valid. If that's the case don't attempt to dereference it
- * to look at the dsense_enabled flag.
- */
- if ((cmd->c_lu != NULL) && (cmd->c_lu->l_dsense_enabled == True)) {
- struct scsi_descr_sense_hdr d;
-
- if ((buf = (char *)calloc(1,
- sizeof (d) + 2 + addl_sense_len)) == NULL)
- return;
-
- size = sizeof (d) + addl_sense_len;
- bzero(&d, sizeof (d));
- d.ds_class = CLASS_EXTENDED_SENSE;
- d.ds_code = CODE_FMT_DESCR_CURRENT;
- d.ds_key = sense_key;
- d.ds_addl_sense_length = addl_sense_len;
- bcopy(&d, &buf[2], sizeof (d));
-
- } else {
- struct scsi_extended_sense e;
-
- if ((buf = (char *)calloc(1, sizeof (e) + 2)) == NULL)
- return;
- size = sizeof (e);
- bzero(&e, sizeof (e));
- e.es_class = CLASS_EXTENDED_SENSE;
- e.es_code = CODE_FMT_FIXED_CURRENT;
- e.es_key = sense_key;
- bcopy(&e, &buf[2], size);
-
- }
-
- /* ---- First two bytes of the sense store the length ---- */
- buf[0] = hibyte(loword(size));
- buf[1] = lobyte(loword(size));
-
- cmd->c_cmd_sense = buf;
- cmd->c_cmd_sense_len = size + 2;
-}
-
-/*
- * []----
- * | spc_sense_raw -- copy an existing sense buffer for return.
- * |
- * | If an emulation module already has a sense buffer there's no need
- * | to decode the sense data and call the various spc_sense_ routines
- * | to reencode the information.
- * []----
- */
-void
-spc_sense_raw(t10_cmd_t *cmd, uchar_t *sense_buf, size_t sense_len)
-{
- ushort_t s = (ushort_t)sense_len;
- if ((cmd->c_cmd_sense = malloc(sense_len + 2)) == NULL)
- return;
- bcopy(sense_buf, &cmd->c_cmd_sense[2], sense_len);
- cmd->c_cmd_sense[0] = hibyte(s);
- cmd->c_cmd_sense[1] = lobyte(s);
- cmd->c_cmd_sense_len = s + 2;
-}
-
-void
-spc_sense_ascq(t10_cmd_t *cmd, int asc, int ascq)
-{
- struct scsi_extended_sense s;
- struct scsi_descr_sense_hdr d;
-
- bcopy(&cmd->c_cmd_sense[2], &s, sizeof (s));
-
- switch (s.es_code) {
- case CODE_FMT_DESCR_CURRENT:
- case CODE_FMT_DESCR_DEFERRED:
- bcopy(&cmd->c_cmd_sense[2], &d, sizeof (d));
- d.ds_add_code = asc;
- d.ds_qual_code = ascq;
- bcopy(&d, &cmd->c_cmd_sense[2], sizeof (d));
- break;
-
- default:
- s.es_add_code = asc;
- s.es_qual_code = ascq;
- bcopy(&s, &cmd->c_cmd_sense[2], sizeof (s));
- break;
- }
-}
-
-void
-spc_sense_info(t10_cmd_t *cmd, uint64_t info)
-{
- struct scsi_information_sense_descr isd;
- struct scsi_extended_sense s;
- char *p;
- uint32_t fixed_info = (uint32_t)info;
-
- switch (cmd->c_cmd_sense[2] & 0x0f) {
- case CODE_FMT_DESCR_CURRENT:
- case CODE_FMT_DESCR_DEFERRED:
- isd.isd_descr_type = DESCR_INFORMATION;
- isd.isd_addl_length = 0x0a;
- isd.isd_valid = 1;
- isd.isd_information[0] = (info >> 56) & 0xff;
- isd.isd_information[1] = (info >> 48) & 0xff;
- isd.isd_information[2] = (info >> 40) & 0xff;
- isd.isd_information[3] = (info >> 32) & 0xff;
- isd.isd_information[4] = (info >> 24) & 0xff;
- isd.isd_information[5] = (info >> 16) & 0xff;
- isd.isd_information[6] = (info >> 8) & 0xff;
- isd.isd_information[7] = info & 0xff;
- p = &cmd->c_cmd_sense[2] + sizeof (struct scsi_descr_sense_hdr);
- bcopy(&isd, p, sizeof (isd));
- break;
-
- case CODE_FMT_VENDOR_SPECIFIC:
- case CODE_FMT_FIXED_CURRENT:
- case CODE_FMT_FIXED_DEFERRED:
- default:
- bcopy(&cmd->c_cmd_sense[2], &s, sizeof (s));
-
- s.es_valid = 1;
- if (info > FIXED_SENSE_ADDL_INFO_LEN) {
- s.es_info_1 = 0xff;
- s.es_info_2 = 0xff;
- s.es_info_3 = 0xff;
- s.es_info_4 = 0xff;
- } else {
- s.es_info_1 = hibyte(hiword(fixed_info));
- s.es_info_2 = lobyte(hiword(fixed_info));
- s.es_info_3 = hibyte(loword(fixed_info));
- s.es_info_4 = lobyte(loword(fixed_info));
- }
- bcopy(&s, &cmd->c_cmd_sense[2], sizeof (s));
- break;
- }
-}
-
-void
-spc_sense_flags(t10_cmd_t *cmd, int flags)
-{
- struct scsi_extended_sense s;
-
- bcopy(&cmd->c_cmd_sense[2], &s, sizeof (s));
- if (flags & SPC_SENSE_EOM)
- s.es_eom = 1;
- if (flags & SPC_SENSE_FM)
- s.es_filmk = 1;
- if (flags & SPC_SENSE_ILI)
- s.es_ili = 1;
- bcopy(&s, &cmd->c_cmd_sense[2], sizeof (s));
-}
-
-/*
- * []----
- * | spc_decode_lu_addr -- Decodes LU addressing as specified in SAM-3
- * []----
- */
-Boolean_t
-spc_decode_lu_addr(uint8_t *buf, int len, uint32_t *val)
-{
- uint32_t lun;
-
- if (len < 2)
- return (False);
-
- switch (buf[0] & SCSI_REPORTLUNS_ADDRESS_MASK) {
- case SCSI_REPORTLUNS_ADDRESS_PERIPHERAL:
- case SCSI_REPORTLUNS_ADDRESS_FLAT_SPACE:
- lun = ((buf[0] & 0x3f) << 8) | (buf[1] & 0xff);
- break;
-
- /*
- * Since we never encode a LUN using this method, we
- * shouldn't receive it back.
- */
- case SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT:
- return (False);
-
- case SCSI_REPORTLUNS_ADDRESS_EXTENDED_UNIT:
- switch (buf[0] & SCSI_REPORTLUNS_ADDRESS_EXTENDED_MASK) {
- case SCSI_REPORTLUNS_ADDRESS_EXTENDED_2B:
- lun = buf[1] & 0xff;
- break;
-
- case SCSI_REPORTLUNS_ADDRESS_EXTENDED_4B:
- if (len < 4)
- return (False);
- lun = buf[1] << 16 | buf[2] << 8 | (buf[3] & 0xff);
- break;
-
- case SCSI_REPORTLUNS_ADDRESS_EXTENDED_6B:
- if (len < 6)
- return (False);
- /*
- * This should be able to handle a 40-bit LUN,
- * but since our LUNs are only 32-bit we don't
- * bother to decode buf[1]. This is okay since
- * we generate the LUN in the first place.
- */
- lun = buf[2] << 24 | buf[3] << 16 |
- buf[4] << 8 | (buf[5] & 0xff);
- break;
-
- case SCSI_REPORTLUNS_ADDRESS_EXTENDED_8B:
- /*
- * Since we current don't support larger than
- * 32-bit LUNs we'll never create an extended
- * address using this format. So, if we are to
- * get this format in, just return an error.
- */
- return (False);
-
- break;
- }
- }
- *val = lun;
- return (True);
-}
-
-/*
- * []----
- * | spc_encode_lu_addr -- encode, based on SAM-3/SPC-3 specs, a LUN
- * |
- * | NOTE: This routine only deals with 32-bit logical unit numbers.
- * | If this program ever switches to using larger values we need to
- * | simply deal with those formats.
- * []----
- */
-Boolean_t
-spc_encode_lu_addr(uint8_t *buf, int select_field, uint32_t lun)
-{
- if (lun < 256) {
-
- /*
- * SAM-3 revision 14, Section 4.9.6.
- * No bus identifier for our luns.
- */
- buf[0] = SCSI_REPORTLUNS_ADDRESS_PERIPHERAL;
- buf[1] = lun;
-
- } else if (lun <= T10_MAX_LUNS) {
-
- /*
- * SAM-3 revision 14, Section 4.9.7.
- * 14-bit flat address space.
- */
- buf[0] = SCSI_REPORTLUNS_ADDRESS_FLAT_SPACE | (lun >> 8 & 0x3f);
- buf[1] = lun & 0xff;
-
- } else if (select_field == SCSI_REPORTLUNS_SELECT_ALL) {
-
- buf[0] = SCSI_REPORTLUNS_ADDRESS_EXTENDED_UNIT |
- SCSI_REPORTLUNS_ADDRESS_EXTENDED_6B;
- /*
- * 32-bit limitation. This format should be able to
- * handle a 40-bit LUN.
- */
- buf[1] = 0;
- buf[2] = lun >> 24 & 0xff;
- buf[3] = lun >> 16 & 0xff;
- buf[4] = lun >> 8 & 0xff;
- buf[5] = lun & 0xff;
- } else
- /*
- * Either the user hasn't requested extended unit addressing
- * or the LU is greater than 32bits. Since internally we
- * only have 32bit numbers it's more likely that the initiator
- * hasn't selected a correct report format.
- */
- return (False);
- return (True);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/t10_spc.h b/usr/src/cmd/iscsi/iscsitgtd/t10_spc.h
deleted file mode 100644
index be93c43e29..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_spc.h
+++ /dev/null
@@ -1,460 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _T10_SPC_H
-#define _T10_SPC_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * []------------------------------------------------------------------[]
- * | SPC-3 |
- * []------------------------------------------------------------------[]
- */
-
-/*
- * FIXED_SENSE_ADDL_INFO_LEN is the length of INFORMATION field
- * in fixed format sense data
- */
-#define FIXED_SENSE_ADDL_INFO_LEN 0xFFFFFFFF
-#define INFORMATION_SENSE_DESCR sizeof (struct scsi_information_sense_descr)
-
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <sys/scsi/generic/inquiry.h>
-#include <sys/scsi/generic/mode.h>
-
-/*
- * SPC Command Functions
- */
-void spc_tur(struct t10_cmd *cmd, uint8_t *cdb, size_t cdb_len);
-void spc_request_sense(struct t10_cmd *cmd, uint8_t *cdb, size_t cdb_len);
-void spc_unsupported(struct t10_cmd *cmd, uint8_t *cdb, size_t cdb_len);
-void spc_inquiry(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
-void spc_mselect(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
-void spc_mselect_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset,
- char *data, size_t data_len);
-void spc_report_luns(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
-void spc_report_tpgs(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
-void spc_msense(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
-void spc_startstop(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
-void spc_send_diag(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
-
-/*
- * SPC Support Functions
- */
-void spc_cmd_offline(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
-void spc_sense_create(struct t10_cmd *cmd, int sense_key, int addl_sense_len);
-void spc_sense_ascq(struct t10_cmd *cmd, int asc, int ascq);
-void spc_sense_info(t10_cmd_t *cmd, uint64_t info);
-void spc_sense_flags(t10_cmd_t *cmd, int flags);
-void spc_sense_raw(t10_cmd_t *cmd, uchar_t *sense_buf, size_t sense_len);
-Boolean_t spc_decode_lu_addr(uint8_t *buf, int len, uint32_t *val);
-Boolean_t spc_encode_lu_addr(uint8_t *buf, int select_field, uint32_t lun);
-
-/*
- * SPC flags to use when setting various sense code flags
- */
-#define SPC_SENSE_EOM 0x01
-#define SPC_SENSE_FM 0x02
-#define SPC_SENSE_ILI 0x04
-
-/*
- * []------------------------------------------------------------------[]
- * | SPC-3, revision 21c -- ASC/ASCQ values |
- * | The full tables can be found in Appendix D (numerical order) or |
- * | section 4.5.6 (alphabetical order). There are close to fifteen |
- * | pages of values which will not be included here. Only those used |
- * | by the code. |
- * []------------------------------------------------------------------[]
- */
-#define SPC_ASC_FM_DETECTED 0x00 /* file-mark detected */
-#define SPC_ASCQ_FM_DETECTED 0x01
-
-#define SPC_ASC_EOP 0x00 /* end-of-partition/medium detected */
-#define SPC_ASCQ_EOP 0x02
-
-#define SPC_ASC_IN_PROG 0x04
-#define SPC_ASCQ_IN_PROG 0x07
-
-#define SPC_ASC_WRITE_ERROR 0x0c
-#define SPC_ASCQ_WRITE_ERROR 0x00
-
-#define SPC_ASC_PARAM_LIST_LEN 0x1a /* Parameter List Length Error */
-#define SPC_ASCQ_PARAM_LIST_LEN 0x00
-
-#define SPC_ASC_MISCOMPARE 0x1d
-#define SPC_ASCQ_MISCOMPARE 0x00
-
-#define SPC_ASC_INVALID_LU 0x20
-#define SPC_ASCQ_INVALID_LU 0x09
-
-#define SPC_ASC_BLOCK_RANGE 0x21
-#define SPC_ASCQ_BLOCK_RANGE 0x00
-
-#define SPC_ASC_INVALID_FIELD_IN_PARAMETER_LIST 0x26
-#define SPC_ASCQ_INVALID_FIELD_IN_PARAMETER_LIST 0x00
-
-#define SPC_ASC_INVALID_CDB 0x24
-#define SPC_ASCQ_INVALID_CDB 0x00
-
-#define SPC_ASC_PARAMETERS_CHANGED 0x2a
-#define SPC_ASCQ_RES_PREEMPTED 0x03
-#define SPC_ASCQ_RES_RELEASED 0x04
-
-#define SPC_ASC_PWR_RESET 0x29
-#define SPC_ASCQ_PWR_RESET 0x00
-
-#define SPC_ASC_PWR_ON 0x29
-#define SPC_ASCQ_PWR_ON 0x01
-
-#define SPC_ASC_BUS_RESET 0x29
-#define SPC_ASCQ_BUS_RESET 0x02
-
-#define SPC_ASC_CAP_CHANGE 0x2a
-#define SPC_ASCQ_CAP_CHANGE 0x09
-
-#define SPC_ASC_DATA_PATH 0x41
-#define SPC_ASCQ_DATA_PATH 0x00
-
-#define SPC_ASC_MEMORY_OUT_OF 0x55 /* Auxillary Memory Out Of Space */
-#define SPC_ASCQ_MEMORY_OUT_OF 0x00
-#define SPC_ASCQ_RESERVATION_FAIL 0x02
-
-
-/*
- * []------------------------------------------------------------------[]
- * | SAM-3, revision 14, section 5.2 - Command descriptor block (CDB) |
- * | |
- * | "All CDBs shall contain a CONTROL byte (see table 21). The |
- * | location of the CONTROL byte within a CDB depends on the CDB |
- * | format (see SPC-3)." |
- * | |
- * | bits meaning |
- * | 6-7 vendor specific (we don't use so must be zero) |
- * | 3-5 reserved must be zero |
- * | 2 NACA (currently we don't support so must be zero) |
- * | 1 Obsolete |
- * | 0 Link (currently we don't support so must be zero) |
- * | |
- * | So, this means the control byte must be zero and therefore if |
- * | this macro returns a non-zero value the emulation code should |
- * | return a CHECK CONDITION with status set to ILLEGAL REQUEST |
- * | and the additional sense code set to INVALID FIELD IN CDB. |
- * | |
- * | In the future this will likely change with support routines |
- * | added for dealing with NACA and Linked commands. |
- * []------------------------------------------------------------------[]
- */
-#define SAM_CONTROL_BYTE_RESERVED(byte) (byte)
-
-/* ---- Disable Block Descriptors ---- */
-#define SPC_MODE_SENSE_DBD 0x8
-
-#define SPC_GROUP4_SERVICE_ACTION_MASK 0x1f
-
-#define SPC_SEND_DIAG_SELFTEST 0x04
-
-/*
- * []------------------------------------------------------------------[]
- * | SPC-3 revision 21c, section 6.4 -- INQUIRY |
- * | Various defines. The structure for the inquiry command can be |
- * | found in /usr/include/sys/scsi/generic/inquiry.h |
- * []------------------------------------------------------------------[]
- */
-#define SPC_INQUIRY_CODE_SET_BINARY 1
-#define SPC_INQUIRY_CODE_SET_ASCII 2
-#define SPC_INQUIRY_CODE_SET_UTF8 3
-
-/* ---- Table 82: Inquiry Version ---- */
-#define SPC_INQ_VERS_NONE 0x00
-#define SPC_INQ_VERS_OBSOLETE 0x02
-#define SPC_INQ_VERS_SPC_1 0x03
-#define SPC_INQ_VERS_SPC_2 0x04
-#define SPC_INQ_VERS_SPC_3 0x05
-
-/* ---- INQUIRY Response Data Format field ---- */
-#define SPC_INQ_RDF 0x02 /* all other values are OBSOLETE */
-
-/*
- * Table 85 -- Version descriptor values
- * There are many, many different values available, so we'll only include
- * those that we actually use.
- */
-#define SPC_INQ_VD_SAM3 0x0076
-#define SPC_INQ_VD_SPC3 0x0307
-#define SPC_INQ_VD_SBC2 0x0322
-#define SPC_INQ_VD_SSC3 0x0400
-#define SPC_INQ_VD_OSD 0x0355
-
-/* --- Version Descriptor length details --- */
-#define SPC_INQ_VD_IDX 0x3A
-#define SPC_INQ_VD_LEN 0x10
-
-#define SPC_INQ_PAGE0 0x00
-#define SPC_INQ_PAGE80 0x80
-#define SPC_INQ_PAGE83 0x83
-#define SPC_INQ_PAGE86 0x86
-
-/* ---- REPORT LUNS select report has valid values of 0, 1, or 2 ---- */
-#define SPC_RPT_LUNS_SELECT_MASK 0x03
-
-/* ---- Table 293: IDENTIFIER TYPE field ---- */
-#define SPC_INQUIRY_ID_TYPE_T10ID 1 /* ref 7.6.4.3 */
-#define SPC_INQUIRY_ID_TYPE_EUI 2 /* ref 7.6.4.4 */
-#define SPC_INQUIRY_ID_TYPE_NAA 3 /* ref 7.6.4.5 */
-#define SPC_INQUIRY_ID_TYPE_RELATIVE 4 /* ref 7.6.4.6 */
-#define SPC_INQUIRY_ID_TYPE_TARG_PORT 5 /* ref 7.6.4.7 */
-#define SPC_INQUIRY_ID_TYPE_LUN 6 /* ref 7.6.4.8 */
-#define SPC_INQUIRY_ID_TYPE_MD5 7 /* ref 7.6.4.9 */
-#define SPC_INQUIRY_ID_TYPE_SCSI 8 /* ref 7.6.4.10 */
-
-/* ---- Table 292: ASSOCIATION field ---- */
-#define SPC_INQUIRY_ASSOC_LUN 0
-#define SPC_INQUIRY_ASSOC_TARGPORT 1
-#define SPC_INQUIRY_ASSOC_TARG 2
-
-/* ---- Table 80: Peripheral qualifier ---- */
-#define SPC_INQUIRY_PERIPH_CONN 0
-#define SPC_INQUIRY_PERIPH_DISCONN 1
-#define SPC_INQUIRY_PERIPH_INVALID 3
-
-/* ---- Table 256: PROTOCOL IDENTIFIER values ---- */
-#define SPC_INQUIRY_PROTOCOL_FC 0
-#define SPC_INQUIRY_PROTOCOL_PSCSI 1
-#define SPC_INQUIRY_PROTOCOL_SSA 2
-#define SPC_INQUIRY_PROTOCOL_IEEE1394 3
-#define SPC_INQUIRY_PROTOCOL_SCSIRDMA 4
-#define SPC_INQUIRY_PROTOCOL_ISCSI 5
-#define SPC_INQUIRY_PROTOCOL_SAS 6
-#define SPC_INQUIRY_PROTOCOL_ADT 7
-#define SPC_INQUIRY_PROTOCOL_ATA 8
-
-#define SPC_DEFAULT_TPG 1
-
-/*
- * SPC-3, revision 21c, section 7.6.5
- * Extended INQUIRY Data VPD page
- */
-typedef struct extended_inq_data {
- struct vpd_hdr ei_hdr;
-#if defined(_BIT_FIELDS_LTOH)
- uchar_t ei_ref_chk : 1,
- ei_app_chk : 1,
- ei_grd_chk : 1,
- ei_rto : 1,
- ei_rsvd1 : 4;
- uchar_t ei_simpsup : 1,
- ei_ordsup : 1,
- ei_headsup : 1,
- ei_prior_sup : 1,
- ei_group_sup : 1,
- ei_rsvd2 : 3;
- uchar_t ei_v_sup : 1,
- ei_nv_sup : 1,
- ei_rsvd3 : 6;
-#elif defined(_BIT_FIELDS_HTOL)
- uchar_t ei_ref_rsvd1 : 4,
- ei_rto : 1,
- ei_grd_chk : 1,
- ei_app_chk : 1,
- ei_ref_chk : 1;
- uchar_t ei_rsvd2 : 2,
- ei_group_sup : 1,
- ei_prior_sup : 1,
- ei_headsup : 1,
- ei_ordsup : 1,
- ei_simpsup : 1;
- uchar_t ei_rsvd3 : 6,
- ei_nv_sup : 1,
- ei_v_sup : 1;
-#else
-#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
-#endif
- uchar_t ei_rsv4[57];
-} extended_inq_data_t;
-
-
-/*
- * []------------------------------------------------------------------[]
- * | SPC-4 revision 1a, section 6.25 -- REPORT TARGET PORT GROUPS |
- * | Structures and defines |
- * []------------------------------------------------------------------[]
- */
-/*
- * The service action must be set to 0x0A. This command is really a
- * MAINTENANCE_IN command with a specific service action.
- */
-#define SPC_MI_SVC_MASK 0x1f
-#define SPC_MI_SVC_RTPG 0x0a
-
-/* ---- Table 167: Target port descriptor format ---- */
-typedef struct rtpg_targ_desc {
- uchar_t obsolete[2],
- rel_tpi[2];
-} rtpg_targ_desc_t;
-
-/* ---- Table 164: Target port group descript format ---- */
-typedef struct rtpg_desc {
-#if defined(_BIT_FIELDS_LTOH)
- uchar_t access_state : 4,
- : 3,
- pref : 1;
- uchar_t ao_sup : 1,
- an_sup : 1,
- s_sup : 1,
- u_sup : 1,
- : 3,
- t_sup : 1;
-#elif defined(_BIT_FIELDS_HTOL)
- uchar_t pref : 1,
- : 3,
- access_state : 4;
- uchar_t t_sup : 1,
- : 3,
- u_sup : 1,
- s_sup : 1,
- an_sup : 1,
- ao_sup : 1;
-#else
-#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
-#endif
- uchar_t tpg[2],
- reserve_1,
- status_code,
- vendor_spec,
- tpg_cnt;
- rtpg_targ_desc_t targ_list[1];
-} rtpg_desc_t;
-
-/* ---- Table 163: parameter data format. ---- */
-typedef struct rtpg_data {
- uchar_t len[4];
- rtpg_desc_t desc_list[1];
-} rtpg_hdr_t;
-
-/*
- * []------------------------------------------------------------------[]
- * | SPC-3, revision 21c, section 6.6 -- LOG_SENSE |
- * | Structure and defines |
- * []------------------------------------------------------------------[]
- */
-#define SSC_LOG_SP 0x01 /* save parameters */
-#define SSC_LOG_PPC 0x02 /* parameter pointer control */
-#define SPC_LOG_PAGE_MASK 0x3f
-
-/* ---- section 7.2.1, Table 192: Log Parameter ---- */
-typedef struct spc_log_select_param {
- char param_code[2];
-#if defined(_BIT_FIELDS_LTOH)
- char lp : 1, /* list parameter */
- lbin : 1,
- tmc : 2, /* threshold met criteria */
- etc : 1, /* enable threshold comparison */
- tsd : 1, /* target save disable */
- ds : 1, /* disable save */
- du : 1; /* disable update */
-#elif defined(_BIT_FIELDS_HTOL)
- char du : 1, /* disable update */
- ds : 1, /* disable save */
- tsd : 1, /* target save disable */
- etc : 1, /* enable threshold comparison */
- tmc : 2, /* threshold met criteria */
- lbin : 1,
- lp : 1; /* list parameter */
-#else
-#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
-#endif
- char len; /* length of bytes to follow */
-} spc_log_select_param_t;
-
-/* ---- section 7.2.12, table 218: Supported log pages ---- */
-typedef struct spc_log_supported_pages {
- char page_code,
- resvd,
- length[2],
- list[1];
-} spc_log_supported_pages_t;
-
-/*
- * []------------------------------------------------------------------[]
- * | SPC-3, revision 21c, section 6.9 -- MODE_SENSE |
- * | Structures and defines |
- * []------------------------------------------------------------------[]
- */
-/* ---- Section 7.4.6, Table 241: Queue Algorithm Modifer field ---- */
-#define SPC_QUEUE_RESTRICTED 0x00
-#define SPC_QUEUE_UNRESTRICTED 0x01
-
-/* ---- Section 7.4.11, Table 250: Information Controller Page ---- */
-struct mode_info_ctrl {
- struct mode_page mode_page;
- /*
- * Currently we don't sent any of this information and it's set
- * to zero's. We only care about the size.
- */
- char info_data[10];
-};
-
-#define MODE_SENSE_PAGE3_CODE 0x03
-#define MODE_SENSE_PAGE4_CODE 0x04
-#define MODE_SENSE_CACHE 0x08
-#define MODE_SENSE_CONTROL 0x0a
-#define MODE_SENSE_COMPRESSION 0x0f
-#define MODE_SENSE_DEV_CONFIG 0x10
-#define MODE_SENSE_INFO_CTRL 0x1c
-#define MODE_SENSE_SEND_ALL 0x3f
-
-/* -- Page Control Mask for Mode Sense -- */
-#define SPC_MODE_SENSE_PAGE_CODE_MASK 0x3f
-#define SPC_MODE_SENSE_PC_MASK 0xc0
-#define SPC_MODE_SENSE_PC_SHIFT 6
-
-#define SPC_PC_CURRENT_VALUES 0
-#define SPC_PC_MODIFIABLE_VALUES 1
-#define SPC_PC_DEFAULT_VALUES 2
-#define SPC_PC_SAVED_VALUES 3
-
-#define SCSI_REPORTLUNS_ADDRESS_SIZE 8
-#define SCSI_REPORTLUNS_ADDRESS_MASK 0xC0
-#define SCSI_REPORTLUNS_ADDRESS_PERIPHERAL 0x00
-#define SCSI_REPORTLUNS_ADDRESS_FLAT_SPACE 0x40
-#define SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT 0x80
-#define SCSI_REPORTLUNS_ADDRESS_EXTENDED_UNIT 0xC0
-#define SCSI_REPORTLUNS_ADDRESS_EXTENDED_2B 0x00
-#define SCSI_REPORTLUNS_ADDRESS_EXTENDED_4B 0x10
-#define SCSI_REPORTLUNS_ADDRESS_EXTENDED_6B 0x20
-#define SCSI_REPORTLUNS_ADDRESS_EXTENDED_8B 0x30
-#define SCSI_REPORTLUNS_ADDRESS_EXTENDED_MASK 0x30
-#define SCSI_REPORTLUNS_SELECT_ALL 0x02
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _T10_SPC_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.c b/usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.c
deleted file mode 100644
index 7ee28c34ee..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.c
+++ /dev/null
@@ -1,2126 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * []------------------------------------------------------------------[]
- * | Implementation of SPC-3 Persistent Reserve emulation |
- * []------------------------------------------------------------------[]
- */
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/asynch.h>
-#include <sys/param.h>
-#include <sys/sysmacros.h>
-#include <strings.h>
-#include <unistd.h>
-#include <pthread.h>
-#include <assert.h>
-
-#include <sys/scsi/generic/sense.h>
-#include <sys/scsi/generic/status.h>
-#include <sys/scsi/generic/inquiry.h>
-#include <sys/scsi/generic/mode.h>
-#include <sys/scsi/generic/commands.h>
-#include <sys/scsi/generic/persist.h>
-
-#include "t10.h"
-#include "t10_spc.h"
-#include "t10_spc_pr.h"
-#include "t10_sbc.h"
-#include "target.h"
-
-/*
- * External declarations
- */
-extern target_queue_t *mgmtq;
-void spc_free(emul_handle_t id);
-void sbc_cmd(t10_cmd_t *, uint8_t *, size_t);
-void sbc_cmd_reserved(t10_cmd_t *, uint8_t *, size_t);
-
-/*
- * Forward declarations
- */
-static spc_pr_key_t *spc_pr_key_find(scsi3_pgr_t *, uint64_t, char *, char *);
-static spc_pr_key_t *spc_pr_key_alloc(scsi3_pgr_t *, uint64_t, char *, char *);
-static spc_pr_rsrv_t *spc_pr_rsrv_find(scsi3_pgr_t *, uint64_t, char *, char *);
-static spc_pr_rsrv_t *spc_pr_rsrv_alloc(scsi3_pgr_t *, uint64_t, char *, char *,
- uint8_t, uint8_t);
-
-static void spc_pr_key_free(scsi3_pgr_t *, spc_pr_key_t *);
-static void spc_pr_rsrv_free(scsi3_pgr_t *, spc_pr_rsrv_t *);
-static void spc_pr_rsrv_release(t10_cmd_t *, scsi3_pgr_t *, spc_pr_rsrv_t *);
-
-static int spc_pr_out_register(t10_cmd_t *, void *, size_t);
-static int spc_pr_out_reserve(t10_cmd_t *, void *, size_t);
-static int spc_pr_out_release(t10_cmd_t *, void *, size_t);
-static int spc_pr_out_clear(t10_cmd_t *, void *, size_t);
-static int spc_pr_out_preempt(t10_cmd_t *, void *, size_t);
-static int spc_pr_out_register_and_move(t10_cmd_t *, void *, size_t);
-
-static int spc_pr_in_readkeys(char *, scsi3_pgr_t *, void *, uint16_t);
-static int spc_pr_in_readrsrv(char *, scsi3_pgr_t *, void *, uint16_t);
-static int spc_pr_in_repcap(char *, scsi3_pgr_t *, void *, uint16_t);
-static int spc_pr_in_fullstat(char *, scsi3_pgr_t *, void *, uint16_t);
-
-Boolean_t spc_pr_write(t10_cmd_t *);
-static void spc_pr_erase(scsi3_pgr_t *);
-static void spc_pr_initialize(scsi3_pgr_t *);
-
-/*
- * []----
- * | spc_pgr_is_conflicting
- * | PGR reservation conflict checking.
- * | SPC-3, Revision 23, Table 31
- * []----
- */
-static int
-spc_pgr_is_conflicting(uint8_t *cdb, uint_t type)
-{
- Boolean_t conflict = False;
-
- switch (cdb[0]) {
- case SCMD_FORMAT:
- case SCMD_EXTENDED_COPY:
- case SCMD_LOG_SELECT_G1:
- case SCMD_MODE_SELECT:
- case SCMD_MODE_SELECT_G1:
- case SCMD_MODE_SENSE:
- case SCMD_MODE_SENSE_G1:
- case SCMD_READ_ATTRIBUTE:
- case SCMD_READ_BUFFER:
- case SCMD_GDIAG: /* SCMD_RECEIVE_DIAGNOSTIC_RESULTS */
- case SCMD_SDIAG: /* SCMD_SEND_DIAGNOSTIC_RESULTS */
- case SCMD_WRITE_ATTRIBUTE:
- case SCMD_WRITE_BUFFER:
- conflict = True;
- break;
-
- case SCMD_DOORLOCK: /* SCMD_PREVENT_ALLOW_MEDIA_REMOVAL */
- /*
- * As per SPC-3, Revision 23, Table 31
- * (prevent <> 0)
- */
- conflict = (cdb[4] & 0x1) ? True: False;
- break;
-
- case SCMD_MAINTENANCE_IN: /* SCMD_REPORT_ */
- /*
- * As per SPC-3, Revision 23, Section 6.23
- */
- switch ((cdb[1] & 0x1f)) {
- case SSVC_ACTION_GET_SUPPORTED_OPERATIONS:
- case SSVC_SCTION_GET_SUPPORTED_MANAGEMENT:
-
- conflict = True;
- break;
- }
- break;
-
- case SCMD_MAINTENANCE_OUT:
- /*
- * SPC-3, Revision 23, Section 6.29
- */
- switch ((cdb[1] & 0x1F)) {
- case SSVC_ACTION_SET_DEVICE_IDENTIFIER:
- case SSVC_ACTION_SET_PRIORITY:
- case SSVC_ACTION_SET_TARGET_PORT_GROUPS:
- case SSVC_ACTION_SET_TIMESTAMP:
- conflict = True;
- break;
- }
- break;
-
- case SCMD_READ:
- case SCMD_READ_G1:
- case SCMD_READ_G4:
- /*
- * Exclusive Access, and EA Registrants Only
- */
- if (type == PGR_TYPE_EX_AC || type == PGR_TYPE_EX_AC_RO)
- conflict = True;
- break;
- }
-
- return (conflict);
-}
-
-/*
- * []----
- * | spc_npr_check -- NON-PERSISTENT RESERVE check of I_T_L
- * | Refer to SPC-2, Section 5.5.1, Tables 10
- * []----
- */
-Boolean_t
-spc_npr_check(t10_cmd_t *cmd, uint8_t *cdb)
-{
- disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd);
- sbc_reserve_t *res = &p->d_sbc_reserve;
- Boolean_t conflict = False;
-
- /*
- * If a logical unit has been reserved by any RESERVE command and
- * is still reserved by any initiator, all PERSISTENT RESERVE IN
- * and all PRESISTENT RESERVE OUT commands shall conflict regardless
- * of initiator or service action and shall terminate with a
- * RESERVATION CONLICT status. SPC-2 section 5.5.1.
- */
- if ((cdb[0] == SCMD_PERSISTENT_RESERVE_IN) ||
- (cdb[0] == SCMD_PERSISTENT_RESERVE_OUT) ||
- (res->res_owner != cmd->c_lu)) {
- conflict = True;
- }
-
- queue_prt(mgmtq, Q_PR_IO,
- "NPR%x LUN%d CDB:%s - spc_npr_check(Reservation:%s)\n",
- cmd->c_lu->l_targ->s_targ_num,
- cmd->c_lu->l_common->l_num,
- cmd->c_lu->l_cmd_table[cmd->c_cdb[0]].cmd_name == NULL
- ? "(no name)"
- : cmd->c_lu->l_cmd_table[cmd->c_cdb[0]].cmd_name,
- (conflict) ? "Conflict" : "Allowed");
-
- return (conflict);
-}
-
-/*
- * []----
- * | spc_pgr_check -- PERSISTENT_RESERVE {IN|OUT} check of I_T_L
- * | Refer to SPC-3, Section 5.6.1, Tables 31
- * []----
- */
-Boolean_t
-spc_pgr_check(t10_cmd_t *cmd, uint8_t *cdb)
-{
- disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd);
- sbc_reserve_t *res = &p->d_sbc_reserve;
- scsi3_pgr_t *pgr = &res->res_scsi_3_pgr;
- spc_pr_rsrv_t *rsrv = NULL;
- Boolean_t conflict = False;
-
- /*
- * If no reservations exist, allow all remaining command types.
- */
- assert(res->res_type == RT_PGR);
- if ((cdb[0] == SCMD_PERSISTENT_RESERVE_IN) ||
- (cdb[0] == SCMD_TEST_UNIT_READY) ||
- (pgr->pgr_numrsrv == 0)) {
- conflict = False;
- goto done;
- }
-
- /*
- * If a logical unit has executed a PERSISTENT RESERVE OUT command
- * with the REGISTER or REGISTER AND IGNORE EXISTING KEY service
- * action and is still registered by any initiator, all RESERVE
- * commands and all RELEASE commands regardless of initiator shall
- * conflict and shall terminate with a RESERVATION CONFLICT status.
- * SPC-2 section 5.5.1.
- *
- * CRH bit 0, no support for exception defined in
- * SPC-3 section 5.6.3.
- */
- if ((cdb[0] == SCMD_RESERVE) ||
- (cdb[0] == SCMD_RELEASE)) {
- conflict = True;
- goto done;
- }
-
- /*
- * At this point we know there is at least one reservation.
- * If there is no reservation set on this service delivery
- * port then conflict all remaining command types.
- */
- if (!(rsrv = spc_pr_rsrv_find(pgr, 0, "", T10_PGR_TNAME(cmd)))) {
- queue_prt(mgmtq, Q_PR_ERRS, "PGR%x Reserved on other port\n",
- "\t%s:%s\n", cmd->c_lu->l_targ->s_targ_num,
- T10_PGR_INAME(cmd), T10_PGR_TNAME(cmd));
- conflict = True;
- goto done;
- }
-
- /*
- * Check the command against the reservation type for this port.
- */
- switch (rsrv->r_type) {
- case PGR_TYPE_WR_EX: /* Write Exclusive */
- case PGR_TYPE_EX_AC: /* Exclusive Access */
- if (strcmp(T10_PGR_INAME(cmd), rsrv->r_i_name) == 0)
- conflict = False;
- else
- conflict = spc_pgr_is_conflicting(cdb,
- rsrv->r_type);
- break;
- case PGR_TYPE_WR_EX_RO: /* Write Exclusive, Registrants Only */
- case PGR_TYPE_EX_AC_RO: /* Exclusive Access, Registrants Only */
- if (spc_pr_key_find(
- pgr, 0, T10_PGR_INAME(cmd), T10_PGR_TNAME(cmd)))
- conflict = False;
- else
- conflict = spc_pgr_is_conflicting(cdb,
- rsrv->r_type);
- break;
- case PGR_TYPE_WR_EX_AR: /* Write Exclusive, All Registrants */
- case PGR_TYPE_EX_AC_AR: /* Exclusive Access, All Registrants */
- if (spc_pr_key_find(pgr, 0, "", T10_PGR_TNAME(cmd)))
- conflict = False;
- else
- conflict = spc_pgr_is_conflicting(cdb,
- rsrv->r_type);
- break;
- default:
- conflict = True;
- break;
- }
-
-done:
- queue_prt(mgmtq, Q_PR_IO, "PGR%x LUN%d CDB:%s - spc_pgr_check(%s:%s)\n",
- cmd->c_lu->l_targ->s_targ_num,
- cmd->c_lu->l_common->l_num,
- cmd->c_lu->l_cmd_table[cmd->c_cdb[0]].cmd_name == NULL
- ? "(no name)"
- : cmd->c_lu->l_cmd_table[cmd->c_cdb[0]].cmd_name,
- (rsrv == NULL)
- ? "<none>"
- : (rsrv->r_type == PGR_TYPE_WR_EX)
- ? "Write Exclusive"
- : (rsrv->r_type == PGR_TYPE_EX_AC)
- ? "Exclusive Access"
- : (rsrv->r_type == PGR_TYPE_WR_EX_RO)
- ? "Write Exclusive, Registrants Only"
- : (rsrv->r_type == PGR_TYPE_EX_AC_RO)
- ? "Exclusive Access, Registrants Only"
- : (rsrv->r_type == PGR_TYPE_WR_EX_AR)
- ? "Write Exclusive, All Registrants"
- : (rsrv->r_type == PGR_TYPE_EX_AC_AR)
- ? "Exclusive Access, All Registrants"
- : "Uknown reservation type",
- (conflict) ? "Conflict" : "Allowed");
-
- return (conflict);
-}
-
-/*
- * []----
- * | spc_cmd_reserve6 -- RESERVE(6) command
- * []----
- */
-/*ARGSUSED*/
-void
-spc_cmd_reserve6(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd);
- sbc_reserve_t *res = &p->d_sbc_reserve;
- t10_lu_impl_t *lu;
-
- if (cdb[1] & 0xe0 || SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- (void) pthread_rwlock_wrlock(&res->res_rwlock);
- /*
- * The ways to get in here are,
- * 1) to be the owner of the reservation (SPC-2 section 7.21.2)
- * 2) reservation not applied, nobody is the owner.
- */
- if (res->res_owner != cmd->c_lu) {
- lu = avl_first(&cmd->c_lu->l_common->l_all_open);
- do {
- if (lu != cmd->c_lu)
- lu->l_cmd = sbc_cmd_reserved;
- lu = AVL_NEXT(&cmd->c_lu->l_common->l_all_open, lu);
- } while (lu != NULL);
- res->res_owner = cmd->c_lu;
- }
- res->res_type = RT_NPR;
- (void) pthread_rwlock_unlock(&res->res_rwlock);
-
- trans_send_complete(cmd, STATUS_GOOD);
-}
-
-/*
- * []----
- * | spc_cmd_release6 -- RELEASE(6) command
- * []----
- */
-/*ARGSUSED*/
-void
-spc_cmd_release6(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd);
- sbc_reserve_t *res = &p->d_sbc_reserve;
- t10_lu_impl_t *lu;
-
- if (cdb[1] & 0xe0 || cdb[3] || cdb[4] ||
- SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- (void) pthread_rwlock_wrlock(&res->res_rwlock);
- /*
- * The ways to get in here are,
- * 1) to be the owner of the reservation
- * 2) reservation not applied, nobody is the owner.
- */
- if (res->res_owner != NULL) {
- lu = avl_first(&cmd->c_lu->l_common->l_all_open);
- do {
- lu->l_cmd = sbc_cmd;
- lu = AVL_NEXT(&cmd->c_lu->l_common->l_all_open, lu);
- } while (lu != NULL);
- res->res_owner = NULL;
- res->res_type = RT_NONE;
- }
- (void) pthread_rwlock_unlock(&res->res_rwlock);
-
- trans_send_complete(cmd, STATUS_GOOD);
-}
-
-/*
- * []----
- * | spc_cmd_pr_in -- PERSISTENT_RESERVE IN
- * | Refer to SPC-3, Section 6.1, Tables ?? and ??
- * []----
- */
-/*ARGSUSED*/
-void
-spc_cmd_pr_in(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- scsi_cdb_prin_t *p_prin = (scsi_cdb_prin_t *)cdb;
- disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd);
- sbc_reserve_t *res = &p->d_sbc_reserve;
- scsi3_pgr_t *pgr = &res->res_scsi_3_pgr;
- uint16_t alen;
- size_t len = 0;
- void *buf;
-
- /*
- * Information obtained from:
- * SPC-3, Revision 23
- * Section 6.11 PERSISTENCE RESERVE IN
- * Need to generate a CHECK CONDITION with ILLEGAL REQUEST
- * and INVALID FIELD IN CDB (0x24/0x00) if any of the following is
- * true.
- * (1) The SERVICE ACTION field is 004h - 01fh,
- * (2) The reserved area in byte 1 is set,
- * (3) The reserved area in bytes 2 thru 6 are set,
- * (4) If any of the reserved bits in the CONTROL byte are set.
- */
- if ((p_prin->action >= 0x4) || p_prin->resbits || p_prin->resbytes[0] ||
- p_prin->resbytes[1] || p_prin->resbytes[2] || p_prin->resbytes[3] ||
- p_prin->resbytes[4] || p_prin->control) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- /*
- * Information obtained from:
- * SPC-3, Revision 23
- * Section 6.11 PERSISTENCE RESERVE IN
- * Acquire ALLOCATION LENGTH from bytes 7, 8
- * A zero(0) length allocation is not an error and we should just
- * acknowledge the operation.
- */
- if ((alen = SCSI_READ16(p_prin->alloc_len)) == 0) {
- queue_prt(mgmtq, Q_PR_ERRS,
- "PGR%x LUN%d CDB:%s - spc_cmd_pr_in, len = 0\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- cmd->c_lu->l_cmd_table[cmd->c_cdb[0]].cmd_name == NULL
- ? "(no name)"
- : cmd->c_lu->l_cmd_table[cmd->c_cdb[0]].cmd_name);
-
- trans_send_complete(cmd, STATUS_GOOD);
- return;
- }
-
- /*
- * Allocate space with an alignment that will work for any casting.
- */
- if ((buf = memalign(sizeof (void *), alen)) == NULL) {
- /*
- * Lack of memory is not fatal, just too busy
- */
- trans_send_complete(cmd, STATUS_BUSY);
- return;
- } else {
- bzero(buf, alen);
- }
-
- /*
- * Start processing, lock reservation
- */
- (void) pthread_rwlock_rdlock(&res->res_rwlock);
-
- queue_prt(mgmtq, Q_PR_NONIO, "PGR%x LUN%d action:%s\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- (p_prin->action == PR_IN_READ_KEYS)
- ? "Read keys"
- : (p_prin->action == PR_IN_READ_RESERVATION)
- ? "Read reservation"
- : (p_prin->action == PR_IN_REPORT_CAPABILITIES)
- ? "Report capabilties"
- : (p_prin->action == PR_IN_READ_FULL_STATUS)
- ? "Read full status"
- : "Uknown");
-
- /*
- * Per SPC-3, Revision 23, Table 102, validate ranget of service actions
- */
- switch (p_prin->action) {
- case PR_IN_READ_KEYS:
- len = spc_pr_in_readkeys(
- T10_PGR_TNAME(cmd), pgr, buf, alen);
- break;
- case PR_IN_READ_RESERVATION:
- len = spc_pr_in_readrsrv(
- T10_PGR_TNAME(cmd), pgr, buf, alen);
- break;
- case PR_IN_REPORT_CAPABILITIES:
- len = spc_pr_in_repcap(
- T10_PGR_TNAME(cmd), pgr, buf, alen);
- break;
- case PR_IN_READ_FULL_STATUS:
- len = spc_pr_in_fullstat(
- T10_PGR_TNAME(cmd), pgr, buf, alen);
- break;
- }
-
- /*
- * Complete processing, unlock reservation
- */
- (void) pthread_rwlock_unlock(&res->res_rwlock);
-
- /*
- * Now send the selected Persistent Reservation response back
- */
- if (trans_send_datain(cmd, buf, len, 0, spc_free, True, buf) == False)
- trans_send_complete(cmd, STATUS_BUSY);
-}
-
-/*
- * []----
- * | spc_pr_in_readkey -
- * | Refer to SPC-3, Section 6.1, Tables ?? and ??
- * []----
- */
-static int
-spc_pr_in_readkeys(char *transportID, scsi3_pgr_t *pgr, void *bp,
- uint16_t alloc_len)
-{
- int i = 0, max_buf_keys, hsize;
- scsi_prin_readrsrv_t *buf = (scsi_prin_readrsrv_t *)bp;
- spc_pr_key_t *key;
-
- hsize = sizeof (buf->PRgeneration) + sizeof (buf->add_len);
- max_buf_keys = ((int)alloc_len - hsize) / sizeof (key->k_key);
-
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGRIN readkeys - transportID=%s\n", transportID);
-
- if (pgr->pgr_numkeys)
- for (key = (spc_pr_key_t *)pgr->pgr_keylist.lnk_fwd;
- key != (spc_pr_key_t *)&pgr->pgr_keylist;
- key = (spc_pr_key_t *)key->k_link.lnk_fwd) {
-
- if (strcmp(key->k_transportID, transportID))
- continue;
-
- if (i < max_buf_keys) {
- SCSI_WRITE64(&buf->key_list.service_key[i], key->k_key);
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGRIN readkeys - key:%016lx, i_name:%s\n",
- key->k_key, key->k_i_name);
- i++;
- }
- else
- break; /* No room left, leave now */
- }
-
- SCSI_WRITE32(buf->PRgeneration, pgr->pgr_generation);
- SCSI_WRITE32(buf->add_len, pgr->pgr_numkeys * sizeof (key->k_key));
-
- return (hsize + min(i, max_buf_keys) * sizeof (key->k_key));
-}
-
-/*
- * []----
- * | spc_pr_in_readresv -
- * | Refer to SPC-3, Section 6.1, Tables ?? and ??
- * []----
- */
-static int
-spc_pr_in_readrsrv(
- char *transportID, scsi3_pgr_t *pgr, void *bp, uint16_t alloc_len)
-{
- int i = 0, max_buf_rsrv, hsize;
- scsi_prin_readrsrv_t *buf = (scsi_prin_readrsrv_t *)bp;
- scsi_prin_rsrvdesc_t *desc;
- spc_pr_rsrv_t *rsrv;
-
- hsize = sizeof (buf->PRgeneration) + sizeof (buf->add_len);
- max_buf_rsrv = ((int)alloc_len - hsize) / sizeof (scsi_prin_rsrvdesc_t);
-
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGRIN readrsrv - transportID=%s\n", transportID);
-
- if (pgr->pgr_numrsrv)
- for (rsrv = (spc_pr_rsrv_t *)pgr->pgr_rsrvlist.lnk_fwd;
- rsrv != (spc_pr_rsrv_t *)&pgr->pgr_rsrvlist;
- rsrv = (spc_pr_rsrv_t *)rsrv->r_link.lnk_fwd) {
-
- if (strcmp(rsrv->r_transportID, transportID))
- continue;
-
- if (i < max_buf_rsrv) {
- desc = &buf->key_list.res_key_list[i];
- SCSI_WRITE64(desc->reservation_key, rsrv->r_key);
- desc->scope = rsrv->r_scope;
- desc->type = rsrv->r_type;
-
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGRIN readrsrv - "
- "key:%016lx i_name:%s scope:%d type:%d \n",
- rsrv->r_key, rsrv->r_i_name,
- rsrv->r_scope, rsrv->r_type);
-
- i++;
- }
- else
- break; /* No room left, leave now */
- }
-
- SCSI_WRITE32(buf->PRgeneration, pgr->pgr_generation);
- SCSI_WRITE32(buf->add_len,
- pgr->pgr_numrsrv * sizeof (scsi_prin_rsrvdesc_t));
-
- return (hsize + min(i, max_buf_rsrv)* sizeof (scsi_prin_rsrvdesc_t));
-}
-
-/*
- * []----
- * | spc_pr_in_repcap -
- * | Refer to SPC-3, Section 6.1, Tables ?? and ??
- * []----
- */
-/*
- */
-static int
-spc_pr_in_repcap(
- char *transportID, scsi3_pgr_t *pgr, void *bp, uint16_t alloc_len)
-{
- scsi_prin_rpt_cap_t *buf = (scsi_prin_rpt_cap_t *)bp;
-
- buf->crh = 1; /* Support Reserve/Release Exceptions */
- buf->sip_c = 1; /* Specify Initiator Ports Capable */
- buf->atp_c = 1; /* All Target Ports Capable */
- buf->ptpl_c = 1; /* Persist Through Power Loss C */
- buf->tmv = 1; /* Type Mask Valid */
- buf->ptpl_a = pgr_persist; /* Persist Though Power Loss Active */
- buf->pr_type.wr_ex = 1; /* Write Exclusve */
- buf->pr_type.ex_ac = 1; /* Exclusive Access */
- buf->pr_type.wr_ex_ro = 1; /* Write Exclusive Registrants Only */
- buf->pr_type.ex_ac_ro = 1; /* Exclusive Access Registrants Only */
- buf->pr_type.wr_ex_ar = 1; /* Write Exclusive All Registrants */
- buf->pr_type.ex_ac_ar = 1; /* Exclusive Access All Registrants */
-
- SCSI_WRITE16(buf->length, sizeof (scsi_prin_rpt_cap_t));
-
- return (sizeof (scsi_prin_rpt_cap_t));
-}
-
-/*
- * []----
- * | spc_pr_in_fullstat -
- * | Refer to SPC-3, Section 6.1, Tables ?? and ??
- * []----
- */
-/*
- */
-static int
-spc_pr_in_fullstat(
- char *transportID, scsi3_pgr_t *pgr, void *bp, uint16_t alloc_len)
-{
- int i = 0, max_buf_rsrv, hsize;
- spc_pr_rsrv_t *rsrv;
- scsi_prin_full_status_t *buf = (scsi_prin_full_status_t *)bp;
- iscsi_transport_id_t *tptid;
-
- hsize = sizeof (buf->PRgeneration) + sizeof (buf->add_len);
- max_buf_rsrv = ((int)alloc_len - hsize) /
- sizeof (scsi_prin_full_status_t);
-
- if (pgr->pgr_numrsrv)
- for (i = 0, rsrv = (spc_pr_rsrv_t *)pgr->pgr_rsrvlist.lnk_fwd;
- rsrv != (spc_pr_rsrv_t *)&pgr->pgr_rsrvlist;
- rsrv = (spc_pr_rsrv_t *)rsrv->r_link.lnk_fwd) {
-
- if (i < max_buf_rsrv) {
- SCSI_WRITE64(buf->full_desc[i].reservation_key,
- rsrv->r_key);
- buf->full_desc[i].all_tg_pt = 1;
- buf->full_desc[i].r_holder =
- strcmp(rsrv->r_transportID, transportID) ? 0 : 1;
- buf->full_desc[i].scope = rsrv->r_scope;
- buf->full_desc[i].type = rsrv->r_type;
- SCSI_WRITE16(buf->full_desc[i].rel_tgt_port_id, 0);
- SCSI_WRITE32(buf->full_desc[i].add_len,
- sizeof (iscsi_transport_id_t));
- buf->full_desc[i].trans_id.protocol_id =
- iSCSI_PROTOCOL_ID;
- buf->full_desc[i].trans_id.format_code =
- WW_UID_DEVICE_NAME;
- tptid = (iscsi_transport_id_t *)
- &(buf->full_desc[i].trans_id);
- SCSI_WRITE16(tptid->add_len, 0);
- (void) sprintf(tptid->iscsi_name, "");
- i++;
- }
- else
- break; /* No room left, leave now */
-
- }
-
- SCSI_WRITE32(buf->PRgeneration, pgr->pgr_generation);
- SCSI_WRITE32(buf->add_len, i * sizeof (scsi_prin_rsrvdesc_t));
-
- return (hsize + min(i, max_buf_rsrv) * sizeof (scsi_prin_rsrvdesc_t));
-
-}
-
-/*
- * []----
- * | spc_cmd_pr_out -- PERSISTENT_RESERVE OUT
- * | Refer to SPC-3, Section 6.1, Tables ?? and ??
- * []----
- */
-/*ARGSUSED*/
-void
-spc_cmd_pr_out(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- scsi_cdb_prout_t *p_prout = (scsi_cdb_prout_t *)cdb;
- size_t len;
- void *buf;
-
- /*
- * Information obtained from:
- * SPC-3, Revision 23
- * Section 6.12 PERSISTENCE RESERVE OUT
- * Need to generate a CHECK CONDITION with ILLEGAL REQUEST
- * and INVALID FIELD IN CDB (0x24/0x00) if any of the following is
- * true.
- * (1) The SERVICE ACTION field is 008h - 01fh,
- * (2) The reserved area in byte 1 is set,
- * (3) The TYPE and SCOPE fields are invalid,
- * (4) The reserved area in bytes 3 and 4 are set,
- * (5) If any of the reserved bits in the CONTROL byte are set.
- */
- if ((p_prout->action >= 0x8) || p_prout->resbits ||
- (p_prout->type >= 0x9) ||
- (p_prout->scope >= 0x3) || p_prout->control) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- /*
- * Information obtained from:
- * SPC-3, Revision 23
- * Section 6.12 PERSISTENCE RESERVE OUT
- * Acquire ALLOCATION LENGTH from bytes 5 thru 8
- */
- len = SCSI_READ32(p_prout->param_len);
-
- /*
- * Parameter list length shall contain 24 (0x18),
- * the SPEC_I_PIT is zero (it is because we don't support SIP_C))
- * the service action is not REGISTER AND MOVE
- */
- if ((p_prout->action != PR_OUT_REGISTER_MOVE) && (len != 24)) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_PARAM_LIST_LEN, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- /*
- * Information obtained from:
- * SPC-3, Revision 23
- * Section 6.11.3.3 Persistent Reservation Scope
- * SCOPE field shall be set to LU_SCOPE
- */
- if (p_prout->scope != PR_LU_SCOPE) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- /*
- * Allocate space with an alignment that will work for any casting.
- */
- if ((buf = memalign(sizeof (void *), len)) == NULL) {
- /*
- * Lack of memory is not fatal, just too busy
- */
- trans_send_complete(cmd, STATUS_BUSY);
- return;
- }
-
- /*
- * Now request the Persistent Reserve OUT parameter list
- */
- if (trans_rqst_dataout(cmd, buf, len, 0, buf, spc_free) == False)
- trans_send_complete(cmd, STATUS_BUSY);
-}
-
-/*
- * []----
- * | spc_cmd_pr_out_data -- DataIn phase of PERSISTENT_RESERVE OUT command
- * []----
- */
-/*ARGSUSED*/
-void
-spc_cmd_pr_out_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset, char *data,
- size_t data_len)
-{
- scsi_cdb_prout_t *p_prout = (scsi_cdb_prout_t *)cmd->c_cdb;
- disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd);
- sbc_reserve_t *res = &p->d_sbc_reserve;
- scsi3_pgr_t *pgr = &res->res_scsi_3_pgr;
- scsi_prout_plist_t *plist = (scsi_prout_plist_t *)data;
- t10_lu_impl_t *lu;
- int status;
-
- /*
- * If this is the first time using the persistence data,
- * initialize the reservation and resource key queues
- */
- (void) pthread_rwlock_wrlock(&res->res_rwlock);
- if (pgr->pgr_rsrvlist.lnk_fwd == NULL) {
- spc_pr_initialize(pgr);
- }
-
- queue_prt(mgmtq, Q_PR_NONIO, "PGR%x LUN%d action:%s\n",
- cmd->c_lu->l_targ->s_targ_num,
- cmd->c_lu->l_common->l_num,
- (p_prout->action == PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY)
- ? "Register & ignore existing key"
- : (p_prout->action == PR_OUT_REGISTER)
- ? "Register"
- : (p_prout->action == PR_OUT_RESERVE)
- ? "Reserve"
- : (p_prout->action == PR_OUT_RELEASE)
- ? "Release"
- : (p_prout->action == PR_OUT_CLEAR)
- ? "Clear"
- : (p_prout->action == PR_OUT_PREEMPT_ABORT)
- ? "Preempt & abort"
- : (p_prout->action == PR_OUT_PREEMPT)
- ? "Preempt"
- : (p_prout->action == PR_OUT_REGISTER_MOVE)
- ? "Register & move"
- : "Uknown");
-
- /*
- * Now process the action.
- */
- switch (p_prout->action) {
- case PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY:
- case PR_OUT_REGISTER:
- /*
- * PR_OUT_REGISTER_IGNORE differs from PR_OUT_REGISTER
- * in that the reservation_key is ignored.
- */
- status = spc_pr_out_register(cmd, data, data_len);
- break;
-
- case PR_OUT_RESERVE:
- status = spc_pr_out_reserve(cmd, data, data_len);
- break;
-
- case PR_OUT_RELEASE:
- status = spc_pr_out_release(cmd, data, data_len);
- break;
-
- case PR_OUT_CLEAR:
- status = spc_pr_out_clear(cmd, data, data_len);
- break;
-
- case PR_OUT_PREEMPT_ABORT:
- case PR_OUT_PREEMPT:
- /*
- * PR_OUT_PREEMPT_ABORT differs from PR_OUT_PREEMPT
- * in that all current acitivy for the preempted
- * Initiators will be terminated.
- */
- status = spc_pr_out_preempt(cmd, data, data_len);
- break;
-
- case PR_OUT_REGISTER_MOVE:
- /*
- * PR_OUT_REGISTER_MOVE registers a key for another I_T
- */
- status = spc_pr_out_register_and_move(cmd, data, data_len);
- break;
- }
-
- /*
- * Check status of action performed.
- */
- if (status == STATUS_CHECK) {
- /*
- * Check condition required.
- */
- (void) pthread_rwlock_unlock(&res->res_rwlock);
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, cmd->c_lu->l_asc, cmd->c_lu->l_ascq);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- /*
- * Handle Failed processing status
- */
- if (status != STATUS_GOOD) {
- (void) pthread_rwlock_unlock(&res->res_rwlock);
- trans_send_complete(cmd, status);
- return;
- }
-
- /*
- * Successful, bump the PRgeneration value
- */
- if (p_prout->action != PR_OUT_RESERVE &&
- p_prout->action != PR_OUT_RELEASE)
- pgr->pgr_generation++;
-
- /*
- * If Activate Persist Through Power Loss (APTPL) is set, persist
- * this PGR data on disk
- */
- if (plist->aptpl || pgr->pgr_aptpl)
- (void) spc_pr_write(cmd);
-
- /*
- * When the last registration is removed, PGR is no longer
- * active and we must reset the reservation type.
- */
- if ((pgr->pgr_numkeys == 0) && (pgr->pgr_numrsrv == 0)) {
- res->res_type = RT_NONE;
- pgr->pgr_aptpl = 0;
- } else {
- res->res_type = RT_PGR;
- }
-
- /*
- * Set the command dispatcher according to the reservation type
- */
- (void) pthread_mutex_lock(&cmd->c_lu->l_common->l_common_mutex);
- lu = avl_first(&cmd->c_lu->l_common->l_all_open);
- do {
- lu->l_cmd = (res->res_type == RT_NONE)
- ? sbc_cmd : sbc_cmd_reserved;
- lu = AVL_NEXT(&cmd->c_lu->l_common->l_all_open, lu);
- } while (lu != NULL);
- (void) pthread_mutex_unlock(&cmd->c_lu->l_common->l_common_mutex);
-
- /*
- * Processing is complete, release mutex
- */
- (void) pthread_rwlock_unlock(&res->res_rwlock);
-
- /*
- * Send back a succesful response
- */
- trans_send_complete(cmd, STATUS_GOOD);
-}
-
-/*
- * []----
- * | spc_pr_out_register
- * | Refer to SPC-3, Section 6.1, Tables ?? and ??
- * []----
- */
-static int
-spc_pr_out_register(t10_cmd_t *cmd, void *data, size_t data_len)
-{
- scsi_cdb_prout_t *p_prout = (scsi_cdb_prout_t *)cmd->c_cdb;
- scsi_prout_plist_t *plist = (scsi_prout_plist_t *)data;
- disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd);
- sbc_reserve_t *res = &p->d_sbc_reserve;
- scsi3_pgr_t *pgr = &res->res_scsi_3_pgr;
- spc_pr_rsrv_t *rsrv;
- spc_pr_key_t *key;
- uint64_t reservation_key;
- uint64_t service_key;
- t10_lu_impl_t *lu;
- t10_targ_impl_t *ti;
-
- /*
- * Validate Persistent Reserver Out parameter list
- */
- if (plist->obsolete1[0] || plist->obsolete1[1] ||
- plist->obsolete1[2] || plist->obsolete1[3] ||
- plist->resbits1 || plist->resbits2 || plist->resbytes1 ||
- plist->obsolete2[0] || plist->obsolete2[1]) {
- cmd->c_lu->l_status = KEY_ILLEGAL_REQUEST;
- cmd->c_lu->l_asc = SPC_ASC_INVALID_CDB;
- cmd->c_lu->l_ascq = 0;
- return (STATUS_CHECK);
- }
-
- /*
- * Determine if Activate Persist Trhough Power Loss (APTPL)
- * is valid for this device server.
- */
- if (plist->aptpl && (pgr_persist == 0)) {
- /* pgr - define SCSI-3 error codes */
- cmd->c_lu->l_status = KEY_ILLEGAL_REQUEST;
- cmd->c_lu->l_asc = SPC_ASC_INVALID_FIELD_IN_PARAMETER_LIST;
- cmd->c_lu->l_ascq = 0;
- return (STATUS_CHECK);
- }
-
- /*
- * Get reservation values
- */
- reservation_key = SCSI_READ64(plist->reservation_key);
- service_key = SCSI_READ64(plist->service_key);
-
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGR%x LUN%d register reservation:%016lx, key:%016lx\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- reservation_key, service_key);
-
- /*
- * We may need register all initiators, depending on ALL_TG_TP
- */
- (void) pthread_mutex_lock(&cmd->c_lu->l_common->l_common_mutex);
- lu = avl_first(&cmd->c_lu->l_common->l_all_open);
- do {
- /*
- * Find specified key
- */
- ti = lu->l_targ;
- key = spc_pr_key_find(pgr, 0, ti->s_i_name, ti->s_targ_base);
- if (key) {
- /*
- * What about ALL_TG_TP?
- */
- if (plist->all_tg_pt ||
- (strcmp(key->k_i_name, T10_PGR_INAME(cmd)) == 0)) {
-
- if (p_prout->action == PR_OUT_REGISTER &&
- key->k_key != reservation_key) {
- /*
- * The Initiator did not specify the
- * existing key. Reservation conflict.
- */
- return (STATUS_RESERVATION_CONFLICT);
- }
- /*
- * Change existing key ?
- */
- if (service_key) {
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGROUT: change "
- "old:%016lx = new:%016lx\n",
- key->k_key, service_key);
-
- /*
- * Overwrite (change) key
- */
- key->k_key = service_key;
-
- } else {
- /*
- * Remove existing key
- * NOTE: If we own the reservation then
- * we must release it.
- */
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGROUT: delete "
- "old:%016lx = new:%016lx\n",
- key->k_key, service_key);
-
- rsrv = spc_pr_rsrv_find(pgr, 0,
- ti->s_i_name, ti->s_targ_base);
- if (rsrv) {
- spc_pr_rsrv_release(
- cmd, pgr, rsrv);
- }
- spc_pr_key_free(pgr, key);
- }
- }
- } else {
- /*
- * What about ALL_TG_TP?
- */
- if (plist->all_tg_pt ||
- (strcmp(ti->s_i_name, T10_PGR_INAME(cmd)) == 0)) {
- /*
- * Process request from un-registered Initiator.
- */
- if ((p_prout->action == PR_OUT_REGISTER) &&
- (reservation_key || service_key == 0)) {
- /*
- * Unregistered initiator is attempting
- * to modify a key.
- */
- return (STATUS_RESERVATION_CONFLICT);
- }
-
- key = spc_pr_key_alloc(pgr, service_key,
- ti->s_i_name, ti->s_targ_base);
- if (key == NULL) {
- /* pgr - define SCSI-3 error codes */
- cmd->c_lu->l_status =
- KEY_ABORTED_COMMAND;
- cmd->c_lu->l_asc =
- SPC_ASC_MEMORY_OUT_OF;
- cmd->c_lu->l_ascq =
- SPC_ASCQ_RESERVATION_FAIL;
- return (STATUS_CHECK);
- }
- }
- }
- lu = AVL_NEXT(&cmd->c_lu->l_common->l_all_open, lu);
- } while (lu != NULL);
- (void) pthread_mutex_unlock(&cmd->c_lu->l_common->l_common_mutex);
-
- /*
- * Apply the last valid APTPL bit
- * SPC-3, Revision 23
- * Section 5.6.4.1 Preserving persistent reservervations and
- * registrations through power loss
- */
- pgr->pgr_aptpl = plist->aptpl;
-
- return (STATUS_GOOD);
-}
-
-/*
- * []----
- * | spc_pr_out_reserve
- * | Refer to SPC-3, Section 6.1, Tables ?? and ??
- * []----
- */
-/* ARGSUSED */
-static int
-spc_pr_out_reserve(t10_cmd_t *cmd, void *data, size_t data_len)
-{
- scsi_cdb_prout_t *p_prout = (scsi_cdb_prout_t *)cmd->c_cdb;
- disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd);
- sbc_reserve_t *res = &p->d_sbc_reserve;
- scsi3_pgr_t *pgr = &res->res_scsi_3_pgr;
- spc_pr_rsrv_t *rsrv;
- scsi_prout_plist_t *plist = (scsi_prout_plist_t *)data;
- uint64_t reservation_key;
- uint64_t service_key;
- int status;
-
- /*
- * Do not allow an unregistered initiator to
- * make a reservation.
- */
- reservation_key = SCSI_READ64(plist->reservation_key);
- service_key = SCSI_READ64(plist->service_key);
-
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGR%x LUN%d reserve reservation:%016lx, key:%016lx\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- reservation_key, service_key);
-
- if (!spc_pr_key_find(
- pgr, reservation_key, T10_PGR_INAME(cmd), T10_PGR_TNAME(cmd))) {
-
- queue_prt(mgmtq, Q_PR_ERRS,
- "PGROUT: reserve service:%016lx not found\n",
- reservation_key);
-
- return (STATUS_RESERVATION_CONFLICT);
- }
-
- /*
- * See if there is a reservation on this port by
- * another Initiator. There can be only one LU_SCOPE
- * reservation per ITL. We do not support extents.
- */
- if (rsrv = spc_pr_rsrv_find(pgr, 0, "", T10_PGR_TNAME(cmd))) {
- if (strcmp(rsrv->r_i_name, T10_PGR_INAME(cmd)) != 0) {
-
- queue_prt(mgmtq, Q_PR_ERRS,
- "PGROUT: reserve %s != %s:%s\n", rsrv->r_i_name,
- T10_PGR_INAME(cmd), T10_PGR_TNAME(cmd));
-
- return (STATUS_RESERVATION_CONFLICT);
- }
- }
-
- /*
- * At this point there is either no reservation or the
- * reservation is held by this Initiator.
- */
- if (rsrv != NULL) {
-
- /*
- * An Initiator cannot re-reserve. It must first
- * release. But if its' type and scope match then
- * return STATUS_GOOD.
- */
- if (rsrv->r_type == p_prout->type &&
- rsrv->r_scope == p_prout->scope) {
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGROUT reserve - transportID=%s\n"
- "\tkey:%016lx i_name:%s scope:%d type:%d \n",
- rsrv->r_transportID, rsrv->r_key, rsrv->r_i_name,
- rsrv->r_scope, rsrv->r_type);
- status = STATUS_GOOD;
- } else {
- queue_prt(mgmtq, Q_PR_ERRS,
- "PGROUT reserve failed - transportID=%s\n"
- "\tkey:%016lx i_name:%s scope:%d type:%d \n",
- rsrv->r_transportID, rsrv->r_key, rsrv->r_i_name,
- rsrv->r_scope, rsrv->r_type);
- status = STATUS_RESERVATION_CONFLICT;
- }
- } else {
- /*
- * No reservation exists. Establish a new one.
- */
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGROUT reserve - transportID=%s\n"
- "\tkey:%016lx i_name:%s scope:%d type:%d \n",
- T10_PGR_TNAME(cmd), reservation_key, T10_PGR_INAME(cmd),
- p_prout->scope, p_prout->type);
-
- rsrv = spc_pr_rsrv_alloc(pgr, reservation_key,
- T10_PGR_INAME(cmd), T10_PGR_TNAME(cmd),
- p_prout->scope, p_prout->type);
- if (rsrv == NULL) {
- cmd->c_lu->l_status = KEY_ABORTED_COMMAND;
- cmd->c_lu->l_asc = SPC_ASC_MEMORY_OUT_OF;
- cmd->c_lu->l_ascq = SPC_ASCQ_RESERVATION_FAIL;
- status = STATUS_CHECK;
- } else {
- status = STATUS_GOOD;
- }
- }
-
- return (status);
-}
-
-/*
- * []----
- * | spc_pr_out_release
- * | Refer to SPC-3, Section 6.1, Tables ?? and ??
- * []----
- */
-static int
-spc_pr_out_release(t10_cmd_t *cmd, void *data, size_t data_len)
-{
- scsi_cdb_prout_t *p_prout = (scsi_cdb_prout_t *)cmd->c_cdb;
- disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd);
- sbc_reserve_t *res = &p->d_sbc_reserve;
- scsi3_pgr_t *pgr = &res->res_scsi_3_pgr;
- spc_pr_rsrv_t *rsrv;
- scsi_prout_plist_t *plist = (scsi_prout_plist_t *)data;
- uint64_t reservation_key;
- uint64_t service_key;
- int status;
-
- /*
- * Do not allow an unregistered initiator to
- * make a reservation.
- */
- reservation_key = SCSI_READ64(plist->reservation_key);
- service_key = SCSI_READ64(plist->service_key);
-
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGR%x LUN%d release reservation:%016lx, key:%016lx\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- reservation_key, service_key);
-
- if (!spc_pr_key_find(
- pgr, reservation_key, T10_PGR_INAME(cmd), T10_PGR_TNAME(cmd))) {
-
- queue_prt(mgmtq, Q_PR_ERRS,
- "PGROUT: release service:%016lx not found\n",
- reservation_key);
-
- return (STATUS_RESERVATION_CONFLICT);
- } else {
-
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGROUT: release service:%016lx\n", service_key);
- }
-
- /*
- * Releasing a non-existent reservation is allowed.
- */
- if (!(rsrv = spc_pr_rsrv_find(
- pgr, 0, T10_PGR_INAME(cmd), T10_PGR_TNAME(cmd)))) {
-
- status = STATUS_GOOD;
-
- } else if (p_prout->scope != rsrv->r_scope ||
- p_prout->type != rsrv->r_type ||
- reservation_key != rsrv->r_key) {
- queue_prt(mgmtq, Q_PR_ERRS,
- "PGROUT release failed - transportID=%s\n"
- "\tkey:%016lx i_name:%s scope:%d type:%d \n",
- T10_PGR_TNAME(cmd), reservation_key, T10_PGR_INAME(cmd),
- p_prout->scope, p_prout->type);
-
- /*
- * Scope and key must match to release.
- */
- cmd->c_lu->l_status = KEY_ILLEGAL_REQUEST;
- cmd->c_lu->l_asc = SPC_ASC_PARAMETERS_CHANGED;
- cmd->c_lu->l_ascq = SPC_ASCQ_RES_RELEASED;
- status = STATUS_CHECK;
- } else {
- /*
- * Now release the reservation.
- */
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGROUT release - transportID=%s\n"
- "\tkey:%016lx i_name:s scope:%d type:%d \n",
- rsrv->r_transportID, rsrv->r_key, rsrv->r_i_name,
- rsrv->r_scope, rsrv->r_type);
-
- spc_pr_rsrv_release(cmd, pgr, rsrv);
- status = STATUS_GOOD;
- }
-
- return (status);
-}
-
-/*
- * []----
- * | spc_pr_out_preempt
- * | Refer to SPC-3, Section 6.1, Tables ?? and ??
- * []----
- */
-/* ARGSUSED */
-static int
-spc_pr_out_preempt(t10_cmd_t *cmd, void *data, size_t data_len)
-{
- scsi_cdb_prout_t *p_prout = (scsi_cdb_prout_t *)cmd->c_cdb;
- disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd);
- sbc_reserve_t *res = &p->d_sbc_reserve;
- scsi3_pgr_t *pgr = &res->res_scsi_3_pgr;
- scsi_prout_plist_t *plist = (scsi_prout_plist_t *)data;
- uint64_t reservation_key;
- uint64_t service_key;
- spc_pr_key_t *key, *key_next;
- spc_pr_rsrv_t *rsrv, *rsrv_next;
- t10_lu_impl_t *lu;
- int status = STATUS_GOOD;
-
- /*
- * Get reservation values
- */
- reservation_key = SCSI_READ64(plist->reservation_key);
- service_key = SCSI_READ64(plist->service_key);
-
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGR%x LUN%d preempt reservation:%016lx, key:%016lx\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- reservation_key, service_key);
-
- /*
- * Service key (preempt key) must exist, and
- * Initiator must be registered
- */
- if (spc_pr_key_find(pgr, service_key, "", "") == NULL ||
- spc_pr_key_find(pgr, reservation_key, T10_PGR_INAME(cmd), "") ==
- NULL) {
-
- queue_prt(mgmtq, Q_PR_ERRS,
- "PGROUT: preempt failed reservation:%016lx, key:%016lx\n",
- reservation_key, service_key);
-
- return (STATUS_RESERVATION_CONFLICT);
- }
-
- /*
- * Preempt all keys matching service action key and free
- * the associated structures. Do not set UNIT_ATTN for
- * the Initiator which requested the action.
- *
- * Unlike the other Persistent Reservation commands, the preempt,
- * preempt_and_abort and clear actions are service delivery port
- * independent. So we remove matching keys across ports.
- */
- for (key = (spc_pr_key_t *)pgr->pgr_keylist.lnk_fwd;
- key != (spc_pr_key_t *)&pgr->pgr_keylist;
- key = (spc_pr_key_t *)key_next) {
-
- Boolean_t unit_attn;
-
- /*
- * Get next pointer in case the key gets deallocated
- */
- key_next = (spc_pr_key_t *)key->k_link.lnk_fwd;
-
- /* Skip non-matching keys */
- if (key->k_key != service_key) {
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGROUT preempt key:%016lx != key:%016lx "
- "i_name:%s transportID:%s\n", service_key,
- key->k_key, key->k_i_name, key->k_transportID);
- continue;
- }
-
- /*
- * Determine if UNIT ATTN needed
- */
- unit_attn = strcmp(key->k_i_name, T10_PGR_INAME(cmd));
-
- /*
- * Remove the registration key
- */
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGROUT preempt delete key:%016lx "
- "i_name:%s transportID:%s\n",
- key->k_key, key->k_i_name, key->k_transportID);
- spc_pr_key_free(pgr, key);
-
- /*
- * UNIT ATTN needed ?
- * Do not set UNIT ATTN for calling Initiator
- */
- if (unit_attn == False)
- continue;
-
- /*
- * Is this the preempt and abort?
- */
- if (p_prout->action == PR_OUT_PREEMPT_ABORT) {
- queue_message_set(
- cmd->c_lu->l_common->l_from_transports,
- Q_HIGH, msg_reset_lu, (void *)cmd->c_lu);
- }
-
- /*
- * Find associated I_T Nexuses
- */
- (void) pthread_mutex_lock(&cmd->c_lu->l_common->l_common_mutex);
- lu = avl_first(&cmd->c_lu->l_common->l_all_open);
- do {
- lu->l_status = KEY_UNIT_ATTENTION;
- lu->l_asc = SPC_ASC_PARAMETERS_CHANGED;
- lu->l_ascq = SPC_ASCQ_RES_PREEMPTED;
- lu = AVL_NEXT(&cmd->c_lu->l_common->l_all_open, lu);
- } while (lu != NULL);
- (void) pthread_mutex_unlock(
- &cmd->c_lu->l_common->l_common_mutex);
- }
-
- /*
- * Re-establish our service key if we preempted it.
- */
- if (!(key = spc_pr_key_find(
- pgr, reservation_key, T10_PGR_INAME(cmd), T10_PGR_TNAME(cmd)))) {
-
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGROUT: preempt - register:%016lx, i_name:%s:%s\n",
- reservation_key, T10_PGR_INAME(cmd), T10_PGR_TNAME(cmd));
-
- key = spc_pr_key_alloc(pgr, reservation_key,
- T10_PGR_INAME(cmd), T10_PGR_TNAME(cmd));
- if (key == NULL) {
- cmd->c_lu->l_status = KEY_ABORTED_COMMAND;
- cmd->c_lu->l_asc = SPC_ASC_MEMORY_OUT_OF;
- cmd->c_lu->l_ascq = SPC_ASCQ_RESERVATION_FAIL;
- return (STATUS_CHECK);
- }
- }
-
- /*
- * Now look for a matching reservation to preempt.
- */
- for (rsrv = (spc_pr_rsrv_t *)pgr->pgr_rsrvlist.lnk_fwd;
- rsrv != (spc_pr_rsrv_t *)&pgr->pgr_rsrvlist;
- rsrv = (spc_pr_rsrv_t *)rsrv_next) {
-
- /*
- * Get next pointer in case the reservation gets deallocated
- */
- rsrv_next = (spc_pr_rsrv_t *)rsrv->r_link.lnk_fwd;
-
- /* Skip non-matching keys */
- if (rsrv->r_key != service_key) {
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGROUT preempt rsrv:%016lx != rsrv:%016lx"
- "i_name:%s scope:%d type:%d \n", service_key,
- rsrv->r_key, rsrv->r_i_name,
- rsrv->r_scope, rsrv->r_type);
- continue;
- }
-
- /*
- * Remove matching reservations on other ports
- * and establish a new reservation on this port only.
- * To change the fuctionality to preempt rather than
- * delete the reservations on other ports just remove
- * the following block of code.
- */
- if (strcmp(rsrv->r_transportID, T10_PGR_TNAME(cmd))) {
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGROUT preempt(-) rsrv:%016lx "
- "i_name:%s scope:%d type:%d \n",
- rsrv->r_key, rsrv->r_i_name,
- rsrv->r_scope, rsrv->r_type);
-
- spc_pr_rsrv_free(pgr, rsrv);
- continue;
- } else {
- /*
- * We have a matching reservation so preempt it.
- */
- rsrv->r_key = reservation_key;
- rsrv->r_i_name = strdup(T10_PGR_INAME(cmd));
- rsrv->r_scope = p_prout->scope;
- rsrv->r_type = p_prout->type;
-
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGROUT preempt(+) rsrv:%016lx "
- "i_name:%s scope:%d type:%d \n",
- rsrv->r_key, rsrv->r_i_name,
- rsrv->r_scope, rsrv->r_type);
- }
- }
-
- return (status);
-}
-
-/*
- * []----
- * | spc_pr_out_clear
- * | Refer to SPC-3, Section 6.1, Tables ?? and ??
- * []----
- */
-/* ARGSUSED */
-static int
-spc_pr_out_clear(t10_cmd_t *cmd, void *data, size_t data_len)
-{
- disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd);
- sbc_reserve_t *res = &p->d_sbc_reserve;
- scsi3_pgr_t *pgr = &res->res_scsi_3_pgr;
- scsi_prout_plist_t *plist = (scsi_prout_plist_t *)data;
- uint64_t reservation_key;
- uint64_t service_key;
- spc_pr_key_t *key;
- t10_lu_impl_t *lu;
-
- /*
- * Do not allow an unregistered initiator to attempting to
- * clear the PGR.
- */
- reservation_key = SCSI_READ64(plist->reservation_key);
- service_key = SCSI_READ64(plist->service_key);
-
- queue_prt(mgmtq, Q_PR_NONIO,
- "PGR%x LUN%d clear reservation:%016lx, key:%016lx\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- reservation_key, service_key);
-
- if (!spc_pr_key_find(pgr, reservation_key, T10_PGR_INAME(cmd), "")) {
-
- queue_prt(mgmtq, Q_PR_ERRS,
- "PGROUT: clear service:%016lx not found\n",
- reservation_key);
-
- return (STATUS_RESERVATION_CONFLICT);
- }
-
- /*
- * We need to set UNIT ATTENTION for all registered initiators.
- */
- for (key = (spc_pr_key_t *)pgr->pgr_keylist.lnk_fwd;
- key != (spc_pr_key_t *)&pgr->pgr_keylist;
- key = (spc_pr_key_t *)key->k_link.lnk_fwd) {
-
- /* Do not set UNIT ATTN for calling Initiator */
- if (!(strcmp(key->k_i_name, T10_PGR_INAME(cmd))))
- continue;
- /*
- * At this point the only way to get in here is to be the owner
- * of the reservation.
- */
- (void) pthread_mutex_lock(&cmd->c_lu->l_common->l_common_mutex);
- lu = avl_first(&cmd->c_lu->l_common->l_all_open);
- do {
- lu->l_status = KEY_UNIT_ATTENTION;
- lu->l_asc = SPC_ASC_PARAMETERS_CHANGED;
- lu->l_ascq = SPC_ASCQ_RES_PREEMPTED;
- lu = AVL_NEXT(&cmd->c_lu->l_common->l_all_open, lu);
- } while (lu != NULL);
- (void) pthread_mutex_unlock(
- &cmd->c_lu->l_common->l_common_mutex);
- }
-
- /*
- * Now erase the reservation and registration info.
- */
- spc_pr_erase(pgr);
-
- return (STATUS_GOOD);
-}
-
-/*
- * []----
- * | spc_pr_out_register_and_move
- * | Refer to SPC-3, Section 6.1, Tables ?? and ??
- * []----
- */
-static int
-spc_pr_out_register_and_move(t10_cmd_t *cmd, void *data, size_t data_len)
-{
- return (STATUS_RESERVATION_CONFLICT);
-}
-
-/*
- * []----
- * | spc_pr_key_alloc -
- * | Allocate a new registration key and add it to the key list.
- * | Refer to SPC-3, Section 6.1, Tables ?? and ??
- * []----
- */
-static spc_pr_key_t *
-spc_pr_key_alloc(scsi3_pgr_t *pgr, uint64_t service_key, char *i_name,
- char *transportID)
-{
- spc_pr_key_t *key = (spc_pr_key_t *)
- memalign(sizeof (void *), sizeof (spc_pr_key_t));
-
- if (key != NULL) {
- key->k_key = service_key;
- key->k_i_name = strdup(i_name);
- key->k_transportID = strdup(transportID);
-
- insque(&key->k_link, pgr->pgr_keylist.lnk_bwd);
-
- pgr->pgr_numkeys++;
- assert(pgr->pgr_numkeys > 0);
- }
-
- return (key);
-}
-
-/*
- * []----
- * | spc_pr_initialize -
- * | Initialize registration & reservervation queues
- * []----
- */
-static void
-spc_pr_initialize(scsi3_pgr_t *pgr)
-{
- assert(pgr->pgr_numrsrv == 0);
- assert(pgr->pgr_numkeys == 0);
- pgr->pgr_rsrvlist.lnk_fwd = (key_link_t *)&pgr->pgr_rsrvlist.lnk_fwd;
-
- assert(pgr->pgr_rsrvlist.lnk_bwd == NULL);
- pgr->pgr_rsrvlist.lnk_bwd = (key_link_t *)&pgr->pgr_rsrvlist.lnk_fwd;
-
- assert(pgr->pgr_keylist.lnk_fwd == NULL);
- pgr->pgr_keylist.lnk_fwd = (key_link_t *)&pgr->pgr_keylist.lnk_fwd;
-
- assert(pgr->pgr_keylist.lnk_bwd == NULL);
- pgr->pgr_keylist.lnk_bwd = (key_link_t *)&pgr->pgr_keylist.lnk_fwd;
-}
-
-/*
- * []----
- * | spc_pr_key_free -
- * | Free a registration key
- * []----
- */
-static void
-spc_pr_key_free(scsi3_pgr_t *pgr, spc_pr_key_t *key)
-{
- remque(&key->k_link);
- free(key->k_i_name);
- free(key->k_transportID);
- free(key);
-
- pgr->pgr_numkeys--;
- assert(pgr->pgr_numkeys >= 0);
-}
-
-/*
- * []----
- * | spc_pr_key_find -
- * | Find a registration key based on the key, owner id and port id.
- * []----
- */
-static spc_pr_key_t *
-spc_pr_key_find(scsi3_pgr_t *pgr, uint64_t key, char *i_name, char *transportID)
-{
- spc_pr_key_t *kp;
- spc_pr_key_t *rval = NULL;
-
- for (kp = (spc_pr_key_t *)pgr->pgr_keylist.lnk_fwd;
- kp != (spc_pr_key_t *)&pgr->pgr_keylist;
- kp = (spc_pr_key_t *)kp->k_link.lnk_fwd) {
- if ((key == 0 || kp->k_key == key) &&
- (strlen(i_name) == 0 ||
- (strcmp(kp->k_i_name, i_name) == 0)) &&
- (strlen(transportID) == 0 ||
- (strcmp(kp->k_transportID, transportID) == 0))) {
- rval = kp;
- break;
- }
- }
-
- return (rval);
-}
-
-
-/*
- * []----
- * | spc_pr_rsrv_alloc -
- * | Allocate a new reservation and add it to the rsrv list.
- * []----
- */
-static spc_pr_rsrv_t *
-spc_pr_rsrv_alloc(scsi3_pgr_t *pgr, uint64_t service_key, char *i_name,
- char *transportID, uint8_t scope, uint8_t type)
-{
- spc_pr_rsrv_t *rsrv = (spc_pr_rsrv_t *)
- memalign(sizeof (void *), sizeof (spc_pr_rsrv_t));
-
- if (rsrv != NULL) {
- rsrv->r_key = service_key;
- rsrv->r_i_name = strdup(i_name);
- rsrv->r_transportID = strdup(transportID);
- rsrv->r_scope = scope;
- rsrv->r_type = type;
-
- insque(&rsrv->r_link, pgr->pgr_rsrvlist.lnk_bwd);
-
- pgr->pgr_numrsrv++;
- assert(pgr->pgr_numrsrv > 0);
- }
-
- return (rsrv);
-}
-
-
-/*
- * []----
- * | spc_pr_rsrv_free -
- * | Free a reservation.
- * []----
- */
-static void
-spc_pr_rsrv_free(scsi3_pgr_t *pgr, spc_pr_rsrv_t *rsrv)
-{
- remque(&rsrv->r_link);
- free(rsrv->r_i_name);
- free(rsrv->r_transportID);
- free(rsrv);
-
- pgr->pgr_numrsrv--;
- assert(pgr->pgr_numrsrv >= 0);
-}
-
-/*
- * []----
- * | spc_pr_rsrv_find -
- * | Find a reservation based on the key, owner id and port id.
- * []----
- */
-static spc_pr_rsrv_t *
-spc_pr_rsrv_find(scsi3_pgr_t *pgr, uint64_t key, char *i_name,
- char *transportID)
-{
- spc_pr_rsrv_t *rp, *rval = NULL;
-
- for (rp = (spc_pr_rsrv_t *)pgr->pgr_rsrvlist.lnk_fwd;
- rp != (spc_pr_rsrv_t *)&pgr->pgr_rsrvlist;
- rp = (spc_pr_rsrv_t *)rp->r_link.lnk_fwd) {
- if ((key == 0 || rp->r_key == key) &&
- (strlen(i_name) == 0 ||
- (strcmp(rp->r_i_name, i_name) == 0)) &&
- (strlen(transportID) == 0 ||
- (strcmp(rp->r_transportID, transportID) == 0))) {
- rval = rp;
- break;
- }
- }
-
- return (rval);
-}
-
-/*
- * []----
- * | spc_pr_erase -
- * | Find specified key / reservation and erease it
- * []----
- */
-/*
- */
-static void
-spc_pr_erase(scsi3_pgr_t *pgr)
-{
- spc_pr_key_t *key;
- spc_pr_rsrv_t *rsrv;
-
- while ((key = (spc_pr_key_t *)pgr->pgr_keylist.lnk_fwd) !=
- (spc_pr_key_t *)&pgr->pgr_keylist) {
- spc_pr_key_free(pgr, key);
- }
-
- assert(pgr->pgr_numkeys == 0);
-
- while ((rsrv = (spc_pr_rsrv_t *)pgr->pgr_rsrvlist.lnk_fwd) !=
- (spc_pr_rsrv_t *)&pgr->pgr_rsrvlist) {
- spc_pr_rsrv_free(pgr, rsrv);
- }
-
- assert(pgr->pgr_numrsrv == 0);
-
- pgr->pgr_generation = 0;
- pgr->pgr_aptpl = 0;
-}
-
-/*
- * []----
- * | spc_pr_rsrv_release -
- * | Release the reservation the perform any other required clearing actions.
- * | Refer to SPC-3, Section 6.1, Tables ?? and ??
- * []----
- */
-static void
-spc_pr_rsrv_release(t10_cmd_t *cmd, scsi3_pgr_t *pgr, spc_pr_rsrv_t *rsrv)
-{
- t10_lu_impl_t *lu;
- spc_pr_key_t *key;
-
- /*
- * For Registrants-Only mode set UNIT ATTN.
- */
- if (rsrv->r_type == PGR_TYPE_WR_EX_RO ||
- rsrv->r_type == PGR_TYPE_EX_AC_RO) {
-
- for (key = (spc_pr_key_t *)pgr->pgr_keylist.lnk_fwd;
- key != (spc_pr_key_t *)&pgr->pgr_keylist;
- key = (spc_pr_key_t *)key->k_link.lnk_fwd) {
-
- /*
- * No UNIT ATTN for the requesting Initiator.
- */
- if (!(strcmp(key->k_i_name, T10_PGR_INAME(cmd))))
- continue;
-
- /*
- * Find associated I_T Nexuses
- */
- (void) pthread_mutex_lock(
- &cmd->c_lu->l_common->l_common_mutex);
- lu = avl_first(&cmd->c_lu->l_common->l_all_open);
- do {
- lu->l_status = KEY_UNIT_ATTENTION;
- lu->l_asc = SPC_ASC_PARAMETERS_CHANGED;
- lu->l_ascq = SPC_ASCQ_RES_RELEASED;
- lu = AVL_NEXT(&cmd->c_lu->l_common->l_all_open,
- lu);
- } while (lu != NULL);
- (void) pthread_mutex_unlock(
- &cmd->c_lu->l_common->l_common_mutex);
- }
- }
-
- /*
- * Remove the reservation.
- */
- spc_pr_rsrv_free(pgr, rsrv);
-}
-
-/*
- * []----
- * | spc_pr_read -
- * | Read in pgr keys and reservations for this device from backend storage.
- * | At least the local pgr write lock must be held.
- * []----
- */
-void
-spc_pr_read(t10_cmd_t *cmd)
-{
- disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd);
- sbc_reserve_t *res = &p->d_sbc_reserve;
- scsi3_pgr_t *pgr = &res->res_scsi_3_pgr;
- spc_pr_key_t *key;
- spc_pr_rsrv_t *rsrv;
- spc_pr_diskkey_t *klist;
- spc_pr_diskrsrv_t *rlist;
- spc_pr_persist_disk_t *buf = NULL;
- t10_lu_impl_t *lu;
- int i, pfd;
- Boolean_t status = False;
- char *c, path[MAXPATHLEN] = {0};
-
- /*
- * Open the PERSISTENCE file specification if one exists
- * taking into account the alternate location if a ZVOL
- */
- if (tgt_find_value_str(cmd->c_lu->l_common->l_root, XML_ELEMENT_BACK,
- &c) == True) {
- if (((pgr_basedir != NULL) && (strlen(pgr_basedir) != 0)) &&
- (strncmp(ZVOL_PATH, c, sizeof (ZVOL_PATH) - 1) == 0)) {
- (void) snprintf(path, MAXPATHLEN, "%s/%s-%s%d",
- pgr_basedir, &c[sizeof (ZVOL_PATH) - 1],
- PERSISTENCEBASE, cmd->c_lu->l_common->l_num);
- } else {
- (void) snprintf(path, MAXPATHLEN, "%s/%s/%s%d",
- target_basedir, cmd->c_lu->l_targ->s_targ_base,
- PERSISTENCEBASE, cmd->c_lu->l_common->l_num);
- }
- free(c);
- }
- if ((pfd = open(path, O_RDONLY)) >= 0) {
- struct stat pstat;
- if ((fstat(pfd, &pstat)) == 0)
- if (pstat.st_size > 0)
- if (buf = malloc(pstat.st_size))
- if (read(pfd, buf, pstat.st_size) ==
- pstat.st_size)
- status = True;
- }
-
- /*
- * Clean up on no persistence file found
- */
- if (status == False) {
- if (pfd >= 0)
- (void) close(pfd);
- if (buf)
- free(buf);
- return;
- }
-
- /*
- * If this is the first time using the persistence data,
- * initialize the reservation and resource key queues
- */
- if (pgr->pgr_rsrvlist.lnk_fwd == NULL) {
- (void) spc_pr_initialize(pgr);
- }
-
- /*
- * Perform some vailidation on what we are looking at
- */
- assert(buf->magic == PGRMAGIC);
- assert(buf->revision == SPC_PGR_PERSIST_DATA_REVISION);
-
- /*
- * Get the PGR keys
- */
- klist = (spc_pr_diskkey_t *)&buf->keylist[0];
- for (i = 0; i < buf->numkeys; i++) {
- assert(klist[i].rectype == PGRDISKKEY);
-
- /*
- * Was the key previously read, if not restore it
- */
- key = spc_pr_key_find(pgr, 0, T10_PGR_INAME(cmd),
- T10_PGR_TNAME(cmd));
- if (key == NULL)
- key = spc_pr_key_alloc(pgr, klist[i].key,
- klist[i].i_name, klist[i].transportID);
- assert(key);
- }
-
- /*
- * Get the PGR reservations
- */
- rlist = (spc_pr_diskrsrv_t *)&buf->keylist[buf->numkeys];
- for (i = 0; i < buf->numrsrv; i++) {
- assert(rlist[i].rectype == PGRDISKRSRV);
-
- /*
- * Was the reservation previously read, if not restore it
- */
- rsrv = spc_pr_rsrv_find(pgr, 0, T10_PGR_INAME(cmd),
- T10_PGR_TNAME(cmd));
- if (rsrv == NULL)
- rsrv = spc_pr_rsrv_alloc(pgr, rlist[i].key,
- rlist[i].i_name, rlist[i].transportID,
- rlist[i].scope, rlist[i].type);
- assert(rsrv);
- }
-
- /*
- * If there was data then set the reservation type.
- */
- if (pgr->pgr_numkeys > 0 || pgr->pgr_numrsrv > 0) {
- res->res_type = RT_PGR;
- pgr->pgr_generation = buf->generation;
-
- /*
- * Set the command dispatcher according to the reservation type
- */
- (void) pthread_mutex_lock(&cmd->c_lu->l_common->l_common_mutex);
- lu = avl_first(&cmd->c_lu->l_common->l_all_open);
- do {
- lu->l_cmd = sbc_cmd_reserved;
- lu = AVL_NEXT(&cmd->c_lu->l_common->l_all_open, lu);
- } while (lu != NULL);
- (void) pthread_mutex_unlock(
- &cmd->c_lu->l_common->l_common_mutex);
- }
-
- free(buf);
-}
-
-/*
- * []----
- * | spc_pr_write -
- * | Write PGR keys and reservations for this device to backend storage.
- * | At least the local pgr write lock must be held.
- * []----
- */
-Boolean_t
-spc_pr_write(t10_cmd_t *cmd)
-{
- disk_params_t *p = (disk_params_t *)T10_PARAMS_AREA(cmd);
- sbc_reserve_t *res = &p->d_sbc_reserve;
- scsi3_pgr_t *pgr = &res->res_scsi_3_pgr;
- spc_pr_key_t *key;
- spc_pr_rsrv_t *rsrv;
- spc_pr_diskkey_t *klist;
- spc_pr_diskrsrv_t *rlist;
- spc_pr_persist_disk_t *buf;
- ssize_t length, bufsize;
- int i, pfd = -1;
- char *c, path[MAXPATHLEN] = {0};
- Boolean_t status = True;
-
- /*
- * Verify space requirements and allocate buffer memory.
- * Space needed is header + keylist + rsrvlist.
- * Subtract 1 from numkeys since header already defines
- * the first element of the keylist.
- * Round up the bufsize to the next FBA boundary.
- */
- bufsize = sizeof (spc_pr_persist_disk_t) +
- (pgr->pgr_numkeys - 1) * sizeof (spc_pr_diskkey_t) +
- pgr->pgr_numrsrv * sizeof (spc_pr_diskrsrv_t);
- bufsize = roundup(bufsize, 512);
- if ((buf = memalign(sizeof (void *), bufsize)) == NULL)
- return (False);
- else
- bzero(buf, bufsize);
-
- /*
- * Build header.
- */
- buf->magic = PGRMAGIC;
- buf->revision = SPC_PGR_PERSIST_DATA_REVISION;
- buf->generation = pgr->pgr_generation;
- buf->numkeys = pgr->pgr_numkeys;
- buf->numrsrv = pgr->pgr_numrsrv;
-
- /*
- * Copy the keys.
- */
- klist = buf->keylist;
- for (i = 0, key = (spc_pr_key_t *)pgr->pgr_keylist.lnk_fwd;
- key != (spc_pr_key_t *)&pgr->pgr_keylist && i < pgr->pgr_numkeys;
- key = (spc_pr_key_t *)key->k_link.lnk_fwd, i++) {
-
- klist[i].rectype = PGRDISKKEY;
- klist[i].key = key->k_key;
- (void) strncpy(klist[i].i_name, key->k_i_name,
- sizeof (klist[i].i_name));
- (void) strncpy(klist[i].transportID, key->k_transportID,
- sizeof (klist[i].transportID));
- }
-
- /*
- * Copy the reservations.
- */
- rlist = (spc_pr_diskrsrv_t *)&buf->keylist[pgr->pgr_numkeys];
- for (i = 0, rsrv = (spc_pr_rsrv_t *)pgr->pgr_rsrvlist.lnk_fwd;
- rsrv != (spc_pr_rsrv_t *)&pgr->pgr_rsrvlist &&
- i < pgr->pgr_numrsrv;
- rsrv = (spc_pr_rsrv_t *)rsrv->r_link.lnk_fwd, i++) {
-
- rlist[i].rectype = PGRDISKRSRV;
- rlist[i].key = rsrv->r_key;
- rlist[i].scope = rsrv->r_scope;
- rlist[i].type = rsrv->r_type;
- (void) strncpy(rlist[i].i_name, rsrv->r_i_name,
- sizeof (rlist[i].i_name));
- (void) strncpy(rlist[i].transportID, rsrv->r_transportID,
- sizeof (rlist[i].transportID));
- }
-
- /*
- * Open the PERSISTENCE file specification if one exists
- * taking into account the alternate location if a ZVOL
- */
- if (tgt_find_value_str(cmd->c_lu->l_common->l_root, XML_ELEMENT_BACK,
- &c) == True) {
- if (((pgr_basedir != NULL) && (strlen(pgr_basedir) != 0)) &&
- (strncmp(ZVOL_PATH, c, sizeof (ZVOL_PATH) - 1) == 0)) {
- (void) snprintf(path, MAXPATHLEN, "%s/%s-%s%d",
- pgr_basedir, &c[sizeof (ZVOL_PATH) - 1],
- PERSISTENCEBASE, cmd->c_lu->l_common->l_num);
- } else {
- (void) snprintf(path, MAXPATHLEN, "%s/%s/%s%d",
- target_basedir, cmd->c_lu->l_targ->s_targ_base,
- PERSISTENCEBASE, cmd->c_lu->l_common->l_num);
- }
- free(c);
- }
- if ((pfd = open(path, O_WRONLY|O_CREAT, 0600)) >= 0) {
- length = write(pfd, buf, bufsize);
- (void) close(pfd);
- } else {
- if ((pfd < 0) || (length != bufsize))
- status = False;
- }
-
- /*
- * Free allocated buffer
- */
- free(buf);
- return (status);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.h b/usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.h
deleted file mode 100644
index 1ad68ae93b..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _T10_SPC_PR_H
-#define _T10_SPC_PR_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * SPC-3 Persistent Reservation specific structures and defines
- */
-
-/*
- * Key Linked Lists
- */
-typedef struct key_link {
- union {
- uint64_t align;
- struct {
- struct key_link *_lnk_fwd; /* Forward element */
- struct key_link *_lnk_bwd; /* Backward element */
- } key_ptr;
- } key_link;
-} key_link_t;
-#define lnk_fwd key_link.key_ptr._lnk_fwd
-#define lnk_bwd key_link.key_ptr._lnk_bwd
-#define insque(a, b) \
- ((key_link_t *)(a))->lnk_fwd = (key_link_t *)(b); \
- ((key_link_t *)(a))->lnk_bwd = ((key_link_t *)(b))->lnk_bwd; \
- ((key_link_t *)(b))->lnk_bwd = (key_link_t *)(a); \
- ((key_link_t *)(a))->lnk_bwd->lnk_fwd = (key_link_t *)(a);
-
-#define remque(A) \
- ((key_link_t *)(A))->lnk_bwd->lnk_fwd = ((key_link_t *)(A))->lnk_fwd; \
- ((key_link_t *)(A))->lnk_fwd->lnk_bwd = ((key_link_t *)(A))->lnk_bwd;
-
-/*
- * Reservation Types (res_type).
- */
-typedef enum {
- RT_NONE = 0, /* None */
- RT_PGR, /* SCSI-3 Persistent Reservation */
- RT_NPR /* SCSI-2 Non-Persistent Reservation */
-} spc_reserve_types;
-
-/*
- * Persistent reservation data.
- */
-typedef struct spc_pr_key {
- key_link_t k_link; /* Key linked list */
- uint64_t k_key; /* registration key */
- char *k_i_name; /* initiator name */
- char *k_transportID; /* transport ID */
-} spc_pr_key_t;
-
-typedef struct spc_pr_rsrv {
- key_link_t r_link; /* Key linked list */
- uint64_t r_key; /* reservation key */
- char *r_i_name; /* initiator name */
- char *r_transportID; /* transport ID */
- uint8_t r_scope; /* reservation scope */
- uint8_t r_type; /* reservation type */
-} spc_pr_rsrv_t;
-
-/*
- * Persistent Reservation data
- */
-typedef struct scsi3_pgr {
- uint32_t pgr_generation; /* PGR PRgeneration value */
- uint16_t pgr_unused;
- uint16_t pgr_bits : 15,
- pgr_aptpl : 1; /* persistence data exists */
- int32_t pgr_numkeys; /* # entries in key list */
- int32_t pgr_numrsrv; /* # entries in rsrv list */
- key_link_t pgr_keylist; /* Registration key list */
- key_link_t pgr_rsrvlist; /* reservation list */
-} scsi3_pgr_t;
-
-typedef struct sbc_reserve {
- spc_reserve_types res_type; /* standard or pr active */
- pthread_rwlock_t res_rwlock; /* Lock for coordination */
- scsi3_pgr_t res_scsi_3_pgr; /* SCSI-3 PGR */
- t10_lu_impl_t *res_owner; /* SCSI-2 Reservation */
-} sbc_reserve_t;
-
-/*
- * On-disk PGR data.
- *
- * NOTE: The following three structures should be rounded up to 512 bytes each
- * to prevent potential problems with on-disk data skew
- */
-typedef struct spc_pr_diskkey {
- uint64_t key; /* registration key (8) */
- uint32_t rectype; /* record type (4) */
- char i_name[224]; /* initiator name (224) */
- char filler1[20]; /* filler to 256 bytes */
- char transportID[228]; /* transport ID (228) */
- char filler2[28]; /* filler to 512 bytes */
-} spc_pr_diskkey_t;
-
-typedef struct spc_pr_diskrsrv {
- uint64_t key; /* reservation key (8) */
- uint32_t rectype; /* record type (4) */
- uint8_t scope; /* reservation scope (1) */
- uint8_t type; /* reservation type (1) */
- char i_name[224]; /* initiator name (224) */
- char filler1[18]; /* filler to 256 bytes */
- char transportID[228]; /* Transport ID (228) */
- char filler2[28]; /* filler to 512 bytes */
-} spc_pr_diskrsrv_t;
-
-typedef struct spc_pr_persist_disk {
- uint64_t magic; /* magic number (8) */
- uint32_t revision; /* header format revision (4) */
- uint32_t generation; /* pgr generation count (4) */
- int32_t numkeys; /* # items in key list (4) */
- int32_t numrsrv; /* # items in rsrv list (4) */
- char filler[488]; /* 8+4+4+4+4 */
-
-/*
- * After the header the data is laid out as follows:
- * spc_pr_diskkey_t keylist[];
- * spc_pr_diskrsrv_t rsrvlist[];
- */
- spc_pr_diskkey_t keylist[1];
-} spc_pr_persist_disk_t;
-
-
-#define SPC_PGR_PERSIST_DATA_REVISION 0x01 /* REVISON = 1 */
-#define PGRMAGIC 0x5047524D41474943LL /* "PGRMAGIC" */
-#define PGRDISKKEY 0x5047526B /* "PGRk" */
-#define PGRDISKRSRV 0x50475272 /* "PGRr" */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _T10_SPC_PR_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/t10_ssc.c b/usr/src/cmd/iscsi/iscsitgtd/t10_ssc.c
deleted file mode 100644
index dfa83a34a0..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_ssc.c
+++ /dev/null
@@ -1,1646 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Implementation of SSC-2 emulation
- */
-
-#include <strings.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <aio.h>
-#include <sys/asynch.h>
-#include <sys/scsi/generic/sense.h>
-#include <sys/scsi/generic/status.h>
-#include <sys/scsi/targets/stdef.h>
-#include <netinet/in.h>
-
-#include "target.h"
-#include "utility.h"
-#include "t10.h"
-#include "t10_spc.h"
-#include "t10_ssc.h"
-
-/*
- * []----
- * | Forward declarations
- * []----
- */
-static scsi_cmd_table_t ssc_table[];
-static void ssc_cmd(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
-static void ssc_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset,
- char *data, size_t data_len);
-static void ssc_free(emul_handle_t e);
-static void ssc_write_cmplt(emul_handle_t e);
-static void ssc_read_cmplt(emul_handle_t id);
-static void ssc_setup_tape(ssc_params_t *s, t10_lu_common_t *lu);
-static uint32_t find_last_obj_id(char *file_mark, off_t eod);
-static char *sense_dev_config(ssc_params_t *s, char *data);
-static char *sense_compression(ssc_params_t *s, char *data);
-
-static long ssc_page_size;
-
-/*
- * []----
- * | ssc_init_common -- initialize common information that all ITLs will use
- * []----
- */
-Boolean_t
-ssc_common_init(t10_lu_common_t *lu)
-{
- ssc_params_t *s;
- ssc_obj_mark_t mark;
-
- ssc_page_size = sysconf(_SC_PAGESIZE);
-
- if (lu->l_mmap == MAP_FAILED)
- return (False);
-
- if ((s = (ssc_params_t *)calloc(1, sizeof (*s))) == NULL)
- return (False);
-
- s->s_size = lu->l_size;
- s->s_fast_write_ack = lu->l_fast_write_ack;
-
- bcopy(lu->l_mmap, &mark, sizeof (mark));
- if (mark.som_sig != SSC_OBJ_SIG) {
- ssc_setup_tape(s, lu);
- }
- s->s_cur_fm = 0;
- s->s_cur_rec = sizeof (ssc_obj_mark_t);
- s->s_prev_rec = s->s_cur_rec;
- s->s_state = lu->l_state;
-
- lu->l_dtype_params = (void *)s;
- return (True);
-}
-
-/*
- * []----
- * | ssc_fini_common -- free any resources
- * []----
- */
-void
-ssc_common_fini(t10_lu_common_t *lu)
-{
- free(lu->l_dtype_params);
-}
-
-void
-ssc_task_mgmt(t10_lu_common_t *lu, TaskOp_t op)
-{
- ssc_params_t *s = (ssc_params_t *)lu->l_dtype_params;
-
- switch (op) {
- case CapacityChange:
- s->s_size = lu->l_size;
- break;
-
- case DeviceOnline:
- s->s_state = lu->l_state;
- }
-}
-
-/*
- * []----
- * | ssc_init_per -- initialize per ITL information
- * []----
- */
-void
-ssc_per_init(t10_lu_impl_t *itl)
-{
- ssc_params_t *s = (ssc_params_t *)itl->l_common->l_dtype_params;
-
- if (s->s_state == lu_online)
- itl->l_cmd = ssc_cmd;
- else
- itl->l_cmd = spc_cmd_offline;
- itl->l_data = ssc_data;
- itl->l_cmd_table = ssc_table;
-}
-
-/*
- * []----
- * | ssc_fini_per -- release or free any ITL resources
- * []----
- */
-/*ARGSUSED*/
-void
-ssc_per_fini(t10_lu_impl_t *itl)
-{
-}
-
-/*
- * []----
- * | ssc_cmd -- start a SCSI command
- * |
- * | This routine is called from within the SAM-3 Task router.
- * []----
- */
-static void
-ssc_cmd(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- scsi_cmd_table_t *e;
-
- e = &cmd->c_lu->l_cmd_table[cdb[0]];
-#ifdef FULL_DEBUG
- queue_prt(mgmtq, Q_STE_IO, "SSC%x LUN%d Cmd %s\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- e->cmd_name == NULL ? "(no name)" : e->cmd_name);
-#endif
- (*e->cmd_start)(cmd, cdb, cdb_len);
-}
-
-/*
- * []----
- * | ssc_data -- Data phase for command.
- * |
- * | Normally this is only called for the WRITE command. Other commands
- * | that have a data in phase will probably be short circuited when
- * | we call trans_rqst_dataout() and the data is already available.
- * | At least this is true for iSCSI. FC however will need a DataIn phase
- * | for commands like MODE SELECT and PGROUT.
- * []----
- */
-static void
-ssc_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset, char *data,
- size_t data_len)
-{
- scsi_cmd_table_t *e;
-
- e = &cmd->c_lu->l_cmd_table[cmd->c_cdb[0]];
-#ifdef FULL_DEBUG
- queue_prt(mgmtq, Q_STE_IO, "SSC%x LUN%d Data %s\n",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- e->cmd_name);
-#endif
- (*e->cmd_data)(cmd, id, offset, data, data_len);
-}
-
-/*
- * []------------------------------------------------------------------[]
- * | SCSI Streaming Commands - 3 |
- * | T10/1611-D Revision 01c |
- * | The following functions implement the emulation of SSC-3 type |
- * | commands. |
- * []------------------------------------------------------------------[]
- */
-
-/*ARGSUSED*/
-static void
-ssc_read(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- ssc_io_t *io;
- ssc_params_t *s = (ssc_params_t *)T10_PARAMS_AREA(cmd);
- ssc_obj_mark_t fm,
- rm;
- int fixed,
- sili;
- off_t offset = 0;
- size_t xfer,
- req_len;
- void *mmap = cmd->c_lu->l_common->l_mmap;
- t10_cmd_t *c;
-
- fixed = cdb[1] & 0x01;
- sili = cdb[1] & 0x02;
-
- if (s == NULL)
- return;
-
- /*
- * Standard error checking.
- */
- if ((sili && fixed) || (cdb[1] & 0xfc) ||
- SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- req_len = (cdb[2] << 16) | (cdb[3] << 8) | cdb[4];
- req_len *= fixed ? 512 : 1;
-
- if (req_len == 0) {
- trans_send_complete(cmd, STATUS_GOOD);
- return;
- }
-
-#ifdef FULL_DEBUG
- queue_prt(mgmtq, Q_STE_IO,
- "SSC%x LUN%d read 0x%x bytes",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num, req_len);
-#endif
-
- bcopy((char *)mmap + s->s_cur_fm, &fm, sizeof (fm));
- bcopy((char *)mmap + s->s_cur_fm + s->s_cur_rec, &rm, sizeof (rm));
-
- if (rm.som_sig != SSC_OBJ_SIG) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "SSC%x LUN%d bad RECORD-MARK",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num);
- spc_sense_create(cmd, KEY_MEDIUM_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- } else if (rm.som_type != SSC_OBJ_TYPE_RM) {
- s->s_cur_fm += fm.o_fm.size;
- s->s_cur_rec = sizeof (ssc_obj_mark_t);
- s->s_prev_rec = s->s_cur_rec;
-
- spc_sense_create(cmd, KEY_NO_SENSE, 0);
- spc_sense_ascq(cmd, SPC_ASC_FM_DETECTED, SPC_ASCQ_FM_DETECTED);
- spc_sense_info(cmd, req_len);
- spc_sense_flags(cmd, SPC_SENSE_FM);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- } else if ((sili == 0) &&
- ((rm.o_rm.size - sizeof (ssc_obj_mark_t)) != req_len)) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "SSC%x LUN%d Wrong size read",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num);
-
- s->s_prev_rec = s->s_cur_rec;
- s->s_cur_rec += rm.o_rm.size;
-
- spc_sense_create(cmd, KEY_NO_SENSE, 0);
- spc_sense_flags(cmd, SPC_SENSE_ILI);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- do {
- xfer = MIN((req_len - offset), T10_MAX_OUT(cmd));
- if ((offset + xfer) < req_len)
- c = trans_cmd_dup(cmd);
- else
- c = cmd;
- if ((io = (ssc_io_t *)calloc(1, sizeof (*io))) == NULL) {
- trans_send_complete(c, STATUS_BUSY);
- return;
- }
-
- io->sio_cmd = c;
- io->sio_offset = offset;
- io->sio_total = req_len;
- io->sio_data_len = xfer;
- io->sio_data = (char *)mmap + s->s_cur_fm +
- s->s_cur_rec + sizeof (ssc_obj_mark_t) + offset;
- io->sio_aio.a_aio.aio_return = xfer;
-
- ssc_read_cmplt((emul_handle_t)io);
- offset += xfer;
- } while (offset < req_len);
-
- s->s_prev_rec = s->s_cur_rec;
- s->s_cur_rec += req_len + sizeof (ssc_obj_mark_t);
-}
-
-static void
-ssc_read_cmplt(emul_handle_t id)
-{
- ssc_io_t *io = (ssc_io_t *)id;
- t10_cmd_t *cmd = io->sio_cmd;
-
- if (io->sio_aio.a_aio.aio_return != io->sio_data_len) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- if ((io->sio_offset + io->sio_data_len) < io->sio_total) {
- if (trans_send_datain(cmd, io->sio_data, io->sio_data_len,
- io->sio_offset, ssc_free, False, io) == False) {
- trans_send_complete(cmd, STATUS_BUSY);
- }
- } else {
- if (trans_send_datain(cmd, io->sio_data, io->sio_data_len,
- io->sio_offset, ssc_free, True, io) == False) {
- trans_send_complete(cmd, STATUS_BUSY);
- }
- }
-}
-
-/*ARGSUSED*/
-static void
-ssc_write(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- ssc_obj_mark_t mark;
- size_t request_len,
- max_xfer;
- int fixed,
- prev_id;
- ssc_io_t *io;
- ssc_params_t *s = (ssc_params_t *)T10_PARAMS_AREA(cmd);
-
- if (s == NULL)
- return;
-
- if ((cdb[1] & 0xfe) || SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- fixed = cdb[1];
- request_len = (cdb[2] << 16) | (cdb[3] << 8) | cdb[4];
- request_len *= fixed ? 512 : 1;
-
-#ifdef FULL_DEBUG
- queue_prt(mgmtq, Q_STE_IO,
- "SSC%x LUN%d write %d, fixed %d",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- request_len, fixed);
-#endif
- io = cmd->c_emul_id;
- if (io == NULL) {
- if ((io = calloc(1, sizeof (*io))) == NULL) {
- trans_send_complete(cmd, STATUS_BUSY);
- return;
- }
- io->sio_total = request_len;
- io->sio_cmd = cmd;
- io->sio_offset = 0;
-
- /*
- * Writing looses all information after the current
- * file-mark. So, check to see if the current file-mark
- * size doesn't reflect the end-of-media. If not, update
- * it.
- */
- bcopy((char *)cmd->c_lu->l_common->l_mmap + s->s_cur_fm,
- &mark, sizeof (mark));
- if (mark.o_fm.size !=
- (s->s_size - sizeof (ssc_obj_mark_t) - s->s_cur_fm)) {
- mark.o_fm.size = s->s_size - sizeof (ssc_obj_mark_t) -
- s->s_cur_fm;
- bcopy(&mark, (char *)cmd->c_lu->l_common->l_mmap +
- s->s_cur_fm, sizeof (mark));
- }
-
- /*
- * End-of-Partition detection
- */
- if ((s->s_cur_rec + request_len) > (mark.o_fm.size)) {
- spc_sense_create(cmd, KEY_VOLUME_OVERFLOW, 0);
- spc_sense_ascq(cmd, SPC_ASC_EOP, SPC_ASCQ_EOP);
- spc_sense_flags(cmd, SPC_SENSE_EOM);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- if ((s->s_cur_fm == 0) &&
- (s->s_cur_rec == sizeof (ssc_obj_mark_t))) {
-
- /*
- * The current position is a BOM. By setting
- * the prev_id value to -1 the code below will
- * create the first ID with a value of zero
- * Which is what the specification requires.
- */
- prev_id = -1;
-
- } else if (s->s_cur_rec == sizeof (ssc_obj_mark_t)) {
-
- /*
- * If the current position is at the beginning of
- * this file-mark use the object ID found in
- * the file-mark header. It will have been updated
- * from the last object ID in the previous file-mark.
- *
- * NOTE: We're counting on 'mark' still referring
- * to the current file mark here.
- */
- prev_id = mark.o_fm.last_obj_id;
- } else {
- bcopy((char *)cmd->c_lu->l_common->l_mmap +
- s->s_cur_fm + s->s_prev_rec, &mark, sizeof (mark));
- prev_id = mark.o_rm.obj_id;
- }
-
- bzero(&mark, sizeof (mark));
- mark.som_sig = SSC_OBJ_SIG;
- mark.som_type = SSC_OBJ_TYPE_RM;
- mark.o_rm.size = request_len +
- sizeof (ssc_obj_mark_t);
- mark.o_rm.obj_id = prev_id + 1;
- bcopy(&mark, (char *)cmd->c_lu->l_common->l_mmap +
- s->s_cur_fm + s->s_cur_rec, sizeof (mark));
- }
-
- max_xfer = min(io->sio_total - io->sio_offset,
- cmd->c_lu->l_targ->s_maxout);
- io->sio_aio.a_aio.aio_return = max_xfer;
- io->sio_data_len = max_xfer;
- io->sio_data = (char *)cmd->c_lu->l_common->l_mmap +
- s->s_cur_fm + s->s_cur_rec + sizeof (mark) + io->sio_offset;
-
- if (trans_rqst_dataout(cmd, io->sio_data, io->sio_data_len,
- io->sio_offset, io, ssc_free) == False) {
- trans_send_complete(cmd, STATUS_BUSY);
- }
-}
-
-/*ARGSUSED*/
-static void
-ssc_write_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset, char *data,
- size_t data_len)
-{
- ssc_io_t *io = (ssc_io_t *)id;
- ssc_params_t *s = (ssc_params_t *)T10_PARAMS_AREA(cmd);
-
- if (s == NULL)
- return;
-
- if (s->s_fast_write_ack == False) {
- uint64_t sa;
- size_t len;
-
- /*
- * msync requires the address to be page aligned.
- * That means we need to account for any alignment
- * loss in the len field and access the full page.
- */
- sa = (uint64_t)(intptr_t)data & ~(ssc_page_size - 1);
- len = (((size_t)data & (ssc_page_size - 1)) +
- data_len + ssc_page_size - 1) &
- ~(ssc_page_size -1);
-
- /*
- * We only need to worry about sync'ing the blocks
- * in the mmap case because if the fast cache isn't
- * enabled for AIO the file will be opened with F_SYNC
- * which performs the correct action.
- */
- if (msync((char *)(intptr_t)sa, len, MS_SYNC) == -1) {
- perror("msync");
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- }
- ssc_write_cmplt((emul_handle_t)io);
-}
-
-static void
-ssc_write_cmplt(emul_handle_t e)
-{
- ssc_io_t *io = (ssc_io_t *)e;
- t10_cmd_t *cmd = io->sio_cmd;
- ssc_params_t *s = (ssc_params_t *)T10_PARAMS_AREA(cmd);
-
- if (s == NULL)
- return;
-
- if ((io->sio_offset + io->sio_data_len) < io->sio_total) {
- io->sio_offset += io->sio_data_len;
- ssc_write(cmd, cmd->c_cdb, cmd->c_cdb_len);
- return;
- }
-
- s->s_prev_rec = s->s_cur_rec;
- s->s_cur_rec += io->sio_total + sizeof (ssc_obj_mark_t);
- free(io);
- trans_send_complete(cmd, STATUS_GOOD);
-}
-
-/*ARGSUSED*/
-static void
-ssc_rewind(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- ssc_params_t *s = (ssc_params_t *)T10_PARAMS_AREA(cmd);
-
- if (s == NULL)
- return;
-
- if ((cdb[1] & ~SSC_REWIND_IMMED) || cdb[2] || cdb[3] || cdb[4] ||
- SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- s->s_cur_fm = 0;
- s->s_cur_rec = sizeof (ssc_obj_mark_t);
- trans_send_complete(cmd, STATUS_GOOD);
-}
-
-/*ARGSUSED*/
-static void
-ssc_read_limits(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- struct read_blklim *rb;
- int min_size = 512;
-
- if (cdb[1] || cdb[2] || cdb[3] || cdb[4] ||
- SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- if ((rb = (struct read_blklim *)calloc(1, sizeof (*rb))) == NULL) {
- trans_send_complete(cmd, STATUS_BUSY);
- return;
- }
-
- /*
- * maximum block size is set to zero to indicate no maximum block
- * limit is specified.
- */
- rb->granularity = 9; /* 512 block sizes */
- rb->min_hi = hibyte(min_size);
- rb->min_lo = lobyte(min_size);
-
- if (trans_send_datain(cmd, (char *)rb, sizeof (*rb), 0, ssc_free,
- True, (emul_handle_t)rb) == False) {
- trans_send_complete(cmd, STATUS_BUSY);
- }
-}
-
-/*ARGSUSED*/
-static void
-ssc_space(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- int code,
- count;
- ssc_params_t *s = T10_PARAMS_AREA(cmd);
- ssc_obj_mark_t mark;
- t10_lu_common_t *lu = cmd->c_lu->l_common;
-
- if (s == NULL)
- return;
-
- if ((cdb[1] & 0xf0) || SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- code = cdb[1] & 0x0f;
- count = (cdb[2] << 16) | (cdb[3] << 8) | cdb[4];
-
- if ((count == 0) && (code != SSC_SPACE_CODE_END_OF_DATA)) {
- trans_send_complete(cmd, STATUS_GOOD);
- return;
- }
-
- switch (code) {
- case SSC_SPACE_CODE_BLOCKS:
- if (count < 0) {
- bcopy((char *)lu->l_mmap + s->s_cur_fm + s->s_cur_rec,
- &mark, sizeof (mark));
- if ((mark.som_sig == SSC_OBJ_SIG) &&
- (mark.som_type == SSC_OBJ_TYPE_RM)) {
- count = mark.o_rm.obj_id + count;
-
- /*
- * If the count is still negative it means
- * the request is still attempting to go
- * beyond the beginning of the file mark.
- */
- if (count < 0) {
- count *= -1;
- spc_sense_create(cmd, KEY_NO_SENSE, 0);
- spc_sense_ascq(cmd,
- SPC_ASC_FM_DETECTED,
- SPC_ASCQ_FM_DETECTED);
- spc_sense_info(cmd, count);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- s->s_cur_rec = s->s_cur_fm + sizeof (mark);
- } else {
- /*
- * Something is not right. We'll let the
- * processing below determine exactly what
- * is wrong. So don't update the record
- * mark and sent the count to 1.
- */
- count = 1;
- }
- }
-
- while (count) {
- bcopy((char *)lu->l_mmap + s->s_cur_fm + s->s_cur_rec,
- &mark, sizeof (mark));
-
- /*
- * Something internally bad has happened with
- * the marks in the file.
- */
- if (mark.som_sig != SSC_OBJ_SIG) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "SSC%x LUN%d, bad sig mark: "
- "expected=0x%x, got=0x%x",
- cmd->c_lu->l_targ->s_targ_num,
- cmd->c_lu->l_common->l_num,
- SSC_OBJ_SIG, mark.som_sig);
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- /*
- * Hit a filemark. Update the current record if
- * we're not at the End-Of-Medium.
- */
- if (mark.som_type == SSC_OBJ_TYPE_FM) {
- if (mark.o_fm.eom == True) {
- spc_sense_create(cmd, KEY_MEDIUM_ERROR,
- 0);
- spc_sense_ascq(cmd, SPC_ASC_EOP,
- SPC_ASCQ_EOP);
- spc_sense_info(cmd, count);
- spc_sense_flags(cmd, SPC_SENSE_EOM);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- s->s_cur_fm += s->s_cur_rec;
- s->s_cur_rec += sizeof (mark);
- spc_sense_create(cmd, KEY_NO_SENSE, 0);
- spc_sense_ascq(cmd, SPC_ASC_FM_DETECTED,
- SPC_ASCQ_FM_DETECTED);
- spc_sense_info(cmd, count);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- s->s_cur_rec += mark.o_rm.size;
- count--;
- }
- trans_send_complete(cmd, STATUS_CHECK);
- break;
-
- case SSC_SPACE_CODE_FILEMARKS:
- if (count < 0) {
- bcopy((char *)lu->l_mmap + s->s_cur_fm, &mark,
- sizeof (mark));
- if ((mark.som_sig == SSC_OBJ_SIG) &&
- (mark.som_type == SSC_OBJ_TYPE_FM)) {
- count = mark.o_fm.num + count;
-
- /*
- * If the count is still negative it means
- * the request is still attempting to go
- * beyond the beginning of the file mark.
- */
- if (count < 0) {
- count *= -1;
- spc_sense_create(cmd, KEY_NO_SENSE, 0);
- spc_sense_ascq(cmd,
- SPC_ASC_FM_DETECTED,
- SPC_ASCQ_FM_DETECTED);
- spc_sense_info(cmd, count);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- s->s_cur_fm = 0;
- s->s_cur_rec = sizeof (ssc_obj_mark_t);
- } else {
- /*
- * Something is not right. We'll let the
- * processing below determine exactly what
- * is wrong. So don't update the record
- * mark and sent the count to 1.
- */
- count = 1;
- }
- }
-
- while (count--) {
- bcopy((char *)lu->l_mmap + s->s_cur_fm, &mark,
- sizeof (mark));
- if (mark.som_sig != SSC_OBJ_SIG) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "SSC%x LUN%d, bad sig mark: "
- "expected=0x%x, got=0x%x",
- cmd->c_lu->l_targ->s_targ_num,
- cmd->c_lu->l_common->l_num,
- SSC_OBJ_SIG, mark.som_sig);
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- if (mark.som_type != SSC_OBJ_TYPE_FM) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "SSC%x LUN%d, bad mark type: "
- "expected=0x%x, got=0x%x",
- cmd->c_lu->l_targ->s_targ_num,
- cmd->c_lu->l_common->l_num,
- SSC_OBJ_TYPE_FM, mark.som_type);
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- if (mark.o_fm.eom == True) {
- spc_sense_create(cmd, KEY_MEDIUM_ERROR, 0);
- spc_sense_ascq(cmd, SPC_ASC_EOP, SPC_ASCQ_EOP);
- spc_sense_info(cmd, count);
- spc_sense_flags(cmd, SPC_SENSE_EOM);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- s->s_cur_fm += mark.o_fm.size;
- }
- trans_send_complete(cmd, STATUS_GOOD);
- break;
-
- default:
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-}
-
-/*
- * []----
- * | ssc_msense -- MODE SENSE command
- * |
- * | This command is part of the SPC set, but is device specific enough
- * | that it must be emulated in each device type.
- * []----
- */
-/*ARGSUSED*/
-static void
-ssc_msense(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- ssc_params_t *s = T10_PARAMS_AREA(cmd);
- struct mode_header *mode_hdr;
- int request_len,
- alloc_len;
- char *data,
- *np;
-
- /*
- * SPC-3 Revision 21c section 6.8
- * Reserve bit checks
- */
- if ((cdb[1] & ~8) || SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- /*
- * Zero length causes a simple ack to occur.
- */
- if (cdb[4] == 0) {
- trans_send_complete(cmd, STATUS_GOOD);
- return;
- } else {
- request_len = cdb[4];
- alloc_len = max(request_len,
- sizeof (*mode_hdr) + MODE_BLK_DESC_LENGTH +
- sizeof (ssc_data_compression_t) + sizeof (*mode_hdr) +
- MODE_BLK_DESC_LENGTH + sizeof (ssc_device_config_t));
- }
-
- queue_prt(mgmtq, Q_STE_NONIO, "SSC%x LUN%d: MODE_SENSE(0x%x)",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num, cdb[2]);
-
- if ((data = memalign(sizeof (void *), alloc_len)) == NULL) {
- trans_send_complete(cmd, STATUS_BUSY);
- return;
- }
-
- mode_hdr = (struct mode_header *)data;
-
- switch (cdb[2]) {
- case MODE_SENSE_COMPRESSION:
- mode_hdr->length = sizeof (ssc_data_compression_t);
- mode_hdr->bdesc_length = MODE_BLK_DESC_LENGTH;
- (void) sense_compression(s, data + sizeof (*mode_hdr) +
- mode_hdr->bdesc_length);
- break;
-
- case MODE_SENSE_DEV_CONFIG:
- mode_hdr->length = sizeof (ssc_device_config_t);
- mode_hdr->bdesc_length = MODE_BLK_DESC_LENGTH;
- (void) sense_dev_config(s, data + sizeof (*mode_hdr) +
- mode_hdr->bdesc_length);
- break;
-
- case MODE_SENSE_SEND_ALL:
- np = sense_compression(s, data);
- (void) sense_dev_config(s, np);
- break;
-
- case 0x00:
- bzero(data, alloc_len);
- break;
-
- default:
- queue_prt(mgmtq, Q_STE_ERRS,
- "SSC%x LUN%d: MODE SENSE(0x%x) not handled",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num,
- cdb[2]);
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- if (trans_send_datain(cmd, (char *)data, request_len, 0, ssc_free,
- True, data) == False) {
- trans_send_complete(cmd, STATUS_BUSY);
- }
-}
-
-/*ARGSUSED*/
-static void
-ssc_read_pos(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- int service_action,
- request_len,
- alloc_len;
- pos_short_form_t *sf;
- void *data;
- ssc_params_t *s = (ssc_params_t *)T10_PARAMS_AREA(cmd);
- ssc_obj_mark_t mark;
-
- if (s == NULL)
- return;
-
- /*
- * Standard reserve bit check
- */
- if ((cdb[1] & 0xc0) || cdb[2] || cdb[3] || cdb[4] || cdb[5] ||
- cdb[6] || SAM_CONTROL_BYTE_RESERVED(cdb[9])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- service_action = cdb[1] & 0x1f;
- request_len = (cdb[7] << 8) | cdb[8];
- switch (service_action) {
- case SSC_READ_POS_SHORT_FORM:
- alloc_len = max(request_len, sizeof (*sf));
- if ((data = memalign(sizeof (void *), alloc_len)) == NULL) {
- trans_send_complete(cmd, STATUS_BUSY);
- return;
- }
- sf = (pos_short_form_t *)data;
- bcopy((char *)cmd->c_lu->l_common->l_mmap + s->s_cur_fm,
- &mark, sizeof (mark));
- if ((mark.o_fm.bom == True) &&
- (s->s_cur_rec == sizeof (ssc_obj_mark_t)))
- sf->bop = 1;
- bcopy((char *)cmd->c_lu->l_common->l_mmap + s->s_cur_fm +
- s->s_cur_rec, &mark, sizeof (mark));
- sf->first_obj[0] = hibyte(hiword(mark.o_rm.obj_id));
- sf->first_obj[1] = lobyte(hiword(mark.o_rm.obj_id));
- sf->first_obj[2] = hibyte(loword(mark.o_rm.obj_id));
- sf->first_obj[3] = lobyte(loword(mark.o_rm.obj_id));
-
- /*
- * We mark the last object to be the same as the first
- * object which indicates that nothing is currently
- * buffered.
- */
- sf->last_obj[0] = sf->first_obj[0];
- sf->last_obj[1] = sf->first_obj[1];
- sf->last_obj[2] = sf->first_obj[2];
- sf->last_obj[3] = sf->first_obj[3];
-
- break;
-
- case SSC_READ_POS_LONG_FORM:
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
-
- default:
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- if (trans_send_datain(cmd, (char *)data, request_len, 0, ssc_free,
- True, data) == False) {
- trans_send_complete(cmd, STATUS_BUSY);
- }
-}
-
-/*ARGSUSED*/
-static void
-ssc_rpt_density(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- ssc_density_t *d;
- ssc_density_media_t *dm;
- ssc_params_t *s = (ssc_params_t *)T10_PARAMS_AREA(cmd);
- size_t cap = s->s_size / (1024 * 1024);
- int medium_type,
- request_len,
- alloc_len;
- void *data;
-
- if (s == NULL)
- return;
-
- if ((cdb[1] & 0xfc) || cdb[2] || cdb[3] || cdb[4] || cdb[5] ||
- cdb[6] || SAM_CONTROL_BYTE_RESERVED(cdb[9])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- medium_type = cdb[1] & 0x2;
- request_len = (cdb[7] << 8) | cdb[8];
- alloc_len = max(request_len, max(sizeof (*d), sizeof (*dm)));
- if ((data = memalign(sizeof (void *), alloc_len)) == NULL) {
- trans_send_complete(cmd, STATUS_BUSY);
- return;
- }
- if (medium_type == 0) {
- d = (ssc_density_t *)data;
- d->d_hdr.len = htons(sizeof (*d) -
- sizeof (ssc_density_header_t));
- d->d_prim_code = 1;
- d->d_wrtok = 1;
- d->d_deflt = 1;
- d->d_tracks[1] = 1;
- d->d_capacity[0] = hibyte(hiword(cap));
- d->d_capacity[1] = lobyte(hiword(cap));
- d->d_capacity[2] = hibyte(loword(cap));
- d->d_capacity[3] = lobyte(loword(cap));
- bcopy(cmd->c_lu->l_common->l_vid, d->d_organization,
- min(sizeof (d->d_organization),
- strlen(cmd->c_lu->l_common->l_vid)));
- bcopy(cmd->c_lu->l_common->l_pid, d->d_description,
- min(sizeof (d->d_description),
- strlen(cmd->c_lu->l_common->l_pid)));
- } else {
- dm = (ssc_density_media_t *)data;
- dm->d_hdr.len = htons(sizeof (*d) -
- sizeof (ssc_density_header_t));
- bcopy(cmd->c_lu->l_common->l_vid, d->d_organization,
- min(sizeof (d->d_organization),
- strlen(cmd->c_lu->l_common->l_vid)));
- bcopy(cmd->c_lu->l_common->l_pid, dm->d_description,
- min(sizeof (dm->d_description),
- strlen(cmd->c_lu->l_common->l_pid)));
- }
-
- if (trans_send_datain(cmd, (char *)data, request_len, 0, ssc_free,
- True, (emul_handle_t)data) == False) {
- trans_send_complete(cmd, STATUS_BUSY);
- }
-}
-
-/*ARGSUSED*/
-static void
-ssc_write_fm(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- int marks_requested;
- off_t next_size;
- ssc_params_t *s = (ssc_params_t *)T10_PARAMS_AREA(cmd);
- ssc_obj_mark_t mark_fm;
-
- if (s == NULL)
- return;
-
- if ((cdb[1] & 0xfc) || SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- marks_requested = (cdb[2] << 16) | (cdb[3] << 8) | cdb[4];
- while (marks_requested--) {
- /*
- * Get the last file-mark and update it's size.
- */
- bcopy((char *)cmd->c_lu->l_common->l_mmap + s->s_cur_fm,
- &mark_fm, sizeof (mark_fm));
- if (mark_fm.som_sig != SSC_OBJ_SIG) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- next_size = mark_fm.o_fm.size - s->s_cur_rec;
- mark_fm.o_fm.size = s->s_cur_rec;
- bcopy(&mark_fm, (char *)cmd->c_lu->l_common->l_mmap +
- s->s_cur_fm, sizeof (mark_fm));
-
- /*
- * Write new mark and update internal location of mark.
- */
- mark_fm.o_fm.last_obj_id =
- find_last_obj_id((char *)cmd->c_lu->l_common->l_mmap +
- s->s_cur_fm, s->s_cur_rec);
- mark_fm.o_fm.bom = False;
- mark_fm.o_fm.size = next_size;
- s->s_cur_fm += s->s_cur_rec;
- s->s_cur_rec = sizeof (ssc_obj_mark_t);
- s->s_prev_rec = s->s_cur_rec;
- bcopy(&mark_fm, (char *)cmd->c_lu->l_common->l_mmap +
- s->s_cur_fm, sizeof (mark_fm));
- mark_fm.o_fm.size = 0;
- bcopy(&mark_fm, (char *)cmd->c_lu->l_common->l_mmap +
- s->s_cur_fm + s->s_cur_rec, sizeof (mark_fm));
- }
- trans_send_complete(cmd, STATUS_GOOD);
-}
-
-/*ARGSUSED*/
-static void
-ssc_locate(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
-}
-
-/*ARGSUSED*/
-static void
-ssc_erase(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- ssc_obj_mark_t mark;
- ssc_params_t *s = (ssc_params_t *)T10_PARAMS_AREA(cmd);
-
- if (s == NULL)
- return;
-
- bzero(&mark, sizeof (mark));
- mark.som_sig = SSC_OBJ_SIG;
- mark.som_type = SSC_OBJ_TYPE_FM;
- mark.o_fm.bom = True;
- mark.o_fm.eom = False;
- mark.o_fm.size = s->s_size - sizeof (mark);
-
- bcopy(&mark, (char *)cmd->c_lu->l_common->l_mmap, sizeof (mark));
-}
-
-/*ARGSUSED*/
-static void
-ssc_load(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- ssc_params_t *s = T10_PARAMS_AREA(cmd);
- t10_lu_common_t *lu = cmd->c_lu->l_common;
- ssc_obj_mark_t mark;
-
- /*
- * SSC-3, revision 02, section 7.2 LOAD/UNLOAD command
- * Check for various reserve bits.
- */
- if ((cdb[1] & ~SSC_LOAD_CMD_IMMED) || cdb[2] || cdb[3] ||
- (cdb[4] & ~(SSC_LOAD_CMD_LOAD | SSC_LOAD_CMD_RETEN |
- SSC_LOAD_CMD_EOT | SSC_LOAD_CMD_HOLD)) ||
- SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- queue_prt(mgmtq, Q_STE_NONIO, "SSC%x LUN%d load bits 0x%x",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num, cdb[4]);
-
- /*
- * There are four possible actions based on the LOAD and HOLD
- * bits.
- */
- switch (cdb[4] & (SSC_LOAD_CMD_LOAD|SSC_LOAD_CMD_HOLD)) {
- case SSC_LOAD_CMD_LOAD|SSC_LOAD_CMD_HOLD:
- /*
- * Load the media into the system if not already done
- * so, but do not position tape. The EOT and RETEN should
- * be zero. Since this emulation currently is always available
- * we're good to go.
- */
- break;
-
- case SSC_LOAD_CMD_LOAD:
- /*
- * Without the HOLD bit the tape should be positioned at
- * the beginning of partition 0.
- */
- s->s_cur_fm = 0;
- s->s_cur_rec = sizeof (ssc_obj_mark_t);
- break;
-
- case SSC_LOAD_CMD_HOLD:
- /*
- * Without the LOAD bit we leave the tape online, but look
- * at the RETEN and EOT bits. The RETEN doesn't mean anything
- * for this virtual tape, but we can reposition to EOT.
- */
- if (cdb[4] & SSC_LOAD_CMD_EOT) {
- /*CONSTANTCONDITION*/
- while (1) {
- bcopy((char *)lu->l_mmap + s->s_cur_fm, &mark,
- sizeof (mark));
- if (mark.som_sig != SSC_OBJ_SIG) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "SSC%x LUN%d, bad sig mark: "
- "expected=0x%x, got=0x%x",
- cmd->c_lu->l_targ->s_targ_num,
- cmd->c_lu->l_common->l_num,
- SSC_OBJ_SIG, mark.som_sig);
- spc_sense_create(cmd,
- KEY_MEDIUM_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- if (mark.som_type != SSC_OBJ_TYPE_FM) {
- queue_prt(mgmtq, Q_STE_ERRS,
- "SSC%x LUN%d, bad mark type: "
- "expected=0x%x, got=0x%x",
- cmd->c_lu->l_targ->s_targ_num,
- cmd->c_lu->l_common->l_num,
- SSC_OBJ_TYPE_FM, mark.som_type);
- spc_sense_create(cmd,
- KEY_MEDIUM_ERROR, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
- if (mark.o_fm.eom == True)
- break;
- s->s_cur_fm += mark.o_fm.size;
- }
- }
- break;
-
- case 0:
- /*
- * Unload the current tape.
- */
-
- break;
- }
- trans_send_complete(cmd, STATUS_GOOD);
-}
-
-/*ARGSUSED*/
-static void
-ssc_logsense(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
-{
- spc_log_supported_pages_t p;
- void *v;
-
- /*
- * Reserve bit checks
- */
- if ((cdb[1] & ~(SSC_LOG_SP|SSC_LOG_PPC)) || cdb[3] || cdb[4] ||
- SAM_CONTROL_BYTE_RESERVED(cdb[9])) {
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- return;
- }
-
- queue_prt(mgmtq, Q_STE_ERRS, "SSC%x LUN%d page code 0x%x",
- cmd->c_lu->l_targ->s_targ_num, cmd->c_lu->l_common->l_num, cdb[2]);
-
- switch (cdb[2] & SPC_LOG_PAGE_MASK) {
- case 0:
- if ((v = malloc(sizeof (p))) == NULL) {
- trans_send_complete(cmd, STATUS_BUSY);
- return;
- }
- bzero(&p, sizeof (p));
- p.length[0] = 1;
- bcopy(&p, v, sizeof (p));
- if (trans_send_datain(cmd, (char *)v, sizeof (p), 0, free,
- True, (emul_handle_t)v) == False) {
- trans_send_complete(cmd, STATUS_BUSY);
- }
- break;
-
- default:
- spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
- spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0);
- trans_send_complete(cmd, STATUS_CHECK);
- break;
- }
-}
-
-/*
- * []------------------------------------------------------------------[]
- * | Support functions for the SSC command set |
- * []------------------------------------------------------------------[]
- */
-static uint32_t
-find_last_obj_id(char *file_mark, off_t eod)
-{
- ssc_obj_mark_t rm;
- off_t offset = sizeof (ssc_obj_mark_t);
- uint32_t obj_id = 0xffffffff;
-
- bcopy(file_mark + offset, &rm, sizeof (rm));
- while (rm.som_type == SSC_OBJ_TYPE_RM) {
- obj_id = rm.o_rm.obj_id;
- offset += rm.o_rm.size;
- if (offset >= eod)
- break;
- bcopy(file_mark + offset, &rm, sizeof (rm));
- }
- return (obj_id);
-}
-
-static void
-ssc_setup_tape(ssc_params_t *s, t10_lu_common_t *lu)
-{
- ssc_obj_mark_t mark;
-
- /*
- * Add Begin-of-Partition marker
- */
- bzero(&mark, sizeof (mark));
- mark.som_sig = SSC_OBJ_SIG;
- mark.som_type = SSC_OBJ_TYPE_FM;
- mark.o_fm.bom = True;
- mark.o_fm.eom = False;
- mark.o_fm.size = s->s_size - sizeof (mark);
- bcopy(&mark, lu->l_mmap, sizeof (mark));
-
- /*
- * Add first file-record with a zero size.
- */
- bzero(&mark, sizeof (mark));
- mark.som_sig = SSC_OBJ_SIG;
- mark.som_type = SSC_OBJ_TYPE_RM;
- mark.o_rm.size = 0;
- mark.o_rm.obj_id = 0xffffffff;
- bcopy(&mark, (char *)lu->l_mmap + sizeof (ssc_obj_mark_t),
- sizeof (mark));
-
- /*
- * Add End-of-Partiton marker
- */
- bzero(&mark, sizeof (mark));
- mark.som_sig = SSC_OBJ_SIG;
- mark.som_type = SSC_OBJ_TYPE_FM;
- mark.o_fm.bom = False;
- mark.o_fm.eom = True;
- mark.o_fm.size = 0;
- bcopy(&mark, (char *)lu->l_mmap + s->s_size - sizeof (mark),
- sizeof (mark));
-}
-
-static char *
-sense_compression(ssc_params_t *s, char *data)
-{
- ssc_data_compression_t d;
-
- bzero(&d, sizeof (d));
- d.mode_page.code = MODE_SENSE_COMPRESSION;
- d.mode_page.length = sizeof (d) - sizeof (struct mode_page);
- bcopy(&d, data, sizeof (d));
-
- return (data + sizeof (d));
-}
-
-static char *
-sense_dev_config(ssc_params_t *s, char *data)
-{
- ssc_device_config_t d;
-
- bzero(&d, sizeof (d));
- d.mode_page.code = MODE_SENSE_DEV_CONFIG;
- d.mode_page.length = sizeof (d) - sizeof (struct mode_page);
- d.lois = 1;
- d.socf = 1;
- d.rewind_on_reset = 1;
- bcopy(&d, data, sizeof (d));
-
- return (data + sizeof (d));
-}
-
-static void
-ssc_free(emul_handle_t e)
-{
- free(e);
-}
-
-/*
- * []----
- * | Command table for SSC emulation. This is at the end of the file because
- * | it's big and ugly. ;-) To make for fast translation to the appropriate
- * | emulation routine we just have a big command table with all 256 possible
- * | entries. Most will report STATUS_CHECK, unsupport operation. By doing
- * | this we can avoid error checking for command range.
- * []----
- */
-static scsi_cmd_table_t ssc_table[] = {
- /* 0x00 -- 0x0f */
- { spc_tur, NULL, NULL, "TEST_UNIT_READY" },
- { ssc_rewind, NULL, NULL, "REWIND"},
- { spc_unsupported, NULL, NULL, NULL },
- { spc_request_sense, NULL, NULL, "REQUEST_SENSE" },
- { spc_unsupported, NULL, NULL, NULL },
- { ssc_read_limits, NULL, NULL, "READ BLOCK LIMITS"},
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { ssc_read, NULL, ssc_read_cmplt, "READ(6)" },
- { spc_unsupported, NULL, NULL, NULL },
- { ssc_write, ssc_write_data, ssc_write_cmplt, "WRITE(6)" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x10 -- 0x1f */
- { ssc_write_fm, NULL, NULL, "WRITE_FILEMARKS(6)"},
- { ssc_space, NULL, NULL, "SPACE(6)"},
- { spc_inquiry, NULL, NULL, "INQUIRY" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_mselect, spc_mselect_data, NULL, "MODE_SELECT(6)" },
- { spc_request_sense, NULL, NULL, "RESERVE" },
- { spc_request_sense, NULL, NULL, "RELEASE" },
- { spc_unsupported, NULL, NULL, NULL },
- { ssc_erase, NULL, NULL, "ERASE(6)"},
- { ssc_msense, NULL, NULL, "MODE_SENSE(6)" },
- { ssc_load, NULL, NULL, "LOAD_UNLOAD" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_send_diag, NULL, NULL, "SEND_DIAG" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x20 -- 0x2f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, "READ_CAPACITY" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { ssc_read, NULL, ssc_read_cmplt, "READ_G1" },
- { spc_unsupported, NULL, NULL, NULL },
- { ssc_write, ssc_write_data, ssc_write_cmplt, "WRITE_G1" },
- { ssc_locate, NULL, NULL, "LOCATE(10)"},
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x30 -- 0x3f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { ssc_read_pos, NULL, NULL, "READ POSITION"},
- { spc_unsupported, NULL, NULL, "SYNC_CACHE" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x40 -- 0x4f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { ssc_rpt_density, NULL, NULL, "REPORT DENSITY SUPPORT"},
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { ssc_logsense, NULL, NULL, "LOG SENSE" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x50 -- 0x5f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x60 -- 0x6f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x70 -- 0x7f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x80 -- 0x8f */
- { ssc_write_fm, NULL, NULL, "WRITE_FILEMARKS(16)"},
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { ssc_read, NULL, ssc_read_cmplt, "READ_G4" },
- { spc_unsupported, NULL, NULL, NULL },
- { ssc_write, ssc_write_data, ssc_write_cmplt, "WRITE_G4" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0x90 -- 0x9f */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { ssc_locate, NULL, NULL, "LOCATE(16)"},
- { ssc_erase, NULL, NULL, "ERASE" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, "SVC_ACTION_G4" },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xa0 - 0xaf */
- { spc_report_luns, NULL, NULL, "REPORT_LUNS" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_report_tpgs, NULL, NULL, "REPORT_TPGS" },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xb0 -- 0xbf */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xc0 -- 0xcf */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xd0 -- 0xdf */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xe0 -- 0xef */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-
- /* 0xf0 -- 0xff */
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
-};
diff --git a/usr/src/cmd/iscsi/iscsitgtd/t10_ssc.h b/usr/src/cmd/iscsi/iscsitgtd/t10_ssc.h
deleted file mode 100644
index 6096138899..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_ssc.h
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _T10_SSC_H
-#define _T10_SSC_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Implementation specific headers for SCSI Streaming Commands (Tapes)
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#define SSC_SPACE_CODE_BLOCKS 0x00 /* Mandatory support */
-#define SSC_SPACE_CODE_FILEMARKS 0x01 /* Mandatory support */
-#define SSC_SPACE_CODE_SEQ_FILEMARKS 0x02 /* Optional support */
-#define SSC_SPACE_CODE_END_OF_DATA 0x03 /* Optional support */
-
-#define SSC_READ_POS_SHORT_FORM 0x00
-#define SSC_READ_POS_LONG_FORM 0x06
-
-#define SSC_OBJ_SIG 0x22005454
-#define SSC_OBJ_TYPE_FM 1
-#define SSC_OBJ_TYPE_RM 2
-
-#define SSC_REWIND_IMMED 0x01
-
-/*
- * SSC-3, revision 01c, section 7.2
- * LOAD/UNLOAD bits
- */
-#define SSC_LOAD_CMD_LOAD 0x01
-#define SSC_LOAD_CMD_RETEN 0x02
-#define SSC_LOAD_CMD_EOT 0x04
-#define SSC_LOAD_CMD_HOLD 0x08
-/* ---- bit 0 of byte 1 ---- */
-#define SSC_LOAD_CMD_IMMED 0x01
-
-/*
- * On disk file and record mark object structure.
- */
-typedef struct ssc_obj_mark {
- uint32_t som_sig;
- uint32_t som_type;
- union {
- struct {
- Boolean_t bom,
- eom;
- off_t size;
- uint32_t num,
- last_obj_id;
- } _fm_;
- struct {
- off_t size;
- /*
- * SSC-3 Revision 1c, Section 3.1.40
- * Object Identifier relative to beginning of
- * partition.
- */
- uint32_t obj_id;
- } _rm_;
- char _filler_[512 - (sizeof (uint32_t) * 2)];
- } _u_;
-} ssc_obj_mark_t;
-
-#define o_fm _u_._fm_
-#define o_rm _u_._rm_
-
-/*
- * In core structure which indicates current file-mark and record-mark
- */
-typedef struct ssc_params {
- Boolean_t s_fast_write_ack;
- off_t s_size;
- off_t s_cur_rec, /* starts at sizeof (ssc_obj_mark) */
- s_prev_rec,
- s_cur_fm; /* starts at 0 */
- t10_lu_state_t s_state;
-} ssc_params_t;
-
-/*
- * During asynchronous I/O there are a few things needed to complete
- * the operation.
- */
-typedef struct ssc_io {
- /*
- * Look at SBC for the reason that this member must be first
- */
- t10_aio_t sio_aio;
-
- t10_cmd_t *sio_cmd;
-
- char *sio_data;
- size_t sio_data_len;
- off_t sio_offset; /* offset from s_cur_rec */
- size_t sio_total;
-} ssc_io_t;
-
-/*
- * READ POSITION data format, short form
- */
-typedef struct pos_short_form {
-#if defined(_BIT_FIELDS_LTOH)
- uchar_t rsvd2 : 1,
- perr : 1,
- lolu : 1,
- rsvd1 : 1,
- bycu : 1,
- locu : 1,
- eop : 1,
- bop : 1;
-#elif defined(_BIT_FIELDS_HTOL)
- uchar_t bop : 1,
- eop : 1,
- locu : 1,
- bycu : 1,
- rsvd1 : 1,
- lolu : 1,
- perr : 1,
- rsvd2 : 1;
-#else
-#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
-#endif
- uchar_t partition,
- rsvd3[2],
- first_obj[4],
- last_obj[4],
- rsvd4,
- objs_in_buf[3],
- bytes_in_buf[4];
-} pos_short_form_t;
-
-/*
- * REPORT DENSITY SUPPORT header
- */
-typedef struct ssc_density_header {
- uint16_t len,
- rsvd;
-} ssc_density_header_t;
-
-typedef struct ssc_density {
- ssc_density_header_t d_hdr;
- uchar_t d_prim_code,
- d_secondary_code;
-#if defined(_BIT_FIELDS_LTOH)
- uchar_t d_dlv : 1,
- d_rsvd : 4,
- d_deflt : 1,
- d_dup : 1,
- d_wrtok : 1;
-#elif defined(_BIT_FIELDS_HTOL)
- uchar_t d_wrtok : 1,
- d_dup : 1,
- d_deflt : 1,
- d_rsvd : 4,
- d_dlv : 1;
-#else
-#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
-#endif
- uchar_t d_len[2],
- d_bpm[3],
- d_width[2],
- d_tracks[2],
- d_capacity[4],
- d_organization[8],
- d_name[8],
- d_description[20];
-} ssc_density_t;
-
-typedef struct ssc_density_media {
- ssc_density_header_t d_hdr;
- uchar_t d_type,
- d_resvd1,
- d_len[2],
- d_num_codes,
- d_codes[9],
- d_width[2],
- d_medium_len[2],
- d_rsvd2[2],
- d_organization[8],
- d_medium_name[8],
- d_description[20];
-} ssc_density_media_t;
-
-/*
- * MODE_SENSE/MODE_SELECT, Page Code 0xf
- * Data Compression
- */
-typedef struct ssc_data_compression {
- struct mode_page mode_page;
-#if defined(_BIT_FIELDS_LTOH)
- uchar_t c_rsvd1 : 6,
- c_dcc : 1,
- c_dce : 1;
- uchar_t c_rsdv2 : 5,
- c_red : 2,
- c_dde : 1;
-#elif defined(_BIT_FIELDS_HTOL)
- uchar_t c_dce : 1,
- c_dcc : 1,
- c_rsvd1 : 6;
- uchar_t c_dde : 1,
- c_red : 2,
- c_rsvd2 : 5;
-#else
-#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
-#endif
- uchar_t c_compression_algorithm[4],
- c_decompression_algorithm[4],
- c_rsvd3[4];
-} ssc_data_compression_t;
-
-/*
- * MODE_SENSE/MODE_SELECT, Page Code 0x10
- * Device Configuration
- */
-typedef struct ssc_device_config {
- struct mode_page mode_page;
-#if defined(_BIT_FIELDS_LTOH)
- uchar_t active_format : 5,
- caf : 1,
- obsolete1 : 1,
- rsvd : 1;
- uchar_t active_partion,
- wo_buf_ratio,
- ro_buf_ratio,
- wr_delay_time[2];
- uchar_t rew : 1,
- robo : 1,
- socf : 2,
- avc : 1,
- obsolete2 : 1,
- lois : 1,
- obr : 1;
- uchar_t obsolete3;
- uchar_t bam : 1,
- baml : 1,
- swp : 1,
- sew : 1,
- eeg : 1,
- eod_defined : 3;
- uchar_t obj_size_ew[3],
- data_comp_algorithm;
- uchar_t prmwp : 1,
- perswp : 1,
- asocwp : 1,
- rewind_on_reset : 2,
- oir : 1,
- wtre : 2;
-#elif defined(_BIT_FIELDS_HTOL)
- uchar_t rsvd : 1,
- obsolete1 : 1,
- caf : 1,
- active_format : 5;
- uchar_t active_partion,
- wo_buf_ratio,
- ro_buf_ratio,
- wr_delay_time[2];
- uchar_t obr : 1,
- lois : 1,
- obsolete2 : 1,
- avc : 1,
- socf : 2,
- robo : 1,
- rew : 1;
- uchar_t obsolete3;
- uchar_t eod_defined : 3,
- eeg : 1,
- sew : 1,
- swp : 1,
- baml : 1,
- bam : 1;
- uchar_t obj_size_ew[3],
- data_comp_algorithm;
- uchar_t wtre : 2,
- oir : 1,
- rewind_on_reset : 2,
- asocwp : 1,
- perswp : 1,
- prmwp : 1;
-#else
-#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
-#endif
-} ssc_device_config_t;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _T10_SSC_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/target.h b/usr/src/cmd/iscsi/iscsitgtd/target.h
deleted file mode 100644
index e07ec6601c..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/target.h
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _TARGET_H
-#define _TARGET_H
-
-/*
- * Block comment which describes the contents of this file.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define DEFAULT_CONFIG "/etc/iscsi/"
-#define DEFAULT_CONFIG_LOCATION DEFAULT_CONFIG "target_config.xml"
-#define DEFAULT_TARGET_BASEDIR DEFAULT_CONFIG
-#define DEFAULT_TARGET_LOG "/tmp/target_log"
-
-/*
- * []------------------------------------------------------------------[]
- * | Common strings which are used throughout the target. |
- * []------------------------------------------------------------------[]
- */
-/*
- * Target type strings are used to distinguish between the emulated types.
- * These strings are stored in the params file so they must not be changed
- * without thinking about upgrade issues.
- */
-#define TGT_TYPE_DISK "disk"
-#define TGT_TYPE_TAPE "tape"
-#define TGT_TYPE_OSD "osd"
-#define TGT_TYPE_RAW "raw"
-#define TGT_TYPE_INVALID "invalid"
-
-/*
- * During the creation phase of a LU it starts out offline during block
- * initialization, once initialization is complete it will transition to
- * online. If during the initialization an error occurs it will be so marked.
- */
-#define TGT_STATUS_OFFLINE "offline"
-#define TGT_STATUS_ONLINE "online"
-#define TGT_STATUS_ERRORED "errored"
-
-/*
- * Base file names for the logical units (LU). The format used is params.%d and
- * lun.%d These are used both to build the LU name and when searching the
- * target directory for valid luns. Don't change these names unless the upgrade
- * path has been thought about.
- */
-#define PARAMBASE "params."
-#define LUNBASE "lun."
-#define OSDBASE "osd_root."
-#define PERSISTENCEBASE "pgr."
-#define ISCSI_TARGET_ALIAS "TargetAlias"
-#define ZVOL_PATH "/dev/zvol/rdsk/"
-
-/*
- * Base file name for persistent reservation data (PR). The format used is pr.
- * This name is used both to build the PR name and when searching the target
- * directory for persistent reservation data. Don't change these names unless
- * the upgrade path has been thought about.
- */
-#define PRBASE "persistent_reservations"
-
-/*
- * The IQN names that are created use libuuid + the local target name
- * as the idr_str portion of: iqn.1986-03.com.sun:<version>:<id_str>
- * In case this changes we also include a version number. Currently
- * version 1 is used by the Solaris iSCSI Initiator which has the MAC address,
- * timestamp, and hostname.
- */
-#define TARGET_NAME_VERS 2
-#define TARGET_NOFILE 10000
-
-/*
- * Minimum and maximum values for Target Portal Group Tag as specified
- * by RFC3720
- */
-#define TPGT_MIN 1
-#define TPGT_MAX 65535
-
-/*
- * Minimum and maximum values for MaxRecvDataSegmentLength
- */
-#define MAXRCVDATA_MIN 512
-#define MAXRCVDATA_MAX ((1 << 24) - 1)
-
-/*
- * Major/minor versioning for the configuration files.
- * If we find a configuration file that has a higher
- * major number than we support we exit. Major number
- * changes are for radical structure differences. Shouldn't
- * happen, but we've got a means of detecting such a situation
- * a bailing out before doing any damage. Minor number changes
- * mean additions to the current format have been added. For
- * right now, we use -1, which means ignore the minor number. In
- * the future it would be possible for the software to determine
- * that a file had certain additions, but maybe not all changes.
- */
-#define XML_VERS_MAIN_MAJ 1
-#define XML_VERS_MAIN_MIN -1
-#define XML_VERS_TARG_MAJ 1
-#define XML_VERS_TARG_MIN -1
-#define XML_VERS_LUN_MAJ 1
-#define XML_VERS_LUN_MIN -1
-#define XML_VERS_RESULT_MAJ 1
-#define XML_VERS_RESULT_MIN -1
-
-/*
- * Default values of the LUN parameters
- */
-#define DEFAULT_LUN_SIZE ((1024 * 1024 * 1024) / 512)
-#define DEFAULT_RPM 7200
-#define DEFAULT_HEADS 16
-#define DEFAULT_CYLINDERS 100
-#define DEFAULT_SPT 128
-#define DEFAULT_BYTES_PER 512
-#define DEFAULT_INTERLEAVE 1
-#define DEFAULT_PID "SOLARIS"
-#define DEFAULT_VID "SUN"
-#define DEFAULT_REVISION "1"
-
-/*
- * SPC-3 revision 21c, section 7.6.4.4.4
- * EUI-64 based 16-byte IDENTIFIER field format
- */
-typedef struct eui_16 {
- uchar_t e_vers,
- e_resrv1,
- e_mac[6],
- e_company_id[3],
- e_resv2,
- e_timestamp[4];
-} eui_16_t;
-
-/*
- * SPC-4 revision 11, section 7.6.3.6.5
- * NAA IEEE Registered Extended designator format
- */
-typedef struct naa_16 {
-#if defined(_BIT_FIELDS_LTOH)
- uchar_t n_company_id_hi : 4,
- n_naa : 4;
-#elif defined(_BIT_FIELDS_HTOL)
- uchar_t n_naa : 4,
- n_company_id_hi : 4;
-#else
-#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
-#endif
- uchar_t n_company_id_b1,
- n_company_id_b2;
-#if defined(_BIT_FIELDS_LTOH)
- uchar_t n_resv1 : 4,
- n_company_id_lo : 4;
-#elif defined(_BIT_FIELDS_HTOL)
- uchar_t n_company_id_lo : 4,
- n_resv1 : 4;
-#else
-#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
-#endif
- uchar_t n_timestamp[4];
- uchar_t n_resv2;
- uchar_t n_mac[6];
- uchar_t n_resv3;
-} naa_16_t;
-
-#define SUN_EUI_16_VERS 1
-#define SUN_NAA_16_TYPE 6
-
-#define SUN_INQUIRY_ID_TYPE(GUID) \
- (((naa_16_t *)(GUID))->n_naa == SUN_NAA_16_TYPE ? \
- SPC_INQUIRY_ID_TYPE_NAA : SPC_INQUIRY_ID_TYPE_EUI)
-
-#define SUN_EN 0x144f
-#define MIN_VAL 4
-
-#ifndef min
-#define min(a, b) ((a) > (b) ? (b) : (a))
-#endif
-#ifndef max
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#endif
-
-typedef struct {
- char *name;
- char *(*func)(char *, char *);
- char *delete_name;
-} admin_table_t;
-
-#include <sys/socket.h>
-#include <umem.h>
-#include <iscsitgt_impl.h>
-#include "queue.h"
-
-void create_func(tgt_node_t *, target_queue_t *, target_queue_t *, ucred_t *);
-void modify_func(tgt_node_t *, target_queue_t *, target_queue_t *, ucred_t *);
-void remove_func(tgt_node_t *, target_queue_t *, target_queue_t *, ucred_t *);
-void list_func(tgt_node_t *, target_queue_t *, target_queue_t *, ucred_t *);
-void logout_targ(char *targ);
-char *update_basedir(char *, char *);
-char *valid_radius_srv(char *name, char *prop);
-char *valid_isns_srv(char *name, char *prop);
-Boolean_t if_find_mac(target_queue_t *mgmt);
-void if_target_address(char **text, int *text_length, struct sockaddr *sp);
-
-extern admin_table_t admin_prop_list[];
-extern char *target_basedir;
-extern char *target_log;
-extern char *config_file;
-extern char *pgr_basedir;
-extern tgt_node_t *targets_config;
-extern tgt_node_t *main_config;
-extern uchar_t mac_addr[];
-extern size_t mac_len;
-extern int main_vers_maj,
- main_vers_min,
- targets_vers_maj,
- targets_vers_min,
- iscsi_port;
-extern Boolean_t enforce_strict_guid,
- thin_provisioning,
- disable_tpgs,
- dbg_timestamps,
- pgr_persist;
-extern pthread_rwlock_t targ_config_mutex;
-extern umem_cache_t *iscsi_cmd_cache,
- *t10_cmd_cache,
- *queue_cache;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _TARGET_H */
diff --git a/usr/src/cmd/iscsi/iscsitgtd/util.c b/usr/src/cmd/iscsi/iscsitgtd/util.c
deleted file mode 100644
index 31863e6328..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/util.c
+++ /dev/null
@@ -1,1844 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-
-#include <strings.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <inttypes.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <errno.h>
-#include <utility.h>
-#include <fcntl.h>
-#include <syslog.h>
-
-#include <iscsitgt_impl.h>
-#include "target.h"
-#include "utility.h"
-#include "errcode.h"
-#include "isns_client.h"
-#include <sys/scsi/generic/commands.h>
-#include "mgmt_scf.h"
-#include "t10_spc.h"
-
-#define CRC32_STR "CRC32C"
-#define NONE_STR "None"
-
-static thick_provo_t *thick_head,
- *thick_tail;
-pthread_mutex_t thick_mutex;
-
-static Boolean_t connection_parameters_get(iscsi_conn_t *c, char *targ_name);
-static Boolean_t util_create_guid_naa(char **guid);
-
-void
-util_init()
-{
- (void) pthread_mutex_init(&thick_mutex, NULL);
-}
-
-/*
- * []----
- * | check_access -- see if the requesting initiator is in the ACL
- * |
- * | Optionally will also check to see if this initiator requires
- * | authentication.
- * []----
- */
-Boolean_t
-check_access(tgt_node_t *targ, char *initiator_name, Boolean_t req_chap)
-{
- tgt_node_t *acl;
- tgt_node_t *inode = NULL;
- tgt_node_t *tgt_initiator = NULL;
- char *dummy;
- Boolean_t valid = False;
- Boolean_t found_chap = False;
- Boolean_t access = False;
-
- /*
- * If ISNS is enable check for access privilege from isns server
- */
- if (isns_enabled() == True) {
- if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &dummy)
- == False) {
- return (False);
- }
- access = isns_qry_initiator(dummy, initiator_name);
- free(dummy);
- if (req_chap == False) {
- return (access);
- }
-
- /* Need to check if CHAP is needed for initiator */
- while ((inode = tgt_node_next_child(main_config,
- XML_ELEMENT_INIT, inode)) != NULL) {
- if (tgt_find_value_str(inode, XML_ELEMENT_INAME, &dummy)
- == True) {
- if (strcmp(dummy, initiator_name) == 0) {
- free(dummy);
- if (tgt_find_value_str(inode,
- XML_ELEMENT_CHAPSECRET, &dummy)
- == True) {
- free(dummy);
- found_chap = True;
- break;
- }
- }
- }
- }
- if (access == True) {
- if ((req_chap == True) && (found_chap == True))
- access = False;
- }
- return (access);
- }
-
- /*
- * If there's no ACL for this target everyone has access.
- */
- if ((acl = tgt_node_next(targ, XML_ELEMENT_ACLLIST, NULL)) == NULL)
- return (True);
-
- /*
- * Find the local initiator name and also save the knowledge
- * if the initiator had a CHAP secret.
- */
- inode = NULL;
- while ((inode = tgt_node_next_child(main_config, XML_ELEMENT_INIT,
- inode)) != NULL) {
- if (tgt_find_value_str(inode, XML_ELEMENT_INAME, &dummy) ==
- True) {
- if (strcmp(dummy, initiator_name) == 0) {
- free(dummy);
- if (tgt_find_value_str(inode,
- XML_ELEMENT_CHAPSECRET, &dummy) == True) {
- free(dummy);
- found_chap = True;
- }
- break;
- } else {
- free(dummy);
- }
- }
- }
-
- if ((acl != NULL) && (inode == NULL))
- return (False);
-
- while ((tgt_initiator = tgt_node_next(acl, XML_ELEMENT_INIT,
- tgt_initiator)) != NULL) {
-
- if (strcmp(inode->x_value, tgt_initiator->x_value) == 0) {
- valid = True;
- break;
- }
- }
-
- if (valid == True) {
-
- /*
- * If req_chap is True it means the login code hasn't gone
- * through the authentication phase and it's trying to
- * determine if the initiator should have done so. If
- * we find a CHAP-secret then this routine will fail.
- * No CHAP-secret for an initiator just means that a
- * simple ACL list is used. This can be spoofed easily
- * enough and is mainly used to limit the number of
- * targets an initiator would see.
- */
- if ((req_chap == True) && (found_chap == True))
- valid = False;
- }
-
- return (valid);
-}
-
-/*
- * []----
- * | convert_local_tpgt -- Convert a local tpgt name to real addresses
- * |
- * | To simplify the configuration files targets only have a target portal
- * | group tag string(s) associated. In the main configuration file there's
- * | a tpgt element which has one or more ip-address elements. So the tag
- * | is located and the actual data is inserted into the outgoing stream.
- * []----
- */
-static Boolean_t
-convert_local_tpgt(char **text, int *text_length, char *local_tpgt)
-{
- tgt_node_t *tpgt = NULL;
- tgt_node_t *x;
- char buf[80];
- char ipaddr[4];
-
- while ((tpgt = tgt_node_next_child(main_config, XML_ELEMENT_TPGT,
- tpgt)) != NULL) {
- if (strcmp(tpgt->x_value, local_tpgt) == 0) {
-
- /*
- * The only children of the tpgt element are
- * ip-address elements. The value of each element is
- * the string we need to use. So, we don't need to
- * check the node's name to see if this is correct or
- * not.
- */
- if ((tpgt = tgt_node_next(tpgt, XML_ELEMENT_IPADDRLIST,
- NULL)) == NULL) {
- return (False);
- }
-
- x = NULL;
- while ((x = tgt_node_next(tpgt, XML_ELEMENT_IPADDR, x))
- != NULL) {
- if (inet_pton(AF_INET, x->x_value, &ipaddr)
- == 1) {
- /*
- * Valid IPv4 address
- */
- (void) snprintf(buf, sizeof (buf),
-
- "%s,%s", x->x_value, local_tpgt);
- } else {
- /*
- * Invalid IPv4 address
- * try with brackets (RFC2732)
- */
- (void) snprintf(buf, sizeof (buf),
- "[%s],%s", x->x_value, local_tpgt);
- }
- (void) add_text(text, text_length,
- "TargetAddress", buf);
- }
- break;
- }
- }
-
- return (True);
-}
-
-/*
- * []----
- * | add_target_address -- find and add any target address information
- * []----
- */
-static void
-add_target_address(iscsi_conn_t *c, char **text, int *text_length,
- tgt_node_t *targ)
-{
- tgt_node_t *tpgt_list;
- tgt_node_t *tpgt = NULL;
- struct sockaddr_in *sp4;
- struct sockaddr_in6 *sp6;
- /*
- * 7 is enough room for the largest TPGT of "65536", the ',' and a NULL
- */
- char buf[INET6_ADDRSTRLEN + 7];
- char net_buf[INET6_ADDRSTRLEN];
-
- if ((tpgt_list = tgt_node_next(targ, XML_ELEMENT_TPGTLIST,
- NULL)) == NULL) {
- if_target_address(text, text_length,
- (struct sockaddr *)&c->c_target_sockaddr);
- return;
- }
-
- while ((tpgt = tgt_node_next_child(tpgt_list, XML_ELEMENT_TPGT,
- tpgt)) != NULL) {
- if (convert_local_tpgt(text, text_length, tpgt->x_value) ==
- False) {
- if (c->c_target_sockaddr.ss_family == AF_INET) {
- sp4 = (struct sockaddr_in *)
- &c->c_target_sockaddr;
- (void) snprintf(buf, sizeof (buf), "%s,%s",
- inet_ntop(sp4->sin_family,
- (void *)&sp4->sin_addr,
- net_buf, sizeof (net_buf)),
- tpgt->x_value);
- } else {
- sp6 = (struct sockaddr_in6 *)
- &c->c_target_sockaddr;
- (void) snprintf(buf, sizeof (buf), "[%s],%s",
- inet_ntop(sp6->sin6_family,
- (void *)&sp6->sin6_addr,
- net_buf, sizeof (net_buf)),
- tpgt->x_value);
- }
- (void) add_text(text, text_length, "TargetAddress",
- buf);
- }
- }
-}
-
-/*
- * []----
- * | add_targets -- add TargetName and TargetAddress to text argument
- * |
- * | Add targets which this initiator is allowed to see based on
- * | the access_list associated with a target. If a target doesn't
- * | have an access list then let everyone see it.
- * []----
- */
-static Boolean_t
-add_targets(iscsi_conn_t *c, char **text, int *text_length)
-{
- tgt_node_t *targ = NULL;
- Boolean_t rval = True;
- char *targ_name = NULL;
-
- while ((rval == True) && ((targ = tgt_node_next_child(targets_config,
- XML_ELEMENT_TARG, targ)) != NULL)) {
-
- if (check_access(targ, c->c_sess->s_i_name, False) == True) {
-
- if (tgt_find_value_str(targ, XML_ELEMENT_INAME,
- &targ_name) == False) {
- rval = False;
- break;
- }
- queue_prt(c->c_mgmtq, Q_CONN_LOGIN,
- "CON%x %24s = %s\n", c->c_num, "TargetName",
- targ_name);
-
- (void) add_text(text, text_length, "TargetName",
- targ_name);
- free(targ_name);
- add_target_address(c, text, text_length, targ);
- }
- }
- return (rval);
-}
-
-/*
- * []----
- * | add_text -- Add new name/value pair to possibly existing string
- * []----
- */
-Boolean_t
-add_text(char **text, int *current_length, char *name, char *val)
-{
- int dlen = *current_length;
- int plen;
- char *p;
-
- /*
- * Length is 'name' + separator + 'value' + NULL
- */
- plen = strlen(name) + 1 + strlen(val) + 1;
-
- if (dlen) {
- if ((p = (char *)realloc(*text, dlen + plen)) == NULL)
- return (False);
- } else {
- if ((p = (char *)malloc(plen)) == NULL)
- return (False);
- }
-
- *text = p;
- p = *text + dlen;
-
- (void) snprintf(p, plen, "%s%c%s", name, ISCSI_TEXT_SEPARATOR, val);
- *current_length = dlen + plen;
-
- return (True);
-}
-
-static void
-send_named_msg(iscsi_conn_t *c, msg_type_t t, char *name)
-{
- target_queue_t *q = queue_alloc();
- msg_t *m;
- name_request_t n;
-
- n.nr_q = q;
- n.nr_name = name;
-
- queue_message_set(c->c_sessq, 0, t, &n);
- m = queue_message_get(q);
- queue_message_free(m);
- queue_free(q, NULL);
-}
-
-static Boolean_t
-parse_digest_vals(Boolean_t *bp, char *name, char *val, char **text, int *len)
-{
- Boolean_t rval;
-
- /*
- * It's the initiators data so we'll allow them
- * to determine if CRC checks should be enabled
- * or not. So, look at the first token, which
- * declares their preference, and use that.
- */
- if (strncmp(val, CRC32_STR, strlen(CRC32_STR)) == 0) {
- *bp = True;
- rval = add_text(text, len, name, CRC32_STR);
- } else if (strncmp(val, NONE_STR, strlen(NONE_STR)) == 0) {
- *bp = False;
- rval = add_text(text, len, name, NONE_STR);
- } else {
- *bp = False;
- rval = add_text(text, len, name, "Reject");
- }
-
- return (rval);
-}
-
-/*
- * []----
- * | parse_text -- receive text information from initiator and parse
- * |
- * | Read in the current data based on the amount which the login PDU says
- * | should be available. Add it to the end of previous data if it exists.
- * | Previous data would be from a PDU which had the 'C' bit set and was
- * | stored in the connection.
- * |
- * | Once values for parameter name has been selected store outgoing string
- * | in text message for response.
- * |
- * | If errcode is non-NULL the appropriate login error code will be
- * | stored.
- * []----
- */
-Boolean_t
-parse_text(iscsi_conn_t *c, int dlen, char **text, int *text_length,
- int *errcode)
-{
- char *p = NULL;
- char *n;
- char *cur_pair;
- char param_rsp[32];
- int plen; /* pair length */
- Boolean_t rval = True;
- char *target_name = NULL;
- char *initiator_name = NULL;
- char param_buf[16];
-
- if ((p = (char *)malloc(dlen)) == NULL)
- return (False);
-
- /*
- * Read in data to buffer.
- */
- if (read(c->c_fd, p, dlen) != dlen) {
- free(p);
- return (False);
- }
-
- queue_prt(c->c_mgmtq, Q_CONN_NONIO, "CON%x Available text size %d\n",
- c->c_num, dlen);
-
- /*
- * Read in and toss any pad data
- */
- if (dlen % ISCSI_PAD_WORD_LEN) {
- char junk[ISCSI_PAD_WORD_LEN];
- int pad_len = ISCSI_PAD_WORD_LEN - (dlen % ISCSI_PAD_WORD_LEN);
-
- if (read(c->c_fd, junk, pad_len) != pad_len) {
- free(p);
- return (False);
- }
- }
-
- if (c->c_text_area != NULL) {
- if ((n = (char *)realloc(c->c_text_area,
- c->c_text_len + dlen)) == NULL) {
- free(p);
- return (False);
- }
- bcopy(p, n + c->c_text_len, dlen);
-
- /*
- * No longer need the space allocated to 'p' since it
- * will point to the aggregated area of all data.
- */
- free(p);
-
- /*
- * Point 'p' to this new area for parsing and save the
- * combined length in dlen.
- */
- p = n;
- dlen += c->c_text_len;
-
- /*
- * Clear the indication that space has been allocated
- */
- c->c_text_area = NULL;
- c->c_text_len = 0;
- }
-
- /*
- * At this point 'p' points to the name/value parameters. Need
- * to cycle through each pair.
- */
- n = p;
- while (dlen > 0) {
- cur_pair = n;
-
- plen = strlen(n);
- if ((n = strchr(cur_pair, ISCSI_TEXT_SEPARATOR)) == NULL) {
- if (errcode != NULL)
- *errcode =
- (ISCSI_STATUS_CLASS_INITIATOR_ERR << 8) |
- ISCSI_LOGIN_STATUS_INIT_ERR;
- rval = False;
- break;
- } else
- *n++ = '\0';
-
- queue_prt(c->c_mgmtq, Q_CONN_LOGIN, "CON%x %-24s = %s\n",
- c->c_num, cur_pair, n);
-
- /*
- * At this point, 'cur_pair' points at the name and 'n'
- * points at the value.
- */
-
- /*
- * []--------------------------------------------------[]
- * | The order of parameters processed matches the |
- * | the RFC in section 12. |
- * []--------------------------------------------------[]
- */
- /*
- * 12.1 -- HeaderDigest
- * Negotiated
- */
- if (strcmp("HeaderDigest", cur_pair) == 0) {
-
- rval = parse_digest_vals(&c->c_header_digest,
- cur_pair, n, text, text_length);
-
- /*
- * 12.1 -- DataDigest
- * Negotiated
- */
- } else if (strcmp("DataDigest", cur_pair) == 0) {
-
- rval = parse_digest_vals(&c->c_data_digest, cur_pair,
- n, text, text_length);
-
- /*
- * 12.2 -- MaxConnections
- * Negotiated
- */
- } else if (strcmp("MaxConnections", cur_pair) == 0) {
-
- /* ---- To be fixed ---- */
- c->c_max_connections = 1;
- (void) snprintf(param_rsp, sizeof (param_rsp),
- "%d", c->c_max_connections);
- rval = add_text(text, text_length,
- cur_pair, param_rsp);
-
- /*
- * 12.3 -- SendTargets
- * Declarative
- */
- } else if (strcmp("SendTargets", cur_pair) == 0) {
-
- if ((c->c_sess->s_type != SessionDiscovery) &&
- (strcmp("All", n) == 0)) {
- rval = add_text(text, text_length, cur_pair,
- "Irrelevant");
- } else {
- rval = add_targets(c, text, text_length);
- }
-
- /*
- * 12.4 -- TargetName
- * Declarative
- */
- } else if (strcmp("TargetName", cur_pair) == 0) {
-
- send_named_msg(c, msg_target_name, n);
- target_name = n;
-
- /*
- * 12.5 -- IntiatorName
- * Declarative
- */
- } else if (strcmp("InitiatorName", cur_pair) == 0) {
-
- send_named_msg(c, msg_initiator_name, n);
- initiator_name = n;
-
- /* ---- Section 12.6 is handled within TargetName ---- */
-
- /*
- * 12.7 -- InitiatorAlias
- * Declarative
- */
- } else if (strcmp("InitiatorAlias", cur_pair) == 0) {
-
- send_named_msg(c, msg_initiator_alias, n);
-
- /*
- * Sections 12.8 (TargetAddress) and 12.9
- * (TargetPortalGroupTag) are handled during the SendTargets
- * processing.
- */
-
- /*
- * 12.10 -- IntialR2T
- * Negotiated
- */
- } else if (strcmp("InitialR2T", cur_pair) == 0) {
-
- c->c_initialR2T = True;
- rval = add_text(text, text_length, cur_pair, "Yes");
-
- /*
- * 12.11 -- ImmediateData
- * Negotiated
- */
- } else if (strcmp("ImmediateData", cur_pair) == 0) {
-
- /*
- * Since we can handle immediate data without
- * a problem just echo back what the initiator
- * sends. If the initiator decides to violate
- * the spec by sending immediate data even though
- * they've disabled it, it's their problem and
- * we'll deal with the data.
- */
- c->c_immediate_data = strcmp(n, "No") ? True : False;
- rval = add_text(text, text_length, cur_pair, n);
-
- /*
- * 12.12 -- MaxRecvDataSegmentLength
- * Declarative
- */
- } else if (strcmp("MaxRecvDataSegmentLength", cur_pair) == 0) {
-
- c->c_max_recv_data = strtol(n, NULL, 0);
- rval = add_text(text, text_length, cur_pair, n);
-
- /*
- * 12.13 -- MaxBurstLength
- * Negotiated
- */
- } else if (strcmp("MaxBurstLength", cur_pair) == 0) {
-
- c->c_max_burst_len = strtol(n, NULL, 0);
- rval = add_text(text, text_length, cur_pair, n);
-
- /*
- * 12.14 -- FirstBurstLength
- * Negotiated
- */
- } else if (strcmp("FirstBurstLength", cur_pair) == 0) {
-
- /*
- * We can handle anything the initiator wishes
- * to shove in our direction. So, store the value
- * in case we ever wish to validate input data,
- * but there's no real need to do so.
- */
- c->c_first_burst_len = strtol(n, NULL, 0);
- rval = add_text(text, text_length, cur_pair, n);
-
- /*
- * 12.15 DefaultTime2Wait
- * Negotiated
- */
- } else if (strcmp("DefaultTime2Wait", cur_pair) == 0) {
-
- c->c_default_time_2_wait = strtol(n, NULL, 0);
- rval = add_text(text, text_length, cur_pair, n);
-
- /*
- * 12.16 -- DefaultTime2Retain
- * Negotiated
- */
- } else if (strcmp("DefaultTime2Retain", cur_pair) == 0) {
-
- c->c_default_time_2_retain = strtol(n, NULL, 0);
- rval = add_text(text, text_length, cur_pair, n);
-
- /*
- * 12.17 -- MaxOutstandingR2T
- * Negotiated
- */
- } else if (strcmp("MaxOutstandingR2T", cur_pair) == 0) {
-
- /*
- * Save the value, but at most we'll toss out
- * one R2T packet.
- */
- c->c_max_outstanding_r2t = strtol(n, NULL, 0);
- rval = add_text(text, text_length, cur_pair, n);
-
- /*
- * 12.18 -- DataPDUInOder
- * Negotiated
- */
- } else if (strcmp("DataPDUInOrder", cur_pair) == 0) {
-
- /*
- * We can handle DataPDU's out of order and
- * currently we'll only send them in order. We're
- * to far removed from the hardware to see data
- * coming off of the platters out of order so
- * it's unlikely we'd ever implement this feature.
- * Store the parameter and echo back the initiators
- * request.
- */
- c->c_data_pdu_in_order = strcmp(n, "Yes") == 0 ?
- True : False;
- rval = add_text(text, text_length, cur_pair, n);
-
- /*
- * 12.19 -- DataSequenceInOrder
- * Negotiated
- */
- } else if (strcmp("DataSequenceInOrder", cur_pair) == 0) {
-
- /*
- * Currently we're set up to look at and require
- * PDU sequence numbers be in order. The check
- * now is only done as a prelude to supporting
- * MC/S and guaranteeing the order of incoming
- * packets on different connections.
- */
- c->c_data_sequence_in_order = True;
- rval = add_text(text, text_length, cur_pair, "Yes");
-
- /*
- * 12.20 -- ErrorRecoveryLevel
- * Negotiated
- */
- } else if (strcmp("ErrorRecoveryLevel", cur_pair) == 0) {
-
- c->c_erl = 0;
- (void) snprintf(param_rsp, sizeof (param_rsp),
- "%d", c->c_erl);
- rval = add_text(text, text_length,
- cur_pair, param_rsp);
-
- /*
- * 12.21 -- SessionType
- * Declarative
- */
- } else if (strcmp("SessionType", cur_pair) == 0) {
-
- c->c_sess->s_type = strcmp(n, "Discovery") == 0 ?
- SessionDiscovery : SessionNormal;
-
-
- /*
- * Appendix A 3.1 -- IFMarker
- * Negotiated
- */
- } else if (strcmp("IFMarker", cur_pair) == 0) {
-
- c->c_ifmarker = False;
- rval = add_text(text, text_length, cur_pair, "No");
-
- /*
- * Appendix A 3.1 -- OFMarker
- * Negotiated
- */
- } else if (strcmp("OFMarker", cur_pair) == 0) {
-
- c->c_ofmarker = False;
- rval = add_text(text, text_length, cur_pair, "No");
-
- } else if ((strcmp("AuthMethod", cur_pair) == 0) ||
- (strcmp("CHAP_A", cur_pair) == 0) ||
- (strcmp("CHAP_I", cur_pair) == 0) ||
- (strcmp("CHAP_C", cur_pair) == 0) ||
- (strcmp("CHAP_N", cur_pair) == 0) ||
- (strcmp("CHAP_R", cur_pair) == 0)) {
-
- rval = add_text(&(c->auth_text), &c->auth_text_length,
- cur_pair, n);
-
- } else {
-
- /*
- * It's perfectly legitimate for an initiator to
- * send us a parameter we don't currently understand.
- * For example, an initiator that supports iSER will
- * send an RDMA options parameter. If we respond with
- * a valid return value it knows to switch to iSER
- * for future processing.
- */
- rval = add_text(text, text_length,
- cur_pair, "NotUnderstood");
-
- /*
- * Go ahead a log this information in case we see
- * something unexpected.
- */
- queue_prt(c->c_mgmtq, Q_CONN_ERRS,
- "CON%x Unknown parameter %s=%s\n",
- c->c_num, cur_pair, n);
- }
-
- /*
- * If parsed both Initiator and Target names have been parsed,
- * then it is now time to load the connection parameters.
- *
- * This may fail because the target doesn't exist or the
- * initiator doesn't have permission to access this target.
- */
- if ((target_name != NULL) && (initiator_name != NULL)) {
- if ((rval = connection_parameters_get(c, target_name))
- == False) {
- if ((errcode != NULL) && (*errcode == 0))
- *errcode =
- (ISCSI_STATUS_CLASS_INITIATOR_ERR
- << 8) |
- ISCSI_LOGIN_STATUS_TGT_FORBIDDEN;
- } else if ((rval = add_text(text, text_length,
- "TargetAlias", c->c_targ_alias)) == True) {
-
- /*
- * Add TPGT now
- */
- (void) snprintf(param_buf, sizeof (param_buf),
- "%d", c->c_tpgt);
- rval = add_text(text, text_length,
- "TargetPortalGroupTag", param_buf);
- target_name = initiator_name = NULL;
- }
- }
-
- if (rval == False) {
- /*
- * Make sure the caller wants error status and that it
- * hasn't already been set.
- */
- if ((errcode != NULL) && (*errcode == 0))
- *errcode =
- (ISCSI_STATUS_CLASS_TARGET_ERR << 8) |
- ISCSI_LOGIN_STATUS_TARGET_ERROR;
- break;
- }
-
- /*
- * next pair of parameters. 1 is added to include the NULL
- * byte and the end of each string.
- */
- n = cur_pair + plen + 1;
- dlen -= (plen + 1);
- }
-
- if (p != NULL)
- free(p);
-
- return (rval);
-}
-
-/*
- * Pre-seed connection parameters to default values
- * See RFC 3720 Section 12
- */
-void
-connection_parameters_default(iscsi_conn_t *c)
-{
- c->c_max_connections = 1; /* MaxConnections */
- c->c_tpgt = 1; /* TargetPortalGroupTag */
- c->c_initialR2T = True; /* InitialR2T */
- c->c_immediate_data = True; /* ImmediateData */
- c->c_max_recv_data = 8192; /* MaxRecvDataSegmentLength */
- c->c_max_burst_len = 262144; /* MaxBurstLength */
- c->c_first_burst_len = 65536; /* FirstBurstLength */
- c->c_default_time_2_wait = 2; /* DefaultTime2Wait */
- c->c_default_time_2_retain = 20; /* DefaultTime2Retain */
- c->c_max_outstanding_r2t = 1; /* MaxOutStandingR2T */
- c->c_data_pdu_in_order = True; /* DataPDUInOrder */
- c->c_data_sequence_in_order = True; /* DataSequenceOrder */
- c->c_erl = 0; /* ErrorRecoveryLevel */
-}
-
-/*
- * []----
- * | find_main_tpgt -- Looks up the IP address and finds a match TPGT
- * |
- * | If no TPGT for this address exists the routine returns 0 which
- * | is an illegal TPGT value.
- * []----
- */
-static int
-find_main_tpgt(struct sockaddr_storage *pst)
-{
- char ip_addr[16];
- tgt_node_t *tpgt = NULL;
- tgt_node_t *ip_node = NULL;
- struct in_addr addr;
- struct in6_addr addr6;
-
- /*
- * Hardly can you believe that such struct-to-struct
- * assignment IS valid.
- */
- addr = ((struct sockaddr_in *)pst)->sin_addr;
- addr6 = ((struct sockaddr_in6 *)pst)->sin6_addr;
-
- while ((tpgt = tgt_node_next_child(main_config, XML_ELEMENT_TPGT,
- tpgt)) != NULL) {
-
- ip_node = NULL;
- while ((ip_node = tgt_node_next(tpgt, XML_ELEMENT_IPADDR,
- ip_node)) != NULL) {
-
- if (pst->ss_family == AF_INET) {
-
- if (inet_pton(AF_INET, ip_node->x_value,
- ip_addr) != 1) {
- continue;
- }
- if (bcmp(ip_addr, &addr,
- sizeof (struct in_addr)) == 0) {
- return (atoi(tpgt->x_value));
- }
- } else if (pst->ss_family == AF_INET6) {
-
- if (inet_pton(AF_INET6, ip_node->x_value,
- ip_addr) != 1) {
- continue;
- }
- if (bcmp(ip_addr, &addr6,
- sizeof (struct in6_addr)) == 0) {
- return (atoi(tpgt->x_value));
- }
- }
- }
- }
-
- return (0);
-}
-
-/*
- * convert_to_tpgt -- return a TPGT based on the target address
- *
- * If a target doesn't have a TPGT list then just return the default
- * value of 1. Otherwise determine which TPGT the target address is
- * part of and find that TPGT value in the list of TPGTs this target
- * is willing to expose. If the TPGT value is not found in the list
- * return zero which will break the connection.
- */
-static int
-convert_to_tpgt(iscsi_conn_t *c, tgt_node_t *targ)
-{
- tgt_node_t *list;
- tgt_node_t *tpgt = NULL;
- int addr_tpgt, pos_tpgt;
-
- /*
- * If this target doesn't have a list of target portal group tags
- * just return the default which is 1.
- */
- list = tgt_node_next(targ, XML_ELEMENT_TPGTLIST, NULL);
- if (list == NULL)
- return (1);
-
- /*
- * If we don't find our IP in the general configuration list
- * we'll use the default value which is 1 according to RFC3720.
- */
- addr_tpgt = find_main_tpgt(&(c->c_target_sockaddr));
-
- while ((tpgt = tgt_node_next(list, XML_ELEMENT_TPGT, tpgt)) != NULL) {
- (void) tgt_find_value_int(tpgt, XML_ELEMENT_TPGT, &pos_tpgt);
- if (pos_tpgt == addr_tpgt) {
- return (addr_tpgt);
- }
- }
-
- return (0);
-}
-
-/*
- * []----
- * | find_target_node -- given a target IQN name, return the XML node
- * []----
- */
-tgt_node_t *
-find_target_node(char *targ_name)
-{
- tgt_node_t *tnode = NULL;
- char *iname;
-
- while ((tnode = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
- tnode)) != NULL) {
- if (tgt_find_value_str(tnode, XML_ELEMENT_INAME, &iname) ==
- True) {
- if (strcmp(iname, targ_name) == 0) {
- free(iname);
- return (tnode);
- } else
- free(iname);
- }
- }
-
- return (NULL);
-}
-
-static Boolean_t
-connection_parameters_get(iscsi_conn_t *c, char *targ_name)
-{
- tgt_node_t *targ, *alias;
- Boolean_t rval = False;
-
- (void) pthread_rwlock_rdlock(&targ_config_mutex);
- if ((targ = find_target_node(targ_name)) != NULL) {
-
- if (check_access(targ, c->c_sess->s_i_name, False) == False) {
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (False);
- }
-
- /*
- * Have a valid node for our target. Start looking
- * for connection oriented parameters.
- */
- if ((c->c_tpgt = convert_to_tpgt(c, targ)) == 0) {
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (False);
- }
- if ((alias = tgt_node_next(targ, XML_ELEMENT_ALIAS, NULL)) ==
- NULL) {
- (void) tgt_find_value_str(targ, XML_ELEMENT_TARG,
- &c->c_targ_alias);
- } else {
- (void) tgt_find_value_str(alias, XML_ELEMENT_ALIAS,
- &c->c_targ_alias);
- }
-
- (void) tgt_find_value_int(targ, XML_ELEMENT_MAXCMDS,
- &c->c_maxcmdsn);
- rval = True;
- }
-
- (void) pthread_rwlock_unlock(&targ_config_mutex);
- return (rval);
-}
-
-Boolean_t
-validate_version(tgt_node_t *node, int *maj_p, int *min_p)
-{
- char *vers_str = NULL;
- char *minor_part;
- int maj, min;
-
- if ((tgt_find_attr_str(node, XML_ELEMENT_VERS, &vers_str) == False) ||
- (vers_str == NULL))
- return (False);
-
- maj = strtol(vers_str, &minor_part, 0);
- if ((maj > *maj_p) || (minor_part == NULL) || (*minor_part != '.')) {
- free(vers_str);
- return (False);
- }
-
- min = strtol(&minor_part[1], NULL, 0);
- *maj_p = maj;
- *min_p = min;
- free(vers_str);
-
- return (True);
-}
-
-/*
- * []----
- * | sna_lt -- Serial Number Arithmetic, 32 bits, less than, RFC1982
- * []----
- */
-int
-sna_lt(uint32_t n1, uint32_t n2)
-{
- return ((n1 != n2) &&
- (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) ||
- ((n1 > n2) && ((n1 - n2) > SNA32_CHECK))));
-}
-
-/*
- * []----
- * sna_lte -- Serial Number Arithmetic, 32 bits, less than, RFC1982
- * []----
- */
-int
-sna_lte(uint32_t n1, uint32_t n2)
-{
- return ((n1 == n2) ||
- (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) ||
- ((n1 > n2) && ((n1 - n2) > SNA32_CHECK))));
-}
-
-/*
- * util_create_guid -- generate GUID based on the guid type
- * id_type: SPC_INQUIRY_ID_TYPE_EUI -
- * EUI-64 based 16-byte designator format;
- * SPC_INQUIRY_ID_TYPE_NAA -
- * NAA IEEE Registered Extended designator format.
- *
- * SPC-4 revision 11 section 7.6.3.5.4 and 7.6.3.6.5.
- *
- * Note that now this function is always called with parameter
- * id_type SPC_INQUIRY_ID_TYPE_NAA, therefore the code for creating
- * EUI-64 based 16-byte format GUID is no longer used. But in order
- * to keep backward compatiability and for future extension, all the
- * code that has been used for creating old GUIDs should be kept, to
- * make the format clear for all possible GUIDs targets might have.
- */
-Boolean_t
-util_create_guid(char **guid, uchar_t id_type)
-{
- eui_16_t eui;
- /*
- * We only have room for 32bits of data in the GUID. The hiword/loword
- * macros will not work on 64bit variables. The work, but produce
- * invalid results on Big Endian based machines.
- */
- uint32_t tval = (uint_t)time((time_t *)0);
- size_t guid_size;
- int i, fd;
-
- /*
- * Create the NAA (6) GUID.
- */
- if (id_type == SPC_INQUIRY_ID_TYPE_NAA) {
- return (util_create_guid_naa(guid));
- }
-
- if ((mac_len == 0) && (if_find_mac(NULL) == False)) {
-
- /*
- * By default strict GUID generation is enforced. This can
- * be disabled by using the correct XML tag in the configuration
- * file.
- */
- if (enforce_strict_guid == True)
- return (False);
-
- /*
- * There's no MAC address available and we've even tried
- * a second time to get one. So fallback to using a random
- * number for the MAC address.
- */
- if ((fd = open("/dev/random", O_RDONLY)) < 0)
- return (False);
- if (read(fd, &eui, sizeof (eui)) != sizeof (eui))
- return (False);
- (void) close(fd);
-
- eui.e_vers = SUN_EUI_16_VERS;
- eui.e_company_id[0] = (SUN_EN >> 16) & 0xff;
- eui.e_company_id[1] = (SUN_EN >> 8) & 0xff;
- eui.e_company_id[2] = SUN_EN & 0xff;
-
- } else {
- bzero(&eui, sizeof (eui));
-
- eui.e_vers = SUN_EUI_16_VERS;
- eui.e_company_id[0] = (SUN_EN >> 16) & 0xff;
- eui.e_company_id[1] = (SUN_EN >> 8) & 0xff;
- eui.e_company_id[2] = SUN_EN & 0xff;
- eui.e_timestamp[0] = hibyte(hiword(tval));
- eui.e_timestamp[1] = lobyte(hiword(tval));
- eui.e_timestamp[2] = hibyte(loword(tval));
- eui.e_timestamp[3] = lobyte(loword(tval));
- for (i = 0; i < min(mac_len, sizeof (eui.e_mac)); i++) {
- eui.e_mac[i] = mac_addr[i];
- }
-
- /*
- * To prevent duplicate GUIDs we need to sleep for one
- * second here since part of the GUID is a time stamp with
- * a one second resolution.
- */
- (void) sleep(1);
- }
-
- if (tgt_xml_encode((uint8_t *)&eui, sizeof (eui), guid,
- &guid_size) == False) {
- return (False);
- } else
- return (True);
-}
-
-Boolean_t
-util_create_guid_naa(char **guid)
-{
- naa_16_t naa;
- /*
- * We only have room for 32bits of data in the GUID. The hiword/loword
- * macros will not work on 64bit variables. The work, but produce
- * invalid results on Big Endian based machines.
- */
- uint32_t tval = (uint_t)time((time_t *)0);
- size_t guid_size;
- int i, fd;
-
- if ((mac_len == 0) && (if_find_mac(NULL) == False)) {
-
- /*
- * By default strict GUID generation is enforced. This can
- * be disabled by using the correct XML tag in the configuration
- * file.
- */
- if (enforce_strict_guid == True)
- return (False);
-
- /*
- * There's no MAC address available and we've even tried
- * a second time to get one. So fallback to using a random
- * number for the MAC address.
- */
- if ((fd = open("/dev/random", O_RDONLY)) < 0)
- return (False);
- if (read(fd, &naa, sizeof (naa)) != sizeof (naa))
- return (False);
- (void) close(fd);
-
- } else {
- bzero(&naa, sizeof (naa));
-
- /*
- * Set vendor specific identifier and extension.
- */
- naa.n_timestamp[0] = hibyte(hiword(tval));
- naa.n_timestamp[1] = lobyte(hiword(tval));
- naa.n_timestamp[2] = hibyte(loword(tval));
- naa.n_timestamp[3] = lobyte(loword(tval));
- for (i = 0; i < min(mac_len, sizeof (naa.n_mac)); i++) {
- naa.n_mac[i] = mac_addr[i];
- }
-
- /*
- * To prevent duplicate GUIDs we need to sleep for one
- * second here since part of the GUID is a time stamp with
- * a one second resolution.
- */
- (void) sleep(1);
- }
-
- /*
- * Set NAA (6) and IEEE Company_ID.
- */
- naa.n_naa = SUN_NAA_16_TYPE;
- naa.n_company_id_hi = (SUN_EN >> 20) & 0x0f;
- naa.n_company_id_b1 = (SUN_EN >> 12) & 0xff;
- naa.n_company_id_b2 = (SUN_EN >> 4) & 0xff;
- naa.n_company_id_lo = SUN_EN & 0x0f;
- if (tgt_xml_encode((uint8_t *)&naa, sizeof (naa), guid,
- &guid_size) == False) {
- return (False);
- } else
- return (True);
-}
-
-/*
- * []----
- * | create_geom -- based on size, determine best fit for CHS
- * |
- * | Given size in bytes, which will be adjusted to blocks, find
- * | the best fit for making (C * H * S == blocks)
- * |
- * | Note that the following algorithm was derived from the
- * | common disk label implementation, cmlb_convert_geometry().
- * |
- * []----
- */
-void
-create_geom(diskaddr_t size, int *cylinders, int *heads, int *spt)
-{
- diskaddr_t blocks = size >> 9; /* 512 bytes/block */
-
- /*
- * For all devices we calculate cylinders using the heads and sectors
- * we assign based on capacity of the device. The algorithm is
- * designed to be compatible with the way other operating systems
- * lay out fdisk tables for X86 and to insure that the cylinders never
- * exceed 65535 to prevent problems with X86 ioctls that report
- * geometry.
- * For some smaller disk sizes we report geometry that matches those
- * used by X86 BIOS usage. For larger disks, we use SPT that are
- * multiples of 63, since other OSes that are not limited to 16-bits
- * for cylinders stop at 63 SPT we make do by using multiples of 63 SPT.
- *
- * The following table (in order) illustrates some end result
- * calculations:
- *
- * Maximum number of blocks nhead nsect
- *
- * 2097152 (1GB) 64 32
- * 16777216 (8GB) 128 32
- * 1052819775 (502.02GB) 255 63
- * 2105639550 (0.98TB) 255 126
- * 3158459325 (1.47TB) 255 189
- * 4211279100 (1.96TB) 255 252
- * 5264098875 (2.45TB) 255 315
- * ...
- */
-
- if (blocks <= 0x200000) {
- *heads = 64;
- *spt = 32;
- } else if (blocks <= 0x01000000) {
- *heads = 128;
- *spt = 32;
- } else {
- *heads = 255;
-
- /* make sectors-per-track be smallest multiple of 63 */
- *spt = ((blocks +
- (UINT16_MAX * 255 * 63) - 1) /
- (UINT16_MAX * 255 * 63)) * 63;
-
- if (*spt == 0)
- *spt = (UINT16_MAX / 63) * 63;
- }
-
- /* cyls/dsk = (sectors/dsk) / (sectors/trk * tracks/cyl) */
- *cylinders = blocks / (*spt * *heads);
-}
-
-/*
- * []----
- * | strtol_multiplier -- common method to deal with human type numbers
- * []----
- */
-Boolean_t
-strtoll_multiplier(char *str, uint64_t *sp)
-{
- char *m;
- uint64_t size;
-
- size = strtoll(str, &m, 0);
- if (m && *m) {
- switch (*m) {
- case 't':
- case 'T':
- size *= 1024;
- /*FALLTHRU*/
- case 'g':
- case 'G':
- size *= 1024;
- /*FALLTHRU*/
- case 'm':
- case 'M':
- size *= 1024;
- /*FALLTHRU*/
- case 'k':
- case 'K':
- size *= 1024;
- break;
-
- default:
- return (False);
- }
- }
-
- *sp = size;
- return (True);
-}
-
-/*
- * []----
- * | util_title -- print out start/end title in consistent manner
- * []----
- */
-void
-util_title(target_queue_t *q, int type, int num, char *title)
-{
- char *type_str;
- int len, pad;
-
- len = strlen(title);
- pad = len & 1;
-
- switch (type) {
- case Q_CONN_LOGIN:
- case Q_CONN_NONIO:
- type_str = "CON";
- break;
-
- case Q_SESS_LOGIN:
- case Q_SESS_NONIO:
- type_str = "SES";
- break;
-
- case Q_STE_NONIO:
- type_str = "SAM";
- break;
-
- default:
- type_str = "UGH";
- break;
- }
-
- queue_prt(q, type, "%s%x ---- %*s%s%*s ----\n", type_str, num,
- ((60 - len) / 2), "", title, ((60 - len) / 2) + pad, "");
-}
-
-/*
- * []----
- * | task_to_str -- convert task management event to string (DEBUG USE)
- * []----
- */
-char *
-task_to_str(int func)
-{
- switch (func) {
- case ISCSI_TM_FUNC_ABORT_TASK: return ("Abort");
- case ISCSI_TM_FUNC_ABORT_TASK_SET: return ("Abort Set");
- case ISCSI_TM_FUNC_CLEAR_ACA: return ("Clear ACA");
- case ISCSI_TM_FUNC_CLEAR_TASK_SET: return ("Clear Task");
- case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET: return ("LUN Reset");
- case ISCSI_TM_FUNC_TARGET_WARM_RESET: return ("Target Warm Reset");
- case ISCSI_TM_FUNC_TARGET_COLD_RESET: return ("Target Cold Reset");
- case ISCSI_TM_FUNC_TASK_REASSIGN: return ("Task Reassign");
- default: return ("Unknown");
- }
-}
-
-/*
- * []----
- * | xml_rtn_msg -- create a common format for XML replies to management UI
- * []----
- */
-void
-xml_rtn_msg(char **buf, err_code_t code)
-{
- char lbuf[16];
-
- tgt_buf_add_tag_and_attr(buf, XML_ELEMENT_ERROR, "version='1.0'");
- (void) snprintf(lbuf, sizeof (lbuf), "%d", code);
- tgt_buf_add(buf, XML_ELEMENT_CODE, lbuf);
- tgt_buf_add(buf, XML_ELEMENT_MESSAGE, errcode_to_str(code));
- tgt_buf_add_tag(buf, XML_ELEMENT_ERROR, Tag_End);
-}
-
-/*
- * []----
- * | thick_provo_start -- start an initialization thread for targ/lun
- * []----
- */
-void *
-thick_provo_start(void *v)
-{
- thick_provo_t *tp = (thick_provo_t *)v;
- msg_t *m;
- Boolean_t rval;
- char *err = NULL;
-
- /*
- * Add this threads information to the main queue. This is
- * used in case the administrator decides to remove the LU
- * before the initialization is complete.
- */
- (void) pthread_mutex_lock(&thick_mutex);
- if (thick_head == NULL) {
- thick_head = tp;
- } else {
- thick_tail->next = tp;
- tp->prev = thick_tail;
- }
- thick_tail = tp;
- (void) pthread_mutex_unlock(&thick_mutex);
-
- /*
- * This let's the parent thread know this thread is running.
- */
- queue_message_set(tp->q, 0, msg_mgmt_rply, 0);
-
- /* ---- Start the initialization of the LU ---- */
- rval = t10_thick_provision(tp->targ_name, tp->lun, tp->q);
-
- /* ---- Remove from the linked list ---- */
- (void) pthread_mutex_lock(&thick_mutex);
- if (tp->prev == NULL) {
- assert(tp == thick_head);
- thick_head = tp->next;
- if (tp->next == NULL) {
- assert(tp == thick_tail);
- thick_tail = NULL;
- } else
- tp->next->prev = NULL;
- } else {
- tp->prev->next = tp->next;
- if (tp->next != NULL)
- tp->next->prev = tp->prev;
- else
- thick_tail = tp->prev;
- }
- (void) pthread_mutex_unlock(&thick_mutex);
-
- /*
- * There's a race condition where t10_thick_provision() could
- * finish and before the thick_mutex lock is grabbed again
- * that another thread running the thick_provo_stop() could
- * find a match and send a shutdown message. If that happened
- * that thread would wait forever in queue_message_get(). So,
- * After this target/lun pair has been removed check the message
- * queue one last time to see if there's a message available.
- * If so, send an ack.
- */
- m = queue_message_try_get(tp->q);
- if (m != NULL) {
- assert(m->msg_type == msg_shutdown);
- queue_message_set((target_queue_t *)m->msg_data, 0,
- msg_shutdown_rsp, 0);
- }
-
- if (rval == True)
- iscsi_inventory_change(tp->targ_name);
- else {
- queue_prt(mgmtq, Q_GEN_ERRS, "Failed to initialize %s/%d\n",
- tp->targ_name, tp->lun);
- syslog(LOG_ERR, "Failed to initialize %s, LU%d", tp->targ_name,
- tp->lun);
- remove_target_common(tp->targ_name, tp->lun, &err);
- if (err != NULL) {
-
- /*
- * There's not much we can do here. The most likely
- * cause of not being able to remove the target is
- * that it's LU 0 and there is currently another
- * LU allocated.
- */
- queue_prt(mgmtq, Q_GEN_ERRS,
- "Failed to remove target\n");
- syslog(LOG_ERR, "Failed to remove target/lun after "
- "initialization failure");
- }
- }
-
- free(tp->targ_name);
- queue_free(tp->q, NULL);
- free(tp);
-
- queue_message_set(mgmtq, 0, msg_pthread_join,
- (void *)(uintptr_t)pthread_self());
- return (NULL);
-}
-
-/*
- * []----
- * | thick_provo_stop -- stop initialization thread for given targ/lun
- * []----
- */
-void
-thick_provo_stop(char *targ, int lun)
-{
- thick_provo_t *tp;
- target_queue_t *q = queue_alloc();
-
- (void) pthread_mutex_lock(&thick_mutex);
- tp = thick_head;
- while (tp) {
- if ((strcmp(tp->targ_name, targ) == 0) && (tp->lun == lun)) {
- queue_message_set(tp->q, 0, msg_shutdown, (void *)q);
- /*
- * Drop the global mutex because it's entirely
- * possible for a thick_provo_start thread to be
- * in the early stages in which it will can call
- * thick_provo_chk() from the T10 SAM code.
- */
- (void) pthread_mutex_unlock(&thick_mutex);
-
- queue_message_free(queue_message_get(q));
-
- /*
- * Pick the lock back up since it'll make the
- * finish stage easier to deal with.
- */
- (void) pthread_mutex_lock(&thick_mutex);
- break;
- }
- tp = tp->next;
- }
- (void) pthread_mutex_unlock(&thick_mutex);
- queue_free(q, NULL);
-}
-
-/*
- * []----
- * | thick_provo_chk_thr -- see if there's an initialization thread running
- * []----
- */
-Boolean_t
-thick_provo_chk_thr(char *targ, int lun)
-{
- thick_provo_t *tp;
- Boolean_t rval = False;
-
- (void) pthread_mutex_lock(&thick_mutex);
- tp = thick_head;
- while (tp) {
- if ((strcmp(tp->targ_name, targ) == 0) && (tp->lun == lun)) {
- rval = True;
- break;
- }
- tp = tp->next;
- }
- (void) pthread_mutex_unlock(&thick_mutex);
-
- return (rval);
-}
-
-/*
- * []----
- * | remove_target_common -- remove targ/lun from system.
- * |
- * | This is a common function that's used both by the normal remove
- * | target code and when a write failure occurs during initialization.
- * | It will handle being given either the local target name or the full
- * | IQN name of the target.
- * []----
- */
-void
-remove_target_common(char *name, int lun_num, char **msg)
-{
- tgt_node_t *targ = NULL;
- tgt_node_t *list, *lun, *c;
- char path[MAXPATHLEN];
- char *tname = NULL;
- char *iname = NULL;
- int chk;
-
- while ((targ = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
- targ)) != NULL) {
- /* ---- Look for a match on the friendly name ---- */
- if (strcmp(targ->x_value, name) == 0) {
- tname = name;
- break;
- }
-
- /* ---- Check to see if they gave the IQN name instead ---- */
- if ((tgt_find_value_str(targ, XML_ELEMENT_INAME, &iname) ==
- True) && (strcmp(iname, name) == 0))
- break;
- else {
- free(iname);
- iname = NULL;
- }
- }
-
- /* ---- Check to see if it's already been removed ---- */
- if (targ == NULL) {
- return;
- }
-
- /*
- * We need both the friendly and IQN names so figure out which wasn't
- * given and find it's value.
- */
- if (tname == NULL)
- tname = targ->x_value;
- if (iname == NULL) {
- if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &iname) ==
- False) {
- xml_rtn_msg(msg, ERR_INTERNAL_ERROR);
- return;
- }
- }
-
- if ((list = tgt_node_next(targ, XML_ELEMENT_LUNLIST, NULL)) == NULL)
- goto error;
-
- if (lun_num == 0) {
-
- /*
- * LUN must be the last one removed, so check to
- * see if others are still present.
- */
- lun = NULL;
- while ((lun = tgt_node_next(list, XML_ELEMENT_LUN, lun)) !=
- NULL) {
- if (tgt_find_value_int(lun, XML_ELEMENT_LUN, &chk) ==
- False)
- goto error;
-
- if (chk != lun_num) {
- xml_rtn_msg(msg, ERR_LUN_ZERO_NOT_LAST);
- goto error;
- }
- }
- } else {
-
- /*
- * Make sure the LU exists that's being removed
- */
- lun = NULL;
- while ((lun = tgt_node_next(list, XML_ELEMENT_LUN, lun)) !=
- NULL) {
- if (tgt_find_value_int(lun, XML_ELEMENT_LUN, &chk) ==
- False)
- goto error;
-
- if (chk == lun_num) {
- lun = tgt_node_alloc(XML_ELEMENT_LUN, Int,
- &lun_num);
- (void) tgt_node_remove(list, lun, MatchBoth);
- tgt_node_free(lun);
- break;
- }
- }
- if (lun == NULL) {
- xml_rtn_msg(msg, ERR_LUN_NOT_FOUND);
- goto error;
- }
- }
-
- /* ---- Say goodbye to that data ---- */
- (void) snprintf(path, sizeof (path), "%s/%s/%s%d", target_basedir,
- iname, LUNBASE, lun_num);
- (void) unlink(path);
- (void) snprintf(path, sizeof (path), "%s/%s/%s%d", target_basedir,
- iname, PARAMBASE, lun_num);
- (void) unlink(path);
-
- (void) mgmt_param_remove(tname, lun_num);
-
- /*
- * If the was LUN 0 then do to the previous check
- * we know that no other files exist in the target
- * directory so the target information can be removed
- * along with the directory.
- */
- if (lun_num == 0) {
- (void) snprintf(path, sizeof (path), "%s/%s", target_basedir,
- iname);
- (void) rmdir(path);
-
- /*
- * Don't forget to remove the symlink to
- * the target directory.
- */
- (void) snprintf(path, sizeof (path), "%s/%s", target_basedir,
- tname);
- (void) unlink(path);
-
- /*
- * 'tname' is just a reference to the memory within
- * the targets_config structure. So once the tgt_node_remove()
- * is called 'tname' is no longer valid.
- */
- c = tgt_node_alloc(XML_ELEMENT_TARG, String, tname);
- (void) tgt_node_remove(targets_config, c, MatchBoth);
- tgt_node_free(c);
- }
-
- /*
- * Not much we can do here if we fail to updated the config.
- */
- if (mgmt_config_save2scf() == False)
- syslog(LOG_ERR, "Failed to update target configuration!");
-
-error:
- if (iname != NULL)
- free(iname);
-}
-
-/*
- * []----
- * | validate_xml
- * |
- * | This function checks if there is predefined entities &<>'" in xml request
- * []----
- */
-Boolean_t
-validate_xml(char *req)
-{
- in_mark_t in_mark = in_none;
-
- if (req == NULL)
- return (False);
- for (; *req != '\0'; req++) {
- if (in_mark == in_none) {
- if (*req == '<') {
- in_mark = in_lt;
- continue;
- } else if (*req == '&') {
- in_mark = in_amp;
- continue;
- } else if (strchr("\"\'>", *req) != NULL) {
- return (False);
- }
- } else if (in_mark == in_lt) {
- if (*req == '>') {
- in_mark = in_none;
- continue;
- } else if (*req == '<') {
- return (False);
- }
- } else {
- if (*req == ';') {
- in_mark = in_none;
- continue;
- } else if (*req == '&' || *req == '<') {
- return (False);
- }
- }
- }
-
- if (in_mark == in_none)
- return (True);
- else
- return (False);
-}
-
-/*
- * []----
- * | get_local_name
- * |
- * | This function fetches local name from a iscsi-name
- * | Caller is responsible to free the string.
- * []----
- */
-char *
-get_local_name(char *iname)
-{
- tgt_node_t *targ = NULL;
- char *str;
- char *ret = NULL;
-
- while ((targ = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
- targ)) != NULL) {
- if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &str) == True) {
- if (strcmp(str, iname) == 0)
- ret = strdup(targ->x_value);
- free(str);
- if (ret != NULL)
- break;
- }
- }
- return (ret);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/util_err.c b/usr/src/cmd/iscsi/iscsitgtd/util_err.c
deleted file mode 100644
index 8860436ea9..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/util_err.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <libintl.h>
-#include "errcode.h"
-
-char *
-errcode_to_str(err_code_t err_code)
-{
- switch (err_code) {
- case ERR_SUCCESS:
- return ((char *)gettext("Operation completed successfully"));
- case ERR_NULL_XML_MESSAGE:
- return ((char *)gettext("Null XML message"));
- case ERR_SYNTAX_EMPTY:
- return ((char *)gettext("Syntax error: "
- "Empty XML message or syntax error"));
- case ERR_SYNTAX_MISSING_ALL:
- return ((char *)gettext("Syntax error: Missing --all"));
- case ERR_SYNTAX_MISSING_BACKING_STORE:
- return ((char *)gettext("Syntax error: Missing backing-store"));
- case ERR_SYNTAX_MISSING_INAME:
- return ((char *)gettext("Syntax error: Missing iscsi name"));
- case ERR_SYNTAX_MISSING_IPADDR:
- return ((char *)gettext("Syntax error: Missing IP address"));
- case ERR_SYNTAX_MISSING_NAME:
- return ((char *)gettext("Syntax error: Missing name"));
- case ERR_SYNTAX_MISSING_OBJECT:
- return ((char *)gettext("Syntax error: Missing object"));
- case ERR_SYNTAX_MISSING_OPERAND:
- return ((char *)gettext("Syntax error: Missing operand"));
- case ERR_SYNTAX_MISSING_SIZE:
- return ((char *)gettext("Syntax error: Missing size"));
- case ERR_SYNTAX_MISSING_TYPE:
- return ((char *)gettext("Syntax error: Missing type"));
- case ERR_SYNTAX_EMPTY_ACL:
- return ((char *)gettext("Syntax error: empty ACL"));
- case ERR_SYNTAX_EMPTY_ALIAS:
- return ((char *)gettext("Syntax error: empty alias"));
- case ERR_SYNTAX_EMPTY_CHAPNAME:
- return ((char *)gettext("Empty chap-name"));
- case ERR_SYNTAX_EMPTY_CHAPSECRET:
- return ((char *)gettext("Empty 'chap-secret' element"));
- case ERR_SYNTAX_EMPTY_IPADDR:
- return ((char *)gettext("Syntax error: empty IP address"));
- case ERR_SYNTAX_EMPTY_MAXRECV:
- return ((char *)gettext("Syntax error: empty maxrecv"));
- case ERR_SYNTAX_EMPTY_TPGT:
- return ((char *)gettext("Syntax error: empty TPGT"));
- case ERR_SYNTAX_INVALID_NAME:
- return ((char *)gettext("Syntax error: name may contain only "
- "a..z, A..Z, 0-9, dot(.), dash(-), colon(:) characters"));
- case ERR_INVALID_COMMAND:
- return ((char *)gettext("Invalid command"));
- case ERR_INVALID_OBJECT:
- return ((char *)gettext("Invalid object"));
- case ERR_INVALID_BASEDIR:
- return ((char *)gettext("Invalid base directory"));
- case ERR_INVALID_IP:
- return ((char *)gettext("Invalid IP address"));
- case ERR_INVALID_TPGT:
- return ((char *)gettext("Invalid TPGT"));
- case ERR_INVALID_MAXRECV:
- return ((char *)gettext("Invalid MaxRecvDataSegmentLength"));
- case ERR_INVALID_RADSRV:
- return ((char *)gettext("Invalid RADIUS server name"));
- case ERR_INVALID_SIZE:
- return ((char *)gettext("Invalid size parameter"));
- case ERR_INIT_EXISTS:
- return ((char *)gettext("Initiator already exists"));
- case ERR_LUN_EXISTS:
- return ((char *)gettext("LUN already exists"));
- case ERR_LUN_INVALID_RANGE:
- return ((char *)gettext("LUN must be between 0 and 16383"));
- case ERR_TPGT_EXISTS:
- return ((char *)gettext("TPGT already exists"));
- case ERR_ACL_NOT_FOUND:
- return ((char *)gettext("ACL list not found"));
- case ERR_INIT_NOT_FOUND:
- return ((char *)gettext("Initiator not found"));
- case ERR_TARG_NOT_FOUND:
- return ((char *)gettext("Target not found"));
- case ERR_LUN_NOT_FOUND:
- return ((char *)gettext("LUN not found"));
- case ERR_TPGT_NOT_FOUND:
- return ((char *)gettext("TPGT not found"));
- case ERR_ACCESS_RAW_DEVICE_FAILED:
- return ((char *)gettext("Failed to "
- "access a direct access device"));
- case ERR_CREATE_METADATA_FAILED:
- return ((char *)gettext("Failed to "
- "create meta data for tape device"));
- case ERR_CREATE_SYMLINK_FAILED:
- return ((char *)gettext("Failed to "
- "create a symbolic link to the backing store"));
- case ERR_CREATE_NAME_TOO_LONG:
- return ((char *)gettext("Name must be less than 166 "
- "characters"));
- case ERR_NAME_TOO_LONG:
- return ((char *)gettext("Name too long, must be less than 223 "
- "characters"));
- case ERR_DISK_BACKING_SIZE_OR_FILE:
- return ((char *)gettext("Size must be 0 if backing store "
- "exists"));
- case ERR_DISK_BACKING_MUST_BE_REGULAR_FILE:
- return ((char *)gettext("For type "
- "'disk' backing must be a regular file"));
- case ERR_DISK_BACKING_NOT_VALID_RAW:
- return ((char *)gettext("Backing store is not a valid raw "
- "device"));
- case ERR_STAT_BACKING_FAILED:
- return ((char *)gettext("Failed to "
- "stat(2) backing for 'disk'"));
- case ERR_RAW_PART_NOT_CAP:
- return ((char *)gettext("Partition size does not match capacity"
- " of device. Use p0 or ctd name"));
- case ERR_CREATE_TARGET_DIR_FAILED:
- return ((char *)gettext("Failed to "
- "create target directory"));
- case ERR_ENCODE_GUID_FAILED:
- return ((char *)gettext("Failed to encode GUID value"));
- case ERR_INIT_XML_READER_FAILED:
- return ((char *)gettext("Failed to initialize XML reader"));
- case ERR_INVALID_XML_REQUEST:
- return ((char *)gettext("Invalid characters in XML request"));
- case ERR_OPEN_PARAM_FILE_FAILED:
- return ((char *)gettext("Failed to open parameter file"));
- case ERR_UPDATE_MAINCFG_FAILED:
- return ((char *)gettext("Failed to "
- "update main configuration file"));
- case ERR_UPDATE_TARGCFG_FAILED:
- return ((char *)gettext("Failed to "
- "update target configuration file"));
- case ERR_VALID_TARG_EXIST:
- return ((char *)gettext("Valid targets "
- "exist under current base directory"));
- case ERR_TARGCFG_MISSING_INAME:
- return ((char *)gettext("Missing "
- "iscsi name in target configuration"));
- case ERR_NO_MATCH:
- return ((char *)gettext("No match"));
- case ERR_NO_MEM:
- return ((char *)gettext("Internal error: Out of memory"));
- case ERR_LUN_ZERO_NOT_LAST:
- return ((char *)gettext("LUN 0 must be the last one deleted"));
- case ERR_LUN_ZERO_NOT_FIRST:
- return ((char *)gettext("LUN 0 must exist before creating "
- "other LUNs"));
- case ERR_SIZE_MOD_BLOCK:
- return ((char *)gettext("Size must be multiple of 512"));
- case ERR_CANT_SHRINK_LU:
- return ((char *)gettext("Shrinking of LU is not supported"));
- case ERR_RESIZE_WRONG_TYPE:
- return ((char *)gettext("Backing store must be regular file"));
- case ERR_RESIZE_WRONG_DTYPE:
- return ((char *)gettext("Cannot resize 'raw' targets"));
- case ERR_LUN_NOT_GROWN:
- return ((char *)gettext("Failed to grow LU"));
- case ERR_FILE_TOO_BIG:
- return ((char *)gettext("Requested size is too large for "
- "system"));
- case ERR_FAILED_TO_CREATE_LU:
- return ((char *)gettext("Failed to create backing store"));
- case ERR_INTERNAL_ERROR:
- return ((char *)gettext("Internal error"));
- case ERR_TAPE_NOT_SUPPORTED_IN_32BIT:
- return ((char *)gettext("Tape emulation not supported in "
- "32-bit mode"));
- case ERR_BAD_CREDS:
- return ((char *)gettext("No credentials available from door"));
- case ERR_NO_PERMISSION:
- return ((char *)gettext("Permission denied"));
- case ERR_INVALID_ISNS_SRV:
- return ((char *)gettext("Invalid ISNS Server name"));
- case ERR_ISNS_ERROR:
- return ((char *)gettext("ISNS error"));
- case ERR_TPGT_NO_IPADDR:
- return ((char *)gettext("TPGT has no ip-addr"));
- case ERR_TPGT_IN_USE:
- return ((char *)gettext("Specified TPGT is in-use"));
- case ERR_ZFS_ISCSISHARE_OFF:
- return ((char *)gettext("ZFS shareiscsi property is off"));
- default:
- return ((char *)gettext("Internal error: unknown message"));
- }
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/util_ifname.c b/usr/src/cmd/iscsi/iscsitgtd/util_ifname.c
deleted file mode 100644
index 2ee9e089c7..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/util_ifname.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <sys/types.h>
-#include <libdlpi.h>
-#include <ctype.h>
-#include <sys/sysmacros.h>
-#include <net/if_types.h>
-#include <net/if.h>
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <net/if_dl.h>
-#include <sys/sockio.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#include <strings.h>
-#include <stropts.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <iscsitgt_impl.h>
-#include "target.h"
-#include "queue.h"
-#include "utility.h"
-
-#define LOCAL_LOOPBACK "lo0"
-
-/*
- * This entire file is all about getting these two variables. To create a
- * unique iSCSI IQN string we need information that is unique. What Sun has
- * decided is to use a MAC address along with a timestamp. No other machine
- * at this given time will have the same MAC address and as time moves along
- * well, time will change.
- */
-uchar_t mac_addr[DLPI_PHYSADDR_MAX];
-size_t mac_len;
-
-static struct lifreq *if_setup(int *n);
-static void dump_addr_to_ascii(struct sockaddr *addr, char *buf,
- size_t len);
-static Boolean_t grab_address(char *ifname, uchar_t *addrp, size_t *addrlenp);
-
-/*
- * []----
- * | if_find_mac -- Finds a valid MAC address to use for GUID & IQN creation
- * |
- * | To create both the GUID and the IQN string we need to make them unique
- * | and do so without requiring the user to have to register each target
- * | creation with Sun. Each machine that's using iSCSI will have a network
- * | interface from which we can obtain the MAC address. That guarantees
- * | uniqueness within the network, but doesn't guarantee uniqueness with
- * | the machine. So when creating the GUID/IQN we also use a timestamp.
- * []----
- */
-Boolean_t
-if_find_mac(target_queue_t *mgmt)
-{
- struct lifreq *lifrp, *first;
- int n;
- char *str;
-
- mac_len = DLPI_PHYSADDR_MAX;
-
- first = if_setup(&n);
- for (lifrp = first; n > 0; n--, lifrp++) {
- if (grab_address(lifrp->lifr_name, mac_addr,
- &mac_len) == True) {
- str = _link_ntoa(mac_addr, NULL, mac_len, IFT_OTHER);
- if ((str != NULL) && (mgmt != NULL)) {
- queue_prt(mgmt, Q_GEN_DETAILS,
- "MAIN %s: %s \n", lifrp->lifr_name, str);
- free(str);
- }
- /* ---- grab the first valid MAC address ---- */
- break;
- }
- }
- if (first)
- free(first);
- return (mac_len == 0 ? False : True);
-}
-
-/*
- * []----
- * | if_target_address -- setup IP address for SendTargets
- * |
- * | This routine is called when the iSCSI target is returning SendTargets
- * | data during a discovery phase. The target name is returned along
- * | with all of the IP address that can access that target. There's one
- * | catch, the first address in the list will be the address used by
- * | the initiator if it doesn't support multiple connections per session.
- * | Therefore, whatever connection the initiator used is the first one
- * | that should be in our list. The ramificiations of not doing this are
- * | possible performance issues. Take for example a setup where both the
- * | initiator and target have 10GbE and 1GbE interfaces. The initiator wants
- * | to use the 10GbE interface because of it's speed. If the target returns
- * | a list of addresses with the 1GbE listed first, that's the one which
- * | the initiator would use. Not good.
- * []----
- */
-void
-if_target_address(char **text, int *text_length, struct sockaddr *sp)
-{
- struct lifreq *lp, *first;
- int n, i, s;
- struct sockaddr_in *sin4_cur, *sin4_pos;
- struct sockaddr_in6 *sin6_cur, *sin6_pos;
- char ta[80], ip_buf[INET6_ADDRSTRLEN];
- int fromlen;
-
- if (sp->sa_family == AF_INET) {
- fromlen = sizeof (struct sockaddr_in);
-
- if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
- return;
-
- /*LINTED*/
- sin4_cur = (struct sockaddr_in *)sp;
-
- /*
- * Ugh. Would you believe that even though this array
- * is defined as zero, we get back non-zero data from
- * getsockname().
- */
- bzero(&sin4_cur->sin_zero[0], sizeof (sin4_cur->sin_zero));
-
- } else if (sp->sa_family == AF_INET6) {
- fromlen = sizeof (struct sockaddr_in6);
-
- if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) == -1)
- return;
-
- /*LINTED*/
- sin6_cur = (struct sockaddr_in6 *)sp;
- } else
- return;
-
- first = if_setup(&n);
- for (lp = first, i = 0; i < n; i++, lp++) {
-
- if (sp->sa_family != lp->lifr_addr.ss_family)
- continue;
-
- /*
- * Change the possible incoming addresses port number,
- * which would be zero, to that of the current incoming
- * port number. Otherwise the comparison will not match.
- */
- if (sp->sa_family == AF_INET) {
- sin4_pos = (struct sockaddr_in *)&lp->lifr_addr;
- sin4_pos->sin_port = sin4_cur->sin_port;
- } else if (sp->sa_family == AF_INET6) {
- sin6_pos = (struct sockaddr_in6 *)&lp->lifr_addr;
- sin6_pos->sin6_port = sin6_cur->sin6_port;
- } else
- goto clean_up;
- }
-
- for (lp = first, i = 0; i < n; i++, lp++) {
-
- if (bcmp(sp, &lp->lifr_addr, fromlen) == 0) {
- dump_addr_to_ascii((struct sockaddr *)&lp->lifr_addr,
- ip_buf, sizeof (ip_buf));
-
- if (sp->sa_family == AF_INET) {
- (void) snprintf(ta, sizeof (ta), "%s,1",
- ip_buf);
- } else if (sp->sa_family == AF_INET6) {
- (void) snprintf(ta, sizeof (ta), "[%s],1",
- ip_buf);
- } else
- goto clean_up;
-
- (void) add_text(text, text_length, "TargetAddress", ta);
-
- /*
- * There is possiblity that both IPv4 & IPv6 enabled on
- * certain interface, then we will see that interface
- * twice identically in the list.
- * Of course we need only one of them, not both.
- */
- break;
- }
- }
-
- for (lp = first, i = 0; i < n; i++, lp++) {
- /*
- * We allow for the loopback address to match the discovery
- * address above since it's entirely possible to create
- * a target on the same machine that you're running the
- * initiator. Now, when we provide the list of other
- * possible interfaces to use we don't want to include
- * the loopback because that's obviously not a valid I/F
- * for a remote node.
- */
- if (strcmp(lp->lifr_name, LOCAL_LOOPBACK) == 0)
- continue;
-
- if (bcmp(sp, &lp->lifr_addr, fromlen) != 0) {
- struct sockaddr *sp2;
- sp2 = (struct sockaddr *)&lp->lifr_addr;
- dump_addr_to_ascii(sp2, ip_buf, sizeof (ip_buf));
-
- if (sp2->sa_family == AF_INET) {
- (void) snprintf(ta, sizeof (ta), "%s,1",
- ip_buf);
- } else if (sp2->sa_family == AF_INET6) {
- (void) snprintf(ta, sizeof (ta), "[%s],1",
- ip_buf);
- } else
- goto clean_up;
- (void) add_text(text, text_length, "TargetAddress", ta);
- }
- }
-
-clean_up:
- (void) close(s);
- if (first)
- free(first);
-}
-
-/*
- * []----
- * | dump_addr_to_ascii -- Use appropriate translation routine
- * []----
- */
-static void
-dump_addr_to_ascii(struct sockaddr *addr, char *buf, size_t len)
-{
- struct sockaddr_in *sin4;
- struct sockaddr_in6 *sin6;
-
- if (addr->sa_family == AF_INET) {
- /*LINTED*/
- sin4 = (struct sockaddr_in *)addr;
- (void) inet_ntop(AF_INET, &sin4->sin_addr, buf, len);
- } else if (addr->sa_family == AF_INET6) {
- /*LINTED*/
- sin6 = (struct sockaddr_in6 *)addr;
- (void) inet_ntop(AF_INET6, &sin6->sin6_addr, buf, len);
- }
-}
-
-/*
- * []----
- * | if_setup -- Load up the interface names
- * |
- * | If this routine returns NULL, argument 'n' is also guaranteed to
- * | be set to 0.
- * []----
- */
-static struct lifreq *
-if_setup(int *n)
-{
- struct lifnum lifn;
- struct lifconf lifc;
- int numifs;
- unsigned bufsize;
- char *buf;
- int s;
-
- *n = 0;
- if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) == -1) {
- /*
- * If we failed to open an IPv6 socket
- * try IPv4 socket instead
- */
- if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
- return (NULL);
- }
-
- lifn.lifn_family = AF_UNSPEC;
- lifn.lifn_flags = LIFC_ALLZONES | LIFC_EXTERNAL_SOURCE;
- if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) < 0)
- return (NULL);
-
- numifs = lifn.lifn_count;
-
- bufsize = numifs * sizeof (struct lifreq);
- if ((buf = malloc(bufsize)) == NULL) {
- /*
- * This call is made so early on that if we're out of memory
- * here, just say goodbye.
- */
- return (NULL);
- }
-
- lifc.lifc_family = AF_UNSPEC;
- lifc.lifc_flags = LIFC_ALLZONES | LIFC_EXTERNAL_SOURCE;
- lifc.lifc_len = bufsize;
- lifc.lifc_buf = buf;
-
- if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0) {
- free(buf);
- return (NULL);
- }
-
- (void) close(s);
- *n = lifc.lifc_len / sizeof (struct lifreq);
- return (lifc.lifc_req);
-}
-
-static Boolean_t
-grab_address(char *ifname, uchar_t *addrp, size_t *addrlenp)
-{
- int retval;
- dlpi_handle_t dh;
-
- if (dlpi_open(ifname, &dh, 0) != DLPI_SUCCESS)
- return (False);
-
- retval = dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR, addrp, addrlenp);
-
- dlpi_close(dh);
-
- return (retval == DLPI_SUCCESS);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/util_port.c b/usr/src/cmd/iscsi/iscsitgtd/util_port.c
deleted file mode 100644
index 357e07156d..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/util_port.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <string.h>
-#include <strings.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <assert.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include "queue.h"
-#include "port.h"
-#include "iscsi_conn.h"
-#include "utility.h"
-
-pthread_mutex_t port_mutex;
-int port_conn_num;
-iscsi_conn_t *conn_head = NULL;
-iscsi_conn_t *conn_tail = NULL;
-
-void
-port_init(void)
-{
- (void) pthread_mutex_init(&port_mutex, NULL);
- port_conn_num = 0;
-}
-
-void
-canonicalize_sockaddr(struct sockaddr_storage *st)
-{
- struct in6_addr *addr6 = &((struct sockaddr_in6 *)st)->sin6_addr;
-
- /*
- * If target address is IPv4 mapped IPv6 address convert it to IPv4
- * address.
- */
- if (st->ss_family == AF_INET6 &&
- (IN6_IS_ADDR_V4MAPPED(addr6) || IN6_IS_ADDR_V4COMPAT(addr6))) {
- struct in_addr *addr = &((struct sockaddr_in *)st)->sin_addr;
- IN6_V4MAPPED_TO_INADDR(addr6, addr);
- st->ss_family = AF_INET;
- }
-}
-
-
-void *
-port_watcher(void *v)
-{
- int s;
- int fd;
- int on = 1;
- char debug[80];
- struct sockaddr_in sin_ip;
- struct sockaddr_in6 sin6_ip;
- struct sockaddr_storage st;
- socklen_t socklen;
- iscsi_conn_t *conn;
- port_args_t *p = (port_args_t *)v;
- target_queue_t *q = p->port_mgmtq;
- int l;
- const int just_say_no = 1;
- pthread_t junk;
-
- /*
- * Try creating an IPv6 socket first
- * If failed, try creating an IPv4 socket
- */
- if ((s = socket(PF_INET6, SOCK_STREAM, 0)) == -1) {
-
- queue_str(q, Q_GEN_ERRS, msg_log, "Opening IPv4 socket");
- if ((s = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
- queue_str(q, Q_GEN_ERRS, msg_log,
- "Can't open socket");
- return (NULL);
- } else {
- bzero(&sin_ip, sizeof (sin_ip));
- sin_ip.sin_family = AF_INET;
- sin_ip.sin_port = htons(p->port_num);
- sin_ip.sin_addr.s_addr = INADDR_ANY;
-
- (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
- (char *)&on, sizeof (on));
-
- if ((bind(s, (struct sockaddr *)&sin_ip,
- sizeof (sin_ip))) < 0) {
- (void) snprintf(debug, sizeof (debug),
- "bind on port %d failed, errno %d",
- p->port_num, errno);
- queue_str(q, Q_GEN_ERRS, msg_status, debug);
- return (NULL);
- }
- }
-
- } else {
-
- queue_str(q, Q_GEN_DETAILS, msg_log, "Got IPv6 socket");
- bzero(&sin6_ip, sizeof (sin6_ip));
- sin6_ip.sin6_family = AF_INET6;
- sin6_ip.sin6_port = htons(p->port_num);
- sin6_ip.sin6_addr = in6addr_any;
-
- (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
- sizeof (on));
-
- if ((bind(s, (struct sockaddr *)&sin6_ip, sizeof (sin6_ip)))
- < 0) {
- (void) snprintf(debug, sizeof (debug),
- "bind on port %d failed, errno %d",
- p->port_num, errno);
- queue_str(q, Q_GEN_ERRS, msg_status, debug);
- return (NULL);
- }
- }
-
- if (listen(s, 128) < 0) {
- queue_str(q, Q_GEN_ERRS, msg_status, "listen failed");
- return (NULL);
- }
-
- /*CONSTANTCONDITION*/
- while (1) {
-
- socklen = sizeof (st);
- if ((fd = accept(s, (struct sockaddr *)&st,
- &socklen)) < 0) {
- if (errno != EINTR)
- queue_prt(q, Q_GEN_ERRS,
- "accept failed, %s", strerror(errno));
- (void) sleep(1);
- continue;
- }
-
- l = 128 * 1024;
- if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&l,
- sizeof (l)) < 0)
- queue_str(q, Q_GEN_ERRS, msg_status,
- "setsockopt failed");
- if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&l,
- sizeof (l)) < 0)
- queue_str(q, Q_GEN_ERRS, msg_status,
- "setsockopt failed");
- l = 1;
- if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&l,
- sizeof (l)) < 0)
- queue_str(q, Q_GEN_ERRS, msg_status,
- "setsockopt keepalive failed");
-
- if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
- (char *)&just_say_no, sizeof (just_say_no)) != 0)
- queue_str(q, Q_GEN_ERRS, msg_status,
- "setsockopt NODELAY failed");
-
- if ((conn = calloc(1, sizeof (iscsi_conn_t))) == NULL) {
- /*
- * If we fail to get memory this is all rather
- * pointless, since it's unlikely that queue_str
- * could malloc memory to send a message.
- */
- queue_str(q, Q_GEN_ERRS, msg_status,
- "connection malloc failed");
- return (NULL);
- }
-
- /*
- * Save initiator address for future use.
- */
- canonicalize_sockaddr(&st);
- conn->c_initiator_sockaddr = st;
-
- /*
- * Save target address for future use.
- */
- socklen = sizeof (st);
- if (getsockname(fd, (struct sockaddr *)&st, &socklen) == 0)
- canonicalize_sockaddr(&st);
- else
- st.ss_family = AF_UNSPEC;
- conn->c_target_sockaddr = st;
-
- conn->c_fd = fd;
- conn->c_mgmtq = q;
- conn->c_up_at = time(NULL);
- conn->c_state = S1_FREE;
- (void) pthread_mutex_init(&conn->c_mutex, NULL);
- (void) pthread_mutex_init(&conn->c_state_mutex, NULL);
- (void) pthread_mutex_lock(&port_mutex);
- conn->c_num = port_conn_num++;
- if (conn_head == NULL) {
- conn_head = conn;
- assert(conn_tail == NULL);
- conn_tail = conn;
- } else {
- conn_tail->c_next = conn;
- conn->c_prev = conn_tail;
- conn_tail = conn;
- }
- (void) pthread_mutex_unlock(&port_mutex);
-
- (void) pthread_create(&junk, NULL, conn_process, conn);
- }
- return (NULL);
-}
-
-void
-port_conn_remove(iscsi_conn_t *c)
-{
- iscsi_conn_t *n;
-
- (void) pthread_mutex_lock(&port_mutex);
- if (conn_head == c) {
- conn_head = c->c_next;
- if (conn_head == NULL)
- conn_tail = NULL;
- else
- conn_head->c_prev = NULL;
- } else {
- n = c->c_prev;
- n->c_next = c->c_next;
- if (c->c_next != NULL)
- c->c_next->c_prev = n;
- else {
- assert(conn_tail == c);
- conn_tail = n;
- }
- }
-
- /*
- * The connection queue is freed here so that it's protected by
- * locks. The main thread of the deamon when processing incoming
- * management requests will send them on the connection queues.
- * The main thread will grab the port_mutex so that we know the
- * queue is still valid.
- */
- queue_free(c->c_dataq, conn_queue_data_remove);
- (void) pthread_mutex_unlock(&port_mutex);
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/util_queue.c b/usr/src/cmd/iscsi/iscsitgtd/util_queue.c
deleted file mode 100644
index a5258936ee..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/util_queue.c
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <unistd.h>
-#include <assert.h>
-#include <syslog.h>
-#include <synch.h>
-#include <time.h>
-#include <umem.h>
-
-#include "queue.h"
-#include "iscsi_conn.h"
-#include "utility.h"
-#include "target.h"
-#include "t10.h"
-
-/*
- * Constants
- */
-static const timespec_t usec = {0, 1000};
-
-FILE *qlog = NULL;
-int qlog_lvl = 0;
-
-pthread_mutex_t q_mutex;
-int queue_num;
-
-void
-queue_init()
-{
- (void) pthread_mutex_init(&q_mutex, NULL);
- queue_log(True);
-}
-
-target_queue_t *
-queue_alloc()
-{
- target_queue_t *q =
- (target_queue_t *)calloc(1, sizeof (target_queue_t));
-
- if (q == NULL)
- return (NULL);
-
- (void) pthread_mutex_lock(&q_mutex);
- q->q_num = queue_num++;
- (void) pthread_mutex_unlock(&q_mutex);
-
- (void) sema_init(&q->q_sema, 0, USYNC_THREAD, NULL);
- (void) pthread_mutex_init(&q->q_mutex, NULL);
-
- return (q);
-}
-
-void
-queue_log(Boolean_t on)
-{
- (void) pthread_mutex_lock(&q_mutex);
- if ((on == True) && (qlog == NULL) && (qlog_lvl != 0)) {
- qlog = fopen(target_log, "ab");
- } else if ((on == False) && (qlog != NULL)) {
- (void) fclose(qlog);
- qlog = NULL;
- }
- (void) pthread_mutex_unlock(&q_mutex);
-}
-
-/*
- * []----
- * | queue_message_set -- add a given message to the queue.
- * []----
- */
-void
-queue_message_set(target_queue_t *q, uint32_t lvl, msg_type_t type,
- void *data)
-{
- msg_t *msg;
-
- if ((msg = umem_cache_alloc(queue_cache, 0)) == NULL)
- return;
-
- bzero(msg, sizeof (*msg));
- msg->msg_pri_level = lvl;
- msg->msg_type = type;
- msg->msg_data = data;
-
- (void) pthread_mutex_lock(&q->q_mutex);
-
- if (q->q_head == NULL) {
- q->q_head = msg;
- assert(q->q_tail == NULL);
- q->q_tail = msg;
- } else if (lvl & Q_HIGH) {
- msg->msg_next = q->q_head;
- q->q_head->msg_prev = msg;
- q->q_head = msg;
- } else {
- q->q_tail->msg_next = msg;
- msg->msg_prev = q->q_tail;
- q->q_tail = msg;
- }
-
- (void) pthread_mutex_unlock(&q->q_mutex);
-
- (void) sema_post(&q->q_sema);
-}
-
-/*
- * []----
- * | queue_message_get -- retrieve the first message in the queue
- * []----
- */
-msg_t *
-queue_message_get(target_queue_t *q)
-{
- msg_t *m;
-
- while (sema_wait(&q->q_sema) == -1)
- (void) nanosleep(&usec, 0);
- (void) pthread_mutex_lock(&q->q_mutex);
- m = q->q_head;
- if (m == NULL) {
- assert(q->q_tail == NULL);
- (void) pthread_mutex_unlock(&q->q_mutex);
- return (NULL);
- }
- q->q_head = m->msg_next;
- if (q->q_head == NULL)
- q->q_tail = NULL;
- (void) pthread_mutex_unlock(&q->q_mutex);
-
- return (m);
-}
-
-/*
- * []----
- * | queue_message_try_get -- see if there's a message available
- * []----
- */
-msg_t *
-queue_message_try_get(target_queue_t *q)
-{
- msg_t *m;
-
- if (sema_trywait(&q->q_sema) != 0)
- return (NULL);
- (void) pthread_mutex_lock(&q->q_mutex);
- m = q->q_head;
- q->q_head = m->msg_next;
- if (q->q_head == NULL)
- q->q_tail = NULL;
- (void) pthread_mutex_unlock(&q->q_mutex);
-
- return (m);
-}
-
-/*
- * []----
- * | queue_walker_free -- Run through a queue and free certain messages.
- * |
- * | Users of the queues should not walk the queue structure themselves
- * | unless they also need to grab the lock. To prevent that level of
- * | knowledge of the queue structures this method is provided to enable
- * | other subsystems to walk the queue looking for messages which need
- * | to be deleted.
- * []----
- */
-void
-queue_walker_free(target_queue_t *q, Boolean_t (*func)(msg_t *m, void *v),
- void *v1)
-{
- msg_t *m; /* current working message */
- msg_t *n; /* next message */
-
- (void) pthread_mutex_lock(&q->q_mutex);
- m = q->q_head;
- while (m) {
- if ((*func)(m, v1) == True) {
- if (m == q->q_head) {
- q->q_head = m->msg_next;
- if (m->msg_next == NULL)
- q->q_tail = NULL;
- else
- m->msg_next->msg_prev = NULL;
- } else {
- m->msg_prev->msg_next = m->msg_next;
- if (m->msg_next == NULL)
- q->q_tail = m->msg_prev;
- else
- m->msg_next->msg_prev = m->msg_prev;
- }
- n = m->msg_next;
- queue_message_free(m);
- m = n;
- } else {
- m = m->msg_next;
- }
- }
- (void) pthread_mutex_unlock(&q->q_mutex);
-}
-
-/*
- * []----
- * | queue_reset -- Flush a queue of all command messages messages.
- * []----
- */
-void
-queue_reset(target_queue_t *q)
-{
- msg_t *m;
- msg_t *n;
-
- (void) pthread_mutex_lock(&q->q_mutex);
- m = q->q_head;
- while (m != NULL) {
-
- switch (m->msg_type) {
- case msg_cmd_data_out:
- case msg_cmd_send:
- if (m == q->q_head) {
- q->q_head = m->msg_next;
- if (m->msg_next == NULL)
- q->q_tail = NULL;
- else
- m->msg_next->msg_prev = NULL;
- } else {
- assert(m->msg_prev != NULL);
- m->msg_prev->msg_next = m->msg_next;
- if (m->msg_next == NULL)
- q->q_tail = m->msg_prev;
- else
- m->msg_next->msg_prev = m->msg_prev;
- }
- n = m->msg_next;
- queue_message_free(m);
- m = n;
- (void) sema_wait(&q->q_sema);
- break;
-
- case msg_reset_lu:
- case msg_shutdown:
- case msg_lu_add:
- case msg_lu_remove:
- case msg_lu_online:
- case msg_thick_provo:
- /*
- * Don't flush the control messages
- */
- m = m->msg_next;
- break;
-
- default:
- queue_prt(mgmtq, Q_STE_ERRS,
- "---- Unexpected msg type %d ----", m->msg_type);
- m = m->msg_next;
- break;
- }
- }
-
- (void) pthread_mutex_unlock(&q->q_mutex);
-}
-
-void
-queue_message_free(msg_t *m)
-{
- umem_cache_free(queue_cache, m);
-}
-
-/*
- * []----
- * | queue_free -- free resources used by queue structure
- * []----
- */
-void
-queue_free(target_queue_t *q, void (*free_func)(msg_t *))
-{
- msg_t *m;
- msg_t *n;
-
- (void) pthread_mutex_lock(&q->q_mutex);
- m = q->q_head;
- while (m != NULL) {
- if (free_func != NULL)
- (*free_func)(m);
- n = m->msg_next;
- queue_message_free(m);
- m = n;
- }
- (void) pthread_mutex_unlock(&q->q_mutex);
-
- (void) pthread_mutex_destroy(&q->q_mutex);
- (void) sema_destroy(&q->q_sema);
- free(q);
-}
-
-void
-queue_prt(target_queue_t *q, int type, char *fmt, ...)
-{
- va_list ap;
- char buf[80];
-
- va_start(ap, fmt);
- /* LINTED variable format specifier */
- (void) vsnprintf(buf, sizeof (buf), fmt, ap);
- queue_str(q, type, msg_log, buf);
- va_end(ap);
-}
-
-/*
- * []----
- * | queue_str -- helper function which sends a string to the queue
- * []----
- */
-void
-queue_str(target_queue_t *q, uint32_t lvl, msg_type_t type, char *fmt)
-{
- int len;
- char *m;
- hrtime_t h = gethrtime();
- hrtime_t delta;
- static hrtime_t last_h = 0;
- time_t tval = time((time_t *)0);
- char debug[80];
-
- (void) pthread_mutex_lock(&q_mutex);
- if ((qlog) && (qlog_lvl & lvl)) {
- (void) ctime_r(&tval, debug, sizeof (debug));
- (void) fprintf(qlog, "%s %s", debug, fmt);
- (void) fflush(qlog);
- }
- (void) pthread_mutex_unlock(&q_mutex);
-
- if ((dbg_timestamps == True) && (lvl != 0) && ((lvl & Q_HIGH) == 0)) {
- len = strlen(fmt) + 12;
- m = malloc(len);
- delta = h - last_h;
- last_h = h;
- (void) snprintf(m, len, "%9.3f %s",
- (double)delta / (double)1000000.0, fmt);
- queue_message_set(q, lvl, type, (void *)m);
- } else {
- len = strlen(fmt) + 1;
- m = malloc(len);
- (void) strncpy(m, fmt, len);
- queue_message_set(q, lvl, type, (void *)m);
- }
-}
-
-/*
- * []------------------------------------------------------------------[]
- * | Specialized free routines for queue data. |
- * | It is possible for a shutdown to start because the STE thread |
- * | receives an error while reading from the socket. If at the same |
- * | time the connection poll thread is processing a PDU it could place |
- * | a msg_ste_datain package on the STE queue. When the STE hits the |
- * | shutdown message first it will exit and we need to clean up |
- * | anything on that queue which means freeing memory in the |
- * | appropriate manner. This is just one example and there are several |
- * | others. Another method to deal with this would be to have a closed |
- * | flag such that any futher calls to queue_message_set would return |
- * | an error. This would require any calls to queue_message_set() deal |
- * | with this condition. The approach used here seems cleaner. |
- * | The drawback to this approach is that if any new messages are |
- * | added then the developer had better add it to these routines as |
- * | appropriate. |
- * []------------------------------------------------------------------[]
- */
-
-/*
- * []----
- * | sess_queue_data_remove -- free any message data left on the sess queue
- * |
- * | XXX This should be recoded so that we're doing the cleanup within
- * | the session code. Peal off any messages and deal with them there.
- * []----
- */
-void
-sess_queue_data_remove(msg_t *m)
-{
- mgmt_request_t *mq;
- char **buf;
-
- syslog(LOG_ERR, "sess_queue_data: type %d", m->msg_type);
- switch (m->msg_type) {
- default:
- syslog(LOG_ERR, "Unknown session type data being free'd, %d",
- m->msg_type);
- free(m->msg_data);
- break;
-
- case msg_shutdown:
- case msg_shutdown_rsp:
- case msg_ste_media_error:
- syslog(LOG_ERR, "Impossible message left in session queue"
- " of type %d", m->msg_type);
- break;
-
- case msg_cmd_data_out:
- break;
-
- case msg_initiator_name:
- case msg_initiator_alias:
- case msg_target_name:
- free(((name_request_t *)m->msg_data)->nr_name);
- break;
-
- case msg_mgmt_rqst:
- mq = (mgmt_request_t *)m->msg_data;
- (void) pthread_mutex_lock(&mq->m_resp_mutex);
- tgt_buf_add(mq->m_u.m_resp, "queue_freed", NULL);
- (void) pthread_mutex_unlock(&mq->m_resp_mutex);
- queue_message_set(mq->m_q, 0, msg_mgmt_rply, 0);
- break;
-
- case msg_mgmt_rply:
- mq = (mgmt_request_t *)m->msg_data;
- buf = mq->m_u.m_resp;
- tgt_buf_add_tag(buf, XML_ELEMENT_STATS, Tag_End);
- tgt_buf_add_tag(buf, XML_ELEMENT_CONN, Tag_End);
-
- (void) pthread_mutex_unlock(&mq->m_resp_mutex);
- queue_message_set(mq->m_q, 0, msg_mgmt_rply, 0);
- break;
-
- case msg_reset_targ:
- case msg_reset_lu:
- /* ---- these are safe to ignore, no data to free ---- */
- break;
- }
-}
-
-/*
- * []----
- * | conn_queue_data_remove -- free any message data left on the conn queue
- * []----
- */
-void
-conn_queue_data_remove(msg_t *m)
-{
- mgmt_request_t *mq;
-
- syslog(LOG_ERR, "conn_queue_data: type %d", m->msg_type);
- switch (m->msg_type) {
- case msg_cmd_data_rqst:
- case msg_cmd_data_out:
- case msg_cmd_cmplt:
- syslog(LOG_ERR, "Free'ing data which should already be gone");
- free(m->msg_data);
- break;
-
- case msg_mgmt_rqst:
- mq = (mgmt_request_t *)m->msg_data;
- (void) pthread_mutex_lock(&mq->m_resp_mutex);
- if (mq->m_u.m_resp != NULL)
- tgt_buf_add(mq->m_u.m_resp, "queue_freed", NULL);
- (void) pthread_mutex_unlock(&mq->m_resp_mutex);
- queue_message_set(mq->m_q, 0, msg_mgmt_rply, 0);
- break;
-
- default:
- syslog(LOG_ERR, "Unknown connection message being free'd: %d",
- m->msg_type);
- free(m->msg_data);
- break;
- }
-}
diff --git a/usr/src/cmd/iscsi/iscsitgtd/utility.h b/usr/src/cmd/iscsi/iscsitgtd/utility.h
deleted file mode 100644
index f4e32d3222..0000000000
--- a/usr/src/cmd/iscsi/iscsitgtd/utility.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _TARGET_UTILITY_H
-#define _TARGET_UTILITY_H
-
-/*
- * Block comment which describes the contents of this file.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "iscsi_conn.h"
-#include <sys/iscsi_protocol.h>
-#include "errcode.h"
-
-#define SNA32_CHECK 2147483648UL
-
-/*
- * Generates a lot more information on each transfer. Disabling this reduces
- * one possible performance impact in the data path. Event with logging turned
- * off the messages are still queued which requires malloc's and possible lock
- * contention on the management queue. This is a gut feeling, rather than
- * actual tests to confirm.
- */
-#undef FULL_DEBUG
-
-typedef struct thick_provo {
- struct thick_provo *next,
- *prev;
- char *targ_name;
- int lun;
- target_queue_t *q;
-} thick_provo_t;
-
-/*
- * in_mark presents the state in validate_xml()
- * in_lt means it enters a '<' and wants a '>' to return normal
- * in_amp means it meets a '&' and wants a ';' to return normal
- */
-typedef enum {
- in_none,
- in_lt,
- in_amp
-} in_mark_t;
-
-void util_init();
-int read_retry(int fd, char *buf, int count);
-Boolean_t parse_text(iscsi_conn_t *c, int dlen, char **text,
- int *text_length, int *errcode);
-Boolean_t add_text(char **text, int *current_length, char *name, char *val);
-char *task_to_str(int func);
-void create_geom(diskaddr_t size, int *cylinders, int *heads, int *spt);
-void connection_parameters_default(iscsi_conn_t *c);
-int sna_lt(uint32_t n1, uint32_t n2);
-int sna_lte(uint32_t n1, uint32_t n2);
-void xml_rtn_msg(char **buf, err_code_t code);
-Boolean_t add_target_alias(iscsi_conn_t *c, char **text, int *test_length);
-Boolean_t validate_version(tgt_node_t *node, int *maj, int *min);
-char *create_tpgt_list(char *tname);
-Boolean_t check_access(tgt_node_t *targ, char *initiator_name,
- Boolean_t req_chap);
-tgt_node_t *find_target_node(char *targ_name);
-void util_title(target_queue_t *q, int type, int num, char *title);
-Boolean_t util_create_guid(char **guid, uchar_t id_type);
-Boolean_t strtoll_multiplier(char *str, uint64_t *sp);
-void thick_provo_stop(char *targ, int lun);
-void *thick_provo_start(void *v);
-Boolean_t thick_provo_chk_thr(char *targ, int lun);
-void remove_target_common(char *name, int lun, char **msg);
-char *get_local_name(char *iname);
-Boolean_t validate_xml(char *req);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _TARGET_UTILITY_H */
diff --git a/usr/src/cmd/svc/shell/mfsthistory b/usr/src/cmd/svc/shell/mfsthistory
index ec86bd83f3..7a719d1c49 100644
--- a/usr/src/cmd/svc/shell/mfsthistory
+++ b/usr/src/cmd/svc/shell/mfsthistory
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# This file is for historical purposes only, and should not be modified.
@@ -371,8 +371,6 @@ svc:/system/nws_ii:default var/svc/manifest/system/nws_ii.xml
svc:/system/nws_ii var/svc/manifest/system/nws_ii.xml
svc:/network/ipmievd:default var/svc/manifest/network/ipmievd.xml
svc:/network/ipmievd var/svc/manifest/network/ipmievd.xml
-svc:/system/iscsitgt:default var/svc/manifest/system/iscsi_target.xml
-svc:/system/iscsitgt var/svc/manifest/system/iscsi_target.xml
svc:/network/isns_server:default var/svc/manifest/network/isns_server.xml
svc:/network/isns_server var/svc/manifest/network/isns_server.xml
svc:/application/wnn8/server:default var/svc/manifest/application/wnn8/wnn8-server.xml
diff --git a/usr/src/cmd/truss/codes.c b/usr/src/cmd/truss/codes.c
index 09ea03b92f..0bec448ea6 100644
--- a/usr/src/cmd/truss/codes.c
+++ b/usr/src/cmd/truss/codes.c
@@ -1216,8 +1216,6 @@ const struct ioc {
"zfs_cmd_t" },
{ (uint_t)ZFS_IOC_GET_FSACL, "ZFS_IOC_GET_FSACL",
"zfs_cmd_t" },
- { (uint_t)ZFS_IOC_ISCSI_PERM_CHECK, "ZFS_IOC_ISCSI_PERM_CHECK",
- "zfs_cmd_t" },
{ (uint_t)ZFS_IOC_SHARE, "ZFS_IOC_SHARE",
"zfs_cmd_t" },
{ (uint_t)ZFS_IOC_INHERIT_PROP, "ZFS_IOC_INHERIT_PROP",
diff --git a/usr/src/cmd/zfs/zfs_main.c b/usr/src/cmd/zfs/zfs_main.c
index ce65fd57a8..d08f792080 100644
--- a/usr/src/cmd/zfs/zfs_main.c
+++ b/usr/src/cmd/zfs/zfs_main.c
@@ -3189,42 +3189,9 @@ share_mount_one(zfs_handle_t *zhp, int op, int flags, char *protocol,
return (1);
break;
}
- } else {
+ } else
assert(op == OP_SHARE);
- /*
- * Ignore any volumes that aren't shared.
- */
- verify(zfs_prop_get(zhp, ZFS_PROP_SHAREISCSI, shareopts,
- sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0);
-
- if (strcmp(shareopts, "off") == 0) {
- if (!explicit)
- return (0);
-
- (void) fprintf(stderr, gettext("cannot share '%s': "
- "'shareiscsi' property not set\n"),
- zfs_get_name(zhp));
- (void) fprintf(stderr, gettext("set 'shareiscsi' "
- "property or use iscsitadm(1M) to share this "
- "volume\n"));
- return (1);
- }
-
- if (zfs_is_shared_iscsi(zhp)) {
- if (!explicit)
- return (0);
-
- (void) fprintf(stderr, gettext("cannot share "
- "'%s': volume already shared\n"),
- zfs_get_name(zhp));
- return (1);
- }
-
- if (zfs_share_iscsi(zhp) != 0)
- return (1);
- }
-
return (0);
}
@@ -3345,11 +3312,9 @@ share_mount(int op, int argc, char **argv)
if (strcmp(argv[0], "nfs") == 0 ||
strcmp(argv[0], "smb") == 0) {
types = ZFS_TYPE_FILESYSTEM;
- } else if (strcmp(argv[0], "iscsi") == 0) {
- types = ZFS_TYPE_VOLUME;
} else {
(void) fprintf(stderr, gettext("share type "
- "must be 'nfs', 'smb' or 'iscsi'\n"));
+ "must be 'nfs' or 'smb'\n"));
usage(B_FALSE);
}
protocol = argv[0];
@@ -3432,7 +3397,7 @@ share_mount(int op, int argc, char **argv)
}
/*
- * zfs mount -a [nfs | iscsi]
+ * zfs mount -a [nfs]
* zfs mount filesystem
*
* Mount all filesystems, or mount the given filesystem.
@@ -3444,7 +3409,7 @@ zfs_do_mount(int argc, char **argv)
}
/*
- * zfs share -a [nfs | iscsi | smb]
+ * zfs share -a [nfs | smb]
* zfs share filesystem
*
* Share all filesystems, or share the given filesystem.
@@ -3600,7 +3565,7 @@ unshare_unmount(int op, int argc, char **argv)
int ret = 0;
int types, c;
zfs_handle_t *zhp;
- char nfsiscsi_mnt_prop[ZFS_MAXPROPLEN];
+ char nfs_mnt_prop[ZFS_MAXPROPLEN];
char sharesmb[ZFS_MAXPROPLEN];
/* check options */
@@ -3685,25 +3650,25 @@ unshare_unmount(int op, int argc, char **argv)
switch (op) {
case OP_SHARE:
verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS,
- nfsiscsi_mnt_prop,
- sizeof (nfsiscsi_mnt_prop),
+ nfs_mnt_prop,
+ sizeof (nfs_mnt_prop),
NULL, NULL, 0, B_FALSE) == 0);
- if (strcmp(nfsiscsi_mnt_prop, "off") != 0)
+ if (strcmp(nfs_mnt_prop, "off") != 0)
break;
verify(zfs_prop_get(zhp, ZFS_PROP_SHARESMB,
- nfsiscsi_mnt_prop,
- sizeof (nfsiscsi_mnt_prop),
+ nfs_mnt_prop,
+ sizeof (nfs_mnt_prop),
NULL, NULL, 0, B_FALSE) == 0);
- if (strcmp(nfsiscsi_mnt_prop, "off") == 0)
+ if (strcmp(nfs_mnt_prop, "off") == 0)
continue;
break;
case OP_MOUNT:
/* Ignore legacy mounts */
verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT,
- nfsiscsi_mnt_prop,
- sizeof (nfsiscsi_mnt_prop),
+ nfs_mnt_prop,
+ sizeof (nfs_mnt_prop),
NULL, NULL, 0, B_FALSE) == 0);
- if (strcmp(nfsiscsi_mnt_prop, "legacy") == 0)
+ if (strcmp(nfs_mnt_prop, "legacy") == 0)
continue;
/* Ignore canmount=noauto mounts */
if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) ==
@@ -3771,29 +3736,6 @@ unshare_unmount(int op, int argc, char **argv)
uu_avl_destroy(tree);
uu_avl_pool_destroy(pool);
- if (op == OP_SHARE) {
- /*
- * Finally, unshare any volumes shared via iSCSI.
- */
- zfs_handle_t **dslist = NULL;
- size_t i, count = 0;
-
- get_all_datasets(ZFS_TYPE_VOLUME, &dslist, &count,
- B_FALSE);
-
- if (count != 0) {
- qsort(dslist, count, sizeof (void *),
- dataset_cmp);
-
- for (i = 0; i < count; i++) {
- if (zfs_unshare_iscsi(dslist[i]) != 0)
- ret = 1;
- zfs_close(dslist[i]);
- }
-
- free(dslist);
- }
- }
} else {
if (argc != 1) {
if (argc == 0)
@@ -3825,20 +3767,20 @@ unshare_unmount(int op, int argc, char **argv)
if (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
verify(zfs_prop_get(zhp, op == OP_SHARE ?
ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT,
- nfsiscsi_mnt_prop, sizeof (nfsiscsi_mnt_prop), NULL,
+ nfs_mnt_prop, sizeof (nfs_mnt_prop), NULL,
NULL, 0, B_FALSE) == 0);
switch (op) {
case OP_SHARE:
verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS,
- nfsiscsi_mnt_prop,
- sizeof (nfsiscsi_mnt_prop),
+ nfs_mnt_prop,
+ sizeof (nfs_mnt_prop),
NULL, NULL, 0, B_FALSE) == 0);
verify(zfs_prop_get(zhp, ZFS_PROP_SHARESMB,
sharesmb, sizeof (sharesmb), NULL, NULL,
0, B_FALSE) == 0);
- if (strcmp(nfsiscsi_mnt_prop, "off") == 0 &&
+ if (strcmp(nfs_mnt_prop, "off") == 0 &&
strcmp(sharesmb, "off") == 0) {
(void) fprintf(stderr, gettext("cannot "
"unshare '%s': legacy share\n"),
@@ -3858,7 +3800,7 @@ unshare_unmount(int op, int argc, char **argv)
break;
case OP_MOUNT:
- if (strcmp(nfsiscsi_mnt_prop, "legacy") == 0) {
+ if (strcmp(nfs_mnt_prop, "legacy") == 0) {
(void) fprintf(stderr, gettext("cannot "
"unmount '%s': legacy "
"mountpoint\n"), zfs_get_name(zhp));
@@ -3877,29 +3819,6 @@ unshare_unmount(int op, int argc, char **argv)
}
break;
}
- } else {
- assert(op == OP_SHARE);
-
- verify(zfs_prop_get(zhp, ZFS_PROP_SHAREISCSI,
- nfsiscsi_mnt_prop, sizeof (nfsiscsi_mnt_prop),
- NULL, NULL, 0, B_FALSE) == 0);
-
- if (strcmp(nfsiscsi_mnt_prop, "off") == 0) {
- (void) fprintf(stderr, gettext("cannot unshare "
- "'%s': 'shareiscsi' property not set\n"),
- zfs_get_name(zhp));
- (void) fprintf(stderr, gettext("set "
- "'shareiscsi' property or use "
- "iscsitadm(1M) to share this volume\n"));
- ret = 1;
- } else if (!zfs_is_shared_iscsi(zhp)) {
- (void) fprintf(stderr, gettext("cannot "
- "unshare '%s': not currently shared\n"),
- zfs_get_name(zhp));
- ret = 1;
- } else if (zfs_unshare_iscsi(zhp) != 0) {
- ret = 1;
- }
}
zfs_close(zhp);
diff --git a/usr/src/common/zfs/zfs_prop.c b/usr/src/common/zfs/zfs_prop.c
index b6f80614f8..340fb94a20 100644
--- a/usr/src/common/zfs/zfs_prop.c
+++ b/usr/src/common/zfs/zfs_prop.c
@@ -285,8 +285,6 @@ zfs_prop_init(void)
ZFS_TYPE_FILESYSTEM, "<path> | legacy | none", "MOUNTPOINT");
register_string(ZFS_PROP_SHARENFS, "sharenfs", "off", PROP_INHERIT,
ZFS_TYPE_FILESYSTEM, "on | off | share(1M) options", "SHARENFS");
- register_string(ZFS_PROP_SHAREISCSI, "shareiscsi", "off", PROP_INHERIT,
- ZFS_TYPE_DATASET, "on | off | type=<type>", "SHAREISCSI");
register_string(ZFS_PROP_TYPE, "type", NULL, PROP_READONLY,
ZFS_TYPE_DATASET, "filesystem | volume | snapshot", "TYPE");
register_string(ZFS_PROP_SHARESMB, "sharesmb", "off", PROP_INHERIT,
@@ -345,7 +343,7 @@ zfs_prop_init(void)
register_hidden(ZFS_PROP_NAME, "name", PROP_TYPE_STRING,
PROP_READONLY, ZFS_TYPE_DATASET, "NAME");
register_hidden(ZFS_PROP_ISCSIOPTIONS, "iscsioptions", PROP_TYPE_STRING,
- PROP_INHERIT, ZFS_TYPE_VOLUME, "ISCSIOPTIONS");
+ PROP_READONLY, ZFS_TYPE_VOLUME, "ISCSIOPTIONS");
register_hidden(ZFS_PROP_STMF_SHAREINFO, "stmf_sbd_lu",
PROP_TYPE_STRING, PROP_INHERIT, ZFS_TYPE_VOLUME,
"STMF_SBD_LU");
diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile
index b4c910a1ed..8a2993d5af 100644
--- a/usr/src/lib/Makefile
+++ b/usr/src/lib/Makefile
@@ -114,7 +114,6 @@ SUBDIRS += \
libinetutil \
libipmp \
libiscsit \
- libiscsitgt \
libkmf \
libkstat \
libkvm \
@@ -423,7 +422,6 @@ HDRSUBDIRS= \
libipmp \
libipp \
libiscsit \
- libiscsitgt \
libkstat \
libkvm \
libmail \
@@ -640,7 +638,7 @@ librestart: libuutil libscf
pkcs11: libcryptoutil
print: libldap5
udapl/udapl_tavor: udapl/libdat
-libzfs: libdevid libgen libnvpair libuutil libiscsitgt \
+libzfs: libdevid libgen libnvpair libuutil \
libadm libavl libefi libidmap libmd
libzfs_jni: libdiskmgt libnvpair libzfs
libzpool: libavl libumem libnvpair
diff --git a/usr/src/lib/libiscsitgt/Makefile b/usr/src/lib/libiscsitgt/Makefile
deleted file mode 100644
index 58d09d3c9b..0000000000
--- a/usr/src/lib/libiscsitgt/Makefile
+++ /dev/null
@@ -1,56 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
-#
-
-include ../Makefile.lib
-
-SUBDIRS = $(MACH)
-$(BUILD64)SUBDIRS += $(MACH64)
-
-all := TARGET= all
-clean := TARGET= clean
-clobber := TARGET= clobber
-install := TARGET= install
-lint := TARGET= lint
-test := TARGET= test
-
-HDRS= libiscsitgt.h iscsitgt_impl.h
-HDRDIR= common
-
-.KEEP_STATE:
-
-all clean clobber install lint: $(SUBDIRS)
-
-install_h: $(ROOTHDRS)
-
-check: $(CHECKHDRS)
-
-$(SUBDIRS): FRC
- @cd $@; pwd; $(MAKE) $(TARGET)
-
-FRC:
-
-include ../Makefile.targ
diff --git a/usr/src/lib/libiscsitgt/Makefile.com b/usr/src/lib/libiscsitgt/Makefile.com
deleted file mode 100644
index 3d4559c7fd..0000000000
--- a/usr/src/lib/libiscsitgt/Makefile.com
+++ /dev/null
@@ -1,54 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
-#
-
-LIBRARY= libiscsitgt.a
-VERS= .1
-OBJECTS= if_zfs.o if_gen.o xml.o gen.o
-
-include ../../Makefile.lib
-include ../../Makefile.rootfs
-
-SRCDIR = ../common
-
-LIBS = $(DYNLIB) $(LINTLIB)
-LDLIBS += -lscf -lc
-$(DYNLIB) := LDLIBS += -lxml2
-SRCS = $(OBJECTS:%.o=$(SRCDIR)/%.c)
-
-$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
-
-CFLAGS += $(CCVERBOSE)
-CPPFLAGS += -I/usr/include/libxml2 -I$(SRCDIR) \
- -I../../../cmd/iscsi/iscsitgtd
-
-.KEEP_STATE:
-
-all: $(LIBS)
-
-lint: lintcheck
-
-include ../../Makefile.targ
diff --git a/usr/src/lib/libiscsitgt/amd64/Makefile b/usr/src/lib/libiscsitgt/amd64/Makefile
deleted file mode 100644
index 2e8cdecf75..0000000000
--- a/usr/src/lib/libiscsitgt/amd64/Makefile
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
-#
-
-include ../Makefile.com
-include ../../Makefile.lib.64
-
-install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/libiscsitgt/common/gen.c b/usr/src/lib/libiscsitgt/common/gen.c
deleted file mode 100644
index 12bc7bad64..0000000000
--- a/usr/src/lib/libiscsitgt/common/gen.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Support routines for library
- */
-#include <errno.h>
-#include <strings.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <libscf.h>
-#include <door.h>
-#include <libxml/xmlreader.h>
-#include <sys/mman.h>
-
-#include "iscsitgt_impl.h"
-
-#define WAIT_FOR_SERVICE 15
-#define WAIT_FOR_DOOR 15
-static char *service = "system/iscsitgt:default";
-
-static Boolean_t check_and_online(int);
-
-tgt_node_t *
-tgt_door_call(char *str, int smf_flags)
-{
- tgt_node_t *n = NULL;
- door_arg_t d;
- int s;
- int allocated;
- xmlTextReaderPtr r;
- char *door_buf = NULL;
-
- /*
- * Setup the door pointers for the initial try.
- */
- allocated = MAX(DOOR_MIN_SPACE, strlen(str) + 1);
- if ((door_buf = malloc(allocated)) == NULL)
- return (NULL);
- (void) strncpy(door_buf, str, allocated);
- bzero(&d, sizeof (d));
- d.data_ptr = door_buf;
- d.data_size = allocated;
- d.rbuf = door_buf;
- d.rsize = allocated;
-
- /*
- * It's entirely possible that we'll be sending this request more
- * than once. In the case of a list operation it's unknown how much
- * data will be required, so the request will be sent and the daemon
- * will return information on how large of a buffer is needed.
- * It possible that the second request, with a larger buffer, also
- * fails with not enough space since between the first and second
- * calls a third party could have created another target increasing
- * the space required. This is not an error, just need to handle it.
- */
- do {
- /*
- * Open the door and if that doesn't work or the first door call
- * fails, try to bring the service online. Then repeat one
- * more time. If the second attempt at the door_call fails
- * then bail out.
- */
- if (((s = open(ISCSI_TARGET_MGMT_DOOR, 0)) == -1) ||
- (door_call(s, &d) == -1)) {
- if (s != -1) {
- (void) close(s);
- s = -1;
- }
- if (check_and_online(smf_flags) == False) {
- goto error;
- } else if ((s = open(ISCSI_TARGET_MGMT_DOOR, 0)) ==
- -1) {
- goto error;
- } else if (door_call(s, &d) == -1) {
- goto error;
- }
- }
-
- if (d.rbuf == NULL)
- goto error;
-
- if ((r = (xmlTextReaderPtr)xmlReaderForMemory(d.rbuf,
- strlen(d.rbuf), NULL, NULL, 0)) == NULL)
- goto error;
-
- while (xmlTextReaderRead(r) == 1)
- if (tgt_node_process(r, &n) == False)
- break;
- xmlFreeTextReader(r);
-
- /*
- * Check to see if our request failed to provide enough
- * buffer room. This can occur if:
- * (1) The request caused an error and the message
- * is larger than the request.
- * (2) We're requesting a configuration list which is
- * fairly large and need to reissue the request with
- * a larger buffer, which the daemon is kind enough
- * to tell us the size needed.
- */
- if (tgt_find_value_int(n, XML_ELEMENT_MORESPACE,
- &allocated) == True) {
-
- tgt_node_free(n);
- n = NULL;
-
- /*
- * It's possible that we've already done a request
- * with a larger buffer, but before we could reissue
- * the request the results got bigger. Targets being
- * added to the configuration would be the common
- * cause of this condition.
- */
- if (door_buf != NULL)
- free(door_buf);
-
- if ((door_buf = malloc(allocated)) == NULL)
- goto error;
-
- (void) strncpy(door_buf, str, allocated);
- d.data_ptr = door_buf;
- d.data_size = allocated;
- d.rbuf = door_buf;
- d.rsize = allocated;
- }
-
- (void) close(s);
- s = -1;
- } while (n == NULL);
-
-error:
- if (door_buf)
- free(door_buf);
- (void) close(s);
- return (n);
-}
-
-static Boolean_t
-is_online(void)
-{
- char *s;
- Boolean_t rval = False;
-
- if (getenv("iscsitgt_no_daemon") != NULL) {
- rval = True;
- } else {
- if ((s = smf_get_state(service)) != NULL) {
- if (strcmp(s, SCF_STATE_STRING_ONLINE) == 0)
- rval = True;
- free(s);
- }
- }
-
- return (rval);
-}
-
-static Boolean_t
-is_auto_enabled(void)
-{
- scf_simple_prop_t *prop;
- uint8_t *ret;
- Boolean_t rval = True;
-
- if ((prop = scf_simple_prop_get(NULL, service, "application",
- "auto_enable")) == NULL)
- return (True);
-
- if ((ret = scf_simple_prop_next_boolean(prop)) != NULL)
- rval = (*ret != 0);
-
- scf_simple_prop_free(prop);
-
- return (rval);
-}
-
-static Boolean_t
-check_and_online(int smf_flags)
-{
- int i;
- int fd;
- door_arg_t d;
-
- if (!is_online()) {
- if (!is_auto_enabled())
- return (False);
-
- if (smf_enable_instance(service, smf_flags) != 0)
- return (False);
-
- for (i = 0; i < WAIT_FOR_SERVICE; i++) {
- if (is_online() == True)
- break;
- (void) sleep(1);
- }
-
- if (i == WAIT_FOR_SERVICE)
- return (False);
- }
-
- for (i = 0; i < WAIT_FOR_DOOR; i++) {
- if ((fd = open(ISCSI_TARGET_MGMT_DOOR, 0)) >= 0) {
- /*
- * There's at least a file with the same name as our
- * door. Let's see if someone is currently answering
- * by sending an empty XML request.
- */
- d.data_ptr = "<config></config>";
- d.data_size = strlen(d.data_ptr) + 1;
- d.desc_ptr = NULL;
- d.desc_num = 0;
- d.rbuf = NULL;
- d.rsize = 0;
-
- if (door_call(fd, &d) == 0) {
- /*
- * The daemon is now ready to handle requests.
- */
- (void) close(fd);
- return (True);
- } else
- (void) close(fd);
-
- }
- if (!is_online())
- break;
- (void) sleep(1);
- }
- return (False);
-}
-
-/*
- * Not using Boolean_t here, since that is a
- * private type to the library
- */
-int
-iscsitgt_svc_online()
-{
- return ((is_online() == True) ? 0 : 1);
-}
diff --git a/usr/src/lib/libiscsitgt/common/if_gen.c b/usr/src/lib/libiscsitgt/common/if_gen.c
deleted file mode 100644
index 1ab74664fe..0000000000
--- a/usr/src/lib/libiscsitgt/common/if_gen.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <libiscsitgt.h>
-
-/*
- * iscsitgt_init -- Create a handle for each daemon
- */
-/*ARGSUSED*/
-iscsit_handle_t
-iscsitgt_init(char *host)
-{
- return (NULL);
-}
-
-/*
- * iscsitgt_fini -- free resources allocated by iscsitgt_init()
- */
-/*ARGSUSED*/
-void
-iscsitgt_fini(iscsit_handle_t h)
-{
-}
diff --git a/usr/src/lib/libiscsitgt/common/if_zfs.c b/usr/src/lib/libiscsitgt/common/if_zfs.c
deleted file mode 100644
index 3528872286..0000000000
--- a/usr/src/lib/libiscsitgt/common/if_zfs.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Methods for ZFS to notify the iSCSI Target about which ZVOLs
- * need to be made available.
- */
-
-#include <libiscsitgt.h>
-#include <strings.h>
-#include <errno.h>
-#include <libscf.h>
-#include <errcode.h>
-
-#include "iscsitgt_impl.h"
-
-/*
- * iscsitgt_zfs_share -- share a ZFS volume as an iSCSI target
- */
-int
-iscsitgt_zfs_share(const char *dataset)
-{
- char *str = NULL;
- tgt_node_t *n;
- int code;
-
- tgt_buf_add_tag(&str, "create", Tag_Start);
- tgt_buf_add_tag(&str, "zfs", Tag_Start);
- tgt_buf_add(&str, "name", dataset);
- tgt_buf_add_tag(&str, "zfs", Tag_End);
- tgt_buf_add_tag(&str, "create", Tag_End);
-
- if ((n = tgt_door_call(str, SMF_TEMPORARY)) == NULL) {
- if (iscsitgt_svc_online() != 0) {
- errno = EPERM;
- } else {
- errno = EINVAL;
- }
- free(str);
- return (-1);
- }
-
- if (strcmp(n->x_name, XML_ELEMENT_ERROR) == 0 &&
- tgt_find_value_int(n, XML_ELEMENT_CODE, &code) == True) {
- if (code == 1000) {
- free(str);
- tgt_node_free(n);
- return (0);
- } else {
- errno = (code == ERR_NO_PERMISSION) ? EPERM : EINVAL;
- }
- } else {
- errno = EINVAL;
- }
- free(str);
- tgt_node_free(n);
- return (-1);
-}
-
-/*
- * iscsitgt_zfs_unshare -- unshare a ZFS volume
- */
-int
-iscsitgt_zfs_unshare(const char *dataset)
-{
- char *str = NULL;
- tgt_node_t *n;
- int code;
-
- tgt_buf_add_tag(&str, "delete", Tag_Start);
- tgt_buf_add_tag(&str, "zfs", Tag_Start);
- tgt_buf_add(&str, "name", dataset);
- tgt_buf_add_tag(&str, "zfs", Tag_End);
- tgt_buf_add_tag(&str, "delete", Tag_End);
-
- if ((n = tgt_door_call(str, SMF_TEMPORARY)) == NULL) {
- errno = EINVAL;
- free(str);
- return (-1);
- }
-
- if (strcmp(n->x_name, XML_ELEMENT_ERROR) == 0 &&
- tgt_find_value_int(n, XML_ELEMENT_CODE, &code) == True) {
- if (code == 1000) {
- free(str);
- tgt_node_free(n);
- return (0);
- } else {
- errno = (code == ERR_NO_PERMISSION) ? EPERM : EINVAL;
- }
- } else {
- errno = EINVAL;
- }
-
- free(str);
- tgt_node_free(n);
- return (-1);
-}
-
-int
-iscsitgt_zfs_is_shared(const char *dataset)
-{
- char *str = NULL;
- tgt_node_t *n;
- int code;
-
- tgt_buf_add_tag(&str, "modify", Tag_Start);
- tgt_buf_add_tag(&str, "zfs", Tag_Start);
- tgt_buf_add(&str, "name", dataset);
- tgt_buf_add(&str, XML_ELEMENT_VALIDATE, XML_VALUE_TRUE);
- tgt_buf_add_tag(&str, "zfs", Tag_End);
- tgt_buf_add_tag(&str, "modify", Tag_End);
-
- if ((n = tgt_door_call(str, SMF_TEMPORARY)) == NULL) {
- errno = EINVAL;
- free(str);
- return (-1);
- }
- if (strcmp(n->x_name, XML_ELEMENT_ERROR) == 0 &&
- tgt_find_value_int(n, XML_ELEMENT_CODE, &code) == True &&
- code == 1000) {
- free(str);
- tgt_node_free(n);
- return (1);
- }
-
- free(str);
- tgt_node_free(n);
- return (0);
-}
diff --git a/usr/src/lib/libiscsitgt/common/iscsitgt_impl.h b/usr/src/lib/libiscsitgt/common/iscsitgt_impl.h
deleted file mode 100644
index 415273871f..0000000000
--- a/usr/src/lib/libiscsitgt/common/iscsitgt_impl.h
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _ISCSITGT_IMPL_H
-#define _ISCSITGT_IMPL_H
-
-/*
- * Block comment which describes the contents of this file.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <libxml/xmlreader.h>
-
-#ifndef MIN
-#define MIN(x, y) ((x) < (y) ? (x) : (y))
-#endif
-#ifndef MAX
-#define MAX(x, y) ((x) > (y) ? (x) : (y))
-#endif
-
-/*
- * Solaris typedefs boolean_t to be an enum with B_TRUE and B_FALSE.
- * MacOS X typedefs boolean_t to be an int with #defines for TRUE & FALSE
- * I like the use of enum's for return codes so that compilers can catch
- * sloppy coding practices so I've defined a Boolean_t which is unique here.
- */
-typedef enum {
- False = 0,
- True = 1
-} Boolean_t;
-
-#ifndef DTYPE_OSD
-#define DTYPE_OSD 0x11
-#endif
-
-#define DOOR_MIN_SPACE 128
-
-#define ISCSI_TARGET_MGMT_DOOR "/var/run/iscsi_tgt_door"
-/*
- * XML element defines.
- */
-#define XML_ELEMENT_ERROR "error"
-#define XML_ELEMENT_CODE "code"
-#define XML_ELEMENT_MESSAGE "message"
-#define XML_ELEMENT_TRANSVERS "transport-version"
-#define XML_ELEMENT_PROPS "props"
-#define XML_ELEMENT_DATAOUT "data-out-size"
-#define XML_ELEMENT_BASEDIR "base-directory"
-#define XML_ELEMENT_CHAPSECRET "chap-secret"
-#define XML_ELEMENT_DELETE_CHAPSECRET "delete-chap-secret"
-#define XML_ELEMENT_CHAPNAME "chap-name"
-#define XML_ELEMENT_DELETE_CHAPNAME "delete-chap-name"
-#define XML_ELEMENT_RAD_ACCESS "radius-access"
-#define XML_ELEMENT_RAD_SERV "radius-server"
-#define XML_ELEMENT_DELETE_RAD_SERV "delete-radius-server"
-#define XML_ELEMENT_RAD_SECRET "radius-secret"
-#define XML_ELEMENT_DELETE_RAD_SECRET "delete-radius-secret"
-#define XML_ELEMENT_ISNS_ACCESS "isns-access"
-#define XML_ELEMENT_ISNS_SERV "isns-server"
-#define XML_ELEMENT_ISNS_SERVER_STATUS "isns-server-status"
-#define XML_ELEMENT_FAST "fast-write-ack"
-#define XML_ELEMENT_NAME "name"
-#define XML_ELEMENT_ACL "acl"
-#define XML_ELEMENT_ACLLIST "acl-list"
-#define XML_ELEMENT_TPGT "tpgt"
-#define XML_ELEMENT_TPGTLIST "tpgt-list"
-#define XML_ELEMENT_SIZE "size"
-#define XML_ELEMENT_LUN "lun"
-#define XML_ELEMENT_LUNLIST "lun-list"
-#define XML_ELEMENT_TYPE "type"
-#define XML_ELEMENT_ALIAS "alias"
-#define XML_ELEMENT_BACK "backing-store"
-#define XML_ELEMENT_DELETE_BACK "delete-backing-store"
-#define XML_ELEMENT_TARG "target"
-#define XML_ELEMENT_INIT "initiator"
-#define XML_ELEMENT_ZFS "zfs"
-#define XML_ELEMENT_ADMIN "admin"
-#define XML_ELEMENT_INAME "iscsi-name"
-#define XML_ELEMENT_MAXRECV "maxrecv"
-#define XML_ELEMENT_IPADDR "ip-address"
-#define XML_ELEMENT_IPADDRLIST "ip-address-list"
-#define XML_ELEMENT_ALL "all"
-#define XML_ELEMENT_VERBOSE "verbose"
-#define XML_ELEMENT_LIST "list"
-#define XML_ELEMENT_RESULT "result"
-#define XML_ELEMENT_TIMECON "time-connected"
-#define XML_ELEMENT_READCMDS "read-commands"
-#define XML_ELEMENT_WRITECMDS "write-commands"
-#define XML_ELEMENT_READBLKS "read-blks"
-#define XML_ELEMENT_WRITEBLKS "write-blks"
-#define XML_ELEMENT_STATS "statistics"
-#define XML_ELEMENT_CONN "connection"
-#define XML_ELEMENT_LUNINFO "lun-information"
-#define XML_ELEMENT_VID "vid"
-#define XML_ELEMENT_PID "pid"
-#define XML_ELEMENT_GUID "guid"
-#define XML_ELEMENT_DTYPE "dtype"
-#define XML_ELEMENT_IOSTAT "iostat"
-#define XML_ELEMENT_MACADDR "mac-addr"
-#define XML_ELEMENT_MGMTPORT "mgmt-port"
-#define XML_ELEMENT_ISCSIPORT "iscsi-port"
-#define XML_ELEMENT_TARGLOG "target-log"
-#define XML_ELEMENT_DBGLVL "dbg-lvl"
-#define XML_ELEMENT_LOGLVL "qlog-lvl"
-#define XML_ELEMENT_DBGDAEMON "daemonize"
-#define XML_ELEMENT_ENFORCE "enforce-strict-guid"
-#define XML_ELEMENT_VERS "version"
-#define XML_ELEMENT_MMAP_LUN "mmap-lun"
-#define XML_ELEMENT_RPM "rpm"
-#define XML_ELEMENT_HEADS "heads"
-#define XML_ELEMENT_CYLINDERS "cylinders"
-#define XML_ELEMENT_SPT "spt"
-#define XML_ELEMENT_BPS "bps"
-#define XML_ELEMENT_INTERLEAVE "interleave"
-#define XML_ELEMENT_PARAMS "params"
-#define XML_ELEMENT_MAXCMDS "max-outstanding-cmds"
-#define XML_ELEMENT_THIN_PROVO "thin-provisioning"
-#define XML_ELEMENT_DISABLE_TPGS "disable-tpgs"
-#define XML_ELEMENT_STATUS "status"
-#define XML_ELEMENT_PROGRESS "progress"
-#define XML_ELEMENT_TIMESTAMPS "time-stamps"
-#define XML_ELEMENT_INCORE "in-core"
-#define XML_ELEMENT_VALIDATE "validate"
-#define XML_ELEMENT_MORESPACE "more-space-required"
-#define XML_VALUE_TRUE "true"
-#define XML_ELEMENT_PGR_PERSIST "PGR-persist"
-#define XML_ELEMENT_PGR_BASEDIR "PGR-basedir"
-
-typedef enum {
- NodeFree,
- NodeAlloc,
- NodeName,
- NodeValue
-} tgt_node_state;
-
-typedef enum { MatchName, MatchBoth } match_type_t;
-
-typedef struct tgt_node {
- struct tgt_node *x_parent,
- *x_child,
- *x_sibling,
- *x_attr;
- char *x_name,
- *x_value;
- tgt_node_state x_state;
-} tgt_node_t;
-
-typedef enum val_type { Tag_String, Tag_Start, Tag_End } val_type_t;
-typedef enum xml_val_type { String, Int, Uint64 } xml_val_type_t;
-
-tgt_node_t *tgt_door_call(char *str, int smf_flags);
-void tgt_dump2buf(tgt_node_t *t, char **buf);
-
-tgt_node_t *tgt_node_alloc(char *name, xml_val_type_t type, void *value);
-void tgt_node_free(tgt_node_t *x);
-void tgt_node_replace(tgt_node_t *parent, tgt_node_t *child, match_type_t m);
-Boolean_t tgt_node_remove(tgt_node_t *parent, tgt_node_t *child,
- match_type_t m);
-tgt_node_t *tgt_node_next(tgt_node_t *n, char *name, tgt_node_t *cur);
-tgt_node_t *tgt_node_next_child(tgt_node_t *n, char *name, tgt_node_t *cur);
-tgt_node_t *tgt_node_dup(tgt_node_t *n);
-tgt_node_t *tgt_node_find(tgt_node_t *n, char *name);
-void tgt_node_add(tgt_node_t *p, tgt_node_t *c);
-void tgt_node_add_attr(tgt_node_t *p, tgt_node_t *a);
-Boolean_t tgt_node_process(xmlTextReaderPtr r, tgt_node_t **node);
-
-void tgt_buf_add(char **b, char *element, const char *cdata);
-void tgt_buf_add_tag(char **b, const char *str, val_type_t type);
-void tgt_buf_add_tag_and_attr(char **b, char *str, char *attr);
-
-Boolean_t tgt_xml_encode(uint8_t *ip, size_t ip_size, char **buf,
- size_t *buf_size);
-Boolean_t tgt_xml_decode(char *buf, uint8_t **ip, size_t *ip_size);
-Boolean_t tgt_find_value_str(tgt_node_t *n, char *name, char **value);
-Boolean_t tgt_find_value_int(tgt_node_t *n, char *name, int *value);
-Boolean_t tgt_find_value_intchk(tgt_node_t *n, char *name, int *value);
-Boolean_t tgt_find_value_boolean(tgt_node_t *n, char *name, Boolean_t *value);
-Boolean_t tgt_find_attr_str(tgt_node_t *n, char *attr, char **value);
-Boolean_t tgt_update_value_str(tgt_node_t *node, char *name, char *str);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ISCSITGT_IMPL_H */
diff --git a/usr/src/lib/libiscsitgt/common/libiscsitgt.h b/usr/src/lib/libiscsitgt/common/libiscsitgt.h
deleted file mode 100644
index cf01a62fea..0000000000
--- a/usr/src/lib/libiscsitgt/common/libiscsitgt.h
+++ /dev/null
@@ -1,578 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _LIBISCSITGT_H
-#define _LIBISCSITGT_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Management API for the iSCSI Target.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * These includes resolve
- */
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/iscsi_protocol.h>
-#include <sys/scsi/generic/inquiry.h>
-
-#define EUI64_SIZE 16
-#define VID_SIZE 8
-#define PID_SIZE 16
-
-/*
- * []------------------------------------------------------------------[]
- * | Structures and enums returned by the list functions |
- * []------------------------------------------------------------------[]
- */
-
-typedef enum { LU_Offline, LU_Online } iscsit_status_t;
-typedef enum { Target, Initiator, TPGT } iscsit_obj_type_t;
-
-/*
- * Logical Unit (LU) Structure.
- * Each iSCSI Target has one or more Logical Units.
- */
-typedef struct iscsit_lu {
- /* This is the LU number for SCSI commands */
- int l_num;
-
- /* Globally unique identifier */
- uint8_t l_guid[EUI64_SIZE];
-
- /*
- * VID/PID used in SCSI INQUIRY responses
- */
- char l_vid[VID_SIZE],
- l_pid[PID_SIZE];
- /*
- * Value will be one of DTYPE_DIRECT, DTYPE_SEQUENTIAL, etc ...
- * Look at sys/scsi/generic/inquiry.h for full list
- */
- uint8_t l_dtype;
-
- /* Size of device in blocks */
- diskaddr_t l_size;
-
- iscsit_status_t l_status;
-} iscsit_lu_t;
-
-/*
- * iSCSI Session information.
- */
-typedef struct iscsit_conn {
- char c_name[ISCSI_MAX_NAME_LEN],
- *c_alias;
-} iscsit_conn_t;
-
-typedef struct iscsit_target {
- /* This is the full IQN name of the target */
- char t_name[ISCSI_MAX_NAME_LEN];
-
- /*
- * The Alias which is the same as "friendly name" used during the
- * creation of the target.
- */
- char *t_alias;
-
- /*
- * The number of Logical Units associated with this target.
- * There will always be at least one LU with a value of 0.
- * If there are more than LU the order is not guaranteed.
- */
- int t_lu_count;
- iscsit_lu_t **t_lu_list;
-
- /*
- * A list of initiator which may access this target. This list
- * may be 0 in length.
- */
- int t_acl_count;
- char **t_acl_list;
-
- /*
- * Target Portal Group Tags. A value of zero for the count
- * is valid.
- */
- int t_tpgt_count;
- char **t_tpgt_list;
-
- /*
- * The number of sessions that are currently attached to the
- * target. Zero is valid.
- */
- int t_conn_count;
- iscsit_conn_t **t_conn_list;
-} iscsit_target_t;
-
-/*
- * Information stored locally about initiators. Local initiator information
- * is setup when administrators wish to control access to each target. The
- * use of iSNS will be the prefered method once it's supported.
- */
-typedef struct iscsit_initiator {
- char i_name[ISCSI_MAX_NAME_LEN],
- *i_chap_name;
- /*
- * While the target daemon has the CHAP secret available it's
- * never returned. The CHAP name and secret can be changed at
- * any time. This boolean will indicate if the CHAP secret is set
- * and if so will cause the daemon to perform unidirectional
- * authentication.
- */
- boolean_t i_chap_secret_set;
-} iscsit_initiator_t;
-
-/*
- * The list of IP addresses associated with a Target Portal Group Tag
- */
-typedef struct iscsit_tpgt {
- int t_ip_count;
- struct sockaddr_storage **t_ip_list;
-} iscsit_tpgt_t;
-
-/*
- * These are values which are used globally through the target daemon.
- */
-typedef struct iscsit_admin {
- /*
- * This is the targets CHAP information. When an initiator needs
- * to authenticate the target these values are used when creating
- * the response.
- */
- char *a_chap_name;
- boolean_t a_chap_secret_set;
-
- /*
- * The location of the target configuration and default storage for LUs
- */
- char *a_base_directory;
-
- struct sockaddr_storage a_radius_server;
- boolean_t a_radius_secret_set,
- a_isns_discovery;
- struct sockaddr_storage a_isns_ip;
- boolean_t a_fast_write_ack;
-} iscsit_admin_t;
-
-typedef void *iscsit_handle_t;
-
-/*
- * []------------------------------------------------------------------[]
- * | Funtion Prototypes |
- * []------------------------------------------------------------------[]
- */
-
-/*
- * []------------------------------------------------------------------[]
- * | Functions for ZFS |
- * []------------------------------------------------------------------[]
- */
-/*
- * iscsitgt_zfs_share -- advertise a ZFS volume through iSCSI
- * iscsitgt_zfs_unshare -- unadvertise a ZFS volume through iSCSI
- *
- * dataset = this must be a valid ZFS dataset which has a "type" property
- * of "volume".
- *
- * These functions will return 0 on success and -1 on failure setting errno
- * thusly:
- *
- * ENODEV - dataset not found
- * EINVAL - a share parameter has an invalid value
- * ENOSYS - the option string cannot be understood for any other reason
- */
-int iscsitgt_zfs_share(const char *dataset);
-int iscsitgt_zfs_unshare(const char *dataset);
-
-/*
- * iscsitgt_zfs_is_shared -- returns 1 and 0 otherwise
- */
-int iscsitgt_zfs_is_shared(const char *dataset);
-
-/*
- * []------------------------------------------------------------------[]
- * | Functions to create handles which are used by methods defined below|
- * []------------------------------------------------------------------[]
- */
-/*
- * iscsitgt_init -- Create a handle for each daemon
- *
- * A future release will enable this library to work to control multiple
- * daemons on different hosts. For now, the argument 'host' should be
- * set to NULL which will indicate the local host.
- */
-iscsit_handle_t iscsitgt_init(char *host);
-
-/*
- * iscsitgt_fini -- free resources allocated by iscsitgt_init()
- */
-void iscsitgt_fini(iscsit_handle_t h);
-
-/*
- * []------------------------------------------------------------------[]
- * | Funtions for creating base objects |
- * []------------------------------------------------------------------[]
- */
-/*
- * iscsitgt_creat_target -- creates a new target/lu
- *
- * h = This is handle which indicates to which target the request is sent.
- * If NULL, the target daemon on the current host is used.
- * friendly_name = any ASCII string with the following restrictions.
- * - it must be no more than 163 characters
- * - it must only contain charcters from the set of 'a-z', 'A-Z', '0-9',
- * ':', '.', or '-'
- * The friendly_name will also be used as the iSCSI TargetAlias which
- * is sent to the initiator as part of the log in parameters.
- * lun = If the friendly_name has never been used before then lun must be 0.
- * If friendly_name has already been created other luns will be created
- * under that target. 0 <= lun <= 65535. NOTE: Using LUNs larger than
- * 255 is not guaranteed to work for all initiators.
- * size = The requested size for the device in blocks. There must be
- * available space on the device for the create to succeed. size may
- * be zero if, and only if, a 'backing' argument is given which exists.
- * dtype = This indicates which type of emulation is performed by the
- * daemon. Currently DTYPE_DIRECT, DTYPE_SEQUENTIAL, and DTYPE_UNKNOWN
- * are supported. A dtype of DTYPE_UNKNOWN indicates to the daemon
- * that a pass through mode should be used. For the pass through mode
- * to work 'backing' must be a character device which supports the USCSI
- * ioctl. For ZVOLs the dtype should be DTYPE_DIRECT.
- * backing = optional location for the backing store. Normally the storage
- * for the LU is created in the directory supplied to iscsit_mod_adm_store().
- * If the 'backing' file name doesn't exist *and* a valid device 'size' is
- * given then the backing store will be created in that location. When the
- * target/lu is removed this backing store will also be removed.
- *
- * Return codes:
- * EINVAL = one or more of the arguments are invalid
- * ENOSPC = No space remains to create the backing store.
- * EEXIST = A target with the same friendly_name already exists
- */
-int iscsitgt_creat_target(iscsit_handle_t h, char *friendly_name,
- int lun, diskaddr_t size, int dtype, char *backing);
-
-/*
- * iscsitgt_creat_initiator -- creates an initiator object
- *
- * Associates a fully compliant iSCSI name (IQN or EUI type) with
- * a really human readable name.
- *
- * h = Handle used to communicate with remote target daemons. A NULL
- * value may be used to indicate that the local host target daemon
- * friendly_name = Any ASCII string.
- * iqn_name = An initiator IQN or EUI string. There will be no validation
- * of the name to determine if it complies with RFC3720. This way if
- * an initiator has a poorly formed name we can still be configured to
- * work with it.
- *
- * Return codes:
- * 0 = success
- * EEXIST = The friendly_name is already used.
- */
-int iscsitgt_creat_initiator(iscsit_handle_t h, char *friendly_name,
- char *iqn_name);
-
-/*
- * iscsitgt_creat_tpgt -- Create a Target Portal Group Tag
- *
- * Once a TPGT object has been created iscsitgt_add_tpgt_ip would be used
- * to associate certain IP addresses with this TPGT. This is used to
- * limit which NICs connections are accepted on for a given target.
- * Once a TPGT is setup it can be added to a target using:
- * iscsitgt_add_target_tpgt().
- *
- * h = See iscsitgt_creat_target
- * tpgt_num = a value between 1 and 65535 inclusive
- *
- * Return codes:
- * 0 = success
- * EEXIST = A tpgt with that number already exists.
- * EINVAL = TPGT must be a value between 1 and 65535 inclusive
- */
-int iscsitgt_creat_tpgt(iscsit_handle_t h, int tpgt_num);
-
-/*
- * []------------------------------------------------------------------[]
- * | Funtions for removing base objects |
- * []------------------------------------------------------------------[]
- */
-
-/*
- * iscsitgt_rem_target -- Removes a target/LU from the system
- *
- * Logical Unit Number 0 *must* be the last LUN removed from a target
- * If not, an error will be returned. When LUN0 is removed all references
- * to friendly_name are also removed from the system. e.g. Once the LU's
- * are removed there's nothing else required to remove the target.
- *
- * h = See iscsitgt_creat_target()
- * friendly_name = This is the same name used during the creation of
- * the target.
- * lun = Logical Unit Number
- *
- * Return codes:
- * 0 = success
- * ENOENT = either friendly_name wasn't found or lun not found
- * EINVAL = attempt made to remove LUN0 while other LUs still exist.
- */
-int iscsitgt_rem_target(iscsit_handle_t h, char *friendly_name,
- int lun);
-
-/*
- * iscsitgt_rem_initiator -- Removes initiator object
- *
- * This method removes just the initiator object, but not any references
- * to this object. For example let's say an initiator was called
- * payroll_server and that this server was replaced with a new server
- * that had the same function, but with a new IQN value and CHAP secret.
- * The user of this library could then remove the initiator object
- * and create a new one with the changes *without* needing to update all
- * of the target objects that have a reference to 'payroll_server' in
- * their ACLs. This is a security feature. If a target has a reference
- * to an initiator object which doesn't exist, nobody will be able to
- * log into the target. If the daemon we're to remove all references
- * along with the object it would then be possible for an initiator to
- * log into the target during the time the target didn't have a reference.
- *
- * h = See iscsitgt_creat_target()
- * friendly_name = same value as that used during create.
- *
- * Return codes:
- * 0 = success
- * ENOENT = Can't find friendly_name
- */
-int iscsitgt_rem_initiator(iscsit_handle_t h, char *friendly_name);
-
-/*
- * iscsitgt_rem_tpgt -- Removes a tpgt object
- *
- * Similar in function to iscsitgt_rem_initiator. This method only
- * removes the TPGT object, but not any references to the object. This
- * alows the administrator to remove an old TPGT and create a new one
- * without needing to update each and every target first.
- *
- * h = See iscsitgt_creat_target
- * tpgt_num = value used during create
- *
- * Return codes:
- * 0 = success
- * ENOENT = tpgt_num wasn't found
- * EINVAL = a value outside of the accepted range for tpgt_num was used.
- */
-int iscsitgt_rem_tpgt(iscsit_handle_t h, int tpgt_num);
-
-/*
- * []------------------------------------------------------------------[]
- * | Funtions for adding attributes to base objects |
- * []------------------------------------------------------------------[]
- */
-/*
- * iscsitgt_add_target_initiator -- Adds an initiator object to ACL for target
- *
- * h = See iscsitgt_creat_target
- * friendly_name = Existing target
- * initiator = name of initiator object which doesn't need to exist before
- * it's added.
- *
- * Return codes:
- * 0 = success
- * ENOENT = friendly_name doesn't exist.
- */
-int iscsitgt_add_target_initiator(iscsit_handle_t h, char *friendly_name,
- char *initiator);
-
-/*
- * iscsitgt_add_target_tpgt -- adds TPGT to the target
- *
- * h = See iscsitgt_creat_target()
- * friendly_name = Must be a valid target object name
- * tpgt_num = While the TPGT object doesn't need to exist, the value will
- * be validated to see if it's within the valid range of 1 to 65535 inclusive
- *
- * Return codes:
- * 0 = success
- * ENOENT = friendly_name not found
- * EINVAL = tpgt_num is not within the valid range.
- */
-int iscsitgt_add_target_tpgt(iscsit_handle_t h, char *friendly_name,
- int tpgt_num);
-
-/*
- * iscsitgt_add_tpgt_ip -- Adds IP address to TPGT object
- *
- * Return codes:
- * 0 = success
- * ENOENT = tpgt_num doesn't exist
- * EINVAL = tpgt_num is not within the valid range
- */
-int iscsitgt_add_tpgt_ip(iscsit_handle_t h, int tpgt_num,
- struct sockaddr_storage *s);
-
-/*
- * []------------------------------------------------------------------[]
- * | Funtions for deleting attributes from base objects |
- * []------------------------------------------------------------------[]
- */
-/*
- * iscsitgt_del_target_initiator -- Removes initiator from target ACL
- *
- * h = See iscsitgt_creat_target()
- * friendly_name = target object
- * initiator = initiator object to remove from ACL
- *
- * Return codes:
- * 0 = success
- * ENOENT = friendly_name or initiator don't exist
- */
-int iscsitgt_del_target_initiator(iscsit_handle_t h, char *friendly_name,
- char *initiator);
-
-/*
- * iscsitgt_del_target_tpgt -- Removes TPGT from specific target
- *
- * Return codes:
- * 0 = success
- * ENOENT = Either friendly_name or tpgt_num doesn't exist as a valid
- * type
- * EINVAL = tpgt_num is outside of the valid range (1 to 65535)
- */
-int iscsitgt_del_target_tpgt(iscsit_handle_t h, char *friendly_name,
- int tpgt_num);
-
-/*
- * iscsitgt_del_tpgt_ip -- Removes IP address from TPGT
- *
- * Return codes:
- * 0 = success
- * ENOENT = tpgt_num wasn't found or the IP address wasn't found within a valid
- * tpgt
- * EINVAL = tpgt_num is outside of the valid range (1 to 65535)
- */
-int iscsitgt_del_tpgt_ip(iscsit_handle_t h, int tpgt_num,
- struct sockaddr_storage *s);
-
-/*
- * []------------------------------------------------------------------[]
- * | Funtions for modifying singular attributes for base objects |
- * []------------------------------------------------------------------[]
- */
-/*
- * iscsitgt_mode_target_alias -- Modifies the TargetAlias associated with target
- *
- * By default the TargetAlias is the same as that given for the friendly_name.
- * If another name is desired then it can be changed using this interface.
- *
- * h = See iscsitgt_creat_target()
- * friendly_name = target object
- *
- * Return codes:
- * 0 = success
- * ENOENT = friendly_name doesn't exist
- */
-int iscsitgt_mod_target_alias(iscsit_handle_t h, char *friendly_name,
- char *alias);
-int iscsitgt_mod_target_maxrec(iscsit_handle_t h, char *friendly_name,
- size_t maxrecv);
-int iscsitgt_mod_initiator_chap(iscsit_handle_t h,
- char *friendly_name, char *chap_name, char *chap_secret);
-int iscsitgt_mod_adm_store(iscsit_handle_t h, char *base);
-int iscsitgt_mod_adm_chap(iscsit_handle_t h, char *chap_name,
- char *chap_secret);
-int iscsitgt_mod_adm_radius(iscsit_handle_t h, struct sockaddr_storage *s,
- char *secret);
-int iscsitgt_mod_adm_isns_discover(iscsit_handle_t h,
- boolean_t find);
-int iscsitgt_mod_adm_isns(iscsit_handle_t h,
- struct sockaddr_storage *s);
-int iscsitgt_mod_adm_fwa(iscsit_handle_t h, boolean_t enable);
-
-/*
- * []------------------------------------------------------------------[]
- * | Funtions for listing objects |
- * | |
- * | NOTE: Each of the following function have a specific free routine |
- * | which must be called to free the data. |
- * []------------------------------------------------------------------[]
- */
-/*
- * iscsit_list_find -- returns list of specific object names.
- *
- * There are three types of objects which are manipulated by these
- * interfaces (Target, Initiator, and TPGT). This function will return
- * an array of character strings which represent all of the available
- * objects of the specific type. These strings are the same ones that
- * where used during the creation.
- *
- * NOTE: Since there's no locking a call to this this function may
- * return a name which then doesn't exist when the user attempts to
- * get the specific information on that object. This would be caused
- * when another operator deletes an object between the first and second
- * calls.
- */
-char **iscsit_list_find(iscsit_handle_t h, iscsit_obj_type_t t);
-void iscsit_list_free(char **list);
-
-/*
- * iscsit_list_target -- returns detailed information about a target
- */
-iscsit_target_t *iscsit_list_target(iscsit_handle_t h, char *targ);
-void iscsit_list_target_free(iscsit_target_t *t);
-
-/*
- * iscsit_list_initiator -- returns detailed information about an initiator
- */
-iscsit_initiator_t *iscsit_list_initiator(iscsit_handle_t h, char *initiator);
-void iscsit_list_initiator_free(iscsit_initiator_t *t);
-
-/*
- * iscsit_list_tpgt -- returns detailed information about a target port group
- */
-iscsit_tpgt_t *iscsit_list_tpgt(iscsit_handle_t h, char *tpgt);
-void iscsit_list_tpgt_free(iscsit_tpgt_t *t);
-
-/*
- * iscsit_list_adm -- returns information about the global variables used.
- */
-iscsit_admin_t *iscsit_list_adm(iscsit_handle_t h);
-void iscsit_list_adm_free(iscsit_admin_t *t);
-
-/*
- * Misc functions
- */
-int iscsitgt_svc_online();
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _LIBISCSITGT_H */
diff --git a/usr/src/lib/libiscsitgt/common/llib-liscsitgt b/usr/src/lib/libiscsitgt/common/llib-liscsitgt
deleted file mode 100644
index 2b28fe63ff..0000000000
--- a/usr/src/lib/libiscsitgt/common/llib-liscsitgt
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*LINTLIBRARY*/
-/*PROTOLIB1*/
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <libiscsitgt.h>
diff --git a/usr/src/lib/libiscsitgt/common/mapfile-vers b/usr/src/lib/libiscsitgt/common/mapfile-vers
deleted file mode 100644
index 792d56f156..0000000000
--- a/usr/src/lib/libiscsitgt/common/mapfile-vers
+++ /dev/null
@@ -1,72 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-#
-# MAPFILE HEADER START
-#
-# WARNING: STOP NOW. DO NOT MODIFY THIS FILE.
-# Object versioning must comply with the rules detailed in
-#
-# usr/src/lib/README.mapfiles
-#
-# You should not be making modifications here until you've read the most current
-# copy of that file. If you need help, contact a gatekeeper for guidance.
-#
-# MAPFILE HEADER END
-#
-
-SUNWprivate_1.1 {
- global:
- iscsitgt_svc_online;
- iscsitgt_zfs_is_shared;
- iscsitgt_zfs_share;
- iscsitgt_zfs_unshare;
- tgt_door_call;
- tgt_node_free;
- tgt_dump2buf;
- tgt_node_process;
- tgt_find_attr_str;
- tgt_find_value_str;
- tgt_find_value_int;
- tgt_find_value_intchk;
- tgt_find_value_boolean;
- tgt_node_next;
- tgt_node_next_child;
- tgt_node_add;
- tgt_node_add_attr;
- tgt_node_alloc;
- tgt_node_remove;
- tgt_node_replace;
- tgt_node_find;
- tgt_node_dup;
- tgt_xml_encode;
- tgt_xml_decode;
- tgt_update_value_str;
- tgt_buf_add;
- tgt_buf_add_tag;
- tgt_buf_add_tag_and_attr;
- local:
- *;
-};
diff --git a/usr/src/lib/libiscsitgt/common/xml.c b/usr/src/lib/libiscsitgt/common/xml.c
deleted file mode 100644
index 3441bf2a42..0000000000
--- a/usr/src/lib/libiscsitgt/common/xml.c
+++ /dev/null
@@ -1,914 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <inttypes.h>
-#include <assert.h>
-#include <libxml/xmlreader.h>
-#include <strings.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <sys/stat.h>
-
-#include "iscsitgt_impl.h"
-
-/*
- * Forward declarations
- */
-static char *strip_space(char *value);
-static tgt_node_t *node_alloc();
-static void node_free(tgt_node_t *x);
-static Boolean_t node_name(tgt_node_t *x, const xmlChar *n);
-static Boolean_t node_value(tgt_node_t *x, const xmlChar *n, Boolean_t s);
-static tgt_node_t *node_parent(tgt_node_t *x);
-static tgt_node_t *node_child(tgt_node_t *x);
-static tgt_node_t *node_alloc_attr(tgt_node_t *x);
-static void buf_add_node_attr(char **b, tgt_node_t *x);
-static void buf_add_comment(char **b, char *comment);
-static void buf_add_str(char **b, char *str);
-
-#define XML_COMMENT_STR "!--"
-#define XML_COMMENT_END "--"
-
-void
-tgt_node_free(tgt_node_t *n)
-{
- tgt_node_t *c;
- tgt_node_t *c1;
-
- if (n == NULL)
- return;
- for (c = n->x_child; c; ) {
- c1 = c->x_sibling;
- tgt_node_free(c);
- c = c1;
- }
- for (c = n->x_attr; c; ) {
- c1 = c->x_sibling;
- node_free(c);
- c = c1;
- }
- node_free(n);
-
-}
-
-/*
- * tgt_dump2buf -- dumps node tree to buffer, allocating memory as it goes
- *
- * It is up to the caller, when finished with 'buf', to call free()
- */
-void
-tgt_dump2buf(tgt_node_t *n, char **buf)
-{
- tgt_node_t *c;
-
- if (n == NULL)
- return;
- if (strcmp(n->x_name, XML_COMMENT_STR) == 0) {
- buf_add_comment(buf, n->x_value);
- return;
- }
- buf_add_node_attr(buf, n);
- if (n->x_value != NULL)
- tgt_buf_add_tag(buf, n->x_value, Tag_String);
- for (c = n->x_child; c; c = c->x_sibling)
- tgt_dump2buf(c, buf);
- tgt_buf_add_tag(buf, n->x_name, Tag_End);
-}
-
-char *common_attr_list[] = {
- XML_ELEMENT_NAME,
- XML_ELEMENT_VERS,
- XML_ELEMENT_INCORE,
- 0
-};
-
-Boolean_t
-tgt_node_process(xmlTextReaderPtr r, tgt_node_t **node)
-{
- const xmlChar *name;
- const xmlChar *value;
- char **ap;
- xmlElementType node_type;
- tgt_node_t *n;
- tgt_node_t *an;
-
- n = *node;
- if (n == NULL) {
- n = node_alloc();
- if (n == NULL)
- return (False);
- *node = n;
- }
-
- name = (xmlChar *)xmlTextReaderConstName(r);
- if (name == NULL) {
- node_free(n);
- *node = NULL;
- return (False);
- }
-
- node_type = (xmlElementType)xmlTextReaderNodeType(r);
-
- value = (xmlChar *)xmlTextReaderConstValue(r);
-
- if (node_type == XML_ELEMENT_NODE) {
- if (n->x_state != NodeAlloc) {
- n = node_child(n);
- *node = n;
- if (n == NULL)
- return (False);
- }
- if (xmlTextReaderAttributeCount(r) > 0) {
-
- for (ap = common_attr_list; *ap; ap++) {
- value = xmlTextReaderGetAttribute(r,
- (xmlChar *)*ap);
-
- if (value != NULL) {
- if ((an = node_alloc_attr(n)) == NULL)
- return (False);
- if (node_name(an, (xmlChar *)*ap) ==
- False) {
- node_free(an);
- return (False);
- }
- if (node_value(an, value, True) ==
- False) {
- node_free(an);
- return (False);
- }
- free((char *)value);
- }
- }
- }
-
- if (node_name(n, name) == False) {
- node_free(n);
- *node = NULL;
- return (False);
- }
- } else if ((value != NULL) && (node_type == XML_TEXT_NODE)) {
- if (node_value(n, value, True) == False) {
- node_free(n);
- *node = NULL;
- return (False);
- }
- } else if (node_type == XML_ELEMENT_DECL) {
- n = node_parent(n);
- if (n == NULL)
- return (False);
- *node = n;
- } else if (node_type == XML_COMMENT_NODE) {
- n = node_child(n);
- if (node_name(n, (xmlChar *)XML_COMMENT_STR) == False) {
- node_free(n);
- *node = NULL;
- return (False);
- }
- if (node_value(n, (xmlChar *)value, False) == False) {
- node_free(n);
- *node = NULL;
- return (False);
- }
- } else if (node_type != XML_DTD_NODE) {
- node_free(n);
- *node = NULL;
- return (False);
- }
- return (True);
-}
-
-Boolean_t
-tgt_find_attr_str(tgt_node_t *n, char *attr, char **value)
-{
- tgt_node_t *a;
-
- if ((n == NULL) || (n->x_attr == NULL))
- return (False);
-
- for (a = n->x_attr; a; a = a->x_sibling)
- if (strcmp(a->x_name, attr) == 0) {
- *value = a->x_value ? strdup(a->x_value) : NULL;
- return (True);
- }
- return (False);
-}
-
-Boolean_t
-tgt_find_value_str(tgt_node_t *n, char *name, char **value)
-{
- tgt_node_t *c;
-
- if ((n == NULL) || (n->x_name == NULL))
- return (False);
-
- if (strcmp(n->x_name, name) == 0) {
- *value = n->x_value ? strdup(n->x_value) : NULL;
- return (True);
- }
- for (c = n->x_child; c; c = c->x_sibling) {
- if (tgt_find_value_str(c, name, value) == True)
- return (True);
- }
- return (False);
-}
-
-Boolean_t
-tgt_find_value_int(tgt_node_t *n, char *name, int *value)
-{
- tgt_node_t *c;
-
- if ((n == NULL) || (n->x_name == NULL))
- return (False);
-
- if (strcmp(n->x_name, name) == 0) {
- if (n->x_value == NULL)
- return (False);
- *value = strtol(n->x_value, NULL, 0);
- return (True);
- }
- for (c = n->x_child; c; c = c->x_sibling) {
- if (tgt_find_value_int(c, name, value) == True)
- return (True);
- }
- return (False);
-}
-
-/*
- * []----
- * | xml_find_value_intchk -- if node exists, check to see if value is okay
- * []----
- */
-Boolean_t
-tgt_find_value_intchk(tgt_node_t *n, char *name, int *value)
-{
- char *str;
- char chk[32];
- Boolean_t rval;
-
- if (tgt_find_value_str(n, name, &str) == True) {
-
- *value = strtol(str, NULL, 0);
- /*
- * Validate that the input string hasn't overrun what
- * what an integer can handle. This is done by simply
- * printing out the result of the conversion into a buffer
- * and comparing it to the incoming string. That way when
- * someone enters 4294967296 which strtol returns as 0
- * we'll catch it.
- */
- if ((str[0] == '0') && (str[1] != '\0')) {
- if (str[1] == 'x')
- (void) snprintf(chk, sizeof (chk), "0x%x",
- *value);
- else if (str[1] == 'X')
- (void) snprintf(chk, sizeof (chk), "0X%x",
- *value);
- else
- (void) snprintf(chk, sizeof (chk), "0%o",
- *value);
- } else
- (void) snprintf(chk, sizeof (chk), "%d", *value);
- if (strcmp(chk, str) == 0)
- rval = True;
- else
- rval = False;
- free(str);
- return (rval);
- } else
- return (True);
-}
-
-Boolean_t
-tgt_find_value_boolean(tgt_node_t *n, char *name, Boolean_t *value)
-{
- tgt_node_t *c;
-
- if ((n == NULL) || (n->x_name == NULL))
- return (False);
-
- if (strcmp(n->x_name, name) == 0) {
- if (n->x_value == NULL)
- return (False);
- *value = strcmp(n->x_value, "true") == 0 ? True : False;
- return (True);
- }
- for (c = n->x_child; c; c = c->x_sibling) {
- if (tgt_find_value_boolean(c, name, value) == True)
- return (True);
- }
- return (False);
-}
-
-tgt_node_t *
-tgt_node_next(tgt_node_t *n, char *name, tgt_node_t *cur)
-{
- tgt_node_t *x;
- tgt_node_t *p;
-
- if (n == NULL)
- return (NULL);
-
- if (cur != NULL) {
- for (x = cur->x_sibling; x; x = x->x_sibling)
- if (strcmp(x->x_name, name) == 0)
- return (x);
- return (NULL);
- }
-
- if (n->x_name == NULL)
- return (NULL);
-
- if (strcmp(n->x_name, name) == 0)
- return (n);
- for (x = n->x_child; x; x = x->x_sibling)
- if ((p = tgt_node_next(x, name, 0)) != NULL)
- return (p);
- return (NULL);
-}
-
-tgt_node_t *
-tgt_node_next_child(tgt_node_t *n, char *name, tgt_node_t *cur)
-{
- if (cur != NULL) {
- n = cur->x_sibling;
- } else {
- if (n != NULL)
- n = n->x_child;
- else
- return (NULL);
- }
- while (n) {
- if (strcmp(n->x_name, name) == 0)
- return (n);
- n = n->x_sibling;
- }
- return (NULL);
-}
-
-void
-tgt_node_add(tgt_node_t *p, tgt_node_t *c)
-{
- if ((p == NULL) || (c == NULL))
- return;
-
- c->x_parent = p;
- if (p->x_child == NULL)
- p->x_child = c;
- else {
- c->x_sibling = p->x_child;
- p->x_child = c;
- }
-}
-
-void
-tgt_node_add_attr(tgt_node_t *p, tgt_node_t *a)
-{
- if ((p == NULL) || (a == NULL))
- return;
-
- if (p->x_attr == NULL)
- p->x_attr = a;
- else {
- a->x_sibling = p->x_attr;
- p->x_attr = a;
- }
-}
-
-tgt_node_t *
-tgt_node_alloc(char *name, xml_val_type_t type, void *value)
-{
- tgt_node_t *d = node_alloc();
- int value_len = 0;
- char *value_str = NULL;
-
- if (d == NULL)
- return (NULL);
- switch (type) {
- case String:
- if (value)
- value_len = strlen((char *)value) + 1;
- break;
- case Int:
- value_len = sizeof (int) * 2 + 3;
- break;
- case Uint64:
- value_len = sizeof (uint64_t) * 2 + 3;
- break;
- }
- if (value_len &&
- (value_str = (char *)calloc(sizeof (char), value_len)) == NULL)
- return (NULL);
- if (node_name(d, (xmlChar *)name) == False) {
- free(value_str);
- return (NULL);
- }
- if (value_str) {
- switch (type) {
- case String:
- (void) snprintf(value_str, value_len, "%s",
- (char *)value);
- break;
- case Int:
- (void) snprintf(value_str, value_len, "%d",
- *(int *)value);
- break;
- case Uint64:
- (void) snprintf(value_str, value_len, "0x%llx",
- *(uint64_t *)value);
- break;
- }
- }
- (void) node_value(d, (xmlChar *)value_str, True);
- free(value_str);
-
- return (d);
-}
-
-Boolean_t
-tgt_xml_encode(uint8_t *ip, size_t ip_size, char **buf, size_t *buf_size)
-{
- char *bp;
- *buf_size = (ip_size * 2) + 1;
-
- if ((*buf = (char *)malloc(*buf_size)) == NULL) {
- *buf_size = 0;
- return (False);
- }
-
- for (bp = *buf; ip_size; ip_size--) {
- (void) sprintf(bp, "%.2x", *ip);
- ip++;
- bp += 2;
- }
-
- /* make it null terminated */
- *bp = 0;
-
- return (True);
-}
-
-Boolean_t
-tgt_xml_decode(char *buf, uint8_t **ip, size_t *ip_size)
-{
- uint8_t *i;
- size_t buf_size = strlen(buf);
- *ip_size = buf_size / 2;
-
- if ((*ip = (uint8_t *)malloc(*ip_size)) == NULL) {
- *ip_size = 0;
- return (False);
- }
-
- for (i = *ip; buf_size; buf_size -= 2) {
- char x[3];
- bcopy(buf, x, 2);
- x[2] = 0;
- *i++ = strtol(x, NULL, 16);
- buf += 2;
- }
- return (True);
-}
-
-Boolean_t
-tgt_node_remove(tgt_node_t *parent, tgt_node_t *child, match_type_t m)
-{
- tgt_node_t *s;
- tgt_node_t *c = NULL;
-
- if ((parent == NULL) || (child == NULL))
- return (False);
-
- for (s = parent->x_child; s; c = s, s = s->x_sibling) {
-
- /*
- * See if the new child node matches one of the children
- * in the parent.
- */
- if ((strcmp(s->x_name, child->x_name) == 0) &&
- ((m == MatchName) || (strcmp(s->x_value,
- child->x_value) == 0))) {
-
- if (parent->x_child == s) {
- parent->x_child = s->x_sibling;
- } else {
- c->x_sibling = s->x_sibling;
- }
- tgt_node_free(s);
- break;
- }
- }
- if (s == NULL)
- return (False);
- else
- return (True);
-}
-
-void
-tgt_node_replace(tgt_node_t *parent, tgt_node_t *child, match_type_t m)
-{
- tgt_node_t *s;
- tgt_node_t *c;
-
- if ((parent == NULL) || (child == NULL))
- return;
-
- for (s = parent->x_child; s; s = s->x_sibling) {
-
- /*
- * See if the new child node matches one of the children
- * in the parent.
- */
- if ((strcmp(s->x_name, child->x_name) == 0) &&
- ((m == MatchName) || (strcmp(s->x_value,
- child->x_value) == 0))) {
-
- /*
- * We have a match. Now save the values of the new
- * child in this current node.
- */
- free(s->x_name);
- free(s->x_value);
- s->x_name = strdup(child->x_name);
- s->x_value = strdup(child->x_value);
- if (s->x_child) {
- tgt_node_free(s->x_child);
- s->x_child = NULL;
- }
- for (c = child->x_child; c; c = c->x_sibling)
- (void) tgt_node_add(s, tgt_node_dup(c));
- break;
- }
- }
-
- if (s == NULL) {
- /*
- * Never found the child so add it
- */
- (void) tgt_node_add(parent, tgt_node_dup(child));
- }
-}
-
-Boolean_t
-tgt_update_value_str(tgt_node_t *node, char *name, char *str)
-{
- if ((node == NULL) || (strcmp(name, node->x_name) != 0))
- return (False);
- if (node->x_value != NULL)
- free(node->x_value);
- node->x_value = strdup(str);
- node->x_state = NodeValue;
- return (True);
-}
-
-tgt_node_t *
-tgt_node_find(tgt_node_t *n, char *name)
-{
- tgt_node_t *rval;
-
- for (rval = n->x_child; rval; rval = rval->x_sibling)
- if (strcmp(rval->x_name, name) == 0)
- break;
- return (rval);
-}
-
-tgt_node_t *
-tgt_node_dup(tgt_node_t *n)
-{
- tgt_node_t *d = node_alloc();
- tgt_node_t *c;
-
- if (d == NULL)
- return (NULL);
- if (node_name(d, (xmlChar *)n->x_name) == False)
- return (NULL);
- if (n->x_value && (node_value(d, (xmlChar *)n->x_value, True) == False))
- return (NULL);
- for (c = n->x_child; c; c = c->x_sibling)
- (void) tgt_node_add(d, tgt_node_dup(c));
- for (c = n->x_attr; c; c = c->x_sibling)
- (void) tgt_node_add_attr(d, tgt_node_dup(c));
- return (d);
-}
-
-#define MAX_REPLACEMENT_ENTITY 8
-#define MAX_REPLACEMENT_BUFFER 1024
-void
-tgt_buf_add(char **b, char *element, const char *cdata)
-{
- char entity[MAX_REPLACEMENT_ENTITY];
- char buf[MAX_REPLACEMENT_BUFFER];
- int len, i;
-
- bzero(buf, sizeof (buf));
-
- tgt_buf_add_tag(b, element, Tag_Start);
- /*
- * we have to transform the predefined xml entities;
- */
- if (cdata != NULL) {
- len = strlen(cdata);
- for (i = 0; i < len; i++) {
- switch (cdata[i]) {
- case '&':
- (void) strcpy(entity, "&amp;");
- break;
- case '<':
- (void) strcpy(entity, "&lt;");
- break;
- case '>':
- (void) strcpy(entity, "&gt;");
- break;
- case '\'':
- (void) strcpy(entity, "&apos;");
- break;
- case '"':
- (void) strcpy(entity, "&quot;");
- break;
- default:
- entity[0] = cdata[i];
- entity[1] = '\0';
- break;
- }
- (void) strlcat(buf, entity, sizeof (buf));
- }
- tgt_buf_add_tag(b, buf, Tag_String);
- }
- tgt_buf_add_tag(b, element, Tag_End);
-}
-
-/*
- * []----
- * | tgt_buf_add_tag -- adds string to buffer allocating space, sets up tags too
- * |
- * | Helper function to build a string by allocating memory as we go.
- * | If the string argument 'str' is defined to be a start or end tag
- * | as declared by 'type' argument add the appropriate characters.
- * []----
- */
-void
-tgt_buf_add_tag(char **b, const char *str, val_type_t type)
-{
- char *buf;
- int len;
-
- /*
- * We will add potentially up to 3 extra characters plus the NULL byte
- */
- len = strlen(str) + 4;
- if ((buf = malloc(len)) == NULL)
- return;
-
- (void) snprintf(buf, len, "%s%s%s%s", type == Tag_String ? "" : "<",
- type == Tag_End ? "/" : "", str, type == Tag_String ? "" : ">");
- buf_add_str(b, buf);
- free(buf);
-}
-
-/*
- * []----
- * | tgt_buf_add_tag_and_attr -- variant on tgt_buf_add_tag which also gives
- * | attr
- * []----
- */
-void
-tgt_buf_add_tag_and_attr(char **b, char *str, char *attr)
-{
- char *buf;
- int len;
-
- /*
- * In addition to the 'str' and 'attr' strings the code will add
- * three characters plus a null byte.
- */
- len = strlen(str) + strlen(attr) + 4;
- if ((buf = malloc(len)) == NULL)
- return;
-
- (void) snprintf(buf, len, "<%s %s>", str, attr);
- buf_add_str(b, buf);
- free(buf);
-}
-
-/*
- * []----
- * | Utility functions
- * []----
- */
-static tgt_node_t *
-node_alloc()
-{
- tgt_node_t *x = (tgt_node_t *)calloc(sizeof (tgt_node_t), 1);
-
- if (x == NULL)
- return (NULL);
-
- x->x_state = NodeAlloc;
- return (x);
-}
-
-static void
-node_free(tgt_node_t *x)
-{
- x->x_state = NodeFree;
- if (x->x_name)
- free(x->x_name);
- if (x->x_value)
- free(x->x_value);
- free(x);
-}
-
-static Boolean_t
-node_name(tgt_node_t *x, const xmlChar *n)
-{
- assert(x->x_state == NodeAlloc);
- if ((n == NULL) || (strlen((char *)n) == 0))
- return (False);
-
- x->x_state = NodeName;
- x->x_name = strip_space((char *)n);
- return (True);
-}
-
-static Boolean_t
-node_value(tgt_node_t *x, const xmlChar *n, Boolean_t do_strip)
-{
- assert(x->x_state == NodeName);
- if ((n == NULL) || (strlen((char *)n) == NULL))
- return (False);
-
- x->x_state = NodeValue;
- x->x_value = (do_strip == True) ?
- strip_space((char *)n) : strdup((char *)n);
- return (True);
-}
-
-static tgt_node_t *
-node_parent(tgt_node_t *x)
-{
- return (x->x_parent);
-}
-
-static tgt_node_t *
-node_child(tgt_node_t *x)
-{
- tgt_node_t *n;
-
- if ((n = node_alloc()) == NULL)
- return (NULL);
-
- if (x->x_child == NULL) {
- x->x_child = n;
- } else {
- n->x_sibling = x->x_child;
- x->x_child = n;
- }
- n->x_parent = x;
- return (n);
-}
-
-static tgt_node_t *
-node_alloc_attr(tgt_node_t *x)
-{
- tgt_node_t *n;
- tgt_node_t *next;
-
- n = node_alloc();
- if (x->x_attr == NULL) {
- x->x_attr = n;
- } else {
- for (next = x->x_attr; next->x_sibling; next = next->x_sibling)
- ;
- next->x_sibling = n;
- }
- if (n != NULL)
- n->x_parent = x;
- return (n);
-}
-
-static void
-buf_add_str(char **b, char *str)
-{
- int len;
- int olen = 0;
- char *p = *b;
-
- /*
- * Make sure we have enough room for the string and tag characters
- * plus a NULL byte.
- */
- if (str == NULL)
- return;
-
- len = strlen(str) + 1;
- if (p == NULL) {
- if ((p = malloc(len)) == NULL)
- return;
- } else {
- olen = strlen(p);
- p = realloc(p, olen + len);
- }
- (void) strncpy(p + olen, str, len);
- *b = p;
-}
-
-static void
-buf_add_node_attr(char **b, tgt_node_t *x)
-{
- char *buf;
- tgt_node_t *n;
- int len;
-
- /* ---- null byte and starting '<' character ---- */
- len = strlen(x->x_name) + 2;
- if ((buf = malloc(len)) == NULL)
- return;
- (void) snprintf(buf, len, "<%s", x->x_name);
- buf_add_str(b, buf);
- free(buf);
-
- for (n = x->x_attr; n; n = n->x_sibling) {
- len = strlen(n->x_name) + strlen(n->x_value) + 5;
- if ((buf = malloc(len)) == NULL)
- return;
- (void) snprintf(buf, len, " %s='%s'", n->x_name, n->x_value);
- buf_add_str(b, buf);
- free(buf);
- }
- buf_add_str(b, ">");
-}
-
-static void
-buf_add_comment(char **b, char *comment)
-{
- char *p = *b;
- int len;
- int olen;
-
- if (comment == NULL)
- return;
-
- /*
- * Room for the strings, plus the brackets and NULL byte
- */
- len = strlen(comment) + strlen(XML_COMMENT_STR) +
- strlen(XML_COMMENT_END) + 3;
-
- if (p == NULL)
- p = malloc(len);
- else {
- olen = strlen(p);
- p = realloc(p, olen + len);
- }
- (void) snprintf(p + olen, len, "<%s%s%s>", XML_COMMENT_STR, comment,
- XML_COMMENT_END);
- *b = p;
-}
-
-static char *
-strip_space(char *value)
-{
- char *p;
- char *n;
-
- for (p = value; p && *p; p++)
- if (!isspace(*p))
- break;
- if ((p == NULL) || (*p == '\0'))
- return (NULL);
-
- p = strdup(p);
- for (n = (p + strlen(p) - 1); n >= p; n--)
- if (!isspace(*n)) {
- n++;
- break;
- }
- *n = '\0';
- return (p);
-}
diff --git a/usr/src/lib/libiscsitgt/i386/Makefile b/usr/src/lib/libiscsitgt/i386/Makefile
deleted file mode 100644
index a333224278..0000000000
--- a/usr/src/lib/libiscsitgt/i386/Makefile
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
-#
-
-include ../Makefile.com
-
-install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libiscsitgt/sparc/Makefile b/usr/src/lib/libiscsitgt/sparc/Makefile
deleted file mode 100644
index a333224278..0000000000
--- a/usr/src/lib/libiscsitgt/sparc/Makefile
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
-#
-
-include ../Makefile.com
-
-install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libiscsitgt/sparcv9/Makefile b/usr/src/lib/libiscsitgt/sparcv9/Makefile
deleted file mode 100644
index 2e8cdecf75..0000000000
--- a/usr/src/lib/libiscsitgt/sparcv9/Makefile
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
-#
-
-include ../Makefile.com
-include ../../Makefile.lib.64
-
-install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/libsecdb/auth_attr.txt b/usr/src/lib/libsecdb/auth_attr.txt
index 84dee31da3..0a10c10a11 100644
--- a/usr/src/lib/libsecdb/auth_attr.txt
+++ b/usr/src/lib/libsecdb/auth_attr.txt
@@ -201,11 +201,7 @@ solaris.system.power.cpu:::Manage CPU related power::help=SysCpuPowerMgmt.html
solaris.system.sysevent.read:::Retrieve Sysevents::help=SysSyseventRead.html
solaris.system.sysevent.write:::Publish Sysevents::help=SysSyseventWrite.html
#
-solaris.smf.manage.iscsitgt:::Manage ISCSI Target Service States::help=SmfValueIscsitgt.html
-solaris.smf.read.iscsitgt:::Read ISCSI Target secrets::help=SmfValueIscsitgt.html
-solaris.smf.modify.iscsitgt:::Add/Remove Values of ISCSI Target Service Properties::help=SmfValueIscsitgt.html
solaris.smf.modify.stmf:::Modify STMF Properties::help=SmfSTMFValue.html
-solaris.smf.value.iscsitgt:::Change Values of ISCSI Target Service Properties::help=SmfValueIscsitgt.html
#
solaris.smf.manage.mms:::Manage MMS Service States::help=SmfManageMMS.html
solaris.smf.value.mms:::Change Values of MMS Service Properties::help=SmfValueMMS.html
diff --git a/usr/src/lib/libsecdb/exec_attr.txt b/usr/src/lib/libsecdb/exec_attr.txt
index c660d44510..d6258a1e2c 100644
--- a/usr/src/lib/libsecdb/exec_attr.txt
+++ b/usr/src/lib/libsecdb/exec_attr.txt
@@ -90,7 +90,6 @@ File System Management:suser:cmd:::/usr/sbin/fsdb:euid=0
File System Management:suser:cmd:::/usr/sbin/fstyp:euid=0
File System Management:suser:cmd:::/usr/sbin/fuser:euid=0
File System Management:solaris:cmd:::/usr/sbin/iscsiadm:euid=0;privs=basic
-File System Management:solaris:cmd:::/usr/sbin/iscsitadm:euid=0;privs=basic
File System Management:suser:cmd:::/usr/sbin/mkfile:euid=0
File System Management:suser:cmd:::/usr/sbin/mkfs:euid=0
File System Management:suser:cmd:::/usr/sbin/mount:uid=0
diff --git a/usr/src/lib/libsecdb/help/auths/Makefile b/usr/src/lib/libsecdb/help/auths/Makefile
index b56ddefdd6..cb9361c94e 100644
--- a/usr/src/lib/libsecdb/help/auths/Makefile
+++ b/usr/src/lib/libsecdb/help/auths/Makefile
@@ -106,7 +106,6 @@ HTMLENTS = \
SmfValueHeader.html \
SmfValueInetd.html \
SmfValueIPsec.html \
- SmfValueIscsitgt.html \
SmfValueMDNS.html \
SmfValueNADD.html \
SmfValueNDMP.html \
diff --git a/usr/src/lib/libsecdb/prof_attr.txt b/usr/src/lib/libsecdb/prof_attr.txt
index 28d0107d29..a8d5fc56b6 100644
--- a/usr/src/lib/libsecdb/prof_attr.txt
+++ b/usr/src/lib/libsecdb/prof_attr.txt
@@ -110,8 +110,6 @@ WUSB Management:::Manage Wireless USB:auths=solaris.admin.wusb.*,solaris.smf.man
Information Security:::Maintains MAC and DAC security policies:profiles=Device Security,File System Security,Name Service Security,Network Security,Object Access Management,Object Label Management;help=RtInfoSec.html
Object Label Management:::Change labels on files.:auths=solaris.device.allocate,solaris.label.file.downgrade,solaris.label.win.downgrade,solaris.label.win.upgrade,solaris.label.file.upgrade,solaris.label.range,solaris.smf.manage.labels;help=RtObjectLabelMngmnt.html
Outside Accred:::Allow a user to operate outside the user accreditation range.:auths=solaris.label.range;help=RtOutsideAccred.html
-ISCSI Target Administration:::Configure ISCSI Target service:auths=solaris.smf.modify.iscsitgt,solaris.smf.read.iscsitgt,solaris.smf.value.iscsitgt
-ISCSI Target Management:::Start/Stop ISCSI Target service:auths=solaris.smf.manage.iscsitgt
#
# Power Management profiles:
#
diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h
index b3123ad38a..7a8d3d769a 100644
--- a/usr/src/lib/libzfs/common/libzfs.h
+++ b/usr/src/lib/libzfs/common/libzfs.h
@@ -93,8 +93,6 @@ enum {
EZFS_INVALCONFIG, /* invalid vdev configuration */
EZFS_RECURSIVE, /* recursive dependency */
EZFS_NOHISTORY, /* no history object */
- EZFS_UNSHAREISCSIFAILED, /* iscsitgtd failed request to unshare */
- EZFS_SHAREISCSIFAILED, /* iscsitgtd failed request to share */
EZFS_POOLPROPS, /* couldn't retrieve pool props */
EZFS_POOL_NOTSUP, /* ops not supported for this type of pool */
EZFS_POOL_INVALARG, /* invalid argument for this pool operation */
@@ -102,7 +100,6 @@ enum {
EZFS_OPENFAILED, /* open of device failed */
EZFS_NOCAP, /* couldn't get capacity */
EZFS_LABELFAILED, /* write of label failed */
- EZFS_ISCSISVCUNAVAIL, /* iscsi service unavailable */
EZFS_BADWHO, /* invalid permission who */
EZFS_BADPERM, /* invalid permission */
EZFS_BADPERMSET, /* invalid permission set name */
@@ -621,10 +618,6 @@ extern int zfs_unshareall_nfs(zfs_handle_t *);
extern int zfs_unshareall_smb(zfs_handle_t *);
extern int zfs_unshareall_bypath(zfs_handle_t *, const char *);
extern int zfs_unshareall(zfs_handle_t *);
-extern boolean_t zfs_is_shared_iscsi(zfs_handle_t *);
-extern int zfs_share_iscsi(zfs_handle_t *);
-extern int zfs_unshare_iscsi(zfs_handle_t *);
-extern int zfs_iscsi_perm_check(libzfs_handle_t *, char *, ucred_t *);
extern int zfs_deleg_share_nfs(libzfs_handle_t *, char *, char *, char *,
void *, void *, int, zfs_share_op_t);
diff --git a/usr/src/lib/libzfs/common/libzfs_changelist.c b/usr/src/lib/libzfs/common/libzfs_changelist.c
index c970d1e488..4328d38a2c 100644
--- a/usr/src/lib/libzfs/common/libzfs_changelist.c
+++ b/usr/src/lib/libzfs/common/libzfs_changelist.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Portions Copyright 2007 Ramprakash Jelari
@@ -116,22 +116,7 @@ changelist_prefix(prop_changelist_t *clp)
if (getzoneid() == GLOBAL_ZONEID && cn->cn_zoned)
continue;
- if (ZFS_IS_VOLUME(cn->cn_handle)) {
- switch (clp->cl_realprop) {
- case ZFS_PROP_NAME:
- /* If this was a rename, unshare the zvol */
- (void) zfs_unshare_iscsi(cn->cn_handle);
- break;
-
- case ZFS_PROP_VOLSIZE:
- /*
- * If this was a change to the volume size, we
- * need to unshare and reshare the volume.
- */
- (void) zfs_unshare_iscsi(cn->cn_handle);
- break;
- }
- } else {
+ if (!ZFS_IS_VOLUME(cn->cn_handle)) {
/*
* Do the property specific processing.
*/
@@ -224,24 +209,8 @@ changelist_postfix(prop_changelist_t *clp)
zfs_refresh_properties(cn->cn_handle);
- if (ZFS_IS_VOLUME(cn->cn_handle)) {
- if (cn->cn_shared ||
- clp->cl_prop == ZFS_PROP_SHAREISCSI) {
- if (zfs_prop_get(cn->cn_handle,
- ZFS_PROP_SHAREISCSI, shareopts,
- sizeof (shareopts), NULL, NULL, 0,
- B_FALSE) == 0 &&
- strcmp(shareopts, "off") == 0) {
- errors +=
- zfs_unshare_iscsi(cn->cn_handle);
- } else {
- errors +=
- zfs_share_iscsi(cn->cn_handle);
- }
- }
-
+ if (ZFS_IS_VOLUME(cn->cn_handle))
continue;
- }
/*
* Remount if previously mounted or mountpoint was legacy,
@@ -640,8 +609,7 @@ changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int gather_flags,
if (clp->cl_prop != ZFS_PROP_MOUNTPOINT &&
clp->cl_prop != ZFS_PROP_SHARENFS &&
- clp->cl_prop != ZFS_PROP_SHARESMB &&
- clp->cl_prop != ZFS_PROP_SHAREISCSI)
+ clp->cl_prop != ZFS_PROP_SHARESMB)
return (clp);
/*
diff --git a/usr/src/lib/libzfs/common/libzfs_dataset.c b/usr/src/lib/libzfs/common/libzfs_dataset.c
index e9725e96b4..773e05896a 100644
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c
@@ -938,19 +938,6 @@ zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
}
break;
- case ZFS_PROP_SHAREISCSI:
- if (strcmp(strval, "off") != 0 &&
- strcmp(strval, "on") != 0 &&
- strcmp(strval, "type=disk") != 0) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "'%s' must be 'on', 'off', or 'type=disk'"),
- propname);
- (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
- goto error;
- }
-
- break;
-
case ZFS_PROP_MLSLABEL:
{
/*
@@ -1318,6 +1305,14 @@ zfs_setprop_error(libzfs_handle_t *hdl, zfs_prop_t prop, int err,
}
break;
+ case EINVAL:
+ if (prop == ZPROP_INVAL) {
+ (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
+ } else {
+ (void) zfs_standard_error(hdl, err, errbuf);
+ }
+ break;
+
case EOVERFLOW:
/*
* This platform can't address a volume this big.
@@ -2936,15 +2931,6 @@ zfs_destroy(zfs_handle_t *zhp, boolean_t defer)
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
if (ZFS_IS_VOLUME(zhp)) {
- /*
- * If user doesn't have permissions to unshare volume, then
- * abort the request. This would only happen for a
- * non-privileged user.
- */
- if (zfs_unshare_iscsi(zhp) != 0) {
- return (-1);
- }
-
zc.zc_objset_type = DMU_OST_ZVOL;
} else {
zc.zc_objset_type = DMU_OST_ZFS;
@@ -3740,52 +3726,6 @@ zfs_expand_proplist(zfs_handle_t *zhp, zprop_list_t **plp, boolean_t received)
}
int
-zfs_iscsi_perm_check(libzfs_handle_t *hdl, char *dataset, ucred_t *cred)
-{
- zfs_cmd_t zc = { 0 };
- nvlist_t *nvp;
- gid_t gid;
- uid_t uid;
- const gid_t *groups;
- int group_cnt;
- int error;
-
- if (nvlist_alloc(&nvp, NV_UNIQUE_NAME, 0) != 0)
- return (no_memory(hdl));
-
- uid = ucred_geteuid(cred);
- gid = ucred_getegid(cred);
- group_cnt = ucred_getgroups(cred, &groups);
-
- if (uid == (uid_t)-1 || gid == (uid_t)-1 || group_cnt == (uid_t)-1)
- return (1);
-
- if (nvlist_add_uint32(nvp, ZFS_DELEG_PERM_UID, uid) != 0) {
- nvlist_free(nvp);
- return (1);
- }
-
- if (nvlist_add_uint32(nvp, ZFS_DELEG_PERM_GID, gid) != 0) {
- nvlist_free(nvp);
- return (1);
- }
-
- if (nvlist_add_uint32_array(nvp,
- ZFS_DELEG_PERM_GROUPS, (uint32_t *)groups, group_cnt) != 0) {
- nvlist_free(nvp);
- return (1);
- }
- (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
-
- if (zcmd_write_src_nvlist(hdl, &zc, nvp))
- return (-1);
-
- error = ioctl(hdl->libzfs_fd, ZFS_IOC_ISCSI_PERM_CHECK, &zc);
- nvlist_free(nvp);
- return (error);
-}
-
-int
zfs_deleg_share_nfs(libzfs_handle_t *hdl, char *dataset, char *path,
char *resource, void *export, void *sharetab,
int sharemax, zfs_share_op_t operation)
diff --git a/usr/src/lib/libzfs/common/libzfs_impl.h b/usr/src/lib/libzfs/common/libzfs_impl.h
index ef34591fe3..fabd454de8 100644
--- a/usr/src/lib/libzfs/common/libzfs_impl.h
+++ b/usr/src/lib/libzfs/common/libzfs_impl.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -128,7 +128,6 @@ typedef enum {
*/
typedef enum {
SHARED_NOT_SHARED = 0x0,
- SHARED_ISCSI = 0x1,
SHARED_NFS = 0x2,
SHARED_SMB = 0x4
} zfs_share_type_t;
diff --git a/usr/src/lib/libzfs/common/libzfs_mount.c b/usr/src/lib/libzfs/common/libzfs_mount.c
index 8392fc9fb1..c225ad562a 100644
--- a/usr/src/lib/libzfs/common/libzfs_mount.c
+++ b/usr/src/lib/libzfs/common/libzfs_mount.c
@@ -44,17 +44,14 @@
*
* zfs_is_shared_nfs()
* zfs_is_shared_smb()
- * zfs_is_shared_iscsi()
* zfs_share_proto()
* zfs_shareall();
- * zfs_share_iscsi()
* zfs_unshare_nfs()
* zfs_unshare_smb()
* zfs_unshareall_nfs()
* zfs_unshareall_smb()
* zfs_unshareall()
* zfs_unshareall_bypath()
- * zfs_unshare_iscsi()
*
* The following functions are available for pool consumers, and will
* mount/unmount and share/unshare all datasets within pool:
@@ -89,11 +86,6 @@ static int zfs_share_proto(zfs_handle_t *, zfs_share_proto_t *);
zfs_share_type_t zfs_is_shared_proto(zfs_handle_t *, char **,
zfs_share_proto_t);
-static int (*iscsitgt_zfs_share)(const char *);
-static int (*iscsitgt_zfs_unshare)(const char *);
-static int (*iscsitgt_zfs_is_shared)(const char *);
-static int (*iscsitgt_svc_online)();
-
/*
* The share protocols table must be in the same order as the zfs_share_prot_t
* enum in libzfs_impl.h
@@ -125,29 +117,6 @@ zfs_share_proto_t share_all_proto[] = {
PROTO_END
};
-#pragma init(zfs_iscsi_init)
-static void
-zfs_iscsi_init(void)
-{
- void *libiscsitgt;
-
- if ((libiscsitgt = dlopen("/lib/libiscsitgt.so.1",
- RTLD_LAZY | RTLD_GLOBAL)) == NULL ||
- (iscsitgt_zfs_share = (int (*)(const char *))dlsym(libiscsitgt,
- "iscsitgt_zfs_share")) == NULL ||
- (iscsitgt_zfs_unshare = (int (*)(const char *))dlsym(libiscsitgt,
- "iscsitgt_zfs_unshare")) == NULL ||
- (iscsitgt_zfs_is_shared = (int (*)(const char *))dlsym(libiscsitgt,
- "iscsitgt_zfs_is_shared")) == NULL ||
- (iscsitgt_svc_online = (int (*)(const char *))dlsym(libiscsitgt,
- "iscsitgt_svc_online")) == NULL) {
- iscsitgt_zfs_share = NULL;
- iscsitgt_zfs_unshare = NULL;
- iscsitgt_zfs_is_shared = NULL;
- iscsitgt_svc_online = NULL;
- }
-}
-
/*
* Search the sharetab for the given mountpoint and protocol, returning
* a zfs_share_type_t value.
@@ -455,7 +424,7 @@ zfs_is_shared(zfs_handle_t *zhp)
zfs_share_proto_t *curr_proto;
if (ZFS_IS_VOLUME(zhp))
- return (zfs_is_shared_iscsi(zhp));
+ return (B_FALSE);
for (curr_proto = share_all_proto; *curr_proto != PROTO_END;
curr_proto++)
@@ -468,7 +437,7 @@ int
zfs_share(zfs_handle_t *zhp)
{
if (ZFS_IS_VOLUME(zhp))
- return (zfs_share_iscsi(zhp));
+ return (0);
return (zfs_share_proto(zhp, share_all_proto));
}
@@ -477,7 +446,7 @@ int
zfs_unshare(zfs_handle_t *zhp)
{
if (ZFS_IS_VOLUME(zhp))
- return (zfs_unshare_iscsi(zhp));
+ return (0);
return (zfs_unshareall(zhp));
}
@@ -1009,81 +978,6 @@ remove_mountpoint(zfs_handle_t *zhp)
}
}
-boolean_t
-zfs_is_shared_iscsi(zfs_handle_t *zhp)
-{
-
- /*
- * If iscsi deamon isn't running then we aren't shared
- */
- if (iscsitgt_svc_online && iscsitgt_svc_online() == 1)
- return (B_FALSE);
- else
- return (iscsitgt_zfs_is_shared != NULL &&
- iscsitgt_zfs_is_shared(zhp->zfs_name) != 0);
-}
-
-int
-zfs_share_iscsi(zfs_handle_t *zhp)
-{
- char shareopts[ZFS_MAXPROPLEN];
- const char *dataset = zhp->zfs_name;
- libzfs_handle_t *hdl = zhp->zfs_hdl;
-
- /*
- * Return success if there are no share options.
- */
- if (zfs_prop_get(zhp, ZFS_PROP_SHAREISCSI, shareopts,
- sizeof (shareopts), NULL, NULL, 0, B_FALSE) != 0 ||
- strcmp(shareopts, "off") == 0)
- return (0);
-
- if (iscsitgt_zfs_share == NULL || iscsitgt_zfs_share(dataset) != 0) {
- int error = EZFS_SHAREISCSIFAILED;
-
- /*
- * If service isn't availabele and EPERM was
- * returned then use special error.
- */
- if (iscsitgt_svc_online && errno == EPERM &&
- (iscsitgt_svc_online() != 0))
- error = EZFS_ISCSISVCUNAVAIL;
-
- return (zfs_error_fmt(hdl, error,
- dgettext(TEXT_DOMAIN, "cannot share '%s'"), dataset));
- }
-
- return (0);
-}
-
-int
-zfs_unshare_iscsi(zfs_handle_t *zhp)
-{
- const char *dataset = zfs_get_name(zhp);
- libzfs_handle_t *hdl = zhp->zfs_hdl;
-
- /*
- * Return if the volume is not shared
- */
- if (zfs_is_shared_iscsi(zhp) != SHARED_ISCSI)
- return (0);
-
- /*
- * If this fails with ENODEV it indicates that zvol wasn't shared so
- * we should return success in that case.
- */
- if (iscsitgt_zfs_unshare == NULL ||
- (iscsitgt_zfs_unshare(dataset) != 0 && errno != ENODEV)) {
- if (errno == EPERM)
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "Insufficient privileges to unshare iscsi"));
- return (zfs_error_fmt(hdl, EZFS_UNSHAREISCSIFAILED,
- dgettext(TEXT_DOMAIN, "cannot unshare '%s'"), dataset));
- }
-
- return (0);
-}
-
typedef struct mount_cbdata {
zfs_handle_t **cb_datasets;
int cb_used;
@@ -1225,21 +1119,6 @@ out:
return (ret);
}
-/*ARGSUSED1*/
-static int
-zvol_cb(zfs_handle_t *zhp, void *unused)
-{
- int error = 0;
-
- if (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM)
- (void) zfs_iter_children(zhp, zvol_cb, NULL);
- if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME)
- error = zfs_unshare_iscsi(zhp);
- zfs_close(zhp);
-
- return (error);
-}
-
static int
mountpoint_compare(const void *a, const void *b)
{
@@ -1265,23 +1144,12 @@ zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force)
struct mnttab entry;
size_t namelen;
char **mountpoints = NULL;
- zfs_handle_t *zfp;
zfs_handle_t **datasets = NULL;
libzfs_handle_t *hdl = zhp->zpool_hdl;
int i;
int ret = -1;
int flags = (force ? MS_FORCE : 0);
- /*
- * First unshare all zvols.
- */
- zfp = zfs_open(zhp->zpool_hdl, zhp->zpool_name,
- ZFS_TYPE_FILESYSTEM);
- if (zfp != NULL) {
- (void) zfs_iter_children(zfp, zvol_cb, NULL);
- zfs_close(zfp);
- }
-
namelen = strlen(zhp->zpool_name);
rewind(hdl->libzfs_mnttab);
diff --git a/usr/src/lib/libzfs/common/libzfs_util.c b/usr/src/lib/libzfs/common/libzfs_util.c
index 09a1631925..98b56ff79a 100644
--- a/usr/src/lib/libzfs/common/libzfs_util.c
+++ b/usr/src/lib/libzfs/common/libzfs_util.c
@@ -136,10 +136,6 @@ libzfs_error_description(libzfs_handle_t *hdl)
return (dgettext(TEXT_DOMAIN, "smb remove share failed"));
case EZFS_SHARESMBFAILED:
return (dgettext(TEXT_DOMAIN, "smb add share failed"));
- case EZFS_ISCSISVCUNAVAIL:
- return (dgettext(TEXT_DOMAIN,
- "iscsitgt service need to be enabled by "
- "a privileged user"));
case EZFS_PERM:
return (dgettext(TEXT_DOMAIN, "permission denied"));
case EZFS_NOSPC:
@@ -159,12 +155,6 @@ libzfs_error_description(libzfs_handle_t *hdl)
return (dgettext(TEXT_DOMAIN, "recursive dataset dependency"));
case EZFS_NOHISTORY:
return (dgettext(TEXT_DOMAIN, "no history available"));
- case EZFS_UNSHAREISCSIFAILED:
- return (dgettext(TEXT_DOMAIN,
- "iscsitgtd failed request to unshare"));
- case EZFS_SHAREISCSIFAILED:
- return (dgettext(TEXT_DOMAIN,
- "iscsitgtd failed request to share"));
case EZFS_POOLPROPS:
return (dgettext(TEXT_DOMAIN, "failed to retrieve "
"pool properties"));
diff --git a/usr/src/lib/libzfs/common/mapfile-vers b/usr/src/lib/libzfs/common/mapfile-vers
index 4e2eeb38fa..672129e017 100644
--- a/usr/src/lib/libzfs/common/mapfile-vers
+++ b/usr/src/lib/libzfs/common/mapfile-vers
@@ -75,10 +75,8 @@ SUNWprivate_1.1 {
zfs_get_type;
zfs_hold;
zfs_hold_range;
- zfs_iscsi_perm_check;
zfs_is_mounted;
zfs_is_shared;
- zfs_is_shared_iscsi;
zfs_is_shared_nfs;
zfs_is_shared_smb;
zfs_iter_children;
@@ -130,7 +128,6 @@ SUNWprivate_1.1 {
zfs_shareall;
zfs_share_nfs;
zfs_share_smb;
- zfs_share_iscsi;
zfs_smb_acl_add;
zfs_smb_acl_purge;
zfs_smb_acl_remove;
@@ -141,7 +138,6 @@ SUNWprivate_1.1 {
zfs_unmount;
zfs_unmountall;
zfs_unshare;
- zfs_unshare_iscsi;
zfs_unshare_nfs;
zfs_unshare_smb;
zfs_unshareall;
diff --git a/usr/src/pkg/manifests/SUNWcs.mf b/usr/src/pkg/manifests/SUNWcs.mf
index 5ad00495da..004d8894b8 100644
--- a/usr/src/pkg/manifests/SUNWcs.mf
+++ b/usr/src/pkg/manifests/SUNWcs.mf
@@ -992,7 +992,6 @@ file path=usr/lib/help/auths/locale/C/SmfValueHeader.html
file path=usr/lib/help/auths/locale/C/SmfValueIPsec.html
file path=usr/lib/help/auths/locale/C/SmfValueIdmap.html
file path=usr/lib/help/auths/locale/C/SmfValueInetd.html
-file path=usr/lib/help/auths/locale/C/SmfValueIscsitgt.html
file path=usr/lib/help/auths/locale/C/SmfValueMDNS.html
file path=usr/lib/help/auths/locale/C/SmfValueMMS.html
file path=usr/lib/help/auths/locale/C/SmfValueNADD.html
diff --git a/usr/src/pkg/manifests/SUNWiscsitgt.mf b/usr/src/pkg/manifests/SUNWiscsitgt.mf
deleted file mode 100644
index 5b41ebafbd..0000000000
--- a/usr/src/pkg/manifests/SUNWiscsitgt.mf
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-set name=pkg.fmri value=pkg:/SUNWiscsitgt@0.5.11,5.11-0.133
-set name=pkg.renamed value=true
-set name=variant.arch value=$(ARCH)
-set name=variant.opensolaris.zone value=global value=nonglobal
-depend fmri=pkg:/network/iscsi/target/legacy@0.5.11,5.11-0.133 type=require
diff --git a/usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf b/usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf
index b3dc1bd736..fc19087040 100644
--- a/usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf
+++ b/usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf
@@ -194,7 +194,6 @@ file path=usr/lib/help/auths/locale/SmfValueHeader.html
file path=usr/lib/help/auths/locale/SmfValueIPsec.html
file path=usr/lib/help/auths/locale/SmfValueIdmap.html
file path=usr/lib/help/auths/locale/SmfValueInetd.html
-file path=usr/lib/help/auths/locale/SmfValueIscsitgt.html
file path=usr/lib/help/auths/locale/SmfValueMDNS.html
file path=usr/lib/help/auths/locale/SmfValueMMS.html
file path=usr/lib/help/auths/locale/SmfValueNADD.html
diff --git a/usr/src/pkg/manifests/network-iscsi-target-legacy.mf b/usr/src/pkg/manifests/network-iscsi-target-legacy.mf
deleted file mode 100644
index 78055778a6..0000000000
--- a/usr/src/pkg/manifests/network-iscsi-target-legacy.mf
+++ /dev/null
@@ -1,77 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-#
-# This package will install successfully into any zone, global or
-# non-global. The files, directories, links, and hardlinks, however,
-# will only be installed into the global zone.
-#
-<include hollow_zone_pkg>
-set name=pkg.fmri value=pkg:/network/iscsi/target/legacy@$(PKGVERS)
-set name=pkg.description value="Sun iSCSI Target"
-set name=pkg.summary value="Sun iSCSI Target"
-set name=info.classification value=org.opensolaris.category.2008:System/Hardware
-set name=variant.arch value=$(ARCH)
-set name=variant.opensolaris.zone value=global value=nonglobal
-dir path=etc group=sys
-dir path=etc/iscsi group=sys
-dir path=lib
-dir path=lib/$(ARCH64)
-dir path=lib/svc
-dir path=lib/svc/method
-dir path=usr group=sys
-dir path=usr/lib
-dir path=usr/lib/$(ARCH64)
-dir path=usr/lib/dtrace
-dir path=usr/sbin
-$(i386_ONLY)dir path=usr/sbin/$(ARCH32)
-dir path=usr/sbin/$(ARCH64)
-dir path=var group=sys
-dir path=var/svc group=sys
-dir path=var/svc/manifest group=sys
-dir path=var/svc/manifest/system group=sys
-file path=lib/$(ARCH64)/libiscsitgt.so.1
-file path=lib/libiscsitgt.so.1
-file path=lib/svc/method/svc-iscsitgt mode=0555
-file path=usr/lib/dtrace/iscsi.d
-$(i386_ONLY)file path=usr/sbin/$(ARCH32)/iscsitgtd mode=0555
-file path=usr/sbin/$(ARCH64)/iscsitgtd mode=0555
-file path=usr/sbin/iscsitadm mode=0555
-file path=var/svc/manifest/system/iscsi_target.xml group=sys mode=0444
-hardlink path=usr/sbin/iscsitgtd target=../../usr/lib/isaexec
-legacy pkg=SUNWiscsitgtr arch=$(ARCH) category=system desc="Sun iSCSI Target" \
- hotline="Please contact your local service provider" \
- name="Sun iSCSI Target (Root)" vendor="Sun Microsystems, Inc." \
- version=11.11,REV=2009.11.11
-legacy pkg=SUNWiscsitgtu arch=$(ARCH) category=system desc="Sun iSCSI Target" \
- hotline="Please contact your local service provider" \
- name="Sun iSCSI Target (Usr)" vendor="Sun Microsystems, Inc." \
- version=11.11,REV=2009.11.11
-license cr_Sun license=cr_Sun
-license lic_CDDL license=lic_CDDL
-link path=usr/lib/$(ARCH64)/libiscsitgt.so.1 \
- target=../../../lib/$(ARCH64)/libiscsitgt.so.1
-link path=usr/lib/libiscsitgt.so.1 target=../../lib/libiscsitgt.so.1
diff --git a/usr/src/tools/scripts/bfu.sh b/usr/src/tools/scripts/bfu.sh
index ae53e733c5..4b0aecc8d1 100644
--- a/usr/src/tools/scripts/bfu.sh
+++ b/usr/src/tools/scripts/bfu.sh
@@ -1532,6 +1532,7 @@ smf_obsolete_manifests="
var/svc/manifest/network/iscsi_initiator.xml
var/svc/manifest/network/fcoe_config.xml
var/svc/manifest/network/rpc/ocfserv.xml
+ var/svc/manifest/system/iscsi_target.xml
"
# smf services whose manifests have been renamed
@@ -1555,6 +1556,7 @@ smf_obsolete_methods="
lib/svc/share/krb_include.sh
lib/svc/method/iscsid
lib/svc/method/fcoeconfig
+ lib/svc/method/svc-iscsitgt
"
smf_cleanup () {
@@ -4076,6 +4078,59 @@ SUNWocfr SUNWpamsc SUNWscmhdlr'
printf 'done.\n'
}
+#
+# Remove iSCSI Target Daemon
+#
+remove_eof_iscsitgtd()
+{
+ # Packages to remove
+ typeset -r iscsitgtd_pkgs='SUNWiscsitgtu SUNWiscsitgtr'
+ typeset pkg
+
+ printf 'Removing iSCSI Target Daemon... '
+
+ #
+ # First, attempt to remove the packages cleanly if possible.
+ #
+ for pkg in $iscsitgtd_pkgs
+ do
+ if pkginfo $pkgroot -q $pkg; then
+ printf ' %s' $pkg
+ pkgrm $pkgroot -n $pkg >/dev/null 2>&1
+ fi
+ done
+ printf '\n'
+
+ #
+ # In case that didn't work, do it manually.
+ # Remove iSCSI Target Daemon from $rootprefix/var/sadm/install/contents
+ #
+ for pkg in $iscsitgtd_pkgs
+ do
+ if [ -d $rootprefix/var/sadm/pkg/$pkg ]; then
+ rm -rf $rootprefix/var/sadm/pkg/$pkg
+ grep -vw $pkg $rootprefix/var/sadm/install/contents > \
+ /tmp/contents.$$
+ cp /tmp/contents.$$ $rootprefix/var/sadm/install/contents.$$
+ rm /tmp/contents.$$
+ fi
+ done
+
+ #
+ # Cleanup if any remaining files, symlinks, and directories.
+ #
+ rm -f $usr/sbin/iscsitadm
+ rm -f $usr/sbin/amd64/iscsitgtd
+ rm -f $usr/sbin/i86/iscsitgtd
+ rm -f $usr/sbin/sparv9/iscsitgtd
+ rm -f $usr/sbin/iscsitgtd
+ rm -f $usr/lib/dtrace/iscsi.d
+ rm -f $usr/lib/amd64/libiscsitgt.so.1
+ rm -f $usr/lib/sparcv9/libiscsitgt.so.1
+ rm -f $usr/lib/libiscsitgt.so.1
+ rm -f $usr/svc/method/svc-iscsitgt
+}
+
remove_properties() {
#
@@ -6843,6 +6898,13 @@ mondo_loop() {
fi
#
+ # Remove obsolete iSCSI Target Daemon software
+ #
+ if [ -f $usr/sbin/iscsitadm ]; then
+ remove_eof_iscsitgtd
+ fi
+
+ #
# Remove SUNWcoff package
#
pkg=SUNWcoff
diff --git a/usr/src/uts/common/fs/zfs/zfs_ioctl.c b/usr/src/uts/common/fs/zfs/zfs_ioctl.c
index 8375d2aa94..e06fcff58f 100644
--- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c
+++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c
@@ -625,16 +625,6 @@ zfs_secpolicy_destroy_snaps(zfs_cmd_t *zc, cred_t *cr)
return (error);
}
-/*
- * Must have sys_config privilege to check the iscsi permission
- */
-/* ARGSUSED */
-static int
-zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr)
-{
- return (secpolicy_zfs(cr));
-}
-
int
zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr)
{
@@ -2423,53 +2413,6 @@ zfs_ioc_pool_get_props(zfs_cmd_t *zc)
return (error);
}
-static int
-zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc)
-{
- nvlist_t *nvp;
- int error;
- uint32_t uid;
- uint32_t gid;
- uint32_t *groups;
- uint_t group_cnt;
- cred_t *usercred;
-
- if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
- zc->zc_iflags, &nvp)) != 0) {
- return (error);
- }
-
- if ((error = nvlist_lookup_uint32(nvp,
- ZFS_DELEG_PERM_UID, &uid)) != 0) {
- nvlist_free(nvp);
- return (EPERM);
- }
-
- if ((error = nvlist_lookup_uint32(nvp,
- ZFS_DELEG_PERM_GID, &gid)) != 0) {
- nvlist_free(nvp);
- return (EPERM);
- }
-
- if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS,
- &groups, &group_cnt)) != 0) {
- nvlist_free(nvp);
- return (EPERM);
- }
- usercred = cralloc();
- if ((crsetugid(usercred, uid, gid) != 0) ||
- (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) {
- nvlist_free(nvp);
- crfree(usercred);
- return (EPERM);
- }
- nvlist_free(nvp);
- error = dsl_deleg_access(zc->zc_name,
- zfs_prop_to_name(ZFS_PROP_SHAREISCSI), usercred);
- crfree(usercred);
- return (error);
-}
-
/*
* inputs:
* zc_name name of filesystem
@@ -4358,8 +4301,6 @@ static zfs_ioc_vec_t zfs_ioc_vec[] = {
B_TRUE },
{ zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE,
B_FALSE },
- { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, DATASET_NAME, B_FALSE,
- B_FALSE },
{ zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE, B_FALSE },
{ zfs_ioc_inherit_prop, zfs_secpolicy_inherit, DATASET_NAME, B_TRUE,
B_TRUE },
diff --git a/usr/src/uts/common/io/comstar/port/iscsit/iscsit.c b/usr/src/uts/common/io/comstar/port/iscsit/iscsit.c
index ba0ca1aa50..e68a50291d 100644
--- a/usr/src/uts/common/io/comstar/port/iscsit/iscsit.c
+++ b/usr/src/uts/common/io/comstar/port/iscsit/iscsit.c
@@ -2888,8 +2888,7 @@ iscsit_config_merge(it_config_t *in_cfg)
* Compare serial numbers using serial number arithmetic as defined in
* RFC 1982.
*
- * NOTE: This code is duplicated in the isns server as well as iscsitgtd. It
- * ought to be common.
+ * NOTE: This code is duplicated in the isns server. It ought to be common.
*/
static int
diff --git a/usr/src/uts/common/sys/fs/zfs.h b/usr/src/uts/common/sys/fs/zfs.h
index e986759a2d..6538ac1ca9 100644
--- a/usr/src/uts/common/sys/fs/zfs.h
+++ b/usr/src/uts/common/sys/fs/zfs.h
@@ -91,7 +91,6 @@ typedef enum {
ZFS_PROP_CREATETXG, /* not exposed to the user */
ZFS_PROP_NAME, /* not exposed to the user */
ZFS_PROP_CANMOUNT,
- ZFS_PROP_SHAREISCSI,
ZFS_PROP_ISCSIOPTIONS, /* not exposed to the user */
ZFS_PROP_XATTR,
ZFS_PROP_NUMCLONES, /* not exposed to the user */
@@ -707,7 +706,6 @@ typedef enum zfs_ioc {
ZFS_IOC_POOL_GET_PROPS,
ZFS_IOC_SET_FSACL,
ZFS_IOC_GET_FSACL,
- ZFS_IOC_ISCSI_PERM_CHECK,
ZFS_IOC_SHARE,
ZFS_IOC_INHERIT_PROP,
ZFS_IOC_SMB_ACL,