changeset 3126:4f4fb617fdd0

PSARC 2006/622 iSCSI/ZFS Integration 6484731 zfs import only mounts and shares the first layer of hierarchy 6493750 zfs and iSCSI do not work togetherly correctly 6494075 destroying a pool shouldn't touch the DSL
author ahl
date Wed, 15 Nov 2006 19:25:44 -0800
parents 084bca4d4623
children 73afde3df4cf
files deleted_files/usr/src/cmd/iscsi/common/iscsi_door.h deleted_files/usr/src/cmd/iscsi/common/local_types.h usr/src/Makefile.lint usr/src/Targetdirs usr/src/cmd/dfs.cmds/sharemgr/sharemgr.h usr/src/cmd/iscsi/Makefile.iscsi usr/src/cmd/iscsi/common/iscsi_door.h usr/src/cmd/iscsi/common/local_types.h usr/src/cmd/iscsi/common/xml.c usr/src/cmd/iscsi/common/xml.h usr/src/cmd/iscsi/iscsitadm/Makefile usr/src/cmd/iscsi/iscsitadm/helper.c usr/src/cmd/iscsi/iscsitadm/helper.h usr/src/cmd/iscsi/iscsitadm/main.c usr/src/cmd/iscsi/iscsitgtd/Makefile usr/src/cmd/iscsi/iscsitgtd/Makefile.com usr/src/cmd/iscsi/iscsitgtd/iscsi_authglue.c usr/src/cmd/iscsi/iscsitgtd/iscsi_cmd.h usr/src/cmd/iscsi/iscsitgtd/iscsi_conn.c usr/src/cmd/iscsi/iscsitgtd/iscsi_login.c usr/src/cmd/iscsi/iscsitgtd/iscsi_sess.c usr/src/cmd/iscsi/iscsitgtd/iscsi_target.xml usr/src/cmd/iscsi/iscsitgtd/main.c usr/src/cmd/iscsi/iscsitgtd/mgmt.c usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c usr/src/cmd/iscsi/iscsitgtd/mgmt_list.c usr/src/cmd/iscsi/iscsitgtd/mgmt_modify.c usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c usr/src/cmd/iscsi/iscsitgtd/queue.h usr/src/cmd/iscsi/iscsitgtd/svc-iscsitgt usr/src/cmd/iscsi/iscsitgtd/t10.h usr/src/cmd/iscsi/iscsitgtd/t10_osd.c usr/src/cmd/iscsi/iscsitgtd/t10_raw_if.c usr/src/cmd/iscsi/iscsitgtd/t10_sam.c usr/src/cmd/iscsi/iscsitgtd/t10_sbc.c usr/src/cmd/iscsi/iscsitgtd/t10_spc.c usr/src/cmd/iscsi/iscsitgtd/t10_ssc.c usr/src/cmd/iscsi/iscsitgtd/target.h usr/src/cmd/iscsi/iscsitgtd/util.c usr/src/cmd/iscsi/iscsitgtd/util_ifname.c usr/src/cmd/iscsi/iscsitgtd/util_queue.c usr/src/cmd/iscsi/iscsitgtd/utility.h usr/src/cmd/zfs/zfs_main.c usr/src/cmd/zpool/zpool_main.c usr/src/common/zfs/zfs_prop.c usr/src/lib/Makefile usr/src/lib/libiscsitgt/Makefile usr/src/lib/libiscsitgt/Makefile.com usr/src/lib/libiscsitgt/amd64/Makefile usr/src/lib/libiscsitgt/common/gen.c usr/src/lib/libiscsitgt/common/if_gen.c usr/src/lib/libiscsitgt/common/if_zfs.c usr/src/lib/libiscsitgt/common/iscsitgt_impl.h usr/src/lib/libiscsitgt/common/libiscsitgt.h usr/src/lib/libiscsitgt/common/llib-liscsitgt usr/src/lib/libiscsitgt/common/mapfile-vers usr/src/lib/libiscsitgt/common/xml.c usr/src/lib/libiscsitgt/i386/Makefile usr/src/lib/libiscsitgt/sparc/Makefile usr/src/lib/libiscsitgt/sparcv9/Makefile usr/src/lib/libzfs/Makefile.com usr/src/lib/libzfs/common/libzfs.h usr/src/lib/libzfs/common/libzfs_changelist.c usr/src/lib/libzfs/common/libzfs_dataset.c usr/src/lib/libzfs/common/libzfs_impl.h usr/src/lib/libzfs/common/libzfs_mount.c usr/src/lib/libzfs/common/libzfs_pool.c usr/src/lib/libzfs/common/libzfs_util.c usr/src/lib/libzfs/common/mapfile-vers usr/src/pkgdefs/SUNWiscsitgtr/prototype_com usr/src/pkgdefs/SUNWiscsitgtr/prototype_i386 usr/src/pkgdefs/SUNWiscsitgtr/prototype_sparc usr/src/pkgdefs/SUNWiscsitgtu/prototype_com usr/src/pkgdefs/SUNWiscsitgtu/prototype_i386 usr/src/pkgdefs/SUNWiscsitgtu/prototype_sparc usr/src/pkgdefs/etc/exception_list_i386 usr/src/pkgdefs/etc/exception_list_sparc usr/src/uts/common/sys/fs/zfs.h
diffstat 78 files changed, 5064 insertions(+), 2885 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/cmd/iscsi/common/iscsi_door.h	Wed Nov 15 19:25:44 2006 -0800
@@ -0,0 +1,159 @@
+/*
+ * 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	_ISCSI_DOOR_H
+#define	_ISCSI_DOOR_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define	ISCSI_TARGET_MGMT_DOOR		"/var/run/iscsi_tgt_door"
+#define	ISCSI_DOOR_REQ_SIGNATURE	0x53435349
+#define	ISCSI_DOOR_REQ_VERSION_1	1
+#define	ISCSI_DOOR_MAX_DATA_SIZE	8192
+
+
+#define	ISCSI_DOOR_GETIPNODEBYNAME_REQ	0x0000
+#define	ISCSI_DOOR_GETIPNODEBYNAME_CNF	0x4000
+#define	ISCSI_DOOR_ERROR_IND		0x8000
+
+#define	ISCSI_DOOR_STATUS_SUCCESS	0x00000000
+#define	ISCSI_DOOR_STATUS_REQ_LENGTH	0x00000001
+#define	ISCSI_DOOR_STATUS_REQ_FORMAT	0x00000002
+#define	ISCSI_DOOR_STATUS_REQ_INVALID	0x00000003
+#define	ISCSI_DOOR_STATUS_REQ_VERSION	0x00000004
+#define	ISCSI_DOOR_STATUS_MORE		0x00000005
+
+typedef struct _iscsi_door_msg_hdr {
+	uint32_t		signature;
+	uint32_t		version;
+	uint32_t		opcode;
+	uint32_t		status;
+} iscsi_door_msg_hdr_t;
+
+typedef struct _getipnodebyname_req {
+	iscsi_door_msg_hdr_t	hdr;
+	uint32_t		name_offset;
+	uint32_t		name_length;
+	uint32_t		af;
+	uint32_t		flags;
+} getipnodebyname_req_t;
+
+typedef struct _getipnodebyname_cnf {
+	iscsi_door_msg_hdr_t	hdr;
+	uint32_t		h_size_needed;
+	uint32_t		h_addr_list_offset;
+	uint32_t		h_addr_list_length;
+	uint32_t		h_addrtype;
+	uint32_t		h_addrlen;
+	uint32_t		h_name_offset;
+	uint32_t		h_name_len;
+	uint32_t		h_alias_list_offset;
+	uint32_t		h_alias_list_length;
+	int32_t			error_num;
+} getipnodebyname_cnf_t;
+
+typedef union _iscsi_door_req {
+	iscsi_door_msg_hdr_t	hdr;
+	getipnodebyname_req_t	ginbn_req;
+} iscsi_door_req_t;
+
+typedef union _iscsi_door_cnf {
+	iscsi_door_msg_hdr_t	hdr;
+	getipnodebyname_cnf_t	ginbn_cnf;
+} iscsi_door_cnf_t;
+
+typedef union _iscsi_door_ind {
+	iscsi_door_msg_hdr_t	hdr;
+	iscsi_door_msg_hdr_t	error_ind;
+} iscsi_door_ind_t;
+
+typedef union _iscsi_door_msg {
+	iscsi_door_msg_hdr_t	hdr;
+	iscsi_door_req_t	req;
+	iscsi_door_cnf_t	cnf;
+	iscsi_door_ind_t	ind;
+} iscsi_door_msg_t;
+
+#ifdef _KERNEL
+
+/* Defines copied from netdb.h */
+#define	HOST_NOT_FOUND	1 /* Authoritive Answer Host not found */
+#define	TRY_AGAIN	2 /* Non-Authoritive Host not found, or SERVERFAIL */
+#define	NO_RECOVERY	3 /* Non recoverable errors,FORMERR,REFUSED,NOTIMP */
+#define	NO_DATA		4 /* Valid name, no data record of requested type */
+#define	NO_ADDRESS	NO_DATA	/* no address, look for MX record */
+
+#define	AI_V4MAPPED	0x0001 /* IPv4 mapped addresses if no IPv6 */
+#define	AI_ALL		0x0002 /* IPv6 and IPv4 mapped addresses */
+#define	AI_ADDRCONFIG	0x0004 /* AAAA or A records only if IPv6/IPv4 cnfgd */
+
+struct  hostent {
+	char	*h_name;	/* official name of host */
+	char	**h_aliases;	/* alias list */
+	int	h_addrtype;	/* host address type */
+	int	h_length;	/* length of address */
+	char	**h_addr_list;	/* list of addresses from name server */
+};
+
+boolean_t
+iscsi_door_ini(void);
+
+boolean_t
+iscsi_door_term(void);
+
+boolean_t
+iscsi_door_bind(
+	int		did
+);
+
+void
+kfreehostent(
+	struct hostent	*hptr
+);
+
+struct hostent *
+kgetipnodebyname(
+	const char	*name,
+	int		af,
+	int		flags,
+	int		*error_num
+);
+
+#else	/* !_KERNEL */
+
+#define	kfreehostent		freehostent
+#define	kgetipnodebyname	getipnodebyname
+
+#endif	/* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ISCSI_DOOR_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/cmd/iscsi/common/local_types.h	Wed Nov 15 19:25:44 2006 -0800
@@ -0,0 +1,66 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _LOCAL_TYPES_H
+#define	_LOCAL_TYPES_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+/*
+ * Block comment which describes the contents of this file.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#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
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LOCAL_TYPES_H */
--- a/usr/src/Makefile.lint	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/Makefile.lint	Wed Nov 15 19:25:44 2006 -0800
@@ -332,6 +332,7 @@
 	lib/libipmp \
 	lib/libipp \
 	lib/libipsecutil \
+	lib/libiscsitgt \
 	lib/libkmf \
 	lib/libkstat \
 	lib/liblaadm \
--- a/usr/src/Targetdirs	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/Targetdirs	Wed Nov 15 19:25:44 2006 -0800
@@ -857,6 +857,8 @@
 $(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/libkstat.so.1:=		REALPATH=../../lib/libkstat.so.1
 $(ROOT)/usr/lib/libkstat.so:=		REALPATH=../../lib/libkstat.so.1
 $(ROOT)/usr/lib/liblddbg.so.4:=		REALPATH=../../lib/liblddbg.so.4
@@ -1126,6 +1128,10 @@
 	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:= \
@@ -1435,6 +1441,8 @@
 	/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 \
@@ -1669,6 +1677,8 @@
 	/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 \
--- a/usr/src/cmd/dfs.cmds/sharemgr/sharemgr.h	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/dfs.cmds/sharemgr/sharemgr.h	Wed Nov 15 19:25:44 2006 -0800
@@ -81,7 +81,7 @@
 #define	SVC_SET		0x01 /* need value permissions */
 #define	SVC_ACTION	0x02 /* need action permissions */
 
-#define	ZFS_SHAREALL	"/usr/sbin/zfs share -a"
+#define	ZFS_SHAREALL	"/usr/sbin/zfs share -a nfs"
 
 /*
  * functions/values for manipulating options
--- a/usr/src/cmd/iscsi/Makefile.iscsi	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/Makefile.iscsi	Wed Nov 15 19:25:44 2006 -0800
@@ -29,6 +29,3 @@
 
 ISCSISRC	= $(SRC)/cmd/iscsi
 ISCSICOMMONDIR	= $(ISCSISRC)/common
-
-COMMON_OBJS	= xml.o
-COMMON_SRCS	= $(COMMON_OBJS:%.o=$(ISCSICOMMONDIR)/%.c)
--- a/usr/src/cmd/iscsi/common/iscsi_door.h	Wed Nov 15 19:19:07 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +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	_ISCSI_DOOR_H
-#define	_ISCSI_DOOR_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define	ISCSI_TARGET_MGMT_DOOR		"/var/run/iscsi_tgt_door"
-#define	ISCSI_DOOR_REQ_SIGNATURE	0x53435349
-#define	ISCSI_DOOR_REQ_VERSION_1	1
-#define	ISCSI_DOOR_MAX_DATA_SIZE	8192
-
-
-#define	ISCSI_DOOR_GETIPNODEBYNAME_REQ	0x0000
-#define	ISCSI_DOOR_GETIPNODEBYNAME_CNF	0x4000
-#define	ISCSI_DOOR_ERROR_IND		0x8000
-
-#define	ISCSI_DOOR_STATUS_SUCCESS	0x00000000
-#define	ISCSI_DOOR_STATUS_REQ_LENGTH	0x00000001
-#define	ISCSI_DOOR_STATUS_REQ_FORMAT	0x00000002
-#define	ISCSI_DOOR_STATUS_REQ_INVALID	0x00000003
-#define	ISCSI_DOOR_STATUS_REQ_VERSION	0x00000004
-#define	ISCSI_DOOR_STATUS_MORE		0x00000005
-
-typedef struct _iscsi_door_msg_hdr {
-	uint32_t		signature;
-	uint32_t		version;
-	uint32_t		opcode;
-	uint32_t		status;
-} iscsi_door_msg_hdr_t;
-
-typedef struct _getipnodebyname_req {
-	iscsi_door_msg_hdr_t	hdr;
-	uint32_t		name_offset;
-	uint32_t		name_length;
-	uint32_t		af;
-	uint32_t		flags;
-} getipnodebyname_req_t;
-
-typedef struct _getipnodebyname_cnf {
-	iscsi_door_msg_hdr_t	hdr;
-	uint32_t		h_size_needed;
-	uint32_t		h_addr_list_offset;
-	uint32_t		h_addr_list_length;
-	uint32_t		h_addrtype;
-	uint32_t		h_addrlen;
-	uint32_t		h_name_offset;
-	uint32_t		h_name_len;
-	uint32_t		h_alias_list_offset;
-	uint32_t		h_alias_list_length;
-	int32_t			error_num;
-} getipnodebyname_cnf_t;
-
-typedef union _iscsi_door_req {
-	iscsi_door_msg_hdr_t	hdr;
-	getipnodebyname_req_t	ginbn_req;
-} iscsi_door_req_t;
-
-typedef union _iscsi_door_cnf {
-	iscsi_door_msg_hdr_t	hdr;
-	getipnodebyname_cnf_t	ginbn_cnf;
-} iscsi_door_cnf_t;
-
-typedef union _iscsi_door_ind {
-	iscsi_door_msg_hdr_t	hdr;
-	iscsi_door_msg_hdr_t	error_ind;
-} iscsi_door_ind_t;
-
-typedef union _iscsi_door_msg {
-	iscsi_door_msg_hdr_t	hdr;
-	iscsi_door_req_t	req;
-	iscsi_door_cnf_t	cnf;
-	iscsi_door_ind_t	ind;
-} iscsi_door_msg_t;
-
-#ifdef _KERNEL
-
-/* Defines copied from netdb.h */
-#define	HOST_NOT_FOUND	1 /* Authoritive Answer Host not found */
-#define	TRY_AGAIN	2 /* Non-Authoritive Host not found, or SERVERFAIL */
-#define	NO_RECOVERY	3 /* Non recoverable errors,FORMERR,REFUSED,NOTIMP */
-#define	NO_DATA		4 /* Valid name, no data record of requested type */
-#define	NO_ADDRESS	NO_DATA	/* no address, look for MX record */
-
-#define	AI_V4MAPPED	0x0001 /* IPv4 mapped addresses if no IPv6 */
-#define	AI_ALL		0x0002 /* IPv6 and IPv4 mapped addresses */
-#define	AI_ADDRCONFIG	0x0004 /* AAAA or A records only if IPv6/IPv4 cnfgd */
-
-struct  hostent {
-	char	*h_name;	/* official name of host */
-	char	**h_aliases;	/* alias list */
-	int	h_addrtype;	/* host address type */
-	int	h_length;	/* length of address */
-	char	**h_addr_list;	/* list of addresses from name server */
-};
-
-boolean_t
-iscsi_door_ini(void);
-
-boolean_t
-iscsi_door_term(void);
-
-boolean_t
-iscsi_door_bind(
-	int		did
-);
-
-void
-kfreehostent(
-	struct hostent	*hptr
-);
-
-struct hostent *
-kgetipnodebyname(
-	const char	*name,
-	int		af,
-	int		flags,
-	int		*error_num
-);
-
-#else	/* !_KERNEL */
-
-#define	kfreehostent		freehostent
-#define	kgetipnodebyname	getipnodebyname
-
-#endif	/* _KERNEL */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ISCSI_DOOR_H */
--- a/usr/src/cmd/iscsi/common/local_types.h	Wed Nov 15 19:19:07 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +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 _LOCAL_TYPES_H
-#define	_LOCAL_TYPES_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * Block comment which describes the contents of this file.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#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
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _LOCAL_TYPES_H */
--- a/usr/src/cmd/iscsi/common/xml.c	Wed Nov 15 19:19:07 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,968 +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/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 "xml.h"
-
-/*
- * Forward declarations
- */
-static char *strip_space(char *value);
-static xml_node_t *node_alloc();
-static void node_free(xml_node_t *x);
-static Boolean_t node_name(xml_node_t *x, const xmlChar *n);
-static Boolean_t node_value(xml_node_t *x, const xmlChar *n, Boolean_t s);
-static xml_node_t *node_parent(xml_node_t *x);
-static xml_node_t *node_child(xml_node_t *x);
-static xml_node_t *node_alloc_attr(xml_node_t *x);
-
-#define	XML_COMMENT_STR	"!--"
-#define	XML_COMMENT_END "--"
-
-void
-xml_tree_free(xml_node_t *n)
-{
-	xml_node_t	*c,
-			*c1;
-	if (n == NULL)
-		return;
-	for (c = n->x_child; c; ) {
-		c1 = c->x_sibling;
-		xml_tree_free(c);
-		c = c1;
-	}
-	for (c = n->x_attr; c; ) {
-		c1 = c->x_sibling;
-		node_free(c);
-		c = c1;
-	}
-	node_free(n);
-
-}
-
-void
-xml_walk(xml_node_t *n, int depth)
-{
-	int		i;
-	xml_node_t	*c;
-
-	if (n == NULL)
-		return;
-	for (i = 0; i < depth; i++)
-		(void) printf("    ");
-	if (n->x_name && n->x_value) {
-		if (strcmp(n->x_name, XML_COMMENT_STR) == 0) {
-			(void) printf("%s%s%s\n", XML_COMMENT_STR, n->x_value,
-			    XML_COMMENT_END);
-		} else if (n->x_attr != NULL) {
-			(void) printf("%s(", n->x_name);
-			for (c = n->x_attr; c; c = c->x_sibling)
-				(void) printf("%s='%s'%c", c->x_name,
-				    c->x_value,
-				    (c->x_sibling != NULL) ? ',' : '\0');
-			(void) printf(")=%s\n", n->x_value);
-		} else {
-			(void) printf("%s=%s\n", n->x_name, n->x_value);
-		}
-	} else if (n->x_name) {
-		if (n->x_attr != NULL) {
-			(void) printf("%s (", n->x_name);
-			for (c = n->x_attr; c; c = c->x_sibling) {
-				if (c != n->x_attr)
-					(void) printf(" ");
-				(void) printf("%s='%s'", c->x_name,
-				    c->x_value);
-			}
-			(void) printf(")...\n");
-		} else
-			(void) printf("%s...\n", n->x_name);
-	}
-	for (c = n->x_child; c; c = c->x_sibling)
-		xml_walk(c, depth + 1);
-}
-
-void
-xml_walk_to_buf(xml_node_t *n, char **buf)
-{
-	xml_node_t	*c;
-
-	if (n == NULL)
-		return;
-	if (strcmp(n->x_name, XML_COMMENT_STR) == 0) {
-		xml_add_comment(buf, n->x_value);
-		return;
-	}
-	buf_add_node_attr(buf, n);
-	if (n->x_value != NULL)
-		buf_add_tag(buf, n->x_value, Tag_String);
-	for (c = n->x_child; c; c = c->x_sibling)
-		xml_walk_to_buf(c, buf);
-	buf_add_tag(buf, n->x_name, Tag_End);
-}
-
-/*
- * []----
- * | xml_update_config -- dump out in core node tree to XML parsable file
- * |
- * | The depth argument is only used to pad the output with white space
- * | for indentation. This is meant to help the readability of the file
- * | for humans.
- * []----
- */
-void
-xml_update_config(xml_node_t *t, int depth, FILE *output)
-{
-	int		i;
-	xml_node_t	*c;
-
-	if (t == NULL)
-		return;
-
-	for (i = 0; i < depth; i++)
-		(void) fprintf(output, "    ");
-	if (strcmp(t->x_name, XML_COMMENT_STR) == 0) {
-		(void) fprintf(output, "<%s%s%s>\n", XML_COMMENT_STR,
-			t->x_value, XML_COMMENT_END);
-		return;
-	}
-	if ((t->x_child == NULL) && (t->x_value != NULL) &&
-	    (t->x_attr == NULL) &&
-	    (((depth * 4) + ((strlen(t->x_name) * 2) + 5) +
-	    strlen(t->x_value)) < 80)) {
-
-		(void) fprintf(output, "<%s>%s</%s>\n", t->x_name, t->x_value,
-		    t->x_name);
-
-	} else {
-		(void) fprintf(output, "<%s", t->x_name);
-		for (c = t->x_attr; c; c = c->x_sibling)
-			(void) fprintf(output, " %s='%s'", c->x_name,
-			    c->x_value);
-		(void) fprintf(output, ">\n");
-		if (t->x_value) {
-			for (i = 0; i < depth + 1; i++)
-				(void) fprintf(output, "    ");
-			(void) fprintf(output, "%s\n", t->x_value);
-		}
-		for (c = t->x_child; c; c = c->x_sibling)
-			xml_update_config(c, depth + 1, output);
-		for (i = 0; i < depth; i++)
-			(void) fprintf(output, "    ");
-		(void) fprintf(output, "</%s>\n", t->x_name);
-	}
-}
-
-Boolean_t
-xml_dump2file(xml_node_t *root, char *path)
-{
-	FILE	*output;
-
-	if ((output = fopen(path, "wb")) == NULL) {
-		syslog(LOG_ERR, "Cannot open the file: %s\n", path);
-		return (False);
-	} else {
-		xml_update_config(root, 0, output);
-		(void) fclose(output);
-
-		/*
-		 * Make sure only root can access the file since we're
-		 * optionally keeping CHAP secrets located here.
-		 */
-		(void) chmod(path, 0600);
-
-		return (True);
-	}
-}
-
-char *common_attr_list[] = {
-	"name",
-	"version",
-	0
-};
-
-Boolean_t
-xml_process_node(xmlTextReaderPtr r, xml_node_t **node)
-{
-	const xmlChar	*name,
-			*value;
-	char		**ap;
-	xmlElementType	node_type;
-	xml_node_t	*n,
-			*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);
-		return (False);
-	}
-
-	node_type = (xmlElementType)xmlTextReaderNodeType(r);
-
-	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);
-			}
-		}
-	}
-	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 (node_name(n, name) == False) {
-			node_free(n);
-			return (False);
-		}
-	} else if ((value != NULL) && (node_type == XML_TEXT_NODE)) {
-		if (node_value(n, value, True) == False) {
-			node_free(n);
-			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);
-			return (False);
-		}
-		if (node_value(n, (xmlChar *)value, False) == False) {
-			node_free(n);
-			return (False);
-		}
-	} else if (node_type != XML_DTD_NODE) {
-		node_free(n);
-		return (False);
-	}
-	return (True);
-}
-
-Boolean_t
-xml_find_attr_str(xml_node_t *n, char *attr, char **value)
-{
-	xml_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
-xml_find_value_str(xml_node_t *n, char *name, char **value)
-{
-	xml_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 (xml_find_value_str(c, name, value) == True)
-			return (True);
-	}
-	return (False);
-}
-
-Boolean_t
-xml_find_value_int(xml_node_t *n, char *name, int *value)
-{
-	xml_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 (xml_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
-xml_find_value_intchk(xml_node_t *n, char *name, int *value)
-{
-	char		*str,
-			chk[32];
-	Boolean_t	rval;
-
-	if (xml_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')
-				snprintf(chk, sizeof (chk), "0x%x", *value);
-			else if (str[1] == 'X')
-				snprintf(chk, sizeof (chk), "0X%x", *value);
-			else
-				snprintf(chk, sizeof (chk), "0%o", *value);
-		} else
-			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
-xml_find_value_boolean(xml_node_t *n, char *name, Boolean_t *value)
-{
-	xml_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 (xml_find_value_boolean(c, name, value) == True)
-			return (True);
-	}
-	return (False);
-}
-
-xml_node_t *
-xml_node_next(xml_node_t *n, char *name, xml_node_t *cur)
-{
-	xml_node_t	*x,
-			*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 = xml_node_next(x, name, 0)) != NULL)
-			return (p);
-	return (NULL);
-}
-
-xml_node_t *
-xml_node_next_child(xml_node_t *n, char *name, xml_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);
-}
-
-Boolean_t
-xml_add_child(xml_node_t *p, xml_node_t *c)
-{
-	xml_node_t	*s;
-	if ((p == NULL) || (c == NULL))
-		return (False);
-
-	if (p->x_child == NULL)
-		p->x_child = c;
-	else {
-		for (s = p->x_child; s->x_sibling; s = s->x_sibling)
-			;
-		s->x_sibling = c;
-	}
-	return (True);
-}
-
-xml_node_t *
-xml_alloc_node(char *name, xml_val_type_t type, void *value)
-{
-	xml_node_t	*d = node_alloc();
-	int	value_len;
-	char	*value_str;
-
-	if (d == NULL)
-		return (NULL);
-	switch (type) {
-	case String:
-		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_str = (char *)calloc(sizeof (char), value_len)) == NULL)
-		return (NULL);
-	if (node_name(d, (xmlChar *)name) == False) {
-		free(value_str);
-		return (NULL);
-	}
-	switch (type) {
-	case String:
-		(void) snprintf(value_str, value_len, "%s", (char *)value);
-		break;
-	case Int:
-		(void) snprintf(value_str, value_len, "0x%x", *(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);
-
-	return (d);
-}
-
-Boolean_t
-xml_encode_bytes(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;
-	}
-
-	return (True);
-}
-
-Boolean_t
-xml_decode_bytes(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);
-}
-
-void
-xml_free_node(xml_node_t *node)
-{
-	node_free(node);
-}
-
-Boolean_t
-xml_remove_child(xml_node_t *parent, xml_node_t *child, match_type_t m)
-{
-	xml_node_t	*s,
-			*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;
-			}
-			xml_tree_free(s);
-			break;
-		}
-	}
-	if (s == NULL)
-		return (False);
-	else
-		return (True);
-}
-
-void
-xml_replace_child(xml_node_t *parent, xml_node_t *child, match_type_t m)
-{
-	xml_node_t	*s,
-			*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) {
-				xml_tree_free(s->x_child);
-				s->x_child = NULL;
-			}
-			for (c = child->x_child; c; c = c->x_sibling)
-				(void) xml_add_child(s, xml_node_dup(c));
-			break;
-		}
-	}
-
-	if (s == NULL) {
-		/*
-		 * Never found the child so add it
-		 */
-		(void) xml_add_child(parent, xml_node_dup(child));
-	}
-}
-
-#ifdef notused
-/*
- * Update node value when value type is usigned long long
- */
-Boolean_t
-xml_update_value_ull(xml_node_t *node, char *name, uint64_t value)
-{
-	if (node == NULL || strcmp(name, node->x_name))
-		return (False);
-
-	if (strtoll(node->x_value, NULL, 0) == value)
-		return (True);
-	(void) snprintf(node->x_value, 64, "0x%llx", value);
-	return (True);
-}
-#endif
-
-Boolean_t
-xml_update_value_str(xml_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);
-}
-
-xml_node_t *
-xml_find_child(xml_node_t *n, char *name)
-{
-	xml_node_t	*rval;
-
-	for (rval = n->x_child; rval; rval = rval->x_sibling)
-		if (strcmp(rval->x_name, name) == 0)
-			break;
-	return (rval);
-}
-
-xml_node_t *
-xml_node_dup(xml_node_t *n)
-{
-	xml_node_t	*d = node_alloc(),
-			*c;
-
-	if (d == NULL)
-		return (NULL);
-	if (node_name(d, (xmlChar *)n->x_name) == False)
-		return (NULL);
-	if (node_value(d, (xmlChar *)n->x_value, True) == False)
-		return (NULL);
-	for (c = n->x_child; c; c = c->x_sibling)
-		(void) xml_add_child(d, xml_node_dup(c));
-	return (d);
-}
-
-/*
- * []----
- * | Utility functions
- * []----
- */
-static xml_node_t *
-node_alloc()
-{
-	xml_node_t	*x = (xml_node_t *)calloc(sizeof (xml_node_t), 1);
-
-	if (x == NULL)
-		return (NULL);
-
-	x->x_state = NodeAlloc;
-	return (x);
-}
-
-static void
-node_free(xml_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(xml_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(xml_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 xml_node_t *
-node_parent(xml_node_t *x)
-{
-	return (x->x_parent);
-}
-
-static xml_node_t *
-node_child(xml_node_t *x)
-{
-	xml_node_t	*n,
-			*next;
-
-	n = node_alloc();
-	if (x->x_child == NULL) {
-		x->x_child = n;
-	} else {
-		for (next = x->x_child; next->x_sibling; next = next->x_sibling)
-			;
-		next->x_sibling = n;
-	}
-	if (n != NULL)
-		n->x_parent = x;
-	return (n);
-}
-
-static xml_node_t *
-node_alloc_attr(xml_node_t *x)
-{
-	xml_node_t	*n,
-			*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);
-}
-
-void
-buf_add_str(char **b, char *str)
-{
-	int	len,
-		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) {
-		p = malloc(len);
-	} else {
-		olen = strlen(p);
-		p = realloc(p, olen + len);
-	}
-	(void) strcpy(p + olen, str);
-	*b = p;
-}
-
-/*
- * []----
- * | 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
-buf_add_tag(char **b, 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);
-}
-
-/*
- * []----
- * | buf_add_tag_and_attr -- variant on buf_add_tag which also gives attr
- * []----
- */
-void
-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);
-}
-
-void
-buf_add_node_attr(char **b, xml_node_t *x)
-{
-	char		*buf;
-	xml_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, ">");
-}
-
-void
-xml_add_comment(char **b, char *comment)
-{
-	char	*p	= *b;
-	int	len,
-		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;
-}
-
-void
-xml_add_tag(char **b, char *element, char *cdata)
-{
-	buf_add_tag(b, element, Tag_Start);
-	if (cdata != NULL)
-		buf_add_tag(b, cdata, Tag_String);
-	buf_add_tag(b, element, Tag_End);
-}
-
-static char *
-strip_space(char *value)
-{
-	char	*p,
-		*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);
-}
--- a/usr/src/cmd/iscsi/common/xml.h	Wed Nov 15 19:19:07 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _TARGET_XML_H
-#define	_TARGET_XML_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * Block comment which describes the contents of this file.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <libxml/xmlreader.h>
-
-#include "local_types.h"
-
-/*
- * 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_CHAPNAME	"chap-name"
-#define	XML_ELEMENT_RAD_ACCESS	"radius-access"
-#define	XML_ELEMENT_RAD_SERV	"radius-server"
-#define	XML_ELEMENT_RAD_SECRET	"radius-secret"
-#define	XML_ELEMENT_ISNS_ACCESS	"isns-access"
-#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_ADMIN	"admin"
-#define	XML_ELEMENT_INAME	"iscsi-name"
-#define	XML_ELEMENT_MAXRECV	"maxrecv"
-#define	XML_ELEMENT_IPADDR	"ip-address"
-#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"
-
-typedef enum {
-	NodeFree,
-	NodeAlloc,
-	NodeName,
-	NodeValue
-} xml_node_state;
-
-typedef enum { MatchName, MatchBoth } match_type_t;
-
-typedef struct xml_node {
-	struct xml_node	*x_parent,
-			*x_child,
-			*x_sibling,
-			*x_attr;
-	char		*x_name,
-			*x_value;
-	xml_node_state	x_state;
-} xml_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;
-
-void xml_tree_free(xml_node_t *x);
-void xml_walk(xml_node_t *x, int depth);
-void xml_walk_to_buf(xml_node_t *n, char **buf);
-void xml_update_config(xml_node_t *t, int depth, FILE *output);
-void buf_add_str(char **b, char *str);
-void buf_add_tag(char **b, char *str, val_type_t type);
-void buf_add_tag_and_attr(char **b, char *str, char *attr);
-void buf_add_node_attr(char **b, xml_node_t *x);
-void xml_add_tag(char **b, char *element, char *cdata);
-void xml_add_comment(char **b, char *comment);
-void xml_replace_child(xml_node_t *parent, xml_node_t *child, match_type_t m);
-Boolean_t xml_remove_child(xml_node_t *parent, xml_node_t *child,
-    match_type_t m);
-Boolean_t xml_encode_bytes(uint8_t *ip, size_t ip_size, char **buf,
-    size_t *buf_size);
-Boolean_t xml_decode_bytes(char *buf, uint8_t **ip, size_t *ip_size);
-Boolean_t xml_find_value_str(xml_node_t *n, char *name, char **value);
-Boolean_t xml_find_value_int(xml_node_t *n, char *name, int *value);
-Boolean_t xml_find_value_intchk(xml_node_t *n, char *name, int *value);
-Boolean_t xml_update_value_ull(xml_node_t *root, char *name, uint64_t value);
-Boolean_t xml_dump2file(xml_node_t *root, char *path);
-Boolean_t xml_find_value_boolean(xml_node_t *n, char *name, Boolean_t *value);
-Boolean_t xml_find_attr_str(xml_node_t *n, char *attr, char **value);
-Boolean_t xml_process_node(xmlTextReaderPtr r, xml_node_t **node);
-Boolean_t xml_add_child(xml_node_t *p, xml_node_t *c);
-xml_node_t *xml_alloc_node(char *name, xml_val_type_t type, void *value);
-void xml_free_node(xml_node_t *node);
-xml_node_t *xml_node_next(xml_node_t *n, char *name, xml_node_t *cur);
-xml_node_t *xml_node_next_child(xml_node_t *n, char *name, xml_node_t *cur);
-xml_node_t *xml_node_dup(xml_node_t *n);
-xml_node_t *xml_find_child(xml_node_t *n, char *name);
-Boolean_t xml_update_value_str(xml_node_t *node, char *name, char *str);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _TARGET_XML_H */
--- a/usr/src/cmd/iscsi/iscsitadm/Makefile	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitadm/Makefile	Wed Nov 15 19:25:44 2006 -0800
@@ -27,13 +27,13 @@
 
 PROG = iscsitadm
 OBJS = main.o helper.o cmdparse.o
-SRCS =$(OBJS:%.o=%.c) $(COMMON_SRCS)
+SRCS =$(OBJS:%.o=%.c)
 POFILES= $(OBJS:%.o=%.po)
 
 include $(SRC)/cmd/Makefile.cmd
 include $(SRC)/cmd/iscsi/Makefile.iscsi
 
-LDLIBS += -lxml2 -lsocket -lnsl -ldoor -lscf
+LDLIBS += -liscsitgt -lxml2
 CFLAGS += $(CCVERBOSE) -I${ISCSICOMMONDIR}
 FILEMODE= 0555
 GROUP= bin
--- a/usr/src/cmd/iscsi/iscsitadm/helper.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitadm/helper.c	Wed Nov 15 19:25:44 2006 -0800
@@ -44,7 +44,6 @@
 #include <netinet/in.h>
 #include <sys/iscsi_protocol.h>
 #include <door.h>
-#include <iscsi_door.h>
 #include <sys/scsi/generic/inquiry.h>
 #include <sys/mman.h>
 #include <sys/filio.h>
@@ -52,64 +51,15 @@
 #include <libscf.h>
 #include <fcntl.h>
 
-#include "local_types.h"
+#include <iscsitgt_impl.h>
 #include "cmdparse.h"
 #include "utility.h"
-#include "xml.h"
 #include "helper.h"
 
 extern char *cmdName;
 
-#define	WAIT_FOR_SERVICE	15
-#define	WAIT_FOR_DOOR		15
-static char *service = "system/iscsitgt:default";
 static stat_delta_t *stat_head;
 
-static Boolean_t
-is_online()
-{
-	char		*s;
-	Boolean_t	rval = False;
-
-	if ((s = smf_get_state(service)) != NULL) {
-		if (strcmp(s, SCF_STATE_STRING_ONLINE) == 0)
-			rval = True;
-		free(s);
-	}
-
-	return (rval);
-}
-
-Boolean_t
-check_and_online()
-{
-	int		i,
-			fd;
-
-	if (is_online() == False) {
-		if (smf_enable_instance(service, 0) != 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) {
-			(void) close(fd);
-			return (True);
-		}
-		(void) sleep(1);
-	}
-	return (False);
-}
-
 /*
  * []----
  * | buffer_xml -- buffer incoming XML response until complete
@@ -120,9 +70,9 @@
  * []----
  */
 Boolean_t
