1120 Use real file descriptors for smbfs named pipes.
authorGordon Ross <gwr@nexenta.com>
Thu, 30 Jun 2011 17:58:05 -0400
changeset 13394 96340372b72d
parent 13393 a055831123f1
child 13395 29f0883d3bc0
1120 Use real file descriptors for smbfs named pipes. Reviewed by: Eric Schrock <[email protected]> Reviewed by: Albert Lee <[email protected]> Approved by: Garrett D'Amore <[email protected]>
exception_lists/copyright
exception_lists/packaging
usr/src/cmd/fs.d/smbclnt/Makefile
usr/src/cmd/fs.d/smbclnt/smbutil/print.c
usr/src/cmd/fs.d/smbclnt/test/Makefile
usr/src/cmd/fs.d/smbclnt/test/testnp.c
usr/src/cmd/mdb/common/modules/nsmb/nsmb.c
usr/src/cmd/mdb/common/modules/smbfs/smbfs.c
usr/src/cmd/mdb/intel/amd64/nsmb/Makefile
usr/src/cmd/mdb/intel/amd64/smbfs/Makefile
usr/src/cmd/mdb/intel/ia32/nsmb/Makefile
usr/src/cmd/mdb/intel/ia32/smbfs/Makefile
usr/src/cmd/mdb/sparc/v9/nsmb/Makefile
usr/src/cmd/mdb/sparc/v9/smbfs/Makefile
usr/src/lib/libsmbfs/Makefile
usr/src/lib/libsmbfs/netsmb/smb_keychain.h
usr/src/lib/libsmbfs/netsmb/smb_lib.h
usr/src/lib/libsmbfs/netsmb/smbfs_api.h
usr/src/lib/libsmbfs/smb/ctx.c
usr/src/lib/libsmbfs/smb/file.c
usr/src/lib/libsmbfs/smb/keychain.c
usr/src/lib/libsmbfs/smb/mapfile-vers
usr/src/lib/libsmbfs/smb/print.c
usr/src/lib/libsmbfs/smb/private.h
usr/src/lib/libsmbfs/smb/rap.c
usr/src/lib/libsmbfs/smb/rq.c
usr/src/uts/common/fs/smbclnt/netsmb/offsets.in
usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h
usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c
usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c
usr/src/uts/common/fs/smbclnt/netsmb/smb_subr.h
usr/src/uts/common/fs/smbclnt/netsmb/smb_usr.c
usr/src/uts/common/fs/smbclnt/netsmb/subr_mchain.c
usr/src/uts/common/fs/smbclnt/smbfs/smbfs_node.h
usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c
usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.c
usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.h
usr/src/uts/common/netsmb/smb_dev.h
usr/src/uts/intel/nsmb/ioc_check.ref
usr/src/uts/sparc/nsmb/ioc_check.ref
--- a/exception_lists/copyright	Fri Jun 24 08:44:32 2011 -0700
+++ b/exception_lists/copyright	Thu Jun 30 17:58:05 2011 -0400
@@ -18,8 +18,8 @@
 #
 # CDDL HEADER END
 #
+# Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
 # Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
 #
 
 syntax: glob
@@ -48,6 +48,7 @@
 usr/src/cmd/krb5/ldap_util/kdb5_ldap_policy.h
 usr/src/cmd/krb5/ldap_util/kdb5_ldap_realm.h
 usr/src/cmd/krb5/ldap_util/kdb5_ldap_services.h
+usr/src/cmd/smbsrv/smbd/eventlog.dll
 usr/src/common/bzip2/LICENSE
 usr/src/common/bzip2/Solaris.README.txt
 usr/src/common/bzip2/bzlib.h
@@ -328,6 +329,7 @@
 usr/src/lib/libkmsagent/common/SOAP/*.*
 usr/src/lib/librstp/common/*.[ch]
 usr/src/lib/librstp/common/[CRT]*
+usr/src/uts/intel/nsmb/ioc_check.ref
 usr/src/uts/intel/os/splashimage.xpm
 usr/src/uts/common/gssapi/mechs/krb5/crypto/block_size.c
 usr/src/uts/common/gssapi/mechs/krb5/crypto/checksum_length.c
@@ -354,4 +356,4 @@
 usr/src/uts/common/gssapi/mechs/krb5/mech/util_seed.c
 usr/src/uts/common/gssapi/mechs/krb5/mech/util_seqnum.c
 usr/src/uts/common/gssapi/mechs/krb5/mech/val_cred.c
-usr/src/cmd/smbsrv/smbd/eventlog.dll
+usr/src/uts/sparc/nsmb/ioc_check.ref
--- a/exception_lists/packaging	Fri Jun 24 08:44:32 2011 -0700
+++ b/exception_lists/packaging	Thu Jun 30 17:58:05 2011 -0400
@@ -821,6 +821,7 @@
 #
 usr/lib/fs/smbfs/chacl
 usr/lib/fs/smbfs/lsacl
+usr/lib/fs/smbfs/testnp
 #
 # FC related files
 kernel/kmdb/fcip		i386
--- a/usr/src/cmd/fs.d/smbclnt/Makefile	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/cmd/fs.d/smbclnt/Makefile	Thu Jun 30 17:58:05 2011 -0400
@@ -20,6 +20,7 @@
 #
 
 #
+# Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
 # Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
 #
 
@@ -32,7 +33,7 @@
 
 SUBDIRS_CATALOG=	smbutil mount umount share
 SUBDIRS=		$(SUBDIRS_CATALOG) chacl lsacl \
-			smbiod smbiod-svc svc
+			smbiod smbiod-svc svc test
 
 # for messaging catalog files
 #
--- a/usr/src/cmd/fs.d/smbclnt/smbutil/print.c	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/cmd/fs.d/smbclnt/smbutil/print.c	Thu Jun 30 17:58:05 2011 -0400
@@ -33,6 +33,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -150,7 +151,7 @@
 	 * Have the printer share connection.
 	 * Print the file.
 	 */