-buffer_xml(char *s, char **storage, xml_node_t **np)
+buffer_xml(char *s, char **storage, tgt_node_t **np)
 {
-	xml_node_t		*node		= NULL;
+	tgt_node_t		*node		= NULL;
 	xmlTextReaderPtr	r;
 	char			*p,
 				*e,
@@ -201,7 +151,7 @@
 		return (False);
 
 	while (xmlTextReaderRead(r) == 1) {
-		if (xml_process_node(r, &node) == False)
+		if (tgt_node_process(r, &node) == False)
 			break;
 	}
 
@@ -220,118 +170,6 @@
 	return (True);
 }
 
-xml_node_t *
-send_data(char *hostname, char *first_str)
-{
-	struct sockaddr_in	sin;
-	struct hostent		*hp;
-	int			s,
-				min,
-				nmsgs,
-				nbytes,
-				error_num,
-				port		= 3269;
-	struct pollfd		fds[1];
-	nfds_t			nfds		= 1;
-	char			input[128],
-				*storage	= NULL;
-	xml_node_t		*node		= NULL;
-
-	if (hostname != NULL) {
-		if ((hp = getipnodebyname(hostname, AF_INET,
-		    AI_ALL | AI_ADDRCONFIG | AI_V4MAPPED,
-		    &error_num)) == NULL) {
-			(void) printf("Can't find IP addr for %s\n", hostname);
-			exit(1);
-		}
-
-		bzero(&sin, sizeof (sin));
-		sin.sin_family	= hp->h_addrtype;
-		sin.sin_port	= ntohs(port);
-		bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length);
-
-		if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
-			(void) printf("Failed to open socket\n");
-			exit(1);
-		}
-
-		if (connect(s, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
-			(void) printf("Failed to connect\n");
-			exit(1);
-		}
-
-		fds[0].fd	= s;
-		fds[0].events	= POLLIN;
-		fds[0].revents	= 0;
-
-		if (write(s, first_str, strlen(first_str)) !=
-		    strlen(first_str)) {
-			perror("Failed to send request");
-			exit(1);
-		}
-		while (poll(fds, nfds, -1) != -1) {
-			if ((nmsgs = ioctl(s, FIONREAD, &nbytes)) < 0)
-				exit(1);
-			if ((nmsgs == 0) && (nbytes == 0))
-				exit(1);
-			min = MIN(nbytes, sizeof (input) - 1);
-			if (read(s, input, min) != min)
-				exit(1);
-			input[min] = '\0';
-
-			if (buffer_xml(input, &storage, &node) == True) {
-				break;
-			}
-		}
-	} else {
-		door_arg_t		d;
-		xmlTextReaderPtr	r;
-
-		d.data_ptr	= first_str;
-		d.data_size	= strlen(first_str) + 1;
-		d.desc_ptr	= NULL;
-		d.desc_num	= 0;
-		d.rbuf		= NULL;
-		d.rsize		= 0;
-
-		if (((s = open(ISCSI_TARGET_MGMT_DOOR, 0)) < 0) ||
-		    (door_call(s, &d) < 0)) {
-			if (s != -1)
-				(void) close(s);
-
-			if (check_and_online() == False) {
-				(void) fprintf(stderr,
-				    "iscsitadm: SMF service unavailable\n");
-				exit(1);
-			}
-
-			if ((s = open(ISCSI_TARGET_MGMT_DOOR, 0)) < 0) {
-				(void) fprintf(stderr,
-				    "iscsitadm: Failed to open iSCSI target"
-				    " management door\n");
-				exit(1);
-			}
-			if (door_call(s, &d) < 0) {
-				perror("door_call");
-				exit(1);
-			}
-		}
-
-		if ((r = (xmlTextReaderPtr)xmlReaderForMemory(d.rbuf,
-		    strlen(d.rbuf), NULL, NULL, 0)) == NULL) {
-			perror("xmlReaderForMemory");
-			exit(1);
-		}
-		while (xmlTextReaderRead(r) == 1)
-			if (xml_process_node(r, &node) == False)
-				break;
-		xmlFreeTextReader(r);
-		(void) munmap(d.rbuf, d.rsize);
-	}
-	(void) close(s);
-	return (node);
-}
-
 /*
  * Retrieve CHAP secret from input
  */
@@ -573,34 +411,34 @@
 }
 
 void
-stats_load_counts(xml_node_t *n, stat_delta_t *d)
+stats_load_counts(tgt_node_t *n, stat_delta_t *d)
 {
-	xml_node_t	*conn	= NULL,
+	tgt_node_t	*conn	= NULL,
 			*lun;
 	char		*val;
 
 	bzero(d, sizeof (*d));
 	d->device = n->x_value;
 
-	while (conn = xml_node_next(n, XML_ELEMENT_CONN, conn)) {
+	while (conn = tgt_node_next(n, XML_ELEMENT_CONN, conn)) {
 		lun = NULL;
-		while (lun = xml_node_next(conn, XML_ELEMENT_LUN, lun)) {
-			if (xml_find_value_str(lun, XML_ELEMENT_READCMDS,
+		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 (xml_find_value_str(lun, XML_ELEMENT_WRITECMDS,
+			if (tgt_find_value_str(lun, XML_ELEMENT_WRITECMDS,
 			    &val) == True) {
 				d->write_cmds += strtoll(val, NULL, 0);
 				free(val);
 			}
-			if (xml_find_value_str(lun, XML_ELEMENT_READBLKS,
+			if (tgt_find_value_str(lun, XML_ELEMENT_READBLKS,
 			    &val) == True) {
 				d->read_blks += strtoll(val, NULL, 0);
 				free(val);
 			}
-			if (xml_find_value_str(lun, XML_ELEMENT_WRITEBLKS,
+			if (tgt_find_value_str(lun, XML_ELEMENT_WRITEBLKS,
 			    &val) == True) {
 				d->write_blks += strtoll(val, NULL, 0);
 				free(val);
--- a/usr/src/cmd/iscsi/iscsitadm/helper.h	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitadm/helper.h	Wed Nov 15 19:25:44 2006 -0800
@@ -69,7 +69,7 @@
 
 /* helper functions */
 int getSecret(char *, int *, int, int);
-xml_node_t *send_data(char *hostname, char *first_str);
+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);
@@ -78,7 +78,7 @@
 	unsigned long long number,
 	int unit_from,
 	int scale);
-void stats_load_counts(xml_node_t *n, stat_delta_t *d);
+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();
--- a/usr/src/cmd/iscsi/iscsitadm/main.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitadm/main.c	Wed Nov 15 19:25:44 2006 -0800
@@ -39,8 +39,8 @@
 #include <sys/stat.h>
 #include <zone.h>
 
+#include <iscsitgt_impl.h>
 #include "cmdparse.h"
-#include "xml.h"
 #include "helper.h"
 
 #define	CREATE	SUBCOMMAND(0)
@@ -100,7 +100,6 @@
 
 /* globals */
 char *cmdName;
-static char *hostname = NULL;
 
 /*
  * Add new options here
@@ -358,15 +357,15 @@
 }
 
 static int
-formatErrString(xml_node_t *node)
+formatErrString(tgt_node_t *node)
 {
 	int	code	= 0,
 		rtn	= 0;
 	char	*msg	= NULL;
 
 	if ((strcmp(node->x_name, XML_ELEMENT_ERROR) == 0) &&
-	    (xml_find_value_int(node, XML_ELEMENT_CODE, &code) == B_TRUE) &&
-	    (xml_find_value_str(node, XML_ELEMENT_MESSAGE, &msg) == B_TRUE)) {
+	    (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
@@ -392,15 +391,15 @@
 createTarget(int operandLen, char *operand[], cmdOptions_t *options)
 {
 	char		*first_str	= NULL;
-	xml_node_t	*node;
+	tgt_node_t	*node;
 	cmdOptions_t	*optionList = options;
 
 	if (operand == NULL)
 		return (1);
 
-	buf_add_tag(&first_str, "create", Tag_Start);
-	buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start);
-	xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]);
+	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) {
@@ -415,25 +414,25 @@
 					free(first_str);
 					return (1);
 				} else {
-					xml_add_tag(&first_str,
+					tgt_buf_add(&first_str,
 					    XML_ELEMENT_TYPE,
 					    optionList->optarg);
 				}
 				break;
 			case 'z': /* size */
-				xml_add_tag(&first_str, XML_ELEMENT_SIZE,
+				tgt_buf_add(&first_str, XML_ELEMENT_SIZE,
 				    optionList->optarg);
 				break;
 			case 'u': /* lun number */
-				xml_add_tag(&first_str, XML_ELEMENT_LUN,
+				tgt_buf_add(&first_str, XML_ELEMENT_LUN,
 				    optionList->optarg);
 				break;
 			case 'a': /* alias */
-				xml_add_tag(&first_str, XML_ELEMENT_ALIAS,
+				tgt_buf_add(&first_str, XML_ELEMENT_ALIAS,
 				    optionList->optarg);
 				break;
 			case 'b': /* backing store */
-				xml_add_tag(&first_str, XML_ELEMENT_BACK,
+				tgt_buf_add(&first_str, XML_ELEMENT_BACK,
 				    optionList->optarg);
 				break;
 			default:
@@ -445,10 +444,10 @@
 		}
 	}
 
-	buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End);
-	buf_add_tag(&first_str, "create", Tag_End);
+	tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End);
+	tgt_buf_add_tag(&first_str, "create", Tag_End);
 
-	node = send_data(hostname, first_str);
+	node = tgt_door_call(first_str, 0);
 	free(first_str);
 	return (formatErrString(node));
 }
@@ -458,7 +457,7 @@
 createInitiator(int operandLen, char *operand[], cmdOptions_t *options)
 {
 	char		*first_str	= NULL;
-	xml_node_t	*node;
+	tgt_node_t	*node;
 	cmdOptions_t	*optionList	= options;
 
 	if (operand == NULL)
@@ -466,13 +465,13 @@
 	if (options == NULL)
 		return (1);
 
-	buf_add_tag(&first_str, "create", Tag_Start);
-	buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start);
-	xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]);
+	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 */
-		xml_add_tag(&first_str, XML_ELEMENT_INAME, optionList->optarg);
+		tgt_buf_add(&first_str, XML_ELEMENT_INAME, optionList->optarg);
 		break;
 	default:
 		(void) fprintf(stderr, "%s: %c: %s\n",
@@ -482,10 +481,10 @@
 		return (1);
 	}
 
-	buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End);
-	buf_add_tag(&first_str, "create", Tag_End);
+	tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End);
+	tgt_buf_add_tag(&first_str, "create", Tag_End);
 
-	node = send_data(hostname, first_str);
+	node = tgt_door_call(first_str, 0);
 	free(first_str);
 	return (formatErrString(node));
 }
@@ -495,18 +494,18 @@
 createTpgt(int operandLen, char *operand[], cmdOptions_t *options)
 {
 	char		*first_str	= NULL;
-	xml_node_t	*node;
+	tgt_node_t	*node;
 
 	if (operand == NULL)
 		return (1);
 
-	buf_add_tag(&first_str, "create", Tag_Start);
-	buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start);
-	xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]);
-	buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End);
-	buf_add_tag(&first_str, "create", Tag_End);
+	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 = send_data(hostname, first_str);
+	node = tgt_door_call(first_str, 0);
 	free(first_str);
 	return (formatErrString(node));
 }
@@ -516,40 +515,40 @@
 modifyTarget(int operandLen, char *operand[], cmdOptions_t *options)
 {
 	char		*first_str	= NULL;
-	xml_node_t	*node;
+	tgt_node_t	*node;
 	cmdOptions_t	*optionList	= options;
 
 	if (operand == NULL)
 		return (1);
 
-	buf_add_tag(&first_str, "modify", Tag_Start);
-	buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start);
-	xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]);
+	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 */
-				xml_add_tag(&first_str, XML_ELEMENT_TPGT,
+				tgt_buf_add(&first_str, XML_ELEMENT_TPGT,
 				    optionList->optarg);
 				break;
 			case 'l': /* acl */
-				xml_add_tag(&first_str, XML_ELEMENT_ACL,
+				tgt_buf_add(&first_str, XML_ELEMENT_ACL,
 				    optionList->optarg);
 				break;
 			case 'a': /* alias */
-				xml_add_tag(&first_str, XML_ELEMENT_ALIAS,
+				tgt_buf_add(&first_str, XML_ELEMENT_ALIAS,
 				    optionList->optarg);
 				break;
 			case 'm': /* max recv */
-				xml_add_tag(&first_str, XML_ELEMENT_MAXRECV,
+				tgt_buf_add(&first_str, XML_ELEMENT_MAXRECV,
 				    optionList->optarg);
 				break;
 			case 'z': /* grow lun size */
-				xml_add_tag(&first_str, XML_ELEMENT_SIZE,
+				tgt_buf_add(&first_str, XML_ELEMENT_SIZE,
 				    optionList->optarg);
 				break;
 			case 'u':
-				xml_add_tag(&first_str, XML_ELEMENT_LUN,
+				tgt_buf_add(&first_str, XML_ELEMENT_LUN,
 				    optionList->optarg);
 				break;
 			default:
@@ -561,10 +560,10 @@
 		}
 	}
 
-	buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End);
-	buf_add_tag(&first_str, "modify", Tag_End);
+	tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End);
+	tgt_buf_add_tag(&first_str, "modify", Tag_End);
 
-	node = send_data(hostname, first_str);
+	node = tgt_door_call(first_str, 0);
 	free(first_str);
 	return (formatErrString(node));
 }
@@ -574,7 +573,7 @@
 modifyInitiator(int operandLen, char *operand[], cmdOptions_t *options)
 {
 	char		*first_str	= NULL;
-	xml_node_t	*node;
+	tgt_node_t	*node;
 	cmdOptions_t	*optionList	= options;
 	char		chapSecret[MAX_CHAP_SECRET_LEN];
 	int		secretLen	= 0;
@@ -585,14 +584,14 @@
 	if (options == NULL)
 		return (1);
 
-	buf_add_tag(&first_str, "modify", Tag_Start);
-	buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start);
-	xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]);
+	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 */
-			xml_add_tag(&first_str, XML_ELEMENT_CHAPNAME,
+			tgt_buf_add(&first_str, XML_ELEMENT_CHAPNAME,
 			    optionList->optarg);
 			break;
 		case 'C': /* chap-secret */
@@ -604,7 +603,7 @@
 				return (ret);
 			}
 			chapSecret[secretLen] = '\0';
-			xml_add_tag(&first_str, XML_ELEMENT_CHAPSECRET,
+			tgt_buf_add(&first_str, XML_ELEMENT_CHAPSECRET,
 			    chapSecret);
 			break;
 		default:
@@ -615,10 +614,10 @@
 			return (1);
 		}
 	}
-	buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End);
-	buf_add_tag(&first_str, "modify", Tag_End);
+	tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End);
+	tgt_buf_add_tag(&first_str, "modify", Tag_End);
 
-	node = send_data(hostname, first_str);
+	node = tgt_door_call(first_str, 0);
 	free(first_str);
 	return (formatErrString(node));
 }
@@ -628,7 +627,7 @@
 modifyTpgt(int operandLen, char *operand[], cmdOptions_t *options)
 {
 	char		*first_str	= NULL;
-	xml_node_t	*node;
+	tgt_node_t	*node;
 	cmdOptions_t	*optionList	= options;
 	boolean_t	isIpv6 = B_FALSE;
 	uint16_t	port;
@@ -639,9 +638,9 @@
 	if (optionList == NULL)
 		return (1);
 
-	buf_add_tag(&first_str, "modify", Tag_Start);
-	buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start);
-	xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]);
+	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 */
@@ -650,7 +649,7 @@
 		    PARSE_ADDR_OK) {
 			return (1);
 		}
-		xml_add_tag(&first_str, XML_ELEMENT_IPADDR, IpAddress);
+		tgt_buf_add(&first_str, XML_ELEMENT_IPADDR, IpAddress);
 		break;
 	default:
 		(void) fprintf(stderr, "%s: %c: %s\n",
@@ -660,10 +659,10 @@
 		return (1);
 	}
 
-	buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End);
-	buf_add_tag(&first_str, "modify", Tag_End);
+	tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End);
+	tgt_buf_add_tag(&first_str, "modify", Tag_End);
 
-	node = send_data(hostname, first_str);
+	node = tgt_door_call(first_str, 0);
 	free(first_str);
 	return (formatErrString(node));
 }
@@ -673,7 +672,7 @@
 modifyAdmin(int operandLen, char *operand[], cmdOptions_t *options)
 {
 	char		*first_str	= NULL;
-	xml_node_t	*node;
+	tgt_node_t	*node;
 	cmdOptions_t	*optionList	= options;
 	char		chapSecret[MAX_CHAP_SECRET_LEN],
 			olddir[MAXPATHLEN],
@@ -686,9 +685,9 @@
 	if (options == NULL)
 		return (1);
 
-	buf_add_tag(&first_str, "modify", Tag_Start);
-	buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_Start);
-	xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]);
+	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) {
@@ -713,12 +712,12 @@
 					return (1);
 				}
 				(void) getcwd(newdir, sizeof (newdir));
-				xml_add_tag(&first_str, XML_ELEMENT_BASEDIR,
+				tgt_buf_add(&first_str, XML_ELEMENT_BASEDIR,
 				    newdir);
 				chdir(olddir);
 				break;
 			case 'H': /* chap name */
-				xml_add_tag(&first_str, XML_ELEMENT_CHAPNAME,
+				tgt_buf_add(&first_str, XML_ELEMENT_CHAPNAME,
 				    optionList->optarg);
 				break;
 			case 'C': /* chap secert */
@@ -734,18 +733,18 @@
 					return (ret);
 				}
 				chapSecret[secretLen] = '\0';
-				xml_add_tag(&first_str, XML_ELEMENT_CHAPSECRET,
+				tgt_buf_add(&first_str, XML_ELEMENT_CHAPSECRET,
 				    chapSecret);
 				break;
 			case 'R': /* radius access */
 				if (strcmp(optionList->optarg,
 					OPT_ENABLE) == 0) {
-					xml_add_tag(&first_str,
+					tgt_buf_add(&first_str,
 					    XML_ELEMENT_RAD_ACCESS, OPT_TRUE);
 				} else
 					if (strcmp(optionList->optarg,
 						OPT_DISABLE) == 0) {
-					xml_add_tag(&first_str,
+					tgt_buf_add(&first_str,
 					    XML_ELEMENT_RAD_ACCESS, OPT_FALSE);
 				} else {
 					(void) fprintf(stderr, "%s: %s\n",
@@ -757,7 +756,7 @@
 				}
 				break;
 			case 'r': /* radius server */
-				xml_add_tag(&first_str, XML_ELEMENT_RAD_SERV,
+				tgt_buf_add(&first_str, XML_ELEMENT_RAD_SERV,
 				    optionList->optarg);
 				break;
 			case 'P': /* radius secret */
@@ -773,18 +772,18 @@
 					return (ret);
 				}
 				chapSecret[secretLen] = '\0';
-				xml_add_tag(&first_str, XML_ELEMENT_RAD_SECRET,
+				tgt_buf_add(&first_str, XML_ELEMENT_RAD_SECRET,
 				    chapSecret);
 				break;
 			case 'S': /* iSNS access */
 				if (strcmp(optionList->optarg,
 					OPT_ENABLE) == 0) {
-					xml_add_tag(&first_str,
+					tgt_buf_add(&first_str,
 					    XML_ELEMENT_ISNS_ACCESS, OPT_TRUE);
 				} else
 					if (strcmp(optionList->optarg,
 						OPT_DISABLE) == 0) {
-					xml_add_tag(&first_str,
+					tgt_buf_add(&first_str,
 					    XML_ELEMENT_ISNS_ACCESS, OPT_FALSE);
 				} else {
 					(void) fprintf(stderr, "%s: %s\n",
@@ -798,12 +797,12 @@
 			case 'f': /* fast write back */
 				if (strcmp(optionList->optarg,
 					OPT_ENABLE) == 0) {
-					xml_add_tag(&first_str,
+					tgt_buf_add(&first_str,
 					    XML_ELEMENT_FAST, OPT_TRUE);
 				} else
 					if (strcmp(optionList->optarg,
 						OPT_DISABLE) == 0) {
-					xml_add_tag(&first_str,
+					tgt_buf_add(&first_str,
 					    XML_ELEMENT_FAST, OPT_FALSE);
 				} else {
 					(void) fprintf(stderr, "%s: %s\n",
@@ -823,10 +822,10 @@
 		}
 	}
 
-	buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_End);
-	buf_add_tag(&first_str, "modify", Tag_End);
+	tgt_buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_End);
+	tgt_buf_add_tag(&first_str, "modify", Tag_End);
 
-	node = send_data(hostname, first_str);
+	node = tgt_door_call(first_str, 0);
 	free(first_str);
 	return (formatErrString(node));
 }
@@ -836,7 +835,7 @@
 deleteTarget(int operandLen, char *operand[], cmdOptions_t *options)
 {
 	char		*first_str	= NULL;
-	xml_node_t	*node;
+	tgt_node_t	*node;
 	cmdOptions_t	*optionList = options;
 
 	if (operand == NULL)
@@ -844,19 +843,19 @@
 	if (options == NULL)
 		return (1);
 
-	buf_add_tag(&first_str, "delete", Tag_Start);
-	buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start);
-	xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]);
+	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 */
-		xml_add_tag(&first_str, XML_ELEMENT_LUN, optionList->optarg);
+		tgt_buf_add(&first_str, XML_ELEMENT_LUN, optionList->optarg);
 		break;
 	case 'l': /* acl */
-		xml_add_tag(&first_str, XML_ELEMENT_ACL, optionList->optarg);
+		tgt_buf_add(&first_str, XML_ELEMENT_ACL, optionList->optarg);
 		break;
 	case 'p': /* tpgt number */
-		xml_add_tag(&first_str, XML_ELEMENT_TPGT, optionList->optarg);
+		tgt_buf_add(&first_str, XML_ELEMENT_TPGT, optionList->optarg);
 		break;
 	default:
 		(void) fprintf(stderr, "%s: %c: %s\n",
@@ -866,10 +865,10 @@
 		return (1);
 	}
 
-	buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End);
-	buf_add_tag(&first_str, "delete", Tag_End);
+	tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End);
+	tgt_buf_add_tag(&first_str, "delete", Tag_End);
 
-	node = send_data(hostname, first_str);
+	node = tgt_door_call(first_str, 0);
 	free(first_str);
 	return (formatErrString(node));
 }
@@ -879,7 +878,7 @@
 deleteInitiator(int operandLen, char *operand[], cmdOptions_t *options)
 {
 	char		*first_str	= NULL;
-	xml_node_t	*node;
+	tgt_node_t	*node;
 	cmdOptions_t	*optionList = options;
 
 	if (operand == NULL)
@@ -887,13 +886,13 @@
 	if (options == NULL)
 		return (1);
 
-	buf_add_tag(&first_str, "delete", Tag_Start);
-	buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start);
-	xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]);
+	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 */
-		xml_add_tag(&first_str, XML_ELEMENT_ALL, optionList->optarg);
+		tgt_buf_add(&first_str, XML_ELEMENT_ALL, optionList->optarg);
 		break;
 	default:
 		(void) fprintf(stderr, "%s: %c: %s\n",
@@ -903,10 +902,10 @@
 		return (1);
 	}
 
-	buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End);
-	buf_add_tag(&first_str, "delete", Tag_End);
+	tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End);
+	tgt_buf_add_tag(&first_str, "delete", Tag_End);
 
-	node = send_data(hostname, first_str);
+	node = tgt_door_call(first_str, 0);
 	free(first_str);
 	return (formatErrString(node));
 }
@@ -916,7 +915,7 @@
 deleteTpgt(int operandLen, char *operand[], cmdOptions_t *options)
 {
 	char		*first_str	= NULL;
-	xml_node_t	*node;
+	tgt_node_t	*node;
 	cmdOptions_t	*optionList = options;
 	boolean_t	isIpv6 = B_FALSE;
 	uint16_t	port;
@@ -927,13 +926,13 @@
 	if (options == NULL)
 		return (1);
 
-	buf_add_tag(&first_str, "delete", Tag_Start);
-	buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start);
-	xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]);
+	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 */
-		xml_add_tag(&first_str, XML_ELEMENT_ALL, optionList->optarg);
+		tgt_buf_add(&first_str, XML_ELEMENT_ALL, optionList->optarg);
 		break;
 	case 'i': /* ip address */
 		if (parseAddress(optionList->optarg, 0,
@@ -941,7 +940,7 @@
 		    PARSE_ADDR_OK) {
 			return (1);
 		}
-		xml_add_tag(&first_str, XML_ELEMENT_IPADDR, IpAddress);
+		tgt_buf_add(&first_str, XML_ELEMENT_IPADDR, IpAddress);
 		break;
 	default:
 		(void) fprintf(stderr, "%s: %c: %s\n",
@@ -951,10 +950,10 @@
 		return (1);
 	}
 
-	buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End);
-	buf_add_tag(&first_str, "delete", Tag_End);
+	tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End);
+	tgt_buf_add_tag(&first_str, "delete", Tag_End);
 
-	node = send_data(hostname, first_str);
+	node = tgt_door_call(first_str, 0);
 	free(first_str);
 	return (formatErrString(node));
 }
@@ -963,11 +962,11 @@
 listTarget(int operandLen, char *operand[], cmdOptions_t *options)
 {
 	char		*first_str	= NULL;
-	xml_node_t	*node		= NULL;
-	xml_node_t	*n1		= NULL; /* pointer to node (depth=1) */
-	xml_node_t	*n2		= NULL; /* pointer to node (depth=2) */
-	xml_node_t	*n3		= NULL; /* pointer to node (depth=3) */
-	xml_node_t	*n4		= NULL; /* pointer to node (depth=4) */
+	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;
@@ -975,25 +974,25 @@
 	if (operand == NULL)
 		return (1);
 
-	buf_add_tag(&first_str, "list", Tag_Start);
-	buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start);
+	tgt_buf_add_tag(&first_str, "list", Tag_Start);
+	tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start);
 
 	if (operandLen)
-		xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]);
+		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.
 	 */
-	xml_add_tag(&first_str, XML_ELEMENT_IOSTAT, OPT_TRUE);
+	tgt_buf_add(&first_str, XML_ELEMENT_IOSTAT, OPT_TRUE);
 
 	if (options) {
 		switch (options->optval) {
 		case 0:
 			break;
 		case 'v':
-			xml_add_tag(&first_str, XML_ELEMENT_LUNINFO, OPT_TRUE);
+			tgt_buf_add(&first_str, XML_ELEMENT_LUNINFO, OPT_TRUE);
 			verbose = True;
 			break;
 		default:
@@ -1004,10 +1003,10 @@
 		}
 	}
 
-	buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End);
-	buf_add_tag(&first_str, "list", Tag_End);
+	tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End);
+	tgt_buf_add_tag(&first_str, "list", Tag_End);
 
-	node = send_data(hostname, first_str);
+	node = tgt_door_call(first_str, 0);
 	free(first_str);
 
 	if (strcmp(node->x_name, XML_ELEMENT_RESULT)) {
@@ -1017,18 +1016,18 @@
 	}
 
 	n1 = NULL;
-	while ((n1 = xml_node_next_child(node, XML_ELEMENT_TARG, 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 = xml_node_next_child(n1, XML_ELEMENT_INAME, NULL);
+		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 = xml_node_next_child(n1, XML_ELEMENT_ALIAS, NULL)) !=
+		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 = xml_node_next_child(n1, XML_ELEMENT_MAXRECV, NULL)) !=
+		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);
@@ -1038,7 +1037,7 @@
 		 */
 		n2 = NULL;
 		conns = 0;
-		while (n2 = xml_node_next_child(n1, XML_ELEMENT_CONN, n2))
+		while (n2 = tgt_node_next_child(n1, XML_ELEMENT_CONN, n2))
 			conns++;
 		(void) printf("%s%s: %d\n", dospace(1), gettext("Connections"),
 		    conns);
@@ -1053,30 +1052,30 @@
 		 * indicating connections are coming next.
 		 */
 		n2 = NULL;
-		while (n2 = xml_node_next_child(n1, XML_ELEMENT_CONN, n2)) {
+		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 = xml_node_next_child(n2, XML_ELEMENT_ALIAS, NULL);
+			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 = xml_node_next_child(n1, XML_ELEMENT_ACLLIST, NULL);
+		n2 = tgt_node_next_child(n1, XML_ELEMENT_ACLLIST, NULL);
 		n3 = NULL;
-		while (n3 = xml_node_next_child(n2, XML_ELEMENT_INIT, n3)) {
+		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 = xml_node_next_child(n1, XML_ELEMENT_TPGTLIST, NULL);
+		n2 = tgt_node_next_child(n1, XML_ELEMENT_TPGTLIST, NULL);
 		n3 = NULL;
-		while (n3 = xml_node_next_child(n2, XML_ELEMENT_TPGT, n3)) {
+		while (n3 = tgt_node_next_child(n2, XML_ELEMENT_TPGT, n3)) {
 			(void) printf("%s%s: %s\n", dospace(2),
 			    gettext("TPGT"),
 			    n3->x_value);
@@ -1084,29 +1083,29 @@
 
 		(void) printf("%s%s:\n", dospace(1),
 		    gettext("LUN information"));
-		n2 = xml_node_next_child(n1, XML_ELEMENT_LUNINFO, NULL);
+		n2 = tgt_node_next_child(n1, XML_ELEMENT_LUNINFO, NULL);
 		n3 = NULL;
-		while (n3 = xml_node_next_child(n2, XML_ELEMENT_LUN, n3)) {
+		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 = xml_node_next_child(n3, XML_ELEMENT_GUID, NULL);
+			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 = xml_node_next_child(n3, XML_ELEMENT_VID, NULL);
+			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 = xml_node_next_child(n3, XML_ELEMENT_PID, NULL);
+			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 = xml_node_next_child(n3, XML_ELEMENT_DTYPE, NULL);
+			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 = xml_node_next_child(n3, XML_ELEMENT_SIZE, NULL);
+			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"),
@@ -1118,13 +1117,13 @@
 				    gettext("Size"), gettext("unknown"));
 			}
 
-			n4 = xml_node_next_child(n3, XML_ELEMENT_BACK, NULL);
+			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 = xml_node_next_child(n3, XML_ELEMENT_STATUS, NULL);
+			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"));
@@ -1138,20 +1137,20 @@
 listInitiator(int operandLen, char *operand[], cmdOptions_t *options)
 {
 	char		*first_str	= NULL;
-	xml_node_t	*node;
-	xml_node_t	*n1		= NULL; /* pointer to node (depth=1) */
-	xml_node_t	*n2		= NULL; /* pointer to node (depth=2) */
+	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);
 
-	buf_add_tag(&first_str, "list", Tag_Start);
-	buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start);
+	tgt_buf_add_tag(&first_str, "list", Tag_Start);
+	tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start);
 
 	if (operandLen) {
-		xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]);
+		tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]);
 	}
 	if (optionList) {
 		switch (optionList->optval) {
@@ -1159,7 +1158,7 @@
 			break;
 		case 'v':
 			verbose = True;
-			xml_add_tag(&first_str,
+			tgt_buf_add(&first_str,
 				    XML_ELEMENT_VERBOSE, OPT_TRUE);
 			break;
 
@@ -1172,10 +1171,10 @@
 		}
 	}
 
-	buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End);
-	buf_add_tag(&first_str, "list", Tag_End);
+	tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End);
+	tgt_buf_add_tag(&first_str, "list", Tag_End);
 
-	node = send_data(hostname, first_str);
+	node = tgt_door_call(first_str, 0);
 	free(first_str);
 
 	if (strcmp(node->x_name, XML_ELEMENT_RESULT)) {
@@ -1185,19 +1184,19 @@
 	}
 
 	n1 = NULL;
-	while (n1 = xml_node_next_child(node, XML_ELEMENT_INIT, n1)) {
+	while (n1 = tgt_node_next_child(node, XML_ELEMENT_INIT, n1)) {
 		(void) printf("%s: %s\n", gettext("Initiator"), n1->x_value);
 
-		n2 = xml_node_next_child(n1, XML_ELEMENT_INAME, NULL);
+		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 = xml_node_next_child(n1, XML_ELEMENT_CHAPNAME, NULL);
+		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 = xml_node_next_child(n1, XML_ELEMENT_CHAPSECRET,
+			n2 = tgt_node_next_child(n1, XML_ELEMENT_CHAPSECRET,
 			    NULL);
 			(void) printf("%s%s: %s\n", dospace(1),
 			    gettext("CHAP Secret"),
@@ -1213,9 +1212,9 @@
 listTpgt(int operandLen, char *operand[], cmdOptions_t *options)
 {
 	char		*first_str	= NULL;
-	xml_node_t	*node		= NULL;
-	xml_node_t	*n1		= NULL; /* pointer to node (depth=1) */
-	xml_node_t	*n2		= NULL; /* pointer to node (depth=2) */
+	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;
@@ -1223,18 +1222,18 @@
 	if (operand == NULL)
 		return (1);
 
-	buf_add_tag(&first_str, "list", Tag_Start);
-	buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start);
+	tgt_buf_add_tag(&first_str, "list", Tag_Start);
+	tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start);
 
 	if (operandLen)
-		xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]);
+		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;
-			xml_add_tag(&first_str,
+			tgt_buf_add(&first_str,
 				    XML_ELEMENT_VERBOSE, OPT_TRUE);
 			break;
 		default:
@@ -1246,10 +1245,10 @@
 		}
 	}
 
-	buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End);
-	buf_add_tag(&first_str, "list", Tag_End);
+	tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End);
+	tgt_buf_add_tag(&first_str, "list", Tag_End);
 
-	node = send_data(hostname, first_str);
+	node = tgt_door_call(first_str, 0);
 	free(first_str);
 
 	if (strcmp(node->x_name, XML_ELEMENT_RESULT)) {
@@ -1259,11 +1258,11 @@
 	}
 
 	n1 = NULL;
-	while (n1 = xml_node_next_child(node, XML_ELEMENT_TPGT, n1)) {
+	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 = xml_node_next_child(n1, XML_ELEMENT_IPADDR, n2)) {
+		while (n2 = tgt_node_next_child(n1, XML_ELEMENT_IPADDR, n2)) {
 			if (verbose == True)
 				(void) printf("%s%s: %s\n", dospace(1),
 				    gettext("IP Address"),
@@ -1294,19 +1293,19 @@
 showAdmin(int operandLen, char *operand[], cmdOptions_t *options)
 {
 	char		*first_str	= NULL;
-	xml_node_t	*node		= NULL;
-	xml_node_t	*n1		= NULL; /* pointer to node (depth=1) */
-	xml_node_t	*n2		= NULL; /* pointer to node (depth=2) */
+	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);
 
-	buf_add_tag(&first_str, "list", Tag_Start);
-	buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_Start);
-	buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_End);
-	buf_add_tag(&first_str, "list", Tag_End);
+	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);
 
-	node = send_data(hostname, first_str);
+	node = tgt_door_call(first_str, 0);
 	free(first_str);
 
 	if (strcmp(node->x_name, XML_ELEMENT_RESULT)) {
@@ -1317,22 +1316,22 @@
 
 	(void) printf("%s:\n", cmdName);
 
-	n1 = xml_node_next_child(node, XML_ELEMENT_ADMIN, NULL);
+	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 = xml_node_next_child(n1, XML_ELEMENT_BASEDIR, NULL);
+	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 = xml_node_next_child(n1, XML_ELEMENT_CHAPNAME, NULL);
+	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 = xml_node_next_child(n1, XML_ELEMENT_RAD_ACCESS, NULL);
+	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)
@@ -1342,11 +1341,11 @@
 	} else
 		(void) printf("%s\n", gettext("Not set"));
 
-	n2 = xml_node_next_child(n1, XML_ELEMENT_RAD_SERV, NULL);
+	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 = xml_node_next_child(n1, XML_ELEMENT_ISNS_ACCESS, NULL);
+	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)
@@ -1356,7 +1355,7 @@
 	} else
 		(void) printf("%s\n", gettext("Not set"));
 
-	n2 = xml_node_next_child(n1, XML_ELEMENT_FAST, NULL);
+	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)
@@ -1374,7 +1373,7 @@
 {
 	char		*first_str	= NULL,
 			scale_buf[16];
-	xml_node_t	*node,
+	tgt_node_t	*node,
 			*n1;
 	int		interval	= -1,
 			count		= -1,
@@ -1382,12 +1381,12 @@
 	stat_delta_t	cur_data,
 			*pd;
 
-	buf_add_tag(&first_str, "list", Tag_Start);
-	buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start);
+	tgt_buf_add_tag(&first_str, "list", Tag_Start);
+	tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start);
 
-	xml_add_tag(&first_str, XML_ELEMENT_IOSTAT, OPT_TRUE);
+	tgt_buf_add(&first_str, XML_ELEMENT_IOSTAT, OPT_TRUE);
 	if (operandLen)
-		xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]);
+		tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]);
 
 	for (; options->optval; options++) {
 		switch (options->optval) {
@@ -1419,8 +1418,8 @@
 		}
 	}
 
-	buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End);
-	buf_add_tag(&first_str, "list", Tag_End);
+	tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End);
+	tgt_buf_add_tag(&first_str, "list", Tag_End);
 
 	header = 1;
 	/*CONSTANTCONDITION*/
@@ -1437,23 +1436,23 @@
 			    "-----", "-----");
 			header = 20;
 		}