-	snprintf(titlebuf, sizeof (titlebuf), "%s_%s",
+	snprintf(titlebuf, sizeof (titlebuf), "%s %s",
 	    ctx->ct_user, filename);
 
 	error = print_file(ctx, titlebuf, file);
@@ -185,13 +186,15 @@
 print_file(smb_ctx_t *ctx, char *title, int file)
 {
 	off_t offset;
-	int error, rcnt, wcnt;
+	int rcnt, wcnt;
 	int setup_len = 0;		/* No printer setup data */
 	int mode = MODE_GRAPHICS;	/* treat as raw data */
-	int fh = -1;
+	int error = 0;
+	int pfd = -1;
 
-	error = smb_printer_open(ctx, setup_len, mode, title, &fh);
-	if (error) {
+	pfd = smb_open_printer(ctx, title, setup_len, mode);
+	if (pfd < 0) {
+		error = errno;
 		smb_error("could not open print job", error);
 		return (error);
 	}
@@ -207,7 +210,7 @@
 		if (rcnt == 0)
 			break;
 
-		wcnt = smb_fh_write(ctx, fh, offset, rcnt, databuf);
+		wcnt = smb_fh_write(pfd, offset, rcnt, databuf);
 		if (wcnt < 0) {
 			error = errno;
 			smb_error("error writing spool file\n", error);
@@ -221,6 +224,6 @@
 		offset += wcnt;
 	}
 
-	(void) smb_printer_close(ctx, fh);
+	(void) smb_fh_close(pfd);
 	return (error);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fs.d/smbclnt/test/Makefile	Thu Jun 30 17:58:05 2011 -0400
@@ -0,0 +1,58 @@
+#
+# 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 2011 Nexenta Systems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+FSTYPE=		smbfs
+LIBPROG=	testnp
+ROOTFS_PROG=	$(LIBPROG)
+
+include		../../Makefile.fstype
+
+OBJS=	$(LIBPROG).o
+SRCS=	$(LIBPROG).c $(FSLIBSRC)
+
+LDLIBS += -lsmbfs
+
+CFLAGS += $(CCVERBOSE)
+C99MODE= $(C99_ENABLE)
+
+CLOBBERFILES	+= $(LIBPROG)
+
+# uncomment these for dbx debugging
+#COPTFLAG = -g
+#CTF_FLAGS =
+#CTFCONVERT_O=
+#CTFMERGE_LIB=
+
+all:	$(ROOTFS_PROG)
+
+install:	$(ROOTLIBFSTYPEPROG)
+
+lint:	lint_SRCS
+
+clean:     
+	$(RM) $(OBJS)
+
+.KEEP_STATE:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fs.d/smbclnt/test/testnp.c	Thu Jun 30 17:58:05 2011 -0400
@@ -0,0 +1,416 @@
+/*
+ * 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 2011 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/*
+ * Test program for the smbfs named pipe API.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <libintl.h>
+
+#include <netsmb/smbfs_api.h>
+
+/*
+ * This is a quick hack for testing client-side named pipes.
+ * Its purpose is to test the ability to connect to a server,
+ * open a pipe, send and receive data.  The "hack" aspect is
+ * the use of hand-crafted RPC messages, which allows testing
+ * of the named pipe API separately from the RPC libraries.
+ *
+ * I captured the two small name pipe messages sent when
+ * requesting a server info via RPC over /pipe/srvsvc and
+ * dropped them into the arrays below (bind and info).
+ * This program sends the two messages (with adjustments)
+ * and just dumps whatever comes back over the pipe.
+ * Use wireshark if you want to see decoded messages.
+ */
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+/* This is a DCE/RPC bind call for "srvsvc". */
+static const uchar_t
+srvsvc_bind[] = {
+	0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
+	0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+	0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
+	0xc8, 0x4f, 0x32, 0x4b, 0x70, 0x16, 0xd3, 0x01,
+	0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e, 0xe1, 0x88,
+	0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+	0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+	0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00 };
+
+/* This is a srvsvc "get server info" call, in two parts */
+static const uchar_t
+srvsvc_info[] = {
+	0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
+#define	INFO_RPCLEN_OFF	8
+	/* V - RPC frag length */
+	0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* ... and the operation number is: VVVV */
+	0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x15, 0x00,
+#define	INFO_SLEN1_OFF	28
+#define	INFO_SLEN2_OFF	36
+	/* server name, length 14 vv ... */
+	0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00 };
+	/* UNC server here, i.e.: "\\192.168.1.6" */
+
+static uchar_t sendbuf[1024];
+static uchar_t recvbuf[1024];
+static char *server;
+
+static int pipetest(struct smb_ctx *);
+
+static void
+testnp_usage(void)
+{
+	printf("usage: testnp [-d domain][-u user][-p passwd] server\n");
+	exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+	int c, error;
+	struct smb_ctx *ctx = NULL;
+	char *dom = NULL;
+	char *usr = NULL;
+	char *pw = NULL;
+
+	while ((c = getopt(argc, argv, "vd:u:p:")) != -1) {
+		switch (c) {
+		case 'v':
+			smb_verbose = 1;
+			break;
+
+		case 'd':
+			dom = optarg;
+			break;
+		case 'u':
+			usr = optarg;
+			break;
+		case 'p':
+			pw = optarg;
+			break;
+		case '?':
+			testnp_usage();
+			break;
+		}
+	}
+	if (optind >= argc)
+		testnp_usage();
+	server = argv[optind];
+
+	if (pw != NULL && (dom == NULL || usr == NULL)) {
+		fprintf(stderr, "%0: -p arg requires -d dom -u usr\n",
+		    argv[0]);
+		testnp_usage();
+	}
+
+	/*
+	 * This section is intended to demonstrate how an
+	 * RPC client library might use this interface.
+	 */
+	error = smb_ctx_alloc(&ctx);
+	if (error) {
+		fprintf(stderr, "%s: smb_ctx_alloc failed\n", argv[0]);
+		goto out;
+	}
+
+	/*
+	 * Set server, share, domain, user
+	 * (in the ctx handle).
+	 */
+	smb_ctx_setfullserver(ctx, server);
+	smb_ctx_setshare(ctx, "IPC$", USE_IPC);
+	if (dom)
+		smb_ctx_setdomain(ctx, dom, B_TRUE);
+	if (usr)
+		smb_ctx_setuser(ctx, usr, B_TRUE);
+	if (pw)
+		smb_ctx_setpassword(ctx, pw, NULL);
+
+
+	/*
+	 * If this code were in smbutil or mount_smbfs, it would
+	 * get system and $HOME/.nsmbrc settings here, like this:
+	 */
+#if 0
+	error = smb_ctx_readrc(ctx);
+	if (error) {
+		fprintf(stderr, "%s: smb_ctx_readrc failed\n", argv[0]);
+		goto out;
+	}
+#endif
+
+	/*
+	 * Resolve the server address,
+	 * setup derived defaults.
+	 */
+	error = smb_ctx_resolve(ctx);
+	if (error) {
+		fprintf(stderr, "%s: smb_ctx_resolve failed\n", argv[0]);
+		goto out;
+	}
+
+	/*
+	 * Get the session and tree.
+	 */
+	error = smb_ctx_get_ssn(ctx);
+	if (error) {
+		fprintf(stderr, "//%s: login failed, error %d\n",
+		    server, error);
+		goto out;
+	}
+	error = smb_ctx_get_tree(ctx);
+	if (error) {
+		fprintf(stderr, "//%s/%s: tree connect failed, %d\n",
+		    server, "IPC$", error);
+		goto out;
+	}
+
+	/*
+	 * Do some named pipe I/O.
+	 */
+	error = pipetest(ctx);
+	if (error) {
+		fprintf(stderr, "pipetest, %d\n", error);
+		goto out;
+	}
+
+out:
+	smb_ctx_free(ctx);
+
+	return ((error) ? 1 : 0);
+}
+
+static void
+hexdump(const uchar_t *buf, int len) {
+	int ofs = 0;
+
+	while (len--) {
+		if (ofs % 16 == 0)
+			printf("\n%02X: ", ofs);
+		printf("%02x ", *buf++);
+		ofs++;
+	}
+	printf("\n");
+}
+
+/*
+ * Put a unicode UNC server name, including the null.
+ * Quick-n-dirty, just for this test...
+ */
+static int
+put_uncserver(const char *s, uchar_t *buf)
+{
+	uchar_t *p = buf;
+	int slashcnt = 0;
+	char c;
+
+	*p++ = '\\'; *p++ = '\0';
+	*p++ = '\\'; *p++ = '\0';
+
+	do {
+		c = *s++;
+		if (c == '/')
+			c = '\\';
+		*p++ = c;
+		*p++ = '\0';
+
+	} while (c != 0);
+
+	return (p - buf);
+}
+
+/* Get a little-endian int.  Just for testing. */
+static int
+getint(const uchar_t *p)
+{
+	return (p[0] + (p[1]<<8) + (p[2]<<16) + (p[3]<<24));
+}
+
+/*
+ * Send the bind and read the ack.
+ * This tests smb_fh_xactnp.
+ */
+static int
+do_bind(int fid)
+{
+	int err, len, more;
+
+	more = 0;
+	len = sizeof (recvbuf);
+	err = smb_fh_xactnp(fid,
+	    sizeof (srvsvc_bind), (char *)srvsvc_bind,
+	    &len, (char *)recvbuf, &more);
+	if (err) {
+		printf("xact bind, err=%d\n", err);
+		return (err);
+	}
+	if (smb_verbose) {
+		printf("bind ack, len=%d\n", len);
+		hexdump(recvbuf, len);
+	}
+	if (more > 0) {
+		if (more > sizeof (recvbuf)) {
+			printf("bogus more=%d\n", more);
+			more = sizeof (recvbuf);
+		}
+		len = smb_fh_read(fid, 0,
+		    more, (char *)recvbuf);
+		if (len == -1) {
+			err = EIO;
+			printf("read info resp, err=%d\n", err);
+			return (err);
+		}
+		if (smb_verbose) {
+			printf("bind ack (more), len=%d\n", len);
+			hexdump(recvbuf, len);
+		}
+	}
+
+	return (0);
+}
+
+static int
+do_info(int fid)
+{
+	int err, len, rlen, wlen, x;
+	uchar_t *p;
+
+	/*
+	 * Build the info request - two parts.
+	 * See above: srvsvc_info
+	 *
+	 * First part: RPC header, etc.
+	 */
+	p = sendbuf;
+	len = sizeof (srvsvc_info); /* 40 */
+	memcpy(p, srvsvc_info, len);
+	p += len;
+
+	/* Second part: UNC server name */
+	len = put_uncserver(server, p);
+	p += len;
+	sendbuf[INFO_SLEN1_OFF] = len / 2;
+	sendbuf[INFO_SLEN2_OFF] = len / 2;
+
+	/* Third part: level, etc. (align4) */
+	for (len = (p - sendbuf) & 3; len; len--)
+		*p++ = '\0';
+	*p++ = 101;	/* the "level" */
+	*p++ = 0; *p++ = 0; *p++ = 0;
+
+	/*
+	 * Compute total length, and fixup RPC header.
+	 */
+	len = p - sendbuf;
+	sendbuf[INFO_RPCLEN_OFF] = len;
+
+	/*
+	 * Send the info request, read the response.
+	 * This tests smb_fh_write, smb_fh_read.
+	 */
+	wlen = smb_fh_write(fid, 0, len, (char *)sendbuf);
+	if (wlen == -1) {
+		err = errno;
+		printf("write info req, err=%d\n", err);
+		return (err);
+	}
+	if (wlen != len) {
+		printf("write info req, short write %d\n", wlen);
+		return (EIO);
+	}
+
+	rlen = smb_fh_read(fid, 0,
+	    sizeof (recvbuf), (char *)recvbuf);
+	if (rlen == -1) {
+		err = errno;
+		printf("read info resp, err=%d\n", err);
+		return (err);
+	}
+
+	if (smb_verbose) {
+		printf("info recv, len=%d\n", rlen);
+		hexdump(recvbuf, rlen);
+	}
+
+	x = getint(recvbuf + 4);
+	if (x != 0x10) {
+		printf("Data representation 0x%x not supported\n", x);
+		return (ENOTSUP);
+	}
+	printf("Platform Id: %d\n", getint(recvbuf + 0x20));
+	printf("Version Major: %d\n", getint(recvbuf + 0x28));
+	printf("Version Minor: %d\n", getint(recvbuf + 0x2c));
+	printf("Srv type flags: 0x%x\n", getint(recvbuf + 0x30));
+
+	return (0);
+}
+
+static int
+pipetest(struct smb_ctx *ctx)
+{
+	static char path[] = "/srvsvc";
+	static uchar_t key[16];
+	int err, fd;
+
+	printf("open pipe: %s\n", path);
+	fd = smb_fh_open(ctx, path, O_RDWR);
+	if (fd < 0) {
+		perror(path);
+		return (errno);
+	}
+
+	/* Test this too. */
+	err = smb_fh_getssnkey(fd, key, sizeof (key));
+	if (err) {
+		printf("getssnkey: %d\n", err);
+		goto out;
+	}
+
+	err = do_bind(fd);
+	if (err) {
+		printf("do_bind: %d\n", err);
+		goto out;
+	}
+	err = do_info(fd);
+	if (err)
+		printf("do_info: %d\n", err);
+
+out:
+	smb_fh_close(fd);
+	return (err);
+}
--- a/usr/src/cmd/mdb/common/modules/nsmb/nsmb.c	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/cmd/mdb/common/modules/nsmb/nsmb.c	Thu Jun 30 17:58:05 2011 -0400
@@ -20,6 +20,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -30,9 +31,9 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 
-#include "smb_conn.h"
-#include "smb_rq.h"
-#include "smb_pass.h"
+#include <netsmb/smb_conn.h>
+#include <netsmb/smb_rq.h>
+#include <netsmb/smb_pass.h>
 
 #define	OPT_VERBOSE	0x0001	/* Be [-v]erbose in dcmd's */
 #define	OPT_RECURSE	0x0002	/* recursive display */
--- a/usr/src/cmd/mdb/common/modules/smbfs/smbfs.c	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/cmd/mdb/common/modules/smbfs/smbfs.c	Thu Jun 30 17:58:05 2011 -0400
@@ -20,6 +20,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -30,8 +31,8 @@
 #include <sys/vnode.h>
 #include <sys/vfs.h>
 
-#include "smbfs.h"
-#include "smbfs_node.h"
+#include <smbfs/smbfs.h>
+#include <smbfs/smbfs_node.h>
 
 #define	OPT_VERBOSE	0x0001	/* Be [-v]erbose in dcmd's */
 
--- a/usr/src/cmd/mdb/intel/amd64/nsmb/Makefile	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/cmd/mdb/intel/amd64/nsmb/Makefile	Thu Jun 30 17:58:05 2011 -0400
@@ -19,6 +19,7 @@
 # CDDL HEADER END
 #
 #
+# Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
 # Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 
@@ -36,11 +37,10 @@
 
 include ../../../Makefile.module
 
-CPPFLAGS	+= -I$(SRC)/uts/common/fs/smbclnt/netsmb
+CPPFLAGS	+= -I$(SRC)/uts/common/fs/smbclnt
 CPPFLAGS	+= -I$(SRC)/uts/common
 
-C99MODE=	-xc99=%all
-C99LMODE=	-Xc99=%all
+C99MODE=	$(C99_ENABLE)
 
 # maybe not the best place for this, but
 # we need to create this directory.
--- a/usr/src/cmd/mdb/intel/amd64/smbfs/Makefile	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/cmd/mdb/intel/amd64/smbfs/Makefile	Thu Jun 30 17:58:05 2011 -0400
@@ -19,6 +19,7 @@
 # CDDL HEADER END
 #
 #
+# Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
 # Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 
@@ -36,9 +37,11 @@
 
 include ../../../Makefile.module
 
-CPPFLAGS	+= -I$(SRC)/uts/common/fs/smbclnt/smbfs
+CPPFLAGS	+= -I$(SRC)/uts/common/fs/smbclnt
 CPPFLAGS	+= -I$(SRC)/uts/common
 
+C99MODE=	$(C99_ENABLE)
+
 # maybe not the best place for this, but
 # we need to create this directory.
 $(ROOTKMOD):
--- a/usr/src/cmd/mdb/intel/ia32/nsmb/Makefile	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/cmd/mdb/intel/ia32/nsmb/Makefile	Thu Jun 30 17:58:05 2011 -0400
@@ -19,6 +19,7 @@
 # CDDL HEADER END
 #
 #
+# Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
 # Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 
@@ -35,11 +36,10 @@
 
 include ../../../Makefile.module
 
-CPPFLAGS	+= -I$(SRC)/uts/common/fs/smbclnt/netsmb
+CPPFLAGS	+= -I$(SRC)/uts/common/fs/smbclnt
 CPPFLAGS	+= -I$(SRC)/uts/common
 
-C99MODE=	-xc99=%all
-C99LMODE=	-Xc99=%all
+C99MODE=	$(C99_ENABLE)
 
 # maybe not the best place for this, but
 # we need to create this directory.
--- a/usr/src/cmd/mdb/intel/ia32/smbfs/Makefile	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/cmd/mdb/intel/ia32/smbfs/Makefile	Thu Jun 30 17:58:05 2011 -0400
@@ -19,6 +19,7 @@
 # CDDL HEADER END
 #
 #
+# Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
 # Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 
@@ -35,9 +36,11 @@
 
 include ../../../Makefile.module
 
-CPPFLAGS	+= -I$(SRC)/uts/common/fs/smbclnt/smbfs
+CPPFLAGS	+= -I$(SRC)/uts/common/fs/smbclnt
 CPPFLAGS	+= -I$(SRC)/uts/common
 
+C99MODE=	$(C99_ENABLE)
+
 # maybe not the best place for this, but
 # we need to create this directory.
 $(ROOTKMOD):
--- a/usr/src/cmd/mdb/sparc/v9/nsmb/Makefile	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/cmd/mdb/sparc/v9/nsmb/Makefile	Thu Jun 30 17:58:05 2011 -0400
@@ -19,6 +19,7 @@
 # CDDL HEADER END
 #
 #
+# Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
 # Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 
@@ -36,11 +37,10 @@
 
 include ../../../Makefile.module
 
-CPPFLAGS	+= -I$(SRC)/uts/common/fs/smbclnt/netsmb
+CPPFLAGS	+= -I$(SRC)/uts/common/fs/smbclnt
 CPPFLAGS	+= -I$(SRC)/uts/common
 
-C99MODE=	-xc99=%all
-C99LMODE=	-Xc99=%all
+C99MODE=	$(C99_ENABLE)
 
 # maybe not the best place for this, but
 # we need to create this directory.
--- a/usr/src/cmd/mdb/sparc/v9/smbfs/Makefile	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/cmd/mdb/sparc/v9/smbfs/Makefile	Thu Jun 30 17:58:05 2011 -0400
@@ -19,6 +19,7 @@
 # CDDL HEADER END
 #
 #
+# Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
 # Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 
@@ -36,9 +37,11 @@
 
 include ../../../Makefile.module
 
-CPPFLAGS	+= -I$(SRC)/uts/common/fs/smbclnt/smbfs
+CPPFLAGS	+= -I$(SRC)/uts/common/fs/smbclnt
 CPPFLAGS	+= -I$(SRC)/uts/common
 
+C99MODE=	$(C99_ENABLE)
+
 # maybe not the best place for this, but
 # we need to create this directory.
 $(ROOTKMOD):
--- a/usr/src/lib/libsmbfs/Makefile	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/lib/libsmbfs/Makefile	Thu Jun 30 17:58:05 2011 -0400
@@ -19,6 +19,7 @@
 # CDDL HEADER END
 #
 #
+# Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
 # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
@@ -29,7 +30,7 @@
 
 include $(SRC)/lib/Makefile.lib
 
-HDRS=		smbfs_acl.h smbfs_api.h
+HDRS=		smbfs_acl.h smbfs_api.h smb_keychain.h
 HDRDIR=		netsmb
 
 ROOTHDRDIR=	$(ROOT)/usr/include/netsmb
--- a/usr/src/lib/libsmbfs/netsmb/smb_keychain.h	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/lib/libsmbfs/netsmb/smb_keychain.h	Thu Jun 30 17:58:05 2011 -0400
@@ -20,6 +20,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -27,8 +28,6 @@
 #ifndef _SMB_KEYCHAIN_H
 #define	_SMB_KEYCHAIN_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * External interface to the libsmbfs/netsmb keychain
  * storage mechanism.  This interface is consumed by
@@ -36,6 +35,10 @@
  * and by the SMBFS PAM module.
  */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define	SMB_KEYCHAIN_SUCCESS	0
 #define	SMB_KEYCHAIN_BADPASSWD	300
 #define	SMB_KEYCHAIN_BADDOMAIN	301
@@ -47,6 +50,10 @@
 int smbfs_keychain_add(uid_t uid, const char *domain, const char *user,
 	const char *password);
 
+/* Add an NT-hash (16-bytes) to the keychain. */
+int smbfs_keychain_addhash(uid_t uid, const char *domain, const char *user,
+	const uchar_t *nthash);
+
 /* Delete a password from the keychain. */
 int smbfs_keychain_del(uid_t uid, const char *domain, const char *user);
 
@@ -79,4 +86,8 @@
 smbfs_default_dom_usr(const char *home, const char *server,
 	char *dom, int maxdom, char *usr, int maxusr);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _SMB_KEYCHAIN_H */
--- a/usr/src/lib/libsmbfs/netsmb/smb_lib.h	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/lib/libsmbfs/netsmb/smb_lib.h	Thu Jun 30 17:58:05 2011 -0400
@@ -33,6 +33,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
@@ -108,6 +109,7 @@
 	int		ct_shtype_req;	/* share type wanted */
 	char		*ct_origshare;
 	char		*ct_home;
+	char		*ct_rpath;	/* remote file name */
 
 	/* Connection setup SMB stuff. */
 	/* Strings from the SMB negotiate response. */
--- a/usr/src/lib/libsmbfs/netsmb/smbfs_api.h	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/lib/libsmbfs/netsmb/smbfs_api.h	Thu Jun 30 17:58:05 2011 -0400
@@ -20,6 +20,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -28,8 +29,8 @@
 #define	_NETSMB_SMBFS_API_H
 
 /*
- * Define the API exported to our commands and to the
- * MS-style RPC-over-named-pipes library (mlrpc).
+ * Define the API exported to our commands and to
+ * libraries doing DCE-RPC over SMB named pipes.
  */
 
 #include <sys/types.h>
@@ -58,13 +59,14 @@
  * Share type values for smb_ctx_new, _init
  * Based on NetUseAdd() USE_INFO_[12] _asg_type values
  * They also happen to match: STYPE_DISKTREE, etc.
+ * Note: these values appear on the wire.
  */
 typedef enum {
-	USE_WILDCARD = -1,
-	USE_DISKDEV,
-	USE_SPOOLDEV,
-	USE_CHARDEV,
-	USE_IPC
+	USE_DISKDEV = 0,	/* also STYPE_DISKTREE */
+	USE_SPOOLDEV,		/* also STYPE_PRINTQ */
+	USE_CHARDEV,		/* also STYPE_DEVICE */
+	USE_IPC,		/* also STYPE_IPC */
+	USE_WILDCARD		/* also STYPE_UNKNOWN */
 } smb_use_shtype_t;
 
 /*
@@ -115,7 +117,6 @@
 int  smb_ctx_flags2(struct smb_ctx *);
 int  smb_ctx_resolve(struct smb_ctx *);
 int  smb_ctx_get_ssn(struct smb_ctx *);
-int  smb_ctx_get_ssnkey(struct smb_ctx *, uchar_t *, size_t);
 int  smb_ctx_get_tree(struct smb_ctx *);
 
 int  smb_ctx_setauthflags(struct smb_ctx *, int);
@@ -138,20 +139,18 @@
 
 typedef void (*smb_ctx_close_hook_t)(struct smb_ctx *);
 void smb_ctx_set_close_hook(smb_ctx_close_hook_t);
-int  smb_fh_close(struct smb_ctx *ctx, int);
-int  smb_fh_open(struct smb_ctx *ctx, const char *, int, int *);
-int  smb_fh_read(struct smb_ctx *, int, off_t, size_t, char *);
-int  smb_fh_write(struct smb_ctx *, int, off_t, size_t, const char *);
-int  smb_fh_xactnp(struct smb_ctx *, int, int, const char *,
+int  smb_fh_close(int);
+int  smb_fh_open(struct smb_ctx *ctx, const char *, int);
+int  smb_fh_read(int, off_t, size_t, char *);
+int  smb_fh_write(int, off_t, size_t, const char *);
+int  smb_fh_xactnp(int, int, const char *,
 	int *, char *, int *);
+int  smb_fh_getssnkey(int, uchar_t *, size_t);
 
-int  smb_iod_start(struct smb_ctx *);
+int  smb_open_printer(struct smb_ctx *, const char *, int, int);
 
-int  smb_t2_request(struct smb_ctx *, int, uint16_t *, const char *,
-	int, void *, int, void *, int *, void *, int *, void *, int *);
-
-int  smb_printer_open(struct smb_ctx *, int, int, const char *, int *);
-int  smb_printer_close(struct smb_ctx *, int);
+void smbfs_set_default_domain(const char *);
+void smbfs_set_default_user(const char *);
 
 char *smb_strerror(int);
 
--- a/usr/src/lib/libsmbfs/smb/ctx.c	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/lib/libsmbfs/smb/ctx.c	Thu Jun 30 17:58:05 2011 -0400
@@ -33,6 +33,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
@@ -64,8 +65,6 @@
 #include <netsmb/smb_dev.h>
 
 #include "charsets.h"
-#include "spnego.h"
-#include "derparse.h"
 #include "private.h"
 #include "ntlm.h"
 
@@ -90,6 +89,14 @@
 const char smbutil_std_opts[] = "ABCD:E:I:L:M:NO:P:U:R:S:T:W:";
 
 /*
+ * Defaults for new contexts (connections to servers).
+ * These are set by smbfs_set_default_...
+ */
+static char default_domain[SMBIOC_MAX_NAME];
+static char default_user[SMBIOC_MAX_NAME];
+
+
+/*
  * Give the RPC library a callback hook that will be
  * called whenever we destroy or reinit an smb_ctx_t.
  * The name rpc_cleanup_smbctx() is legacy, and was
@@ -206,7 +213,8 @@
 	    ctx->ct_origshare ? ctx->ct_origshare : "",
 	    ctx->ct_shtype_req);
 
-	/* dump_iod_work()? */
+	printf(" ct_home=\"%s\"\n", ctx->ct_home);
+	printf(" ct_rpath=\"%s\"\n", ctx->ct_rpath);
 }
 
 int
@@ -233,9 +241,7 @@
 int
 smb_ctx_init(struct smb_ctx *ctx)
 {
-	char pwbuf[NSS_BUFLEN_PASSWD];
-	struct passwd pw;
-	int error = 0;
+	int error;
 
 	bzero(ctx, sizeof (*ctx));
 
@@ -256,32 +262,15 @@
 	ctx->ct_authflags = SMB_AT_DEFAULT;
 	ctx->ct_minauth = SMB_AT_DEFAULT;
 
-	error = nb_ctx_setscope(ctx->ct_nb, "");
-	if (error)
-		return (error);
-
 	/*
-	 * if the user name is not specified some other way,
-	 * use the current user name (built-in default)
+	 * Default domain, user, ...
 	 */
-	if (getpwuid_r(getuid(), &pw, pwbuf, sizeof (pwbuf)) != NULL) {
-		error = smb_ctx_setuser(ctx, pw.pw_name, 0);
-		if (error)
-			return (error);
-		ctx->ct_home = strdup(pw.pw_name);
-		if (ctx->ct_home == NULL)
-			return (ENOMEM);
-	}
+	strlcpy(ctx->ct_domain, default_domain,
+	    sizeof (ctx->ct_domain));
+	strlcpy(ctx->ct_user, default_user,
+	    sizeof (ctx->ct_user));
 
-	/*
-	 * Set a built-in default domain (workgroup).
-	 * Using the Windows/NT default for now.
-	 */
-	error = smb_ctx_setdomain(ctx, "WORKGROUP", 0);
-	if (error)
-		return (error);
-
-	return (error);
+	return (0);
 }
 
 /*
@@ -441,8 +430,14 @@
 		freeaddrinfo(ctx->ct_addrinfo);
 		ctx->ct_addrinfo = NULL;
 	}
-	if (ctx->ct_home)
+	if (ctx->ct_home) {
 		free(ctx->ct_home);
+		ctx->ct_home = NULL;
+	}
+	if (ctx->ct_rpath) {
+		free(ctx->ct_rpath);
+		ctx->ct_rpath = NULL;
+	}
 	if (ctx->ct_srv_OS) {
 		free(ctx->ct_srv_OS);
 		ctx->ct_srv_OS = NULL;
@@ -457,26 +452,9 @@
 	}
 }
 
-static int
-getsubstring(const char *p, uchar_t sep, char *dest, int maxlen,
-    const char **next)
-{
-	int len;
-
-	maxlen--;
-	for (len = 0; len < maxlen && *p != sep; p++, len++, dest++) {
-		if (*p == 0)
-			return (EINVAL);
-		*dest = *p;
-	}
-	*dest = 0;
-	*next = *p ? p + 1 : p;
-	return (0);
-}
-
 /*
  * Parse the UNC path.  Here we expect something like
- *   "//[workgroup;][user[:password]@]host[/share[/path]]"
+ *   "//[[domain;]user[:password]@]host[/share[/path]]"
  * See http://ietf.org/internet-drafts/draft-crhertel-smb-url-07.txt
  * Values found here are marked as "from CMD".
  */
@@ -485,9 +463,9 @@
 	int minlevel, int maxlevel, int sharetype,
 	const char **next)
 {
-	const char *p = unc;
-	char *p1, *colon;
 	char tmp[1024];
+	char *host, *share, *path;
+	char *dom, *usr, *pw, *p;
 	int error;
 
 	/*
@@ -497,118 +475,146 @@
 	ctx->ct_minlevel = minlevel;
 	ctx->ct_maxlevel = maxlevel;
 	ctx->ct_shtype_req = sharetype;
+	ctx->ct_parsedlevel = SMBL_NONE;
 
-	ctx->ct_parsedlevel = SMBL_NONE;
-	if (*p++ != '/' || *p++ != '/') {
+	dom = usr = pw = host = NULL;
+
+	/* Work on a temporary copy, fix back slashes. */
+	strlcpy(tmp, unc, sizeof (tmp));
+	for (p = tmp; *p; p++)
+		if (*p == '\\')
+			*p = '/';
+
+	if (tmp[0] != '/' || tmp[1] != '/') {
 		smb_error(dgettext(TEXT_DOMAIN,
 		    "UNC should start with '//'"), 0);
 		error = EINVAL;
 		goto out;
 	}
-	p1 = tmp;
-	error = getsubstring(p, ';', p1, sizeof (tmp), &p);
-	if (!error) {
-		if (*p1 == 0) {
+	p = tmp + 2;	/* user@host... */
+
+	/* Find the share part, if any. */
+	share = strchr(p, '/');
+	if (share)
+		*share = '\0';
+	(void) unpercent(p);	/* host component */
+
+	/*
+	 * Parse the "host" stuff right to left:
+	 * 1: trailing "@hostname" (or whole field)
+	 * 2: trailing ":password"
+	 * 3: trailing "domain;user" (or just user)
+	 */
+	host = strrchr(p, '@');
+	if (host == NULL) {
+		host = p;	/* no user@ prefix */
+	} else {
+		*host++ = '\0';
+
+		/* may have [[domain;]user[:passwd]] */
+		pw = strchr(p, ':');
+		if (pw)
+			*pw++ = '\0';
+		usr = strchr(p, ';');
+		if (usr) {
+			*usr++ = '\0';
+			dom = p;
+		} else
+			usr = p;
+	}
+
+	if (*host == '\0') {
+		smb_error(dgettext(TEXT_DOMAIN, "empty server name"), 0);
+		error = EINVAL;
+		goto out;
+	}
+	error = smb_ctx_setfullserver(ctx, host);
+	if (error)
+		goto out;
+	ctx->ct_parsedlevel = SMBL_VC;
+
+	if (dom != NULL) {
+		error = smb_ctx_setdomain(ctx, dom, TRUE);
+		if (error)
+			goto out;
+	}
+	if (usr != NULL) {
+		if (*usr == '\0') {
 			smb_error(dgettext(TEXT_DOMAIN,
-			    "empty workgroup name"), 0);
+			    "empty user name"), 0);
 			error = EINVAL;
 			goto out;
 		}
-		error = smb_ctx_setdomain(ctx, unpercent(tmp), TRUE);
-		if (error)
-			goto out;
-	}
-	colon = (char *)p;
-	error = getsubstring(p, '@', p1, sizeof (tmp), &p);
-	if (!error) {
 		if (ctx->ct_maxlevel < SMBL_VC) {
 			smb_error(dgettext(TEXT_DOMAIN,
 			    "no user name required"), 0);
 			error = EINVAL;
 			goto out;
 		}
-		p1 = strchr(tmp, ':');
-		if (p1) {
-			colon += p1 - tmp;
-			*p1++ = (char)0;
-			error = smb_ctx_setpassword(ctx, unpercent(p1), TRUE);
-			if (error)
-				goto out;
-			if (p - colon > 2)
-				memset(colon+1, '*', p - colon - 2);
-		}
-		p1 = tmp;
-		if (*p1 == 0) {
+		error = smb_ctx_setuser(ctx, usr, TRUE);
+		if (error)
+			goto out;
+	}
+	if (pw != NULL) {
+		error = smb_ctx_setpassword(ctx, pw, TRUE);
+		if (error)
+			goto out;
+	}
+
+	if (share != NULL) {
+		/* restore the slash */
+		*share = '/';
+		p = share + 1;
+
+		/* Find the path part, if any. */
+		path = strchr(p, '/');
+		if (path)
+			*path = '\0';
+		(void) unpercent(p);	/* share component */
+
+		if (*p == '\0') {
 			smb_error(dgettext(TEXT_DOMAIN,
-			    "empty user name"), 0);
+			    "empty share name"), 0);
 			error = EINVAL;
 			goto out;
 		}
-		error = smb_ctx_setuser(ctx, unpercent(tmp), TRUE);
+		if (ctx->ct_maxlevel < SMBL_SHARE) {
+			smb_error(dgettext(TEXT_DOMAIN,
+			    "no share name required"), 0);
+			error = EINVAL;
+			goto out;
+		}
+
+		/*
+		 * Special case UNC names like:
+		 *	//host/PIPE/endpoint
+		 * to have share: IPC$
+		 */
+		if (strcasecmp(p, "PIPE") == 0) {
+			sharetype = USE_IPC;
+			p = "IPC$";
+		}
+		error = smb_ctx_setshare(ctx, p, sharetype);
 		if (error)
 			goto out;
-		ctx->ct_parsedlevel = SMBL_VC;
-	}
-	error = getsubstring(p, '/', p1, sizeof (tmp), &p);
-	if (error) {
-		error = getsubstring(p, '\0', p1, sizeof (tmp), &p);
-		if (error) {
-			smb_error(dgettext(TEXT_DOMAIN,
-			    "no server name found"), 0);
-			goto out;
+		ctx->ct_parsedlevel = SMBL_SHARE;
+
+		if (path) {
+			/* restore the slash */
+			*path = '/';
+			p = path + 1;
+			(void) unpercent(p);	/* remainder */
+			free(ctx->ct_rpath);
+			ctx->ct_rpath = strdup(path);
 		}
-	}
-	if (*p1 == 0) {
-		smb_error(dgettext(TEXT_DOMAIN, "empty server name"), 0);
+	} else if (ctx->ct_minlevel >= SMBL_SHARE) {
+		smb_error(dgettext(TEXT_DOMAIN, "empty share name"), 0);
 		error = EINVAL;
 		goto out;
 	}
 
-	/*
-	 * Save ct_fullserver without case conversion.
-	 */
-	if (strchr(tmp, '%'))
-		(void) unpercent(tmp);
-	error = smb_ctx_setfullserver(ctx, tmp);
-	if (error)
-		goto out;
-
-#ifdef	SMB_ST_NONE
-	if (sharetype == SMB_ST_NONE) {
-		if (next)
-			*next = p;
-		error = 0;
-		goto out;
-	}
-#endif
-
-	if (*p != 0 && ctx->ct_maxlevel < SMBL_SHARE) {
-		smb_error(dgettext(TEXT_DOMAIN, "no share name required"), 0);
-		error = EINVAL;
-		goto out;
-	}
-	error = getsubstring(p, '/', p1, sizeof (tmp), &p);
-	if (error) {
-		error = getsubstring(p, '\0', p1, sizeof (tmp), &p);
-		if (error) {
-			smb_error(dgettext(TEXT_DOMAIN,
-			    "unexpected end of line"), 0);
-			goto out;
-		}
-	}
-	if (*p1 == 0 && ctx->ct_minlevel >= SMBL_SHARE &&
-	    !(ctx->ct_flags & SMBCF_BROWSEOK)) {
-		smb_error(dgettext(TEXT_DOMAIN, "empty share name"), 0);
-		error = EINVAL;
-		goto out;
-	}
 	if (next)
-		*next = p;
-	if (*p1 == 0) {
-		error = 0;
-		goto out;
-	}
-	error = smb_ctx_setshare(ctx, unpercent(p1), sharetype);
+		*next = NULL;
 
 out:
 	if (error == 0 && smb_debug > 0)
@@ -1147,27 +1153,10 @@
 int
 smb_open_driver()
 {
-	int err, fd;
-	uint32_t version;
+	int fd;
 
 	fd = open("/dev/"NSMB_NAME, O_RDWR);
 	if (fd < 0) {
-		err = errno;
-		smb_error(dgettext(TEXT_DOMAIN,
-		    "failed to open driver"), err);
-		return (-1);
-	}
-
-	/*
-	 * Check the driver version (paranoia)
-	 * Do this BEFORE any other ioctl calls.
-	 */
-	if (ioctl(fd, SMBIOC_GETVERS, &version) < 0)
-		version = 0;
-	if (version != NSMB_VERSION) {
-		smb_error(dgettext(TEXT_DOMAIN,
-		    "incorrect driver version"), 0);
-		close(fd);
 		return (-1);
 	}
 
@@ -1180,7 +1169,8 @@
 int
 smb_ctx_gethandle(struct smb_ctx *ctx)
 {
-	int fd;
+	int fd, err;
+	uint32_t version;
 
 	if (ctx->ct_dev_fd != -1) {
 		rpc_cleanup_smbctx(ctx);
@@ -1190,8 +1180,24 @@
 	}
 
 	fd = smb_open_driver();
-	if (fd < 0)
+	if (fd < 0) {
+		err = errno;
+		smb_error(dgettext(TEXT_DOMAIN,
+		    "failed to open driver"), err);
+		return (err);
+	}
+
+	/*
+	 * Check the driver version (paranoia)
+	 */
+	if (ioctl(fd, SMBIOC_GETVERS, &version) < 0)
+		version = 0;
+	if (version != NSMB_VERSION) {
+		smb_error(dgettext(TEXT_DOMAIN,
+		    "incorrect driver version"), 0);
+		close(fd);
 		return (ENODEV);
+	}
 
 	ctx->ct_dev_fd = fd;
 	return (0);
@@ -1241,43 +1247,12 @@
 }
 
 /*
- * Get the string representation of a share "use" type,
- * as needed for the "service" in tree connect.
- */
-static const char *
-smb_use_type_str(smb_use_shtype_t stype)
-{
-	const char *pp;
-
-	switch (stype) {
-	default:
-	case USE_WILDCARD:
-		pp = "?????";
-		break;
-	case USE_DISKDEV:
-		pp = "A:";
-		break;
-	case USE_SPOOLDEV:
-		pp = "LPT1:";
-		break;
-	case USE_CHARDEV:
-		pp = "COMM";
-		break;
-	case USE_IPC:
-		pp = "IPC";
-		break;
-	}
-	return (pp);
-}
-
-/*
  * Find or create a tree connection
  */
 int
 smb_ctx_get_tree(struct smb_ctx *ctx)
 {
 	smbioc_tcon_t *tcon = NULL;
-	const char *stype;
 	int cmd, err = 0;
 
 	if (ctx->ct_dev_fd < 0 ||
@@ -1297,18 +1272,8 @@
 	strlcpy(tcon->tc_sh.sh_name, ctx->ct_origshare,
 	    sizeof (tcon->tc_sh.sh_name));
 
-	/*
-	 * Share password (unused - no share-level security)
-	 * MS-SMB 2.2.6 says this should be null terminated,
-	 * and the length includes the null.  Did bzero above,
-	 * so just set length for the null.
-	 */
-	tcon->tc_sh.sh_pwlen = 1;
-
 	/* The share "use" type. */
-	stype = smb_use_type_str(ctx->ct_shtype_req);
-	strlcpy(tcon->tc_sh.sh_type_req, stype,
-	    sizeof (tcon->tc_sh.sh_type_req));
+	tcon->tc_sh.sh_use = ctx->ct_shtype_req;
 
 	/*
 	 * Todo: share passwords for share-level security.
@@ -1323,13 +1288,12 @@
 	/*
 	 * Check the returned share type
 	 */
-	DPRINT("ret. sh_type: \"%s\"", tcon->tc_sh.sh_type_ret);
+	DPRINT("ret. sh_type: \"%d\"", tcon->tc_sh.sh_type);
 	if (ctx->ct_shtype_req != USE_WILDCARD &&
-	    0 != strcmp(stype, tcon->tc_sh.sh_type_ret)) {
+	    ctx->ct_shtype_req != tcon->tc_sh.sh_type) {
 		smb_error(dgettext(TEXT_DOMAIN,
 		    "%s: incompatible share type"),
 		    0, ctx->ct_origshare);
-		err = EINVAL;
 	}
 
 out:
@@ -1360,12 +1324,12 @@
  * Must already have an active SMB session.
  */
 int
-smb_ctx_get_ssnkey(struct smb_ctx *ctx, uchar_t *key, size_t len)
+smb_fh_getssnkey(int dev_fd, uchar_t *key, size_t len)
 {
 	if (len < SMBIOC_HASH_SZ)
 		return (EINVAL);
 
-	if (ioctl(ctx->ct_dev_fd, SMBIOC_GETSSNKEY, key) == -1)
+	if (ioctl(dev_fd, SMBIOC_GETSSNKEY, key) == -1)
 		return (errno);
 
 	return (0);
@@ -1536,14 +1500,26 @@
 int
 smb_ctx_readrc(struct smb_ctx *ctx)
 {
-	char *home;
+	char pwbuf[NSS_BUFLEN_PASSWD];
+	struct passwd pw;
 	char *sname = NULL;
 	int sname_max;
 	int err = 0;
 
-	if ((home = getenv("HOME")) == NULL)
-		home = ctx->ct_home;
-	if ((err = smb_open_rcfile(home)) != 0) {
+	/*
+	 * If the user name is not specified some other way,
+	 * use the current user name.  Also save the homedir.
+	 * NB: ct_home=NULL is allowed, and we don't want to
+	 * bail out with an error for a missing ct_home.
+	 */
+	if (getpwuid_r(getuid(), &pw, pwbuf, sizeof (pwbuf)) != NULL) {
+		if (ctx->ct_user[0] == 0)
+			(void) smb_ctx_setuser(ctx, pw.pw_name, B_FALSE);
+		if (ctx->ct_home == NULL)
+			ctx->ct_home = strdup(pw.pw_dir);
+	}
+
+	if ((err = smb_open_rcfile(ctx->ct_home)) != 0) {
 		DPRINT("smb_open_rcfile, err=%d", err);
 		/* ignore any error here */
 		return (0);
@@ -1614,3 +1590,15 @@
 
 	return (err);
 }
+
+void
+smbfs_set_default_domain(const char *domain)
+{
+	strlcpy(default_domain, domain, sizeof (default_domain));
+}
+
+void
+smbfs_set_default_user(const char *user)
+{
+	strlcpy(default_user, user, sizeof (default_user));
+}
--- a/usr/src/lib/libsmbfs/smb/file.c	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/lib/libsmbfs/smb/file.c	Thu Jun 30 17:58:05 2011 -0400
@@ -33,6 +33,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -62,133 +63,66 @@
 #include "private.h"
 
 int
-smb_fh_close(struct smb_ctx *ctx, int fh)
+smb_fh_close(int fd)
 {
-	struct smb_rq	*rqp;
-	struct mbdata	*mbp;
-	int error;
-
-	error = smb_rq_init(ctx, SMB_COM_CLOSE, &rqp);
-	if (error != 0)
-		return (error);
-	mbp = smb_rq_getrequest(rqp);
-	smb_rq_wstart(rqp);
-	mb_put_uint16le(mbp, (uint16_t)fh);
-	mb_put_uint32le(mbp, 0);	/* time stamp */
-	smb_rq_wend(rqp);
-	mb_put_uint16le(mbp, 0);	/* byte count */
-
-	error = smb_rq_simple(rqp);
-	smb_rq_done(rqp);
-
-	return (error);
+	return (close(fd));
 }
 
 int
 smb_fh_ntcreate(
 	struct smb_ctx *ctx, char *path,
-	int flags, int req_acc, int efattr,
-	int share_acc, int open_disp,
-	int create_opts, int impersonation,
-	int *fhp, uint32_t *action_taken)
+	int req_acc, int efattr, int share_acc,
+	int open_disp, int create_opts)
 {
-	struct smb_rq	*rqp;
-	struct mbdata	*mbp;
-	char		*pathsizep;
-	int		pathstart, pathsize;
-	int		error, flags2, uc;
-	uint16_t	fh;
-	uint8_t		wc;
-
-	flags2 = smb_ctx_flags2(ctx);
-	if (flags2 == -1)
-		return (EIO);
-	uc = flags2 & SMB_FLAGS2_UNICODE;
-
-	error = smb_rq_init(ctx, SMB_COM_NT_CREATE_ANDX, &rqp);
-	if (error != 0)
-		return (error);
+	smbioc_ntcreate_t ioc;
+	int err, nmlen;
+	int new_fd = -1;
+	int32_t from_fd;
 
-	mbp = smb_rq_getrequest(rqp);
-	smb_rq_wstart(rqp);
-	mb_put_uint16le(mbp, 0xff);	/* secondary command */
-	mb_put_uint16le(mbp, 0);	/* offset to next command (none) */
-	mb_put_uint8(mbp, 0);		/* MBZ (pad?) */
-	(void) mb_fit(mbp, 2, &pathsizep); /* path size - fill in below */
-	mb_put_uint32le(mbp, flags);	/* create flags (oplock) */
-	mb_put_uint32le(mbp, 0);	/* FID - basis for path if not root */
-	mb_put_uint32le(mbp, req_acc);
-	mb_put_uint64le(mbp, 0);		/* initial alloc. size */
-	mb_put_uint32le(mbp, efattr);		/* ext. file attributes */
-	mb_put_uint32le(mbp, share_acc);	/* share access mode */
-	mb_put_uint32le(mbp, open_disp);	/* open disposition */
-	mb_put_uint32le(mbp, create_opts);  /* create_options */
-	mb_put_uint32le(mbp, impersonation);
-	mb_put_uint8(mbp, 0);	/* security flags (?) */
-	smb_rq_wend(rqp);
-	smb_rq_bstart(rqp);
-	if (uc) {
-		/*
-		 * We're about to put a unicode string.  We know
-		 * we're misaligned at this point, and need to
-		 * save the mb_count at the start of the string,
-		 * not at the alignment padding placed before it.
-		 * So add the algnment padding by hand here.
-		 */
-		mb_put_uint8(mbp, 0);
+	nmlen = strlen(path);
+	if (nmlen >= SMBIOC_MAX_NAME) {
+		err = EINVAL;
+		goto errout;
+	}
+
+	/*
+	 * Will represent this SMB-level open as a new
+	 * open device handle.  Get one, then duplicate
+	 * the driver session and tree bindings.
+	 */
+	new_fd = smb_open_driver();
+	if (new_fd < 0) {
+		err = errno;
+		goto errout;
 	}
-	pathstart = mbp->mb_count;
-	mb_put_string(mbp, path, uc);
-	smb_rq_bend(rqp);
-
-	/* Now go back and fill in pathsizep */
-	pathsize = mbp->mb_count - pathstart;
-	pathsizep[0] = pathsize & 0xFF;
-	pathsizep[1] = (pathsize >> 8);
-
-	error = smb_rq_simple(rqp);
-	if (error)
-		goto out;
-
-	mbp = smb_rq_getreply(rqp);
-	/*
-	 * spec says 26 for word count, but 34 words are defined
-	 * and observed from win2000
-	 */
-	error = md_get_uint8(mbp, &wc);
-	if (error || wc < 26) {
-		smb_error(dgettext(TEXT_DOMAIN,
-		    "%s: open failed, bad word count"), 0, path);
-		error = EBADRPC;
-		goto out;
+	from_fd = ctx->ct_dev_fd;
+	if (ioctl(new_fd, SMBIOC_DUP_DEV, &from_fd) == -1) {
+		err = errno;
+		goto errout;
 	}
-	md_get_uint8(mbp, NULL);	/* secondary cmd */
-	md_get_uint8(mbp, NULL);	/* mbz */
-	md_get_uint16le(mbp, NULL);	/* andxoffset */
-	md_get_uint8(mbp, NULL);	/* oplock lvl granted */
-	md_get_uint16le(mbp, &fh);	/* FID */
-	md_get_uint32le(mbp, action_taken);
-#if 0	/* skip decoding the rest */
-	md_get_uint64le(mbp, NULL);	/* creation time */
-	md_get_uint64le(mbp, NULL);	/* access time */
-	md_get_uint64le(mbp, NULL);	/* write time */
-	md_get_uint64le(mbp, NULL);	/* change time */
-	md_get_uint32le(mbp, NULL);	/* attributes */
-	md_get_uint64le(mbp, NULL);	/* allocation size */
-	md_get_uint64le(mbp, NULL);	/* EOF */
-	md_get_uint16le(mbp, NULL);	/* file type */
-	md_get_uint16le(mbp, NULL);	/* device state */
-	md_get_uint8(mbp, NULL);	/* directory (boolean) */
-#endif
 
-	/* success! */
-	*fhp = fh;
-	error = 0;
+	/*
+	 * Do the SMB-level open with the new dev handle.
+	 */
+	bzero(&ioc, sizeof (ioc));
+	strlcpy(ioc.ioc_name, path, SMBIOC_MAX_NAME);
+	ioc.ioc_req_acc = req_acc;
+	ioc.ioc_efattr = efattr;
+	ioc.ioc_share_acc = share_acc;
+	ioc.ioc_open_disp = open_disp;
+	ioc.ioc_creat_opts = create_opts;
+	if (ioctl(new_fd, SMBIOC_NTCREATE, &ioc) == -1) {
+		err = errno;
+		goto errout;
+	}
 
-out:
-	smb_rq_done(rqp);
+	return (new_fd);
 
-	return (error);
+errout:
+	if (new_fd != -1)
+		close(new_fd);
+	errno = err;
+	return (-1);
 }
 
 /*
@@ -196,10 +130,21 @@
  * Converts Unix-style open call to NTCreate.
  */
 int
-smb_fh_open(struct smb_ctx *ctx, const char *path, int oflag, int *fhp)
+smb_fh_open(struct smb_ctx *ctx, const char *path, int oflag)
 {
-	int error, mode, open_disp, req_acc, share_acc;
+	int mode, open_disp, req_acc, share_acc;
 	char *p, *ntpath = NULL;
+	int fd = -1;
+
+	/*
+	 * Convert Unix path to NT (backslashes)
+	 */
+	ntpath = strdup(path);
+	if (ntpath == NULL)
+		return (-1);	/* errno was set */
+	for (p = ntpath; *p; p++)
+		if (*p == '/')
+			*p = '\\';
 
 	/*
 	 * Map O_RDONLY, O_WRONLY, O_RDWR
@@ -250,55 +195,43 @@
 			open_disp = NTCREATEX_DISP_OPEN;
 	}
 
-	/*
-	 * Convert Unix path to NT (backslashes)
-	 */
-	ntpath = strdup(path);
-	if (ntpath == NULL)
-		return (ENOMEM);
-	for (p = ntpath; *p; p++)
-		if (*p == '/')
-			*p = '\\';
+	fd = smb_fh_ntcreate(ctx, ntpath,
+	    req_acc, SMB_EFA_NORMAL, share_acc, open_disp,
+	    NTCREATEX_OPTIONS_NON_DIRECTORY_FILE);
 
-	error = smb_fh_ntcreate(ctx, ntpath, 0, /* flags */
-	    req_acc, SMB_EFA_NORMAL, share_acc, open_disp,
-	    NTCREATEX_OPTIONS_NON_DIRECTORY_FILE,
-	    NTCREATEX_IMPERSONATION_IMPERSONATION,
-	    fhp, NULL);
 	free(ntpath);
-
-	return (error);
+	return (fd);
 }
 
 int
-smb_fh_read(struct smb_ctx *ctx, int fh, off_t offset, size_t count,
+smb_fh_read(int fd, off_t offset, size_t count,
 	char *dst)
 {
 	struct smbioc_rw rwrq;
 
 	bzero(&rwrq, sizeof (rwrq));
-	rwrq.ioc_fh = fh;
+	rwrq.ioc_fh = -1;	/* tell driver to supply this */
 	rwrq.ioc_base = dst;
 	rwrq.ioc_cnt = count;
 	rwrq.ioc_offset = offset;
-	if (ioctl(ctx->ct_dev_fd, SMBIOC_READ, &rwrq) == -1) {
+	if (ioctl(fd, SMBIOC_READ, &rwrq) == -1) {
 		return (-1);
 	}
 	return (rwrq.ioc_cnt);
 }
 
 int
-smb_fh_write(struct smb_ctx *ctx, int fh, off_t offset, size_t count,
+smb_fh_write(int fd, off_t offset, size_t count,
 	const char *src)
 {
 	struct smbioc_rw rwrq;
 
 	bzero(&rwrq, sizeof (rwrq));
-	rwrq.ioc_fh = fh;
+	rwrq.ioc_fh = -1;	/* tell driver to supply this */
 	rwrq.ioc_base = (char *)src;
 	rwrq.ioc_cnt = count;
 	rwrq.ioc_offset = offset;
-	if (ioctl(ctx->ct_dev_fd, SMBIOC_WRITE, &rwrq) == -1) {
+	if (ioctl(fd, SMBIOC_WRITE, &rwrq) == -1) {
 		return (-1);
 	}
 	return (rwrq.ioc_cnt);
@@ -313,7 +246,7 @@
  * and on output *rdlen is the received length.
  */
 int
-smb_fh_xactnp(struct smb_ctx *ctx, int fh,
+smb_fh_xactnp(int fd,
 	int tdlen, const char *tdata,	/* transmit */
 	int *rdlen, char *rdata,	/* receive */
 	int *more)
@@ -322,10 +255,10 @@
 	uint16_t	setup[2];
 
 	setup[0] = TRANS_TRANSACT_NAMED_PIPE;
-	setup[1] = fh;
+	setup[1] = 0xFFFF; /* driver replaces this */
 	rparamcnt = 0;
 
-	err = smb_t2_request(ctx, 2, setup, "\\PIPE\\",
+	err = smb_t2_request(fd, 2, setup, "\\PIPE\\",
 	    0, NULL,	/* TX paramcnt, params */
 	    tdlen, (void *)tdata,
 	    &rparamcnt, NULL,	/* no RX params */
--- a/usr/src/lib/libsmbfs/smb/keychain.c	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/lib/libsmbfs/smb/keychain.c	Thu Jun 30 17:58:05 2011 -0400
@@ -20,6 +20,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -173,6 +174,18 @@
 	return (err);
 }
 
+/* Variant of the above that takes an NT hash. */
+int
+smbfs_keychain_addhash(uid_t uid, const char *dom, const char *usr,
+	const uchar_t *nthash)
+{
+	static const uchar_t lmhash[SMBIOC_HASH_SZ] = { 0 };
+	int err, cmd = SMBIOC_PK_ADD;
+	err = smbfs_keychain_cmn(cmd, uid, dom, usr,
+	    (uchar_t *)lmhash, (uchar_t *)nthash);
+	return (err);
+}
+
 /* Delete a password from the keychain. */
 int
 smbfs_keychain_del(uid_t uid, const char *dom, const char *usr)
--- a/usr/src/lib/libsmbfs/smb/mapfile-vers	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/lib/libsmbfs/smb/mapfile-vers	Thu Jun 30 17:58:05 2011 -0400
@@ -18,6 +18,7 @@
 # CDDL HEADER END
 #
 #
+# Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
 # Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
 #
 
@@ -66,7 +67,6 @@
 	smb_ctx_flags2;
 	smb_ctx_free;
 	smb_ctx_get_ssn;
-	smb_ctx_get_ssnkey;
 	smb_ctx_get_tree;
 	smb_ctx_gethandle;
 	smb_ctx_init;
@@ -97,6 +97,7 @@
 #
 # Functions to support named pipes
 	smb_fh_close;
+	smb_fh_getssnkey;
 	smb_fh_open;
 	smb_fh_read;
 	smb_fh_write;
@@ -111,9 +112,8 @@
 	smb_iod_work;
 	smb_lib_init;
 	smb_netshareenum;	# will move to libnetapi
+	smb_open_printer;
 	smb_open_rcfile;
-	smb_printer_open;
-	smb_printer_close;
 	smb_simplecrypt;
 	smb_simpledecrypt;
 	smb_strerror;
@@ -141,11 +141,15 @@
 #
 	smbfs_default_dom_usr;
 	smbfs_keychain_add;
+	smbfs_keychain_addhash;
 	smbfs_keychain_chk;
 	smbfs_keychain_del;
 	smbfs_keychain_del_everyone;
 	smbfs_keychain_del_owner;
 
+	smbfs_set_default_domain;
+	smbfs_set_default_user;
+
 	smbutil_std_opts;
     local:
 	*;
--- a/usr/src/lib/libsmbfs/smb/print.c	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/lib/libsmbfs/smb/print.c	Thu Jun 30 17:58:05 2011 -0400
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2000, Boris Popov
  * All rights reserved.
  *
@@ -41,82 +42,61 @@
 #include <errno.h>
 #include <stdio.h>
 #include <string.h>
+#include <strings.h>
 #include <stdlib.h>
 #include <pwd.h>
 #include <grp.h>
 #include <unistd.h>
+#include <libintl.h>
 
 #include <netsmb/smb.h>
 #include <netsmb/smb_lib.h>
+
 #include "private.h"
 
 int
-smb_printer_open(struct smb_ctx *ctx, int setuplen, int mode,
-	const char *ident, int *fhp)
+smb_open_printer(struct smb_ctx *ctx, const char *title,
+	int setuplen, int mode)
 {
-	struct smb_rq *rqp;
-	struct mbdata *mbp;
-	int error, flags2, uc;
-	uint16_t fh;
-	uint8_t wc;
-
-	flags2 = smb_ctx_flags2(ctx);
-	if (flags2 == -1)
-		return (EIO);
-	uc = flags2 & SMB_FLAGS2_UNICODE;
+	smbioc_printjob_t ioc;
+	int err, tlen, new_fd;
+	int32_t from_fd;
 
-	error = smb_rq_init(ctx, SMB_COM_OPEN_PRINT_FILE, &rqp);
-	if (error)
-		return (error);
-	mbp = smb_rq_getrequest(rqp);
-	smb_rq_wstart(rqp);
-	mb_put_uint16le(mbp, setuplen);
-	mb_put_uint16le(mbp, mode);
-	smb_rq_wend(rqp);
-	smb_rq_bstart(rqp);
-	mb_put_uint8(mbp, SMB_DT_ASCII);
-	mb_put_string(mbp, ident, uc);
-	smb_rq_bend(rqp);
-	error = smb_rq_simple(rqp);
-	if (error)
-		goto out;
+	tlen = strlen(title);
+	if (tlen >= SMBIOC_MAX_NAME)
+		return (EINVAL);
 
-	mbp = smb_rq_getreply(rqp);
-	error = md_get_uint8(mbp, &wc);
-	if (error || wc < 1) {
-		error = EBADRPC;
-		goto out;
+	/*
+	 * Will represent this SMB-level open as a new
+	 * open device handle.  Get one, then duplicate
+	 * the driver session and tree bindings.
+	 */
+	new_fd = smb_open_driver();
+	if (new_fd < 0)
+		return (errno);
+	from_fd = ctx->ct_dev_fd;
+	if (ioctl(new_fd, SMBIOC_DUP_DEV, &from_fd) == -1) {
+		err = errno;
+		goto errout;
 	}
-	md_get_uint16le(mbp, &fh);
-	*fhp = fh;
-	error = 0;
-
-out:
-	smb_rq_done(rqp);
-	return (error);
-}
 
-/*
- * Similar to smb_fh_close
- */
-int
-smb_printer_close(struct smb_ctx *ctx, int fh)
-{
-	struct smb_rq *rqp;
-	struct mbdata *mbp;
-	int error;
+	/*
+	 * Do the SMB-level open with the new dev handle.
+	 */
+	bzero(&ioc, sizeof (ioc));
+	ioc.ioc_setuplen = setuplen;
+	ioc.ioc_prmode = mode;
+	strlcpy(ioc.ioc_title, title, SMBIOC_MAX_NAME);
 
-	error = smb_rq_init(ctx, SMB_COM_CLOSE_PRINT_FILE, &rqp);
-	if (error)
-		return (error);
-	mbp = smb_rq_getrequest(rqp);
-	smb_rq_wstart(rqp);
-	mb_put_uint16le(mbp, (uint16_t)fh);
-	smb_rq_wend(rqp);
-	mb_put_uint16le(mbp, 0);	/* byte count */
+	if (ioctl(new_fd, SMBIOC_PRINTJOB, &ioc) == -1) {
+		err = errno;
+		goto errout;
+	}
 
-	error = smb_rq_simple(rqp);
-	smb_rq_done(rqp);
+	return (new_fd);
 
-	return (error);
+errout:
+	close(new_fd);
+	errno = err;
+	return (-1);
 }
--- a/usr/src/lib/libsmbfs/smb/private.h	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/lib/libsmbfs/smb/private.h	Thu Jun 30 17:58:05 2011 -0400
@@ -31,6 +31,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -110,6 +111,8 @@
 int  smb_rq_internal(struct smb_ctx *, struct smb_rq *);
 void smb_rq_sign(struct smb_rq *);
 int  smb_rq_verify(struct smb_rq *);
+int  smb_t2_request(int, int, uint16_t *, const char *,
+	int, void *, int, void *, int *, void *, int *, void *, int *);
 
 /*
  * This library extends the mchain.h function set a little.
@@ -170,6 +173,8 @@
 int smb_ctx_getaddr(struct smb_ctx *ctx);
 int smb_ctx_gethandle(struct smb_ctx *ctx);
 
+int  smb_iod_start(struct smb_ctx *);
+
 int smb_ssn_send(struct smb_ctx *, struct mbdata *);
 int smb_ssn_recv(struct smb_ctx *, struct mbdata *);
 
--- a/usr/src/lib/libsmbfs/smb/rap.c	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/lib/libsmbfs/smb/rap.c	Thu Jun 30 17:58:05 2011 -0400
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2000, Boris Popov
  * All rights reserved.
  *
@@ -334,7 +335,8 @@
 
 	rdatacnt = rap->r_rcvbuflen;
 	rparamcnt = rap->r_plen;
-	error = smb_t2_request(ctx, 0, NULL, "\\PIPE\\LANMAN",
+	error = smb_t2_request(ctx->ct_dev_fd,
+	    0, NULL, "\\PIPE\\LANMAN",
 	    rap->r_plen, rap->r_pbuf,		/* int tparamcnt,void *tparam */
 	    0, NULL,				/* int tdatacnt, void *tdata */
 	    &rparamcnt, rap->r_pbuf,		/* rparamcnt, void *rparam */
--- a/usr/src/lib/libsmbfs/smb/rq.c	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/lib/libsmbfs/smb/rq.c	Thu Jun 30 17:58:05 2011 -0400
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2000, Boris Popov
  * All rights reserved.
  *
@@ -279,7 +280,7 @@
 
 
 int
-smb_t2_request(struct smb_ctx *ctx, int setupcount, uint16_t *setup,
+smb_t2_request(int dev_fd, int setupcount, uint16_t *setup,
 	const char *name,
 	int tparamcnt, void *tparam,
 	int tdatacnt, void *tdata,
@@ -311,7 +312,7 @@
 	krq->ioc_rparam = rparam;
 	krq->ioc_rdata  = rdata;
 
-	if (ioctl(ctx->ct_dev_fd, SMBIOC_T2RQ, krq) == -1) {
+	if (ioctl(dev_fd, SMBIOC_T2RQ, krq) == -1) {
 		return (errno);
 	}
 
--- a/usr/src/uts/common/fs/smbclnt/netsmb/offsets.in	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/offsets.in	Thu Jun 30 17:58:05 2011 -0400
@@ -20,6 +20,7 @@
 \
 
 \
+\ Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
 \ Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 \ Use is subject to license terms.
 \
@@ -57,11 +58,10 @@
 	ssn_srvname
 
 smbioc_oshare
-	sh_pwlen
+	sh_use
+	sh_type
 	sh_name
 	sh_pass
-	sh_type_req
-	sh_type_ret
 
 smbioc_tcon
 	tc_flags
@@ -114,7 +114,7 @@
 smbioc_t2rq	SIZEOF_SMBIOC_T2RQ
 	ioc_setup
 	ioc_setupcnt
-	ioc_name
+	ioc_name	IOC_T2_NAME
 	ioc_tparamcnt
 	ioc_tdatacnt
 	ioc_rparamcnt
@@ -139,6 +139,19 @@
 	_ioc_offset
 	_ioc_base
 
+smbioc_ntcreate	SIZEOF_NTCREATE
+	ioc_req_acc
+	ioc_efattr
+	ioc_share_acc
+	ioc_open_disp
+	ioc_creat_opts
+	ioc_name	IOC_NTCR_NAME
+
+smbioc_printjob		SIZEOF_PRINTJOB
+	ioc_setuplen
+	ioc_prmode
+	ioc_title
+
 smbioc_pk	SIZEOF_SMBIOC_PK
 	pk_uid
 	pk_dom
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h	Thu Jun 30 17:58:05 2011 -0400
@@ -33,6 +33,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -236,11 +237,10 @@
 #define	ss_lock		ss_co.co_lock
 #define	ss_flags	ss_co.co_flags
 
+#define	ss_use		ss_ioc.sh_use
+#define	ss_type		ss_ioc.sh_type
 #define	ss_name		ss_ioc.sh_name
-#define	ss_pwlen	ss_ioc.sh_pwlen
 #define	ss_pass		ss_ioc.sh_pass
-#define	ss_type_req	ss_ioc.sh_type_req
-#define	ss_type_ret	ss_ioc.sh_type_ret
 
 #define	SMB_SS_LOCK(ssp)	mutex_enter(&(ssp)->ss_lock)
 #define	SMB_SS_UNLOCK(ssp)	mutex_exit(&(ssp)->ss_lock)
@@ -275,20 +275,19 @@
  * Mostly used in: smb_dev.c, smb_usr.c
  */
 typedef struct smb_dev {
-	int		sd_opened;	/* Opened or not */
-	int		sd_level;	/* Future use */
+	dev_info_t	*sd_dip;	/* ptr to dev_info node */
+	struct cred	*sd_cred;	/* per dev credentails */
 	struct smb_vc	*sd_vc;		/* Reference to VC */
 	struct smb_share *sd_share;	/* Reference to share if any */
+	int		sd_level;	/* SMBL_VC, ... */
 	int		sd_vcgenid;	/* Generation of share or VC */
 	int		sd_poll;	/* Future use */
 	int		sd_seq;		/* Kind of minor number/instance no */
 	int		sd_flags;	/* State of connection */
 #define	NSMBFL_OPEN		0x0001
 #define	NSMBFL_IOD		0x0002
+	int		sd_smbfid;	/* library read/write */
 	zoneid_t	zoneid;		/* Zone id */
-	dev_info_t	*smb_dip;	/* ptr to dev_info node */
-	void		*sd_devfs;	/* Dont know how to use this. but */
-	struct cred	*smb_cred;	/* per dev credentails. Future use */
 } smb_dev_t;
 
 extern const uint32_t nsmb_version;
@@ -304,10 +303,15 @@
  */
 int smb_usr_get_flags2(smb_dev_t *sdp, intptr_t arg, int flags);
 int smb_usr_get_ssnkey(smb_dev_t *sdp, intptr_t arg, int flags);
+int smb_usr_dup_dev(smb_dev_t *sdp, intptr_t arg, int flags);
 
 int smb_usr_simplerq(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr);
 int smb_usr_t2request(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr);
+
+int smb_usr_closefh(smb_dev_t *, cred_t *);
 int smb_usr_rw(smb_dev_t *sdp, int cmd, intptr_t arg, int flags, cred_t *cr);
+int smb_usr_ntcreate(smb_dev_t *, intptr_t, int, cred_t *);
+int smb_usr_printjob(smb_dev_t *, intptr_t, int, cred_t *);
 
 int smb_usr_get_ssn(smb_dev_t *, int, intptr_t, int, cred_t *);
 int smb_usr_drop_ssn(smb_dev_t *sdp, int cmd);
@@ -378,14 +382,4 @@
 void smb_share_invalidate(smb_share_t *ssp);
 int  smb_share_tcon(smb_share_t *, smb_cred_t *);
 
-/*
- * SMB protocol level functions
- */
-int  smb_smb_echo(smb_vc_t *vcp, smb_cred_t *scred, int timo);
-int  smb_smb_treeconnect(smb_share_t *ssp, smb_cred_t *scred);
-int  smb_smb_treedisconnect(smb_share_t *ssp, smb_cred_t *scred);
-
-int smb_rwuio(smb_share_t *ssp, uint16_t fid, uio_rw_t rw,
-	uio_t *uiop, smb_cred_t *scred, int timo);
-
 #endif /* _SMB_CONN_H */
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c	Thu Jun 30 17:58:05 2011 -0400
@@ -33,6 +33,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -317,14 +318,9 @@
 		goto attach_failed;
 	}
 
-	/*
-	 * Need to see if this field is required.
-	 * REVISIT
-	 */
-	sdp->smb_dip = dip;
+	sdp->sd_dip = dip;
 	sdp->sd_seq = 0;
-	sdp->sd_opened = 1;
-
+	sdp->sd_smbfid = -1;
 	mutex_exit(&dev_lck);
 	ddi_report_dev(dip);
 	return (DDI_SUCCESS);
@@ -397,6 +393,10 @@
 		err = smb_usr_get_ssnkey(sdp, arg, flags);
 		break;
 
+	case SMBIOC_DUP_DEV:
+		err = smb_usr_dup_dev(sdp, arg, flags);
+		break;
+
 	case SMBIOC_REQUEST:
 		err = smb_usr_simplerq(sdp, arg, flags, cr);
 		break;
@@ -410,6 +410,18 @@
 		err = smb_usr_rw(sdp, cmd, arg, flags, cr);
 		break;
 
+	case SMBIOC_NTCREATE:
+		err = smb_usr_ntcreate(sdp, arg, flags, cr);
+		break;
+
+	case SMBIOC_PRINTJOB:
+		err = smb_usr_printjob(sdp, arg, flags, cr);
+		break;
+
+	case SMBIOC_CLOSEFH:
+		err = smb_usr_closefh(sdp, cr);
+		break;
+
 	case SMBIOC_SSN_CREATE:
 	case SMBIOC_SSN_FIND:
 		err = smb_usr_get_ssn(sdp, cmd, arg, flags, cr);
@@ -523,9 +535,9 @@
 		return (ENXIO);
 	}
 
-	sdp->sd_opened = 1;
 	sdp->sd_seq = nsmb_minor;
-	sdp->smb_cred = cr;
+	sdp->sd_cred = cr;
+	sdp->sd_smbfid = -1;
 	sdp->sd_flags |= NSMBFL_OPEN;
 	sdp->zoneid = crgetzoneid(cr);
 	mutex_exit(&dev_lck);
@@ -570,12 +582,14 @@
 {
 	struct smb_vc *vcp;
 	struct smb_share *ssp;
-	struct smb_cred scred;
 
-	smb_credinit(&scred, cr);
+	if (sdp->sd_smbfid != -1)
+		(void) smb_usr_closefh(sdp, cr);
+
 	ssp = sdp->sd_share;
 	if (ssp != NULL)
 		smb_share_rele(ssp);
+
 	vcp = sdp->sd_vc;
 	if (vcp != NULL) {
 		/*
@@ -588,10 +602,69 @@
 		smb_vc_rele(vcp);
 	}
 
-	smb_credrele(&scred);
 	return (0);
 }
 
+/*
+ * Helper for SMBIOC_DUP_DEV
+ * Duplicate state from the FD @arg ("from") onto
+ * the FD for this device instance.
+ */
+int
+smb_usr_dup_dev(smb_dev_t *sdp, intptr_t arg, int flags)
+{
+	file_t *fp = NULL;
+	vnode_t *vp;
+	smb_dev_t *from_sdp;
+	dev_t dev;
+	int32_t ufd;
+	int err;
+
+	/* Should be no VC */
+	if (sdp->sd_vc != NULL)
+		return (EISCONN);
+
+	/*
+	 * Get from_sdp (what we will duplicate)
+	 */
+	if (ddi_copyin((void *) arg, &ufd, sizeof (ufd), flags))
+		return (EFAULT);
+	if ((fp = getf(ufd)) == NULL)
+		return (EBADF);
+	/* rele fp below */
+	vp = fp->f_vnode;
+	dev = vp->v_rdev;
+	if (dev == 0 || dev == NODEV ||
+	    getmajor(dev) != nsmb_major) {
+		err = EINVAL;
+		goto out;
+	}
+	from_sdp = ddi_get_soft_state(statep, getminor(dev));
+	if (from_sdp == NULL) {
+		err = EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Duplicate VC and share references onto this FD.
+	 */
+	if ((sdp->sd_vc = from_sdp->sd_vc) != NULL)
+		smb_vc_hold(sdp->sd_vc);
+	if ((sdp->sd_share = from_sdp->sd_share) != NULL)
+		smb_share_hold(sdp->sd_share);
+	sdp->sd_level = from_sdp->sd_level;
+	err = 0;
+
+out:
+	if (fp)
+		releasef(ufd);
+	return (err);
+}
+
+
+/*
+ * Helper used by smbfs_mount
+ */
 int
 smb_dev2share(int fd, struct smb_share **sspp)
 {
@@ -604,12 +677,13 @@
 
 	if ((fp = getf(fd)) == NULL)
 		return (EBADF);
+	/* rele fp below */
 
 	vp = fp->f_vnode;
 	dev = vp->v_rdev;
 	if (dev == 0 || dev == NODEV ||
 	    getmajor(dev) != nsmb_major) {
-		err = EBADF;
+		err = EINVAL;
 		goto out;
 	}
 
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c	Thu Jun 30 17:58:05 2011 -0400
@@ -33,6 +33,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
@@ -58,6 +59,8 @@
 #include <netsmb/smb_subr.h>
 #include <netsmb/smb_tran.h>
 
+#define	STYPE_LEN	8	/* share type strings */
+
 /*
  * Largest size to use with LARGE_READ/LARGE_WRITE.
  * Specs say up to 64k data bytes, but Windows traffic
@@ -88,6 +91,64 @@
 static int smb_smb_writex(struct smb_share *ssp, uint16_t fid,
 	uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
 
+/*
+ * Get the string representation of a share "use" type,
+ * as needed for the "service" in tree connect.
+ */
+static const char *
+smb_share_typename(uint32_t stype)
+{
+	const char *p;
+
+	switch (stype) {
+	case STYPE_DISKTREE:
+		p = "A:";
+		break;
+	case STYPE_PRINTQ:
+		p = "LPT1:";
+		break;
+	case STYPE_DEVICE:
+		p = "COMM";
+		break;
+	case STYPE_IPC:
+		p = "IPC";
+		break;
+	case STYPE_UNKNOWN:
+	default:
+		p = "?????";
+		break;
+	}
+	return (p);
+}
+
+/*
+ * Parse a share type name (inverse of above)
+ */
+static uint32_t
+smb_share_parsetype(char *name)
+{
+	int stype;
+
+	switch (*name) {
+	case 'A':	/* A: */
+		stype = STYPE_DISKTREE;
+		break;
+	case 'C':	/* COMM */
+		stype = STYPE_DEVICE;
+		break;
+	case 'I':	/* IPC */
+		stype = STYPE_IPC;
+		break;
+	case 'L':	/* LPT: */
+		stype = STYPE_PRINTQ;
+		break;
+	default:
+		stype = STYPE_UNKNOWN;
+		break;
+	}
+	return (stype);
+}
+
 int
 smb_smb_treeconnect(struct smb_share *ssp, struct smb_cred *scred)
 {
@@ -95,10 +156,12 @@
 	struct smb_rq *rqp = NULL;
 	struct mbchain *mbp;
 	struct mdchain *mdp;
+	const char *tname;
 	char *pbuf, *unc_name = NULL;
 	int error, tlen, plen, unc_len;
 	uint16_t bcnt, options;
 	uint8_t wc;
+	char stype_str[STYPE_LEN];
 
 	vcp = SSTOVC(ssp);
 
@@ -127,12 +190,14 @@
 	    vcp->vc_srvname, ssp->ss_name);
 	SMBSDEBUG("unc_name: \"%s\"", unc_name);
 
+
 	/*
-	 * The password is now pre-computed in the
-	 * user-space helper process.
+	 * Share-level password (pre-computed in user-space)
+	 * MS-SMB 2.2.6 says this should be null terminated,
+	 * and the pw length includes the null.
 	 */
-	plen = ssp->ss_pwlen;
 	pbuf = ssp->ss_pass;
+	plen = strlen(pbuf) + 1;
 
 	/*
 	 * Build the request.
@@ -161,8 +226,9 @@
 	 * Put the type string (always ASCII),
 	 * including the null.
 	 */
-	tlen = strlen(ssp->ss_type_req) + 1;
-	error = mb_put_mem(mbp, ssp->ss_type_req, tlen, MB_MSYSTEM);
+	tname = smb_share_typename(ssp->ss_use);
+	tlen = strlen(tname) + 1;
+	error = mb_put_mem(mbp, tname, tlen, MB_MSYSTEM);
 	if (error)
 		goto out;
 
@@ -210,15 +276,17 @@
 		goto out;
 
 	/*
-	 * Get the returned share type string,
-	 * i.e. "IPC" or whatever.   Don't care
-	 * if we get an error reading the type.
+	 * Get the returned share type string, i.e. "IPC" or whatever.
+	 * (See smb_share_typename, smb_share_parsetype).  If we get
+	 * an error reading the type, just say STYPE_UNKNOWN.
 	 */
-	tlen = sizeof (ssp->ss_type_ret);
-	bzero(ssp->ss_type_ret, tlen--);
+	tlen = STYPE_LEN;
+	bzero(stype_str, tlen--);
 	if (tlen > bcnt)
 		tlen = bcnt;
-	md_get_mem(mdp, ssp->ss_type_ret, tlen, MB_MSYSTEM);
+	md_get_mem(mdp, stype_str, tlen, MB_MSYSTEM);
+	stype_str[tlen] = '\0';
+	ssp->ss_type = smb_share_parsetype(stype_str);
 
 	/* Success! */
 	SMB_SS_LOCK(ssp);
@@ -281,6 +349,258 @@
 }
 
 /*
+ * Modern create/open of file or directory.
+ */
+int
+smb_smb_ntcreate(
+	struct smb_share *ssp,
+	struct mbchain	*name_mb,
+	uint32_t cr_flags,	/* create flags */
+	uint32_t req_acc,	/* requested access */
+	uint32_t efa,		/* ext. file attrs (DOS attr +) */
+	uint32_t share_acc,
+	uint32_t open_disp,	/* open disposition */
+	uint32_t createopt,	/* NTCREATEX_OPTIONS_ */
+	uint32_t impersonate,	/* NTCREATEX_IMPERSONATION_... */
+	struct smb_cred *scrp,
+	uint16_t *fidp,		/* returned FID */
+	uint32_t *cr_act_p,	/* optional create action */
+	struct smbfattr *fap)	/* optional attributes */
+{
+	struct smb_rq rq, *rqp = &rq;
+	struct smb_vc *vcp = SSTOVC(ssp);
+	struct mbchain *mbp;
+	struct mdchain *mdp;
+	struct smbfattr fa;
+	uint64_t llongint;
+	uint32_t longint, createact;
+	uint16_t fid;
+	uint8_t wc;
+	int error;
+
+	bzero(&fa, sizeof (fa));
+	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_NT_CREATE_ANDX, scrp);
+	if (error)
+		return (error);
+	smb_rq_getrequest(rqp, &mbp);
+
+	/* Word parameters */
+	smb_rq_wstart(rqp);
+	mb_put_uint8(mbp, 0xff);	/* secondary command */
+	mb_put_uint8(mbp, 0);		/* MBZ */
+	mb_put_uint16le(mbp, 0);	/* offset to next command (none) */
+	mb_put_uint8(mbp, 0);		/* MBZ */
+	mb_put_uint16le(mbp, name_mb->mb_count);
+	mb_put_uint32le(mbp, cr_flags);	/* NTCREATEX_FLAGS_* */
+	mb_put_uint32le(mbp, 0);	/* FID - basis for path if not root */
+	mb_put_uint32le(mbp, req_acc);
+	mb_put_uint64le(mbp, 0);	/* "initial allocation size" */
+	mb_put_uint32le(mbp, efa);
+	mb_put_uint32le(mbp, share_acc);
+	mb_put_uint32le(mbp, open_disp);
+	mb_put_uint32le(mbp, createopt);
+	mb_put_uint32le(mbp, impersonate);
+	mb_put_uint8(mbp, 0);   /* security flags (?) */
+	smb_rq_wend(rqp);
+
+	/*
+	 * Byte parameters: Just the path name, aligned.
+	 * Note: mb_put_mbuf consumes mb_top, so clear it.
+	 */
+	smb_rq_bstart(rqp);
+	if (SMB_UNICODE_STRINGS(vcp))
+		mb_put_padbyte(mbp);
+	mb_put_mbuf(mbp, name_mb->mb_top);
+	bzero(name_mb, sizeof (*name_mb));
+	smb_rq_bend(rqp);
+
+	/*
+	 * Don't want to risk missing a successful
+	 * open response, or we could "leak" FIDs.
+	 */
+	rqp->sr_flags |= SMBR_NOINTR_RECV;
+	error = smb_rq_simple_timed(rqp, smb_timo_open);
+	if (error)
+		goto done;
+	smb_rq_getreply(rqp, &mdp);
+	/*
+	 * spec says 26 for word count, but 34 words are defined
+	 * and observed from win2000
+	 */
+	error = md_get_uint8(mdp, &wc);
+	if (error)
+		goto done;
+	if (wc != 26 && wc < 34) {
+		error = EBADRPC;
+		goto done;
+	}
+	md_get_uint8(mdp, NULL);		/* secondary cmd */
+	md_get_uint8(mdp, NULL);		/* mbz */
+	md_get_uint16le(mdp, NULL);		/* andxoffset */
+	md_get_uint8(mdp, NULL);		/* oplock lvl granted */
+	md_get_uint16le(mdp, &fid);		/* file ID */
+	md_get_uint32le(mdp, &createact);	/* create_action */
+
+	md_get_uint64le(mdp, &llongint);	/* creation time */
+	smb_time_NT2local(llongint, &fa.fa_createtime);
+	md_get_uint64le(mdp, &llongint);	/* access time */
+	smb_time_NT2local(llongint, &fa.fa_atime);
+	md_get_uint64le(mdp, &llongint);	/* write time */
+	smb_time_NT2local(llongint, &fa.fa_mtime);
+	md_get_uint64le(mdp, &llongint);	/* change time */
+	smb_time_NT2local(llongint, &fa.fa_ctime);
+
+	md_get_uint32le(mdp, &longint);		/* attributes */
+	fa.fa_attr = longint;
+	md_get_uint64le(mdp, &llongint);	/* allocation size */
+	fa.fa_allocsz = llongint;
+	md_get_uint64le(mdp, &llongint);	/* EOF position */
+	fa.fa_size = llongint;
+
+	error = md_get_uint16le(mdp, NULL);	/* file type */
+	/* other stuff we don't care about */
+
+done:
+	smb_rq_done(rqp);
+	if (error)
+		return (error);
+
+	*fidp = fid;
+	if (cr_act_p)
+		*cr_act_p = createact;
+	if (fap)
+		*fap = fa; /* struct copy */
+
+	return (0);
+}
+
+int
+smb_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime,
+	struct smb_cred *scrp)
+{
+	struct smb_rq rq, *rqp = &rq;
+	struct mbchain *mbp;
+	long time;
+	int error;
+
+	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scrp);
+	if (error)
+		return (error);
+	smb_rq_getrequest(rqp, &mbp);
+	smb_rq_wstart(rqp);
+	mb_put_uint16le(mbp, fid);
+	if (mtime) {
+		int sv_tz = SSTOVC(ssp)->vc_sopt.sv_tz;
+		smb_time_local2server(mtime, sv_tz, &time);
+	} else {
+		time = 0;
+	}
+	mb_put_uint32le(mbp, time);
+	smb_rq_wend(rqp);
+	smb_rq_bstart(rqp);
+	smb_rq_bend(rqp);
+
+	/* Make sure we send it... */
+	rqp->sr_flags |= SMBR_NOINTR_SEND;
+	error = smb_rq_simple(rqp);
+	smb_rq_done(rqp);
+	return (error);
+}
+
+int
+smb_smb_open_prjob(
+	struct smb_share *ssp,
+	char	*title,
+	uint16_t setuplen,
+	uint16_t mode,
+	struct smb_cred *scrp,
+	uint16_t *fidp)
+{
+	struct smb_rq rq, *rqp = &rq;
+	struct smb_vc *vcp = SSTOVC(ssp);
+	struct mbchain *mbp;
+	struct mdchain *mdp;
+	uint16_t fid;
+	uint8_t wc;
+	int error;
+
+	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_OPEN_PRINT_FILE, scrp);
+	if (error)
+		return (error);
+	smb_rq_getrequest(rqp, &mbp);
+
+	/* Word parameters */
+	smb_rq_wstart(rqp);
+	mb_put_uint16le(mbp, setuplen);
+	mb_put_uint16le(mbp, mode);
+	smb_rq_wend(rqp);
+
+	/*
+	 * Byte parameters: Just the title
+	 */
+	smb_rq_bstart(rqp);
+	mb_put_uint8(mbp, SMB_DT_ASCII);
+	error = smb_put_dstring(mbp, vcp, title, SMB_CS_NONE);
+	smb_rq_bend(rqp);
+	if (error)
+		goto done;
+
+	/*
+	 * Don't want to risk missing a successful
+	 * open response, or we could "leak" FIDs.
+	 */
+	rqp->sr_flags |= SMBR_NOINTR_RECV;
+	error = smb_rq_simple_timed(rqp, smb_timo_open);
+	if (error)
+		goto done;
+
+	smb_rq_getreply(rqp, &mdp);
+	error = md_get_uint8(mdp, &wc);
+	if (error || wc < 1) {
+		error = EBADRPC;
+		goto done;
+	}
+	error = md_get_uint16le(mdp, &fid);
+
+done:
+	smb_rq_done(rqp);
+	if (error)
+		return (error);
+
+	*fidp = fid;
+	return (0);
+}
+
+/*
+ * Like smb_smb_close, but for print shares.
+ */
+int
+smb_smb_close_prjob(struct smb_share *ssp, uint16_t fid,
+	struct smb_cred *scrp)
+{
+	struct smb_rq rq, *rqp = &rq;
+	struct mbchain *mbp;
+	int error;
+
+	error = smb_rq_init(rqp, SSTOCP(ssp),
+	    SMB_COM_CLOSE_PRINT_FILE, scrp);
+	if (error)
+		return (error);
+	smb_rq_getrequest(rqp, &mbp);
+	smb_rq_wstart(rqp);
+	mb_put_uint16le(mbp, fid);
+	smb_rq_wend(rqp);
+	smb_rq_bstart(rqp);
+	smb_rq_bend(rqp);
+
+	/* Make sure we send it... */
+	rqp->sr_flags |= SMBR_NOINTR_SEND;
+	error = smb_rq_simple(rqp);
+	smb_rq_done(rqp);
+	return (error);
+}
+
+/*
  * Common function for read/write with UIO.
  * Called by netsmb smb_usr_rw,
  *  smbfs_readvnode, smbfs_writevnode
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_subr.h	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_subr.h	Thu Jun 30 17:58:05 2011 -0400
@@ -33,6 +33,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
@@ -42,6 +43,7 @@
 #include <sys/cmn_err.h>
 #include <sys/lock.h>
 #include <sys/note.h>
+#include <netsmb/smb_conn.h>
 
 /* Helper function for SMBERROR */
 /*PRINTFLIKE3*/
@@ -84,6 +86,27 @@
 struct smb_vc;
 
 /*
+ * These are the attributes we can get from the server via
+ * SMB commands such as TRANS2_QUERY_FILE_INFORMATION
+ * with info level SMB_QFILEINFO_ALL_INFO, and directory
+ * FindFirst/FindNext info. levels FIND_DIRECTORY_INFO
+ * and FIND_BOTH_DIRECTORY_INFO, etc.
+ *
+ * Values in this struct are always native endian,
+ * and times are converted converted to Unix form.
+ * Note: zero in any of the times means "unknown".
+ */
+typedef struct smbfattr {
+	timespec_t	fa_createtime;	/* Note, != ctime */
+	timespec_t	fa_atime;	/* these 3 are like unix */
+	timespec_t	fa_mtime;
+	timespec_t	fa_ctime;
+	u_offset_t	fa_size;	/* EOF position */
+	u_offset_t	fa_allocsz;	/* Allocated size. */
+	uint32_t	fa_attr;	/* Ext. file (DOS) attr */
+} smbfattr_t;
+
+/*
  * Tunable timeout values.  See: smb_smb.c
  */
 extern int smb_timo_notice;
@@ -129,6 +152,39 @@
 	const uchar_t *, size_t);
 void smb_crypto_mech_init(void);
 
+
+/*
+ * SMB protocol level functions
+ */
+int  smb_smb_echo(smb_vc_t *vcp, smb_cred_t *scred, int timo);
+int  smb_smb_treeconnect(smb_share_t *ssp, smb_cred_t *scred);
+int  smb_smb_treedisconnect(smb_share_t *ssp, smb_cred_t *scred);
+
+int
+smb_smb_ntcreate(struct smb_share *ssp, struct mbchain *name_mb,
+	uint32_t crflag, uint32_t req_acc, uint32_t efa, uint32_t sh_acc,
+	uint32_t disp, uint32_t createopt,  uint32_t impersonate,
+	struct smb_cred *scrp, uint16_t *fidp,
+	uint32_t *cr_act_p, struct smbfattr *fap);
+
+int  smb_smb_close(struct smb_share *ssp, uint16_t fid,
+	struct timespec *mtime, struct smb_cred *scrp);
+
+int
+smb_smb_open_prjob(struct smb_share *ssp, char *title,
+	uint16_t setuplen, uint16_t mode,
+	struct smb_cred *scrp, uint16_t *fidp);
+
+int  smb_smb_close_prjob(struct smb_share *ssp, uint16_t fid,
+	struct smb_cred *scrp);
+
+int smb_rwuio(smb_share_t *ssp, uint16_t fid, uio_rw_t rw,
+	uio_t *uiop, smb_cred_t *scred, int timo);
+
+/*
+ * time conversions
+ */
+
 void smb_time_init(void);
 void smb_time_fini(void);
 
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_usr.c	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_usr.c	Thu Jun 30 17:58:05 2011 -0400
@@ -33,6 +33,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -199,8 +200,7 @@
 out:
 	if (rqp != NULL)
 		smb_rq_done(rqp); /* free rqp */
-	if (ioc != NULL)
-		kmem_free(ioc, sizeof (*ioc));
+	kmem_free(ioc, sizeof (*ioc));
 	smb_credrele(&scred);
 
 	return (err);
@@ -239,14 +239,24 @@
 		goto out;
 	}
 
+	/*
+	 * Fill in the FID for libsmbfs transact named pipe.
+	 */
+	if (ioc->ioc_setupcnt > 1 && ioc->ioc_setup[1] == 0xFFFF) {
+		if (sdp->sd_vcgenid != ssp->ss_vcgenid) {
+			err = ESTALE;
+			goto out;
+		}
+		ioc->ioc_setup[1] = (uint16_t)sdp->sd_smbfid;
+	}
+
 	t2p = kmem_alloc(sizeof (*t2p), KM_SLEEP);
 	err = smb_t2_init(t2p, SSTOCP(ssp),
 	    ioc->ioc_setup, ioc->ioc_setupcnt, &scred);
 	if (err)
 		goto out;
-	len = t2p->t2_setupcount = ioc->ioc_setupcnt;
-	if (len > 1)
-		t2p->t2_setupdata = ioc->ioc_setup;
+	t2p->t2_setupcount = ioc->ioc_setupcnt;
+	t2p->t2_setupdata  = ioc->ioc_setup;
 
 	/* This ioc member is a fixed-size array. */
 	if (ioc->ioc_name[0]) {
@@ -319,8 +329,7 @@
 		smb_t2_done(t2p);
 		kmem_free(t2p, sizeof (*t2p));
 	}
-	if (ioc != NULL)
-		kmem_free(ioc, sizeof (*ioc));
+	kmem_free(ioc, sizeof (*ioc));
 	smb_credrele(&scred);
 
 	return (err);
@@ -352,7 +361,7 @@
 	smbioc_rw_t *ioc = NULL;
 	struct iovec aiov[1];
 	struct uio  auio;
-	u_int16_t fh;
+	uint16_t fh;
 	int err;
 	uio_rw_t rw;
 
@@ -383,7 +392,14 @@
 		goto out;
 	}
 
-	fh = ioc->ioc_fh;
+	/*
+	 * If caller passes -1 in ioc_fh, then
+	 * use the FID from SMBIOC_NTCREATE.
+	 */
+	if (ioc->ioc_fh == -1)
+		fh = (uint16_t)sdp->sd_smbfid;
+	else
+		fh = (uint16_t)ioc->ioc_fh;
 
 	aiov[0].iov_base = ioc->ioc_base;
 	aiov[0].iov_len = (size_t)ioc->ioc_cnt;
@@ -407,8 +423,154 @@
 	(void) ddi_copyout(ioc, (void *)arg, sizeof (*ioc), flags);
 
 out:
-	if (ioc != NULL)
-		kmem_free(ioc, sizeof (*ioc));
+	kmem_free(ioc, sizeof (*ioc));
+	smb_credrele(&scred);
+
+	return (err);
+}
+
+/*
+ * Helper for nsmb_ioctl case
+ * SMBIOC_NTCREATE
+ */
+int
+smb_usr_ntcreate(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr)
+{
+	struct smb_cred scred;
+	struct mbchain name_mb;
+	struct smb_share *ssp;
+	smbioc_ntcreate_t *ioc = NULL;
+	uint16_t fid;
+	int err, nmlen;
+
+	/* This ioctl requires a share. */
+	if ((ssp = sdp->sd_share) == NULL)
+		return (ENOTCONN);
+
+	/* Must not be already open. */
+	if (sdp->sd_smbfid != -1)
+		return (EINVAL);
+
+	mb_init(&name_mb);
+	smb_credinit(&scred, cr);
+	ioc = kmem_alloc(sizeof (*ioc), KM_SLEEP);
+	if (ddi_copyin((void *) arg, ioc, sizeof (*ioc), flags)) {
+		err = EFAULT;
+		goto out;
+	}
+
+	/* Build name_mb */
+	ioc->ioc_name[SMBIOC_MAX_NAME-1] = '\0';
+	nmlen = strnlen(ioc->ioc_name, SMBIOC_MAX_NAME-1);
+	err = smb_put_dmem(&name_mb, SSTOVC(ssp),
+	    ioc->ioc_name, nmlen,
+	    SMB_CS_NONE, NULL);
+	if (err != 0)
+		goto out;
+
+	/* Do the OtW open, save the FID. */
+	err = smb_smb_ntcreate(ssp, &name_mb,
+	    0,	/* create flags */
+	    ioc->ioc_req_acc,
+	    ioc->ioc_efattr,
+	    ioc->ioc_share_acc,
+	    ioc->ioc_open_disp,
+	    ioc->ioc_creat_opts,
+	    NTCREATEX_IMPERSONATION_IMPERSONATION,
+	    &scred,
+	    &fid,
+	    NULL,
+	    NULL);
+	if (err != 0)
+		goto out;
+
+	sdp->sd_smbfid = fid;
+	sdp->sd_vcgenid = ssp->ss_vcgenid;
+
+out:
+	kmem_free(ioc, sizeof (*ioc));
+	smb_credrele(&scred);
+	mb_done(&name_mb);
+
+	return (err);
+}
+
+/*
+ * Helper for nsmb_ioctl case
+ * SMBIOC_PRINTJOB
+ */
+int
+smb_usr_printjob(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr)
+{
+	struct smb_cred scred;
+	struct smb_share *ssp;
+	smbioc_printjob_t *ioc = NULL;
+	uint16_t fid;
+	int err;
+
+	/* This ioctl requires a share. */
+	if ((ssp = sdp->sd_share) == NULL)
+		return (ENOTCONN);
+
+	/* The share must be a print queue. */
+	if (ssp->ss_type != STYPE_PRINTQ)
+		return (EINVAL);
+
+	/* Must not be already open. */
+	if (sdp->sd_smbfid != -1)
+		return (EINVAL);
+
+	smb_credinit(&scred, cr);
+	ioc = kmem_alloc(sizeof (*ioc), KM_SLEEP);
+	if (ddi_copyin((void *) arg, ioc, sizeof (*ioc), flags)) {
+		err = EFAULT;
+		goto out;
+	}
+	ioc->ioc_title[SMBIOC_MAX_NAME-1] = '\0';
+
+	/* Do the OtW open, save the FID. */
+	err = smb_smb_open_prjob(ssp, ioc->ioc_title,
+	    ioc->ioc_setuplen, ioc->ioc_prmode,
+	    &scred, &fid);
+	if (err != 0)
+		goto out;
+
+	sdp->sd_smbfid = fid;
+	sdp->sd_vcgenid = ssp->ss_vcgenid;
+
+out:
+	kmem_free(ioc, sizeof (*ioc));
+	smb_credrele(&scred);
+
+	return (err);
+}
+
+/*
+ * Helper for nsmb_ioctl case
+ * SMBIOC_CLOSEFH
+ */
+int
+smb_usr_closefh(smb_dev_t *sdp, cred_t *cr)
+{
+	struct smb_cred scred;
+	struct smb_share *ssp;
+	uint16_t fid;
+	int err;
+
+	/* This ioctl requires a share. */
+	if ((ssp = sdp->sd_share) == NULL)
+		return (ENOTCONN);
+
+	if (sdp->sd_smbfid == -1)
+		return (0);
+	fid = (uint16_t)sdp->sd_smbfid;
+	sdp->sd_smbfid = -1;
+
+	smb_credinit(&scred, cr);
+	if (ssp->ss_type == STYPE_PRINTQ)
+		err = smb_smb_close_prjob(ssp, fid, &scred);
+	else
+		err = smb_smb_close(ssp, fid, NULL, &scred);
 	smb_credrele(&scred);
 
 	return (err);
@@ -514,8 +676,7 @@
 		/* Error path: rele hold from _findcreate */
 		smb_vc_rele(vcp);
 	}
-	if (ossn != NULL)
-		kmem_free(ossn, sizeof (*ossn));
+	kmem_free(ossn, sizeof (*ossn));
 	smb_credrele(&scred);
 
 	return (error);
@@ -583,8 +744,6 @@
 	 */
 	tcon->tc_sh.sh_name[SMBIOC_MAX_NAME-1] = '\0';
 	tcon->tc_sh.sh_pass[SMBIOC_MAX_NAME-1] = '\0';
-	tcon->tc_sh.sh_type_req[SMBIOC_STYPE_LEN-1] = '\0';
-	bzero(tcon->tc_sh.sh_type_ret, SMBIOC_STYPE_LEN);
 
 	if (cmd == SMBIOC_TREE_CONNECT)
 		tcon->tc_opt |= SMBSOPT_CREATE;
@@ -612,8 +771,7 @@
 	 * the tree connect response, so they can
 	 * see if they got the requested type.
 	 */
-	(void) memcpy(tcon->tc_sh.sh_type_ret,
-	    ssp->ss_type_ret, SMBIOC_STYPE_LEN);
+	tcon->tc_sh.sh_type = ssp->ss_type;
 
 	/*
 	 * The share has a hold from _tcon
@@ -630,14 +788,12 @@
 		/* Error path: rele hold from _findcreate */
 		smb_share_rele(ssp);
 	}
-	if (tcon) {
-		/*
-		 * This structure may contain a
-		 * cleartext password, so zap it.
-		 */
-		bzero(tcon, sizeof (*tcon));
-		kmem_free(tcon, sizeof (*tcon));
-	}
+	/*
+	 * This structure may contain a
+	 * cleartext password, so zap it.
+	 */
+	bzero(tcon, sizeof (*tcon));
+	kmem_free(tcon, sizeof (*tcon));
 	smb_credrele(&scred);
 
 	return (error);
--- a/usr/src/uts/common/fs/smbclnt/netsmb/subr_mchain.c	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/subr_mchain.c	Thu Jun 30 17:58:05 2011 -0400
@@ -33,6 +33,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -109,9 +110,6 @@
  * hurt transports that support larger frames.
  * 4K fits nicely in 3 Ethernet frames (3 * 1500)
  * leaving about 500 bytes for protocol headers.
- *
- * XXX: Would Ethernet drivers be happier
- * (more efficient) if we used 1K here?
  */
 #define	MLEN	4096
 
@@ -543,14 +541,36 @@
 int
 mb_put_mbuf(struct mbchain *mbp, mblk_t *m)
 {
-	mblk_t *mb;
+	mblk_t *nm, *tail_mb;
+	size_t size;
 
 	/* See: linkb(9f) */
-	for (mb = mbp->mb_cur; mb->b_cont; mb = mb->b_cont)
-		;
-	mb->b_cont = m;
-	mbp->mb_cur = m;
-	mbp->mb_count += msgdsize(m);
+	tail_mb = mbp->mb_cur;
+	while (tail_mb->b_cont != NULL)
+		tail_mb = tail_mb->b_cont;
+
+	/*
+	 * Avoid small frags:  Only link if the size of the
+	 * new mbuf is larger than the space left in the last
+	 * mblk of the chain (tail), otherwise just copy.
+	 */
+	while (m != NULL) {
+		size = MBLKL(m);
+		if (size > MBLKTAIL(tail_mb)) {
+			/* Link */
+			tail_mb->b_cont = m;
+			mbp->mb_cur = m;
+			mbp->mb_count += msgdsize(m);
+			return (0);
+		}
+		/* Copy */
+		bcopy(m->b_rptr, tail_mb->b_wptr, size);
+		tail_mb->b_wptr += size;
+		mbp->mb_count += size;
+		nm = unlinkb(m);
+		freeb(m);
+		m = nm;
+	}
 
 	return (0);
 }
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_node.h	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_node.h	Thu Jun 30 17:58:05 2011 -0400
@@ -33,6 +33,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -47,35 +48,13 @@
 
 #include <sys/avl.h>
 #include <sys/list.h>
+#include <netsmb/smb_subr.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /*
- * These are the attributes we can get from the server via
- * SMB commands such as TRANS2_QUERY_FILE_INFORMATION
- * with info level SMB_QFILEINFO_ALL_INFO, and directory
- * FindFirst/FindNext info. levels FIND_DIRECTORY_INFO
- * and FIND_BOTH_DIRECTORY_INFO, etc.
- *
- * Values in this struct are always native endian,
- * and times are converted converted to Unix form.
- * Note: zero in any of the times means "unknown".
- *
- * XXX: Later, move this to nsmb
- */
-typedef struct smbfattr {
-	timespec_t	fa_createtime;	/* Note, != ctime */
-	timespec_t	fa_atime;	/* these 3 are like unix */
-	timespec_t	fa_mtime;
-	timespec_t	fa_ctime;
-	u_offset_t	fa_size;	/* EOF position */
-	u_offset_t	fa_allocsz;	/* Allocated size. */
-	uint32_t	fa_attr;	/* Ext. file (DOS) attr */
-} smbfattr_t;
-
-/*
  * Cache whole directories (not yet)
  */
 typedef struct rddir_cache {
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c	Thu Jun 30 17:58:05 2011 -0400
@@ -33,6 +33,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -273,7 +274,7 @@
 	if (cmd == SMB_TRANS2_QUERY_PATH_INFORMATION) {
 		mb_put_uint32le(mbp, 0);
 		/* mb_put_uint8(mbp, SMB_DT_ASCII); specs are wrong */
-		error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\');
+		error = smbfs_fullpath(mbp, vcp, np, NULL, 0, '\\');
 		if (error) {
 			smb_t2_done(t2p);
 			return (error);
@@ -800,7 +801,7 @@
 	mb_put_uint8(mbp, SMB_DT_ASCII);
 
 	error = smbfs_fullpath(mbp, SSTOVC(ssp), np,
-	    name, &nmlen, '\\');
+	    name, nmlen, '\\');
 	if (error)
 		goto out;
 	smb_rq_bend(rqp);
@@ -865,7 +866,7 @@
 	smb_rq_bstart(rqp);
 	mb_put_uint8(mbp, SMB_DT_ASCII);
 
-	error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, &len, '\\');
+	error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, len, '\\');
 	if (error)
 		goto out;
 	mb_put_uint8(mbp, SMB_DT_ASCII);
@@ -1057,7 +1058,7 @@
 	mb_put_uint32le(mbp, 0);		/* MBZ */
 
 	if (cmd == SMB_TRANS2_SET_PATH_INFORMATION) {
-		error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\');
+		error = smbfs_fullpath(mbp, vcp, np, NULL, 0, '\\');
 		if (error != 0)
 			goto out;
 	}
@@ -1096,21 +1097,6 @@
 
 /*
  * Modern create/open of file or directory.
- *
- * If disp is ..._DISP_OPEN, or ...DISP_OPEN_IF, or...
- * then this is an open attempt, and:
- *   If xattr then name is the stream to be opened at np,
- *   Else np should be opened.
- *   ...we won't touch *fidp,
- *   ...we will set or clear *attrcacheupdated.
- * Else this is a creation attempt, and:
- *   If xattr then name is the stream to create at np,
- *   Else name is the thing to create under directory np.
- *   ...we will return *fidp,
- *   ...we won't touch *attrcacheupdated.
- *
- * Note, We use: disp = ...OPEN_IF, ...OVERWRITE_IF, etc.
- * now too, which may or may not create a new object.
  */
 int
 smbfs_smb_ntcreatex(
@@ -1124,119 +1110,33 @@
 	uint32_t disp,		/* open disposition */
 	uint32_t createopt,	/* NTCREATEX_OPTIONS_ */
 	struct smb_cred *scrp,
-	uint16_t *fidp,
-	uint32_t *cr_act_p,	/* create action */
-	struct smbfattr *fap)	/* optional */
+	uint16_t *fidp,		/* returned FID */
+	uint32_t *cr_act_p,	/* optional returned create action */
+	struct smbfattr *fap)	/* optional returned attributes */
 {
-	struct smb_rq rq, *rqp = &rq;
+	struct mbchain name_mb;
 	struct smb_share *ssp = np->n_mount->smi_share;
-	struct smb_vc *vcp = SSTOVC(ssp);
-	struct mbchain *mbp;
-	struct mdchain *mdp;
-	struct smbfattr fa;
-	uint8_t wc;
-	uint32_t longint, createact;
-	uint64_t llongint;
-	int error;
-	uint16_t fid, *namelenp;
+	int err;
 
-	bzero(&fa, sizeof (fa));
-	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_NT_CREATE_ANDX, scrp);
-	if (error)
-		return (error);
-	smb_rq_getrequest(rqp, &mbp);
-	smb_rq_wstart(rqp);
-	mb_put_uint8(mbp, 0xff);	/* secondary command */
-	mb_put_uint8(mbp, 0);		/* MBZ */
-	mb_put_uint16le(mbp, 0);	/* offset to next command (none) */
-	mb_put_uint8(mbp, 0);		/* MBZ */
-	namelenp = (uint16_t *)mb_reserve(mbp, sizeof (uint16_t));
-	/*
-	 * XP to a W2K Server does not use NTCREATEX_FLAGS_OPEN_DIRECTORY
-	 * for creating nor for opening a directory.  Samba ignores the bit.
-	 */
-	mb_put_uint32le(mbp, 0);	/* NTCREATEX_FLAGS_* */
-	mb_put_uint32le(mbp, 0);	/* FID - basis for path if not root */
-	mb_put_uint32le(mbp, req_acc);
-	mb_put_uint64le(mbp, 0);	/* "initial allocation size" */
-	mb_put_uint32le(mbp, efa);
-	mb_put_uint32le(mbp, share_acc);
-	mb_put_uint32le(mbp, disp);
-	mb_put_uint32le(mbp, createopt);
-	mb_put_uint32le(mbp, NTCREATEX_IMPERSONATION_IMPERSONATION); /* (?) */
-	mb_put_uint8(mbp, 0);   /* security flags (?) */
-	smb_rq_wend(rqp);
-	smb_rq_bstart(rqp);
+	mb_init(&name_mb);
 
 	if (name == NULL)
 		nmlen = 0;
-	error = smbfs_fullpath(mbp, vcp, np, name, &nmlen,
-	    xattr ? ':' : '\\');
-	if (error)
-		goto done;
-	*namelenp = htoles(nmlen); /* includes null */
-	smb_rq_bend(rqp);
-	/*
-	 * Don't want to risk missing a successful
-	 * open response, or we could "leak" FIDs.
-	 */
-	rqp->sr_flags |= SMBR_NOINTR_RECV;
-	error = smb_rq_simple_timed(rqp, smb_timo_open);
-	if (error)
-		goto done;
-	smb_rq_getreply(rqp, &mdp);
-	/*
-	 * spec says 26 for word count, but 34 words are defined
-	 * and observed from win2000
-	 */
-	error = md_get_uint8(mdp, &wc);
-	if (error)
-		goto done;
-	if (wc != 26 && wc != 34 && wc != 42) {
-		error = EBADRPC;
-		goto done;
-	}
-	md_get_uint8(mdp, NULL);		/* secondary cmd */
-	md_get_uint8(mdp, NULL);		/* mbz */
-	md_get_uint16le(mdp, NULL);		/* andxoffset */
-	md_get_uint8(mdp, NULL);		/* oplock lvl granted */
-	md_get_uint16le(mdp, &fid);		/* file ID */
-	md_get_uint32le(mdp, &createact);	/* create_action */
+	err = smbfs_fullpath(&name_mb, SSTOVC(ssp),
+	    np, name, nmlen, xattr ? ':' : '\\');
+	if (err)
+		goto out;
 
-	md_get_uint64le(mdp, &llongint);	/* creation time */
-	smb_time_NT2local(llongint, &fa.fa_createtime);
-	md_get_uint64le(mdp, &llongint);	/* access time */
-	smb_time_NT2local(llongint, &fa.fa_atime);
-	md_get_uint64le(mdp, &llongint);	/* write time */
-	smb_time_NT2local(llongint, &fa.fa_mtime);
-	md_get_uint64le(mdp, &llongint);	/* change time */
-	smb_time_NT2local(llongint, &fa.fa_ctime);
-
-	md_get_uint32le(mdp, &longint);		/* attributes */
-	fa.fa_attr = longint;
-
-	md_get_uint64le(mdp, &llongint);	/* allocation size */
-	fa.fa_allocsz = llongint;
+	err = smb_smb_ntcreate(ssp, &name_mb,
+	    0,	/* NTCREATEX_FLAGS... */
+	    req_acc, efa, share_acc, disp, createopt,
+	    NTCREATEX_IMPERSONATION_IMPERSONATION,
+	    scrp, fidp, cr_act_p, fap);
 
-	md_get_uint64le(mdp, &llongint);	/* EOF position */
-	fa.fa_size = llongint;
-
-	error = md_get_uint16le(mdp, NULL);	/* file type */
-	/* other stuff we don't care about */
+out:
+	mb_done(&name_mb);
 
-done:
-	smb_rq_done(rqp);
-	if (error)
-		return (error);
-
-	if (fidp)
-		*fidp = fid;
-	if (cr_act_p)
-		*cr_act_p = createact;
-	if (fap)
-		*fap = fa; /* struct copy */
-
-	return (0);
+	return (err);
 }
 
 static uint32_t
@@ -1335,7 +1235,7 @@
 	smb_rq_bstart(rqp);
 	mb_put_uint8(mbp, SMB_DT_ASCII);
 
-	error = smbfs_fullpath(mbp, vcp, np, name, &nmlen,
+	error = smbfs_fullpath(mbp, vcp, np, name, nmlen,
 	    xattr ? ':' : '\\');
 	if (error)
 		goto done;
@@ -1514,41 +1414,14 @@
 }
 
 int
-smbfs_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime,
-	struct smb_cred *scrp)
+smbfs_smb_close(struct smb_share *ssp, uint16_t fid,
+	struct timespec *mtime,	struct smb_cred *scrp)
 {
-	struct smb_rq rq, *rqp = &rq;
-	struct mbchain *mbp;
-	long time;
 	int error;
 
-	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scrp);
-	if (error)
-		return (error);
-	smb_rq_getrequest(rqp, &mbp);
-	smb_rq_wstart(rqp);
-	mb_put_uint16le(mbp, fid);
-	if (mtime) {
-		int sv_tz = SSTOVC(ssp)->vc_sopt.sv_tz;
-		smb_time_local2server(mtime, sv_tz, &time);
-	} else
-		time = 0;
-	mb_put_uint32le(mbp, time);
-	smb_rq_wend(rqp);
-	smb_rq_bstart(rqp);
-	smb_rq_bend(rqp);
+	error = smb_smb_close(ssp, fid, mtime, scrp);
 
 	/*
-	 * We don't really care about the result here, but we
-	 * do need to make sure we send this out, or we could
-	 * "leak" open file handles on interrupt or timeout.
-	 * The NOINTR_SEND flag makes this request immune to
-	 * interrupt or timeout until the send is done.
-	 */
-	rqp->sr_flags |= SMBR_NOINTR_SEND;
-	error = smb_rq_simple(rqp);
-	smb_rq_done(rqp);
-	/*
 	 * ENOTCONN isn't interesting - if the connection is closed,
 	 * so are all our FIDs - and EIO is also not interesting,
 	 * as it means a forced unmount was done. (was ENXIO)
@@ -1596,7 +1469,7 @@
 	smb_rq_wend(rqp);
 	smb_rq_bstart(rqp);
 	mb_put_uint8(mbp, SMB_DT_ASCII);
-	error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, &nmlen,
+	error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, nmlen,
 	    xattr ? ':' : '\\');
 	if (error)
 		goto out;
@@ -1680,7 +1553,7 @@
 	smb_rq_wend(rqp);
 	smb_rq_bstart(rqp);
 	mb_put_uint8(mbp, SMB_DT_ASCII);
-	error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, &nmlen,
+	error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, nmlen,
 	    xattr ? ':' : '\\');
 	if (!error) {
 		smb_rq_bend(rqp);
@@ -1718,7 +1591,7 @@
 	 * passed sep is ignored, so just pass sep=0.
 	 */
 	mb_put_uint8(mbp, SMB_DT_ASCII);
-	error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, NULL, 0);
+	error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, 0, 0);
 	if (error)
 		goto out;
 
@@ -1727,7 +1600,7 @@
 	 */
 	sep = (src->n_flag & N_XATTR) ? ':' : '\\';
 	mb_put_uint8(mbp, SMB_DT_ASCII);
-	error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, &tnmlen, sep);
+	error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, tnmlen, sep);
 	if (error)
 		goto out;
 
@@ -1759,11 +1632,11 @@
 	smb_rq_bstart(rqp);
 	mb_put_uint8(mbp, SMB_DT_ASCII);
 
-	error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, NULL, '\\');
+	error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, 0, '\\');
 	if (error)
 		goto out;
 	mb_put_uint8(mbp, SMB_DT_ASCII);
-	error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, &tnmlen, '\\');
+	error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, tnmlen, '\\');
 	if (error)
 		goto out;
 	smb_rq_bend(rqp);
@@ -1791,7 +1664,7 @@
 	smb_rq_wend(rqp);
 	smb_rq_bstart(rqp);
 	mb_put_uint8(mbp, SMB_DT_ASCII);
-	error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, &len, '\\');
+	error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, len, '\\');
 	if (!error) {
 		smb_rq_bend(rqp);
 		error = smb_rq_simple(rqp);
@@ -1850,7 +1723,7 @@
 	smb_rq_wend(rqp);
 	smb_rq_bstart(rqp);
 	mb_put_uint8(mbp, SMB_DT_ASCII);
-	error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, NULL, '\\');
+	error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, 0, '\\');
 	if (!error) {
 		smb_rq_bend(rqp);
 		error = smb_rq_simple(rqp);
@@ -1868,7 +1741,7 @@
 	struct mdchain *mdp;
 	uint8_t wc, bt;
 	uint16_t ec, dlen, bc;
-	int len, maxent, error, iseof = 0;
+	int maxent, error, iseof = 0;
 
 	maxent = min(ctx->f_left,
 	    (vcp->vc_txmax - SMB_HDRLEN - 2*2) / SMB_DENTRYLEN);
@@ -1889,9 +1762,8 @@
 	smb_rq_bstart(rqp);
 	mb_put_uint8(mbp, SMB_DT_ASCII);	/* buffer format */
 	if (ctx->f_flags & SMBFS_RDD_FINDFIRST) {
-		len = ctx->f_wclen;
-		error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard,
-		    &len, '\\');
+		error = smbfs_fullpath(mbp, vcp, ctx->f_dnp,
+		    ctx->f_wildcard, ctx->f_wclen, '\\');
 		if (error)
 			return (error);
 		mb_put_uint8(mbp, SMB_DT_VARIABLE);
@@ -2029,7 +1901,7 @@
 	struct mbchain *mbp;
 	struct mdchain *mdp;
 	uint16_t ecnt, eos, lno, flags;
-	int len, error;
+	int error;
 
 	if (ctx->f_t2) {
 		smb_t2_done(ctx->f_t2);
@@ -2053,9 +1925,8 @@
 		mb_put_uint16le(mbp, flags);
 		mb_put_uint16le(mbp, ctx->f_infolevel);
 		mb_put_uint32le(mbp, 0);
-		len = ctx->f_wclen;
-		error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard,
-		    &len, '\\');
+		error = smbfs_fullpath(mbp, vcp, ctx->f_dnp,
+		    ctx->f_wildcard, ctx->f_wclen, '\\');
 		if (error)
 			return (error);
 	} else	{
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.c	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.c	Thu Jun 30 17:58:05 2011 -0400
@@ -33,6 +33,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -66,19 +67,15 @@
  */
 int
 smbfs_fullpath(struct mbchain *mbp, struct smb_vc *vcp, struct smbnode *dnp,
-	const char *name, int *lenp, u_int8_t sep)
+	const char *name, int nmlen, u_int8_t sep)
 {
 	int caseopt = SMB_CS_NONE;
-	int error, len = 0;
 	int unicode = (SMB_UNICODE_STRINGS(vcp)) ? 1 : 0;
+	int error;
 
 	if (SMB_DIALECT(vcp) < SMB_DIALECT_LANMAN1_0)
 		caseopt |= SMB_CS_UPPER;
 
-	if (lenp) {
-		len = *lenp;
-		*lenp = 0;
-	}
 	if (unicode) {
 		error = mb_put_padbyte(mbp);
 		if (error)
@@ -87,7 +84,7 @@
 
 	error = smb_put_dmem(mbp, vcp,
 	    dnp->n_rpath, dnp->n_rplen,
-	    caseopt, lenp);
+	    caseopt, NULL);
 	if (name) {
 		/*
 		 * Special case at share root:
@@ -116,14 +113,12 @@
 				error = mb_put_uint16le(mbp, sep);
 			else
 				error = mb_put_uint8(mbp, sep);
-			if (!error && lenp)
-				*lenp += (unicode + 1);
 			if (error)
 				return (error);
 		}
 		/* Put the name */
 		error = smb_put_dmem(mbp, vcp,
-		    name, len, caseopt, lenp);
+		    name, nmlen, caseopt, NULL);
 		if (error)
 			return (error);
 	}
@@ -132,8 +127,6 @@
 		error = mb_put_uint16le(mbp, 0);
 	else
 		error = mb_put_uint8(mbp, 0);
-	if (!error && lenp)
-		*lenp += (unicode + 1);
 
 	return (error);
 }
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.h	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.h	Thu Jun 30 17:58:05 2011 -0400
@@ -33,6 +33,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -42,6 +43,8 @@
 
 #include <sys/cmn_err.h>
 #include <netsmb/mchain.h>
+#include <netsmb/smb_subr.h>
+#include <smbfs/smbfs_node.h>
 
 #if defined(DEBUG) || defined(lint)
 #define	SMB_VNODE_DEBUG 1
@@ -196,7 +199,7 @@
 	struct smb_cred *scrp);
 int  smbfs_smb_findclose(struct smbfs_fctx *ctx, struct smb_cred *scrp);
 int  smbfs_fullpath(struct mbchain *mbp, struct smb_vc *vcp,
-	struct smbnode *dnp, const char *name, int *nmlenp, uint8_t sep);
+	struct smbnode *dnp, const char *name, int nmlen, uint8_t sep);
 int  smbfs_smb_lookup(struct smbnode *dnp, const char **namep, int *nmlenp,
 	struct smbfattr *fap, struct smb_cred *scrp);
 int  smbfs_smb_hideit(struct smbnode *np, const char *name, int len,
--- a/usr/src/uts/common/netsmb/smb_dev.h	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/uts/common/netsmb/smb_dev.h	Thu Jun 30 17:58:05 2011 -0400
@@ -33,6 +33,7 @@
  */
 
 /*
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -71,7 +72,7 @@
  * make them incompatible with an old driver.
  */
 #define	NSMB_VERMAJ	1
-#define	NSMB_VERMIN	3900
+#define	NSMB_VERMIN	4000
 #define	NSMB_VERSION	(NSMB_VERMAJ * 100000 + NSMB_VERMIN)
 
 /*
@@ -217,14 +218,11 @@
 /*
  * Structure used with SMBIOC_TREE_FIND, _CONNECT
  */
-#define	SMBIOC_STYPE_LEN	8
 struct smbioc_oshare {
-	uint32_t	sh_pwlen;
+	uint32_t	sh_use;		/* requested */
+	uint32_t	sh_type;	/* returned */
 	char		sh_name[SMBIOC_MAX_NAME];
 	char		sh_pass[SMBIOC_MAX_NAME];
-	/* share types, in ASCII form, i.e. "A:", "IPC", ... */
-	char		sh_type_req[SMBIOC_STYPE_LEN];	/* requested */
-	char		sh_type_ret[SMBIOC_STYPE_LEN];	/* returned */
 };
 typedef struct smbioc_oshare smbioc_oshare_t;
 
@@ -342,7 +340,7 @@
 } smbioc_flags_t;
 
 typedef struct smbioc_rw {
-	uint32_t	ioc_fh;
+	int32_t		ioc_fh;
 	uint32_t	ioc_cnt;
 	lloff_t	_ioc_offset;
 	lptr_t	_ioc_base;
@@ -350,6 +348,21 @@
 #define	ioc_offset	_ioc_offset._f
 #define	ioc_base	_ioc_base.lp_ptr
 
+typedef struct smbioc_ntcreate {
+	uint32_t	ioc_req_acc;
+	uint32_t	ioc_efattr;
+	uint32_t	ioc_share_acc;
+	uint32_t	ioc_open_disp;
+	uint32_t	ioc_creat_opts;
+	char		ioc_name[SMBIOC_MAX_NAME];
+} smbioc_ntcreate_t;
+
+typedef struct smbioc_printjob {
+	uint16_t	ioc_setuplen;
+	uint16_t	ioc_prmode;
+	char		ioc_title[SMBIOC_MAX_NAME];
+} smbioc_printjob_t;
+
 /* Password Keychain (PK) support. */
 typedef struct smbioc_pk {
 	uid_t	pk_uid;				/* UID for PAM use */
@@ -375,11 +388,16 @@
 	SMBIOC_GETVERS = SMBIOC_BASE,	/* keep first */
 	SMBIOC_FLAGS2,		/* get hflags2 */
 	SMBIOC_GETSSNKEY,	/* get SMB session key */
+	SMBIOC_DUP_DEV,		/* duplicate dev handle */
 
 	SMBIOC_REQUEST,		/* simple request */
 	SMBIOC_T2RQ,		/* trans2 request */
+
 	SMBIOC_READ,		/* read (pipe) */
 	SMBIOC_WRITE,		/* write (pipe) */
+	SMBIOC_NTCREATE,	/* open or create */
+	SMBIOC_PRINTJOB,	/* open print job */
+	SMBIOC_CLOSEFH,		/* from ntcreate or printjob */
 
 	SMBIOC_SSN_CREATE,
 	SMBIOC_SSN_FIND,
--- a/usr/src/uts/intel/nsmb/ioc_check.ref	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/uts/intel/nsmb/ioc_check.ref	Thu Jun 30 17:58:05 2011 -0400
@@ -8,15 +8,12 @@
 #define	SSN_ID	0x8
 #define	SSN_SRVNAME	0x228
 #define	SSN_SRVNAME_INCR	0x1
-#define	SH_PWLEN	0x0
-#define	SH_NAME	0x4
+#define	SH_USE	0x0
+#define	SH_TYPE	0x4
+#define	SH_NAME	0x8
 #define	SH_NAME_INCR	0x1
-#define	SH_PASS	0x104
+#define	SH_PASS	0x108
 #define	SH_PASS_INCR	0x1
-#define	SH_TYPE_REQ	0x204
-#define	SH_TYPE_REQ_INCR	0x1
-#define	SH_TYPE_RET	0x20c
-#define	SH_TYPE_RET_INCR	0x1
 #define	TC_FLAGS	0x0
 #define	TC_OPT	0x4
 #define	TC_SH	0x8
@@ -61,8 +58,8 @@
 #define	IOC_SETUP	0x0
 #define	IOC_SETUP_INCR	0x2
 #define	IOC_SETUPCNT	0x8
-#define	IOC_NAME	0xc
-#define	IOC_NAME_INCR	0x1
+#define	IOC_T2_NAME	0xc
+#define	IOC_T2_NAME_INCR	0x1
 #define	IOC_TPARAMCNT	0x8c
 #define	IOC_TDATACNT	0x8e
 #define	IOC_RPARAMCNT	0x90
@@ -84,6 +81,19 @@
 #define	IOC_CNT	0x4
 #define	_IOC_OFFSET	0x8
 #define	_IOC_BASE	0x10
+#define	SIZEOF_NTCREATE	0x114
+#define	IOC_REQ_ACC	0x0
+#define	IOC_EFATTR	0x4
+#define	IOC_SHARE_ACC	0x8
+#define	IOC_OPEN_DISP	0xc
+#define	IOC_CREAT_OPTS	0x10
+#define	IOC_NTCR_NAME	0x14
+#define	IOC_NTCR_NAME_INCR	0x1
+#define	SIZEOF_PRINTJOB	0x104
+#define	IOC_SETUPLEN	0x0
+#define	IOC_PRMODE	0x2
+#define	IOC_TITLE	0x4
+#define	IOC_TITLE_INCR	0x1
 #define	SIZEOF_SMBIOC_PK	0x224
 #define	PK_UID	0x0
 #define	PK_DOM	0x4
--- a/usr/src/uts/sparc/nsmb/ioc_check.ref	Fri Jun 24 08:44:32 2011 -0700
+++ b/usr/src/uts/sparc/nsmb/ioc_check.ref	Thu Jun 30 17:58:05 2011 -0400
@@ -8,15 +8,12 @@
 #define	SSN_ID	0x8
 #define	SSN_SRVNAME	0x228
 #define	SSN_SRVNAME_INCR	0x1
-#define	SH_PWLEN	0x0
-#define	SH_NAME	0x4
+#define	SH_USE	0x0
+#define	SH_TYPE	0x4
+#define	SH_NAME	0x8
 #define	SH_NAME_INCR	0x1
-#define	SH_PASS	0x104
+#define	SH_PASS	0x108
 #define	SH_PASS_INCR	0x1
-#define	SH_TYPE_REQ	0x204
-#define	SH_TYPE_REQ_INCR	0x1
-#define	SH_TYPE_RET	0x20c
-#define	SH_TYPE_RET_INCR	0x1
 #define	TC_FLAGS	0x0
 #define	TC_OPT	0x4
 #define	TC_SH	0x8
@@ -61,8 +58,8 @@
 #define	IOC_SETUP	0x0
 #define	IOC_SETUP_INCR	0x2
 #define	IOC_SETUPCNT	0x8
-#define	IOC_NAME	0xc
-#define	IOC_NAME_INCR	0x1
+#define	IOC_T2_NAME	0xc
+#define	IOC_T2_NAME_INCR	0x1
 #define	IOC_TPARAMCNT	0x8c
 #define	IOC_TDATACNT	0x8e
 #define	IOC_RPARAMCNT	0x90
@@ -84,6 +81,19 @@
 #define	IOC_CNT	0x4
 #define	_IOC_OFFSET	0x8
 #define	_IOC_BASE	0x10
+#define	SIZEOF_NTCREATE	0x114
+#define	IOC_REQ_ACC	0x0
+#define	IOC_EFATTR	0x4
+#define	IOC_SHARE_ACC	0x8
+#define	IOC_OPEN_DISP	0xc
+#define	IOC_CREAT_OPTS	0x10
+#define	IOC_NTCR_NAME	0x14
+#define	IOC_NTCR_NAME_INCR	0x1
+#define	SIZEOF_PRINTJOB	0x104
+#define	IOC_SETUPLEN	0x0
+#define	IOC_PRMODE	0x2
+#define	IOC_TITLE	0x4
+#define	IOC_TITLE_INCR	0x1
 #define	SIZEOF_SMBIOC_PK	0x224
 #define	PK_UID	0x0
 #define	PK_DOM	0x4