-		node = send_data(hostname, first_str);
+		node = tgt_door_call(first_str, 0);
 
 		if (strcmp(node->x_name, XML_ELEMENT_RESULT)) {
 			(void) fprintf(stderr, "%s: %s\n", cmdName,
 			    gettext("Bad XML response"));
 			free(first_str);
-			xml_tree_free(node);
+			tgt_node_free(node);
 			stats_free();
 			return (1);
 		}
 
 		n1 = NULL;
-		while (n1 = xml_node_next_child(node, XML_ELEMENT_TARG, n1)) {
+		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);
-				xml_tree_free(node);
+				tgt_node_free(node);
 				return (1);
 			}
 			(void) printf("%-20s  ", pd->device);
@@ -1471,7 +1470,7 @@
 			    cur_data.write_blks - pd->write_blks, 512, 1024));
 			stats_update_counts(pd, &cur_data);
 		}
-		xml_tree_free(node);
+		tgt_node_free(node);
 
 		if (count == -1) {
 			if (interval == -1)
--- a/usr/src/cmd/iscsi/iscsitgtd/Makefile	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/Makefile	Wed Nov 15 19:25:44 2006 -0800
@@ -18,13 +18,13 @@
 #
 # CDDL HEADER END
 #
-#
-#ident	"%Z%%M%	%I%	%E% SMI"
+
 #
 # Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# cmd/iscsi/iscsitgtd/Makefile
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
 
 PROG= iscsitgtd
 OBJS	= main.o mgmt.o mgmt_create.o mgmt_list.o mgmt_modify.o mgmt_remove.o
@@ -42,6 +42,7 @@
 $(BUILD64)SUBDIRS += $(MACH64)
 
 MANIFEST	= iscsi_target.xml
+SVCMETHOD	= svc-iscsitgt
 
 ROOTMANIFESTDIR	= $(ROOTSVCSYSTEM)
 $(ROOTSVCSYSTEM)/iscsi_target.xml	:= OWNER = root
@@ -62,7 +63,7 @@
 
 clean clobber lint:	$(SUBDIRS)
 
-install: $(SUBDIRS) $(ROOTMANIFEST)
+install: $(SUBDIRS) $(ROOTMANIFEST) $(ROOTSVCMETHOD)
 	-$(RM) $(ROOTUSRSBINPROG)
 	-$(LN) $(ISAEXEC) $(ROOTUSRSBINPROG)
 
--- a/usr/src/cmd/iscsi/iscsitgtd/Makefile.com	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/Makefile.com	Wed Nov 15 19:25:44 2006 -0800
@@ -40,7 +40,7 @@
 SUFFIX_LINT	= .ln
 
 CFLAGS +=	$(CCVERBOSE)
-CPPFLAGS +=	-D_LARGEFILE64_SOURCE=1 -I$(ISCSICOMMONDIR) -I/usr/include/libxml2
+CPPFLAGS +=	-D_LARGEFILE64_SOURCE=1 -I/usr/include/libxml2
 CFLAGS64 +=	$(CCVERBOSE)
 
 GROUP=sys
@@ -52,6 +52,8 @@
 all: $(PROG)
 
 LDLIBS	+=	-luuid -lxml2 -lsocket -lnsl -ldoor -lavl -lmd5 -ladm -lefi
+LDLIBS  +=	-liscsitgt -lzfs
+
 $(PROG): $(OBJS) $(COMMON_OBJS)
 	$(LINK.c) $(OBJS) $(COMMON_OBJS) -o $@ $(LDLIBS)
 	$(POST_PROCESS)
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_authglue.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/iscsi_authglue.c	Wed Nov 15 19:25:44 2006 -0800
@@ -45,10 +45,10 @@
 #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 "xml.h"
 #include "target.h"
 
 #define	DEFAULT_RADIUS_PORT 1812
@@ -67,7 +67,7 @@
 	radius->r_radius_config_valid = B_FALSE;
 
 	/* Load RADIUS access option: enable/disable */
-	if (xml_find_value_boolean(main_config, XML_ELEMENT_RAD_ACCESS,
+	if (tgt_find_value_boolean(main_config, XML_ELEMENT_RAD_ACCESS,
 		&bRadiusAccess) == False) {
 		return (B_FALSE);
 	}
@@ -76,7 +76,7 @@
 	}
 
 	/* Load RADIUS server: ipaddr[:port] */
-	if (xml_find_value_str(main_config, XML_ELEMENT_RAD_SERV,
+	if (tgt_find_value_str(main_config, XML_ELEMENT_RAD_SERV,
 		&szRadiusServer) == False) {
 		return (B_FALSE);
 	}
@@ -109,7 +109,7 @@
 	 */
 
 	/* Load RADIUS shared secret */
-	if (xml_find_value_str(main_config, XML_ELEMENT_RAD_SECRET,
+	if (tgt_find_value_str(main_config, XML_ELEMENT_RAD_SECRET,
 		&szRadiusSecret) == False) {
 		freeaddrinfo(res);
 		return (B_FALSE);
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_cmd.h	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/iscsi_cmd.h	Wed Nov 15 19:25:44 2006 -0800
@@ -41,7 +41,7 @@
 #include <sys/avl.h>
 #include <aio.h>
 
-#include "local_types.h"
+#include <iscsitgt_impl.h>
 #include "t10.h"
 
 #define	CMD_MAXOUTSTANDING 64
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_conn.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/iscsi_conn.c	Wed Nov 15 19:25:44 2006 -0800
@@ -41,7 +41,7 @@
 #include <syslog.h>
 #include <sys/iscsi_protocol.h>
 
-#include "local_types.h"
+#include <iscsitgt_impl.h>
 #include "iscsi_conn.h"
 #include "iscsi_sess.h"
 #include "iscsi_login.h"
@@ -269,7 +269,7 @@
 				else {
 					(void) pthread_mutex_lock(
 						&mgmt->m_resp_mutex);
-					xml_add_tag(mgmt->m_u.m_resp,
+					tgt_buf_add(mgmt->m_u.m_resp,
 					    "connection", NULL);
 					(void) pthread_mutex_unlock(
 						&mgmt->m_resp_mutex);
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_login.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/iscsi_login.c	Wed Nov 15 19:25:44 2006 -0800
@@ -32,13 +32,12 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/iscsi_protocol.h>
-
+#include <iscsitgt_impl.h>
 #include "queue.h"
 #include "iscsi_conn.h"
 #include "iscsi_sess.h"
 #include "iscsi_login.h"
 #include "utility.h"
-#include "xml.h"
 #include "target.h"
 
 typedef enum auth_action {
@@ -144,7 +143,7 @@
 				transit		= 0,
 				rc		= 0;
 	auth_action_t		auth_action	= LOGIN_DROP;
-	xml_node_t		*tnode		= NULL;
+	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,
@@ -694,9 +693,9 @@
 static auth_action_t
 login_set_auth(iscsi_sess_t *s)
 {
-	xml_node_t *xnInitiator = NULL;
-	xml_node_t *xnTarget = NULL;
-	xml_node_t *xnAcl = NULL;
+	tgt_node_t *xnInitiator = NULL;
+	tgt_node_t *xnTarget = NULL;
+	tgt_node_t *xnAcl = NULL;
 	char *szIniAlias = NULL;
 	char *szIscsiName = NULL;
 	char *szChapName = NULL;
@@ -710,13 +709,13 @@
 	sess_auth->password_length_in = 0;
 
 	/* Load alias, iscsi-name, chap-name, chap-secret from config file */
-	while ((xnInitiator = xml_node_next(main_config, XML_ELEMENT_INIT,
+	while ((xnInitiator = tgt_node_next(main_config, XML_ELEMENT_INIT,
 	    xnInitiator)) != NULL) {
 
-		(void) xml_find_value_str(xnInitiator, XML_ELEMENT_INIT,
+		(void) tgt_find_value_str(xnInitiator, XML_ELEMENT_INIT,
 		    &szIniAlias);
 
-		if (xml_find_value_str(xnInitiator, XML_ELEMENT_INAME,
+		if (tgt_find_value_str(xnInitiator, XML_ELEMENT_INAME,
 			&szIscsiName) == True) {
 
 			comp = strcmp(s->s_i_name, szIscsiName);
@@ -725,7 +724,7 @@
 
 			if (comp == 0) {
 
-				if (xml_find_value_str(xnInitiator,
+				if (tgt_find_value_str(xnInitiator,
 					XML_ELEMENT_CHAPNAME,
 					&szChapName) == True) {
 					/*CSTYLED*/
@@ -734,7 +733,7 @@
 					free(szChapName);
 				}
 
-				if (xml_find_value_str(xnInitiator,
+				if (tgt_find_value_str(xnInitiator,
 					XML_ELEMENT_CHAPSECRET,
 					&szChapSecret) == True) {
 					/*CSTYLED*/
@@ -769,10 +768,10 @@
 	 * If a CHAP secret exists for the initiator, it must be authed.
 	 */
 
-	while ((xnTarget = xml_node_next(targets_config, XML_ELEMENT_TARG,
+	while ((xnTarget = tgt_node_next(targets_config, XML_ELEMENT_TARG,
 	    xnTarget)) != NULL) {
 
-		if ((xml_find_value_str(xnTarget, XML_ELEMENT_INAME,
+		if ((tgt_find_value_str(xnTarget, XML_ELEMENT_INAME,
 		    &szIscsiName) == False) || (szIscsiName == NULL)) {
 			return (LOGIN_DROP);
 		}
@@ -783,7 +782,7 @@
 
 		if (comp == 0) {
 
-			if ((xnAcl = xml_node_next(xnTarget,
+			if ((xnAcl = tgt_node_next(xnTarget,
 				XML_ELEMENT_ACLLIST, 0)) == NULL) {
 				/*
 				 * No acl_list found, return True for no auth
@@ -797,10 +796,10 @@
 			 * this session.
 			 */
 			xnInitiator = NULL;
-			while ((xnInitiator = xml_node_next(xnAcl,
+			while ((xnInitiator = tgt_node_next(xnAcl,
 				    XML_ELEMENT_INIT, xnInitiator)) != NULL) {
 
-				if ((xml_find_value_str(xnInitiator,
+				if ((tgt_find_value_str(xnInitiator,
 				    XML_ELEMENT_INIT, &possible) == False) ||
 				    (possible == NULL))
 					continue;
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_sess.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/iscsi_sess.c	Wed Nov 15 19:25:44 2006 -0800
@@ -33,11 +33,11 @@
 #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 "xml.h"
 #include "target.h"
 
 pthread_mutex_t	sess_mutex;
@@ -185,18 +185,18 @@
 Boolean_t
 convert_i_local(char *ip, char **rtn)
 {
-	xml_node_t	*inode = NULL;
+	tgt_node_t	*inode = NULL;
 	char		*iname,
 			*name;
 
-	while ((inode = xml_node_next(main_config, XML_ELEMENT_INIT, inode)) !=
+	while ((inode = tgt_node_next(main_config, XML_ELEMENT_INIT, inode)) !=
 	    NULL) {
-		if (xml_find_value_str(inode, XML_ELEMENT_INAME, &iname) ==
+		if (tgt_find_value_str(inode, XML_ELEMENT_INAME, &iname) ==
 		    False) {
 			continue;
 		}
 		if (strcmp(iname, ip) == 0) {
-			if (xml_find_value_str(inode, XML_ELEMENT_INIT,
+			if (tgt_find_value_str(inode, XML_ELEMENT_INIT,
 			    &name) == False) {
 				free(iname);
 				return (False);
@@ -483,10 +483,11 @@
 			    (mgmt->m_request == mgmt_full_phase_statistics) &&
 			    (strcmp(s->s_t_name, mgmt->m_targ_name) == 0)) {
 
-				buf_add_tag(buf, XML_ELEMENT_CONN, Tag_Start);
-				buf_add_tag(buf, s->s_i_name, Tag_String);
+				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) {
-					xml_add_tag(buf, XML_ELEMENT_ALIAS,
+					tgt_buf_add(buf, XML_ELEMENT_ALIAS,
 					    s->s_i_alias);
 				}
 
@@ -499,15 +500,17 @@
 				(void) snprintf(local_buf, sizeof (local_buf),
 				    "%d",
 				    mgmt->m_time - s->s_conn_head->c_up_at);
-				xml_add_tag(buf, XML_ELEMENT_TIMECON,
+				tgt_buf_add(buf, XML_ELEMENT_TIMECON,
 				    local_buf);
 
-				buf_add_tag(buf, XML_ELEMENT_STATS, Tag_Start);
+				tgt_buf_add_tag(buf, XML_ELEMENT_STATS,
+				    Tag_Start);
 
 				t10_targ_stat(s->s_t10, buf);
 
-				buf_add_tag(buf, XML_ELEMENT_STATS, Tag_End);
-				buf_add_tag(buf, XML_ELEMENT_CONN, Tag_End);
+				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);
@@ -610,7 +613,7 @@
 sess_set_auth(iscsi_sess_t *isp)
 {
 	IscsiAuthClient		*auth_client	= NULL;
-	xml_node_t		*node		= NULL;
+	tgt_node_t		*node		= NULL;
 
 	if (isp == (iscsi_sess_t *)NULL)
 		return;
@@ -620,13 +623,13 @@
 	isp->sess_auth.auth_enabled = B_TRUE;
 
 	/* Load CHAP name */
-	node = xml_node_next_child(main_config, XML_ELEMENT_CHAPNAME, NULL);
+	node = tgt_node_next_child(main_config, XML_ELEMENT_CHAPNAME, NULL);
 	if (node == NULL)
 		return;
 	(void) strcpy(isp->sess_auth.username, node->x_value);
 
 	/* Load CHAP secret */
-	node = xml_node_next_child(main_config, XML_ELEMENT_CHAPSECRET, NULL);
+	node = tgt_node_next_child(main_config, XML_ELEMENT_CHAPSECRET, NULL);
 	if (node == NULL)
 		return;
 	(void) strcpy((char *)isp->sess_auth.password, node->x_value);
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_target.xml	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/iscsi_target.xml	Wed Nov 15 19:25:44 2006 -0800
@@ -56,7 +56,7 @@
 	<exec_method
 		type='method'
 		name='start'
-		exec='/usr/sbin/iscsitgtd'
+		exec='/lib/svc/method/svc-iscsitgt %m'
 		timeout_seconds='60'>
 		<method_context>
 			<method_credential
@@ -69,7 +69,7 @@
 	<exec_method
 		type='method'
 		name='stop'
-		exec=':kill'
+		exec='/lib/svc/method/svc-iscsitgt %m %{restarter/contract}'
 		timeout_seconds='60'>
 		<method_context>
 			<method_credential
@@ -79,11 +79,17 @@
 		</method_context>
 	</exec_method>
 
+	<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'> Solaris iSCSI Target
+			<loctext xml:lang='C'>
+				iSCSI Target
 			</loctext>
 		</common_name>
 		<documentation>
--- a/usr/src/cmd/iscsi/iscsitgtd/main.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/main.c	Wed Nov 15 19:25:44 2006 -0800
@@ -45,7 +45,6 @@
 #include <assert.h>
 #include <errno.h>
 #include <door.h>
-#include <iscsi_door.h>
 #include <signal.h>
 #include <siginfo.h>
 #include <sys/ethernet.h>
@@ -56,12 +55,12 @@
 #include <sys/resource.h>
 #include <syslog.h>
 #include <sys/select.h>
+#include <iscsitgt_impl.h>
 
 #include "queue.h"
 #include "port.h"
 #include "iscsi_conn.h"
 #include "target.h"
-#include "xml.h"
 #include "utility.h"
 #include "iscsi_ffp.h"
 #include "errcode.h"
@@ -70,7 +69,7 @@
 #define	EMPTY_CONFIG "<config version='1.0'>\n</config>\n"
 
 /* ---- Forward declarations ---- */
-static void variable_handler(xml_node_t *, target_queue_t *, target_queue_t *);
+static void variable_handler(tgt_node_t *, target_queue_t *, target_queue_t *);
 
 
 /* ---- Global configuration data. ---- */
@@ -78,7 +77,7 @@
 char *target_log			= DEFAULT_TARGET_LOG;
 char *config_file			= DEFAULT_CONFIG_LOCATION;
 int iscsi_port				= 3260; /* defined by the spec */
-xml_node_t	*main_config,
+tgt_node_t	*main_config,
 		*targets_config;
 Boolean_t	enforce_strict_guid	= True,
 		thin_provisioning	= False,
@@ -114,7 +113,7 @@
 
 typedef struct cmd_table {
 	char	*c_name;
-	void	(*c_func)(xml_node_t *, target_queue_t *, target_queue_t *);
+	void	(*c_func)(tgt_node_t *, target_queue_t *, target_queue_t *);
 } cmd_table_t;
 
 admin_table_t admin_prop_list[] = {
@@ -165,7 +164,7 @@
 	char			path[MAXPATHLEN],
 				*target			= NULL;
 	struct stat		ss;
-	xml_node_t		*node			= NULL,
+	tgt_node_t		*node			= NULL,
 				*next			= NULL;
 	int			xml_fd			= -1;
 
@@ -230,7 +229,7 @@
 
 	if (r != NULL) {
 		while (xmlTextReaderRead(r) == 1) {
-			if (xml_process_node(r, &node) == False)
+			if (tgt_node_process(r, &node) == False)
 				break;
 		}
 
@@ -248,9 +247,9 @@
 		}
 
 		targets_config = node;
-		while ((next = xml_node_next(node, XML_ELEMENT_TARG,
+		while ((next = tgt_node_next(node, XML_ELEMENT_TARG,
 		    next)) != NULL) {
-			if (xml_find_value_str(next, XML_ELEMENT_INAME,
+			if (tgt_find_value_str(next, XML_ELEMENT_INAME,
 			    &target) == False) {
 				continue;
 			}
@@ -297,7 +296,7 @@
 	xmlTextReaderPtr	r;
 	int			ret,
 				xml_fd		= -1;
-	xml_node_t		*node = NULL;
+	tgt_node_t		*node = NULL;
 
 #ifndef lint
 	LIBXML_TEST_VERSION;
@@ -318,7 +317,7 @@
 	if (r != NULL) {
 		ret = xmlTextReaderRead(r);
 		while (ret == 1) {
-			if (xml_process_node(r, &node) == False) {
+			if (tgt_node_process(r, &node) == False) {
 				break;
 			}
 			ret = xmlTextReaderRead(r);
@@ -341,7 +340,7 @@
 		 * can start without it, but the daemon can't really do
 		 * anything until the administrator sets the value.
 		 */
-		(void) xml_find_value_str(node, XML_ELEMENT_BASEDIR,
+		(void) tgt_find_value_str(node, XML_ELEMENT_BASEDIR,
 		    &target_basedir);
 
 		/*
@@ -349,20 +348,20 @@
 		 * these has a default value which can be overwritten in
 		 * the configuration file.
 		 */
-		(void) xml_find_value_str(node, XML_ELEMENT_TARGLOG,
+		(void) tgt_find_value_str(node, XML_ELEMENT_TARGLOG,
 		    &target_log);
-		(void) xml_find_value_int(node, XML_ELEMENT_ISCSIPORT,
+		(void) tgt_find_value_int(node, XML_ELEMENT_ISCSIPORT,
 		    &iscsi_port);
-		(void) xml_find_value_int(node, XML_ELEMENT_DBGLVL, &dbg_lvl);
-		(void) xml_find_value_boolean(node, XML_ELEMENT_ENFORCE,
+		(void) tgt_find_value_int(node, XML_ELEMENT_DBGLVL, &dbg_lvl);
+		(void) tgt_find_value_boolean(node, XML_ELEMENT_ENFORCE,
 		    &enforce_strict_guid);
-		(void) xml_find_value_boolean(node, XML_ELEMENT_THIN_PROVO,
+		(void) tgt_find_value_boolean(node, XML_ELEMENT_THIN_PROVO,
 		    &thin_provisioning);
-		(void) xml_find_value_boolean(node, XML_ELEMENT_DISABLE_TPGS,
+		(void) tgt_find_value_boolean(node, XML_ELEMENT_DISABLE_TPGS,
 		    &disable_tpgs);
-		(void) xml_find_value_boolean(node, XML_ELEMENT_TIMESTAMPS,
+		(void) tgt_find_value_boolean(node, XML_ELEMENT_TIMESTAMPS,
 		    &dbg_timestamps);
-		if (xml_find_value_int(node, XML_ELEMENT_LOGLVL,
+		if (tgt_find_value_int(node, XML_ELEMENT_LOGLVL,
 		    &qlog_lvl) == True)
 			queue_log(True);
 
@@ -488,11 +487,11 @@
  */
 /*ARGSUSED*/
 void
-variable_handler(xml_node_t *x, target_queue_t *reply, target_queue_t *mgmt)
+variable_handler(tgt_node_t *x, target_queue_t *reply, target_queue_t *mgmt)
 {
 	char		*reply_buf	= NULL;
 	var_table_t	*v;
-	xml_node_t	*c;
+	tgt_node_t	*c;
 
 	for (c = x->x_child; c; c = c->x_sibling) {
 
@@ -518,7 +517,7 @@
  * []----
  */
 static void
-parse_xml(xml_node_t *x, target_queue_t *reply, target_queue_t *mgmt)
+parse_xml(tgt_node_t *x, target_queue_t *reply, target_queue_t *mgmt)
 {
 	char		*reply_msg	= NULL;
 	cmd_table_t	*c;
@@ -589,7 +588,7 @@
 	target_queue_t		*mgmtq		= (target_queue_t *)cookie;
 	mgmt_request_t		m;
 	msg_t			*msg		= NULL;
-	xml_node_t		*node		= NULL;
+	tgt_node_t		*node		= NULL;
 	xmlTextReaderPtr	r;
 	char			*err_rply	= NULL;
 
@@ -598,7 +597,7 @@
 	if ((r = (xmlTextReaderPtr)xmlReaderForMemory(argp, strlen(argp),
 	    NULL, NULL, 0)) != NULL) {
 		while (xmlTextReaderRead(r)) {
-			if (xml_process_node(r, &node) == False)
+			if (tgt_node_process(r, &node) == False)
 				break;
 		}
 		if (node != NULL) {
@@ -643,7 +642,7 @@
 	}
 
 	if (node != NULL)
-		xml_tree_free(node);
+		tgt_node_free(node);
 	if (err_rply != NULL) {
 		strcpy(argp, err_rply);
 		free(err_rply);
@@ -777,7 +776,7 @@
 	if (process_target_config() == False)
 		exit(SMF_EXIT_ERR_CONFIG);
 
-	(void) xml_find_value_boolean(main_config, XML_ELEMENT_DBGDAEMON,
+	(void) tgt_find_value_boolean(main_config, XML_ELEMENT_DBGDAEMON,
 	    &daemonize);
 	if (daemonize == True) {
 		switch (fork()) {
@@ -837,7 +836,7 @@
 	(void) pthread_create(&junk, NULL, port_watcher, &port1);
 
 	setup_door(q, door_name);
-	if ((xml_find_value_int(main_config, XML_ELEMENT_MGMTPORT,
+	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();
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/mgmt.c	Wed Nov 15 19:25:44 2006 -0800
@@ -40,11 +40,11 @@
 #include <synch.h>
 #include <sys/stropts.h>
 #include <libxml/xmlreader.h>
+#include <iscsitgt_impl.h>
 
 #include "queue.h"
 #include "port.h"
 #include "utility.h"
-#include "xml.h"
 
 static void
 mgmt_monitor_queue(port_args_t *p)
@@ -65,7 +65,7 @@
 		case msg_log:
 			data = (char *)m->msg_data;
 			output = NULL;
-			xml_add_tag(&output, "log", data);
+			tgt_buf_add(&output, "log", data);
 			(void) write(p->port_socket, output, strlen(output));
 			free(output);
 			break;
@@ -73,7 +73,7 @@
 		case msg_mgmt_rply:
 			data = (char *)m->msg_data;
 			output = NULL;
-			xml_add_tag(&output, "mgmt", data);
+			tgt_buf_add(&output, "mgmt", data);
 			(void) write(p->port_socket, output, strlen(output));
 			free(output);
 			free(data);
@@ -103,7 +103,7 @@
 	nfds_t			nfds		= 1;
 	struct pollfd		fds[1];
 	xmlTextReaderPtr	r;
-	xml_node_t		*node		= NULL;
+	tgt_node_t		*node		= NULL;
 	mgmt_request_t		m;
 
 	fds[0].fd = p->port_socket;
@@ -143,7 +143,7 @@
 		if (r != NULL) {
 			ret = xmlTextReaderRead(r);
 			while (ret == 1) {
-				if (xml_process_node(r, &node) == False)
+				if (tgt_node_process(r, &node) == False)
 					break;
 				ret = xmlTextReaderRead(r);
 			}
@@ -153,6 +153,7 @@
 					msg_mgmt_rqst, &m);
 			}
 			xmlFreeTextReader(r);
+			tgt_node_free(node);
 			node = NULL;
 		}
 
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c	Wed Nov 15 19:25:44 2006 -0800
@@ -43,8 +43,10 @@
 #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 "xml.h"
+#include <iscsitgt_impl.h>
 #include "queue.h"
 #include "target.h"
 #include "iscsi_cmd.h"
@@ -54,9 +56,10 @@
 
 extern char *getfullrawname();
 
-static char *create_target(xml_node_t *);
-static char *create_initiator(xml_node_t *);
-static char *create_tpgt(xml_node_t *);
+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 *);
 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 *type, int lun,
@@ -67,7 +70,9 @@
     FILE *fp, uint64_t *size);
 static Boolean_t setup_raw_backing(err_code_t *code, char *path, char *backing,
     uint64_t *size);
+static void zfs_lun(tgt_node_t *l, uint64_t size, char *dataset);
 
+#define	ZVOL_PATH	"/dev/zvol/rdsk/"
 
 /*
  * []----
@@ -76,9 +81,9 @@
  */
 /*ARGSUSED*/
 void
-create_func(xml_node_t *p, target_queue_t *reply, target_queue_t *mgmt)
+create_func(tgt_node_t *p, target_queue_t *reply, target_queue_t *mgmt)
 {
-	xml_node_t	*x;
+	tgt_node_t	*x;
 	char		msgbuf[80],
 			*reply_msg	= NULL;
 
@@ -95,6 +100,8 @@
 			reply_msg = create_initiator(x);
 		} else if (strcmp(x->x_name, XML_ELEMENT_TPGT) == 0) {
 			reply_msg = create_tpgt(x);
+		} else if (strcmp(x->x_name, XML_ELEMENT_ZFS) == 0) {
+			reply_msg = create_zfs(x);
 		} else {
 			(void) snprintf(msgbuf, sizeof (msgbuf),
 			    "Unknown object '%s' for create element",
@@ -105,8 +112,11 @@
 	queue_message_set(reply, 0, msg_mgmt_rply, reply_msg);
 }
 
+/*
+ * create_target -- an administrative request to create a target
+ */
 static char *
-create_target(xml_node_t *x)
+create_target(tgt_node_t *x)
 {
 	char		*msg		= NULL,
 			*name		= NULL,
@@ -118,14 +128,14 @@
 			path[MAXPATHLEN];
 	int		lun		= 0, /* default to LUN 0 */
 			i;
-	xml_node_t	*n,
+	tgt_node_t	*n,
 			*c,
 			*l;
 	err_code_t	code;
 
-	(void) xml_find_value_str(x, XML_ELEMENT_BACK, &backing);
-	(void) xml_find_value_str(x, XML_ELEMENT_ALIAS, &alias);
-	if (xml_find_value_intchk(x, XML_ELEMENT_LUN, &lun) == False) {
+	(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;
 	}
@@ -133,7 +143,7 @@
 	/*
 	 * We've got to have a name element or all bets are off.
 	 */
-	if (xml_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
+	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
 		goto error;
 	}
@@ -157,7 +167,7 @@
 			name[i] = tolower(name[i]);
 	}
 
-	if (xml_find_value_str(x, XML_ELEMENT_TYPE, &type) == False) {
+	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
@@ -171,7 +181,7 @@
 		goto error;
 	}
 
-	if (xml_find_value_str(x, XML_ELEMENT_SIZE, &size) == False) {
+	if (tgt_find_value_str(x, XML_ELEMENT_SIZE, &size) == False) {
 		if (backing != NULL) {
 
 			/*
@@ -218,31 +228,31 @@
 			xml_rtn_msg(&msg, ERR_CREATE_TARGET_DIR_FAILED);
 			goto error;
 		}
-		n = xml_alloc_node(XML_ELEMENT_TARG, String, name);
-		c = xml_alloc_node(XML_ELEMENT_INAME, String, node_name);
-		(void) xml_add_child(n, c);
-		c = xml_alloc_node(XML_ELEMENT_LUNLIST, String, "");
-		l = xml_alloc_node(XML_ELEMENT_LUN, Int, &lun);
-		(void) xml_add_child(c, l);
-		(void) xml_add_child(n, c);
+		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 = xml_alloc_node(XML_ELEMENT_ALIAS, String, alias);
-			(void) xml_add_child(n, c);
+			c = tgt_node_alloc(XML_ELEMENT_ALIAS, String, alias);
+			tgt_node_add(n, c);
 		}
-		(void) xml_add_child(targets_config, n);
+		tgt_node_add(targets_config, n);
 
 	} else {
-		if (xml_find_value_str(n, XML_ELEMENT_INAME,
+		if (tgt_find_value_str(n, XML_ELEMENT_INAME,
 		    &node_name) == False) {
 			xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_INAME);
 			goto error;
 		}
-		if ((c = xml_node_next(n, XML_ELEMENT_LUNLIST, NULL)) == NULL) {
+		if ((c = tgt_node_next(n, XML_ELEMENT_LUNLIST, NULL)) == NULL) {
 			xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
 			goto error;
 		}
-		l = xml_alloc_node(XML_ELEMENT_LUN, Int, &lun);
-		(void) xml_add_child(c, l);
+		l = tgt_node_alloc(XML_ELEMENT_LUN, Int, &lun);
+		tgt_node_add(c, l);
 	}
 
 	if (create_lun(node_name, type, lun, size, backing, &code) == True) {
@@ -262,9 +272,9 @@
 		(void) snprintf(path, sizeof (path), "%s/%s",
 		    target_basedir, name);
 		unlink(path);
-		xml_remove_child(targets_config, n, MatchBoth);
+		tgt_node_remove(targets_config, n, MatchBoth);
 	} else
-		xml_remove_child(c, l, MatchBoth);
+		tgt_node_remove(c, l, MatchBoth);
 
 	xml_rtn_msg(&msg, code);
 
@@ -286,20 +296,20 @@
 }
 
 static char *
-create_initiator(xml_node_t *x)
+create_initiator(tgt_node_t *x)
 {
 	char		*msg		= NULL,
 			*name		= NULL,
 			*iscsi_name	= NULL;
-	xml_node_t	*inode		= NULL,
+	tgt_node_t	*inode		= NULL,
 			*n,
 			*c;
 
-	if (xml_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
+	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
 		goto error;
 	}
-	if (xml_find_value_str(x, XML_ELEMENT_INAME, &iscsi_name) == False) {
+	if (tgt_find_value_str(x, XML_ELEMENT_INAME, &iscsi_name) == False) {
 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_INAME);
 		goto error;
 	}
@@ -308,7 +318,7 @@
 		goto error;
 	}
 
-	while ((inode = xml_node_next(main_config, XML_ELEMENT_INIT,
+	while ((inode = tgt_node_next(main_config, XML_ELEMENT_INIT,
 	    inode)) != NULL) {
 		if (strcmp(inode->x_value, name) == 0) {
 			xml_rtn_msg(&msg, ERR_INIT_EXISTS);
@@ -316,10 +326,10 @@
 		}
 	}
 
-	n = xml_alloc_node(XML_ELEMENT_INIT, String, name);
-	c = xml_alloc_node(XML_ELEMENT_INAME, String, iscsi_name);
-	(void) xml_add_child(n, c);
-	(void) xml_add_child(main_config, n);
+	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 (update_config_main(&msg) == True)
 		xml_rtn_msg(&msg, ERR_SUCCESS);
@@ -334,16 +344,16 @@
 }
 
 static char *
-create_tpgt(xml_node_t *x)
+create_tpgt(tgt_node_t *x)
 {
 	char		*msg	= NULL,
 			*tpgt	= NULL,
 			*extra	 = NULL;
-	xml_node_t	*tnode	= NULL,
+	tgt_node_t	*tnode	= NULL,
 			*n;
 	int		tpgt_val;
 
-	if (xml_find_value_str(x, XML_ELEMENT_NAME, &tpgt) == False) {
+	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &tpgt) == False) {
 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
 		goto error;
 	}
@@ -356,7 +366,7 @@
 		goto error;
 	}
 
-	while ((tnode = xml_node_next(main_config, XML_ELEMENT_TPGT,
+	while ((tnode = tgt_node_next(main_config, XML_ELEMENT_TPGT,
 	    tnode)) != NULL) {
 		if (strcmp(tnode->x_value, tpgt) == 0) {
 			xml_rtn_msg(&msg, ERR_TPGT_EXISTS);
@@ -364,8 +374,8 @@
 		}
 	}
 
-	n = xml_alloc_node(XML_ELEMENT_TPGT, String, tpgt);
-	(void) xml_add_child(main_config, n);
+	n = tgt_node_alloc(XML_ELEMENT_TPGT, String, tpgt);
+	tgt_node_add(main_config, n);
 
 	if (update_config_main(&msg) == True)
 		xml_rtn_msg(&msg, ERR_SUCCESS);
@@ -377,6 +387,230 @@
 	return (msg);
 }
 
+static char *
+create_zfs(tgt_node_t *x)
+{
+	char		*msg		= NULL,
+			*dataset	= NULL,
+			*node_name	= NULL,
+			*prop		= NULL,
+			path[MAXPATHLEN],
+			*cp,	/* current pair */
+			*np,	/* next pair */
+			*vp;	/* value pointer */
+	tgt_node_t	*dnode		= NULL,
+			*n,
+			*c,
+			*attr,
+			*ll,
+			*l;
+	libzfs_handle_t	*zh		= NULL;
+	zfs_handle_t	*zfsh		= NULL;
+	uint64_t	size;
+	size_t		prop_len;
+	int		lun		= 0;
+	xmlTextReaderPtr	r;
+
+	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &dataset) == False) {
+		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
+		goto error;
+	}
+
+	while ((dnode = tgt_node_next(targets_config, XML_ELEMENT_TARG,
+	    dnode)) != NULL) {
+		if (strcmp(dnode->x_value, dataset) == 0) {
+			xml_rtn_msg(&msg, ERR_LUN_EXISTS);
+			goto error;
+		}
+	}
+
+	if (((zh = libzfs_init()) == NULL) ||
+	    ((zfsh = zfs_open(zh, dataset, ZFS_TYPE_ANY)) == NULL)) {
+		xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
+		goto error;
+	}
+
+	prop_len = 1024;
+	if ((prop = malloc(prop_len)) == NULL) {
+		xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
+		goto error;
+	}
+
+	/*
+	 * In case zfs_prop_get returns no contents.
+	 */
+	*prop = '\0';
+
+	/*
+	 * If we fail to get the shareiscsi property or the property is
+	 * set to "off" return an error.
+	 */
+	if (zfs_prop_get(zfsh, ZFS_PROP_SHAREISCSI, prop, prop_len, NULL,
+	    NULL, 0, B_TRUE)) {
+		xml_rtn_msg(&msg, 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.
+	 */
+	cp = prop;
+	while (cp) {
+		if (np = strchr(cp, ','))
+			*np++ = '\0';
+		if (strcmp(cp, "on") == 0) {
+			cp = np;
+			continue;
+		}
+		if (strcmp(cp, "off") == 0) {
+			xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
+			goto error;
+		}
+		if (vp = strchr(cp, '='))
+			*vp++ = '\0';
+		/*
+		 * Only support 'disk' emulation at this point.
+		 */
+		if ((strcmp(cp, "type") == 0) && (strcmp(vp, "disk") != 0)) {
+			xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
+			goto error;
+		}
+
+		cp = np;
+	}
+
+	/*
+	 * In case zfs_prop_get returns no contents.
+	 */
+	*prop = '\0';
+
+	if (zfs_prop_get(zfsh, ZFS_PROP_ISCSIOPTIONS, prop, prop_len, NULL,
+	    NULL, 0, B_TRUE)) {
+		xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
+		goto error;
+	}
+
+	/*
+	 * Pick up the current size of the volume.
+	 */
+	size = zfs_prop_get_int(zfsh, ZFS_PROP_VOLSIZE);
+	if (strlen(prop)) {
+		n = NULL;
+		if ((r = (xmlTextReaderPtr)xmlReaderForMemory(prop,
+		    strlen(prop), NULL, NULL, 0)) != NULL) {
+			while (xmlTextReaderRead(r)) {
+				if (tgt_node_process(r, &n) == False)
+					break;
+			}
+			xmlTextReaderClose(r);
+			xmlFreeTextReader(r);
+			xmlCleanupParser();
+
+			/*
+			 * 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.
+			 * 'l' will be used later.
+			 */
+			if (((ll = tgt_node_next(n, XML_ELEMENT_LUNLIST, NULL))
+			    == NULL) ||
+			    ((l = tgt_node_next(ll, XML_ELEMENT_LUN, NULL)) ==
+			    NULL)) {
+				xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
+				goto error;
+			}
+
+		} else {
+			xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
+			goto error;
+		}
+	} else {
+		if ((node_name = create_node_name(NULL, NULL)) == NULL) {
+			xml_rtn_msg(&msg, ERR_CREATE_NAME_TO_LONG);
+			goto error;
+		}
+
+		n = tgt_node_alloc(XML_ELEMENT_TARG, String, NULL);
+		attr = tgt_node_alloc(XML_ELEMENT_INCORE, String,
+		    XML_VALUE_TRUE);
+		tgt_node_add_attr(n, attr);
+		attr = tgt_node_alloc(XML_ELEMENT_VERS, String, "1.0");
+		tgt_node_add_attr(n, attr);
+
+		c = tgt_node_alloc(XML_ELEMENT_INAME, String, node_name);
+		tgt_node_add(n, c);
+
+		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);
+		attr = tgt_node_alloc(XML_ELEMENT_VERS, String, "1.0");
+		tgt_node_add_attr(l, attr);
+
+		zfs_lun(l, size, dataset);
+
+		/*
+		 * Now store this information on the ZVOL property so that
+		 * next time we get a share request the same data will be
+		 * used.
+		 */
+		free(prop);
+		prop = NULL;
+		tgt_dump2buf(n, &prop);
+		if (zfs_prop_set(zfsh, zfs_prop_to_name(ZFS_PROP_ISCSIOPTIONS),
+		    prop)) {
+			xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
+			goto error;
+		}
+	}
+
+	/*
+	 * NOTE: 'n' is expected to be the target node for this
+	 * ZVOL at this point.
+	 */
+
+	/*
+	 * Several 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.
+	 */
+	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);
+
+	tgt_node_add(targets_config, n);
+
+	xml_rtn_msg(&msg, ERR_SUCCESS);
+error:
+	if (zfsh)
+		zfs_close(zfsh);
+	if (zh)
+		libzfs_fini(zh);
+	if (dataset)
+		free(dataset);
+	if (node_name)
+		free(node_name);
+	if (prop)
+		free(prop);
+	return (msg);
+}
+
 /*
  * []------------------------------------------------------------------[]
  * | Utility functions used by the routines above.			|
@@ -393,7 +627,8 @@
 {
 	uuid_t	id;
 	char	id_str[37],
-		*p;
+		*p,
+		*anp;		/* alias or nick pointer */
 
 	if ((p = (char *)malloc(ISCSI_MAX_NAME_LEN)) == NULL)
 		return (NULL);
@@ -411,12 +646,26 @@
 	 */
 	uuid_generate(id);
 	uuid_unparse(id, id_str);
-	if (snprintf(p, ISCSI_MAX_NAME_LEN, "iqn.1986-03.com.sun:%02d:%s.%s",
-	    TARGET_NAME_VERS, id_str, alias != NULL ? alias : local_nick) >
-	    ISCSI_MAX_NAME_LEN) {
+	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);
 }
@@ -632,7 +881,7 @@
 	char			path[MAXPATHLEN],
 				buf[512];
 	struct statvfs		fs;
-	xml_node_t		*node			= NULL,
+	tgt_node_t		*node			= NULL,
 				*c;
 	xmlTextReaderPtr	r;
 
@@ -732,18 +981,18 @@
 		    target_basedir, targ_name, PARAMBASE, lun);
 		if (r = (xmlTextReaderPtr)xmlReaderForFile(path, NULL, 0)) {
 			while (xmlTextReaderRead(r) == 1)
-				if (xml_process_node(r, &node) == False)
+				if (tgt_node_process(r, &node) == False)
 					break;
-			c = xml_alloc_node(XML_ELEMENT_STATUS, String,
+			c = tgt_node_alloc(XML_ELEMENT_STATUS, String,
 			    TGT_STATUS_ONLINE);
-			xml_replace_child(node, c, MatchName);
-			xml_tree_free(c);
-			if (xml_dump2file(node, path) == False) {
+			tgt_node_replace(node, c, MatchName);
+			tgt_node_free(c);
+			if (tgt_dump2file(node, path) == False) {
 				queue_prt(mgmtq, Q_STE_ERRS,
 				    "GEN%d  failed to dump out params", lun);
 				goto error;
 			}
-			xml_tree_free(node);
+			tgt_node_free(node);
 			xmlTextReaderClose(r);
 			xmlFreeTextReader(r);
 			xmlCleanupParser();
@@ -999,3 +1248,52 @@
 	(void) close(fd);
 	return (rval);
 }
+
+static void
+zfs_lun(tgt_node_t *l, uint64_t size, char *dataset)
+{
+	tgt_node_t	*c;
+	int		cylinders,
+			heads,
+			spt,
+			val,
+			guid;
+	create_geom(size, &cylinders, &heads, &spt);
+
+	guid = 0;
+	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);
+
+	val = DEFAULT_RPM;
+	c = tgt_node_alloc(XML_ELEMENT_RPM, Int, &val);
+	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);
+
+	val = DEFAULT_BYTES_PER;
+	c = tgt_node_alloc(XML_ELEMENT_BPS, Int, &val);
+	tgt_node_add(l, c);
+
+	val = DEFAULT_INTERLEAVE;
+	c = tgt_node_alloc(XML_ELEMENT_INTERLEAVE, Int, &val);
+	tgt_node_add(l, c);
+
+	c = tgt_node_alloc(XML_ELEMENT_STATUS, String, TGT_STATUS_ONLINE);
+	tgt_node_add(l, c);
+}
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_list.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/mgmt_list.c	Wed Nov 15 19:25:44 2006 -0800
@@ -36,8 +36,8 @@
 #include <strings.h>
 #include <dirent.h>
 
+#include <iscsitgt_impl.h>
 #include "utility.h"
-#include <xml.h>
 #include "queue.h"
 #include "target.h"
 #include "iscsi_cmd.h"
@@ -45,18 +45,18 @@
 #include "port.h"
 #include "errcode.h"
 
-static char *list_targets(xml_node_t *x);
-static char *list_initiator(xml_node_t *x);
-static char *list_tpgt(xml_node_t *x);
-static char *list_admin(xml_node_t *x);
-static void target_info(char **msg, char *targ_name, xml_node_t *tnode);
+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(xml_node_t *p, target_queue_t *reply, target_queue_t *mgmt)
+list_func(tgt_node_t *p, target_queue_t *reply, target_queue_t *mgmt)
 {
-	xml_node_t	*x;
+	tgt_node_t	*x;
 	char		msgbuf[80],
 			*reply_msg	= NULL;
 
@@ -86,12 +86,12 @@
 }
 
 static char *
-list_targets(xml_node_t *x)
+list_targets(tgt_node_t *x)
 {
 	char		*msg	= NULL,
 			*prop	= NULL,
 			*iname	= NULL;
-	xml_node_t	*targ	= NULL;
+	tgt_node_t	*targ	= NULL;
 	Boolean_t	luninfo	= False,
 			dostat	= False;
 
@@ -100,153 +100,156 @@
 	 * administrator wants a complete list of targets. However if a
 	 * "name" is supplied then there must be a value for that element.
 	 */
-	if ((xml_find_value_str(x, XML_ELEMENT_NAME, &prop) == True) &&
+	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) xml_find_value_boolean(x, XML_ELEMENT_LUNINFO, &luninfo);
-	(void) xml_find_value_boolean(x, XML_ELEMENT_IOSTAT, &dostat);
+	(void) tgt_find_value_boolean(x, XML_ELEMENT_LUNINFO, &luninfo);
+	(void) tgt_find_value_boolean(x, XML_ELEMENT_IOSTAT, &dostat);
 
-	buf_add_tag_and_attr(&msg, XML_ELEMENT_RESULT, "version='1.0'");
-	while ((targ = xml_node_next(targets_config, XML_ELEMENT_TARG,
+	tgt_buf_add_tag_and_attr(&msg, XML_ELEMENT_RESULT, "version='1.0'");
+	while ((targ = tgt_node_next(targets_config, XML_ELEMENT_TARG,
 	    targ)) != NULL) {
 		if (targ->x_value == NULL) {
-			xml_add_tag(&msg, XML_ELEMENT_TARG,
+			tgt_buf_add(&msg, XML_ELEMENT_TARG,
 				    "bogus entry");
 			continue;
 		}
-		if (xml_find_value_str(targ, XML_ELEMENT_INAME, &iname) ==
+		if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &iname) ==
 		    False) {
-			xml_add_tag(&msg, XML_ELEMENT_TARG,
+			tgt_buf_add(&msg, XML_ELEMENT_TARG,
 				    "missing iscsi-name");
 			continue;
 		}
 		if (prop != NULL) {
 			if (strcmp(prop, targ->x_value) == 0) {
-				buf_add_tag(&msg, XML_ELEMENT_TARG, Tag_Start);
-				buf_add_tag(&msg, targ->x_value, Tag_String);
-				xml_add_tag(&msg, XML_ELEMENT_INAME, iname);
+				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);
-				buf_add_tag(&msg, XML_ELEMENT_TARG, Tag_End);
+				tgt_buf_add_tag(&msg, XML_ELEMENT_TARG,
+				    Tag_End);
 			}
 		} else {
-			buf_add_tag(&msg, XML_ELEMENT_TARG, Tag_Start);
-			buf_add_tag(&msg, targ->x_value, Tag_String);
-			xml_add_tag(&msg, XML_ELEMENT_INAME, iname);
+			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);
-			buf_add_tag(&msg, XML_ELEMENT_TARG, Tag_End);
+			tgt_buf_add_tag(&msg, XML_ELEMENT_TARG, Tag_End);
 		}
 		free(iname);
 	}
-	buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End);
+	tgt_buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End);
 	free(prop);
 
 	return (msg);
 }
 
 static char *
-list_initiator(xml_node_t *x)
+list_initiator(tgt_node_t *x)
 {
 	char		*msg	= NULL,
 			*attr,
 			*prop	= NULL;
 	Boolean_t	verbose	= False;
-	xml_node_t	*init	= NULL;
+	tgt_node_t	*init	= NULL;
 
 	/* ---- Optional arguments ---- */
-	if ((xml_find_value_str(x, XML_ELEMENT_NAME, &prop) == True) &&
+	if ((tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == True) &&
 	    (prop == NULL)) {
 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
 		return (msg);
 	}
-	(void) xml_find_value_boolean(x, XML_ELEMENT_VERBOSE, &verbose);
+	(void) tgt_find_value_boolean(x, XML_ELEMENT_VERBOSE, &verbose);
 
-	buf_add_tag_and_attr(&msg, XML_ELEMENT_RESULT, "version='1.0'");
-	while ((init = xml_node_next(main_config, XML_ELEMENT_INIT, init)) !=
+	tgt_buf_add_tag_and_attr(&msg, XML_ELEMENT_RESULT, "version='1.0'");
+	while ((init = tgt_node_next(main_config, XML_ELEMENT_INIT, init)) !=
 	    NULL) {
 		if ((prop == NULL) ||
 		    ((prop != NULL) && (strcmp(prop, init->x_value) == 0))) {
 
-			buf_add_tag(&msg, XML_ELEMENT_INIT, Tag_Start);
-			buf_add_tag(&msg, init->x_value, Tag_String);
+			tgt_buf_add_tag(&msg, XML_ELEMENT_INIT, Tag_Start);
+			tgt_buf_add_tag(&msg, init->x_value, Tag_String);
 
-			if (xml_find_value_str(init, XML_ELEMENT_INAME,
+			if (tgt_find_value_str(init, XML_ELEMENT_INAME,
 			    &attr) == True) {
-				xml_add_tag(&msg, XML_ELEMENT_INAME, attr);
+				tgt_buf_add(&msg, XML_ELEMENT_INAME, attr);
 				free(attr);
 			}
 
-			if (xml_find_value_str(init, XML_ELEMENT_CHAPSECRET,
+			if (tgt_find_value_str(init, XML_ELEMENT_CHAPSECRET,
 			    &attr) == True) {
-				xml_add_tag(&msg, XML_ELEMENT_CHAPSECRET,
+				tgt_buf_add(&msg, XML_ELEMENT_CHAPSECRET,
 				    attr);
 				free(attr);
 			}
 
-			if (xml_find_value_str(init, XML_ELEMENT_CHAPNAME,
+			if (tgt_find_value_str(init, XML_ELEMENT_CHAPNAME,
 			    &attr) == True) {
-				xml_add_tag(&msg, XML_ELEMENT_CHAPNAME, attr);
+				tgt_buf_add(&msg, XML_ELEMENT_CHAPNAME, attr);
 				free(attr);
 			}
 
-			buf_add_tag(&msg, XML_ELEMENT_INIT, Tag_End);
+			tgt_buf_add_tag(&msg, XML_ELEMENT_INIT, Tag_End);
 		}
 	}
 
 	if (prop != NULL)
 		free(prop);
 
-	buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End);
+	tgt_buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End);
 
 	return (msg);
 }
 
 static char *
-list_tpgt(xml_node_t *x)
+list_tpgt(tgt_node_t *x)
 {
 	char		*msg	= NULL,
 			*prop	= NULL;
 	Boolean_t	verbose	= False;
-	xml_node_t	*tpgt	= NULL,
+	tgt_node_t	*tpgt	= NULL,
 			*ip	= NULL;
 
 	/* ---- Optional arguments ---- */
-	if ((xml_find_value_str(x, XML_ELEMENT_NAME, &prop) == True) &&
+	if ((tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == True) &&
 	    (prop == NULL)) {
 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
 		return (msg);
 	}
-	(void) xml_find_value_boolean(x, XML_ELEMENT_VERBOSE, &verbose);
+	(void) tgt_find_value_boolean(x, XML_ELEMENT_VERBOSE, &verbose);
 
-	buf_add_tag_and_attr(&msg, XML_ELEMENT_RESULT, "version='1.0'");
-	while ((tpgt = xml_node_next(main_config, XML_ELEMENT_TPGT, tpgt)) !=
+	tgt_buf_add_tag_and_attr(&msg, XML_ELEMENT_RESULT, "version='1.0'");
+	while ((tpgt = tgt_node_next(main_config, XML_ELEMENT_TPGT, tpgt)) !=
 	    NULL) {
 		if ((prop == NULL) ||
 		    ((prop != NULL) && (strcmp(prop, tpgt->x_value) == 0))) {
 
-			buf_add_tag(&msg, XML_ELEMENT_TPGT, Tag_Start);
-			buf_add_tag(&msg, tpgt->x_value, Tag_String);
+			tgt_buf_add_tag(&msg, XML_ELEMENT_TPGT, Tag_Start);
+			tgt_buf_add_tag(&msg, tpgt->x_value, Tag_String);
 
-			while ((ip = xml_node_next(tpgt, XML_ELEMENT_IPADDR,
+			while ((ip = tgt_node_next(tpgt, XML_ELEMENT_IPADDR,
 			    ip)) != NULL) {
-				xml_add_tag(&msg, ip->x_name, ip->x_value);
+				tgt_buf_add(&msg, ip->x_name, ip->x_value);
 			}
 
-			buf_add_tag(&msg, XML_ELEMENT_TPGT, Tag_End);
+			tgt_buf_add_tag(&msg, XML_ELEMENT_TPGT, Tag_End);
 		}
 	}
-	buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End);
+	tgt_buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End);
 
 	if (prop != NULL)
 		free(prop);
@@ -255,25 +258,25 @@
 
 /*ARGSUSED*/
 static char *
-list_admin(xml_node_t *x)
+list_admin(tgt_node_t *x)
 {
 	char		*msg	= NULL;
 	admin_table_t	*p;
-	xml_node_t	*node	= NULL;
+	tgt_node_t	*node	= NULL;
 
-	buf_add_tag_and_attr(&msg, XML_ELEMENT_RESULT, "version='1.0'");
-	buf_add_tag(&msg, XML_ELEMENT_ADMIN, Tag_Start);
+	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 = xml_node_next_child(main_config, p->name, NULL);
+		node = tgt_node_next_child(main_config, p->name, NULL);
 		if (node) {
-			xml_add_tag(&msg, p->name, node->x_value);
+			tgt_buf_add(&msg, p->name, node->x_value);
 		}
 	}
 
-	buf_add_tag(&msg, XML_ELEMENT_ADMIN, Tag_End);
-	buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End);
+	tgt_buf_add_tag(&msg, XML_ELEMENT_ADMIN, Tag_End);
+	tgt_buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End);
 
 	return (msg);
 }
@@ -335,113 +338,128 @@
 }
 
 static void
-target_info(char **msg, char *targ_name, xml_node_t *tnode)
+target_info(char **msg, char *targ_name, tgt_node_t *tnode)
 {
 	char			path[MAXPATHLEN],
 				lun_buf[16],
 				*prop;
 	xmlTextReaderPtr	r;
-	xml_node_t		*lnode,	/* list node */
+	tgt_node_t		*lnode,	/* list node */
 				*lnp, /* list node pointer */
 				*lun,
 				*params;
 	int			xml_fd,
 				lun_num;
+	Boolean_t		incore;
 
-	if ((lnode = xml_node_next(tnode, XML_ELEMENT_ACLLIST, NULL)) !=
+	if ((lnode = tgt_node_next(tnode, XML_ELEMENT_ACLLIST, NULL)) !=
 	    NULL) {
 		lnp = NULL;
-		buf_add_tag(msg, XML_ELEMENT_ACLLIST, Tag_Start);
-		while ((lnp = xml_node_next(lnode, XML_ELEMENT_INIT, lnp)) !=
+		tgt_buf_add_tag(msg, XML_ELEMENT_ACLLIST, Tag_Start);
+		while ((lnp = tgt_node_next(lnode, XML_ELEMENT_INIT, lnp)) !=
 		    NULL)
-			xml_add_tag(msg, XML_ELEMENT_INIT, lnp->x_value);
-		buf_add_tag(msg, XML_ELEMENT_ACLLIST, Tag_End);
+			tgt_buf_add(msg, XML_ELEMENT_INIT, lnp->x_value);
+		tgt_buf_add_tag(msg, XML_ELEMENT_ACLLIST, Tag_End);
 	}
 
-	if ((lnode = xml_node_next(tnode, XML_ELEMENT_TPGTLIST, NULL)) !=
+	if ((lnode = tgt_node_next(tnode, XML_ELEMENT_TPGTLIST, NULL)) !=
 	    NULL) {
 		lnp = NULL;
-		buf_add_tag(msg, XML_ELEMENT_TPGTLIST, Tag_Start);
-		while ((lnp = xml_node_next(lnode, XML_ELEMENT_TPGT, lnp)) !=
+		tgt_buf_add_tag(msg, XML_ELEMENT_TPGTLIST, Tag_Start);
+		while ((lnp = tgt_node_next(lnode, XML_ELEMENT_TPGT, lnp)) !=
 		    NULL)
-			xml_add_tag(msg, XML_ELEMENT_TPGT, lnp->x_value);
-		buf_add_tag(msg, XML_ELEMENT_TPGTLIST, Tag_End);
+			tgt_buf_add(msg, XML_ELEMENT_TPGT, lnp->x_value);
+		tgt_buf_add_tag(msg, XML_ELEMENT_TPGTLIST, Tag_End);
 	}
 
-	if ((lnode = xml_node_next(tnode, XML_ELEMENT_ALIAS, NULL)) != NULL)
-		xml_add_tag(msg, XML_ELEMENT_ALIAS, lnode->x_value);
+	if ((lnode = tgt_node_next(tnode, XML_ELEMENT_ALIAS, NULL)) != NULL)
+		tgt_buf_add(msg, XML_ELEMENT_ALIAS, lnode->x_value);
 
-	if ((lnode = xml_node_next(tnode, XML_ELEMENT_MAXRECV, NULL)) != NULL)
-		xml_add_tag(msg, XML_ELEMENT_MAXRECV, 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 = xml_node_next(tnode, XML_ELEMENT_LUNLIST, NULL)) == NULL)
+	if ((lnode = tgt_node_next(tnode, XML_ELEMENT_LUNLIST, NULL)) == NULL)
 		return;
 
-	buf_add_tag(msg, XML_ELEMENT_LUNINFO, Tag_Start);
+	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 = xml_node_next(lnode, XML_ELEMENT_LUN, lun)) != NULL) {
-		if ((xml_find_value_int(lun, XML_ELEMENT_LUN, &lun_num)) ==
+	while ((lun = tgt_node_next(lnode, 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/%s%d",
-		    target_basedir, targ_name, PARAMBASE, lun_num);
-		if ((xml_fd = open(path, O_RDONLY)) < 0)
-			continue;
-		if ((r = (xmlTextReaderPtr)xmlReaderForFd(xml_fd,
-		    NULL, NULL, 0)) == NULL)
-			continue;
+		if (incore == False) {
+			(void) snprintf(path, sizeof (path), "%s/%s/%s%d",
+			    target_basedir, targ_name, PARAMBASE, lun_num);
+			if ((xml_fd = open(path, O_RDONLY)) < 0)
+				continue;
+			if ((r = (xmlTextReaderPtr)xmlReaderForFd(xml_fd,
+			    NULL, NULL, 0)) == NULL)
+				continue;
 
-		params = NULL;
-		while (xmlTextReaderRead(r) == 1) {
-			if (xml_process_node(r, &params) == False)
-				break;
+			params = NULL;
+			while (xmlTextReaderRead(r) == 1) {
+				if (tgt_node_process(r, &params) == False)
+					break;
+			}
+			(void) close(xml_fd);
+			xmlTextReaderClose(r);
+			xmlFreeTextReader(r);
+		} else {
+			params = lun;
 		}
-		(void) close(xml_fd);
-		xmlTextReaderClose(r);
-		xmlFreeTextReader(r);
-
-		buf_add_tag(msg, XML_ELEMENT_LUN, Tag_Start);
-		snprintf(lun_buf, sizeof (lun_buf), "%d", lun_num);
-		buf_add_tag(msg, lun_buf, Tag_String);
 
-		if (xml_find_value_str(params, XML_ELEMENT_GUID, &prop) ==
+		tgt_buf_add_tag(msg, XML_ELEMENT_LUN, Tag_Start);
+		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) {
-			xml_add_tag(msg, XML_ELEMENT_GUID, prop);
-			free(prop);
-		}
-		if (xml_find_value_str(params, XML_ELEMENT_VID, &prop) ==
-		    True) {
-			xml_add_tag(msg, XML_ELEMENT_VID, prop);
+			tgt_buf_add(msg, XML_ELEMENT_GUID, prop);
 			free(prop);
 		}
-		if (xml_find_value_str(params, XML_ELEMENT_PID, &prop) ==
+		if (tgt_find_value_str(params, XML_ELEMENT_VID, &prop) ==
 		    True) {
-			xml_add_tag(msg, XML_ELEMENT_PID, prop);
+			tgt_buf_add(msg, XML_ELEMENT_VID, prop);
 			free(prop);
 		}
-		if (xml_find_value_str(params, XML_ELEMENT_DTYPE, &prop) ==
+		if (tgt_find_value_str(params, XML_ELEMENT_PID, &prop) ==
 		    True) {
-			xml_add_tag(msg, XML_ELEMENT_DTYPE, prop);
+			tgt_buf_add(msg, XML_ELEMENT_PID, prop);
 			free(prop);
 		}
-		if (xml_find_value_str(params, XML_ELEMENT_SIZE, &prop) ==
+		if (tgt_find_value_str(params, XML_ELEMENT_DTYPE, &prop) ==
 		    True) {
-			xml_add_tag(msg, XML_ELEMENT_SIZE, prop);
+			tgt_buf_add(msg, XML_ELEMENT_DTYPE, prop);
 			free(prop);
 		}
-		if (xml_find_value_str(params, XML_ELEMENT_STATUS, &prop) ==
+		if (tgt_find_value_str(params, XML_ELEMENT_SIZE, &prop) ==
 		    True) {
-			xml_add_tag(msg, XML_ELEMENT_STATUS, prop);
+			tgt_buf_add(msg, XML_ELEMENT_SIZE, prop);
+			free(prop);
+		}
+		if (tgt_find_value_str(params, XML_ELEMENT_STATUS, &prop) ==
+		    True) {
+			tgt_buf_add(msg, XML_ELEMENT_STATUS, prop);
 			free(prop);
 		}
-		if (xml_find_value_str(params, XML_ELEMENT_BACK, &prop) ==
+		if (tgt_find_value_str(params, XML_ELEMENT_BACK, &prop) ==
 		    True) {
-			xml_add_tag(msg, XML_ELEMENT_BACK, prop);
+			tgt_buf_add(msg, XML_ELEMENT_BACK, prop);
 			free(prop);
 		}
-		buf_add_tag(msg, XML_ELEMENT_LUN, Tag_End);
+		tgt_buf_add_tag(msg, XML_ELEMENT_LUN, Tag_End);
 
-		xml_tree_free(params);
+		if (incore == False)
+			tgt_node_free(params);
 	}
-	buf_add_tag(msg, XML_ELEMENT_LUNINFO, Tag_End);
+	tgt_buf_add_tag(msg, XML_ELEMENT_LUNINFO, Tag_End);
 }
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_modify.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/mgmt_modify.c	Wed Nov 15 19:25:44 2006 -0800
@@ -38,19 +38,21 @@
 #include <assert.h>
 #include <sys/socket.h>
 #include <netdb.h>
+#include <libzfs.h>
 
-#include "xml.h"
+#include <iscsitgt_impl.h>
 #include "queue.h"
 #include "utility.h"
 #include "iscsi_cmd.h"
 #include "target.h"
 #include "errcode.h"
 
-static char *modify_target(xml_node_t *x);
-static char *modify_initiator(xml_node_t *x);
-static char *modify_admin(xml_node_t *x);
-static char *modify_tpgt(xml_node_t *x);
-static Boolean_t modify_element(char *, char *, xml_node_t *, match_type_t);
+static char *modify_target(tgt_node_t *x);
+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);
+static Boolean_t modify_element(char *, char *, tgt_node_t *, match_type_t);
 
 /*
  * []----
@@ -59,9 +61,9 @@
  */
 /*ARGSUSED*/
 void
-modify_func(xml_node_t *p, target_queue_t *reply, target_queue_t *mgmt)
+modify_func(tgt_node_t *p, target_queue_t *reply, target_queue_t *mgmt)
 {
-	xml_node_t	*x;
+	tgt_node_t	*x;
 	char		*reply_msg	= NULL;
 
 	if (p->x_child == NULL) {
@@ -80,6 +82,8 @@
 			reply_msg = modify_admin(x);
 		} else if (strcmp(x->x_name, XML_ELEMENT_TPGT) == 0) {
 			reply_msg = modify_tpgt(x);
+		} else if (strcmp(x->x_name, XML_ELEMENT_ZFS) == 0) {
+			reply_msg = modify_zfs(x);
 		} else {
 			xml_rtn_msg(&reply_msg, ERR_INVALID_OBJECT);
 		}
@@ -93,7 +97,7 @@
  * []----
  */
 static char *
-modify_target(xml_node_t *x)
+modify_target(tgt_node_t *x)
 {
 	char		*msg		= NULL,
 			*name		= NULL,
@@ -103,7 +107,7 @@
 			path[MAXPATHLEN],
 			*m,
 			buf[512];		/* one sector size block */
-	xml_node_t	*t		= NULL,
+	tgt_node_t	*t		= NULL,
 			*list		= NULL,
 			*c		= NULL,
 			*node;
@@ -117,12 +121,12 @@
 	struct stat	st;
 	xmlTextReaderPtr	r;
 
-	if (xml_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
+	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
 		return (msg);
 	}
 
-	while ((t = xml_node_next(targets_config, XML_ELEMENT_TARG,
+	while ((t = tgt_node_next(targets_config, XML_ELEMENT_TARG,
 	    t)) != NULL) {
 		if (strcmp(t->x_value, name) == 0) {
 			break;
@@ -146,7 +150,7 @@
 	 * layer so that the LU thread can remap the smaller size without
 	 * anyone accessing the data.
 	 */
-	if (xml_find_value_str(x, XML_ELEMENT_SIZE, &prop) == True) {
+	if (tgt_find_value_str(x, XML_ELEMENT_SIZE, &prop) == True) {
 		if (prop == NULL) {
 			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_TPGT);
 			return (msg);
@@ -163,13 +167,13 @@
 		}
 		new_lu_size /= 512LL;
 
-		if (xml_find_value_str(x, XML_ELEMENT_INAME, &iscsi) == False) {
+		if (tgt_find_value_str(x, XML_ELEMENT_INAME, &iscsi) == False) {
 			xml_rtn_msg(&msg, ERR_TARGCFG_MISSING_INAME);
 			return (msg);
 		}
 
 		/* ---- default to LUN 0 ---- */
-		(void) xml_find_value_int(x, XML_ELEMENT_LUN, &lun);
+		(void) tgt_find_value_int(x, XML_ELEMENT_LUN, &lun);
 
 		/* ---- read in current paramaters ---- */
 		snprintf(path, sizeof (path), "%s/%s/%s%d", target_basedir,
@@ -182,7 +186,7 @@
 		    0)) != NULL) {
 			node = NULL;
 			while (xmlTextReaderRead(r) == 1)
-				if (xml_process_node(r, &node) == False)
+				if (tgt_node_process(r, &node) == False)
 					break;
 		} else {
 			xml_rtn_msg(&msg, ERR_INIT_XML_READER_FAILED);
@@ -194,7 +198,7 @@
 		xmlFreeTextReader(r);
 
 		/* ---- validate that we're indeed growing the LU ---- */
-		if (xml_find_value_str(node, XML_ELEMENT_SIZE, &prop) ==
+		if (tgt_find_value_str(node, XML_ELEMENT_SIZE, &prop) ==
 		    False) {
 			xml_rtn_msg(&msg, ERR_INIT_XML_READER_FAILED);
 			return (msg);
@@ -212,7 +216,7 @@
 		}
 
 		/* ---- check that this LU is of type 'disk' or 'tape' ---- */
-		if (xml_find_value_str(node, XML_ELEMENT_DTYPE, &prop) ==
+		if (tgt_find_value_str(node, XML_ELEMENT_DTYPE, &prop) ==
 		    False) {
 			xml_rtn_msg(&msg, ERR_INIT_XML_READER_FAILED);
 			return (msg);
@@ -239,18 +243,18 @@
 
 		/* ---- update the parameter node with new size ---- */
 		snprintf(size_str, sizeof (size_str), "0x%llx", new_lu_size);
-		if ((c = xml_alloc_node(XML_ELEMENT_SIZE, Uint64, size_str)) ==
+		if ((c = tgt_node_alloc(XML_ELEMENT_SIZE, Uint64, size_str)) ==
 		    False) {
 			xml_rtn_msg(&msg, ERR_NO_MEM);
 			return (msg);
 		}
-		xml_replace_child(node, c, MatchName);
-		xml_tree_free(c);
+		tgt_node_replace(node, c, MatchName);
+		tgt_node_free(c);
 
 		/* ---- now update params file ---- */
 		snprintf(path, sizeof (path), "%s/%s/%s%d", target_basedir,
 		    iscsi, PARAMBASE, lun);
-		if (xml_dump2file(node, path) == False) {
+		if (tgt_dump2file(node, path) == False) {
 			xml_rtn_msg(&msg, ERR_UPDATE_TARGCFG_FAILED);
 			return (msg);
 		}
@@ -275,10 +279,10 @@
 
 		free(iscsi);
 		prop = NULL;
-		xml_tree_free(node);
+		tgt_node_free(node);
 	}
 
-	if (xml_find_value_str(x, XML_ELEMENT_TPGT, &prop) == True) {
+	if (tgt_find_value_str(x, XML_ELEMENT_TPGT, &prop) == True) {
 		if (prop == NULL) {
 			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ACL);
 			return (msg);
@@ -295,68 +299,68 @@
 			return (msg);
 		}
 
-		if ((c = xml_alloc_node(XML_ELEMENT_TPGT, String, prop)) ==
+		if ((c = tgt_node_alloc(XML_ELEMENT_TPGT, String, prop)) ==
 		    NULL) {
 			free(prop);
 			xml_rtn_msg(&msg, ERR_NO_MEM);
 			return (msg);
 		}
 
-		if ((list = xml_node_next(t, XML_ELEMENT_TPGTLIST,
+		if ((list = tgt_node_next(t, XML_ELEMENT_TPGTLIST,
 		    NULL)) != NULL) {
-			xml_replace_child(list, c, MatchBoth);
+			tgt_node_replace(list, c, MatchBoth);
 			/*
-			 * xml_replace_child will duplicate the child node
-			 * xml_add_child which is used below just links it
+			 * tgt_node_replace will duplicate the child node
+			 * tgt_node_add which is used below just links it
 			 * into the tree.
 			 */
-			xml_tree_free(c);
+			tgt_node_free(c);
 		} else {
-			list = xml_alloc_node(XML_ELEMENT_TPGTLIST, String, "");
+			list = tgt_node_alloc(XML_ELEMENT_TPGTLIST, String, "");
 			if (list == NULL) {
 				free(prop);
 				xml_rtn_msg(&msg, ERR_NO_MEM);
 				return (msg);
 			}
-			(void) xml_add_child(list, c);
-			(void) xml_add_child(t, list);
+			tgt_node_add(list, c);
+			tgt_node_add(t, list);
 		}
 		free(prop);
 		prop = NULL;
 		change_made = True;
 	}
 
-	if (xml_find_value_str(x, XML_ELEMENT_ACL, &prop) == True) {
+	if (tgt_find_value_str(x, XML_ELEMENT_ACL, &prop) == True) {
 		if (prop == NULL) {
 			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ACL);
 			return (msg);
 		}
 
-		c = xml_alloc_node(XML_ELEMENT_INIT, String, prop);
+		c = tgt_node_alloc(XML_ELEMENT_INIT, String, prop);
 		if (c == NULL) {
 			xml_rtn_msg(&msg, ERR_NO_MEM);
 			return (msg);
 		}
-		if ((list = xml_node_next(t, XML_ELEMENT_ACLLIST,
+		if ((list = tgt_node_next(t, XML_ELEMENT_ACLLIST,
 		    NULL)) != NULL) {
-			xml_replace_child(list, c, MatchBoth);
+			tgt_node_replace(list, c, MatchBoth);
 			/* ---- See above usage ---- */
-			xml_tree_free(c);
+			tgt_node_free(c);
 		} else {
-			list = xml_alloc_node(XML_ELEMENT_ACLLIST, String, "");
+			list = tgt_node_alloc(XML_ELEMENT_ACLLIST, String, "");
 			if (list == NULL) {
 				xml_rtn_msg(&msg, ERR_NO_MEM);
 				return (msg);
 			}
-			(void) xml_add_child(list, c);
-			(void) xml_add_child(t, list);
+			tgt_node_add(list, c);
+			tgt_node_add(t, list);
 		}
 		free(prop);
 		prop = NULL;
 		change_made = True;
 	}
 
-	if (xml_find_value_str(x, XML_ELEMENT_ALIAS, &prop) == True) {
+	if (tgt_find_value_str(x, XML_ELEMENT_ALIAS, &prop) == True) {
 		if (prop == NULL) {
 			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ALIAS);
 			return (msg);
@@ -372,7 +376,7 @@
 		change_made = True;
 	}
 
-	if (xml_find_value_str(x, XML_ELEMENT_MAXRECV, &prop) == True) {
+	if (tgt_find_value_str(x, XML_ELEMENT_MAXRECV, &prop) == True) {
 		if (prop == NULL) {
 			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_MAXRECV);
 			return (msg);
@@ -418,20 +422,20 @@
  * []----
  */
 static char *
-modify_initiator(xml_node_t *x)
+modify_initiator(tgt_node_t *x)
 {
 	char		*msg		= NULL,
 			*name		= NULL,
 			*prop		= NULL;
-	xml_node_t	*inode		= NULL;
+	tgt_node_t	*inode		= NULL;
 	Boolean_t	changes_made	= False;
 
-	if (xml_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
+	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
 		return (msg);
 	}
 
-	while ((inode = xml_node_next(main_config, XML_ELEMENT_INIT,
+	while ((inode = tgt_node_next(main_config, XML_ELEMENT_INIT,
 	    inode)) != NULL) {
 		if (strcmp(inode->x_value, name) == 0)
 			break;
@@ -449,7 +453,7 @@
 		return (msg);
 	}
 
-	if (xml_find_value_str(x, XML_ELEMENT_CHAPSECRET, &prop) == True) {
+	if (tgt_find_value_str(x, XML_ELEMENT_CHAPSECRET, &prop) == True) {
 		if (prop == NULL) {
 			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_CHAPSECRET);
 			return (msg);
@@ -464,7 +468,7 @@
 		changes_made = True;
 	}
 
-	if (xml_find_value_str(x, XML_ELEMENT_CHAPNAME, &prop) == True) {
+	if (tgt_find_value_str(x, XML_ELEMENT_CHAPNAME, &prop) == True) {
 		if (prop == NULL) {
 			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_CHAPNAME);
 			return (msg);
@@ -495,7 +499,7 @@
  * []----
  */
 static char *
-modify_admin(xml_node_t *x)
+modify_admin(tgt_node_t *x)
 {
 	char		*msg	= NULL,
 			*prop;
@@ -503,7 +507,7 @@
 	admin_table_t	*ap;
 
 	for (ap = admin_prop_list; ap->name; ap++) {
-		if (xml_find_value_str(x, ap->name, &prop) == True) {
+		if (tgt_find_value_str(x, ap->name, &prop) == True) {
 
 			if ((prop == NULL) || (strlen(prop) == 0))
 				break;
@@ -542,19 +546,19 @@
  * []----
  */
 static char *
-modify_tpgt(xml_node_t *x)
+modify_tpgt(tgt_node_t *x)
 {
 	struct addrinfo	*res	= NULL;
 	char		*msg	= NULL,
 			*name	= NULL,
 			*ip_str	= NULL;
-	xml_node_t	*tnode	= NULL;
+	tgt_node_t	*tnode	= NULL;
 
-	if (xml_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
+	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
 		goto error;
 	}
-	if (xml_find_value_str(x, XML_ELEMENT_IPADDR, &ip_str) == False) {
+	if (tgt_find_value_str(x, XML_ELEMENT_IPADDR, &ip_str) == False) {
 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_IPADDR);
 		goto error;
 	}
@@ -562,7 +566,7 @@
 		xml_rtn_msg(&msg, ERR_INVALID_IP);
 		goto error;
 	}
-	while ((tnode = xml_node_next(main_config, XML_ELEMENT_TPGT,
+	while ((tnode = tgt_node_next(main_config, XML_ELEMENT_TPGT,
 	    tnode)) != NULL) {
 		if (strcmp(tnode->x_value, name) == 0)
 			break;
@@ -588,6 +592,52 @@
 	return (msg);
 }
 
+static char *
+modify_zfs(tgt_node_t *x)
+{
+	char		*msg		= NULL,
+			*prop		= NULL,
+			*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_ANY)) == NULL)) {
+		xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND);
+		goto error;
+	}
+
+	while ((n = tgt_node_next(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
@@ -596,15 +646,15 @@
  * []----
  */
 static Boolean_t
-modify_element(char *name, char *value, xml_node_t *p, match_type_t m)
+modify_element(char *name, char *value, tgt_node_t *p, match_type_t m)
 {
-	xml_node_t	*c;
+	tgt_node_t	*c;
 
-	if ((c = xml_alloc_node(name, String, value)) == NULL)
+	if ((c = tgt_node_alloc(name, String, value)) == NULL)
 		return (False);
 	else {
-		xml_replace_child(p, c, m);
-		xml_tree_free(c);
+		tgt_node_replace(p, c, m);
+		tgt_node_free(c);
 		return (True);
 	}
 }
@@ -625,7 +675,7 @@
 char *
 update_basedir(char *name, char *prop)
 {
-	xml_node_t	*targ	= NULL;
+	tgt_node_t	*targ	= NULL;
 	int		count	= 0;
 	char		*msg	= NULL;
 
@@ -634,7 +684,7 @@
 		return (msg);
 	}
 
-	while ((targ = xml_node_next(targets_config, XML_ELEMENT_TARG,
+	while ((targ = tgt_node_next(targets_config, XML_ELEMENT_TARG,
 	    targ)) != NULL) {
 		count++;
 	}
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c	Wed Nov 15 19:25:44 2006 -0800
@@ -36,22 +36,24 @@
 #include <strings.h>
 #include <unistd.h>
 
+#include <iscsitgt_impl.h>
 #include "utility.h"
-#include "xml.h"
 #include "queue.h"
 #include "target.h"
 #include "iscsi_cmd.h"
 #include "errcode.h"
 
-static char *remove_target(xml_node_t *x);
-static char *remove_initiator(xml_node_t *x);
-static char *remove_tpgt(xml_node_t *x);
+static char *remove_target(tgt_node_t *x);
+static char *remove_initiator(tgt_node_t *x);
+static char *remove_tpgt(tgt_node_t *x);
+static char *remove_zfs(tgt_node_t *x);
+
 
 /*ARGSUSED*/
 void
-remove_func(xml_node_t *p, target_queue_t *reply, target_queue_t *mgmt)
+remove_func(tgt_node_t *p, target_queue_t *reply, target_queue_t *mgmt)
 {
-	xml_node_t	*x;
+	tgt_node_t	*x;
 	char		msgbuf[80],
 			*reply_msg	= NULL;
 
@@ -68,6 +70,8 @@
 			reply_msg = remove_initiator(x);
 		} else if (strcmp(x->x_name, XML_ELEMENT_TPGT) == 0) {
 			reply_msg = remove_tpgt(x);
+		} else if (strcmp(x->x_name, XML_ELEMENT_ZFS) == 0) {
+			reply_msg = remove_zfs(x);
 		} else {
 			(void) snprintf(msgbuf, sizeof (msgbuf),
 			    "Unknown object '%s' for delete element",
@@ -79,22 +83,71 @@
 }
 
 static char *
-remove_target(xml_node_t *x)
+remove_zfs(tgt_node_t *x)
+{
+	char		*prop,
+			*msg		= NULL;
+	tgt_node_t	*targ		= NULL;
+
+	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) {
+		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
+		return (msg);
+	}
+
+	while ((targ = tgt_node_next(targets_config, XML_ELEMENT_TARG, targ))
+	    != NULL) {
+		if (strcmp(targ->x_value, prop) == 0)
+			break;
+	}
+	free(prop);
+	if (targ == NULL) {
+		/*
+		 * We're unsharing a target. If we don't have a reference
+		 * then there's no problem.
+		 */
+		xml_rtn_msg(&msg, ERR_SUCCESS);
+		return (msg);
+	}
+	if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &prop) ==
+	    False) {
+		xml_rtn_msg(&msg, ERR_TARGCFG_MISSING_INAME);
+		return (msg);
+	}
+
+	tgt_node_remove(targets_config, targ, 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 until here
+	 * to issue the logout we'll have removed reference to the target
+	 * such that this can't happen.
+	 */
+	logout_targ(prop);
+	free(prop);
+
+	xml_rtn_msg(&msg, ERR_SUCCESS);
+	return (msg);
+}
+
+static char *
+remove_target(tgt_node_t *x)
 {
 	char		*msg			= NULL,
 			*prop			= NULL;
-	xml_node_t	*targ			= NULL,
+	tgt_node_t	*targ			= NULL,
 			*list,
 			*c			= NULL;
 	Boolean_t	change_made		= False;
 	int		lun_num;
 
-	if (xml_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) {
+	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) {
 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
 		return (msg);
 	}
 
-	while ((targ = xml_node_next(targets_config, XML_ELEMENT_TARG, targ)) !=
+	while ((targ = tgt_node_next(targets_config, XML_ELEMENT_TARG, targ)) !=
 	    NULL) {
 		if (strcmp(targ->x_value, prop) == 0)
 			break;
@@ -104,53 +157,53 @@
 		xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND);
 		return (msg);
 	}
-	if (xml_find_value_str(x, XML_ELEMENT_ACL, &prop) == True) {
+	if (tgt_find_value_str(x, XML_ELEMENT_ACL, &prop) == True) {
 		if (prop == NULL) {
 			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ACL);
 			return (msg);
 		}
-		if ((list = xml_node_next(targ, XML_ELEMENT_ACLLIST, NULL)) ==
+		if ((list = tgt_node_next(targ, XML_ELEMENT_ACLLIST, NULL)) ==
 		    NULL) {
 			free(prop);
 			xml_rtn_msg(&msg, ERR_ACL_NOT_FOUND);
 			return (msg);
 		}
-		c = xml_alloc_node(XML_ELEMENT_INIT, String, prop);
-		if (xml_remove_child(list, c, MatchBoth) == False) {
+		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;
 		}
-		xml_free_node(c);
+		tgt_node_free(c);
 		if (list->x_child == NULL)
-			(void) xml_remove_child(targ, list, MatchName);
+			(void) tgt_node_remove(targ, list, MatchName);
 		free(prop);
 		change_made = True;
 	}
-	if (xml_find_value_str(x, XML_ELEMENT_TPGT, &prop) == True) {
+	if (tgt_find_value_str(x, XML_ELEMENT_TPGT, &prop) == True) {
 		if (prop == NULL) {
 			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_TPGT);
 			return (msg);
 		}
-		if ((list = xml_node_next(targ, XML_ELEMENT_TPGTLIST, NULL)) ==
+		if ((list = tgt_node_next(targ, XML_ELEMENT_TPGTLIST, NULL)) ==
 		    NULL) {
 			free(prop);
 			xml_rtn_msg(&msg, ERR_ACL_NOT_FOUND);
 			return (msg);
 		}
-		c = xml_alloc_node(XML_ELEMENT_TPGT, String, prop);
-		if (xml_remove_child(list, c, MatchBoth) == False) {
+		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;
 		}
-		xml_free_node(c);
+		tgt_node_free(c);
 		if (list->x_child == NULL)
-			(void) xml_remove_child(targ, list, MatchName);
+			(void) tgt_node_remove(targ, list, MatchName);
 		free(prop);
 		change_made = True;
 	}
-	if (xml_find_value_int(x, XML_ELEMENT_LUN, &lun_num) == True) {
+	if (tgt_find_value_int(x, XML_ELEMENT_LUN, &lun_num) == True) {
 
-		if (xml_find_value_intchk(x, XML_ELEMENT_LUN, &lun_num) ==
+		if (tgt_find_value_intchk(x, XML_ELEMENT_LUN, &lun_num) ==
 		    False) {
 			xml_rtn_msg(&msg, ERR_LUN_INVALID_RANGE);
 			return (msg);
@@ -159,7 +212,7 @@
 		/*
 		 * Save the iscsi-name which we'll need to remove LUNs.
 		 */
-		if (xml_find_value_str(targ, XML_ELEMENT_INAME, &prop) ==
+		if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &prop) ==
 		    False) {
 			xml_rtn_msg(&msg, ERR_TARGCFG_MISSING_INAME);
 			return (msg);
@@ -188,24 +241,24 @@
 
 error:
 	if (c != NULL)
-		xml_free_node(c);
+		tgt_node_free(c);
 	if (prop != NULL)
 		free(prop);
 	return (msg);
 }
 
 static char *
-remove_initiator(xml_node_t *x)
+remove_initiator(tgt_node_t *x)
 {
 	char		*msg	= NULL,
 			*name;
-	xml_node_t	*node	= NULL;
+	tgt_node_t	*node	= NULL;
 
-	if (xml_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
+	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
 		return (msg);
 	}
-	while ((node = xml_node_next(main_config, XML_ELEMENT_INIT, node)) !=
+	while ((node = tgt_node_next(main_config, XML_ELEMENT_INIT, node)) !=
 	    NULL) {
 		if (strcmp(node->x_value, name) == 0)
 			break;
@@ -215,11 +268,11 @@
 		xml_rtn_msg(&msg, ERR_INIT_NOT_FOUND);
 		return (msg);
 	}
-	if (xml_find_value_str(x, XML_ELEMENT_ALL, &name) == False) {
+	if (tgt_find_value_str(x, XML_ELEMENT_ALL, &name) == False) {
 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_ALL);
 		return (msg);
 	}
-	(void) xml_remove_child(main_config, node, MatchBoth);
+	(void) tgt_node_remove(main_config, node, MatchBoth);
 
 	if (update_config_main(&msg) == True)
 		xml_rtn_msg(&msg, ERR_SUCCESS);
@@ -228,19 +281,19 @@
 }
 
 static char *
-remove_tpgt(xml_node_t *x)
+remove_tpgt(tgt_node_t *x)
 {
 	char		*msg		= NULL,
 			*prop		= NULL;
-	xml_node_t	*node		= NULL,
+	tgt_node_t	*node		= NULL,
 			*c		= NULL;
 	Boolean_t	change_made	= False;
 
-	if (xml_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) {
+	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) {
 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
 		return (msg);
 	}
-	while ((node = xml_node_next(main_config, XML_ELEMENT_TPGT, node)) !=
+	while ((node = tgt_node_next(main_config, XML_ELEMENT_TPGT, node)) !=
 	    NULL) {
 		if (strcmp(node->x_value, prop) == 0)
 			break;
@@ -250,23 +303,23 @@
 		xml_rtn_msg(&msg, ERR_TPGT_NOT_FOUND);
 		return (msg);
 	}
-	if (xml_find_value_str(x, XML_ELEMENT_IPADDR, &prop) == True) {
+	if (tgt_find_value_str(x, XML_ELEMENT_IPADDR, &prop) == True) {
 		if (prop == NULL) {
 			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_IPADDR);
 			return (msg);
 		}
-		c = xml_alloc_node(XML_ELEMENT_IPADDR, String, prop);
-		if (xml_remove_child(node, c, MatchBoth) == False) {
+		c = tgt_node_alloc(XML_ELEMENT_IPADDR, String, prop);
+		if (tgt_node_remove(node, c, MatchBoth) == False) {
 			xml_rtn_msg(&msg, ERR_INVALID_IP);
 			goto error;
 		}
-		xml_free_node(c);
+		tgt_node_free(c);
 		free(prop);
 		change_made = True;
 	}
 	if ((change_made != True) &&
-	    (xml_find_value_str(x, XML_ELEMENT_ALL, &prop) == True)) {
-		xml_remove_child(main_config, node, MatchBoth);
+	    (tgt_find_value_str(x, XML_ELEMENT_ALL, &prop) == True)) {
+		tgt_node_remove(main_config, node, MatchBoth);
 		change_made = True;
 	}
 
@@ -281,7 +334,7 @@
 
 error:
 	if (c != NULL)
-		xml_free_node(c);
+		tgt_node_free(c);
 	if (prop != NULL)
 		free(prop);
 	return (msg);
--- a/usr/src/cmd/iscsi/iscsitgtd/queue.h	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/queue.h	Wed Nov 15 19:25:44 2006 -0800
@@ -36,10 +36,9 @@
 #include <pthread.h>
 #include <sys/time.h>
 #include <stdarg.h>
-#include <xml.h>
 #include <synch.h>
 
-#include "local_types.h"
+#include <iscsitgt_impl.h>
 
 #define	Q_CONN_ERRS	0x00001
 #define	Q_CONN_LOGIN	0x00002
@@ -243,7 +242,7 @@
 	pthread_mutex_t	m_resp_mutex;
 	union {
 		char		**m_resp;
-		xml_node_t	*m_node;
+		tgt_node_t	*m_node;
 	} m_u;
 } mgmt_request_t;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/iscsi/iscsitgtd/svc-iscsitgt	Wed Nov 15 19:25:44 2006 -0800
@@ -0,0 +1,67 @@
+#!/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 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+. /lib/svc/share/smf_include.sh
+zone=`smf_zonename`
+
+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 1
+	[ $? -ne 0 ] && exit 1
+	;;
+
+*)
+	echo "Usage: $0 { start | stop }"
+	exit 1
+	;;
+esac
+
+exit $SMF_EXIT_OK
--- a/usr/src/cmd/iscsi/iscsitgtd/t10.h	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/t10.h	Wed Nov 15 19:25:44 2006 -0800
@@ -325,7 +325,8 @@
 	/*
 	 * Parameter information in XML format.
 	 */
-	xml_node_t		*l_root;
+	tgt_node_t		*l_root;
+	Boolean_t		l_root_okay_to_free;
 
 	/*
 	 * File descriptor for the open file which is the backing store
@@ -499,6 +500,15 @@
 	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;
+
 /*
  * []----
  * | Interfaces
@@ -611,24 +621,26 @@
  * | Declaration of emulation entry points				|
  * []------------------------------------------------------------------[]
  */
-Boolean_t sbc_init_common(t10_lu_common_t *lu);
-void sbc_fini_common(t10_lu_common_t *lu);
+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_init_per(t10_lu_impl_t *itl);
-void sbc_fini_per(t10_lu_impl_t *itl);
-Boolean_t ssc_init_common(t10_lu_common_t *lu);
-void ssc_fini_common(t10_lu_common_t *lu);
+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_init_per(t10_lu_impl_t *itl);
-void ssc_fini_per(t10_lu_impl_t *itl);
-Boolean_t raw_init_common(t10_lu_common_t *lu);
-void raw_fini_common(t10_lu_common_t *lu);
-void raw_init_per(t10_lu_impl_t *itl);
-void raw_fini_per(t10_lu_impl_t *itl);
-Boolean_t osd_init_common(t10_lu_common_t *lu);
-void osd_fini_common(t10_lu_common_t *lu);
-void osd_init_per(t10_lu_impl_t *itl);
-void osd_fini_per(t10_lu_impl_t *itl);
+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
 }
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_osd.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/t10_osd.c	Wed Nov 15 19:25:44 2006 -0800
@@ -72,16 +72,16 @@
  */
 /*ARGSUSED*/
 Boolean_t
-osd_init_common(t10_lu_common_t *lu)
+osd_common_init(t10_lu_common_t *lu)
 {
 	osd_params_t	*o;
 	char		*str;
-	xml_node_t	*node	= lu->l_root;
+	tgt_node_t	*node	= lu->l_root;
 
 	if ((o = (osd_params_t *)calloc(1, sizeof (*o))) == NULL)
 		return (False);
 
-	if (xml_find_value_str(node, XML_ELEMENT_SIZE, &str) == True) {
+	if (tgt_find_value_str(node, XML_ELEMENT_SIZE, &str) == True) {
 		o->o_size = strtoll(str, NULL, 0);
 		free(str);
 	} else {
@@ -95,7 +95,7 @@
 
 /*ARGSUSED*/
 void
-osd_fini_common(t10_lu_common_t *lu)
+osd_common_fini(t10_lu_common_t *lu)
 {
 	free(lu->l_dtype_params);
 }
@@ -107,7 +107,7 @@
  */
 /*ARGSUSED*/
 void
-osd_init_per(t10_lu_impl_t *itl)
+osd_per_init(t10_lu_impl_t *itl)
 {
 	itl->l_cmd	= osd_cmd;
 	itl->l_data	= osd_data;
@@ -124,7 +124,13 @@
 
 /*ARGSUSED*/
 void
-osd_fini_per(t10_lu_impl_t *itl)
+osd_per_fini(t10_lu_impl_t *itl)
+{
+}
+
+/*ARGSUSED*/
+void
+osd_task_mgmt(t10_lu_common_t *lu, TaskOp_t op)
 {
 }
 
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_raw_if.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/t10_raw_if.c	Wed Nov 15 19:25:44 2006 -0800
@@ -96,16 +96,16 @@
  * []----
  */
 Boolean_t
-raw_init_common(t10_lu_common_t *lu)
+raw_common_init(t10_lu_common_t *lu)
 {
-	xml_node_t	*node	= lu->l_root;
+	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 (xml_find_value_str(node, XML_ELEMENT_SIZE, &str) == True) {
+	if (tgt_find_value_str(node, XML_ELEMENT_SIZE, &str) == True) {
 		r->r_size = strtoll(str, NULL, 0);
 		free(str);
 	}
@@ -114,7 +114,7 @@
 }
 
 void
-raw_fini_common(t10_lu_common_t *lu)
+raw_common_fini(t10_lu_common_t *lu)
 {
 	free(lu->l_dtype_params);
 }
@@ -125,7 +125,7 @@
  * []----
  */
 void
-raw_init_per(t10_lu_impl_t *itl)
+raw_per_init(t10_lu_impl_t *itl)
 {
 	itl->l_cmd	= raw_cmd;
 	itl->l_data	= raw_data;
@@ -142,7 +142,13 @@
 
 /*ARGSUSED*/
 void
-raw_fini_per(t10_lu_impl_t *itl)
+raw_per_fini(t10_lu_impl_t *itl)
+{
+}
+
+/*ARGSUSED*/
+void
+raw_task_mgmt(t10_lu_common_t *t, TaskOp_t op)
 {
 }
 
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_sam.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/t10_sam.c	Wed Nov 15 19:25:44 2006 -0800
@@ -29,6 +29,7 @@
 #include <aio.h>
 #include <sys/aio.h>
 #include <sys/asynch.h>
+#include <stdio.h>
 #include <stddef.h>
 #include <strings.h>
 #include <pthread.h>
@@ -44,6 +45,8 @@
 #include <unistd.h>
 #include <signal.h>
 #include <sys/ucontext.h>
+#include <libzfs.h>
+#include <assert.h>
 
 #include <sys/scsi/generic/sense.h>
 #include <sys/scsi/generic/status.h>
@@ -89,6 +92,7 @@
 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[];
 
 /*
  * Global variables
@@ -765,18 +769,18 @@
 
 	itl = avl_first(&t->s_open_lu);
 	while (itl) {
-		buf_add_tag(buf, XML_ELEMENT_LUN, Tag_Start);
+		tgt_buf_add_tag(buf, XML_ELEMENT_LUN, Tag_Start);
 		(void) snprintf(lb, sizeof (lb), "%d", itl->l_common->l_num);
-		buf_add_tag(buf, lb, Tag_String);
+		tgt_buf_add_tag(buf, lb, Tag_String);
 
 		(void) snprintf(lb, sizeof (lb), "%lld", itl->l_cmds_read);
-		xml_add_tag(buf, XML_ELEMENT_READCMDS, lb);
+		tgt_buf_add(buf, XML_ELEMENT_READCMDS, lb);
 		(void) snprintf(lb, sizeof (lb), "%lld", itl->l_cmds_write);
-		xml_add_tag(buf, XML_ELEMENT_WRITECMDS, lb);
+		tgt_buf_add(buf, XML_ELEMENT_WRITECMDS, lb);
 		(void) snprintf(lb, sizeof (lb), "%lld", itl->l_sects_read);
-		xml_add_tag(buf, XML_ELEMENT_READBLKS, lb);
+		tgt_buf_add(buf, XML_ELEMENT_READBLKS, lb);
 		(void) snprintf(lb, sizeof (lb), "%lld", itl->l_sects_write);
-		xml_add_tag(buf, XML_ELEMENT_WRITEBLKS, lb);
+		tgt_buf_add(buf, XML_ELEMENT_WRITEBLKS, lb);
 
 		switch (itl->l_common->l_state) {
 		case lu_online:
@@ -789,9 +793,9 @@
 			p = TGT_STATUS_ERRORED;
 			break;
 		}
-		xml_add_tag(buf, XML_ELEMENT_STATUS, p);
+		tgt_buf_add(buf, XML_ELEMENT_STATUS, p);
 
-		buf_add_tag(buf, XML_ELEMENT_LUN, Tag_End);
+		tgt_buf_add_tag(buf, XML_ELEMENT_LUN, Tag_End);
 		itl = AVL_NEXT(&t->s_open_lu, itl);
 	}
 }
@@ -824,7 +828,7 @@
 	msg_t			*m		= NULL;
 	target_queue_t		*rq		= NULL;
 	char			path[MAXPATHLEN];
-	xml_node_t		*n1;
+	tgt_node_t		*n1;
 	Boolean_t		rval		= False;
 	struct statvfs		fs;
 
@@ -935,21 +939,22 @@
 		    target_basedir, cmd->c_lu->l_targ->s_targ_base, PARAMBASE,
 		    lun);
 
-		if ((n1 = xml_find_child(cmd->c_lu->l_common->l_root,
+		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 (xml_update_value_str(n1, XML_ELEMENT_STATUS,
+		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;
 		}
 
-		if (xml_dump2file(cmd->c_lu->l_common->l_root, path) ==
+		if (tgt_dump2file(cmd->c_lu->l_common->l_root, path) ==
 		    False) {
 			queue_prt(mgmtq, Q_STE_ERRS,
 			    "STE%x  failed to dump out params\n", lun);
@@ -1312,14 +1317,21 @@
 				search;
 	avl_index_t		wc		= 0, /* where common */
 				wt		= 0; /* where target */
-	char			*guid		= NULL;
+	char			*guid		= NULL,
+				*str,
+				*dataset	= NULL;
 	t10_lu_common_t		lc,
 				*common		= NULL;
-	xml_node_t		*n		= NULL,
-				*n1;
+	tgt_node_t		*n		= NULL,
+				*n1,
+				*targ,
+				*ll;
 	xmlTextReaderPtr	r		= NULL;
 	char			path[MAXPATHLEN];
 	int			xml_fd		= -1;
+	libzfs_handle_t		*zh;
+	zfs_handle_t		*zfsh;
+	Boolean_t		okay_to_free	= True;
 
 	bzero(&lc, sizeof (lc));
 
@@ -1365,76 +1377,138 @@
 	l->l_targ		= t;
 	l->l_targ_lun		= lun;
 
-	/*
-	 * 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.
-	 */
-	(void) snprintf(path, sizeof (path), "%s/%s/%s%d",
-	    target_basedir, t->s_targ_base, PARAMBASE, lun);
-
-	(void) pthread_mutex_lock(&lu_list_mutex);
-	if ((xml_fd = open(path, O_RDONLY)) < 0) {
-		(void) pthread_mutex_unlock(&lu_list_mutex);
-		spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
-		/* ---- ACCESS DENIED - INVALID LU IDENTIFIER ---- */
-		spc_sense_ascq(cmd, 0x20, 0x9);
-		goto error;
-	}
-	if ((r = (xmlTextReaderPtr)xmlReaderForFd(xml_fd, NULL, NULL,
-	    0)) != NULL) {
-		while (xmlTextReaderRead(r) == 1)
-			if (xml_process_node(r, &n) == False)
-				break;
-	} else {
-		(void) pthread_mutex_unlock(&lu_list_mutex);
-		spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
-		goto error;
+	targ = NULL;
+	while ((targ = tgt_node_next(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)) {
+			free(str);
+			break;
+		} else if (str) {
+			free(str);
+			str = NULL;
+		}
 	}
 
-	(void) close(xml_fd);
-	/*
-	 * Set xml_fd back to -1 so that if an error occurs later we don't
-	 * attempt to close a file descriptor that another thread might have
-	 * opened.
-	 */
-	xml_fd = -1;
+	if ((ll = tgt_node_next(targ, XML_ELEMENT_LUNLIST, NULL)) == NULL)
+		goto error;
+	if ((n = tgt_node_next(ll, XML_ELEMENT_LUN, NULL)) == NULL)
+		goto error;
+	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 currently 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.
+		 */
+		(void) snprintf(path, sizeof (path), "%s/%s/%s%d",
+		    target_basedir, t->s_targ_base, PARAMBASE, lun);
 
-	xmlTextReaderClose(r);
-	xmlFreeTextReader(r);
-	r = NULL;
+		(void) pthread_mutex_lock(&lu_list_mutex);
+		if ((xml_fd = open(path, O_RDONLY)) < 0) {
+			(void) pthread_mutex_unlock(&lu_list_mutex);
+			spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
+			/* ---- ACCESS DENIED - INVALID LU IDENTIFIER ---- */
+			spc_sense_ascq(cmd, 0x20, 0x9);
+			goto error;
+		}
+		n = NULL;
+		if ((r = (xmlTextReaderPtr)xmlReaderForFd(xml_fd, NULL, NULL,
+		    0)) != NULL) {
+			while (xmlTextReaderRead(r) == 1)
+				if (tgt_node_process(r, &n) == False)
+					break;
+		} else {
+			(void) pthread_mutex_unlock(&lu_list_mutex);
+			spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
+			goto error;
+		}
 
-	if (xml_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;
-	}
+		(void) close(xml_fd);
+		/*
+		 * Set xml_fd back to -1 so that if an error occurs later we
+		 * don't attempt to close a file descriptor that another thread
+		 * might have opened.
+		 */
+		xml_fd = -1;
 
-	if (strcmp(guid, "0") == 0) {
+		xmlTextReaderClose(r);
+		xmlFreeTextReader(r);
+		r = NULL;
+		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);
 		if (util_create_guid(&guid) == False) {
 			(void) pthread_mutex_unlock(&lu_list_mutex);
 			spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
 			goto error;
 		}
-		if ((n1 = xml_find_child(n, XML_ELEMENT_GUID)) == NULL) {
+		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 (xml_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 (xml_dump2file(n, path) == False) {
+		if (targ != NULL) {
+			str = NULL;
+			tgt_dump2buf(targ, &str);
+
+			if (tgt_find_value_str(targ, XML_ELEMENT_ALIAS,
+			    &dataset) == False ||
+			    (zh = libzfs_init()) == NULL)
+				goto error;
+
+			if ((zfsh = zfs_open(zh, dataset, ZFS_TYPE_ANY)) ==
+			    NULL) {
+				libzfs_fini(zh);
+				goto error;
+			}
+
+			if (zfs_prop_set(zfsh,
+			    zfs_prop_to_name(ZFS_PROP_ISCSIOPTIONS),
+			    str) != 0) {
+				zfs_close(zfsh);
+				libzfs_fini(zh);
+				goto error;
+			}
+
+			zfs_close(zfsh);
+			libzfs_fini(zh);
+			free(dataset);
+			free(str);
+			dataset = NULL;
+			str = NULL;
+
+		} else if (tgt_dump2file(n, path) == False) {
 			(void) pthread_mutex_unlock(&lu_list_mutex);
 			spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
 			goto error;
 		}
 	}
 
-	if (xml_decode_bytes(guid, &lc.l_guid, &lc.l_guid_len) == False) {
+	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;
@@ -1463,6 +1537,9 @@
 		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);
 
@@ -1499,6 +1576,18 @@
 		 * 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,
@@ -1530,7 +1619,6 @@
 	queue_message_set(common->l_from_transports, 0, msg_lu_add, (void *)l);
 
 	free(guid);
-	xml_tree_free(n);
 
 	cmd->c_lu = l;
 	return (True);
@@ -1545,13 +1633,15 @@
 		xmlFreeTextReader(r);
 	}
 	if (n)
-		xml_tree_free(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);
 }
 
@@ -1559,30 +1649,24 @@
 t10_lu_initialize(t10_lu_common_t *lu, char *basedir)
 {
 	char	*str	= NULL;
+	int	dtype;
 
 	if (load_params(lu, basedir) == False)
 		return (False);
 
-	if (xml_find_value_str(lu->l_root, XML_ELEMENT_DTYPE, &str) == True) {
-		if (strcmp(str, TGT_TYPE_DISK) == 0) {
-			lu->l_dtype = DTYPE_DIRECT;
-			if (sbc_init_common(lu) == False)
-				goto error;
-		} else if (strcmp(str, TGT_TYPE_RAW) == 0) {
-			lu->l_dtype = DTYPE_UNKNOWN;
-			if (raw_init_common(lu) == False)
-				goto error;
-		} else if (strcmp(str, TGT_TYPE_TAPE) == 0) {
-			lu->l_dtype = DTYPE_SEQUENTIAL;
-			if (ssc_init_common(lu) == False)
-				goto error;
-		} else if (strcmp(str, TGT_TYPE_OSD) == 0) {
-			lu->l_dtype = DTYPE_OSD;
-			if (osd_init_common(lu) == False)
-				goto error;
+	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;
+			}
 		}
-		if (lu->l_dtype_params == NULL)
-			goto error;
 		free(str);
 	} else
 		goto error;
@@ -1680,23 +1764,7 @@
 
 		case msg_lu_add:
 			itl = (t10_lu_impl_t *)m->msg_data;
-			switch (lu->l_dtype) {
-				case DTYPE_DIRECT:
-					sbc_init_per(itl);
-					break;
-
-				case DTYPE_SEQUENTIAL:
-					ssc_init_per(itl);
-					break;
-
-				case DTYPE_OSD:
-					osd_init_per(itl);
-					break;
-
-				case DTYPE_UNKNOWN:
-					raw_init_per(itl);
-					break;
-			}
+			(*sam_emul_table[lu->l_dtype].t_per_init)(itl);
 			break;
 
 		case msg_reset_lu:
@@ -1711,26 +1779,8 @@
 				 * receive a CHECK_CONDITION on their next
 				 * command.
 				 */
-				switch (lu->l_dtype) {
-				case DTYPE_DIRECT:
-					sbc_fini_per(itl);
-					sbc_init_per(itl);
-					break;
-
-				case DTYPE_SEQUENTIAL:
-					ssc_fini_per(itl);
-					ssc_init_per(itl);
-					break;
-
-				case DTYPE_UNKNOWN:
-					raw_fini_per(itl);
-					raw_init_per(itl);
-					break;
-
-				case DTYPE_OSD:
-					osd_fini_per(itl);
-					osd_init_per(itl);
-				}
+				(*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);
 			} while (itl != NULL);
@@ -1749,23 +1799,8 @@
 
 			queue_walker_free(lu->l_from_transports,
 			    lu_remove_cmds, (void *)itl);
-			switch (lu->l_dtype) {
-			case DTYPE_DIRECT:
-				sbc_fini_per(itl);
-				break;
-
-			case DTYPE_SEQUENTIAL:
-				ssc_fini_per(itl);
-				break;
+			(*sam_emul_table[lu->l_dtype].t_per_fini)(itl);
 
-			case DTYPE_OSD:
-				osd_fini_per(itl);
-				break;
-
-			case DTYPE_UNKNOWN:
-				raw_fini_per(itl);
-				break;
-			}
 			/*
 			 * Don't remove reference to l_common area until after
 			 * the emulation routines are finished since they
@@ -1789,19 +1824,9 @@
 					    "LU_%x  Failed to close fd, "
 					    "errno=%d\n", lu->l_internal_num,
 					    errno);
-				switch (lu->l_dtype) {
-				case DTYPE_DIRECT:
-					sbc_fini_common(lu);
-					break;
+				/*CSTYLED*/
+				(*sam_emul_table[lu->l_dtype].t_common_fini)(lu);
 
-				case DTYPE_SEQUENTIAL:
-					ssc_fini_common(lu);
-					break;
-
-				case DTYPE_UNKNOWN:
-					raw_fini_common(lu);
-					break;
-				}
 				avl_remove(&lu_list, (void *)lu);
 				util_title(mgmtq, Q_STE_NONIO,
 				    lu->l_internal_num, "End LU");
@@ -1809,7 +1834,8 @@
 				(void) pthread_mutex_unlock(
 				    &lu->l_common_mutex);
 				(void) pthread_mutex_unlock(&lu_list_mutex);
-				xml_tree_free(lu->l_root);
+				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);
@@ -1903,15 +1929,8 @@
 			    target_basedir, itl->l_targ->s_targ_base);
 			(void) load_params(lu, path);
 			free(path);
-			switch (lu->l_dtype) {
-			case DTYPE_DIRECT:
-				sbc_task_mgmt(lu, CapacityChange);
-				break;
-
-			case DTYPE_SEQUENTIAL:
-				ssc_task_mgmt(lu, CapacityChange);
-				break;
-			}
+			(*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) {
@@ -1937,27 +1956,12 @@
 			    target_basedir, itl->l_targ->s_targ_base);
 			(void) load_params(lu, path);
 			free(path);
-			switch (lu->l_dtype) {
-			case DTYPE_DIRECT:
-				sbc_task_mgmt(lu, DeviceOnline);
-				break;
-
-			case DTYPE_SEQUENTIAL:
-				ssc_task_mgmt(lu, DeviceOnline);
-				break;
-			}
+			(*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) {
-				switch (lu->l_dtype) {
-				case DTYPE_DIRECT:
-					sbc_init_per(itl);
-					break;
-
-				case DTYPE_SEQUENTIAL:
-					ssc_init_per(itl);
-					break;
-				}
+				(*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);
@@ -2098,15 +2102,13 @@
 static Boolean_t
 load_params(t10_lu_common_t *lu, char *basedir)
 {
-	char			file[MAXPATHLEN],
-				*str;
-	int			oflags		= O_RDWR|O_LARGEFILE|O_NDELAY;
-	Boolean_t		mmap_lun	= True;
-	xml_node_t		*node		= NULL;
-	int			version_maj	= XML_VERS_LUN_MAJ,
-				version_min	= XML_VERS_LUN_MIN,
-				xml_fd;
-	xmlTextReaderPtr	r;
+	char		file[MAXPATHLEN],
+			*str;
+	int		oflags		= O_RDWR|O_LARGEFILE|O_NDELAY;
+	Boolean_t	mmap_lun	= True;
+	tgt_node_t	*node		= NULL;
+	int		version_maj	= XML_VERS_LUN_MAJ,
+			version_min	= XML_VERS_LUN_MIN;
 
 	/*
 	 * Clean up from previous call to this function. This occurs if
@@ -2114,38 +2116,18 @@
 	 */
 	if (lu->l_mmap != MAP_FAILED)
 		munmap(lu->l_mmap, lu->l_size);
-	if (lu->l_root != NULL) {
-		xml_tree_free(lu->l_root);
-		lu->l_root = NULL;
-	}
 	if (lu->l_fd != -1)
 		close(lu->l_fd);
 
-	(void) snprintf(file, sizeof (file), "%s/%s%d", basedir, PARAMBASE,
-			lu->l_num);
-
-	if ((xml_fd = open(file, O_RDONLY)) < 0)
-		return (False);
-	if ((r = (xmlTextReaderPtr)xmlReaderForFd(xml_fd, NULL, NULL,
-	    0)) != NULL) {
-		while (xmlTextReaderRead(r) == 1)
-			if (xml_process_node(r, &node) == False)
-				break;
-		lu->l_root = node;
-	} else
-		return (False);
-
-	(void) close(xml_fd);
-	xmlTextReaderClose(r);
-	xmlFreeTextReader(r);
+	node = lu->l_root;
 
 	if (validate_version(node, &version_maj, &version_min) == False)
+		fprintf(stderr, "Failed version check\n");
+
+	if (tgt_find_value_str(node, XML_ELEMENT_PID, &lu->l_pid) == False)
 		goto error;
 
-	if (xml_find_value_str(node, XML_ELEMENT_PID, &lu->l_pid) == False)
-		goto error;
-
-	if (xml_find_value_str(node, XML_ELEMENT_VID, &lu->l_vid) == False)
+	if (tgt_find_value_str(node, XML_ELEMENT_VID, &lu->l_vid) == False)
 		goto error;
 
 	/*
@@ -2153,7 +2135,7 @@
 	 * file and there's no need to treat it as an error. Just mark
 	 * the device as online.
 	 */
-	if (xml_find_value_str(node, XML_ELEMENT_STATUS, &str) == True) {
+	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)
@@ -2197,9 +2179,9 @@
 	 * The per LU bit is settable via a SCSI command.
 	 */
 	lu->l_fast_write_ack = False;
-	(void) xml_find_value_boolean(main_config, XML_ELEMENT_FAST,
+	(void) tgt_find_value_boolean(main_config, XML_ELEMENT_FAST,
 	    &lu->l_fast_write_ack);
-	(void) xml_find_value_boolean(node, XML_ELEMENT_FAST,
+	(void) tgt_find_value_boolean(node, XML_ELEMENT_FAST,
 	    &lu->l_fast_write_ack);
 	if (lu->l_fast_write_ack == False)
 		oflags |= O_SYNC;
@@ -2211,7 +2193,7 @@
 	 * not just a single file to be opened, but potentially thousands.
 	 * Therefore, stop here if we've got an OSD dtype.
 	 */
-	if (xml_find_value_str(node, XML_ELEMENT_DTYPE, &str) == False)
+	if (tgt_find_value_str(node, XML_ELEMENT_DTYPE, &str) == False)
 		goto error;
 	if (strcmp(str, TGT_TYPE_OSD) == 0) {
 		free(str);
@@ -2219,10 +2201,17 @@
 	} else
 		free(str);
 
-	(void) snprintf(file, sizeof (file), "%s/%s%d", basedir, LUNBASE,
-	    lu->l_num);
-	if ((lu->l_fd = open(file, oflags)) == -1)
-		goto error;
+	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;
+	}
 
 #ifndef	_LP64
 	/*
@@ -2231,8 +2220,8 @@
 	 */
 	mmap_lun	= False;
 #endif
-	(void) xml_find_value_boolean(node, XML_ELEMENT_MMAP_LUN, &mmap_lun);
-	if (xml_find_value_str(node, XML_ELEMENT_SIZE, &str) == True) {
+	(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
@@ -2257,14 +2246,18 @@
 	}
 	return (True);
 error:
-	if (lu->l_root)
-		xml_tree_free(lu->l_root);
-	if (lu->l_pid)
+	if (lu->l_pid) {
 		free(lu->l_pid);
-	if (lu->l_vid)
+		lu->l_pid = NULL;
+	}
+	if (lu->l_vid) {
 		free(lu->l_vid);
-	if (lu->l_fd != -1)
+		lu->l_vid = NULL;
+	}
+	if (lu->l_fd != -1) {
 		(void) close(lu->l_fd);
+		lu->l_fd = -1;
+	}
 	return (False);
 }
 
@@ -2440,6 +2433,21 @@
 		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)
@@ -2470,3 +2478,97 @@
 	}
 	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 }
+};
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_sbc.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/t10_sbc.c	Wed Nov 15 19:25:44 2006 -0800
@@ -81,25 +81,25 @@
  * []----
  */
 Boolean_t
-sbc_init_common(t10_lu_common_t *lu)
+sbc_common_init(t10_lu_common_t *lu)
 {
 	disk_params_t	*d;
-	xml_node_t	*node	= lu->l_root;
+	tgt_node_t	*node	= lu->l_root;
 
 	if ((d = (disk_params_t *)calloc(1, sizeof (*d))) == NULL)
 		return (False);
 
-	(void) xml_find_value_int(node, XML_ELEMENT_BPS,
+	(void) tgt_find_value_int(node, XML_ELEMENT_BPS,
 	    (int *)&d->d_bytes_sect);
-	(void) xml_find_value_int(node, XML_ELEMENT_HEADS,
+	(void) tgt_find_value_int(node, XML_ELEMENT_HEADS,
 	    (int *)&d->d_heads);
-	(void) xml_find_value_int(node, XML_ELEMENT_SPT,
+	(void) tgt_find_value_int(node, XML_ELEMENT_SPT,
 	    (int *)&d->d_spt);
-	(void) xml_find_value_int(node, XML_ELEMENT_CYLINDERS,
+	(void) tgt_find_value_int(node, XML_ELEMENT_CYLINDERS,
 	    (int *)&d->d_cyl);
-	(void) xml_find_value_int(node, XML_ELEMENT_RPM,
+	(void) tgt_find_value_int(node, XML_ELEMENT_RPM,
 	    (int *)&d->d_rpm);
-	(void) xml_find_value_int(node, XML_ELEMENT_INTERLEAVE,
+	(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;
@@ -121,7 +121,7 @@
 }
 
 void
-sbc_fini_common(t10_lu_common_t *lu)
+sbc_common_fini(t10_lu_common_t *lu)
 {
 	disk_params_t	*d = lu->l_dtype_params;
 
@@ -153,7 +153,7 @@
  * []----
  */
 void
-sbc_init_per(t10_lu_impl_t *itl)
+sbc_per_init(t10_lu_impl_t *itl)
 {
 	disk_params_t	*d = (disk_params_t *)itl->l_common->l_dtype_params;
 
@@ -166,7 +166,7 @@
 }
 
 void
-sbc_fini_per(t10_lu_impl_t *itl)
+sbc_per_fini(t10_lu_impl_t *itl)
 {
 	disk_params_t	*d = (disk_params_t *)itl->l_common->l_dtype_params;
 	t10_lu_impl_t	*lu;
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_spc.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/t10_spc.c	Wed Nov 15 19:25:44 2006 -0800
@@ -550,7 +550,7 @@
 			lun_idx,
 			lun_val;
 	char		*str;
-	xml_node_t	*targ,
+	tgt_node_t	*targ,
 			*lun_list,
 			*lun;
 
@@ -581,9 +581,9 @@
 	select = cdb[2];
 
 	targ = NULL;
-	while ((targ = xml_node_next(targets_config, XML_ELEMENT_TARG, targ)) !=
+	while ((targ = tgt_node_next(targets_config, XML_ELEMENT_TARG, targ)) !=
 	    NULL) {
-		if (xml_find_value_str(targ, XML_ELEMENT_INAME, &str) ==
+		if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &str) ==
 		    False) {
 			goto error;
 		}
@@ -595,11 +595,11 @@
 	}
 	if (!targ)
 		goto error;
-	if ((lun_list = xml_node_next(targ, XML_ELEMENT_LUNLIST, NULL)) == NULL)
+	if ((lun_list = tgt_node_next(targ, XML_ELEMENT_LUNLIST, NULL)) == NULL)
 		goto error;
 
 	lun = NULL;
-	while ((lun = xml_node_next(lun_list, XML_ELEMENT_LUN, lun)) != NULL)
+	while ((lun = tgt_node_next(lun_list, XML_ELEMENT_LUN, lun)) != NULL)
 		entries++;
 
 
@@ -616,9 +616,9 @@
 
 		lun_idx = SCSI_REPORTLUNS_ADDRESS_SIZE;
 		lun	= NULL;
-		while ((lun = xml_node_next(lun_list, XML_ELEMENT_LUN, lun)) !=
+		while ((lun = tgt_node_next(lun_list, XML_ELEMENT_LUN, lun)) !=
 		    NULL) {
-			if (xml_find_value_int(lun, XML_ELEMENT_LUN,
+			if (tgt_find_value_int(lun, XML_ELEMENT_LUN,
 			    &lun_val) == False)
 				goto error;
 			if (spc_encode_lu_addr(&buf[lun_idx], select,
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_ssc.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/t10_ssc.c	Wed Nov 15 19:25:44 2006 -0800
@@ -69,7 +69,7 @@
  * []----
  */
 Boolean_t
-ssc_init_common(t10_lu_common_t *lu)
+ssc_common_init(t10_lu_common_t *lu)
 {
 	ssc_params_t	*s;
 	ssc_obj_mark_t	mark;
@@ -102,7 +102,7 @@
  * []----
  */
 void
-ssc_fini_common(t10_lu_common_t *lu)
+ssc_common_fini(t10_lu_common_t *lu)
 {
 	free(lu->l_dtype_params);
 }
@@ -128,7 +128,7 @@
  * []----
  */
 void
-ssc_init_per(t10_lu_impl_t *itl)
+ssc_per_init(t10_lu_impl_t *itl)
 {
 	ssc_params_t	*s = (ssc_params_t *)itl->l_common->l_dtype_params;
 
@@ -147,7 +147,7 @@
  */
 /*ARGSUSED*/
 void
-ssc_fini_per(t10_lu_impl_t *itl)
+ssc_per_fini(t10_lu_impl_t *itl)
 {
 }
 
--- a/usr/src/cmd/iscsi/iscsitgtd/target.h	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/target.h	Wed Nov 15 19:25:44 2006 -0800
@@ -55,6 +55,7 @@
 #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
@@ -166,13 +167,13 @@
 } admin_table_t;
 
 #include <sys/socket.h>
-#include "xml.h"
+#include <iscsitgt_impl.h>
 #include "queue.h"
 
-void create_func(xml_node_t *, target_queue_t *, target_queue_t *);
-void modify_func(xml_node_t *, target_queue_t *, target_queue_t *);
-void remove_func(xml_node_t *, target_queue_t *, target_queue_t *);
-void list_func(xml_node_t *, target_queue_t *, target_queue_t *);
+void create_func(tgt_node_t *, target_queue_t *, target_queue_t *);
+void modify_func(tgt_node_t *, target_queue_t *, target_queue_t *);
+void remove_func(tgt_node_t *, target_queue_t *, target_queue_t *);
+void list_func(tgt_node_t *, target_queue_t *, target_queue_t *);
 void logout_targ(char *targ);
 char *update_basedir(char *, char *);
 char *valid_radius_srv(char *name, char *prop);
@@ -185,8 +186,8 @@
 extern char 		*target_basedir;
 extern char 		*target_log;
 extern char		*config_file;
-extern xml_node_t	*targets_config;
-extern xml_node_t	*main_config;
+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,
--- a/usr/src/cmd/iscsi/iscsitgtd/util.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/util.c	Wed Nov 15 19:25:44 2006 -0800
@@ -42,11 +42,10 @@
 #include <fcntl.h>
 #include <syslog.h>
 
-#include "local_types.h"
+#include <iscsitgt_impl.h>
 #include "target.h"
 #include "utility.h"
 #include "errcode.h"
-#include "xml.h"
 #include <sys/scsi/generic/commands.h>
 
 #define	CRC32_STR	"CRC32C"
@@ -73,9 +72,9 @@
  * []----
  */
 Boolean_t
-check_access(xml_node_t *targ, char *initiator_name, Boolean_t req_chap)
+check_access(tgt_node_t *targ, char *initiator_name, Boolean_t req_chap)
 {
-	xml_node_t	*acl,
+	tgt_node_t	*acl,
 			*inode		= NULL,
 			*tgt_initiator	= NULL;
 	char		*dummy;
@@ -85,20 +84,20 @@
 	/*
 	 * If there's no ACL for this target everyone has access.
 	 */
-	if ((acl = xml_node_next(targ, XML_ELEMENT_ACLLIST, NULL)) == NULL)
+	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.
 	 */
-	while ((inode = xml_node_next(main_config, XML_ELEMENT_INIT,
+	while ((inode = tgt_node_next(main_config, XML_ELEMENT_INIT,
 	    inode)) != NULL) {
-		if (xml_find_value_str(inode, XML_ELEMENT_INAME, &dummy) ==
+		if (tgt_find_value_str(inode, XML_ELEMENT_INAME, &dummy) ==
 		    True) {
 			if (strcmp(dummy, initiator_name) == 0) {
 				free(dummy);
-				if (xml_find_value_str(inode,
+				if (tgt_find_value_str(inode,
 				    XML_ELEMENT_CHAPSECRET, &dummy) == True) {
 					free(dummy);
 					found_chap = True;
@@ -113,7 +112,7 @@
 	if ((acl != NULL) && (inode == NULL))
 		return (False);
 
-	while ((tgt_initiator = xml_node_next(acl, XML_ELEMENT_INIT,
+	while ((tgt_initiator = tgt_node_next(acl, XML_ELEMENT_INIT,
 	    tgt_initiator)) != NULL) {
 
 		if (strcmp(inode->x_value, tgt_initiator->x_value) == 0) {
@@ -154,12 +153,12 @@
 static Boolean_t
 convert_local_tpgt(char **text, int *text_length, char *local_tpgt)
 {
-	xml_node_t	*tpgt	= NULL,
+	tgt_node_t	*tpgt	= NULL,
 	*x;
 	char		buf[80];
 	char		ipaddr[4];
 
-	while ((tpgt = xml_node_next(main_config, XML_ELEMENT_TPGT,
+	while ((tpgt = tgt_node_next(main_config, XML_ELEMENT_TPGT,
 	    tpgt)) != NULL) {
 		if (strcmp(tpgt->x_value, local_tpgt) == 0) {
 
@@ -206,9 +205,9 @@
  */
 static void
 add_target_address(iscsi_conn_t *c, char **text, int *text_length,
-    xml_node_t *targ)
+    tgt_node_t *targ)
 {
-	xml_node_t	*tpgt_list,
+	tgt_node_t	*tpgt_list,
 			*tpgt		= NULL;
 	struct sockaddr_in	*sp4;
 	struct sockaddr_in6	*sp6;
@@ -218,14 +217,14 @@
 	char	buf[INET6_ADDRSTRLEN + 7],
 		net_buf[INET6_ADDRSTRLEN];
 
-	if ((tpgt_list = xml_node_next(targ, XML_ELEMENT_TPGTLIST,
+	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 = xml_node_next(tpgt_list, XML_ELEMENT_TPGT,
+	while ((tpgt = tgt_node_next(tpgt_list, XML_ELEMENT_TPGT,
 	    tpgt)) != NULL) {
 		if (convert_local_tpgt(text, text_length, tpgt->x_value) ==
 		    False) {
@@ -264,16 +263,16 @@
 static Boolean_t
 add_targets(iscsi_conn_t *c, char **text, int *text_length)
 {
-	xml_node_t	*targ		= NULL;
+	tgt_node_t	*targ		= NULL;
 	Boolean_t	rval		= True;
 	char		*targ_name	= NULL;
 
-	while ((rval == True) && ((targ = xml_node_next(targets_config,
+	while ((rval == True) && ((targ = tgt_node_next(targets_config,
 	    XML_ELEMENT_TARG, targ)) != NULL)) {
 
 		if (check_access(targ, c->c_sess->s_i_name, False) == True) {
 
-			if (xml_find_value_str(targ, XML_ELEMENT_INAME,
+			if (tgt_find_value_str(targ, XML_ELEMENT_INAME,
 			    &targ_name) == False) {
 				rval = False;
 				break;
@@ -823,7 +822,7 @@
 find_main_tpgt(struct sockaddr_storage *pst)
 {
 	char		ip_addr[16];
-	xml_node_t	*tpgt				= NULL,
+	tgt_node_t	*tpgt				= NULL,
 			*ip_node			= NULL;
 	struct in_addr	addr;
 	struct in6_addr	addr6;
@@ -835,11 +834,11 @@
 	addr = ((struct sockaddr_in *)pst)->sin_addr;
 	addr6 = ((struct sockaddr_in6 *)pst)->sin6_addr;
 
-	while ((tpgt = xml_node_next(main_config, XML_ELEMENT_TPGT,
+	while ((tpgt = tgt_node_next(main_config, XML_ELEMENT_TPGT,
 	    tpgt)) != NULL) {
 
 		ip_node = NULL;
-		while ((ip_node = xml_node_next(tpgt, XML_ELEMENT_IPADDR,
+		while ((ip_node = tgt_node_next(tpgt, XML_ELEMENT_IPADDR,
 		    ip_node)) != NULL) {
 
 			if (pst->ss_family == AF_INET) {
@@ -879,9 +878,9 @@
  * return zero which will break the connection.
  */
 static int
-convert_to_tpgt(iscsi_conn_t *c, xml_node_t *targ)
+convert_to_tpgt(iscsi_conn_t *c, tgt_node_t *targ)
 {
-	xml_node_t	*list,
+	tgt_node_t	*list,
 			*tpgt		= NULL;
 	int		addr_tpgt,
 			pos_tpgt;
@@ -890,7 +889,7 @@
 	 * If this target doesn't have a list of target portal group tags
 	 * just return the default which is 1.
 	 */
-	list = xml_node_next(targ, XML_ELEMENT_TPGTLIST, NULL);
+	list = tgt_node_next(targ, XML_ELEMENT_TPGTLIST, NULL);
 	if (list == NULL)
 		return (1);
 
@@ -900,8 +899,8 @@
 	 */
 	addr_tpgt = find_main_tpgt(&(c->c_target_sockaddr));
 
-	while ((tpgt = xml_node_next(list, XML_ELEMENT_TPGT, tpgt)) != NULL) {
-		(void) xml_find_value_int(tpgt, XML_ELEMENT_TPGT, &pos_tpgt);
+	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);
 		}
@@ -915,15 +914,15 @@
  * | find_target_node -- given a target IQN name, return the XML node
  * []----
  */
-xml_node_t *
+tgt_node_t *
 find_target_node(char *targ_name)
 {
-	xml_node_t	*tnode	= NULL;
+	tgt_node_t	*tnode	= NULL;
 	char		*iname;
 
-	while ((tnode = xml_node_next(targets_config, XML_ELEMENT_TARG,
+	while ((tnode = tgt_node_next(targets_config, XML_ELEMENT_TARG,
 	    tnode)) != NULL) {
-		if (xml_find_value_str(tnode, XML_ELEMENT_INAME, &iname) ==
+		if (tgt_find_value_str(tnode, XML_ELEMENT_INAME, &iname) ==
 		    True) {
 			if (strcmp(iname, targ_name) == 0) {
 				free(iname);
@@ -939,7 +938,7 @@
 static Boolean_t
 connection_parameters_get(iscsi_conn_t *c, char *targ_name)
 {
-	xml_node_t	*targ,
+	tgt_node_t	*targ,
 			*alias;
 	Boolean_t	rval	= False;
 
@@ -954,16 +953,16 @@
 		 */
 		if ((c->c_tpgt = convert_to_tpgt(c, targ)) == 0)
 			return (False);
-		if ((alias = xml_node_next(targ, XML_ELEMENT_ALIAS, NULL)) ==
+		if ((alias = tgt_node_next(targ, XML_ELEMENT_ALIAS, NULL)) ==
 		    NULL) {
-			(void) xml_find_value_str(targ, XML_ELEMENT_TARG,
+			(void) tgt_find_value_str(targ, XML_ELEMENT_TARG,
 			    &c->c_targ_alias);
 		} else {
-			(void) xml_find_value_str(alias, XML_ELEMENT_ALIAS,
+			(void) tgt_find_value_str(alias, XML_ELEMENT_ALIAS,
 			    &c->c_targ_alias);
 		}
 
-		(void) xml_find_value_int(targ, XML_ELEMENT_MAXCMDS,
+		(void) tgt_find_value_int(targ, XML_ELEMENT_MAXCMDS,
 		    &c->c_maxcmdsn);
 		rval = True;
 	}
@@ -972,14 +971,14 @@
 }
 
 Boolean_t
-validate_version(xml_node_t *node, int *maj_p, int *min_p)
+validate_version(tgt_node_t *node, int *maj_p, int *min_p)
 {
 	char	*vers_str	= NULL,
 		*minor_part;
 	int	maj,
 		min;
 
-	if ((xml_find_attr_str(node, XML_ELEMENT_VERS, &vers_str) == False) ||
+	if ((tgt_find_attr_str(node, XML_ELEMENT_VERS, &vers_str) == False) ||
 	    (vers_str == NULL))
 		return (False);
 
@@ -1026,7 +1025,7 @@
 Boolean_t
 update_config_main(char **msg)
 {
-	if (xml_dump2file(main_config, config_file) == False) {
+	if (tgt_dump2file(main_config, config_file) == False) {
 		xml_rtn_msg(msg, ERR_UPDATE_MAINCFG_FAILED);
 		return (False);
 	} else
@@ -1039,7 +1038,7 @@
 	char	path[MAXPATHLEN];
 
 	(void) snprintf(path, sizeof (path), "%s/config.xml", target_basedir);
-	if (xml_dump2file(targets_config, path) == False) {
+	if (tgt_dump2file(targets_config, path) == False) {
 		if (msg != NULL)
 			xml_rtn_msg(msg, ERR_UPDATE_TARGCFG_FAILED);
 		return (False);
@@ -1109,7 +1108,7 @@
 		sleep(1);
 	}
 
-	if (xml_encode_bytes((uint8_t *)&eui, sizeof (eui), guid,
+	if (tgt_xml_encode((uint8_t *)&eui, sizeof (eui), guid,
 	    &guid_size) == False) {
 		return (False);
 	} else
@@ -1162,6 +1161,20 @@
 					return;
 				}
 		}
+
+	/*
+	 * At this point we've got a size which will not fit into
+	 * any values where C * H * S = size. So, set the heads and
+	 * sectors per track values to their largest which will make
+	 * a single cylinder 8GB. Then divide that into the size to
+	 * get the number of cylinders.
+	 */
+	h		= 0xff;
+	s		= 0xffff;
+	c		= sects / (h * s);
+	*heads		= (int)h;
+	*spt		= (int)s;
+	*cylinder	= (int)c;
 }
 
 /*
@@ -1274,11 +1287,11 @@
 {
 	char	lbuf[16];
 
-	buf_add_tag_and_attr(buf, XML_ELEMENT_ERROR, "version='1.0'");
+	tgt_buf_add_tag_and_attr(buf, XML_ELEMENT_ERROR, "version='1.0'");
 	(void) snprintf(lbuf, sizeof (lbuf), "%d", code);
-	xml_add_tag(buf, XML_ELEMENT_CODE, lbuf);
-	xml_add_tag(buf, XML_ELEMENT_MESSAGE, errcode_to_str(code));
-	buf_add_tag(buf, XML_ELEMENT_ERROR, Tag_End);
+	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);
 }
 
 /*
@@ -1462,7 +1475,7 @@
 void
 remove_target_common(char *name, int lun_num, char **msg)
 {
-	xml_node_t	*targ			= NULL,
+	tgt_node_t	*targ			= NULL,
 			*list,
 			*lun,
 			*node,
@@ -1477,7 +1490,7 @@
 	xmlTextReaderPtr	r;
 
 	(void) pthread_mutex_lock(&targ_config_mutex);
-	while ((targ = xml_node_next(targets_config, XML_ELEMENT_TARG, targ)) !=
+	while ((targ = tgt_node_next(targets_config, XML_ELEMENT_TARG, targ)) !=
 	    NULL) {
 		/* ---- Look for a match on the friendly name ---- */
 		if (strcmp(targ->x_value, name) == 0) {
@@ -1486,7 +1499,7 @@
 		}
 
 		/* ---- Check to see if they gave the IQN name instead ---- */
-		if ((xml_find_value_str(targ, XML_ELEMENT_INAME, &iname) ==
+		if ((tgt_find_value_str(targ, XML_ELEMENT_INAME, &iname) ==
 		    True) && (strcmp(iname, name) == 0))
 			break;
 		else {
@@ -1508,7 +1521,7 @@
 	if (tname == NULL)
 		tname = targ->x_value;
 	if (iname == NULL) {
-		if (xml_find_value_str(targ, XML_ELEMENT_INAME, &iname) ==
+		if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &iname) ==
 		    False) {
 			xml_rtn_msg(msg, ERR_INTERNAL_ERROR);
 			(void) pthread_mutex_unlock(&targ_config_mutex);
@@ -1516,7 +1529,7 @@
 		}
 	}
 
-	if ((list = xml_node_next(targ, XML_ELEMENT_LUNLIST, NULL)) == NULL)
+	if ((list = tgt_node_next(targ, XML_ELEMENT_LUNLIST, NULL)) == NULL)
 		goto error;
 
 	if (lun_num == 0) {
@@ -1526,9 +1539,9 @@
 		 * see if others are still present.
 		 */
 		lun = NULL;
-		while ((lun = xml_node_next(list, XML_ELEMENT_LUN, lun)) !=
+		while ((lun = tgt_node_next(list, XML_ELEMENT_LUN, lun)) !=
 		    NULL) {
-			if (xml_find_value_int(lun, XML_ELEMENT_LUN, &chk) ==
+			if (tgt_find_value_int(lun, XML_ELEMENT_LUN, &chk) ==
 			    False)
 				goto error;
 
@@ -1543,17 +1556,17 @@
 		 * Make sure the LU exists that's being removed
 		 */
 		lun = NULL;
-		while ((lun = xml_node_next(list, XML_ELEMENT_LUN, lun)) !=
+		while ((lun = tgt_node_next(list, XML_ELEMENT_LUN, lun)) !=
 		    NULL) {
-			if (xml_find_value_int(lun, XML_ELEMENT_LUN, &chk) ==
+			if (tgt_find_value_int(lun, XML_ELEMENT_LUN, &chk) ==
 			    False)
 				goto error;
 
 			if (chk == lun_num) {
-				lun = xml_alloc_node(XML_ELEMENT_LUN, Int,
+				lun = tgt_node_alloc(XML_ELEMENT_LUN, Int,
 				    &lun_num);
-				(void) xml_remove_child(list, lun, MatchBoth);
-				xml_free_node(lun);
+				(void) tgt_node_remove(list, lun, MatchBoth);
+				tgt_node_free(lun);
 				break;
 			}
 		}
@@ -1580,20 +1593,20 @@
 	    NULL) {
 		node = NULL;
 		while (xmlTextReaderRead(r) == 1)
-			if (xml_process_node(r, &node) == False)
+			if (tgt_node_process(r, &node) == False)
 				break;
 		close(xml_fd);
 		xmlTextReaderClose(r);
 		xmlFreeTextReader(r);
 		xmlCleanupParser();
 
-		(void) xml_find_value_str(node, XML_ELEMENT_BACK, &bs_path);
-		if ((xml_find_value_boolean(node, XML_ELEMENT_DELETE_BACK,
+		(void) tgt_find_value_str(node, XML_ELEMENT_BACK, &bs_path);
+		if ((tgt_find_value_boolean(node, XML_ELEMENT_DELETE_BACK,
 		    &bs_delete) == True) && (bs_delete == True))
 			unlink(bs_path);
 		if (bs_path != NULL)
 			free(bs_path);
-		xml_tree_free(node);
+		tgt_node_free(node);
 	}
 
 	(void) unlink(path);
@@ -1619,12 +1632,12 @@
 
 		/*
 		 * 'tname' is just a reference to the memory within
-		 * the targets_config structure. So once the xml_remove_child
+		 * the targets_config structure. So once the tgt_node_remove()
 		 * is called 'tname' is no longer valid.
 		 */
-		c = xml_alloc_node(XML_ELEMENT_TARG, String, tname);
-		(void) xml_remove_child(targets_config, c, MatchBoth);
-		xml_free_node(c);
+		c = tgt_node_alloc(XML_ELEMENT_TARG, String, tname);
+		(void) tgt_node_remove(targets_config, c, MatchBoth);
+		tgt_node_free(c);
 	}
 
 	/*
--- a/usr/src/cmd/iscsi/iscsitgtd/util_ifname.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/util_ifname.c	Wed Nov 15 19:25:44 2006 -0800
@@ -45,7 +45,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#include "local_types.h"
+#include <iscsitgt_impl.h>
 #include "target.h"
 #include "queue.h"
 #include "utility.h"
--- a/usr/src/cmd/iscsi/iscsitgtd/util_queue.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/util_queue.c	Wed Nov 15 19:25:44 2006 -0800
@@ -424,7 +424,7 @@
 	case msg_mgmt_rqst:
 		mq = (mgmt_request_t *)m->msg_data;
 		(void) pthread_mutex_lock(&mq->m_resp_mutex);
-		xml_add_tag(mq->m_u.m_resp, "queue_freed", 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;
@@ -432,8 +432,8 @@
 	case msg_mgmt_rply:
 		mq	= (mgmt_request_t *)m->msg_data;
 		buf	= mq->m_u.m_resp;
-		buf_add_tag(buf, XML_ELEMENT_STATS, Tag_End);
-		buf_add_tag(buf, XML_ELEMENT_CONN, Tag_End);
+		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);
@@ -469,7 +469,7 @@
 		mq = (mgmt_request_t *)m->msg_data;
 		(void) pthread_mutex_lock(&mq->m_resp_mutex);
 		if (mq->m_u.m_resp != NULL)
-			xml_add_tag(mq->m_u.m_resp, "queue_freed", 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;
--- a/usr/src/cmd/iscsi/iscsitgtd/utility.h	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/iscsi/iscsitgtd/utility.h	Wed Nov 15 19:25:44 2006 -0800
@@ -74,11 +74,11 @@
 Boolean_t update_config_targets(char **msg);
 Boolean_t update_config_main(char **msg);
 Boolean_t add_target_alias(iscsi_conn_t *c, char **text, int *test_length);
-Boolean_t validate_version(xml_node_t *node, int *maj, int *min);
+Boolean_t validate_version(tgt_node_t *node, int *maj, int *min);
 char *create_tpgt_list(char *tname);
-Boolean_t check_access(xml_node_t *targ, char *initiator_name,
+Boolean_t check_access(tgt_node_t *targ, char *initiator_name,
     Boolean_t req_chap);
-xml_node_t *find_target_node(char *targ_name);
+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);
 Boolean_t strtoll_multiplier(char *str, uint64_t *sp);
--- a/usr/src/cmd/zfs/zfs_main.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/zfs/zfs_main.c	Wed Nov 15 19:25:44 2006 -0800
@@ -18,6 +18,7 @@
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
@@ -77,7 +78,7 @@
  * debugging facilities.
  */
 const char *
-_umem_debug_init()
+_umem_debug_init(void)
 {
 	return ("default,verbose"); /* $UMEM_DEBUG setting */
 }
@@ -1919,7 +1920,7 @@
 			(void) fprintf(stderr, gettext("property may be set "
 			    "but unable to remount filesystem\n"));
 			break;
-		case EZFS_SHAREFAILED:
+		case EZFS_SHARENFSFAILED:
 			(void) fprintf(stderr, gettext("property may be set "
 			    "but unable to reshare filesystem\n"));
 			break;
@@ -2190,17 +2191,27 @@
 	zfs_handle_t	**cb_handles;
 	size_t		cb_alloc;
 	size_t		cb_used;
+	uint_t		cb_types;
 } get_all_cbdata_t;
 
 static int
-get_one_filesystem(zfs_handle_t *zhp, void *data)
+get_one_dataset(zfs_handle_t *zhp, void *data)
 {
 	get_all_cbdata_t *cbp = data;
+	zfs_type_t type = zfs_get_type(zhp);
 
 	/*
-	 * Skip any zvols
+	 * Interate over any nested datasets.
 	 */
-	if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
+	if (type == ZFS_TYPE_FILESYSTEM &&
+	    zfs_iter_filesystems(zhp, get_one_dataset, data) != 0) {
+		return (1);
+	}
+
+	/*
+	 * Skip any datasets whose type does not match.
+	 */
+	if ((type & cbp->cb_types) == 0) {
 		zfs_close(zhp);
 		return (0);
 	}
@@ -2226,34 +2237,46 @@
 
 	cbp->cb_handles[cbp->cb_used++] = zhp;
 
-	return (zfs_iter_filesystems(zhp, get_one_filesystem, data));
+	return (0);
 }
 
 static void
-get_all_filesystems(zfs_handle_t ***fslist, size_t *count)
+get_all_datasets(uint_t types, zfs_handle_t ***dslist, size_t *count)
 {
 	get_all_cbdata_t cb = { 0 };
-
-	(void) zfs_iter_root(g_zfs, get_one_filesystem, &cb);
-
-	*fslist = cb.cb_handles;
+	cb.cb_types = types;
+
+	(void) zfs_iter_root(g_zfs, get_one_dataset, &cb);
+
+	*dslist = cb.cb_handles;
 	*count = cb.cb_used;
 }
 
 static int
-mountpoint_compare(const void *a, const void *b)
+dataset_cmp(const void *a, const void *b)
 {
 	zfs_handle_t **za = (zfs_handle_t **)a;
 	zfs_handle_t **zb = (zfs_handle_t **)b;
 	char mounta[MAXPATHLEN];
 	char mountb[MAXPATHLEN];
-
-	verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta,
-	    sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0);
-	verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb,
-	    sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0);
-
-	return (strcmp(mounta, mountb));
+	boolean_t gota, gotb;
+
+	if ((gota = (zfs_get_type(*za) == ZFS_TYPE_FILESYSTEM)) != 0)
+		verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta,
+		    sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0);
+	if ((gotb = (zfs_get_type(*zb) == ZFS_TYPE_FILESYSTEM)) != 0)
+		verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb,
+		    sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0);
+
+	if (gota && gotb)
+		return (strcmp(mounta, mountb));
+
+	if (gota)
+		return (-1);
+	if (gotb)
+		return (1);
+
+	return (strcmp(zfs_get_name(a), zfs_get_name(b)));
 }
 
 /*
@@ -2264,69 +2287,63 @@
 #define	OP_SHARE	0x1
 #define	OP_MOUNT	0x2
 
-typedef struct share_mount_cbdata {
-	int	cb_type;
-	int	cb_explicit;
-	int	cb_flags;
-	const char *cb_options;
-} share_mount_cbdata_t;
-
 /*
- * Share or mount the filesystem.
+ * Share or mount a dataset.
  */
 static int
-share_mount_callback(zfs_handle_t *zhp, void *data)
+share_mount_one(zfs_handle_t *zhp, int op, int flags, boolean_t explicit,
+    const char *options)
 {
 	char mountpoint[ZFS_MAXPROPLEN];
 	char shareopts[ZFS_MAXPROPLEN];
-	share_mount_cbdata_t *cbp = data;
-	const char *cmdname = cbp->cb_type == OP_SHARE ? "share" : "mount";
+	const char *cmdname = op == OP_SHARE ? "share" : "mount";
 	struct mnttab mnt;
 	uint64_t zoned, canmount;
-
-	if (cbp->cb_options == NULL)
-		mnt.mnt_mntopts = "";
-	else
-		mnt.mnt_mntopts = (char *)cbp->cb_options;
-
-	/*
-	 * Check to make sure we can mount/share this dataset.  If we are in the
-	 * global zone and the filesystem is exported to a local zone, or if we
-	 * are in a local zone and the filesystem is not exported, then it is an
-	 * error.
-	 */
-	zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);
-
-	if (zoned && getzoneid() == GLOBAL_ZONEID) {
-		if (!cbp->cb_explicit)
-			return (0);
-
-		(void) fprintf(stderr, gettext("cannot %s '%s': dataset is "
-		    "exported to a local zone\n"), cmdname, zfs_get_name(zhp));
-		return (1);
-
-	} else if (!zoned && getzoneid() != GLOBAL_ZONEID) {
-		if (!cbp->cb_explicit)
-			return (0);
-
-		(void) fprintf(stderr, gettext("cannot %s '%s': permission "
-		    "denied\n"), cmdname, zfs_get_name(zhp));
-		return (1);
-	}
-
-	/*
-	 * Inore any filesystems which don't apply to us.  This includes those
-	 * with a legacy mountpoint, or those with legacy share options.
-	 */
-	verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
-	    sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0);
-	verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts,
-	    sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0);
-	canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT);
-
-	if (cbp->cb_type == OP_SHARE) {
-		if (strcmp(shareopts, "off") == 0) {
-			if (!cbp->cb_explicit)
+	zfs_type_t type = zfs_get_type(zhp);
+
+	assert(type & (ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME));
+
+	if (type == ZFS_TYPE_FILESYSTEM) {
+		/*
+		 * Check to make sure we can mount/share this dataset.  If we
+		 * are in the global zone and the filesystem is exported to a
+		 * local zone, or if we are in a local zone and the
+		 * filesystem is not exported, then it is an error.
+		 */
+		zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);
+
+		if (zoned && getzoneid() == GLOBAL_ZONEID) {
+			if (!explicit)
+				return (0);
+
+			(void) fprintf(stderr, gettext("cannot %s '%s': "
+			    "dataset is exported to a local zone\n"), cmdname,
+			    zfs_get_name(zhp));
+			return (1);
+
+		} else if (!zoned && getzoneid() != GLOBAL_ZONEID) {
+			if (!explicit)
+				return (0);
+
+			(void) fprintf(stderr, gettext("cannot %s '%s': "
+			    "permission denied\n"), cmdname,
+			    zfs_get_name(zhp));
+			return (1);
+		}
+
+		/*
+		 * Ignore any filesystems which don't apply to us. This
+		 * includes those with a legacy mountpoint, or those with
+		 * legacy share options.
+		 */
+		verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
+		    sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0);
+		verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts,
+		    sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0);
+		canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT);
+
+		if (op == OP_SHARE && strcmp(shareopts, "off") == 0) {
+			if (!explicit)
 				return (0);
 
 			(void) fprintf(stderr, gettext("cannot share '%s': "
@@ -2335,123 +2352,150 @@
 			    "share this filesystem\n"));
 			return (1);
 		}
-	}
-
-	/*
-	 * We cannot share or mount legacy filesystems.  If the shareopts is
-	 * non-legacy but the mountpoint is legacy, we treat it as a legacy
-	 * share.
-	 */
-	if (strcmp(mountpoint, "legacy") == 0) {
-		if (!cbp->cb_explicit)
-			return (0);
-
-		(void) fprintf(stderr, gettext("cannot %s '%s': "
-		    "legacy mountpoint\n"), cmdname, zfs_get_name(zhp));
-		(void) fprintf(stderr, gettext("use %s to "
-		    "%s this filesystem\n"), cbp->cb_type == OP_SHARE ?
-		    "share(1M)" : "mount(1M)", cmdname);
-		return (1);
-	}
-
-	if (strcmp(mountpoint, "none") == 0) {
-		if (!cbp->cb_explicit)
-			return (0);
-
-		(void) fprintf(stderr, gettext("cannot %s '%s': no "
-		    "mountpoint set\n"), cmdname, zfs_get_name(zhp));
-		return (1);
-	}
-
-	if (!canmount) {
-		if (!cbp->cb_explicit)
-			return (0);
-
-		(void) fprintf(stderr, gettext("cannot %s '%s': 'canmount' "
-		    "property is set to 'off'\n"), cmdname, zfs_get_name(zhp));
-		return (1);
-	}
-
-	/*
-	 * At this point, we have verified that the mountpoint and/or shareopts
-	 * are appropriate for auto management.  Determine if the filesystem is
-	 * currently mounted or shared, and abort if this is an explicit
-	 * request.
-	 */
-	switch (cbp->cb_type) {
-	case OP_SHARE:
-		if (zfs_is_shared(zhp, NULL)) {
-			if (cbp->cb_explicit) {
+
+		/*
+		 * We cannot share or mount legacy filesystems. If the
+		 * shareopts is non-legacy but the mountpoint is legacy, we
+		 * treat it as a legacy share.
+		 */
+		if (strcmp(mountpoint, "legacy") == 0) {
+			if (!explicit)
+				return (0);
+
+			(void) fprintf(stderr, gettext("cannot %s '%s': "
+			    "legacy mountpoint\n"), cmdname, zfs_get_name(zhp));
+			(void) fprintf(stderr, gettext("use %s to "
+			    "%s this filesystem\n"), op == OP_SHARE ?
+			    "share(1M)" : "mount(1M)", cmdname);
+			return (1);
+		}
+
+		if (strcmp(mountpoint, "none") == 0) {
+			if (!explicit)
+				return (0);
+
+			(void) fprintf(stderr, gettext("cannot %s '%s': no "
+			    "mountpoint set\n"), cmdname, zfs_get_name(zhp));
+			return (1);
+		}
+
+		if (!canmount) {
+			if (!explicit)
+				return (0);
+
+			(void) fprintf(stderr, gettext("cannot %s '%s': "
+			    "'canmount' property is set to 'off'\n"), cmdname,
+			    zfs_get_name(zhp));
+			return (1);
+		}
+
+		/*
+		 * At this point, we have verified that the mountpoint and/or
+		 * shareopts are appropriate for auto management. If the
+		 * filesystem is already mounted or shared, return (failing
+		 * for explicit requests); otherwise mount or share the
+		 * filesystem.
+		 */
+		switch (op) {
+		case OP_SHARE:
+			if (zfs_is_shared_nfs(zhp, NULL)) {
+				if (!explicit)
+					return (0);
+
 				(void) fprintf(stderr, gettext("cannot share "
 				    "'%s': filesystem already shared\n"),
 				    zfs_get_name(zhp));
 				return (1);
-			} else {
-				return (0);
 			}
-		}
-		break;
-
-	case OP_MOUNT:
-		if (!hasmntopt(&mnt, MNTOPT_REMOUNT) &&
-		    zfs_is_mounted(zhp, NULL)) {
-			if (cbp->cb_explicit) {
+
+			if (!zfs_is_mounted(zhp, NULL) &&
+			    zfs_mount(zhp, NULL, 0) != 0)
+				return (1);
+
+			if (zfs_share_nfs(zhp) != 0)
+				return (1);
+			break;
+
+		case OP_MOUNT:
+			if (options == NULL)
+				mnt.mnt_mntopts = "";
+			else
+				mnt.mnt_mntopts = (char *)options;
+
+			if (!hasmntopt(&mnt, MNTOPT_REMOUNT) &&
+			    zfs_is_mounted(zhp, NULL)) {
+				if (!explicit)
+					return (0);
+
 				(void) fprintf(stderr, gettext("cannot mount "
 				    "'%s': filesystem already mounted\n"),
 				    zfs_get_name(zhp));
 				return (1);
-			} else {
-				return (0);
 			}
+
+			if (zfs_mount(zhp, options, flags) != 0)
+				return (1);
+			break;
 		}
-		break;
-	}
-
-	/*
-	 * Mount and optionally share the filesystem.
-	 */
-	switch (cbp->cb_type) {
-	case OP_SHARE:
-		{
-			if (!zfs_is_mounted(zhp, NULL) &&
-			    zfs_mount(zhp, NULL, 0) != 0)
-				return (1);
-
-			if (zfs_share(zhp) != 0)
-				return (1);
+	} 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);
 		}
-		break;
-
-	case OP_MOUNT:
-		if (zfs_mount(zhp, cbp->cb_options, cbp->cb_flags) != 0)
+
+		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);
-		break;
+		}
+
+		if (zfs_share_iscsi(zhp) != 0)
+			return (1);
 	}
 
 	return (0);
 }
 
 static int
-share_or_mount(int type, int argc, char **argv)
+share_mount(int op, int argc, char **argv)
 {
 	int do_all = 0;
 	int c, ret = 0;
-	share_mount_cbdata_t cb = { 0 };
-
-	cb.cb_type = type;
+	const char *options = NULL;
+	int types, flags = 0;
 
 	/* check options */
-	while ((c = getopt(argc, argv, type == OP_MOUNT ? ":ao:O" : "a"))
+	while ((c = getopt(argc, argv, op == OP_MOUNT ? ":ao:O" : "a"))
 	    != -1) {
 		switch (c) {
 		case 'a':
 			do_all = 1;
 			break;
 		case 'o':
-			cb.cb_options = optarg;
+			options = optarg;
 			break;
 		case 'O':
-			cb.cb_flags |= MS_OVERLAY;
+			flags |= MS_OVERLAY;
 			break;
 		case ':':
 			(void) fprintf(stderr, gettext("missing argument for "
@@ -2470,34 +2514,52 @@
 
 	/* check number of arguments */
 	if (do_all) {
-		zfs_handle_t **fslist = NULL;
+		zfs_handle_t **dslist = NULL;
 		size_t i, count = 0;
 
+		if (op == OP_MOUNT) {
+			types = ZFS_TYPE_FILESYSTEM;
+		} else if (argc > 0) {
+			if (strcmp(argv[0], "nfs") == 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' or 'iscsi'\n"));
+				usage(B_FALSE);
+			}
+
+			argc--;
+			argv++;
+		} else {
+			types = ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME;
+		}
+
 		if (argc != 0) {
 			(void) fprintf(stderr, gettext("too many arguments\n"));
 			usage(B_FALSE);
 		}
 
-		get_all_filesystems(&fslist, &count);
+		get_all_datasets(types, &dslist, &count);
 
 		if (count == 0)
 			return (0);
 
-		qsort(fslist, count, sizeof (void *), mountpoint_compare);
+		qsort(dslist, count, sizeof (void *), dataset_cmp);
 
 		for (i = 0; i < count; i++) {
-			if (share_mount_callback(fslist[i], &cb) != 0)
+			if (share_mount_one(dslist[i], op, flags, B_FALSE,
+			    options) != 0)
 				ret = 1;
+			zfs_close(dslist[i]);
 		}
 
-		for (i = 0; i < count; i++)
-			zfs_close(fslist[i]);
-
-		free(fslist);
+		free(dslist);
 	} else if (argc == 0) {
 		struct mnttab entry;
 
-		if (type == OP_SHARE) {
+		if (op == OP_SHARE) {
 			(void) fprintf(stderr, gettext("missing filesystem "
 			    "argument\n"));
 			usage(B_FALSE);
@@ -2521,18 +2583,21 @@
 	} else {
 		zfs_handle_t *zhp;
 
+		types = ZFS_TYPE_FILESYSTEM;
+		if (op == OP_SHARE)
+			types |= ZFS_TYPE_VOLUME;
+
 		if (argc > 1) {
 			(void) fprintf(stderr,
 			    gettext("too many arguments\n"));
 			usage(B_FALSE);
 		}
 
-		if ((zhp = zfs_open(g_zfs, argv[0],
-		    ZFS_TYPE_FILESYSTEM)) == NULL)
+		if ((zhp = zfs_open(g_zfs, argv[0], types)) == NULL) {
 			ret = 1;
-		else {
-			cb.cb_explicit = B_TRUE;
-			ret = share_mount_callback(zhp, &cb);
+		} else {
+			ret = share_mount_one(zhp, op, flags, B_TRUE,
+			    options);
 			zfs_close(zhp);
 		}
 	}
@@ -2541,7 +2606,7 @@
 }
 
 /*
- * zfs mount -a
+ * zfs mount -a [nfs | iscsi]
  * zfs mount filesystem
  *
  * Mount all filesystems, or mount the given filesystem.
@@ -2549,11 +2614,11 @@
 static int
 zfs_do_mount(int argc, char **argv)
 {
-	return (share_or_mount(OP_MOUNT, argc, argv));
+	return (share_mount(OP_MOUNT, argc, argv));
 }
 
 /*
- * zfs share -a
+ * zfs share -a [nfs | iscsi]
  * zfs share filesystem
  *
  * Share all filesystems, or share the given filesystem.
@@ -2561,7 +2626,7 @@
 static int
 zfs_do_share(int argc, char **argv)
 {
-	return (share_or_mount(OP_SHARE, argc, argv));
+	return (share_mount(OP_SHARE, argc, argv));
 }
 
 typedef struct unshare_unmount_node {
@@ -2586,13 +2651,13 @@
  * and unmount it appropriately.
  */
 static int
-unshare_unmount_path(int type, char *path, int flags, boolean_t is_manual)
+unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
 {
 	zfs_handle_t *zhp;
 	int ret;
 	struct stat64 statbuf;
 	struct extmnttab entry;
-	const char *cmdname = (type == OP_SHARE) ? "unshare" : "unmount";
+	const char *cmdname = (op == OP_SHARE) ? "unshare" : "unmount";
 	char property[ZFS_MAXPROPLEN];
 
 	/*
@@ -2632,23 +2697,23 @@
 	    ZFS_TYPE_FILESYSTEM)) == NULL)
 		return (1);
 
-	verify(zfs_prop_get(zhp, type == OP_SHARE ?
+	verify(zfs_prop_get(zhp, op == OP_SHARE ?
 		ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT, property,
 		sizeof (property), NULL, NULL, 0, B_FALSE) == 0);
 
-	if (type == OP_SHARE) {
+	if (op == OP_SHARE) {
 		if (strcmp(property, "off") == 0) {
 			(void) fprintf(stderr, gettext("cannot unshare "
 			    "'%s': legacy share\n"), path);
 			(void) fprintf(stderr, gettext("use "
 			    "unshare(1M) to unshare this filesystem\n"));
 			ret = 1;
-		} else if (!zfs_is_shared(zhp, NULL)) {
+		} else if (!zfs_is_shared_nfs(zhp, NULL)) {
 			(void) fprintf(stderr, gettext("cannot unshare '%s': "
 			    "not currently shared\n"), path);
 			ret = 1;
 		} else {
-			ret = zfs_unshareall(zhp);
+			ret = zfs_unshareall_nfs(zhp);
 		}
 	} else {
 		if (is_manual) {
@@ -2674,17 +2739,17 @@
  * Generic callback for unsharing or unmounting a filesystem.
  */
 static int
-unshare_unmount(int type, int argc, char **argv)
+unshare_unmount(int op, int argc, char **argv)
 {
 	int do_all = 0;
 	int flags = 0;
 	int ret = 0;
-	int c;
+	int types, c;
 	zfs_handle_t *zhp;
 	char property[ZFS_MAXPROPLEN];
 
 	/* check options */
-	while ((c = getopt(argc, argv, type == OP_SHARE ? "a" : "af")) != -1) {
+	while ((c = getopt(argc, argv, op == OP_SHARE ? "a" : "af")) != -1) {
 		switch (c) {
 		case 'a':
 			do_all = 1;
@@ -2702,22 +2767,6 @@
 	argc -= optind;
 	argv += optind;
 
-	/* ensure correct number of arguments */
-	if (do_all) {
-		if (argc != 0) {
-			(void) fprintf(stderr, gettext("too many arguments\n"));
-			usage(B_FALSE);
-		}
-	} else if (argc != 1) {
-		if (argc == 0)
-			(void) fprintf(stderr,
-			    gettext("missing filesystem argument\n"));
-		else
-			(void) fprintf(stderr,
-			    gettext("too many arguments\n"));
-		usage(B_FALSE);
-	}
-
 	if (do_all) {
 		/*
 		 * We could make use of zfs_for_each() to walk all datasets in
@@ -2740,6 +2789,11 @@
 		uu_avl_index_t idx;
 		uu_avl_walk_t *walk;
 
+		if (argc != 0) {
+			(void) fprintf(stderr, gettext("too many arguments\n"));
+			usage(B_FALSE);
+		}
+
 		if ((pool = uu_avl_pool_create("unmount_pool",
 		    sizeof (unshare_unmount_node_t),
 		    offsetof(unshare_unmount_node_t, un_avlnode),
@@ -2773,15 +2827,15 @@
 				continue;
 			}
 
-			verify(zfs_prop_get(zhp, type == OP_SHARE ?
+			verify(zfs_prop_get(zhp, op == OP_SHARE ?
 			    ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT,
 			    property, sizeof (property), NULL, NULL,
 			    0, B_FALSE) == 0);
 
 			/* Ignore legacy mounts and shares */
-			if ((type == OP_SHARE &&
+			if ((op == OP_SHARE &&
 			    strcmp(property, "off") == 0) ||
-			    (type == OP_MOUNT &&
+			    (op == OP_MOUNT &&
 			    strcmp(property, "legacy") == 0)) {
 				zfs_close(zhp);
 				continue;
@@ -2822,9 +2876,9 @@
 		while ((node = uu_avl_walk_next(walk)) != NULL) {
 			uu_avl_remove(tree, node);
 
-			switch (type) {
+			switch (op) {
 			case OP_SHARE:
-				if (zfs_unshare(node->un_zhp,
+				if (zfs_unshare_nfs(node->un_zhp,
 				    node->un_mountp) != 0)
 					ret = 1;
 				break;
@@ -2844,7 +2898,40 @@
 		uu_avl_walk_end(walk);
 		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);
+
+			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)
+				(void) fprintf(stderr,
+				    gettext("missing filesystem argument\n"));
+			else
+				(void) fprintf(stderr,
+				    gettext("too many arguments\n"));
+			usage(B_FALSE);
+		}
+
 		/*
 		 * We have an argument, but it may be a full path or a ZFS
 		 * filesystem.  Pass full paths off to unmount_path() (shared by
@@ -2852,49 +2939,81 @@
 		 * zfs_unmount().
 		 */
 		if (argv[0][0] == '/')
-			return (unshare_unmount_path(type, argv[0],
+			return (unshare_unmount_path(op, argv[0],
 				flags, B_FALSE));
 
-		if ((zhp = zfs_open(g_zfs, argv[0],
-		    ZFS_TYPE_FILESYSTEM)) == NULL)
+		types = ZFS_TYPE_FILESYSTEM;
+		if (op == OP_SHARE)
+			types |= ZFS_TYPE_VOLUME;
+
+		if ((zhp = zfs_open(g_zfs, argv[0], types)) == NULL)
 			return (1);
 
-		verify(zfs_prop_get(zhp, type == OP_SHARE ?
-		    ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT, property,
-		    sizeof (property), NULL, NULL, 0, B_FALSE) == 0);
-
-		switch (type) {
-		case OP_SHARE:
+		if (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
+			verify(zfs_prop_get(zhp, op == OP_SHARE ?
+			    ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT, property,
+			    sizeof (property), NULL, NULL, 0, B_FALSE) == 0);
+
+			switch (op) {
+			case OP_SHARE:
+				if (strcmp(property, "off") == 0) {
+					(void) fprintf(stderr, gettext("cannot "
+					    "unshare '%s': legacy share\n"),
+					    zfs_get_name(zhp));
+					(void) fprintf(stderr, gettext("use "
+					    "unshare(1M) to unshare this "
+					    "filesystem\n"));
+					ret = 1;
+				} else if (!zfs_is_shared_nfs(zhp, NULL)) {
+					(void) fprintf(stderr, gettext("cannot "
+					    "unshare '%s': not currently "
+					    "shared\n"), zfs_get_name(zhp));
+					ret = 1;
+				} else if (zfs_unshareall_nfs(zhp) != 0) {
+					ret = 1;
+				}
+				break;
+
+			case OP_MOUNT:
+				if (strcmp(property, "legacy") == 0) {
+					(void) fprintf(stderr, gettext("cannot "
+					    "unmount '%s': legacy "
+					    "mountpoint\n"), zfs_get_name(zhp));
+					(void) fprintf(stderr, gettext("use "
+					    "umount(1M) to unmount this "
+					    "filesystem\n"));
+					ret = 1;
+				} else if (!zfs_is_mounted(zhp, NULL)) {
+					(void) fprintf(stderr, gettext("cannot "
+					    "unmount '%s': not currently "
+					    "mounted\n"),
+					    zfs_get_name(zhp));
+					ret = 1;
+				} else if (zfs_unmountall(zhp, flags) != 0) {
+					ret = 1;
+				}
+				break;
+			}
+		} else {
+			assert(op == OP_SHARE);
+
+			verify(zfs_prop_get(zhp, ZFS_PROP_SHAREISCSI, property,
+			    sizeof (property), NULL, NULL, 0, B_FALSE) == 0);
+
 			if (strcmp(property, "off") == 0) {
 				(void) fprintf(stderr, gettext("cannot unshare "
-				    "'%s': legacy share\n"), zfs_get_name(zhp));
-				(void) fprintf(stderr, gettext("use unshare(1M)"
-				    " to unshare this filesystem\n"));
+				    "'%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(zhp, NULL)) {
-				(void) fprintf(stderr, gettext("cannot unshare "
-				    "'%s': not currently shared\n"),
+			} 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_unshareall(zhp) != 0) {
-				ret = 1;
-			}
-			break;
-
-		case OP_MOUNT:
-			if (strcmp(property, "legacy") == 0) {
-				(void) fprintf(stderr, gettext("cannot unmount "
-				    "'%s': legacy mountpoint\n"),
-				    zfs_get_name(zhp));
-				(void) fprintf(stderr, gettext("use umount(1M) "
-				    "to unmount this filesystem\n"));
-				ret = 1;
-			} else if (!zfs_is_mounted(zhp, NULL)) {
-				(void) fprintf(stderr, gettext("cannot unmount "
-				    "'%s': not currently mounted\n"),
-				    zfs_get_name(zhp));
-				ret = 1;
-			} else if (zfs_unmountall(zhp, flags) != 0) {
+			} else if (zfs_unshare_iscsi(zhp) != 0) {
 				ret = 1;
 			}
 		}
--- a/usr/src/cmd/zpool/zpool_main.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/cmd/zpool/zpool_main.c	Wed Nov 15 19:25:44 2006 -0800
@@ -678,7 +678,7 @@
 					    ZFS_PROP_MOUNTPOINT),
 					    mountpoint) == 0);
 				if (zfs_mount(pool, NULL, 0) == 0)
-					ret = zfs_share(pool);
+					ret = zfs_share_nfs(pool);
 				zfs_close(pool);
 			}
 			zpool_log_history(g_zfs, argc + optind, argv - optind,
@@ -749,7 +749,7 @@
 		return (1);
 	}
 
-	if (zpool_unmount_datasets(zhp, force) != 0) {
+	if (zpool_disable_datasets(zhp, force) != 0) {
 		(void) fprintf(stderr, gettext("could not destroy '%s': "
 		    "could not unmount datasets\n"), zpool_get_name(zhp));
 		return (1);
@@ -812,7 +812,7 @@
 			continue;
 		}
 
-		if (zpool_unmount_datasets(zhp, force) != 0) {
+		if (zpool_disable_datasets(zhp, force) != 0) {
 			ret = 1;
 			zpool_close(zhp);
 			continue;
@@ -1134,7 +1134,7 @@
 
 	verify((zhp = zpool_open(g_zfs, name)) != NULL);
 
-	if (zpool_mount_datasets(zhp, mntopts, 0) != 0) {
+	if (zpool_enable_datasets(zhp, mntopts, 0) != 0) {
 		zpool_close(zhp);
 		return (1);
 	}
--- a/usr/src/common/zfs/zfs_prop.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/common/zfs/zfs_prop.c	Wed Nov 15 19:25:44 2006 -0800
@@ -118,6 +118,9 @@
 	{ "sharenfs",	prop_type_string,	0,	"off",	prop_inherit,
 	    ZFS_TYPE_FILESYSTEM,
 	    "on | off | share(1M) options", "SHARENFS", B_FALSE },
+	{ "shareiscsi",	prop_type_string,	0,	"off",	prop_inherit,
+	    ZFS_TYPE_ANY,
+	    "on | off | type=<type>", "SHAREISCSI", B_FALSE },
 	{ "checksum",	prop_type_index,	ZIO_CHECKSUM_DEFAULT,	"on",
 	    prop_inherit,	ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
 	    "on | off | fletcher2 | fletcher4 | sha256", "CHECKSUM", B_TRUE },
@@ -159,6 +162,8 @@
 	    ZFS_TYPE_ANY, NULL, NULL, B_FALSE},
 	{ "name",	prop_type_string,	0,	NULL,	prop_readonly,
 	    ZFS_TYPE_ANY, NULL, "NAME", B_FALSE },
+	{ "iscsioptions", prop_type_string,	0,	NULL,	prop_inherit,
+	    ZFS_TYPE_VOLUME, NULL, "ISCSIOPTIONS", B_FALSE },
 };
 
 zfs_proptype_t
--- a/usr/src/lib/Makefile	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/lib/Makefile	Wed Nov 15 19:25:44 2006 -0800
@@ -108,6 +108,7 @@
 	libinetcfg	\
 	libinetutil	\
 	libipmp		\
+	libiscsitgt	\
 	libkmf		\
 	libkstat	\
 	libkvm		\
@@ -335,6 +336,7 @@
 	libinetutil	\
 	libipmp		\
 	libipp		\
+	libiscsitgt	\
 	libkstat	\
 	libkvm		\
         liblaadm        \
@@ -500,7 +502,7 @@
 pkcs11:		libcryptoutil
 print:		libldap5
 udapl/udapl_tavor:	udapl/libdat
-libzfs:		libdevinfo libdevid libgen libnvpair libuutil
+libzfs:		libdevinfo libdevid libgen libnvpair libuutil libiscsitgt
 libzfs_jni:	libdiskmgt libnvpair libzfs
 libzpool:	libavl libumem libnvpair
 libsec:		libavl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libiscsitgt/Makefile	Wed Nov 15 19:25:44 2006 -0800
@@ -0,0 +1,56 @@
+#
+# 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libiscsitgt/Makefile.com	Wed Nov 15 19:25:44 2006 -0800
@@ -0,0 +1,53 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+LIBRARY=	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)
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+include ../../Makefile.targ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libiscsitgt/amd64/Makefile	Wed Nov 15 19:25:44 2006 -0800
@@ -0,0 +1,31 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libiscsitgt/common/gen.c	Wed Nov 15 19:25:44 2006 -0800
@@ -0,0 +1,160 @@
+/*
+ * 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"
+
+/*
+ * 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 char *bad_call_str = "<error><code>1</code>"
+	"<message>Can't call daemon</message></error>";
+
+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;
+	xmlTextReaderPtr	r;
+
+	d.data_ptr	= str;
+	d.data_size	= strlen(str) + 1;
+	d.desc_ptr	= NULL;
+	d.desc_num	= 0;
+	d.rbuf		= NULL;
+	d.rsize		= 0;
+
+	if (((s = open(ISCSI_TARGET_MGMT_DOOR, 0)) < 0) ||
+	    (door_call(s, &d) < 0)) {
+		if (s != -1)
+			(void) close(s);
+		if (check_and_online(smf_flags) == False) {
+			d.rbuf = bad_call_str;
+		} else if ((s = open(ISCSI_TARGET_MGMT_DOOR, 0)) < 0) {
+			d.rbuf = bad_call_str;
+		} else if (door_call(s, &d) < 0)
+			d.rbuf = bad_call_str;
+	}
+	if ((r = (xmlTextReaderPtr)xmlReaderForMemory(d.rbuf, strlen(d.rbuf),
+	    NULL, NULL, 0)) == NULL)
+		return (NULL);
+
+	while (xmlTextReaderRead(r) == 1)
+		if (tgt_node_process(r, &n) == False)
+			break;
+	xmlFreeTextReader(r);
+	if (d.rbuf != bad_call_str)
+		(void) munmap(d.rbuf, d.rsize);
+	(void) close(s);
+
+	return (n);
+}
+
+static Boolean_t
+is_online(void)
+{
+	char		*s;
+	Boolean_t	rval = False;
+
+	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,
+		fd;
+
+	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) {
+			(void) close(fd);
+			return (True);
+		}
+		if (!is_online())
+			break;
+		(void) sleep(1);
+	}
+	return (False);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libiscsitgt/common/if_gen.c	Wed Nov 15 19:25:44 2006 -0800
@@ -0,0 +1,48 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <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)
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libiscsitgt/common/if_zfs.c	Wed Nov 15 19:25:44 2006 -0800
@@ -0,0 +1,123 @@
+/*
+ * 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"
+
+/*
+ * 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 "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);
+
+	n = tgt_door_call(str, SMF_TEMPORARY);
+	if (strcmp(n->x_name, XML_ELEMENT_ERROR) == 0 &&
+	    tgt_find_value_int(n, XML_ELEMENT_CODE, &code) == True &&
+	    code == 1000) {
+		tgt_node_free(n);
+		return (0);
+	}
+
+	errno = EINVAL;
+	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);
+
+	n = tgt_door_call(str, SMF_TEMPORARY);
+	if (strcmp(n->x_name, XML_ELEMENT_ERROR) == 0 &&
+	    tgt_find_value_int(n, XML_ELEMENT_CODE, &code) == True &&
+	    code == 1000) {
+		tgt_node_free(n);
+		return (0);
+	}
+
+	tgt_node_free(n);
+	errno = EINVAL;
+	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);
+
+	n = tgt_door_call(str, SMF_TEMPORARY);
+	if (strcmp(n->x_name, XML_ELEMENT_ERROR) == 0 &&
+	    tgt_find_value_int(n, XML_ELEMENT_CODE, &code) == True &&
+	    code == 1000) {
+		tgt_node_free(n);
+		return (1);
+	}
+
+	tgt_node_free(n);
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libiscsitgt/common/iscsitgt_impl.h	Wed Nov 15 19:25:44 2006 -0800
@@ -0,0 +1,202 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _ISCSITGT_IMPL_H
+#define	_ISCSITGT_IMPL_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+/*
+ * 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	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_CHAPNAME	"chap-name"
+#define	XML_ELEMENT_RAD_ACCESS	"radius-access"
+#define	XML_ELEMENT_RAD_SERV	"radius-server"
+#define	XML_ELEMENT_RAD_SECRET	"radius-secret"
+#define	XML_ELEMENT_ISNS_ACCESS	"isns-access"
+#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_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_VALUE_TRUE		"true"
+
+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);
+Boolean_t tgt_dump2file(tgt_node_t *t, char *path);
+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 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libiscsitgt/common/libiscsitgt.h	Wed Nov 15 19:25:44 2006 -0800
@@ -0,0 +1,573 @@
+/*
+ * 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 _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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBISCSITGT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libiscsitgt/common/llib-liscsitgt	Wed Nov 15 19:25:44 2006 -0800
@@ -0,0 +1,30 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*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>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libiscsitgt/common/mapfile-vers	Wed Nov 15 19:25:44 2006 -0800
@@ -0,0 +1,60 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+SUNWprivate_1.1 {
+    global:
+    	iscsitgt_zfs_is_shared;
+    	iscsitgt_zfs_share;
+	iscsitgt_zfs_unshare;
+	tgt_door_call;
+	tgt_node_free;
+	tgt_dump2file;
+	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:
+	*;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libiscsitgt/common/xml.c	Wed Nov 15 19:25:44 2006 -0800
@@ -0,0 +1,949 @@
+/*
+ * 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 <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,
+			*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);
+
+}
+
+/*
+ * []----
+ * | xml_update_config -- dump out in core node tree to XML parsable file
+ * |
+ * | The depth argument is only used to pad the output with white space
+ * | for indentation. This is meant to help the readability of the file
+ * | for humans.
+ * []----
+ */
+static void
+xml_update_config(tgt_node_t *t, int depth, FILE *output)
+{
+	int		i;
+	tgt_node_t	*c;
+
+	if (t == NULL)
+		return;
+
+	/*
+	 * If this node has an attribute which indicates it's incore only
+	 * we don't dump it out to a file.
+	 */
+	for (c = t->x_attr; c; c = c->x_sibling)
+		if ((strcmp(c->x_name, XML_ELEMENT_INCORE) == 0) &&
+		    (strcmp(c->x_value, XML_VALUE_TRUE) == 0))
+			return;
+
+	for (i = 0; i < depth; i++)
+		(void) fprintf(output, "    ");
+	if (strcmp(t->x_name, XML_COMMENT_STR) == 0) {
+		(void) fprintf(output, "<%s%s%s>\n", XML_COMMENT_STR,
+			t->x_value, XML_COMMENT_END);
+		return;
+	}
+	if ((t->x_child == NULL) && (t->x_value != NULL) &&
+	    (t->x_attr == NULL) &&
+	    (((depth * 4) + ((strlen(t->x_name) * 2) + 5) +
+	    strlen(t->x_value)) < 80)) {
+
+		(void) fprintf(output, "<%s>%s</%s>\n", t->x_name, t->x_value,
+		    t->x_name);
+
+	} else {
+		(void) fprintf(output, "<%s", t->x_name);
+		for (c = t->x_attr; c; c = c->x_sibling)
+			(void) fprintf(output, " %s='%s'", c->x_name,
+			    c->x_value);
+		(void) fprintf(output, ">\n");
+		if (t->x_value) {
+			for (i = 0; i < depth + 1; i++)
+				(void) fprintf(output, "    ");
+			(void) fprintf(output, "%s\n", t->x_value);
+		}
+		for (c = t->x_child; c; c = c->x_sibling)
+			xml_update_config(c, depth + 1, output);
+		for (i = 0; i < depth; i++)
+			(void) fprintf(output, "    ");
+		(void) fprintf(output, "</%s>\n", t->x_name);
+	}
+}
+
+Boolean_t
+tgt_dump2file(tgt_node_t *root, char *path)
+{
+	FILE	*output;
+
+	if ((output = fopen(path, "wb")) == NULL) {
+		syslog(LOG_ERR, "Cannot open the file: %s\n", path);
+		return (False);
+	} else {
+		xml_update_config(root, 0, output);
+		(void) fclose(output);
+
+		/*
+		 * Make sure only root can access the file since we're
+		 * optionally keeping CHAP secrets located here.
+		 */
+		(void) chmod(path, 0600);
+
+		return (True);
+	}
+}
+
+/*
+ * 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,
+			*value;
+	char		**ap;
+	xmlElementType	node_type;
+	tgt_node_t	*n,
+			*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);
+		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);
+			return (False);
+		}
+	} else if ((value != NULL) && (node_type == XML_TEXT_NODE)) {
+		if (node_value(n, value, True) == False) {
+			node_free(n);
+			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);
+			return (False);
+		}
+		if (node_value(n, (xmlChar *)value, False) == False) {
+			node_free(n);
+			return (False);
+		}
+	} else if (node_type != XML_DTD_NODE) {
+		node_free(n);
+		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,
+			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,
+			*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;
+
+	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, "0x%x",
+			    *(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);
+
+	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;
+	}
+
+	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,
+			*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,
+			*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(),
+			*c;
+
+	if (d == NULL)
+		return (NULL);
+	if (node_name(d, (xmlChar *)n->x_name) == False)
+		return (NULL);
+	if (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));
+	return (d);
+}
+
+void
+tgt_buf_add(char **b, char *element, const char *cdata)
+{
+	tgt_buf_add_tag(b, element, Tag_Start);
+	if (cdata != NULL)
+		tgt_buf_add_tag(b, cdata, 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,
+			*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,
+		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,
+		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,
+		*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);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libiscsitgt/i386/Makefile	Wed Nov 15 19:25:44 2006 -0800
@@ -0,0 +1,30 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libiscsitgt/sparc/Makefile	Wed Nov 15 19:25:44 2006 -0800
@@ -0,0 +1,30 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libiscsitgt/sparcv9/Makefile	Wed Nov 15 19:25:44 2006 -0800
@@ -0,0 +1,31 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
--- a/usr/src/lib/libzfs/Makefile.com	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/lib/libzfs/Makefile.com	Wed Nov 15 19:25:44 2006 -0800
@@ -49,7 +49,7 @@
 
 C99MODE=	-xc99=%all
 C99LMODE=	-Xc99=%all
-LDLIBS +=	-lc -lm -ldevinfo -ldevid -lgen -lnvpair -luutil
+LDLIBS +=	-lc -lm -ldevinfo -ldevid -lgen -lnvpair -luutil -liscsitgt
 CPPFLAGS +=	$(INCS) -D_REENTRANT
 
 SRCS=	$(OBJS_COMMON:%.o=$(SRCDIR)/%.c)	\
--- a/usr/src/lib/libzfs/common/libzfs.h	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/lib/libzfs/common/libzfs.h	Wed Nov 15 19:25:44 2006 -0800
@@ -18,6 +18,7 @@
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
@@ -80,8 +81,8 @@
 	EZFS_ZONED,		/* used improperly in local zone */
 	EZFS_MOUNTFAILED,	/* failed to mount dataset */
 	EZFS_UMOUNTFAILED,	/* failed to unmount dataset */
-	EZFS_UNSHAREFAILED,	/* unshare(1M) failed */
-	EZFS_SHAREFAILED,	/* share(1M) failed */
+	EZFS_UNSHARENFSFAILED,	/* unshare(1M) failed */
+	EZFS_SHARENFSFAILED,	/* share(1M) failed */
 	EZFS_DEVLINKS,		/* failed to create zvol links */
 	EZFS_PERM,		/* permission denied */
 	EZFS_NOSPC,		/* out of space */
@@ -91,6 +92,8 @@
 	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_UNKNOWN		/* unknown error */
 };
 
@@ -312,6 +315,8 @@
 extern const char *zfs_type_to_name(zfs_type_t);
 extern void zfs_refresh_properties(zfs_handle_t *);
 extern int zfs_name_valid(const char *, zfs_type_t);
+extern int zfs_disable(zfs_handle_t *);
+extern int zfs_enable(zfs_handle_t *);
 
 /*
  * Mount support functions.
@@ -324,10 +329,20 @@
 /*
  * Share support functions.
  */
-extern boolean_t zfs_is_shared(zfs_handle_t *, char **);
+extern boolean_t zfs_is_shared(zfs_handle_t *);
 extern int zfs_share(zfs_handle_t *);
-extern int zfs_unshare(zfs_handle_t *, const char *);
-extern int zfs_unshareall(zfs_handle_t *);
+extern int zfs_unshare(zfs_handle_t *);
+
+/*
+ * Protocol-specifc share support functions.
+ */
+extern boolean_t zfs_is_shared_nfs(zfs_handle_t *, char **);
+extern int zfs_share_nfs(zfs_handle_t *);
+extern int zfs_unshare_nfs(zfs_handle_t *, const char *);
+extern int zfs_unshareall_nfs(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 *);
 
 /*
  * When dealing with nvlists, verify() is extremely useful
@@ -362,16 +377,17 @@
 extern int zpool_read_label(int, nvlist_t **);
 
 /*
- * Create and remove zvol /dev links
+ * Create and remove zvol /dev links.
  */
 extern int zpool_create_zvol_links(zpool_handle_t *);
 extern int zpool_remove_zvol_links(zpool_handle_t *);
 
 /*
- * Mount and unmount datasets within a pool
+ * Enable and disable datasets within a pool by mounting/unmounting and
+ * sharing/unsharing them.
  */
-extern int zpool_mount_datasets(zpool_handle_t *, const char *, int);
-extern int zpool_unmount_datasets(zpool_handle_t *, boolean_t);
+extern int zpool_enable_datasets(zpool_handle_t *, const char *, int);
+extern int zpool_disable_datasets(zpool_handle_t *, boolean_t);
 
 #ifdef	__cplusplus
 }
--- a/usr/src/lib/libzfs/common/libzfs_changelist.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/lib/libzfs/common/libzfs_changelist.c	Wed Nov 15 19:25:44 2006 -0800
@@ -18,6 +18,7 @@
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
@@ -97,21 +98,34 @@
 	for (cn = uu_list_first(clp->cl_list); cn != NULL;
 	    cn = uu_list_next(clp->cl_list, cn)) {
 		/*
-		 * if we are in a global zone, but this dataset is exported to
-		 * a local zone, do nothing.
+		 * If we are in the global zone, but this dataset is exported
+		 * to a local zone, do nothing.
 		 */
-		if ((getzoneid() == GLOBAL_ZONEID) && cn->cn_zoned)
+		if (getzoneid() == GLOBAL_ZONEID && cn->cn_zoned)
 			continue;
 
-		/*
-		 * If we have a volume and this was a rename, remove the
-		 * /dev/zvol links
-		 */
-		if (ZFS_IS_VOLUME(cn->cn_handle) &&
-		    clp->cl_realprop == ZFS_PROP_NAME) {
-			if (zvol_remove_link(cn->cn_handle->zfs_hdl,
-			    cn->cn_handle->zfs_name) != 0)
-				ret = -1;
+		if (ZFS_IS_VOLUME(cn->cn_handle)) {
+			switch (clp->cl_realprop) {
+			case ZFS_PROP_NAME:
+				/*
+				 * If this was a rename, unshare the zvol, and
+				 * remove the /dev/zvol links.
+				 */
+				(void) zfs_unshare_iscsi(cn->cn_handle);
+
+				if (zvol_remove_link(cn->cn_handle->zfs_hdl,
+				    cn->cn_handle->zfs_name) != 0)
+					ret = -1;
+				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_unmount(cn->cn_handle, NULL, clp->cl_flags) != 0)
 			ret = -1;
 	}
@@ -120,7 +134,7 @@
 }
 
 /*
- * If the proeprty is 'mountpoint' or 'sharenfs', go through and remount and/or
+ * If the property is 'mountpoint' or 'sharenfs', go through and remount and/or
  * reshare the filesystems as necessary.  In changelist_gather() we recorded
  * whether the filesystem was previously shared or mounted.  The action we take
  * depends on the previous state, and whether the value was previously 'legacy'.
@@ -132,6 +146,7 @@
 changelist_postfix(prop_changelist_t *clp)
 {
 	prop_changenode_t *cn;
+	char shareopts[ZFS_MAXPROPLEN];
 	int ret = 0;
 
 	/*
@@ -154,23 +169,36 @@
 	for (cn = uu_list_last(clp->cl_list); cn != NULL;
 	    cn = uu_list_prev(clp->cl_list, cn)) {
 		/*
-		 * if we are in a global zone, but this dataset is exported to
-		 * a local zone, do nothing.
+		 * If we are in the global zone, but this dataset is exported
+		 * to a local zone, do nothing.
 		 */
-		if ((getzoneid() == GLOBAL_ZONEID) && cn->cn_zoned)
+		if (getzoneid() == GLOBAL_ZONEID && cn->cn_zoned)
 			continue;
 
 		zfs_refresh_properties(cn->cn_handle);
 
-		/*
-		 * If this is a volume and we're doing a rename, recreate the
-		 * /dev/zvol links.
-		 */
-		if (ZFS_IS_VOLUME(cn->cn_handle) &&
-		    clp->cl_realprop == ZFS_PROP_NAME) {
-			if (zvol_create_link(cn->cn_handle->zfs_hdl,
-			    cn->cn_handle->zfs_name) != 0)
+		if (ZFS_IS_VOLUME(cn->cn_handle)) {
+			/*
+			 * If we're doing a rename, recreate the /dev/zvol
+			 * links.
+			 */
+			if (clp->cl_realprop == ZFS_PROP_NAME &&
+			    zvol_create_link(cn->cn_handle->zfs_hdl,
+			    cn->cn_handle->zfs_name) != 0) {
 				ret = -1;
+			} else 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) {
+					ret = zfs_unshare_iscsi(cn->cn_handle);
+				} else {
+					ret = zfs_share_iscsi(cn->cn_handle);
+				}
+			}
+
 			continue;
 		}
 
@@ -183,15 +211,15 @@
 		 * We always re-share even if the filesystem is currently
 		 * shared, so that we can adopt any new options.
 		 */
-		if ((cn->cn_shared ||
-		    (clp->cl_prop == ZFS_PROP_SHARENFS && clp->cl_waslegacy))) {
-			char shareopts[ZFS_MAXPROPLEN];
+		if (cn->cn_shared ||
+		    (clp->cl_prop == ZFS_PROP_SHARENFS && clp->cl_waslegacy)) {
 			if (zfs_prop_get(cn->cn_handle, ZFS_PROP_SHARENFS,
 			    shareopts, sizeof (shareopts), NULL, NULL, 0,
-			    B_FALSE) == 0 && strcmp(shareopts, "off") == 0)
-				ret = zfs_unshare(cn->cn_handle, NULL);
-			else
-				ret = zfs_share(cn->cn_handle);
+			    B_FALSE) == 0 && strcmp(shareopts, "off") == 0) {
+				ret = zfs_unshare_nfs(cn->cn_handle, NULL);
+			} else {
+				ret = zfs_share_nfs(cn->cn_handle);
+			}
 		}
 	}
 
@@ -221,11 +249,11 @@
 }
 
 /*
- * If we rename a filesystem, and child filesystem handles are no longer valid,
- * since we identify datasets by their name in the ZFS namespace.  So, we have
- * to go through and fix up all the names appropriately.  We could do this
- * automatically if libzfs kept track of all open handles, but this is a lot
- * less work.
+ * If we rename a filesystem, child filesystem handles are no longer valid
+ * since we identify each dataset by its name in the ZFS namespace.  As a
+ * result, we have to go through and fix up all the names appropriately.  We
+ * could do this automatically if libzfs kept track of all open handles, but
+ * this is a lot less work.
  */
 void
 changelist_rename(prop_changelist_t *clp, const char *src, const char *dst)
@@ -255,8 +283,8 @@
 }
 
 /*
- * Given a gathered changelist for the "sharenfs" property,
- * unshare all the nodes in the list.
+ * Given a gathered changelist for the 'sharenfs' property, unshare all the
+ * datasets in the list.
  */
 int
 changelist_unshare(prop_changelist_t *clp)
@@ -269,8 +297,7 @@
 
 	for (cn = uu_list_first(clp->cl_list); cn != NULL;
 	    cn = uu_list_next(clp->cl_list, cn)) {
-
-		if (zfs_unshare(cn->cn_handle, NULL) != 0)
+		if (zfs_unshare_nfs(cn->cn_handle, NULL) != 0)
 			ret = -1;
 	}
 
@@ -278,9 +305,9 @@
 }
 
 /*
- * Check if there is any child exported to a local zone in a
- * given changelist. This information has already been recorded
- * while gathering the changelist via changelist_gather().
+ * Check if there is any child exported to a local zone in a given changelist.
+ * This information has already been recorded while gathering the changelist
+ * via changelist_gather().
  */
 int
 changelist_haszonedchild(prop_changelist_t *clp)
@@ -349,13 +376,13 @@
 	zfs_source_t sourcetype;
 
 	/*
-	 * We only want to unmount/unshare those filesystems which may
-	 * inherit from the target filesystem.  If we find any filesystem
-	 * with a locally set mountpoint, we ignore any children since changing
-	 * the property will not affect them.  If this is a rename, we iterate
-	 * over all children regardless, since we need them unmounted in order
-	 * to do the rename.  Also, if this is a volume and we're doing a
-	 * rename, then always add it to the changelist.
+	 * We only want to unmount/unshare those filesystems that may inherit
+	 * from the target filesystem.  If we find any filesystem with a
+	 * locally set mountpoint, we ignore any children since changing the
+	 * property will not affect them.  If this is a rename, we iterate
+	 * over all children regardless, since we need them unmounted in
+	 * order to do the rename.  Also, if this is a volume and we're doing
+	 * a rename, then always add it to the changelist.
 	 */
 
 	if (!(ZFS_IS_VOLUME(zhp) && clp->cl_realprop == ZFS_PROP_NAME) &&
@@ -376,11 +403,11 @@
 
 		cn->cn_handle = zhp;
 		cn->cn_mounted = zfs_is_mounted(zhp, NULL);
-		cn->cn_shared = zfs_is_shared(zhp, NULL);
+		cn->cn_shared = zfs_is_shared(zhp);
 		cn->cn_zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);
 
-		/* indicate if any child is exported to a local zone */
-		if ((getzoneid() == GLOBAL_ZONEID) && cn->cn_zoned)
+		/* Indicate if any child is exported to a local zone. */
+		if (getzoneid() == GLOBAL_ZONEID && cn->cn_zoned)
 			clp->cl_haszonedchild = B_TRUE;
 
 		uu_list_node_init(cn, &cn->cn_listnode, clp->cl_pool);
@@ -442,12 +469,12 @@
 }
 
 /*
- * Given a ZFS handle and a property, construct a complete list of datasets that
- * need to be modified as part of this process.  For anything but the
+ * Given a ZFS handle and a property, construct a complete list of datasets
+ * that need to be modified as part of this process.  For anything but the
  * 'mountpoint' and 'sharenfs' properties, this just returns an empty list.
- * Otherwise, we iterate over all children and look for any datasets which
- * inherit this property.  For each such dataset, we add it to the list and mark
- * whether it was shared beforehand.
+ * Otherwise, we iterate over all children and look for any datasets that
+ * inherit the property.  For each such dataset, we add it to the list and
+ * mark whether it was shared beforehand.
  */
 prop_changelist_t *
 changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int flags)
@@ -499,8 +526,8 @@
 	 * changing the mountpoint and flag it so we can catch all children in
 	 * change_one().
 	 *
-	 * Flag cl_alldependents to catch all children plus the
-	 * dependents (clones) that are not in the hierarchy.
+	 * Flag cl_alldependents to catch all children plus the dependents
+	 * (clones) that are not in the hierarchy.
 	 */
 	if (prop == ZFS_PROP_NAME) {
 		clp->cl_prop = ZFS_PROP_MOUNTPOINT;
@@ -510,13 +537,16 @@
 		clp->cl_allchildren = B_TRUE;
 	} else if (prop == ZFS_PROP_CANMOUNT) {
 		clp->cl_prop = ZFS_PROP_MOUNTPOINT;
+	} else if (prop == ZFS_PROP_VOLSIZE) {
+		clp->cl_prop = ZFS_PROP_MOUNTPOINT;
 	} else {
 		clp->cl_prop = prop;
 	}
 	clp->cl_realprop = prop;
 
 	if (clp->cl_prop != ZFS_PROP_MOUNTPOINT &&
-	    clp->cl_prop != ZFS_PROP_SHARENFS)
+	    clp->cl_prop != ZFS_PROP_SHARENFS &&
+	    clp->cl_prop != ZFS_PROP_SHAREISCSI)
 		return (clp);
 
 	if (clp->cl_alldependents) {
@@ -552,7 +582,7 @@
 
 	cn->cn_handle = temp;
 	cn->cn_mounted = zfs_is_mounted(temp, NULL);
-	cn->cn_shared = zfs_is_shared(temp, NULL);
+	cn->cn_shared = zfs_is_shared(temp);
 	cn->cn_zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);
 
 	uu_list_node_init(cn, &cn->cn_listnode, clp->cl_pool);
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c	Wed Nov 15 19:25:44 2006 -0800
@@ -18,6 +18,7 @@
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
@@ -855,6 +856,19 @@
 			}
 			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_MOUNTPOINT:
 			if (strcmp(strval, ZFS_MOUNTPOINT_NONE) == 0 ||
 			    strcmp(strval, ZFS_MOUNTPOINT_LEGACY) == 0)
@@ -867,23 +881,22 @@
 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
 				goto error;
 			}
-			break;
-		}
-
-		/*
-		 * For the mountpoint and sharenfs properties, check if it can
-		 * be set in a global/non-global zone based on the zoned
-		 * property value:
-		 *
-		 *		global zone	    non-global zone
-		 * -----------------------------------------------------
-		 * zoned=on	mountpoint (no)	    mountpoint (yes)
-		 *		sharenfs (no)	    sharenfs (no)
-		 *
-		 * zoned=off	mountpoint (yes)	N/A
-		 *		sharenfs (yes)
-		 */
-		if (prop == ZFS_PROP_MOUNTPOINT || prop == ZFS_PROP_SHARENFS) {
+			/*FALLTHRU*/
+
+		case ZFS_PROP_SHARENFS:
+			/*
+			 * For the mountpoint and sharenfs properties, check if
+			 * it can be set in a global/non-global zone based on
+			 * the zoned property value:
+			 *
+			 *		global zone	    non-global zone
+			 * --------------------------------------------------
+			 * zoned=on	mountpoint (no)	    mountpoint (yes)
+			 *		sharenfs (no)	    sharenfs (no)
+			 *
+			 * zoned=off	mountpoint (yes)	N/A
+			 *		sharenfs (yes)
+			 */
 			if (zoned) {
 				if (getzoneid() == GLOBAL_ZONEID) {
 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@@ -912,6 +925,8 @@
 				(void) zfs_error(hdl, EZFS_ZONED, errbuf);
 				goto error;
 			}
+
+			break;
 		}
 
 		/*
@@ -958,6 +973,7 @@
 					    errbuf);
 					goto error;
 				}
+				break;
 			}
 		}
 	}
@@ -1591,6 +1607,8 @@
 		break;
 
 	case ZFS_PROP_SHARENFS:
+	case ZFS_PROP_SHAREISCSI:
+	case ZFS_PROP_ISCSIOPTIONS:
 		(void) strlcpy(propbuf, getprop_string(zhp, prop, &source),
 		    proplen);
 		break;
@@ -2090,11 +2108,16 @@
 zfs_destroy(zfs_handle_t *zhp)
 {
 	zfs_cmd_t zc = { 0 };
-	int ret;
 
 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
 
 	if (ZFS_IS_VOLUME(zhp)) {
+		/*
+		 * Unconditionally unshare this zvol ignoring failure as it
+		 * indicates only that the volume wasn't shared initially.
+		 */
+		(void) zfs_unshare_iscsi(zhp);
+
 		if (zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name) != 0)
 			return (-1);
 
@@ -2103,8 +2126,7 @@
 		zc.zc_objset_type = DMU_OST_ZFS;
 	}
 
-	ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc);
-	if (ret != 0) {
+	if (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc) != 0) {
 		return (zfs_standard_error(zhp->zfs_hdl, errno,
 		    dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
 		    zhp->zfs_name));
--- a/usr/src/lib/libzfs/common/libzfs_impl.h	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/lib/libzfs/common/libzfs_impl.h	Wed Nov 15 19:25:44 2006 -0800
@@ -18,6 +18,7 @@
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
@@ -124,6 +125,7 @@
 
 int zvol_create_link(libzfs_handle_t *, const char *);
 int zvol_remove_link(libzfs_handle_t *, const char *);
+int zpool_iter_zvol(zpool_handle_t *, int (*)(const char *, void *), void *);
 
 void namespace_clear(libzfs_handle_t *);
 
--- a/usr/src/lib/libzfs/common/libzfs_mount.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/lib/libzfs/common/libzfs_mount.c	Wed Nov 15 19:25:44 2006 -0800
@@ -18,6 +18,7 @@
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
@@ -27,33 +28,42 @@
 
 /*
  * Routines to manage ZFS mounts.  We separate all the nasty routines that have
- * to deal with the OS.  The main entry points are:
+ * to deal with the OS.  The following functions are the main entry points --
+ * they are used by mount and unmount and when changing a filesystem's
+ * mountpoint.
  *
  * 	zfs_is_mounted()
  * 	zfs_mount()
  * 	zfs_unmount()
  * 	zfs_unmountall()
  *
- * These functions are used by mount and unmount, and when changing a
- * filesystem's mountpoint.  This file also contains the functions used to
- * manage sharing filesystems via NFS:
+ * This file also contains the functions used to manage sharing filesystems via
+ * NFS and iSCSI:
  *
  * 	zfs_is_shared()
  * 	zfs_share()
  * 	zfs_unshare()
- * 	zfs_unshareall()
+ *
+ * 	zfs_is_shared_nfs()
+ * 	zfs_share_nfs()
+ * 	zfs_unshare_nfs()
+ * 	zfs_unshareall_nfs()
+ * 	zfs_is_shared_iscsi()
+ * 	zfs_share_iscsi()
+ * 	zfs_unshare_iscsi()
  *
  * The following functions are available for pool consumers, and will
- * mount/unmount (and share/unshare) all datasets within pool:
+ * mount/unmount and share/unshare all datasets within pool:
  *
- * 	zpool_mount_datasets()
- * 	zpool_unmount_datasets()
+ * 	zpool_enable_datasets()
+ * 	zpool_disable_datasets()
  */
 
 #include <dirent.h>
 #include <errno.h>
 #include <libgen.h>
 #include <libintl.h>
+#include <libiscsitgt.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <strings.h>
@@ -288,7 +298,7 @@
 		/*
 		 * Unshare and unmount the filesystem
 		 */
-		if (zfs_unshare(zhp, mountpoint) != 0 ||
+		if (zfs_unshare_nfs(zhp, mountpoint) != 0 ||
 		    unmount_one(zhp->zfs_hdl, mountpoint, flags) != 0)
 			return (-1);
 	}
@@ -317,11 +327,38 @@
 	return (ret);
 }
 
+boolean_t
+zfs_is_shared(zfs_handle_t *zhp)
+{
+	if (ZFS_IS_VOLUME(zhp))
+		return (zfs_is_shared_iscsi(zhp));
+
+	return (zfs_is_shared_nfs(zhp, NULL));
+}
+
+int
+zfs_share(zfs_handle_t *zhp)
+{
+	if (ZFS_IS_VOLUME(zhp))
+		return (zfs_share_iscsi(zhp));
+
+	return (zfs_share_nfs(zhp));
+}
+
+int
+zfs_unshare(zfs_handle_t *zhp)
+{
+	if (ZFS_IS_VOLUME(zhp))
+		return (zfs_unshare_iscsi(zhp));
+
+	return (zfs_unshare_nfs(zhp, NULL));
+}
+
 /*
  * Check to see if the filesystem is currently shared.
  */
 boolean_t
-zfs_is_shared(zfs_handle_t *zhp, char **where)
+zfs_is_shared_nfs(zfs_handle_t *zhp, char **where)
 {
 	char *mountpoint;
 
@@ -345,7 +382,7 @@
  * on share(1M) to the dirty work for us.
  */
 int
-zfs_share(zfs_handle_t *zhp)
+zfs_share_nfs(zfs_handle_t *zhp)
 {
 	char mountpoint[ZFS_MAXPROPLEN];
 	char shareopts[ZFS_MAXPROPLEN];
@@ -356,7 +393,9 @@
 	if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL))
 		return (0);
 
-	/* return success if there are no share options */
+	/*
+	 * Return success if there are no share options.
+	 */
 	if (zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts, sizeof (shareopts),
 	    NULL, NULL, 0, B_FALSE) != 0 ||
 	    strcmp(shareopts, "off") == 0)
@@ -383,7 +422,7 @@
 		    mountpoint);
 
 	if ((fp = popen(buf, "r")) == NULL)
-		return (zfs_error(hdl, EZFS_SHAREFAILED,
+		return (zfs_error(hdl, EZFS_SHARENFSFAILED,
 		    dgettext(TEXT_DOMAIN, "cannot share '%s'"),
 		    zfs_get_name(zhp)));
 
@@ -401,7 +440,7 @@
 		if (colon != NULL)
 			zfs_error_aux(hdl, colon + 2);
 
-		(void) zfs_error(hdl, EZFS_SHAREFAILED,
+		(void) zfs_error(hdl, EZFS_SHARENFSFAILED,
 		    dgettext(TEXT_DOMAIN, "cannot share '%s'"),
 		    zfs_get_name(zhp));
 
@@ -428,7 +467,7 @@
 	    mountpoint);
 
 	if ((fp = popen(buf, "r")) == NULL)
-		return (zfs_error(hdl, EZFS_UNSHAREFAILED,
+		return (zfs_error(hdl, EZFS_UNSHARENFSFAILED,
 		    dgettext(TEXT_DOMAIN,
 		    "cannot unshare '%s'"), name));
 
@@ -448,7 +487,7 @@
 
 		verify(pclose(fp) != 0);
 
-		return (zfs_error(hdl, EZFS_UNSHAREFAILED,
+		return (zfs_error(hdl, EZFS_UNSHARENFSFAILED,
 		    dgettext(TEXT_DOMAIN,
 		    "cannot unshare '%s'"), name));
 	}
@@ -462,7 +501,7 @@
  * Unshare the given filesystem.
  */
 int
-zfs_unshare(zfs_handle_t *zhp, const char *mountpoint)
+zfs_unshare_nfs(zfs_handle_t *zhp, const char *mountpoint)
 {
 	struct mnttab search = { 0 }, entry;
 
@@ -485,10 +524,10 @@
 }
 
 /*
- * Same as zfs_unmountall(), but for unshares.
+ * Same as zfs_unmountall(), but for NFS unshares.
  */
 int
-zfs_unshareall(zfs_handle_t *zhp)
+zfs_unshareall_nfs(zfs_handle_t *zhp)
 {
 	prop_changelist_t *clp;
 	int ret;
@@ -536,14 +575,51 @@
 	}
 }
 
-/*
- * Mount and share all datasets within the given pool.  This assumes that no
- * datasets within the pool are currently mounted.  Because users can create
- * complicated nested hierarchies of mountpoints, we first gather all the
- * datasets and mountpoints within the pool, and sort them by mountpoint.  Once
- * we have the list of all filesystems, we iterate over them in order and mount
- * and/or share each one.
- */
+boolean_t
+zfs_is_shared_iscsi(zfs_handle_t *zhp)
+{
+	return (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(dataset) != 0)
+		return (zfs_error(hdl, EZFS_SHAREISCSIFAILED,
+		    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;
+
+	/*
+	 * If this fails with ENODEV it indicates that zvol wasn't shared so
+	 * we should return success in that case.
+	 */
+	if (iscsitgt_zfs_unshare(dataset) != 0 && errno != ENODEV)
+		return (zfs_error(hdl, EZFS_UNSHAREISCSIFAILED,
+		    dgettext(TEXT_DOMAIN, "cannot unshare '%s'"), dataset));
+
+	return (0);
+}
+
 typedef struct mount_cbdata {
 	zfs_handle_t	**cb_datasets;
 	int 		cb_used;
@@ -555,7 +631,7 @@
 {
 	mount_cbdata_t *cbp = data;
 
-	if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
+	if (!(zfs_get_type(zhp) & (ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME))) {
 		zfs_close(zhp);
 		return (0);
 	}
@@ -573,27 +649,48 @@
 	}
 
 	cbp->cb_datasets[cbp->cb_used++] = zhp;
-	return (0);
+
+	return (zfs_iter_children(zhp, mount_cb, cbp));
 }
 
 static int
-dataset_compare(const void *a, const void *b)
+dataset_cmp(const void *a, const void *b)
 {
 	zfs_handle_t **za = (zfs_handle_t **)a;
 	zfs_handle_t **zb = (zfs_handle_t **)b;
 	char mounta[MAXPATHLEN];
 	char mountb[MAXPATHLEN];
+	boolean_t gota, gotb;
 
-	verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta,
-	    sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0);
-	verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb,
-	    sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0);
+	if ((gota = (zfs_get_type(*za) == ZFS_TYPE_FILESYSTEM)) != 0)
+		verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta,
+		    sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0);
+	if ((gotb = (zfs_get_type(*zb) == ZFS_TYPE_FILESYSTEM)) != 0)
+		verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb,
+		    sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0);
 
-	return (strcmp(mounta, mountb));
+	if (gota && gotb)
+		return (strcmp(mounta, mountb));
+
+	if (gota)
+		return (-1);
+	if (gotb)
+		return (1);
+
+	return (strcmp(zfs_get_name(a), zfs_get_name(b)));
 }
 
+/*
+ * Mount and share all datasets within the given pool.  This assumes that no
+ * datasets within the pool are currently mounted.  Because users can create
+ * complicated nested hierarchies of mountpoints, we first gather all the
+ * datasets and mountpoints within the pool, and sort them by mountpoint.  Once
+ * we have the list of all filesystems, we iterate over them in order and mount
+ * and/or share each one.
+ */
+#pragma weak zpool_mount_datasets = zpool_enable_datasets
 int
-zpool_mount_datasets(zpool_handle_t *zhp, const char *mntopts, int flags)
+zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags)
 {
 	mount_cbdata_t cb = { 0 };
 	libzfs_handle_t *hdl = zhp->zpool_hdl;
@@ -619,7 +716,7 @@
 	/*
 	 * Sort the datasets by mountpoint.
 	 */
-	qsort(cb.cb_datasets, cb.cb_used, sizeof (void *), dataset_compare);
+	qsort(cb.cb_datasets, cb.cb_used, sizeof (void *), dataset_cmp);
 
 	/*
 	 * And mount all the datasets.
@@ -639,13 +736,27 @@
 	return (ret);
 }
 
-/*
- * Unshare and unmount all datasets within the given pool.  We don't want to
- * rely on traversing the DSL to discover the filesystems within the pool,
- * because this may be expensive (if not all of them are mounted), and can fail
- * arbitrarily (on I/O error, for example).  Instead, we walk /etc/mnttab and
- * gather all the filesystems that are currently mounted.
- */
+
+static int
+zvol_cb(const char *dataset, void *data)
+{
+	libzfs_handle_t *hdl = data;
+	zfs_handle_t *zhp;
+
+	/*
+	 * Ignore snapshots and ignore failures from non-existant datasets.
+	 */
+	if (strchr(dataset, '@') != NULL ||
+	    (zhp = zfs_open(hdl, dataset, ZFS_TYPE_VOLUME)) == NULL)
+		return (0);
+
+	(void) zfs_unshare_iscsi(zhp);
+
+	zfs_close(zhp);
+
+	return (0);
+}
+
 static int
 mountpoint_compare(const void *a, const void *b)
 {
@@ -655,8 +766,16 @@
 	return (strcmp(mountb, mounta));
 }
 
+/*
+ * Unshare and unmount all datasets within the given pool.  We don't want to
+ * rely on traversing the DSL to discover the filesystems within the pool,
+ * because this may be expensive (if not all of them are mounted), and can fail
+ * arbitrarily (on I/O error, for example).  Instead, we walk /etc/mnttab and
+ * gather all the filesystems that are currently mounted.
+ */
+#pragma weak zpool_unmount_datasets = zpool_disable_datasets
 int
-zpool_unmount_datasets(zpool_handle_t *zhp, boolean_t force)
+zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force)
 {
 	int used, alloc;
 	struct mnttab entry;
@@ -668,6 +787,12 @@
 	int ret = -1;
 	int flags = (force ? MS_FORCE : 0);
 
+	/*
+	 * First unshare all zvols.
+	 */
+	if (zpool_iter_zvol(zhp, zvol_cb, hdl) != 0)
+		return (-1);
+
 	namelen = strlen(zhp->zpool_name);
 
 	rewind(hdl->libzfs_mnttab);
--- a/usr/src/lib/libzfs/common/libzfs_pool.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/lib/libzfs/common/libzfs_pool.c	Wed Nov 15 19:25:44 2006 -0800
@@ -26,15 +26,17 @@
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
+#include <alloca.h>
 #include <assert.h>
 #include <ctype.h>
 #include <errno.h>
 #include <devid.h>
+#include <dirent.h>
 #include <fcntl.h>
 #include <libintl.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
+#include <strings.h>
 #include <unistd.h>
 #include <sys/zfs_ioctl.h>
 #include <sys/zio.h>
@@ -1231,26 +1233,126 @@
 	return (zpool_standard_error(hdl, errno, msg));
 }
 
-static int
-do_zvol(zfs_handle_t *zhp, void *data)
+/*
+ * Iterate over all zvols in a given pool by walking the /dev/zvol/dsk/<pool>
+ * hierarchy.
+ */
+int
+zpool_iter_zvol(zpool_handle_t *zhp, int (*cb)(const char *, void *),
+    void *data)
 {
-	int linktype = (int)(uintptr_t)data;
-	int ret;
+	libzfs_handle_t *hdl = zhp->zpool_hdl;
+	char (*paths)[MAXPATHLEN];
+	size_t size = 4;
+	int curr, fd, base, ret = 0;
+	DIR *dirp;
+	struct dirent *dp;
+	struct stat st;
+
+	if ((base = open("/dev/zvol/dsk", O_RDONLY)) < 0)
+		return (errno == ENOENT ? 0 : -1);
+
+	if (fstatat(base, zhp->zpool_name, &st, 0) != 0) {
+		int err = errno;
+		(void) close(base);
+		return (err == ENOENT ? 0 : -1);
+	}
 
 	/*
-	 * We check for volblocksize intead of ZFS_TYPE_VOLUME so that we
-	 * correctly handle snapshots of volumes.
+	 * Oddly this wasn't a directory -- ignore that failure since we
+	 * know there are no links lower in the (non-existant) hierarchy.
 	 */
-	if (ZFS_IS_VOLUME(zhp)) {
-		if (linktype)
-			ret = zvol_create_link(zhp->zfs_hdl, zhp->zfs_name);
-		else
-			ret = zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name);
+	if (!S_ISDIR(st.st_mode)) {
+		(void) close(base);
+		return (0);
+	}
+
+	if ((paths = zfs_alloc(hdl, size * sizeof (paths[0]))) == NULL) {
+		(void) close(base);
+		return (-1);
 	}
 
-	ret = zfs_iter_children(zhp, do_zvol, data);
+	(void) strlcpy(paths[0], zhp->zpool_name, sizeof (paths[0]));
+	curr = 0;
+
+	while (curr >= 0) {
+		if (fstatat(base, paths[curr], &st, AT_SYMLINK_NOFOLLOW) != 0)
+			goto err;
+
+		if (S_ISDIR(st.st_mode)) {
+			if ((fd = openat(base, paths[curr], O_RDONLY)) < 0)
+				goto err;
+
+			if ((dirp = fdopendir(fd)) == NULL) {
+				(void) close(fd);
+				goto err;
+			}
+
+			while ((dp = readdir(dirp)) != NULL) {
+				if (dp->d_name[0] == '.')
+					continue;
+
+				if (curr + 1 == size) {
+					paths = zfs_realloc(hdl, paths,
+					    size * sizeof (paths[0]),
+					    size * 2 * sizeof (paths[0]));
+					if (paths == NULL) {
+						(void) closedir(dirp);
+						(void) close(fd);
+						goto err;
+					}
+
+					size *= 2;
+				}
+
+				(void) strlcpy(paths[curr + 1], paths[curr],
+				    sizeof (paths[curr + 1]));
+				(void) strlcat(paths[curr], "/",
+				    sizeof (paths[curr]));
+				(void) strlcat(paths[curr], dp->d_name,
+				    sizeof (paths[curr]));
+				curr++;
+			}
+
+			(void) closedir(dirp);
+
+		} else {
+			if ((ret = cb(paths[curr], data)) != 0)
+				break;
+		}
+
+		curr--;
+	}
+
+	free(paths);
+	(void) close(base);
+
+	return (ret);
+
+err:
+	free(paths);
+	(void) close(base);
+	return (-1);
+}
+
+typedef struct zvol_cb {
+	zpool_handle_t *zcb_pool;
+	boolean_t zcb_create;
+} zvol_cb_t;
+
+/*ARGSUSED*/
+static int
+do_zvol_create(zfs_handle_t *zhp, void *data)
+{
+	int ret;
+
+	if (ZFS_IS_VOLUME(zhp))
+		(void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name);
+
+	ret = zfs_iter_children(zhp, do_zvol_create, NULL);
 
 	zfs_close(zhp);
+
 	return (ret);
 }
 
@@ -1270,32 +1372,29 @@
 	    zhp->zpool_name)) == NULL)
 		return (0);
 
-	ret = zfs_iter_children(zfp, do_zvol, (void *)B_TRUE);
+	ret = zfs_iter_children(zfp, do_zvol_create, NULL);
 
 	zfs_close(zfp);
 	return (ret);
 }
 
+static int
+do_zvol_remove(const char *dataset, void *data)
+{
+	zpool_handle_t *zhp = data;
+
+	return (zvol_remove_link(zhp->zpool_hdl, dataset));
+}
+
 /*
- * Iterate over all zvols in the poool and remove any minor nodes.
+ * Iterate over all zvols in the pool and remove any minor nodes.  We iterate
+ * by examining the /dev links so that a corrupted pool doesn't impede this
+ * operation.
  */
 int
 zpool_remove_zvol_links(zpool_handle_t *zhp)
 {
-	zfs_handle_t *zfp;
-	int ret;
-
-	/*
-	 * If the pool is unavailable, just return success.
-	 */
-	if ((zfp = make_dataset_handle(zhp->zpool_hdl,
-	    zhp->zpool_name)) == NULL)
-		return (0);
-
-	ret = zfs_iter_children(zfp, do_zvol, (void *)B_FALSE);
-
-	zfs_close(zfp);
-	return (ret);
+	return (zpool_iter_zvol(zhp, do_zvol_remove, zhp));
 }
 
 /*
--- a/usr/src/lib/libzfs/common/libzfs_util.c	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/lib/libzfs/common/libzfs_util.c	Wed Nov 15 19:25:44 2006 -0800
@@ -127,9 +127,9 @@
 		return (dgettext(TEXT_DOMAIN, "mount failed"));
 	case EZFS_UMOUNTFAILED:
 		return (dgettext(TEXT_DOMAIN, "umount failed"));
-	case EZFS_UNSHAREFAILED:
+	case EZFS_UNSHARENFSFAILED:
 		return (dgettext(TEXT_DOMAIN, "unshare(1M) failed"));
-	case EZFS_SHAREFAILED:
+	case EZFS_SHARENFSFAILED:
 		return (dgettext(TEXT_DOMAIN, "share(1M) failed"));
 	case EZFS_DEVLINKS:
 		return (dgettext(TEXT_DOMAIN, "failed to create /dev links"));
@@ -150,6 +150,12 @@
 		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_UNKNOWN:
 		return (dgettext(TEXT_DOMAIN, "unknown error"));
 	default:
--- a/usr/src/lib/libzfs/common/mapfile-vers	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/lib/libzfs/common/mapfile-vers	Wed Nov 15 19:25:44 2006 -0800
@@ -47,6 +47,8 @@
 	zfs_get_type;
 	zfs_is_mounted;
 	zfs_is_shared;
+	zfs_is_shared_iscsi;
+	zfs_is_shared_nfs;
 	zfs_iter_children;
 	zfs_iter_dependents;
 	zfs_iter_filesystems;
@@ -82,18 +84,24 @@
 	zfs_rollback;
 	zfs_send;
 	zfs_share;
+	zfs_share_nfs;
+	zfs_share_iscsi;
 	zfs_snapshot;
 	zfs_type_to_name;
 	zfs_unmount;
 	zfs_unmountall;
 	zfs_unshare;
-	zfs_unshareall;
+	zfs_unshare_iscsi;
+	zfs_unshare_nfs;
+	zfs_unshareall_nfs;
 	zpool_add;
 	zpool_clear;
 	zpool_close;
 	zpool_create;
 	zpool_create_zvol_links;
 	zpool_destroy;
+	zpool_disable_datasets;
+	zpool_enable_datasets;
 	zpool_export;
 	zpool_find_import;
 	zpool_find_vdev;
--- a/usr/src/pkgdefs/SUNWiscsitgtr/prototype_com	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/pkgdefs/SUNWiscsitgtr/prototype_com	Wed Nov 15 19:25:44 2006 -0800
@@ -50,3 +50,5 @@
 f manifest var/svc/manifest/system/iscsi_target.xml 0444 root sys
 d none etc 755 root sys
 d none etc/iscsi 0755 root sys
+d none lib 755 root bin
+f none lib/libiscsitgt.so.1 755 root bin
--- a/usr/src/pkgdefs/SUNWiscsitgtr/prototype_i386	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/pkgdefs/SUNWiscsitgtr/prototype_i386	Wed Nov 15 19:25:44 2006 -0800
@@ -46,3 +46,5 @@
 #
 # SUNWiscsitgtr
 #
+d none lib/amd64 755 root bin
+f none lib/amd64/libiscsitgt.so.1 755 root bin
--- a/usr/src/pkgdefs/SUNWiscsitgtr/prototype_sparc	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/pkgdefs/SUNWiscsitgtr/prototype_sparc	Wed Nov 15 19:25:44 2006 -0800
@@ -45,4 +45,5 @@
 #
 # SUNWiscsitgtr
 #
-
+d none lib/sparcv9 755 root bin
+f none lib/sparcv9/libiscsitgt.so.1 755 root bin
--- a/usr/src/pkgdefs/SUNWiscsitgtu/prototype_com	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/pkgdefs/SUNWiscsitgtu/prototype_com	Wed Nov 15 19:25:44 2006 -0800
@@ -42,7 +42,13 @@
 #
 # SUNWiscsitgtu
 #
+d none lib 0755 root bin
+d none lib/svc 0755 root bin
+d none lib/svc/method 0755 root bin
+f none lib/svc/method/svc-iscsitgt 0555 root bin
 d none usr 0755 root sys
+d none usr/lib 755 root bin
+s none usr/lib/libiscsitgt.so.1=../../lib/libiscsitgt.so.1
 d none usr/sbin 0755 root bin
 f none usr/sbin/iscsitadm 0555 root bin
 l none usr/sbin/iscsitgtd=../../usr/lib/isaexec
--- a/usr/src/pkgdefs/SUNWiscsitgtu/prototype_i386	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/pkgdefs/SUNWiscsitgtu/prototype_i386	Wed Nov 15 19:25:44 2006 -0800
@@ -50,3 +50,5 @@
 f none usr/sbin/amd64/iscsitgtd 555 root bin
 d none usr/sbin/i86 755 root bin
 f none usr/sbin/i86/iscsitgtd 555 root bin
+d none usr/lib/amd64 755 root bin
+s none usr/lib/amd64/libiscsitgt.so.1=../../../lib/amd64/libiscsitgt.so.1
--- a/usr/src/pkgdefs/SUNWiscsitgtu/prototype_sparc	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/pkgdefs/SUNWiscsitgtu/prototype_sparc	Wed Nov 15 19:25:44 2006 -0800
@@ -47,3 +47,5 @@
 #
 d none usr/sbin/sparcv9 755 root bin
 f none usr/sbin/sparcv9/iscsitgtd 555 root bin
+d none usr/lib/sparcv9 755 root bin
+s none usr/lib/sparcv9/libiscsitgt.so.1=../../../lib/sparcv9/libiscsitgt.so.1
--- a/usr/src/pkgdefs/etc/exception_list_i386	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/pkgdefs/etc/exception_list_i386	Wed Nov 15 19:25:44 2006 -0800
@@ -801,3 +801,12 @@
 usr/include/sys/iscsi_protocol.h	i386
 usr/include/sys/iscsi_authclient.h	i386
 usr/include/sys/iscsi_authclientglue.h	i386
+usr/include/libiscsitgt.h		i386
+usr/include/iscsitgt_impl.h		i386
+usr/lib/libiscsitgt.so			i386
+usr/lib/amd64/libiscsitgt.so		i386
+lib/libiscsitgt.so			i386
+lib/llib-liscsitgt			i386
+lib/llib-liscsitgt.ln			i386
+lib/amd64/libiscsitgt.so		i386
+lib/amd64/llib-liscsitgt.ln		i386
--- a/usr/src/pkgdefs/etc/exception_list_sparc	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/pkgdefs/etc/exception_list_sparc	Wed Nov 15 19:25:44 2006 -0800
@@ -868,3 +868,12 @@
 usr/include/sys/iscsi_protocol.h	sparc
 usr/include/sys/iscsi_authclient.h	sparc
 usr/include/sys/iscsi_authclientglue.h	sparc
+usr/include/libiscsitgt.h		sparc
+usr/include/iscsitgt_impl.h		sparc
+usr/lib/libiscsitgt.so			sparc
+usr/lib/sparcv9/libiscsitgt.so		sparc
+lib/libiscsitgt.so			sparc
+lib/llib-liscsitgt			sparc
+lib/llib-liscsitgt.ln			sparc
+lib/sparcv9/libiscsitgt.so		sparc
+lib/sparcv9/llib-liscsitgt.ln		sparc
--- a/usr/src/uts/common/sys/fs/zfs.h	Wed Nov 15 19:19:07 2006 -0800
+++ b/usr/src/uts/common/sys/fs/zfs.h	Wed Nov 15 19:25:44 2006 -0800
@@ -73,6 +73,7 @@
 	ZFS_PROP_RECORDSIZE,
 	ZFS_PROP_MOUNTPOINT,
 	ZFS_PROP_SHARENFS,
+	ZFS_PROP_SHAREISCSI,
 	ZFS_PROP_CHECKSUM,
 	ZFS_PROP_COMPRESSION,
 	ZFS_PROP_ATIME,
@@ -91,6 +92,7 @@
 	 */
 	ZFS_PROP_CREATETXG,
 	ZFS_PROP_NAME,
+	ZFS_PROP_ISCSIOPTIONS,
 	ZFS_NPROP_ALL
 } zfs_prop_t;