--- old/exception_lists/packaging	Sun Mar 18 01:13:14 2018
+++ new/exception_lists/packaging	Sun Mar 18 01:13:14 2018
@@ -740,10 +740,11 @@
 usr/lib/smbsrv/fksmbd
 usr/lib/smbsrv/libfksmbsrv.so
 usr/lib/smbsrv/libfksmbsrv.so.1
+usr/lib/smbsrv/libmlsvc.so
+usr/lib/smbsrv/libsmb.so
+usr/lib/smbsrv/libsmbns.so
 usr/lib/smbsrv/llib-lfksmbsrv
 usr/lib/smbsrv/llib-lfksmbsrv.ln
-usr/lib/smbsrv/llib-lmlrpc
-usr/lib/smbsrv/llib-lmlrpc.ln
 usr/lib/smbsrv/llib-lmlsvc
 usr/lib/smbsrv/llib-lmlsvc.ln
 usr/lib/smbsrv/llib-lsmb
@@ -788,8 +789,21 @@
 #
 usr/include/sys/sdcard
 #
-# libsmbfs is private
+# libmlrpc is private (SMB client and server)
 #
+usr/include/libmlrpc
+usr/lib/libmlrpc.so
+usr/lib/amd64/libmlrpc.so		i386
+usr/lib/amd64/libmlrpc.so.2		i386
+usr/lib/sparcv9/libmlrpc.so		sparc
+usr/lib/sparcv9/libmlrpc.so.2		sparc
+usr/lib/llib-lmlrpc
+usr/lib/llib-lmlrpc.ln
+usr/lib/amd64/llib-lmlrpc.ln		i386
+usr/lib/sparcv9/llib-lmlrpc.ln		sparc
+#
+# libsmbfs is private (SMB client and server)
+#
 usr/include/netsmb
 usr/lib/libsmbfs.so
 usr/lib/amd64/libsmbfs.so		i386
--- old/usr/src/Makefile.master	Sun Mar 18 01:13:14 2018
+++ new/usr/src/Makefile.master	Sun Mar 18 01:13:14 2018
@@ -169,6 +169,7 @@
 FLEX=		/usr/bin/flex
 YACC=		/usr/ccs/bin/yacc
 CPP=		/usr/lib/cpp
+ANSI_CPP=	$(GCC_ROOT)/bin/cpp
 JAVAC=		$(JAVA_ROOT)/bin/javac
 JAVAH=		$(JAVA_ROOT)/bin/javah
 JAVADOC=	$(JAVA_ROOT)/bin/javadoc
--- old/usr/src/cmd/fs.d/smbclnt/smbutil/Makefile	Sun Mar 18 01:13:14 2018
+++ new/usr/src/cmd/fs.d/smbclnt/smbutil/Makefile	Sun Mar 18 01:13:14 2018
@@ -23,6 +23,8 @@
 # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
+# Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+#
 
 #
 # cmd/fs.d/smbclnt/smbutil/Makefile
@@ -30,18 +32,22 @@
 
 PROG=		smbutil
 
-include		$(SRC)/cmd/Makefile.cmd
+OBJS=   smbutil.o info.o login.o lookup.o print.o status.o view.o \
+	shares_rap.o shares_rpc.o srvsvc1_clnt.o srvsvc1_ndr.o
 
-OBJS=   smbutil.o login.o lookup.o print.o status.o view.o
-
 SRCS=	$(OBJS:%.o=%.c)
+
+include		$(SRC)/cmd/Makefile.cmd
+
 POFILE=	smbutil_all.po
 POFILES= $(OBJS:%.o=%.po)
+
+CLEANFILES +=  srvsvc1_ndr.c
 CLOBBERFILES+=  $(POFILE) $(POFILES)
 
 CSTD= $(CSTD_GNU99)
 
-LDLIBS += -lsmbfs -lnsl
+LDLIBS += -lmlrpc -lsmbfs -lnsl
 
 CPPFLAGS += -I$(SRC)/lib/libsmbfs \
 	-I$(SRC)/uts/common/smbclnt -I$(SRC)/uts/common
@@ -78,9 +84,12 @@
 
 lint:	lint_SRCS
 
-clean :
-	$(RM) $(OBJS)
+clean:
+	$(RM) $(OBJS) $(CLEANFILES)
 
-.KEEP_STATE:
-
 include ../../../Makefile.targ
+
+srvsvc1_ndr.c : srvsvc1.ndl
+	$(NDRGEN) -Y $(ANSI_CPP) $(CPPFLAGS) srvsvc1.ndl
+
+.KEEP_STATE:
--- old/usr/src/cmd/fs.d/smbclnt/smbutil/common.h	Sun Mar 18 01:13:14 2018
+++ new/usr/src/cmd/fs.d/smbclnt/smbutil/common.h	Sun Mar 18 01:13:14 2018
@@ -30,6 +30,10 @@
  * SUCH DAMAGE.
  */
 
+/*
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
 #ifndef _SMBUTIL_COMMON_H
 #define	_SMBUTIL_COMMON_H
 
@@ -42,6 +46,7 @@
 
 int  cmd_crypt(int argc, char *argv[]);
 int  cmd_help(int argc, char *argv[]);
+int  cmd_info(int argc, char *argv[]);
 int  cmd_login(int argc, char *argv[]);
 int  cmd_logout(int argc, char *argv[]);
 int  cmd_logoutall(int argc, char *argv[]);
@@ -50,8 +55,9 @@
 int  cmd_status(int argc, char *argv[]);
 int  cmd_view(int argc, char *argv[]);
 
-/* No crypt_usage? */
+void crypt_usage(void);
 void help_usage(void);
+void info_usage(void);
 void login_usage(void);
 void logout_usage(void);
 void logoutall_usage(void);
@@ -60,7 +66,10 @@
 void status_usage(void);
 void view_usage(void);
 
-extern int loadsmbvfs();
+/* See view.c */
+int share_enum_rap(struct smb_ctx *ctx);
+int share_enum_rpc(struct smb_ctx *ctx, char *server);
+void view_print_share(char *share, int type, char *comment);
 
 #ifdef __cplusplus
 }
--- /dev/null	Sun Mar 18 01:13:14 2018
+++ new/usr/src/cmd/fs.d/smbclnt/smbutil/info.c	Sun Mar 18 01:13:14 2018
@@ -0,0 +1,212 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+/*
+ * Show information about the remote server, as offered by
+ * NetServerGetInfo with SERVER_INFO_101
+ */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libintl.h>
+
+#include <libmlrpc/libmlrpc.h>
+#include <netsmb/smb_lib.h>
+#include "srvsvc1_clnt.h"
+#include "common.h"
+
+
+static int get_info(smb_ctx_t *);
+
+void
+info_usage(void)
+{
+	printf(gettext("usage: smbutil info [connection options] //"
+	    "[workgroup;][user[:password]@]server\n"));
+	exit(1);
+}
+
+int
+cmd_info(int argc, char *argv[])
+{
+	struct smb_ctx *ctx;
+	int error, err2, opt;
+
+	if (argc < 2)
+		info_usage();
+
+	error = smb_ctx_alloc(&ctx);
+	if (error)
+		return (error);
+
+	error = smb_ctx_scan_argv(ctx, argc, argv,
+	    SMBL_SERVER, SMBL_SERVER, USE_WILDCARD);
+	if (error)
+		goto out;
+
+	error = smb_ctx_readrc(ctx);
+	if (error)
+		goto out;
+
+	while ((opt = getopt(argc, argv, STDPARAM_OPT)) != EOF) {
+		if (opt == '?')
+			info_usage();
+		error = smb_ctx_opt(ctx, opt, optarg);
+		if (error)
+			goto out;
+	}
+
+	smb_ctx_setshare(ctx, "IPC$", USE_IPC);
+
+	/*
+	 * Resolve the server address,
+	 * setup derived defaults.
+	 */
+	error = smb_ctx_resolve(ctx);
+	if (error)
+		goto out;
+
+	/*
+	 * Have server, share, etc. from above:
+	 * smb_ctx_scan_argv, option settings.
+	 * Get the session and tree.
+	 */
+again:
+	error = smb_ctx_get_ssn(ctx);
+	if (error == EAUTH) {
+		err2 = smb_get_authentication(ctx);
+		if (err2 == 0)
+			goto again;
+	}
+	if (error) {
+		smb_error(gettext("//%s: login failed"),
+		    error, ctx->ct_fullserver);
+		goto out;
+	}
+
+	error = smb_ctx_get_tree(ctx);
+	if (error) {
+		smb_error(gettext("//%s/%s: tree connect failed"),
+		    error, ctx->ct_fullserver, ctx->ct_origshare);
+		goto out;
+	}
+
+	/*
+	 * Have IPC$ tcon.  Get the server info.
+	 */
+	error = get_info(ctx);
+	if (error)
+		smb_error("cannot get server info.", error);
+
+out:
+	smb_ctx_free(ctx);
+	return (error);
+}
+
+int
+get_info(smb_ctx_t *ctx)
+{
+	char pf_unk[32];
+	mlrpc_handle_t handle;
+	ndr_service_t *svc;
+	union mslm_NetServerGetInfo_ru res;
+	struct mslm_SERVER_INFO_101 *sv101;
+	char *platform_name;
+	int err;
+
+	/*
+	 * Create an RPC handle using the smb_ctx we already have.
+	 * Just local allocation and initialization.
+	 */
+	srvsvc1_initialize();
+	svc = ndr_svc_lookup_name("srvsvc");
+	if (svc == NULL)
+		return (ENOENT);
+
+	err = mlrpc_clh_create(&handle, ctx);
+	if (err)
+		return (err);
+
+	/*
+	 * Try to bind to the RPC service.  If it fails,
+	 * just return the error and the caller will
+	 * fall back to RAP.
+	 */
+	err = mlrpc_clh_bind(&handle, svc);
+	if (err)
+		goto out;
+
+	err = srvsvc_net_server_getinfo(&handle,
+	    ctx->ct_fullserver, 101, &res);
+	if (err)
+		goto out;
+
+	sv101 = res.info101;
+
+	switch (sv101->sv101_platform_id) {
+	case SV_PLATFORM_ID_DOS:
+		platform_name = "DOS";
+		break;
+	case SV_PLATFORM_ID_OS2:
+		platform_name = "OS2";
+		break;
+	case SV_PLATFORM_ID_NT:
+		platform_name = "NT";
+		break;
+	case SV_PLATFORM_ID_OSF:
+		platform_name = "OSF";
+		break;
+	case SV_PLATFORM_ID_VMS:
+		platform_name = "VMS";
+		break;
+	default:
+		platform_name = pf_unk;
+		snprintf(pf_unk, sizeof (pf_unk), "(%d)",
+		    sv101->sv101_platform_id);
+		break;
+	}
+
+	printf("server info:\n");
+	printf(" platform_id %s\n", platform_name);
+	printf(" vers.major  %d\n", sv101->sv101_version_major);
+	printf(" vers.minor  %d\n", sv101->sv101_version_minor);
+
+	if (smb_verbose)
+		printf(" type_flags  0x%x\n", sv101->sv101_type);
+
+	printf(" name    \"%s\"\n", sv101->sv101_name);
+	printf(" comment \"%s\"\n", sv101->sv101_comment);
+
+out:
+	(void) mlrpc_clh_free(&handle);
+	return (err);
+}
--- /dev/null	Sun Mar 18 01:13:14 2018
+++ new/usr/src/cmd/fs.d/smbclnt/smbutil/shares_rap.c	Sun Mar 18 01:13:14 2018
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2000-2002, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Id: view.c,v 1.9 2002/02/20 09:26:42 bp Exp
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netsmb/mchain.h>	/* letohs, etc. */
+#include <netsmb/smb.h>
+#include <netsmb/smb_lib.h>
+#include <netsmb/smb_rap.h>
+
+#include "common.h"
+
+/*
+ * Enumerate shares using Remote Administration Protocol (RAP)
+ * Was in libsmbfs netshareenum.c
+ */
+
+struct smb_share_info_1 {
+	char		shi1_netname[13];
+	char		shi1_pad;
+	uint16_t	shi1_type;
+	uint32_t	shi1_remark;		/* char * */
+};
+
+static int
+smb_rap_NetShareEnum(struct smb_ctx *ctx, int sLevel, void *pbBuffer,
+	int *cbBuffer, int *pcEntriesRead, int *pcTotalAvail)
+{
+	struct smb_rap *rap;
+	long lval = -1;
+	int error;
+
+	error = smb_rap_create(0, "WrLeh", "B13BWz", &rap);
+	if (error)
+		return (error);
+	smb_rap_setNparam(rap, sLevel);		/* W - sLevel */
+	smb_rap_setPparam(rap, pbBuffer);	/* r - pbBuffer */
+	smb_rap_setNparam(rap, *cbBuffer);	/* L - cbBuffer */
+	error = smb_rap_request(rap, ctx);
+	if (error == 0) {
+		*pcEntriesRead = rap->r_entries;
+		error = smb_rap_getNparam(rap, &lval);
+		*pcTotalAvail = lval;
+		/* Copy the data length into the IN/OUT variable. */
+		*cbBuffer = rap->r_rcvbuflen;
+	}
+	error = smb_rap_error(rap, error);
+	smb_rap_done(rap);
+	return (error);
+}
+
+int
+share_enum_rap(smb_ctx_t *ctx)
+{
+	struct smb_share_info_1 *shi;
+	void *rpbuf;
+	char *cp;
+	int error, bufsize, i, rcnt, total;
+	int lbound, rbound;
+	uint16_t type;
+
+	bufsize = 0xffe0;	/* samba notes win2k bug for 65535 */
+	rpbuf = malloc(bufsize);
+	if (rpbuf == NULL)
+		return (errno);
+
+	error = smb_rap_NetShareEnum(ctx, 1, rpbuf, &bufsize, &rcnt, &total);
+	if (error &&
+	    error != (ERROR_MORE_DATA | SMB_RAP_ERROR))
+		goto out;
+
+	/*
+	 * Bounds for offsets to comments strings.
+	 * After the array, and before the end.
+	 */
+	lbound = rcnt * (sizeof (struct smb_share_info_1));
+	rbound = bufsize;
+
+	/* Print the header line. */
+	view_print_share(NULL, 0, NULL);
+
+	for (shi = rpbuf, i = 0; i < rcnt; i++, shi++) {
+		type = letohs(shi->shi1_type);
+
+		shi->shi1_pad = '\0'; /* ensure null termination */
+
+		/*
+		 * Offsets to comment strings can be trash.
+		 * Only print when the offset is valid.
+		 */
+		if (shi->shi1_remark >= lbound &&
+		    shi->shi1_remark < rbound) {
+			cp = (char *)rpbuf + shi->shi1_remark;
+		} else
+			cp = NULL;
+
+		/* Convert from OEM to local codeset? */
+		view_print_share(shi->shi1_netname, type, cp);
+	}
+	error = 0;
+
+out:
+	free(rpbuf);
+	return (error);
+}
--- /dev/null	Sun Mar 18 01:13:14 2018
+++ new/usr/src/cmd/fs.d/smbclnt/smbutil/shares_rpc.c	Sun Mar 18 01:13:14 2018
@@ -0,0 +1,83 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+/*
+ * Share enumeration using Remote Procedure Call (RPC)
+ */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libmlrpc/libmlrpc.h>
+#include <netsmb/smbfs_api.h>
+#include "srvsvc1_clnt.h"
+#include "common.h"
+
+int
+share_enum_rpc(struct smb_ctx *ctx, char *server)
+{
+	mlrpc_handle_t handle;
+	ndr_service_t *svc;
+	union mslm_NetShareEnum_ru res;
+	struct mslm_NetShareInfo_1 *nsi1;
+	int err, i, count;
+
+	/*
+	 * Create an RPC handle using the smb_ctx we already have.
+	 * Just local allocation and initialization.
+	 */
+	srvsvc1_initialize();
+	svc = ndr_svc_lookup_name("srvsvc");
+	if (svc == NULL)
+		return (ENOENT);
+
+	err = mlrpc_clh_create(&handle, ctx);
+	if (err)
+		return (err);
+
+	/*
+	 * Try to bind to the RPC service.  If it fails,
+	 * just return the error and the caller will
+	 * fall back to RAP.
+	 */
+	err = mlrpc_clh_bind(&handle, svc);
+	if (err)
+		goto out;
+
+	err = srvsvc_net_share_enum(&handle, server, 1, &res);
+	if (err)
+		goto out;
+
+	/* Print the header line. */
+	view_print_share(NULL, 0, NULL);
+
+	/* Print the share list. */
+	count = res.bufptr1->entriesread;
+	i = 0, nsi1 = res.bufptr1->entries;
+	while (i < count) {
+		/* Convert UTF-8 to local code set? */
+		view_print_share((char *)nsi1->shi1_netname,
+		    nsi1->shi1_type, (char *)nsi1->shi1_comment);
+		i++, nsi1++;
+	}
+
+out:
+	(void) mlrpc_clh_free(&handle);
+	return (err);
+}
--- old/usr/src/cmd/fs.d/smbclnt/smbutil/smbutil.c	Sun Mar 18 01:13:14 2018
+++ new/usr/src/cmd/fs.d/smbclnt/smbutil/smbutil.c	Sun Mar 18 01:13:14 2018
@@ -33,6 +33,8 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #include <sys/param.h>
@@ -70,6 +72,7 @@
 } commands[] = {
 	{"crypt",	cmd_crypt,	NULL, CMDFL_NO_KMOD},
 	{"help",	cmd_help,	help_usage, CMDFL_NO_KMOD},
+	{"info",	cmd_info,	info_usage, 0},
 	{"login",	cmd_login,	login_usage, 0},
 	{"logout",	cmd_logout,	logout_usage, 0},
 	{"logoutall",	cmd_logoutall,	logoutall_usage, 0},
@@ -189,6 +192,7 @@
 	" crypt		slightly obscure password\n"
 	" help		display help on specified subcommand\n"
 	/* " lc 		display active connections\n" */
+	" info		display server type and version\n"
 	" login		login to specified host\n"
 	" logout 	logout from specified host\n"
 	" logoutall	logout all users (requires privilege)\n"
--- /dev/null	Sun Mar 18 01:13:14 2018
+++ new/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1.ndl	Sun Mar 18 01:13:14 2018
@@ -0,0 +1,177 @@
+/*
+ * 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 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+/*
+ * SRVSVC - Server Service (partial)
+ *
+ * This module needs only NetShareEnum (levels 0, 1)
+ * and NetServerGetInfo (levels 100, 101)
+ */
+
+#include <libmlrpc/ndrtypes.ndl>
+
+/*
+ * SRVSVC - Server Service
+ */
+
+#define SRVSVC_OPNUM_NetShareEnum                0x0f
+#define SRVSVC_OPNUM_NetServerGetInfo            0x15
+
+/*
+ * SRVSVC NetShareEnum (
+ *	IN  LPTSTR	servername,
+ *	IN  DWORD	level;
+ *	OUT union switch(level) {
+ *		case 0: struct {
+ *				DWORD entriesread;
+ *			     [size_is(entriesread)]
+ *				_SHARE_INFO_0 *entries;
+ *			} *bufptr0;
+ *		case 1: struct {
+ *				DWORD entriesread;
+ *			     [size_is(entriesread)]
+ *				_SHARE_INFO_1 *entries;
+ *			} *bufptr1;
+ *		...
+ *	    }		bufptr,
+ *	IN  DWORD	prefmaxlen,
+ *	OUT DWORD	totalentries,
+ *	IN OUT DWORD ?*	resume_handle,
+ *	OUT DWORD	status
+ *      )
+ */
+
+struct mslm_NetShareInfo_0 {
+	LPTSTR shi0_netname;
+};
+struct mslm_NetShareInfo_0_result {
+	DWORD	entriesread;
+	SIZE_IS(entriesread)
+	struct mslm_NetShareInfo_0 *entries;
+};
+
+struct mslm_NetShareInfo_1 {
+	LPTSTR	shi1_netname;
+	DWORD	shi1_type; /* type of resource such as IPC$ */
+	LPTSTR	shi1_comment;
+};
+struct mslm_NetShareInfo_1_result {
+	DWORD	entriesread;
+	SIZE_IS(entriesread)
+	struct mslm_NetShareInfo_1 *entries;
+};
+
+union mslm_NetShareEnum_ru {
+	CASE(0)		struct mslm_NetShareInfo_0_result *bufptr0;
+	CASE(1)		struct mslm_NetShareInfo_1_result *bufptr1;
+	DEFAULT		char *nullptr;
+};
+struct mslm_NetShareEnum_result {
+	DWORD	level;
+	SWITCH(level)
+	union mslm_NetShareEnum_ru ru;
+};
+
+
+OPERATION(SRVSVC_OPNUM_NetShareEnum)
+struct mslm_NetShareEnum {
+	IN  		LPTSTR	servername;
+	INOUT  		DWORD	level;
+	INOUT 		struct mslm_NetShareEnum_result result;
+	IN  		DWORD	prefmaxlen;
+	OUT 		DWORD	totalentries;
+	INOUT 		DWORD	*resume_handle;
+	OUT 		DWORD	status;
+};
+
+
+/*
+ * SRVSVC NetServerGetInfo (
+ *	IN LPTSTR	servername,
+ *	IN DWORD	level,
+ *	OUT union switch(level) {
+ *		case 100: _SERVER_INFO_100 *	p100;
+ *		case 101: _SERVER_INFO_101 *	p101;
+ *		case 102: _SERVER_INFO_102 *	p102;
+ *	    }		bufptr,
+ *	OUT DWORD	status
+ *      )
+ */
+
+/* for svX_platform (note: decimal!) */
+#define	SV_PLATFORM_ID_DOS	300
+#define	SV_PLATFORM_ID_OS2	400
+#define	SV_PLATFORM_ID_NT	500
+#define	SV_PLATFORM_ID_OSF	600
+#define	SV_PLATFORM_ID_VMS	700
+
+struct mslm_SERVER_INFO_100 {
+	DWORD		sv100_platform_id;
+	LPTSTR		sv100_name;
+};
+
+struct mslm_SERVER_INFO_101 {
+	DWORD		sv101_platform_id;
+	LPTSTR		sv101_name;
+	DWORD		sv101_version_major;
+	DWORD		sv101_version_minor;
+	DWORD		sv101_type;
+	LPTSTR		sv101_comment;
+};
+
+union mslm_NetServerGetInfo_ru {
+	CASE(100)	struct mslm_SERVER_INFO_100 *info100;
+	CASE(101)	struct mslm_SERVER_INFO_101 *info101;
+	DEFAULT		char *nullptr;
+};
+
+struct mslm_NetServerGetInfo_result {
+	DWORD level;
+	SWITCH(level)
+	union mslm_NetServerGetInfo_ru ru;
+};
+
+
+OPERATION(SRVSVC_OPNUM_NetServerGetInfo)
+struct mslm_NetServerGetInfo {
+	IN  LPTSTR	servername;
+	IN  DWORD	level;
+	OUT struct mslm_NetServerGetInfo_result result;
+	OUT DWORD	status;
+};
+
+
+/*
+ * The SRVSVC interface
+ */
+INTERFACE(0)
+union srvsvc_interface {
+	CASE(SRVSVC_OPNUM_NetShareEnum)
+		struct mslm_NetShareEnum	NetShareEnum;
+	CASE(SRVSVC_OPNUM_NetServerGetInfo)
+		struct mslm_NetServerGetInfo	NetServerGetInfo;
+};
+typedef union srvsvc_interface	srvsvc_interface_t;
+EXTERNTYPEINFO(srvsvc_interface)
--- /dev/null	Sun Mar 18 01:13:14 2018
+++ new/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1_clnt.c	Sun Mar 18 01:13:14 2018
@@ -0,0 +1,138 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+/*
+ * A few excerpts from lib/smbsrv/libmlsvc
+ * See longer comment in srvsvc1.ndl
+ */
+
+#include <sys/errno.h>
+#include <stdio.h>
+#include <time.h>
+#include <strings.h>
+#include <time.h>
+
+#include <libmlrpc/libmlrpc.h>
+#include "srvsvc1_clnt.h"
+
+static ndr_service_t srvsvc_service = {
+	"SRVSVC",			/* name */
+	"Server services",		/* desc */
+	"\\srvsvc",			/* endpoint */
+	"\\PIPE\\ntsvcs",		/* sec_addr_port */
+	"4b324fc8-1670-01d3-1278-5a47bf6ee188", 3,	/* abstract */
+	NDR_TRANSFER_SYNTAX_UUID,		2,	/* transfer */
+	0,				/* no bind_instance_size */
+	0,				/* no bind_req() */
+	0,				/* no unbind_and_close() */
+	0,				/* use generic_call_stub() */
+	&TYPEINFO(srvsvc_interface),	/* interface_ti */
+	NULL				/* stub_table */
+};
+
+/*
+ * srvsvc_initialize
+ *
+ * This function registers the SRVSVC RPC interface with the RPC runtime
+ * library. It must be called in order to use either the client side
+ * or the server side functions.
+ */
+void
+srvsvc1_initialize(void)
+{
+	static int init_done;
+	if (init_done)
+		return;
+	init_done = 1;
+	(void) ndr_svc_register(&srvsvc_service);
+}
+
+/*
+ * Client-side stub for NetServerGetInfo
+ */
+int
+srvsvc_net_server_getinfo(mlrpc_handle_t *handle, char *server,
+	int level, union mslm_NetServerGetInfo_ru *resp)
+{
+	struct mslm_NetServerGetInfo arg;
+	int len, opnum, rc;
+
+	opnum = SRVSVC_OPNUM_NetServerGetInfo;
+	bzero(&arg, sizeof (arg));
+
+	len = strlen(server) + 4;
+	arg.servername = ndr_rpc_malloc(handle, len);
+	if (arg.servername == NULL)
+		return (ENOMEM);
+
+	(void) snprintf((char *)arg.servername, len, "\\\\%s", server);
+	arg.level = level;
+
+	rc = ndr_rpc_call(handle, opnum, &arg);
+	if ((rc != 0) || (arg.status != 0))
+		return (EIO);
+
+	*resp = arg.result.ru;
+	return (0);
+}
+
+/*
+ * Client-side stub for NetShareEnum
+ */
+int
+srvsvc_net_share_enum(mlrpc_handle_t *handle, char *server,
+	int level, union mslm_NetShareEnum_ru *resp)
+{
+	/* Any enum result type is OK for nres. */
+	struct mslm_NetShareInfo_0_result nres;
+	struct mslm_NetShareEnum arg;
+	int len, opnum, rc;
+
+	opnum = SRVSVC_OPNUM_NetShareEnum;
+	bzero(&nres, sizeof (nres));
+	bzero(&arg, sizeof (arg));
+
+	len = strlen(server) + 4;
+	arg.servername = ndr_rpc_malloc(handle, len);
+	if (arg.servername == NULL)
+		return (ENOMEM);
+
+	(void) snprintf((char *)arg.servername, len, "\\\\%s", server);
+	arg.level = level;
+	arg.result.level = level;
+	arg.result.ru.bufptr0 = &nres;
+	arg.prefmaxlen = 0xFFFFFFFF;
+	arg.resume_handle = NULL;
+
+	rc = ndr_rpc_call(handle, opnum, &arg);
+	if ((rc != 0) || (arg.status != 0))
+		return (EIO);
+
+	*resp = arg.result.ru;
+	return (0);
+}
--- /dev/null	Sun Mar 18 01:13:15 2018
+++ new/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1_clnt.h	Sun Mar 18 01:13:15 2018
@@ -0,0 +1,46 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+#ifndef _SRVSVC1_CLNT_H
+#define	_SRVSVC1_CLNT_H
+
+/*
+ * Excerpts from lib/smbsrv/libmlsvc
+ * Just enough for share enumeration.
+ */
+
+#include <libmlrpc/libmlrpc.h>
+#include "srvsvc1.ndl"
+
+void srvsvc1_initialize(void);
+int srvsvc_net_share_enum(mlrpc_handle_t *handle, char *server,
+	int level, union mslm_NetShareEnum_ru *resp);
+int srvsvc_net_server_getinfo(mlrpc_handle_t *handle, char *server,
+	int level, union mslm_NetServerGetInfo_ru *resp);
+
+#endif	/* _SRVSVC1_CLNT_H */
--- old/usr/src/cmd/fs.d/smbclnt/smbutil/view.c	Sun Mar 18 01:13:15 2018
+++ new/usr/src/cmd/fs.d/smbclnt/smbutil/view.c	Sun Mar 18 01:13:15 2018
@@ -34,6 +34,7 @@
 
 /*
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #include <sys/types.h>
@@ -48,12 +49,9 @@
 
 #include <netsmb/smb.h>
 #include <netsmb/smb_lib.h>
-#include <netsmb/smb_netshareenum.h>
-
 #include "common.h"
 
-int enum_shares(smb_ctx_t *);
-void print_shares(int, int, struct share_info *);
+static int use_rap;
 
 void
 view_usage(void)
@@ -79,18 +77,27 @@
 	error = smb_ctx_scan_argv(ctx, argc, argv,
 	    SMBL_SERVER, SMBL_SERVER, USE_WILDCARD);
 	if (error)
-		return (error);
+		goto out;
 
 	error = smb_ctx_readrc(ctx);
 	if (error)
-		return (error);
+		goto out;
 
 	while ((opt = getopt(argc, argv, STDPARAM_OPT)) != EOF) {
 		if (opt == '?')
 			view_usage();
+		/*
+		 * This is an undocumented option, just for testing.
+		 * Use the old LanMan Remote API Protocol (RAP) for
+		 * enumerating shares.
+		 */
+		if (opt == 'B') {
+			use_rap++;
+			continue;
+		}
 		error = smb_ctx_opt(ctx, opt, optarg);
 		if (error)
-			return (error);
+			goto out;
 	}
 
 	smb_ctx_setshare(ctx, "IPC$", USE_IPC);
@@ -101,7 +108,7 @@
 	 */
 	error = smb_ctx_resolve(ctx);
 	if (error)
-		return (error);
+		goto out;
 
 	/*
 	 * Have server, share, etc. from above:
@@ -118,7 +125,7 @@
 	if (error) {
 		smb_error(gettext("//%s: login failed"),
 		    error, ctx->ct_fullserver);
-		return (error);
+		goto out;
 	}
 
 	error = smb_ctx_get_tree(ctx);
@@ -125,17 +132,19 @@
 	if (error) {
 		smb_error(gettext("//%s/%s: tree connect failed"),
 		    error, ctx->ct_fullserver, ctx->ct_origshare);
-		return (error);
+		goto out;
 	}
 
 	/*
 	 * Have IPC$ tcon, now list shares.
-	 * This prints its own errors.
+	 * Try RPC; if that fails, do RAP.
 	 */
-	error = enum_shares(ctx);
-	if (error)
-		return (error);
+	if (!use_rap)
+		error = share_enum_rpc(ctx, ctx->ct_fullserver);
+	if (error || use_rap)
+		error = share_enum_rap(ctx);
 
+out:
 	smb_ctx_free(ctx);
 	return (0);
 }
@@ -158,48 +167,29 @@
 };
 #endif
 
-int
-enum_shares(smb_ctx_t *ctx)
+/*
+ * Print one line of the share list, or
+ * if SHARE is null, print the header line.
+ */
+void
+view_print_share(char *share, int type, char *comment)
 {
-	struct share_info *share_info;
-	int error, entries, total;
+	char *stname;
+	int stindex;
 
-	/*
-	 * XXX: Later, try RPC first,
-	 * then fall back to RAP...
-	 */
-	error = smb_netshareenum(ctx, &entries, &total, &share_info);
-	if (error) {
-		smb_error(gettext("//%s failed to list shares"),
-		    error, ctx->ct_fullserver);
-		return (error);
+	if (share == NULL) {
+		printf(gettext("Share        Type       Comment\n"));
+		printf("-------------------------------\n");
+		return;
 	}
-	print_shares(entries, total, share_info);
-	return (0);
-}
 
-void
-print_shares(int entries, int total,
-	struct share_info *share_info)
-{
-	struct share_info *ep;
-	int i;
+	stindex = type & STYPE_MASK;
+	if (stindex > STYPE_UNKNOWN)
+		stindex = STYPE_UNKNOWN;
+	stname = gettext(shtype[stindex]);
 
-	printf(gettext("Share        Type       Comment\n"));
-	printf("-------------------------------\n");
+	if (comment == NULL)
+		comment = "";
 
-	for (ep = share_info, i = 0; i < entries; i++, ep++) {
-		int sti = ep->type & STYPE_MASK;
-		if (sti > STYPE_UNKNOWN)
-			sti = STYPE_UNKNOWN;
-		printf("%-12s %-10s %s\n", ep->netname,
-		    gettext(shtype[sti]),
-		    ep->remark ? ep->remark : "");
-		free(ep->netname);
-		free(ep->remark);
-	}
-	printf(gettext("\n%d shares listed from %d available\n"),
-	    entries, total);
-
-	free(share_info);
+	printf("%-12s %-10s %s\n", share, stname, comment);
 }
--- old/usr/src/common/smbsrv/smb_door_legacy.c	Sun Mar 18 01:13:15 2018
+++ new/usr/src/common/smbsrv/smb_door_legacy.c	Sun Mar 18 01:13:15 2018
@@ -39,7 +39,7 @@
 #include <sys/errno.h>
 #endif
 
-#include <smbsrv/wintypes.h>
+#include <smb/wintypes.h>
 #include <smbsrv/smb_share.h>
 #include <smbsrv/smb_door.h>
 #include <smbsrv/alloc.h>
--- old/usr/src/common/smbsrv/smb_token_xdr.c	Sun Mar 18 01:13:15 2018
+++ new/usr/src/common/smbsrv/smb_token_xdr.c	Sun Mar 18 01:13:15 2018
@@ -32,7 +32,7 @@
 #if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
 #include <stdlib.h>
 #endif /* !_KERNEL */
-#include <smbsrv/wintypes.h>
+#include <smb/wintypes.h>
 #include <smbsrv/smb_sid.h>
 #include <smbsrv/smb_xdr.h>
 #include <smbsrv/smb_token.h>
--- old/usr/src/lib/Makefile	Sun Mar 18 01:13:15 2018
+++ new/usr/src/lib/Makefile	Sun Mar 18 01:13:15 2018
@@ -163,6 +163,7 @@
 	libmapid	\
 	libmapmalloc	\
 	libmd5		\
+	libmlrpc	\
 	libmtmalloc	\
 	libmvec		\
 	libndmp		\
@@ -421,6 +422,7 @@
 	libmail		\
 	libmapid	\
 	libmd		\
+	libmlrpc	\
 	libmtmalloc	\
 	libndmp		\
 	libnsctl	\
@@ -625,6 +627,7 @@
 libkvm:		../cmd/sgs/libelf
 libldap5:	libsasl
 libmapid:	libresolv2 libscf
+libmlrpc:	libsmbfs libuuid
 libndmp:	libscf
 libnisdb:	libldap5
 libnwam:	libscf libbsm libdladm libipadm
@@ -694,7 +697,7 @@
 scsi:		libfru libumem libdevid libdevinfo
 smbsrv:		libxnet libpthread librt libshare libidmap pkcs11 libsqlite \
 		libcryptoutil libreparse libcmdutils libresolv2 libsmbfs \
-		libuuid libfakekernel libads libgss libldap5 krb5
+		libuuid libfakekernel libads libgss libldap5 krb5 libmlrpc
 storage:	libdevice libdevinfo libdevid
 sun_fc:		libdevinfo libsysevent
 sun_sas:	libdevinfo libsysevent libkstat libdevid
--- /dev/null	Sun Mar 18 01:13:15 2018
+++ new/usr/src/lib/libmlrpc/Makefile	Sun Mar 18 01:13:15 2018
@@ -0,0 +1,65 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+#
+
+include $(SRC)/lib/Makefile.lib
+
+HDRS=		libmlrpc.h ndr.h ndrtypes.ndl rpcpdu.ndl
+HDRDIR=		common
+
+ROOTHDRDIR=	$(ROOT)/usr/include/libmlrpc
+ROOTHDRS= $(HDRS:%=$(ROOTHDRDIR)/%)
+
+# ISA targets
+SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+all :=		TARGET = all
+install :=	TARGET = install
+clean :=	TARGET = clean
+clobber :=	TARGET = clobber
+lint :=		TARGET = lint
+
+.KEEP_STATE:
+
+all install clean clobber lint: $(SUBDIRS)
+
+install_h: $(ROOTHDRDIR) $(ROOTHDRS)
+
+check: $(CHECKHDRS)
+
+$(ROOTHDRDIR)/%: %
+	$(INS.file)
+
+$(ROOTHDRDIR):
+	$(INS.dir)
+
+$(SUBDIRS): FRC
+	@cd $@; pwd; VERSION='$(VERSION)' $(MAKE) $(TARGET)
+
+FRC:
+
+include $(SRC)/lib/Makefile.targ
--- /dev/null	Sun Mar 18 01:13:15 2018
+++ new/usr/src/lib/libmlrpc/Makefile.com	Sun Mar 18 01:13:15 2018
@@ -0,0 +1,75 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+#
+
+LIBRARY =	libmlrpc.a
+VERS =		.2
+
+OBJS_COMMON = 			\
+	mlrpc_clh.o		\
+	ndr_client.o		\
+	ndr_heap.o		\
+	ndr_marshal.o		\
+	ndr_ops.o		\
+	ndr_process.o		\
+	ndr_server.o		\
+	ndr_svc.o		\
+	ndr_wchar.o
+
+NDLLIST = rpcpdu
+
+OBJECTS=	$(OBJS_COMMON) $(NDLLIST:%=%_ndr.o)
+CLEANFILES += $(NDLLIST:%=%_ndr.c)
+
+include ../../Makefile.lib
+
+LIBS=		$(DYNLIB) $(LINTLIB)
+
+LDLIBS +=	-lsmbfs -luuid -lc
+
+SRCDIR=		../common
+SRCS=   $(OBJS_COMMON:%.o=$(SRCDIR)/%.c)
+$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
+
+NDLDIR =	$(SRCDIR)
+
+CFLAGS +=	$(CCVERBOSE)
+INCS = -I. -I$(SRCDIR)
+CPPFLAGS += $(INCS) -D_REENTRANT
+
+all:	$(LIBS)
+
+lint:	lintcheck
+
+include ../../Makefile.targ
+
+objs/%_ndr.o pics/%_ndr.o : %_ndr.c
+
+%_ndr.c : $(NDLDIR)/%.ndl
+	$(NDRGEN) -Y $(ANSI_CPP) $(CPPFLAGS) $<
+
+.KEEP_STATE:
--- old/usr/src/lib/smbsrv/libmlrpc/amd64/Makefile	Sun Mar 18 01:13:15 2018
+++ /dev/null	Sun Mar 18 01:13:15 2018
@@ -1,35 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-MACH_LDLIBS +=	-L$(ROOT)/usr/lib/smbsrv/$(MACH64)
-
-include ../Makefile.com
-include ../../../Makefile.lib.64
-
-DYNFLAGS +=	-R/usr/lib/smbsrv/$(MACH64)
-
-install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
--- /dev/null	Sun Mar 18 01:13:15 2018
+++ new/usr/src/lib/libmlrpc/amd64/Makefile	Sun Mar 18 01:13:15 2018
@@ -0,0 +1,31 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+MACH_LDLIBS +=	-L$(ROOT)/usr/lib/smbsrv/$(MACH64)
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
--- old/usr/src/lib/smbsrv/libmlrpc/common/libmlrpc.h	Sun Mar 18 01:13:15 2018
+++ /dev/null	Sun Mar 18 01:13:15 2018
@@ -1,545 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
- */
-
-#ifndef	_LIBMLRPC_H
-#define	_LIBMLRPC_H
-
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <smbsrv/wintypes.h>
-#include <smbsrv/ndr.h>
-#include <smbsrv/smb_sid.h>
-#include <smbsrv/smb_xdr.h>
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-/*
- * An MSRPC compatible implementation of OSF DCE RPC.  DCE RPC is derived
- * from the Apollo Network Computing Architecture (NCA) RPC implementation.
- *
- * CAE Specification (1997)
- * DCE 1.1: Remote Procedure Call
- * Document Number: C706
- * The Open Group
- * ogspecs@opengroup.org
- *
- * This implementation is based on the DCE Remote Procedure Call spec with
- * enhancements to support Unicode strings.  The diagram below shows the
- * DCE RPC layers compared against ONC SUN RPC.
- *
- *	NDR RPC Layers		Sun RPC Layers		Remark
- *	+---------------+	+---------------+	+---------------+
- *	+---------------+	+---------------+
- *	| Application	|	| Application	|	The application
- *	+---------------+	+---------------+
- *	| Hand coded    |	| RPCGEN gen'd  |	Where the real
- *	| client/server |	| client/server |	work happens
- *	| srvsvc.ndl	|	| *_svc.c *_clnt|
- *	| srvsvc.c	|	|               |
- *	+---------------+	+---------------+
- *	| RPC Library	|	| RPC Library   |	Calls/Return
- *	| ndr_*.c       |	|               |	Binding/PMAP
- *	+---------------+	+---------------+
- *	| RPC Protocol	|	| RPC Protocol  |	Headers, Auth,
- *	| rpcpdu.ndl    |	|               |
- *	+---------------+	+---------------+
- *	| IDL gen'd	|	| RPCGEN gen'd  |	Aggregate
- *	| NDR stubs	|	| XDR stubs     |	Composition
- *	| *__ndr.c      |	| *_xdr.c       |
- *	+---------------+	+---------------+
- *	| NDR Represen	|	| XDR Represen  |	Byte order, padding
- *	+---------------+	+---------------+
- *	| Packet Heaps  |	| Network Conn  |	DCERPC does not talk
- *	| ndo_*.c       |	| clnt_{tcp,udp}|	directly to network.
- *	+---------------+	+---------------+
- *
- * There are two major differences between the DCE RPC and ONC RPC:
- *
- * 1. NDR RPC only generates or processes packets from buffers.  Other
- *    layers must take care of packet transmission and reception.
- *    The packet heaps are managed through a simple interface provided
- *    by the Network Data Representation (NDR) module called ndr_stream_t.
- *    ndo_*.c modules implement the different flavors (operations) of
- *    packet heaps.
- *
- *    ONC RPC communicates directly with the network.  You have to do
- *    something special for the RPC packet to be placed in a buffer
- *    rather than sent to the wire.
- *
- * 2. NDR RPC uses application provided heaps to support operations.
- *    A heap is a single, monolithic chunk of memory that NDR RPC manages
- *    as it allocates.  When the operation and its result are done, the
- *    heap is disposed of as a single item.  The transaction, which
- *    is the anchor of most operations, contains the necessary book-
- *    keeping for the heap.
- *
- *    ONC RPC uses malloc() liberally throughout its run-time system.
- *    To free results, ONC RPC supports an XDR_FREE operation that
- *    traverses data structures freeing memory as it goes, whether
- *    it was malloc'd or not.
- */
-
-/*
- * Dispatch Return Code (DRC)
- *
- *	0x8000	15:01	Set to indicate a fault, clear indicates status
- *	0x7F00	08:07	Status/Fault specific
- *	0x00FF	00:08	PTYPE_... of PDU, 0xFF for header
- */
-#define	NDR_DRC_OK				0x0000
-#define	NDR_DRC_MASK_FAULT			0x8000
-#define	NDR_DRC_MASK_SPECIFIER			0xFF00
-#define	NDR_DRC_MASK_PTYPE			0x00FF
-
-/* Fake PTYPE DRC discriminators */
-#define	NDR_DRC_PTYPE_RPCHDR(DRC)		((DRC) | 0x00FF)
-#define	NDR_DRC_PTYPE_API(DRC)			((DRC) | 0x00AA)
-
-/* DRC Recognizers */
-#define	NDR_DRC_IS_OK(DRC)	(((DRC) & NDR_DRC_MASK_SPECIFIER) == 0)
-#define	NDR_DRC_IS_FAULT(DRC)	(((DRC) & NDR_DRC_MASK_FAULT) != 0)
-
-/*
- * (Un)Marshalling category specifiers
- */
-#define	NDR_DRC_FAULT_MODE_MISMATCH		0x8100
-#define	NDR_DRC_RECEIVED			0x0200
-#define	NDR_DRC_FAULT_RECEIVED_RUNT		0x8300
-#define	NDR_DRC_FAULT_RECEIVED_MALFORMED	0x8400
-#define	NDR_DRC_DECODED				0x0500
-#define	NDR_DRC_FAULT_DECODE_FAILED		0x8600
-#define	NDR_DRC_ENCODED				0x0700
-#define	NDR_DRC_FAULT_ENCODE_FAILED		0x8800
-#define	NDR_DRC_FAULT_ENCODE_TOO_BIG		0x8900
-#define	NDR_DRC_SENT				0x0A00
-#define	NDR_DRC_FAULT_SEND_FAILED		0x8B00
-
-/*
- * Resource category specifier
- */
-#define	NDR_DRC_FAULT_RESOURCE_1		0x9100
-#define	NDR_DRC_FAULT_RESOURCE_2		0x9200
-
-/*
- * Parameters. Usually #define'd with useful alias
- */
-#define	NDR_DRC_FAULT_PARAM_0_INVALID		0xC000
-#define	NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED	0xD000
-#define	NDR_DRC_FAULT_PARAM_1_INVALID		0xC100
-#define	NDR_DRC_FAULT_PARAM_1_UNIMPLEMENTED	0xD100
-#define	NDR_DRC_FAULT_PARAM_2_INVALID		0xC200
-#define	NDR_DRC_FAULT_PARAM_2_UNIMPLEMENTED	0xD200
-#define	NDR_DRC_FAULT_PARAM_3_INVALID		0xC300
-#define	NDR_DRC_FAULT_PARAM_3_UNIMPLEMENTED	0xD300
-
-#define	NDR_DRC_FAULT_OUT_OF_MEMORY		0xF000
-
-/* RPCHDR */
-#define	NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH	0x81FF
-#define	NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT	0x83FF
-#define	NDR_DRC_FAULT_RPCHDR_DECODE_FAILED	0x86FF
-#define	NDR_DRC_FAULT_RPCHDR_PTYPE_INVALID	0xC0FF	/* PARAM_0_INVALID */
-#define	NDR_DRC_FAULT_RPCHDR_PTYPE_UNIMPLEMENTED 0xD0FF	/* PARAM_0_UNIMP */
-
-/* Request */
-#define	NDR_DRC_FAULT_REQUEST_PCONT_INVALID	0xC000	/* PARAM_0_INVALID */
-#define	NDR_DRC_FAULT_REQUEST_OPNUM_INVALID	0xC100	/* PARAM_1_INVALID */
-
-/* Bind */
-#define	NDR_DRC_BINDING_MADE			0x000B	/* OK */
-#define	NDR_DRC_FAULT_BIND_PCONT_BUSY		0xC00B	/* PARAM_0_INVALID */
-#define	NDR_DRC_FAULT_BIND_UNKNOWN_SERVICE	0xC10B	/* PARAM_1_INVALID */
-#define	NDR_DRC_FAULT_BIND_NO_SLOTS		0x910B	/* RESOURCE_1 */
-
-/* API */
-#define	NDR_DRC_FAULT_API_SERVICE_INVALID	0xC0AA	/* PARAM_0_INVALID */
-#define	NDR_DRC_FAULT_API_BIND_NO_SLOTS		0x91AA	/* RESOURCE_1 */
-#define	NDR_DRC_FAULT_API_OPNUM_INVALID		0xC1AA	/* PARAM_1_INVALID */
-
-struct ndr_xa;
-struct ndr_client;
-
-typedef struct ndr_stub_table {
-	int		(*func)(void *, struct ndr_xa *);
-	unsigned short	opnum;
-} ndr_stub_table_t;
-
-typedef struct ndr_service {
-	char		*name;
-	char		*desc;
-	char		*endpoint;
-	char		*sec_addr_port;
-	char		*abstract_syntax_uuid;
-	int		abstract_syntax_version;
-	char		*transfer_syntax_uuid;
-	int		transfer_syntax_version;
-	unsigned	bind_instance_size;
-	int		(*bind_req)();
-	int		(*unbind_and_close)();
-	int		(*call_stub)(struct ndr_xa *);
-	ndr_typeinfo_t	*interface_ti;
-	ndr_stub_table_t *stub_table;
-} ndr_service_t;
-
-/*
- * The list of bindings is anchored at a connection.  Nothing in the
- * RPC mechanism allocates them.  Binding elements which have service==0
- * indicate free elements.  When a connection is instantiated, at least
- * one free binding entry should also be established.  Something like
- * this should suffice for most (all) situations:
- *
- *	struct connection {
- *		....
- *		ndr_binding_t *binding_list_head;
- *		ndr_binding_t binding_pool[N_BINDING_POOL];
- *		....
- *	};
- *
- *	init_connection(struct connection *conn) {
- *		....
- *		ndr_svc_binding_pool_init(&conn->binding_list_head,
- *		    conn->binding_pool, N_BINDING_POOL);
- */
-typedef struct ndr_binding {
-	struct ndr_binding 	*next;
-	ndr_p_context_id_t	p_cont_id;
-	unsigned char		which_side;
-	struct ndr_client	*clnt;
-	ndr_service_t		*service;
-	void 			*instance_specific;
-} ndr_binding_t;
-
-#define	NDR_BIND_SIDE_CLIENT	1
-#define	NDR_BIND_SIDE_SERVER	2
-
-#define	NDR_BINDING_TO_SPECIFIC(BINDING, TYPE) \
-	((TYPE *) (BINDING)->instance_specific)
-
-/*
- * The binding list space must be provided by the application library
- * for use by the underlying RPC library.  We need at least two binding
- * slots per connection.
- */
-#define	NDR_N_BINDING_POOL	2
-
-typedef struct ndr_pipe {
-	void 			*np_listener;
-	const char		*np_endpoint;
-	smb_netuserinfo_t	*np_user;
-	int			(*np_send)(struct ndr_pipe *, void *, size_t);
-	int			(*np_recv)(struct ndr_pipe *, void *, size_t);
-	int			np_fid;
-	uint16_t		np_max_xmit_frag;
-	uint16_t		np_max_recv_frag;
-	ndr_binding_t		*np_binding;
-	ndr_binding_t		np_binding_pool[NDR_N_BINDING_POOL];
-} ndr_pipe_t;
-
-/*
- * Number of bytes required to align SIZE on the next dword/4-byte
- * boundary.
- */
-#define	NDR_ALIGN4(SIZE)	((4 - (SIZE)) & 3);
-
-/*
- * DCE RPC strings (CAE section 14.3.4) are represented as varying or varying
- * and conformant one-dimensional arrays. Characters can be single-byte
- * or multi-byte as long as all characters conform to a fixed element size,
- * i.e. UCS-2 is okay but UTF-8 is not a valid DCE RPC string format. The
- * string is terminated by a null character of the appropriate element size.
- *
- * MSRPC strings should always be varying/conformant and not null terminated.
- * This format uses the size_is, first_is and length_is attributes (CAE
- * section 4.2.18).
- *
- *	typedef struct string {
- *		DWORD size_is;
- *		DWORD first_is;
- *		DWORD length_is;
- *		wchar_t string[ANY_SIZE_ARRAY];
- *	} string_t;
- *
- * The size_is attribute is used to specify the number of data elements in
- * each dimension of an array.
- *
- * The first_is attribute is used to define the lower bound for significant
- * elements in each dimension of an array. For strings this is always 0.
- *
- * The length_is attribute is used to define the number of significant
- * elements in each dimension of an array. For strings this is typically
- * the same as size_is. Although it might be (size_is - 1) if the string
- * is null terminated.
- *
- *   4 bytes   4 bytes   4 bytes  2bytes 2bytes 2bytes 2bytes
- * +---------+---------+---------+------+------+------+------+
- * |size_is  |first_is |length_is| char | char | char | char |
- * +---------+---------+---------+------+------+------+------+
- *
- * Unfortunately, not all MSRPC Unicode strings are null terminated, which
- * means that the recipient has to manually null-terminate the string after
- * it has been unmarshalled.  There may be a wide-char pad following a
- * string, and it may sometimes contains zero, but it's not guaranteed.
- *
- * To deal with this, MSRPC sometimes uses an additional wrapper with two
- * more fields, as shown below.
- *	length: the array length in bytes excluding terminating null bytes
- *	maxlen: the array length in bytes including null terminator bytes
- *	LPTSTR: converted to a string_t by NDR
- *
- * typedef struct ms_string {
- *		WORD length;
- *		WORD maxlen;
- *		LPTSTR str;
- * } ms_string_t;
- */
-typedef struct ndr_mstring {
-	uint16_t length;
-	uint16_t allosize;
-	LPTSTR str;
-} ndr_mstring_t;
-
-/*
- * A number of heap areas are used during marshalling and unmarshalling.
- * Under some circumstances these areas can be discarded by the library
- * code, i.e. on the server side before returning to the client and on
- * completion of a client side bind.  In the case of a client side RPC
- * call, these areas must be preserved after an RPC returns to give the
- * caller time to take a copy of the data.  In this case the client must
- * call ndr_clnt_free_heap to free the memory.
- *
- * The heap management data definition looks a bit like this:
- *
- * heap -> +---------------+     +------------+
- *         | iovec[0].base | --> | data block |
- *         | iovec[0].len  |     +------------+
- *         +---------------+
- *                ::
- *                ::
- * iov  -> +---------------+     +------------+
- *         | iovec[n].base | --> | data block |
- *         | iovec[n].len  |     +------------+
- *         +---------------+     ^            ^
- *                               |            |
- *    next ----------------------+            |
- *    top  -----------------------------------+
- *
- */
-
-/*
- * Setting MAXIOV to 384 will use ((8 * 384) + 16) = 3088 bytes
- * of the first heap block.
- */
-#define	NDR_HEAP_MAXIOV		384
-#define	NDR_HEAP_BLKSZ		8192
-
-typedef struct ndr_heap {
-	struct iovec iovec[NDR_HEAP_MAXIOV];
-	struct iovec *iov;
-	int iovcnt;
-	char *top;
-	char *next;
-} ndr_heap_t;
-
-/*
- * Alternate varying/conformant string definition
- * - for non-null-terminated strings.
- */
-typedef struct ndr_vcs {
-	/*
-	 * size_is (actually a copy of length_is) will
-	 * be inserted here by the marshalling library.
-	 */
-	uint32_t vc_first_is;
-	uint32_t vc_length_is;
-	uint16_t buffer[ANY_SIZE_ARRAY];
-} ndr_vcs_t;
-
-typedef struct ndr_vcstr {
-	uint16_t wclen;
-	uint16_t wcsize;
-	ndr_vcs_t *vcs;
-} ndr_vcstr_t;
-
-typedef struct ndr_vcb {
-	/*
-	 * size_is (actually a copy of length_is) will
-	 * be inserted here by the marshalling library.
-	 */
-	uint32_t vc_first_is;
-	uint32_t vc_length_is;
-	uint8_t buffer[ANY_SIZE_ARRAY];
-} ndr_vcb_t;
-
-typedef struct ndr_vcbuf {
-	uint16_t len;
-	uint16_t size;
-	ndr_vcb_t *vcb;
-} ndr_vcbuf_t;
-
-ndr_heap_t *ndr_heap_create(void);
-void ndr_heap_destroy(ndr_heap_t *);
-void *ndr_heap_malloc(ndr_heap_t *, unsigned);
-void *ndr_heap_strdup(ndr_heap_t *, const char *);
-int ndr_heap_mstring(ndr_heap_t *, const char *, ndr_mstring_t *);
-void ndr_heap_mkvcs(ndr_heap_t *, char *, ndr_vcstr_t *);
-void ndr_heap_mkvcb(ndr_heap_t *, uint8_t *, uint32_t, ndr_vcbuf_t *);
-smb_sid_t *ndr_heap_siddup(ndr_heap_t *, smb_sid_t *);
-int ndr_heap_used(ndr_heap_t *);
-int ndr_heap_avail(ndr_heap_t *);
-
-#define	NDR_MALLOC(XA, SZ)	ndr_heap_malloc((XA)->heap, SZ)
-#define	NDR_NEW(XA, T)		ndr_heap_malloc((XA)->heap, sizeof (T))
-#define	NDR_NEWN(XA, T, N)	ndr_heap_malloc((XA)->heap, sizeof (T)*(N))
-#define	NDR_STRDUP(XA, S)	ndr_heap_strdup((XA)->heap, (S))
-#define	NDR_MSTRING(XA, S, OUT)	ndr_heap_mstring((XA)->heap, (S), (OUT))
-#define	NDR_SIDDUP(XA, S)	ndr_heap_siddup((XA)->heap, (S))
-
-typedef struct ndr_xa {
-	unsigned short		ptype;		/* high bits special */
-	unsigned short		opnum;
-	ndr_stream_t		recv_nds;
-	ndr_hdr_t		recv_hdr;
-	ndr_stream_t		send_nds;
-	ndr_hdr_t		send_hdr;
-	ndr_binding_t		*binding;	/* what we're using */
-	ndr_binding_t		*binding_list;	/* from connection */
-	ndr_heap_t		*heap;
-	ndr_pipe_t		*pipe;
-} ndr_xa_t;
-
-/*
- * 20-byte opaque id used by various RPC services.
- */
-CONTEXT_HANDLE(ndr_hdid) ndr_hdid_t;
-
-typedef struct ndr_client {
-	/* transport stuff (xa_* members) */
-	int (*xa_init)(struct ndr_client *, ndr_xa_t *);
-	int (*xa_exchange)(struct ndr_client *, ndr_xa_t *);
-	int (*xa_read)(struct ndr_client *, ndr_xa_t *);
-	void (*xa_preserve)(struct ndr_client *, ndr_xa_t *);
-	void (*xa_destruct)(struct ndr_client *, ndr_xa_t *);
-	void (*xa_release)(struct ndr_client *);
-	void			*xa_private;
-	int			xa_fd;
-
-	ndr_hdid_t		*handle;
-	ndr_binding_t		*binding;
-	ndr_binding_t		*binding_list;
-	ndr_binding_t		binding_pool[NDR_N_BINDING_POOL];
-
-	boolean_t		nonull;
-	boolean_t		heap_preserved;
-	ndr_heap_t		*heap;
-	ndr_stream_t		*recv_nds;
-	ndr_stream_t		*send_nds;
-
-	uint32_t		next_call_id;
-	unsigned		next_p_cont_id;
-} ndr_client_t;
-
-typedef struct ndr_handle {
-	ndr_hdid_t		nh_id;
-	struct ndr_handle	*nh_next;
-	ndr_pipe_t		*nh_pipe;
-	const ndr_service_t	*nh_svc;
-	ndr_client_t		*nh_clnt;
-	void			*nh_data;
-	void			(*nh_data_free)(void *);
-} ndr_handle_t;
-
-#define	NDR_PDU_SIZE_HINT_DEFAULT	(16*1024)
-#define	NDR_BUF_MAGIC			0x4E425546	/* NBUF */
-
-typedef struct ndr_buf {
-	uint32_t		nb_magic;
-	ndr_stream_t		nb_nds;
-	ndr_heap_t		*nb_heap;
-	ndr_typeinfo_t		*nb_ti;
-} ndr_buf_t;
-
-/* ndr_ops.c */
-int nds_initialize(ndr_stream_t *, unsigned, int, ndr_heap_t *);
-void nds_destruct(ndr_stream_t *);
-void nds_show_state(ndr_stream_t *);
-
-/* ndr_client.c */
-int ndr_clnt_bind(ndr_client_t *, const char *, ndr_binding_t **);
-int ndr_clnt_call(ndr_binding_t *, int, void *);
-void ndr_clnt_free_heap(ndr_client_t *);
-
-/* ndr_marshal.c */
-ndr_buf_t *ndr_buf_init(ndr_typeinfo_t *);
-void ndr_buf_fini(ndr_buf_t *);
-int ndr_buf_decode(ndr_buf_t *, unsigned, unsigned, const char *data, size_t,
-    void *);
-int ndr_decode_call(ndr_xa_t *, void *);
-int ndr_encode_return(ndr_xa_t *, void *);
-int ndr_encode_call(ndr_xa_t *, void *);
-int ndr_decode_return(ndr_xa_t *, void *);
-int ndr_decode_pdu_hdr(ndr_xa_t *);
-int ndr_encode_pdu_hdr(ndr_xa_t *);
-void ndr_decode_frag_hdr(ndr_stream_t *, ndr_common_header_t *);
-void ndr_remove_frag_hdr(ndr_stream_t *);
-void ndr_show_hdr(ndr_common_header_t *);
-unsigned ndr_bind_ack_hdr_size(ndr_xa_t *);
-unsigned ndr_alter_context_rsp_hdr_size(void);
-
-/* ndr_server.c */
-void ndr_pipe_worker(ndr_pipe_t *);
-
-int ndr_generic_call_stub(ndr_xa_t *);
-
-boolean_t ndr_is_admin(ndr_xa_t *);
-boolean_t ndr_is_poweruser(ndr_xa_t *);
-int32_t ndr_native_os(ndr_xa_t *);
-
-/* ndr_svc.c */
-ndr_stub_table_t *ndr_svc_find_stub(ndr_service_t *, int);
-ndr_service_t *ndr_svc_lookup_name(const char *);
-ndr_service_t *ndr_svc_lookup_uuid(ndr_uuid_t *, int, ndr_uuid_t *, int);
-int ndr_svc_register(ndr_service_t *);
-void ndr_svc_unregister(ndr_service_t *);
-void ndr_svc_binding_pool_init(ndr_binding_t **, ndr_binding_t pool[], int);
-ndr_binding_t *ndr_svc_find_binding(ndr_xa_t *, ndr_p_context_id_t);
-ndr_binding_t *ndr_svc_new_binding(ndr_xa_t *);
-
-int ndr_uuid_parse(char *, ndr_uuid_t *);
-void ndr_uuid_unparse(ndr_uuid_t *, char *);
-
-ndr_hdid_t *ndr_hdalloc(const ndr_xa_t *, const void *);
-void ndr_hdfree(const ndr_xa_t *, const ndr_hdid_t *);
-ndr_handle_t *ndr_hdlookup(const ndr_xa_t *, const ndr_hdid_t *);
-void ndr_hdclose(ndr_pipe_t *);
-
-ssize_t ndr_uiomove(caddr_t, size_t, enum uio_rw, struct uio *);
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _LIBMLRPC_H */
--- /dev/null	Sun Mar 18 01:13:15 2018
+++ new/usr/src/lib/libmlrpc/common/libmlrpc.h	Sun Mar 18 01:13:15 2018
@@ -0,0 +1,572 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+#ifndef	_LIBMLRPC_H
+#define	_LIBMLRPC_H
+
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <smb/wintypes.h>
+#include <libmlrpc/ndr.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * An MSRPC compatible implementation of OSF DCE RPC.  DCE RPC is derived
+ * from the Apollo Network Computing Architecture (NCA) RPC implementation.
+ *
+ * CAE Specification (1997)
+ * DCE 1.1: Remote Procedure Call
+ * Document Number: C706
+ * The Open Group
+ * ogspecs@opengroup.org
+ *
+ * This implementation is based on the DCE Remote Procedure Call spec with
+ * enhancements to support Unicode strings.  The diagram below shows the
+ * DCE RPC layers compared against ONC SUN RPC.
+ *
+ *	NDR RPC Layers		Sun RPC Layers		Remark
+ *	+---------------+	+---------------+	+---------------+
+ *	+---------------+	+---------------+
+ *	| Application	|	| Application	|	The application
+ *	+---------------+	+---------------+
+ *	| Hand coded    |	| RPCGEN gen'd  |	Where the real
+ *	| client/server |	| client/server |	work happens
+ *	| srvsvc.ndl	|	| *_svc.c *_clnt|
+ *	| srvsvc.c	|	|               |
+ *	+---------------+	+---------------+
+ *	| RPC Library	|	| RPC Library   |	Calls/Return
+ *	| ndr_*.c       |	|               |	Binding/PMAP
+ *	+---------------+	+---------------+
+ *	| RPC Protocol	|	| RPC Protocol  |	Headers, Auth,
+ *	| rpcpdu.ndl    |	|               |
+ *	+---------------+	+---------------+
+ *	| IDL gen'd	|	| RPCGEN gen'd  |	Aggregate
+ *	| NDR stubs	|	| XDR stubs     |	Composition
+ *	| *__ndr.c      |	| *_xdr.c       |
+ *	+---------------+	+---------------+
+ *	| NDR Represen	|	| XDR Represen  |	Byte order, padding
+ *	+---------------+	+---------------+
+ *	| Packet Heaps  |	| Network Conn  |	DCERPC does not talk
+ *	| ndo_*.c       |	| clnt_{tcp,udp}|	directly to network.
+ *	+---------------+	+---------------+
+ *
+ * There are two major differences between the DCE RPC and ONC RPC:
+ *
+ * 1. NDR RPC only generates or processes packets from buffers.  Other
+ *    layers must take care of packet transmission and reception.
+ *    The packet heaps are managed through a simple interface provided
+ *    by the Network Data Representation (NDR) module called ndr_stream_t.
+ *    ndo_*.c modules implement the different flavors (operations) of
+ *    packet heaps.
+ *
+ *    ONC RPC communicates directly with the network.  You have to do
+ *    something special for the RPC packet to be placed in a buffer
+ *    rather than sent to the wire.
+ *
+ * 2. NDR RPC uses application provided heaps to support operations.
+ *    A heap is a single, monolithic chunk of memory that NDR RPC manages
+ *    as it allocates.  When the operation and its result are done, the
+ *    heap is disposed of as a single item.  The transaction, which
+ *    is the anchor of most operations, contains the necessary book-
+ *    keeping for the heap.
+ *
+ *    ONC RPC uses malloc() liberally throughout its run-time system.
+ *    To free results, ONC RPC supports an XDR_FREE operation that
+ *    traverses data structures freeing memory as it goes, whether
+ *    it was malloc'd or not.
+ */
+
+/*
+ * Dispatch Return Code (DRC)
+ *
+ *	0x8000	15:01	Set to indicate a fault, clear indicates status
+ *	0x7F00	08:07	Status/Fault specific
+ *	0x00FF	00:08	PTYPE_... of PDU, 0xFF for header
+ */
+#define	NDR_DRC_OK				0x0000
+#define	NDR_DRC_MASK_FAULT			0x8000
+#define	NDR_DRC_MASK_SPECIFIER			0xFF00
+#define	NDR_DRC_MASK_PTYPE			0x00FF
+
+/* Fake PTYPE DRC discriminators */
+#define	NDR_DRC_PTYPE_RPCHDR(DRC)		((DRC) | 0x00FF)
+#define	NDR_DRC_PTYPE_API(DRC)			((DRC) | 0x00AA)
+
+/* DRC Recognizers */
+#define	NDR_DRC_IS_OK(DRC)	(((DRC) & NDR_DRC_MASK_SPECIFIER) == 0)
+#define	NDR_DRC_IS_FAULT(DRC)	(((DRC) & NDR_DRC_MASK_FAULT) != 0)
+
+/*
+ * (Un)Marshalling category specifiers
+ */
+#define	NDR_DRC_FAULT_MODE_MISMATCH		0x8100
+#define	NDR_DRC_RECEIVED			0x0200
+#define	NDR_DRC_FAULT_RECEIVED_RUNT		0x8300
+#define	NDR_DRC_FAULT_RECEIVED_MALFORMED	0x8400
+#define	NDR_DRC_DECODED				0x0500
+#define	NDR_DRC_FAULT_DECODE_FAILED		0x8600
+#define	NDR_DRC_ENCODED				0x0700
+#define	NDR_DRC_FAULT_ENCODE_FAILED		0x8800
+#define	NDR_DRC_FAULT_ENCODE_TOO_BIG		0x8900
+#define	NDR_DRC_SENT				0x0A00
+#define	NDR_DRC_FAULT_SEND_FAILED		0x8B00
+
+/*
+ * Resource category specifier
+ */
+#define	NDR_DRC_FAULT_RESOURCE_1		0x9100
+#define	NDR_DRC_FAULT_RESOURCE_2		0x9200
+
+/*
+ * Parameters. Usually #define'd with useful alias
+ */
+#define	NDR_DRC_FAULT_PARAM_0_INVALID		0xC000
+#define	NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED	0xD000
+#define	NDR_DRC_FAULT_PARAM_1_INVALID		0xC100
+#define	NDR_DRC_FAULT_PARAM_1_UNIMPLEMENTED	0xD100
+#define	NDR_DRC_FAULT_PARAM_2_INVALID		0xC200
+#define	NDR_DRC_FAULT_PARAM_2_UNIMPLEMENTED	0xD200
+#define	NDR_DRC_FAULT_PARAM_3_INVALID		0xC300
+#define	NDR_DRC_FAULT_PARAM_3_UNIMPLEMENTED	0xD300
+
+#define	NDR_DRC_FAULT_OUT_OF_MEMORY		0xF000
+
+/* RPCHDR */
+#define	NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH	0x81FF
+#define	NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT	0x83FF
+#define	NDR_DRC_FAULT_RPCHDR_DECODE_FAILED	0x86FF
+#define	NDR_DRC_FAULT_RPCHDR_PTYPE_INVALID	0xC0FF	/* PARAM_0_INVALID */
+#define	NDR_DRC_FAULT_RPCHDR_PTYPE_UNIMPLEMENTED 0xD0FF	/* PARAM_0_UNIMP */
+
+/* Request */
+#define	NDR_DRC_FAULT_REQUEST_PCONT_INVALID	0xC000	/* PARAM_0_INVALID */
+#define	NDR_DRC_FAULT_REQUEST_OPNUM_INVALID	0xC100	/* PARAM_1_INVALID */
+
+/* Bind */
+#define	NDR_DRC_BINDING_MADE			0x000B	/* OK */
+#define	NDR_DRC_FAULT_BIND_PCONT_BUSY		0xC00B	/* PARAM_0_INVALID */
+#define	NDR_DRC_FAULT_BIND_UNKNOWN_SERVICE	0xC10B	/* PARAM_1_INVALID */
+#define	NDR_DRC_FAULT_BIND_NO_SLOTS		0x910B	/* RESOURCE_1 */
+
+/* API */
+#define	NDR_DRC_FAULT_API_SERVICE_INVALID	0xC0AA	/* PARAM_0_INVALID */
+#define	NDR_DRC_FAULT_API_BIND_NO_SLOTS		0x91AA	/* RESOURCE_1 */
+#define	NDR_DRC_FAULT_API_OPNUM_INVALID		0xC1AA	/* PARAM_1_INVALID */
+
+struct ndr_xa;
+struct ndr_client;
+
+typedef struct ndr_stub_table {
+	int		(*func)(void *, struct ndr_xa *);
+	unsigned short	opnum;
+} ndr_stub_table_t;
+
+typedef struct ndr_service {
+	char		*name;
+	char		*desc;
+	char		*endpoint;
+	char		*sec_addr_port;
+	char		*abstract_syntax_uuid;
+	int		abstract_syntax_version;
+	char		*transfer_syntax_uuid;
+	int		transfer_syntax_version;
+	unsigned	bind_instance_size;
+	int		(*bind_req)();
+	int		(*unbind_and_close)();
+	int		(*call_stub)(struct ndr_xa *);
+	ndr_typeinfo_t	*interface_ti;
+	ndr_stub_table_t *stub_table;
+} ndr_service_t;
+
+/*
+ * The list of bindings is anchored at a connection.  Nothing in the
+ * RPC mechanism allocates them.  Binding elements which have service==0
+ * indicate free elements.  When a connection is instantiated, at least
+ * one free binding entry should also be established.  Something like
+ * this should suffice for most (all) situations:
+ *
+ *	struct connection {
+ *		....
+ *		ndr_binding_t *binding_list_head;
+ *		ndr_binding_t binding_pool[N_BINDING_POOL];
+ *		....
+ *	};
+ *
+ *	init_connection(struct connection *conn) {
+ *		....
+ *		ndr_svc_binding_pool_init(&conn->binding_list_head,
+ *		    conn->binding_pool, N_BINDING_POOL);
+ */
+typedef struct ndr_binding {
+	struct ndr_binding 	*next;
+	ndr_p_context_id_t	p_cont_id;
+	unsigned char		which_side;
+	struct ndr_client	*clnt;
+	ndr_service_t		*service;
+	void 			*instance_specific;
+} ndr_binding_t;
+
+#define	NDR_BIND_SIDE_CLIENT	1
+#define	NDR_BIND_SIDE_SERVER	2
+
+#define	NDR_BINDING_TO_SPECIFIC(BINDING, TYPE) \
+	((TYPE *) (BINDING)->instance_specific)
+
+/*
+ * The binding list space must be provided by the application library
+ * for use by the underlying RPC library.  We need at least two binding
+ * slots per connection.
+ */
+#define	NDR_N_BINDING_POOL	2
+
+typedef struct ndr_pipe {
+	void 			*np_listener;
+	const char		*np_endpoint;
+	struct smb_netuserinfo	*np_user;
+	int			(*np_send)(struct ndr_pipe *, void *, size_t);
+	int			(*np_recv)(struct ndr_pipe *, void *, size_t);
+	int			np_fid;
+	uint16_t		np_max_xmit_frag;
+	uint16_t		np_max_recv_frag;
+	ndr_binding_t		*np_binding;
+	ndr_binding_t		np_binding_pool[NDR_N_BINDING_POOL];
+} ndr_pipe_t;
+
+/*
+ * Number of bytes required to align SIZE on the next dword/4-byte
+ * boundary.
+ */
+#define	NDR_ALIGN4(SIZE)	((4 - (SIZE)) & 3);
+
+/*
+ * DCE RPC strings (CAE section 14.3.4) are represented as varying or varying
+ * and conformant one-dimensional arrays. Characters can be single-byte
+ * or multi-byte as long as all characters conform to a fixed element size,
+ * i.e. UCS-2 is okay but UTF-8 is not a valid DCE RPC string format. The
+ * string is terminated by a null character of the appropriate element size.
+ *
+ * MSRPC strings should always be varying/conformant and not null terminated.
+ * This format uses the size_is, first_is and length_is attributes (CAE
+ * section 4.2.18).
+ *
+ *	typedef struct string {
+ *		DWORD size_is;
+ *		DWORD first_is;
+ *		DWORD length_is;
+ *		wchar_t string[ANY_SIZE_ARRAY];
+ *	} string_t;
+ *
+ * The size_is attribute is used to specify the number of data elements in
+ * each dimension of an array.
+ *
+ * The first_is attribute is used to define the lower bound for significant
+ * elements in each dimension of an array. For strings this is always 0.
+ *
+ * The length_is attribute is used to define the number of significant
+ * elements in each dimension of an array. For strings this is typically
+ * the same as size_is. Although it might be (size_is - 1) if the string
+ * is null terminated.
+ *
+ *   4 bytes   4 bytes   4 bytes  2bytes 2bytes 2bytes 2bytes
+ * +---------+---------+---------+------+------+------+------+
+ * |size_is  |first_is |length_is| char | char | char | char |
+ * +---------+---------+---------+------+------+------+------+
+ *
+ * Unfortunately, not all MSRPC Unicode strings are null terminated, which
+ * means that the recipient has to manually null-terminate the string after
+ * it has been unmarshalled.  There may be a wide-char pad following a
+ * string, and it may sometimes contains zero, but it's not guaranteed.
+ *
+ * To deal with this, MSRPC sometimes uses an additional wrapper with two
+ * more fields, as shown below.
+ *	length: the array length in bytes excluding terminating null bytes
+ *	maxlen: the array length in bytes including null terminator bytes
+ *	LPTSTR: converted to a string_t by NDR
+ *
+ * typedef struct ms_string {
+ *		WORD length;
+ *		WORD maxlen;
+ *		LPTSTR str;
+ * } ms_string_t;
+ */
+typedef struct ndr_mstring {
+	uint16_t length;
+	uint16_t allosize;
+	LPTSTR str;
+} ndr_mstring_t;
+
+/*
+ * A number of heap areas are used during marshalling and unmarshalling.
+ * Under some circumstances these areas can be discarded by the library
+ * code, i.e. on the server side before returning to the client and on
+ * completion of a client side bind.  In the case of a client side RPC
+ * call, these areas must be preserved after an RPC returns to give the
+ * caller time to take a copy of the data.  In this case the client must
+ * call ndr_clnt_free_heap to free the memory.
+ *
+ * The heap management data definition looks a bit like this:
+ *
+ * heap -> +---------------+     +------------+
+ *         | iovec[0].base | --> | data block |
+ *         | iovec[0].len  |     +------------+
+ *         +---------------+
+ *                ::
+ *                ::
+ * iov  -> +---------------+     +------------+
+ *         | iovec[n].base | --> | data block |
+ *         | iovec[n].len  |     +------------+
+ *         +---------------+     ^            ^
+ *                               |            |
+ *    next ----------------------+            |
+ *    top  -----------------------------------+
+ *
+ */
+
+/*
+ * Setting MAXIOV to 384 will use ((8 * 384) + 16) = 3088 bytes
+ * of the first heap block.
+ */
+#define	NDR_HEAP_MAXIOV		384
+#define	NDR_HEAP_BLKSZ		8192
+
+typedef struct ndr_heap {
+	struct iovec iovec[NDR_HEAP_MAXIOV];
+	struct iovec *iov;
+	int iovcnt;
+	char *top;
+	char *next;
+} ndr_heap_t;
+
+/*
+ * Alternate varying/conformant string definition
+ * - for non-null-terminated strings.
+ */
+typedef struct ndr_vcs {
+	/*
+	 * size_is (actually a copy of length_is) will
+	 * be inserted here by the marshalling library.
+	 */
+	uint32_t vc_first_is;
+	uint32_t vc_length_is;
+	uint16_t buffer[ANY_SIZE_ARRAY];
+} ndr_vcs_t;
+
+typedef struct ndr_vcstr {
+	uint16_t wclen;
+	uint16_t wcsize;
+	ndr_vcs_t *vcs;
+} ndr_vcstr_t;
+
+typedef struct ndr_vcb {
+	/*
+	 * size_is (actually a copy of length_is) will
+	 * be inserted here by the marshalling library.
+	 */
+	uint32_t vc_first_is;
+	uint32_t vc_length_is;
+	uint8_t buffer[ANY_SIZE_ARRAY];
+} ndr_vcb_t;
+
+typedef struct ndr_vcbuf {
+	uint16_t len;
+	uint16_t size;
+	ndr_vcb_t *vcb;
+} ndr_vcbuf_t;
+
+ndr_heap_t *ndr_heap_create(void);
+void ndr_heap_destroy(ndr_heap_t *);
+void *ndr_heap_dupmem(ndr_heap_t *, const void *, size_t);
+void *ndr_heap_malloc(ndr_heap_t *, unsigned);
+void *ndr_heap_strdup(ndr_heap_t *, const char *);
+int ndr_heap_mstring(ndr_heap_t *, const char *, ndr_mstring_t *);
+void ndr_heap_mkvcs(ndr_heap_t *, char *, ndr_vcstr_t *);
+void ndr_heap_mkvcb(ndr_heap_t *, uint8_t *, uint32_t, ndr_vcbuf_t *);
+int ndr_heap_used(ndr_heap_t *);
+int ndr_heap_avail(ndr_heap_t *);
+
+#define	NDR_MALLOC(XA, SZ)	ndr_heap_malloc((XA)->heap, SZ)
+#define	NDR_NEW(XA, T)		ndr_heap_malloc((XA)->heap, sizeof (T))
+#define	NDR_NEWN(XA, T, N)	ndr_heap_malloc((XA)->heap, sizeof (T)*(N))
+#define	NDR_STRDUP(XA, S)	ndr_heap_strdup((XA)->heap, (S))
+#define	NDR_MSTRING(XA, S, OUT)	ndr_heap_mstring((XA)->heap, (S), (OUT))
+#define	NDR_SIDDUP(XA, S)	ndr_heap_dupmem((XA)->heap, (S), smb_sid_len(S))
+
+typedef struct ndr_xa {
+	unsigned short		ptype;		/* high bits special */
+	unsigned short		opnum;
+	ndr_stream_t		recv_nds;
+	ndr_hdr_t		recv_hdr;
+	ndr_stream_t		send_nds;
+	ndr_hdr_t		send_hdr;
+	ndr_binding_t		*binding;	/* what we're using */
+	ndr_binding_t		*binding_list;	/* from connection */
+	ndr_heap_t		*heap;
+	ndr_pipe_t		*pipe;
+} ndr_xa_t;
+
+/*
+ * 20-byte opaque id used by various RPC services.
+ */
+CONTEXT_HANDLE(ndr_hdid) ndr_hdid_t;
+
+typedef struct ndr_client {
+	/* transport stuff (xa_* members) */
+	int (*xa_init)(struct ndr_client *, ndr_xa_t *);
+	int (*xa_exchange)(struct ndr_client *, ndr_xa_t *);
+	int (*xa_read)(struct ndr_client *, ndr_xa_t *);
+	void (*xa_preserve)(struct ndr_client *, ndr_xa_t *);
+	void (*xa_destruct)(struct ndr_client *, ndr_xa_t *);
+	void (*xa_release)(struct ndr_client *);
+	void			*xa_private;
+	int			xa_fd;
+
+	ndr_hdid_t		*handle;
+	ndr_binding_t		*binding;
+	ndr_binding_t		*binding_list;
+	ndr_binding_t		binding_pool[NDR_N_BINDING_POOL];
+
+	boolean_t		nonull;
+	boolean_t		heap_preserved;
+	ndr_heap_t		*heap;
+	ndr_stream_t		*recv_nds;
+	ndr_stream_t		*send_nds;
+
+	uint32_t		next_call_id;
+	unsigned		next_p_cont_id;
+} ndr_client_t;
+
+typedef struct ndr_handle {
+	ndr_hdid_t		nh_id;
+	struct ndr_handle	*nh_next;
+	ndr_pipe_t		*nh_pipe;
+	const ndr_service_t	*nh_svc;
+	ndr_client_t		*nh_clnt;
+	void			*nh_data;
+	void			(*nh_data_free)(void *);
+} ndr_handle_t;
+
+#define	NDR_PDU_SIZE_HINT_DEFAULT	(16*1024)
+#define	NDR_BUF_MAGIC			0x4E425546	/* NBUF */
+
+typedef struct ndr_buf {
+	uint32_t		nb_magic;
+	ndr_stream_t		nb_nds;
+	ndr_heap_t		*nb_heap;
+	ndr_typeinfo_t		*nb_ti;
+} ndr_buf_t;
+
+/* ndr_ops.c */
+int nds_initialize(ndr_stream_t *, unsigned, int, ndr_heap_t *);
+void nds_destruct(ndr_stream_t *);
+void nds_show_state(ndr_stream_t *);
+
+/* ndr_client.c */
+int ndr_clnt_bind(ndr_client_t *, ndr_service_t *, ndr_binding_t **);
+int ndr_clnt_call(ndr_binding_t *, int, void *);
+void ndr_clnt_free_heap(ndr_client_t *);
+
+/* ndr_marshal.c */
+ndr_buf_t *ndr_buf_init(ndr_typeinfo_t *);
+void ndr_buf_fini(ndr_buf_t *);
+int ndr_buf_decode(ndr_buf_t *, unsigned, unsigned, const char *data, size_t,
+    void *);
+int ndr_decode_call(ndr_xa_t *, void *);
+int ndr_encode_return(ndr_xa_t *, void *);
+int ndr_encode_call(ndr_xa_t *, void *);
+int ndr_decode_return(ndr_xa_t *, void *);
+int ndr_decode_pdu_hdr(ndr_xa_t *);
+int ndr_encode_pdu_hdr(ndr_xa_t *);
+void ndr_decode_frag_hdr(ndr_stream_t *, ndr_common_header_t *);
+void ndr_remove_frag_hdr(ndr_stream_t *);
+void ndr_show_hdr(ndr_common_header_t *);
+unsigned ndr_bind_ack_hdr_size(ndr_xa_t *);
+unsigned ndr_alter_context_rsp_hdr_size(void);
+
+/* ndr_server.c */
+void ndr_pipe_worker(ndr_pipe_t *);
+
+int ndr_generic_call_stub(ndr_xa_t *);
+
+/* ndr_svc.c */
+ndr_stub_table_t *ndr_svc_find_stub(ndr_service_t *, int);
+ndr_service_t *ndr_svc_lookup_name(const char *);
+ndr_service_t *ndr_svc_lookup_uuid(ndr_uuid_t *, int, ndr_uuid_t *, int);
+int ndr_svc_register(ndr_service_t *);
+void ndr_svc_unregister(ndr_service_t *);
+void ndr_svc_binding_pool_init(ndr_binding_t **, ndr_binding_t pool[], int);
+ndr_binding_t *ndr_svc_find_binding(ndr_xa_t *, ndr_p_context_id_t);
+ndr_binding_t *ndr_svc_new_binding(ndr_xa_t *);
+
+int ndr_uuid_parse(char *, ndr_uuid_t *);
+void ndr_uuid_unparse(ndr_uuid_t *, char *);
+
+ndr_hdid_t *ndr_hdalloc(const ndr_xa_t *, const void *);
+void ndr_hdfree(const ndr_xa_t *, const ndr_hdid_t *);
+ndr_handle_t *ndr_hdlookup(const ndr_xa_t *, const ndr_hdid_t *);
+void ndr_hdclose(ndr_pipe_t *);
+
+ssize_t ndr_uiomove(caddr_t, size_t, enum uio_rw, struct uio *);
+
+/*
+ * An ndr_client_t is created while binding a client connection to hold
+ * the context for calls made using that connection.
+ *
+ * Handles are RPC call specific and we use an inheritance mechanism to
+ * ensure that each handle has a pointer to the client_t.  When the top
+ * level (bind) handle is released, we close the connection.
+ *
+ * There are some places in libmlsvc where the code assumes that the
+ * handle member is first in this struct.  careful
+ */
+typedef struct mlrpc_handle {
+	ndr_hdid_t	handle;		/* keep first */
+	ndr_client_t	*clnt;
+} mlrpc_handle_t;
+
+int mlrpc_clh_create(mlrpc_handle_t *, void *);
+uint32_t mlrpc_clh_bind(mlrpc_handle_t *, ndr_service_t *);
+void mlrpc_clh_unbind(mlrpc_handle_t *);
+void *mlrpc_clh_free(mlrpc_handle_t *);
+
+int ndr_rpc_call(mlrpc_handle_t *, int, void *);
+int ndr_rpc_get_ssnkey(mlrpc_handle_t *, unsigned char *, size_t);
+void *ndr_rpc_malloc(mlrpc_handle_t *, size_t);
+ndr_heap_t *ndr_rpc_get_heap(mlrpc_handle_t *);
+void ndr_rpc_release(mlrpc_handle_t *);
+void ndr_rpc_set_nonull(mlrpc_handle_t *);
+
+boolean_t ndr_is_null_handle(mlrpc_handle_t *);
+boolean_t ndr_is_bind_handle(mlrpc_handle_t *);
+void ndr_inherit_handle(mlrpc_handle_t *, mlrpc_handle_t *);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _LIBMLRPC_H */
--- old/usr/src/lib/smbsrv/libmlrpc/common/llib-lmlrpc	Sun Mar 18 01:13:15 2018
+++ /dev/null	Sun Mar 18 01:13:15 2018
@@ -1,31 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*LINTLIBRARY*/
-/*PROTOLIB1*/
-
-#include <smbsrv/libmlrpc.h>
--- /dev/null	Sun Mar 18 01:13:15 2018
+++ new/usr/src/lib/libmlrpc/common/llib-lmlrpc	Sun Mar 18 01:13:15 2018
@@ -0,0 +1,31 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+/*LINTLIBRARY*/
+/*PROTOLIB1*/
+
+#include <libmlrpc.h>
--- /dev/null	Sun Mar 18 01:13:16 2018
+++ new/usr/src/lib/libmlrpc/common/mapfile-vers	Sun Mar 18 01:13:16 2018
@@ -0,0 +1,115 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+#
+#
+
+#
+# MAPFILE HEADER START
+#
+# WARNING:  STOP NOW.  DO NOT MODIFY THIS FILE.
+# Object versioning must comply with the rules detailed in
+#
+#	usr/src/lib/README.mapfiles
+#
+# You should not be making modifications here until you've read the most current
+# copy of that file. If you need help, contact a gatekeeper for guidance.
+#
+# MAPFILE HEADER END
+#
+
+$mapfile_version 2
+
+SYMBOL_VERSION SUNWprivate {
+    global:
+	mlrpc_clh_bind;
+	mlrpc_clh_create;
+	mlrpc_clh_free;
+	mlrpc_clh_unbind;
+
+	# Allow debug/test programs to provide these.
+	ndo_printf		{ FLAGS = NODIRECT };
+	ndo_trace		{ FLAGS = NODIRECT };
+
+	ndr_buf_decode;
+	ndr_buf_fini;
+	ndr_buf_init;
+	ndr_clnt_bind;
+	ndr_clnt_call;
+	ndr_clnt_free_heap;
+	ndr_generic_call_stub;
+	ndr_heap_avail;
+	ndr_heap_create;
+	ndr_heap_destroy;
+	ndr_heap_dupmem;
+	ndr_heap_malloc;
+	ndr_heap_mkvcb;
+	ndr_heap_mkvcs;
+	ndr_heap_mstring;
+	ndr_heap_strdup;
+	ndr_heap_used;
+	ndr_hdalloc;
+	ndr_hdclose;
+	ndr_hdfree;
+	ndr_hdlookup;
+	ndr_inherit_handle;
+	ndr_inner;
+	ndr_is_bind_handle;
+	ndr_is_null_handle;
+	ndr_mbstowcs;
+	ndr_params;
+	ndr_pipe_worker;
+	ndr_rpc_call;
+	ndr_rpc_get_heap;
+	ndr_rpc_get_ssnkey;
+	ndr_rpc_malloc;
+	ndr_rpc_release;
+	ndr_rpc_set_nonull;
+	ndr_svc_binding_pool_init;
+	ndr_svc_lookup_name;
+	ndr_svc_register;
+	ndr_topmost;
+	ndr_uuid_parse;
+	ndr_uuid_unparse;
+
+	nds_destruct;
+	nds_initialize;
+
+	ndt__char;
+	ndt_s_char;
+	ndt__uchar;
+	ndt_s_uchar;
+	ndt__wchar;
+	ndt_s_wchar;
+	ndt__short;
+	ndt_s_short;
+	ndt__ushort;
+	ndt_s_ushort;
+	ndt__long;
+	ndt_s_long;
+	ndt__ulong;
+	ndt_s_ulong;
+
+    local:
+	*;
+};
--- /dev/null	Sun Mar 18 01:13:16 2018
+++ new/usr/src/lib/libmlrpc/common/mlrpc_clh.c	Sun Mar 18 01:13:16 2018
@@ -0,0 +1,578 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+/*
+ * ML-RPC Client handle interface and support functions.
+ */
+
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/poll.h>
+
+#include <errno.h>
+#include <strings.h>
+#include <unistd.h>
+
+#include <netsmb/smbfs_api.h>
+#include <smb/ntstatus.h>
+#include <libmlrpc.h>
+
+#include <assert.h>
+
+static int ndr_xa_init(ndr_client_t *, ndr_xa_t *);
+static int ndr_xa_exchange(ndr_client_t *, ndr_xa_t *);
+static int ndr_xa_read(ndr_client_t *, ndr_xa_t *);
+static void ndr_xa_preserve(ndr_client_t *, ndr_xa_t *);
+static void ndr_xa_destruct(ndr_client_t *, ndr_xa_t *);
+static void ndr_xa_release(ndr_client_t *);
+
+/* See notes in mlrpc_clh_bind */
+int rpc_pipe_open_retries = 10;
+
+/*
+ * Create an RPC client binding handle using the given smb_ctx.
+ * That context must already have a session and tree connected.
+ *
+ * Returns zero or an errno value.
+ */
+int
+mlrpc_clh_create(mlrpc_handle_t *handle, void *ctx)
+{
+	ndr_client_t	*clnt = NULL;
+
+	if (ctx == NULL)
+		return (EINVAL);
+
+	/*
+	 * Allocate...
+	 */
+	if ((clnt = malloc(sizeof (*clnt))) == NULL)
+		return (ENOMEM);
+	bzero(clnt, sizeof (*clnt));
+
+	clnt->xa_fd = -1;
+
+	/*
+	 * Setup the transport functions.
+	 * Always a named pipe (for now).
+	 */
+	clnt->xa_private = ctx;
+	clnt->xa_init = ndr_xa_init;
+	clnt->xa_exchange = ndr_xa_exchange;
+	clnt->xa_read = ndr_xa_read;
+	clnt->xa_preserve = ndr_xa_preserve;
+	clnt->xa_destruct = ndr_xa_destruct;
+	clnt->xa_release = ndr_xa_release;
+
+	/* See _is_bind_handle */
+	clnt->handle = &handle->handle;
+
+	ndr_svc_binding_pool_init(&clnt->binding_list,
+	    clnt->binding_pool, NDR_N_BINDING_POOL);
+
+	if ((clnt->heap = ndr_heap_create()) == NULL)
+		goto nomem;
+
+	/* success! */
+	bzero(handle, sizeof (*handle));
+	handle->clnt = clnt;
+	return (0);
+
+nomem:
+	free(clnt);
+	return (ENOMEM);
+}
+
+
+/*
+ * This call must be made to initialize an RPC client structure and bind
+ * to the remote service before any RPCs can be exchanged with that service.
+ *
+ * The mlrpc_handle_t is a wrapper that is used to associate an RPC handle
+ * with the client context for an instance of the interface.  The handle
+ * is zeroed to ensure that it doesn't look like a valid handle -
+ * handle content is provided by the remove service.
+ *
+ * The client points to this top-level handle so that we know when to
+ * unbind and teardown the connection.  As each handle is initialized it
+ * will inherit a reference to the client context.
+ *
+ *
+ * Similar to MSRPC RpcBindingBind()
+ *
+ * Returns 0 or an NT_STATUS:		(failed in...)
+ *
+ *	RPC_NT_SERVER_TOO_BUSY		(open pipe)
+ *	RPC_NT_SERVER_UNAVAILABLE	(open pipe)
+ *	NT_STATUS_ACCESS_DENIED		(open pipe)
+ *	NT_STATUS_INVALID_PARAMETER	(rpc bind)
+ *	NT_STATUS_INTERNAL_ERROR	(bad args etc)
+ *	NT_STATUS_NO_MEMORY
+ */
+uint32_t
+mlrpc_clh_bind(mlrpc_handle_t *handle, ndr_service_t *svc)
+{
+	ndr_client_t		*clnt = NULL;
+	struct smb_ctx		*ctx = NULL;
+	uint32_t		status = 0;
+	int			fd = -1;
+	int			rc, retries;
+
+	if ((clnt = handle->clnt) == NULL)
+		return (NT_STATUS_INTERNAL_ERROR);
+	if ((ctx = clnt->xa_private) == NULL)
+		return (NT_STATUS_INTERNAL_ERROR);
+	if (clnt->xa_fd != -1)
+		return (NT_STATUS_INTERNAL_ERROR);
+
+	/*
+	 * Open the named pipe.
+	 *
+	 * Sometimes a DC may return NT_STATUS_PIPE_NOT_AVAILABLE for
+	 * the first few seconds during service auto-start.  The client
+	 * translates that to EBUSY, so when we see that, wait a bit
+	 * and retry the open for up to rpc_pipe_open_retries.  If we
+	 * fail even after retries, return RPC_NT_SERVER_TOO_BUSY,
+	 * which is how callers of this layer expect that reported.
+	 * We try up to 10 times, with a 0.5 sec. wait after each
+	 * BUSY failure, giving a total wait here of 5 sec.
+	 */
+	retries = rpc_pipe_open_retries;
+retry_open:
+	fd = smb_fh_open(ctx, svc->endpoint, O_RDWR);
+	if (fd < 0) {
+		rc = errno;
+		switch (rc) {
+		case EBUSY:
+			if (--retries > 0) {
+				(void) poll(NULL, 0, 500);
+				goto retry_open;
+			}
+			status = RPC_NT_SERVER_TOO_BUSY;
+			break;
+		case EACCES:
+			status = NT_STATUS_ACCESS_DENIED;
+			break;
+		default:
+			status = RPC_NT_SERVER_UNAVAILABLE;
+			break;
+		}
+		return (status);
+	}
+
+	clnt->xa_fd = fd;
+
+	/* Paranoia, in case of re-bind. */
+	bzero(&handle->handle, sizeof (ndr_hdid_t));
+
+	/*
+	 * Do the OtW RPC bind.
+	 */
+	rc = ndr_clnt_bind(clnt, svc, &clnt->binding);
+	switch (rc) {
+	case NDR_DRC_FAULT_OUT_OF_MEMORY:
+		status = NT_STATUS_NO_MEMORY;
+		break;
+	case NDR_DRC_FAULT_API_SERVICE_INVALID:
+		/* svc->..._uuid parse errors */
+		status = NT_STATUS_INTERNAL_ERROR;
+		break;
+	default:
+		if (NDR_DRC_IS_FAULT(rc)) {
+			status = RPC_NT_PROTOCOL_ERROR;
+			break;
+		}
+		/* FALLTHROUGH */
+	case NDR_DRC_OK:
+		status = NT_STATUS_SUCCESS;
+	}
+
+	if (status != 0) {
+		if (fd != -1)
+			(void) smb_fh_close(fd);
+		clnt->xa_fd = -1;
+	}
+
+	return (status);
+}
+
+/*
+ * Unbind and close the pipe to an RPC service.
+ *
+ * Similar to MSRPC RpcBindingUnbind()
+ * This should be called after a dropped connection.
+ */
+void
+mlrpc_clh_unbind(mlrpc_handle_t *handle)
+{
+	ndr_client_t *clnt = handle->clnt;
+
+	if (clnt->xa_fd != -1) {
+		(void) smb_fh_close(clnt->xa_fd);
+		clnt->xa_fd = -1;
+	}
+}
+
+/*
+ * If the heap has been preserved we need to go through an xa release.
+ * The heap is preserved during an RPC call because that's where data
+ * returned from the server is stored.
+ *
+ * Otherwise we destroy the heap directly.
+ *
+ * Returns the xa_private pointer (if non-NULL) to inform the caller
+ * that it can now be destroyed.
+ */
+void *
+mlrpc_clh_free(mlrpc_handle_t *handle)
+{
+	ndr_client_t *clnt = handle->clnt;
+	void *private;
+
+	if (clnt == NULL)
+		return (NULL);
+
+	/*
+	 * Should never get an unbind on inherited handles.
+	 * Callers of ndr_inherit_handle() check handles
+	 * with ndr_is_bind_handle() before calling this.
+	 *
+	 * Maybe make this function more tolerant?
+	 */
+	assert(handle->clnt->handle == &handle->handle);
+
+	mlrpc_clh_unbind(handle);
+
+	if (clnt->heap_preserved)
+		ndr_clnt_free_heap(clnt); /* xa_release */
+	else
+		ndr_heap_destroy(clnt->heap);
+
+	/*
+	 * Note: Caller will free the smb_ctx stored in
+	 * clnt->xa_private (or possibly reuse it).
+	 */
+	private = clnt->xa_private;
+	free(clnt);
+	bzero(handle, sizeof (*handle));
+	return (private);
+}
+
+/*
+ * Call the RPC function identified by opnum.  The remote service is
+ * identified by the handle, which should have been initialized by
+ * ndr_rpc_bind.
+ *
+ * If the RPC call is successful (returns 0), the caller must call
+ * ndr_rpc_release to release the heap.  Otherwise, we release the
+ * heap here.
+ */
+int
+ndr_rpc_call(mlrpc_handle_t *handle, int opnum, void *params)
+{
+	ndr_client_t *clnt = handle->clnt;
+	int rc;
+
+	if (ndr_rpc_get_heap(handle) == NULL)
+		return (-1);
+
+	rc = ndr_clnt_call(clnt->binding, opnum, params);
+
+	/*
+	 * Always clear the nonull flag to ensure
+	 * it is not applied to subsequent calls.
+	 */
+	clnt->nonull = B_FALSE;
+
+	if (NDR_DRC_IS_FAULT(rc)) {
+		ndr_rpc_release(handle);
+		return (-1);
+	}
+
+	return (0);
+}
+
+/*
+ * Outgoing strings should not be null terminated.
+ */
+void
+ndr_rpc_set_nonull(mlrpc_handle_t *handle)
+{
+	handle->clnt->nonull = B_TRUE;
+}
+
+/*
+ * Get the session key from a bound RPC client handle.
+ *
+ * The key returned is the 16-byte "user session key"
+ * established by the underlying authentication protocol
+ * (either Kerberos or NTLM).  This key is needed for
+ * SAM RPC calls such as SamrSetInformationUser, etc.
+ * See [MS-SAMR] sections: 2.2.3.3, 2.2.7.21, 2.2.7.25.
+ *
+ * Returns zero (success) or an errno.
+ */
+int
+ndr_rpc_get_ssnkey(mlrpc_handle_t *handle, uchar_t *key, size_t len)
+{
+	ndr_client_t *clnt = handle->clnt;
+
+	if (clnt == NULL || clnt->xa_fd == -1)
+		return (EINVAL);
+
+	return (smb_fh_getssnkey(clnt->xa_fd, key, len));
+}
+
+void *
+ndr_rpc_malloc(mlrpc_handle_t *handle, size_t size)
+{
+	ndr_heap_t *heap;
+
+	if ((heap = ndr_rpc_get_heap(handle)) == NULL)
+		return (NULL);
+
+	return (ndr_heap_malloc(heap, size));
+}
+
+ndr_heap_t *
+ndr_rpc_get_heap(mlrpc_handle_t *handle)
+{
+	ndr_client_t *clnt = handle->clnt;
+
+	if (clnt->heap == NULL)
+		clnt->heap = ndr_heap_create();
+
+	return (clnt->heap);
+}
+
+/*
+ * Must be called by RPC clients to free the heap after a successful RPC
+ * call, i.e. ndr_rpc_call returned 0.  The caller should take a copy
+ * of any data returned by the RPC prior to calling this function because
+ * returned data is in the heap.
+ */
+void
+ndr_rpc_release(mlrpc_handle_t *handle)
+{
+	ndr_client_t *clnt = handle->clnt;
+
+	if (clnt->heap_preserved)
+		ndr_clnt_free_heap(clnt);
+	else
+		ndr_heap_destroy(clnt->heap);
+
+	clnt->heap = NULL;
+}
+
+/*
+ * Returns true if the handle is null.
+ * Otherwise returns false.
+ */
+boolean_t
+ndr_is_null_handle(mlrpc_handle_t *handle)
+{
+	static const ndr_hdid_t hdid0 = {0};
+
+	if (handle == NULL || handle->clnt == NULL)
+		return (B_TRUE);
+
+	if (!memcmp(&handle->handle, &hdid0, sizeof (hdid0)))
+		return (B_TRUE);
+
+	return (B_FALSE);
+}
+
+/*
+ * Returns true if the handle is the top level bind handle.
+ * Otherwise returns false.
+ */
+boolean_t
+ndr_is_bind_handle(mlrpc_handle_t *handle)
+{
+	return (handle->clnt->handle == &handle->handle);
+}
+
+/*
+ * Pass the client reference from parent to child.
+ */
+void
+ndr_inherit_handle(mlrpc_handle_t *child, mlrpc_handle_t *parent)
+{
+	child->clnt = parent->clnt;
+}
+
+/*
+ * ndr_rpc_status remains in libmlsvc mlsvc_client.c
+ */
+
+/*
+ * The following functions provide the client callback interface.
+ * If the caller hasn't provided a heap, create one here.
+ */
+static int
+ndr_xa_init(ndr_client_t *clnt, ndr_xa_t *mxa)
+{
+	ndr_stream_t *recv_nds = &mxa->recv_nds;
+	ndr_stream_t *send_nds = &mxa->send_nds;
+	ndr_heap_t *heap = clnt->heap;
+	int		rc;
+
+	if (heap == NULL) {
+		if ((heap = ndr_heap_create()) == NULL)
+			return (-1);
+
+		clnt->heap = heap;
+	}
+
+	mxa->heap = heap;
+
+	rc = nds_initialize(send_nds, 0, NDR_MODE_CALL_SEND, heap);
+	if (rc == 0)
+		rc = nds_initialize(recv_nds, NDR_PDU_SIZE_HINT_DEFAULT,
+		    NDR_MODE_RETURN_RECV, heap);
+
+	if (rc != 0) {
+		nds_destruct(&mxa->recv_nds);
+		nds_destruct(&mxa->send_nds);
+		ndr_heap_destroy(mxa->heap);
+		mxa->heap = NULL;
+		clnt->heap = NULL;
+		return (-1);
+	}
+
+	if (clnt->nonull)
+		NDS_SETF(send_nds, NDS_F_NONULL);
+
+	return (0);
+}
+
+/*
+ * This is the entry pointy for an RPC client call exchange with
+ * a server, which will result in an smbrdr SmbTransact request.
+ *
+ * SmbTransact should return the number of bytes received, which
+ * we record as the PDU size, or a negative error code.
+ */
+static int
+ndr_xa_exchange(ndr_client_t *clnt, ndr_xa_t *mxa)
+{
+	ndr_stream_t *recv_nds = &mxa->recv_nds;
+	ndr_stream_t *send_nds = &mxa->send_nds;
+	int err, more, nbytes;
+
+	nbytes = recv_nds->pdu_max_size;
+	err = smb_fh_xactnp(clnt->xa_fd,
+	    send_nds->pdu_size, (char *)send_nds->pdu_base_offset,
+	    &nbytes, (char *)recv_nds->pdu_base_offset, &more);
+	if (err) {
+		recv_nds->pdu_size = 0;
+		return (-1);
+	}
+
+	recv_nds->pdu_size = nbytes;
+	return (0);
+}
+
+/*
+ * This entry point will be invoked if the xa-exchange response contained
+ * only the first fragment of a multi-fragment response.  The RPC client
+ * code will then make repeated xa-read requests to obtain the remaining
+ * fragments, which will result in smbrdr SmbReadX requests.
+ *
+ * SmbReadX should return the number of bytes received, in which case we
+ * expand the PDU size to include the received data, or a negative error
+ * code.
+ */
+static int
+ndr_xa_read(ndr_client_t *clnt, ndr_xa_t *mxa)
+{
+	ndr_stream_t *nds = &mxa->recv_nds;
+	int len;
+	int nbytes;
+
+	if ((len = (nds->pdu_max_size - nds->pdu_size)) < 0)
+		return (-1);
+
+	nbytes = smb_fh_read(clnt->xa_fd, 0, len,
+	    (char *)nds->pdu_base_offset + nds->pdu_size);
+
+	if (nbytes < 0)
+		return (-1);
+
+	nds->pdu_size += nbytes;
+
+	if (nds->pdu_size > nds->pdu_max_size) {
+		nds->pdu_size = nds->pdu_max_size;
+		return (-1);
+	}
+
+	return (nbytes);
+}
+
+/*
+ * Preserve the heap so that the client application has access to data
+ * returned from the server after an RPC call.
+ */
+static void
+ndr_xa_preserve(ndr_client_t *clnt, ndr_xa_t *mxa)
+{
+	assert(clnt->heap == mxa->heap);
+
+	clnt->heap_preserved = B_TRUE;
+	mxa->heap = NULL;
+}
+
+/*
+ * Dispose of the transaction streams.  If the heap has not been
+ * preserved, we can destroy it here.
+ */
+static void
+ndr_xa_destruct(ndr_client_t *clnt, ndr_xa_t *mxa)
+{
+	nds_destruct(&mxa->recv_nds);
+	nds_destruct(&mxa->send_nds);
+
+	if (!clnt->heap_preserved) {
+		ndr_heap_destroy(mxa->heap);
+		mxa->heap = NULL;
+		clnt->heap = NULL;
+	}
+}
+
+/*
+ * Dispose of a preserved heap.
+ */
+static void
+ndr_xa_release(ndr_client_t *clnt)
+{
+	if (clnt->heap_preserved) {
+		ndr_heap_destroy(clnt->heap);
+		clnt->heap = NULL;
+		clnt->heap_preserved = B_FALSE;
+	}
+}
--- old/usr/src/uts/common/smbsrv/ndr.h	Sun Mar 18 01:13:16 2018
+++ /dev/null	Sun Mar 18 01:13:16 2018
@@ -1,467 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
- */
-
-#ifndef _SMBSRV_NDR_H
-#define	_SMBSRV_NDR_H
-
-/*
- * Network Data Representation (NDR) is a compatible subset of DCE RPC
- * and MSRPC NDR.  NDR is used to move parameters consisting of
- * complicated trees of data constructs between an RPC client and server.
- *
- * CAE Specification (1997)
- * DCE 1.1: Remote Procedure Call
- * Document Number: C706
- * The Open Group
- * ogspecs@opengroup.org
- */
-
-#if defined(_KERNEL) || defined(_FAKE_KERNEL)
-#error "not used in kernel code"
-#else /* _KERNEL */
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <syslog.h>
-#include <stdlib.h>
-#include <string.h>
-#include <smbsrv/wintypes.h>
-#include <smbsrv/ndl/rpcpdu.ndl>
-#include <smbsrv/string.h>
-#endif	/* _KERNEL */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Normal sequence:
- *	- Application calls client-side stub w/ TOP-MOST arg structure
- *	- client stub performs NDR_M_OP_MARSHALL+NDR_DIR_IN
- *	- PDU conveyed (request, aka call, aka query)
- *	- server stub performs NDR_M_OP_UNMARSHALL+NDR_DIR_IN
- *	- server function called w/ TOP-MOST arg structure
- *	- server function returns w/ TOP-MOST arg structure modified
- *	- server stub performs NDR_M_OP_MARSHALL+NDR_DIR_OUT
- *	- PDU conveyed (reply, aka result, aka response)
- *	- client stub performs NDR_M_OP_UNMARSHALL+NDR_DIR_OUT
- *	- return to Application w/ TOP-MOST arg structure modified
- *
- * An interface is a sequence of top-most constructs.  Each top-most
- * construct corresponds to one parameter, either argument or return
- * value.
- *
- * A top-most construct is a sequence of outer constructs.  The first
- * outer construct is the referent of the argument, and the subsequent
- * outer constructs are descendents referenced by pointers from prior
- * constructs.
- *
- * An outer construct is a sequence of variable-sized info, fixed-sized
- * data, and variable-sized data.
- */
-
-/*
- * Terminology
- *
- * The ALL UPPER CASE terms recur in the DCE/RPC documentation.
- * The mixed-case names have been introduced as a reading aid.
- *
- * Size		The size of an array in elements. Think of this
- *		as the amount to malloc().
- *
- * Length	The number of elements of an array which are significant
- *		Think of this as the amount to bcopy().
- *
- * Known	Size/length is known at build time.
- *
- * Determined	Size/length is determined at run time.
- *
- * FIXED	The Size and Length are Known.
- *		Think of this as a string constant or a DOS 8.3 file name.
- *		char array[] = "A Constant Size/Length";
- *
- * CONFORMANT	The Size is Determined. Length is the same as Size.
- *		Think of this as strdup().
- *		char *array = strdup("Something");
- *
- * VARYING	The Size is Known. The Length is determined.
- *		Think of this as a strcpy() of a variable length string
- *		into a fixed length buffer:
- *		char array[100];
- *		strcpy(array, "very short string");
- *
- * VARYING/CONFORMANT
- *		The Size is Determined. The Length is separately Determined.
- *		Think of this like:
- *		char *array = malloc(size);
- *		strcpy(array, "short string");
- *
- * STRING	Strings can be CONFORMANT, VARYING, or CONFORMANT/VARYING.
- *		A string is fundamentally an array with the last
- *		significant element some sort of NULL.
- */
-
-#define	NDR_F_NONE		0x0000	/* no flags */
-#define	NDR_F_PARAMS_MASK	0x00FF
-#define	NDR_F_SIZE_IS		0x0001	/* [size_is(X)] required/given */
-#define	NDR_F_LENGTH_IS		0x0002	/* not implemented */
-#define	NDR_F_SWITCH_IS		0x0004	/* [switch_is(X)] req./given */
-#define	NDR_F_IS_STRING		0x0008	/* [string] req./given */
-#define	NDR_F_IS_POINTER	0x0010	/* TYPE * ... req./given */
-#define	NDR_F_IS_REFERENCE	0x0020	/* TYPE & ... req./given */
-#define	NDR_F_DIMENSION_IS	0x0040	/* TYPE [N] req./given */
-
-#define	NDR_F_WHENCE_MASK	0x00F0
-#define	NDR_F_BACKPTR		0x0010	/* ref cause by pointer */
-#define	NDR_F_OUTER		0x0020	/* ref caused by outer */
-#define	NDR_F_TOPMOST		0x0040	/* ref caused by topmost */
-
-#define	NDR_F_TYPEOP_MASK	0x0F00
-#define	NDR_F_ARRAY		0x0100	/* type is array of somethings */
-#define	NDR_F_POINTER		0x0200	/* type is pointer to something(s) */
-#define	NDR_F_STRING		0x0300	/* type is string of somethings */
-#define	NDR_F_UNION		0x0400	/* type is a union */
-#define	NDR_F_STRUCT		0x0500	/* type is a structure */
-#define	NDR_F_OPERATION		0x0600	/* type is a structure, special */
-#define	NDR_F_INTERFACE		0x0700	/* type is a union, special */
-#define	NDR_F_CONFORMANT	0x1000	/* struct conforming (var-size tail) */
-#define	NDR_F_VARYING		0x2000	/* not implemented */
-
-struct ndr_heap;
-struct ndr_stream;
-struct ndr_reference;
-
-typedef uint16_t ndr_wchar_t;
-
-typedef struct ndr_typeinfo {
-	unsigned char		version;	/* sanity check */
-	unsigned char		alignment;	/* mask */
-	unsigned short		type_flags;	/* NDR_F_... */
-	int			(*ndr_func)(struct ndr_reference *);
-	unsigned short		pdu_size_fixed_part;
-	unsigned short		pdu_size_variable_part;
-	unsigned short		c_size_fixed_part;
-	unsigned short		c_size_variable_part;
-} ndr_typeinfo_t;
-
-typedef struct ndr_reference {
-	struct ndr_reference	*next;		/* queue list (outer only) */
-	struct ndr_reference	*enclosing;	/* e.g. struct for this memb */
-	struct ndr_stream	*stream;	/* root of NDR */
-	ndr_typeinfo_t		*ti;		/* type of data referenced */
-	char			*name;		/* name of this member */
-	unsigned long		pdu_offset;	/* referent in stub data */
-	char			*datum;		/* referent in local memory */
-	char			**backptr;	/* referer to set */
-	unsigned short		outer_flags;	/* XXX_is() from top level */
-	unsigned short		inner_flags;	/* XXX_is() in encapsulated */
-	unsigned short		type_flags;	/* "requires" */
-	unsigned short		packed_alignment;
-	unsigned long		size_is;	/* conforming constructs */
-	unsigned long		strlen_is;	/* strings */
-	unsigned long		switch_is;	/* union arg selector */
-	unsigned long		dimension_is;	/* fixed-len array size */
-	unsigned long		pdu_end_offset;	/* offset for limit of PDU */
-} ndr_ref_t;
-
-/*
- * For all operations, the ndr_stream, which is the root of NDR processing,
- * is the primary object.  When available, the appropriate ndr_ref_t
- * is passed, NULL otherwise.  Functions that return 'int' should return
- * TRUE (!0) or FALSE (0).  When functions return FALSE, including
- * ndo_malloc() returning NULL, they should set the stream->error to an
- * appropriate indicator of what went wrong.
- *
- * Functions ndo_get_pdu(), ndo_put_pdu(), and ndo_pad_pdu() must
- * never grow the PDU data.  A request for out-of-bounds data is an error.
- * The swap_bytes flag is 1 if NDR knows that the byte-order in the PDU
- * is different from the local system.  ndo_pad_pdu() advised that the
- * affected bytes should be zero filled.
- */
-typedef struct ndr_stream_ops {
-	char *(*ndo_malloc)(struct ndr_stream *, unsigned, ndr_ref_t *);
-	int (*ndo_free)(struct ndr_stream *, char *, ndr_ref_t *);
-	int (*ndo_grow_pdu)(struct ndr_stream *, unsigned long, ndr_ref_t *);
-	int (*ndo_pad_pdu)(struct ndr_stream *, unsigned long,
-	    unsigned long, ndr_ref_t *);
-	int (*ndo_get_pdu)(struct ndr_stream *, unsigned long,
-	    unsigned long, char *, int, ndr_ref_t *);
-	int (*ndo_put_pdu)(struct ndr_stream *, unsigned long,
-	    unsigned long, char *, int, ndr_ref_t *);
-	void (*ndo_tattle)(struct ndr_stream *, char *, ndr_ref_t *);
-	void (*ndo_tattle_error)(struct ndr_stream *, ndr_ref_t *);
-	int (*ndo_reset)(struct ndr_stream *);
-	void (*ndo_destruct)(struct ndr_stream *);
-} ndr_stream_ops_t;
-
-#define	NDS_MALLOC(NDS, LEN, REF) \
-	(*(NDS)->ndo->ndo_malloc)(NDS, LEN, REF)
-#define	NDS_GROW_PDU(NDS, WANT_END_OFF, REF) \
-	(*(NDS)->ndo->ndo_grow_pdu)(NDS, WANT_END_OFF, REF)
-#define	NDS_PAD_PDU(NDS, PDU_OFFSET, N_BYTES, REF) \
-	(*(NDS)->ndo->ndo_pad_pdu)(NDS, PDU_OFFSET, N_BYTES, REF)
-#define	NDS_GET_PDU(NDS, PDU_OFFSET, N_BYTES, BUF, SWAP, REF) \
-	(*(NDS)->ndo->ndo_get_pdu)(NDS, PDU_OFFSET, N_BYTES, BUF, SWAP, REF)
-#define	NDS_PUT_PDU(NDS, PDU_OFFSET, N_BYTES, BUF, SWAP, REF) \
-	(*(NDS)->ndo->ndo_put_pdu)(NDS, PDU_OFFSET, N_BYTES, BUF, SWAP, REF)
-#define	NDS_TATTLE(NDS, WHAT, REF) \
-	(*(NDS)->ndo->ndo_tattle)(NDS, WHAT, REF)
-#define	NDS_TATTLE_ERROR(NDS, WHAT, REF) \
-	(*(NDS)->ndo->ndo_tattle_error)(NDS, REF)
-#define	NDS_RESET(NDS)		(*(NDS)->ndo->ndo_reset)(NDS)
-#define	NDS_DESTRUCT(NDS)	(*(NDS)->ndo->ndo_destruct)(NDS)
-
-typedef struct ndr_stream {
-	unsigned long		pdu_size;
-	unsigned long		pdu_max_size;
-	unsigned long		pdu_base_offset;
-	unsigned long		pdu_scan_offset;
-	unsigned char		*pdu_base_addr;
-
-	ndr_stream_ops_t	*ndo;
-
-	unsigned char		m_op;
-	unsigned char		dir;
-	unsigned char		swap;		/* native/net endian swap */
-	unsigned char		flags;
-	short			error;
-	short			error_ref;
-
-	ndr_ref_t *outer_queue_head;
-	ndr_ref_t **outer_queue_tailp;
-	ndr_ref_t *outer_current;
-	struct ndr_heap *heap;
-} ndr_stream_t;
-
-#define	NDR_M_OP_NONE		0x00
-#define	NDR_M_OP_MARSHALL	0x01	/* data moving from datum to PDU */
-#define	NDR_M_OP_UNMARSHALL	0x02	/* data moving from PDU to datum */
-
-#define	NDR_DIR_NONE		0x00
-#define	NDR_DIR_IN		0x10	/* data moving from caller to callee */
-#define	NDR_DIR_OUT		0x20	/* data moving from callee to caller */
-
-#define	NDR_MODE_CALL_SEND	(NDR_M_OP_MARSHALL + NDR_DIR_IN)
-#define	NDR_MODE_CALL_RECV	(NDR_M_OP_UNMARSHALL + NDR_DIR_IN)
-#define	NDR_MODE_RETURN_SEND	(NDR_M_OP_MARSHALL + NDR_DIR_OUT)
-#define	NDR_MODE_RETURN_RECV	(NDR_M_OP_UNMARSHALL + NDR_DIR_OUT)
-#define	NDR_MODE_BUF_ENCODE	NDR_MODE_CALL_SEND
-#define	NDR_MODE_BUF_DECODE	NDR_MODE_RETURN_RECV
-
-#define	NDR_MODE_TO_M_OP(MODE)	((MODE) & 0x0F)
-#define	NDR_MODE_TO_DIR(MODE)	((MODE) & 0xF0)
-#define	NDR_M_OP_AND_DIR_TO_MODE(M_OP, DIR)	((M_OP)|(DIR))
-
-#define	NDR_MODE_MATCH(NDS, MODE) \
-	(NDR_M_OP_AND_DIR_TO_MODE((NDS)->m_op, (NDS)->dir) == (MODE))
-
-#define	NDR_IS_FIRST_FRAG(F)	((F) & NDR_PFC_FIRST_FRAG)
-#define	NDR_IS_LAST_FRAG(F)	((F) & NDR_PFC_LAST_FRAG)
-#define	NDR_IS_SINGLE_FRAG(F)	\
-	(NDR_IS_FIRST_FRAG((F)) && NDR_IS_LAST_FRAG((F)))
-
-#define	NDS_F_NONE		0x00
-#define	NDS_F_NOTERM		0x01	/* strings are not null terminated */
-#define	NDS_F_NONULL		0x02	/* strings: no null on size_is */
-#define	NDS_SETF(S, F)		((S)->flags |= (F))
-#define	NDS_CLEARF(S, F)	((S)->flags &= ~(F))
-
-#define	NDR_ERR_MALLOC_FAILED		-1
-#define	NDR_ERR_M_OP_INVALID		-2
-#define	NDR_ERR_UNDERFLOW		-3
-#define	NDR_ERR_GROW_FAILED		-4	/* overflow */
-#define	NDR_ERR_PAD_FAILED		-5	/* couldn't possibly happen */
-#define	NDR_ERR_OUTER_HEADER_BAD	-6
-#define	NDR_ERR_SWITCH_VALUE_ILLEGAL	-7
-#define	NDR_ERR_SWITCH_VALUE_INVALID	-8
-#define	NDR_ERR_SWITCH_VALUE_MISSING	-9
-#define	NDR_ERR_SIZE_IS_MISMATCH_PDU	-10
-#define	NDR_ERR_SIZE_IS_MISMATCH_AFTER	-11
-#define	NDR_ERR_SIZE_IS_UNEXPECTED	-12
-#define	NDR_ERR_SIZE_IS_DUPLICATED	-13
-#define	NDR_ERR_OUTER_PARAMS_MISMATCH	-14
-#define	NDR_ERR_ARRAY_VARLEN_ILLEGAL	-15
-#define	NDR_ERR_ARRAY_UNION_ILLEGAL	-16
-#define	NDR_ERR_OUTER_PARAMS_BAD	-17
-#define	NDR_ERR_OUTER_UNION_ILLEGAL	-18
-#define	NDR_ERR_TOPMOST_UNION_ILLEGAL	-19
-#define	NDR_ERR_TOPMOST_VARLEN_ILLEGAL	-20
-#define	NDR_ERR_INNER_PARAMS_BAD	-21
-#define	NDR_ERR_UNIMPLEMENTED		-22
-#define	NDR_ERR_NOT_AN_INTERFACE	-23
-#define	NDR_ERR_STRLEN			-24
-#define	NDR_ERR_STRING_SIZING		-25
-#define	NDR_ERR_BOUNDS_CHECK		-26
-
-#define	NDR_SET_ERROR(REF, ERROR)			\
-	((REF)->stream->error = (ERROR),		\
-	(REF)->stream->error_ref = __LINE__,		\
-	NDS_TATTLE_ERROR((REF)->stream, 0, REF))
-
-#define	NDR_TATTLE(REF, WHAT) \
-	(*(REF)->stream->ndo->ndo_tattle)((REF)->stream, WHAT, REF)
-
-#define	MEMBER_STR(MEMBER) #MEMBER
-
-#define	NDR_DIR_IS_IN  (encl_ref->stream->dir == NDR_DIR_IN)
-#define	NDR_DIR_IS_OUT (encl_ref->stream->dir == NDR_DIR_OUT)
-
-#define	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET, \
-		ARGFLAGS, ARGMEM, ARGVAL) { \
-		myref.pdu_offset = encl_ref->pdu_offset + (OFFSET);	\
-		myref.name = MEMBER_STR(MEMBER);			\
-		myref.datum = (char *)&val->MEMBER;			\
-		myref.inner_flags = ARGFLAGS;				\
-		myref.ti = &ndt_##TYPE;					\
-		myref.ARGMEM = ARGVAL;					\
-		if (!ndr_inner(&myref))					\
-			return (0);					\
-	}
-
-#define	NDR_MEMBER(TYPE, MEMBER, OFFSET) \
-	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET, \
-		NDR_F_NONE, size_is, 0)
-
-#define	NDR_MEMBER_ARR_WITH_SIZE_IS(TYPE, MEMBER, OFFSET, SIZE_IS) \
-	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET, \
-		NDR_F_SIZE_IS, size_is, SIZE_IS)
-
-#define	NDR_MEMBER_ARR_WITH_DIMENSION(TYPE, MEMBER, OFFSET, SIZE_IS) \
-	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET, \
-		NDR_F_DIMENSION_IS, dimension_is, SIZE_IS)
-
-#define	NDR_MEMBER_PTR_WITH_SIZE_IS(TYPE, MEMBER, OFFSET, SIZE_IS) \
-	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET, \
-		NDR_F_SIZE_IS+NDR_F_IS_POINTER, size_is, SIZE_IS)
-
-#define	NDR_MEMBER_PTR(TYPE, MEMBER, OFFSET)		\
-	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET,	\
-		NDR_F_IS_POINTER, size_is, 0)
-
-#define	NDR_MEMBER_WITH_SWITCH_IS(TYPE, MEMBER, OFFSET, SWITCH_IS)	\
-	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET,			\
-		NDR_F_SWITCH_IS, switch_is, SWITCH_IS)
-
-
-#define	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER, \
-		ARGFLAGS, ARGMEM, ARGVAL) { \
-		myref.pdu_offset = -1;					\
-		myref.name = MEMBER_STR(MEMBER);			\
-		myref.datum = (char *)&val->MEMBER;			\
-		myref.inner_flags = ARGFLAGS;				\
-		myref.ti = &ndt_##TYPE;					\
-		myref.ARGMEM = ARGVAL;					\
-		if (!ndr_topmost(&myref))				\
-			return (0);					\
-	}
-
-#define	NDR_TOPMOST_MEMBER(TYPE, MEMBER)	   			\
-	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,			\
-		NDR_F_NONE, size_is, 0)
-
-#define	NDR_TOPMOST_MEMBER_ARR_WITH_SIZE_IS(TYPE, MEMBER, SIZE_IS)	\
-	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,		    	\
-		NDR_F_SIZE_IS, size_is, SIZE_IS)
-
-#define	NDR_TOPMOST_MEMBER_ARR_WITH_DIMENSION(TYPE, MEMBER, SIZE_IS)	\
-	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,		      	\
-		NDR_F_DIMENSION_IS, dimension_is, SIZE_IS)
-
-#define	NDR_TOPMOST_MEMBER_PTR_WITH_SIZE_IS(TYPE, MEMBER, SIZE_IS)	\
-	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,			\
-		NDR_F_SIZE_IS+NDR_F_IS_POINTER, size_is, SIZE_IS)
-
-#define	NDR_TOPMOST_MEMBER_PTR(TYPE, MEMBER)		\
-	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,	\
-		NDR_F_IS_POINTER, size_is, 0)
-
-#define	NDR_TOPMOST_MEMBER_REF(TYPE, MEMBER)		\
-	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,	\
-		NDR_F_IS_REFERENCE, size_is, 0)
-
-#define	NDR_TOPMOST_MEMBER_REF_WITH_SIZE_IS(TYPE, MEMBER, SIZE_IS)	\
-	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,			\
-		NDR_F_SIZE_IS+NDR_F_IS_REFERENCE, size_is, SIZE_IS)
-
-#define	NDR_TOPMOST_MEMBER_WITH_SWITCH_IS(TYPE, MEMBER, SWITCH_IS)	\
-	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,			\
-		NDR_F_SWITCH_IS, switch_is, SWITCH_IS)
-
-/* this is assuming offset+0 */
-#define	NDR_PARAMS_MEMBER_WITH_ARG(TYPE, MEMBER, ARGFLAGS, \
-	ARGMEM, ARGVAL) { \
-		myref.pdu_offset = encl_ref->pdu_offset;		\
-		myref.name = MEMBER_STR(MEMBER);			\
-		myref.datum = (char *)&val->MEMBER;			\
-		myref.inner_flags = ARGFLAGS;				\
-		myref.ti = &ndt_##TYPE;					\
-		myref.ARGMEM = ARGVAL;					\
-		if (!ndr_params(&myref))				\
-			return (0);					\
-	}
-
-#define	NDR_PARAMS_MEMBER(TYPE, MEMBER)			\
-	NDR_PARAMS_MEMBER_WITH_ARG(TYPE, MEMBER,	\
-	NDR_F_NONE, size_is, 0)
-
-#define	NDR_STRING_DIM		1
-#define	NDR_ANYSIZE_DIM		1
-
-int ndo_process(struct ndr_stream *, ndr_typeinfo_t *, char *);
-int ndo_operation(struct ndr_stream *, ndr_typeinfo_t *, int opnum, char *);
-void ndo_printf(struct ndr_stream *, ndr_ref_t *, const char *, ...);
-void ndo_trace(const char *);
-void ndo_fmt(struct ndr_stream *, ndr_ref_t *, char *);
-
-int ndr_params(ndr_ref_t *);
-int ndr_topmost(ndr_ref_t *);
-int ndr_run_outer_queue(struct ndr_stream *);
-int ndr_outer(ndr_ref_t *);
-int ndr_outer_fixed(ndr_ref_t *);
-int ndr_outer_fixed_array(ndr_ref_t *);
-int ndr_outer_conformant_array(ndr_ref_t *);
-int ndr_outer_conformant_construct(ndr_ref_t *);
-int ndr_size_is(ndr_ref_t *);
-int ndr_outer_string(ndr_ref_t *);
-int ndr_outer_peek_sizing(ndr_ref_t *, unsigned, unsigned long *);
-int ndr_outer_poke_sizing(ndr_ref_t *, unsigned, unsigned long *);
-int ndr_outer_align(ndr_ref_t *);
-int ndr_outer_grow(ndr_ref_t *, unsigned);
-int ndr_inner(ndr_ref_t *);
-int ndr_inner_pointer(ndr_ref_t *);
-int ndr_inner_reference(ndr_ref_t *);
-int ndr_inner_array(ndr_ref_t *);
-
-size_t ndr_mbstowcs(struct ndr_stream *, smb_wchar_t *, const char *, size_t);
-int ndr_mbtowc(struct ndr_stream *, smb_wchar_t *, const char *, size_t);
-
-void nds_bswap(void *src, void *dst, size_t len);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SMBSRV_NDR_H */
--- /dev/null	Sun Mar 18 01:13:16 2018
+++ new/usr/src/lib/libmlrpc/common/ndr.h	Sun Mar 18 01:13:16 2018
@@ -0,0 +1,462 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+#ifndef _SMBSRV_NDR_H
+#define	_SMBSRV_NDR_H
+
+/*
+ * Network Data Representation (NDR) is a compatible subset of DCE RPC
+ * and MSRPC NDR.  NDR is used to move parameters consisting of
+ * complicated trees of data constructs between an RPC client and server.
+ *
+ * CAE Specification (1997)
+ * DCE 1.1: Remote Procedure Call
+ * Document Number: C706
+ * The Open Group
+ * ogspecs@opengroup.org
+ */
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <smb/wintypes.h>
+#include <libmlrpc/ndrtypes.ndl>
+#include <libmlrpc/rpcpdu.ndl>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Normal sequence:
+ *	- Application calls client-side stub w/ TOP-MOST arg structure
+ *	- client stub performs NDR_M_OP_MARSHALL+NDR_DIR_IN
+ *	- PDU conveyed (request, aka call, aka query)
+ *	- server stub performs NDR_M_OP_UNMARSHALL+NDR_DIR_IN
+ *	- server function called w/ TOP-MOST arg structure
+ *	- server function returns w/ TOP-MOST arg structure modified
+ *	- server stub performs NDR_M_OP_MARSHALL+NDR_DIR_OUT
+ *	- PDU conveyed (reply, aka result, aka response)
+ *	- client stub performs NDR_M_OP_UNMARSHALL+NDR_DIR_OUT
+ *	- return to Application w/ TOP-MOST arg structure modified
+ *
+ * An interface is a sequence of top-most constructs.  Each top-most
+ * construct corresponds to one parameter, either argument or return
+ * value.
+ *
+ * A top-most construct is a sequence of outer constructs.  The first
+ * outer construct is the referent of the argument, and the subsequent
+ * outer constructs are descendents referenced by pointers from prior
+ * constructs.
+ *
+ * An outer construct is a sequence of variable-sized info, fixed-sized
+ * data, and variable-sized data.
+ */
+
+/*
+ * Terminology
+ *
+ * The ALL UPPER CASE terms recur in the DCE/RPC documentation.
+ * The mixed-case names have been introduced as a reading aid.
+ *
+ * Size		The size of an array in elements. Think of this
+ *		as the amount to malloc().
+ *
+ * Length	The number of elements of an array which are significant
+ *		Think of this as the amount to bcopy().
+ *
+ * Known	Size/length is known at build time.
+ *
+ * Determined	Size/length is determined at run time.
+ *
+ * FIXED	The Size and Length are Known.
+ *		Think of this as a string constant or a DOS 8.3 file name.
+ *		char array[] = "A Constant Size/Length";
+ *
+ * CONFORMANT	The Size is Determined. Length is the same as Size.
+ *		Think of this as strdup().
+ *		char *array = strdup("Something");
+ *
+ * VARYING	The Size is Known. The Length is determined.
+ *		Think of this as a strcpy() of a variable length string
+ *		into a fixed length buffer:
+ *		char array[100];
+ *		strcpy(array, "very short string");
+ *
+ * VARYING/CONFORMANT
+ *		The Size is Determined. The Length is separately Determined.
+ *		Think of this like:
+ *		char *array = malloc(size);
+ *		strcpy(array, "short string");
+ *
+ * STRING	Strings can be CONFORMANT, VARYING, or CONFORMANT/VARYING.
+ *		A string is fundamentally an array with the last
+ *		significant element some sort of NULL.
+ */
+
+#define	NDR_F_NONE		0x0000	/* no flags */
+#define	NDR_F_PARAMS_MASK	0x00FF
+#define	NDR_F_SIZE_IS		0x0001	/* [size_is(X)] required/given */
+#define	NDR_F_LENGTH_IS		0x0002	/* not implemented */
+#define	NDR_F_SWITCH_IS		0x0004	/* [switch_is(X)] req./given */
+#define	NDR_F_IS_STRING		0x0008	/* [string] req./given */
+#define	NDR_F_IS_POINTER	0x0010	/* TYPE * ... req./given */
+#define	NDR_F_IS_REFERENCE	0x0020	/* TYPE & ... req./given */
+#define	NDR_F_DIMENSION_IS	0x0040	/* TYPE [N] req./given */
+
+#define	NDR_F_WHENCE_MASK	0x00F0
+#define	NDR_F_BACKPTR		0x0010	/* ref cause by pointer */
+#define	NDR_F_OUTER		0x0020	/* ref caused by outer */
+#define	NDR_F_TOPMOST		0x0040	/* ref caused by topmost */
+
+#define	NDR_F_TYPEOP_MASK	0x0F00
+#define	NDR_F_ARRAY		0x0100	/* type is array of somethings */
+#define	NDR_F_POINTER		0x0200	/* type is pointer to something(s) */
+#define	NDR_F_STRING		0x0300	/* type is string of somethings */
+#define	NDR_F_UNION		0x0400	/* type is a union */
+#define	NDR_F_STRUCT		0x0500	/* type is a structure */
+#define	NDR_F_OPERATION		0x0600	/* type is a structure, special */
+#define	NDR_F_INTERFACE		0x0700	/* type is a union, special */
+#define	NDR_F_CONFORMANT	0x1000	/* struct conforming (var-size tail) */
+#define	NDR_F_VARYING		0x2000	/* not implemented */
+
+struct ndr_heap;
+struct ndr_stream;
+struct ndr_reference;
+
+typedef uint16_t ndr_wchar_t;
+
+typedef struct ndr_typeinfo {
+	unsigned char		version;	/* sanity check */
+	unsigned char		alignment;	/* mask */
+	unsigned short		type_flags;	/* NDR_F_... */
+	int			(*ndr_func)(struct ndr_reference *);
+	unsigned short		pdu_size_fixed_part;
+	unsigned short		pdu_size_variable_part;
+	unsigned short		c_size_fixed_part;
+	unsigned short		c_size_variable_part;
+} ndr_typeinfo_t;
+
+typedef struct ndr_reference {
+	struct ndr_reference	*next;		/* queue list (outer only) */
+	struct ndr_reference	*enclosing;	/* e.g. struct for this memb */
+	struct ndr_stream	*stream;	/* root of NDR */
+	ndr_typeinfo_t		*ti;		/* type of data referenced */
+	char			*name;		/* name of this member */
+	unsigned long		pdu_offset;	/* referent in stub data */
+	char			*datum;		/* referent in local memory */
+	char			**backptr;	/* referer to set */
+	unsigned short		outer_flags;	/* XXX_is() from top level */
+	unsigned short		inner_flags;	/* XXX_is() in encapsulated */
+	unsigned short		type_flags;	/* "requires" */
+	unsigned short		packed_alignment;
+	unsigned long		size_is;	/* conforming constructs */
+	unsigned long		strlen_is;	/* strings */
+	unsigned long		switch_is;	/* union arg selector */
+	unsigned long		dimension_is;	/* fixed-len array size */
+	unsigned long		pdu_end_offset;	/* offset for limit of PDU */
+} ndr_ref_t;
+
+/*
+ * For all operations, the ndr_stream, which is the root of NDR processing,
+ * is the primary object.  When available, the appropriate ndr_ref_t
+ * is passed, NULL otherwise.  Functions that return 'int' should return
+ * TRUE (!0) or FALSE (0).  When functions return FALSE, including
+ * ndo_malloc() returning NULL, they should set the stream->error to an
+ * appropriate indicator of what went wrong.
+ *
+ * Functions ndo_get_pdu(), ndo_put_pdu(), and ndo_pad_pdu() must
+ * never grow the PDU data.  A request for out-of-bounds data is an error.
+ * The swap_bytes flag is 1 if NDR knows that the byte-order in the PDU
+ * is different from the local system.  ndo_pad_pdu() advised that the
+ * affected bytes should be zero filled.
+ */
+typedef struct ndr_stream_ops {
+	char *(*ndo_malloc)(struct ndr_stream *, unsigned, ndr_ref_t *);
+	int (*ndo_free)(struct ndr_stream *, char *, ndr_ref_t *);
+	int (*ndo_grow_pdu)(struct ndr_stream *, unsigned long, ndr_ref_t *);
+	int (*ndo_pad_pdu)(struct ndr_stream *, unsigned long,
+	    unsigned long, ndr_ref_t *);
+	int (*ndo_get_pdu)(struct ndr_stream *, unsigned long,
+	    unsigned long, char *, int, ndr_ref_t *);
+	int (*ndo_put_pdu)(struct ndr_stream *, unsigned long,
+	    unsigned long, char *, int, ndr_ref_t *);
+	void (*ndo_tattle)(struct ndr_stream *, char *, ndr_ref_t *);
+	void (*ndo_tattle_error)(struct ndr_stream *, ndr_ref_t *);
+	int (*ndo_reset)(struct ndr_stream *);
+	void (*ndo_destruct)(struct ndr_stream *);
+} ndr_stream_ops_t;
+
+#define	NDS_MALLOC(NDS, LEN, REF) \
+	(*(NDS)->ndo->ndo_malloc)(NDS, LEN, REF)
+#define	NDS_GROW_PDU(NDS, WANT_END_OFF, REF) \
+	(*(NDS)->ndo->ndo_grow_pdu)(NDS, WANT_END_OFF, REF)
+#define	NDS_PAD_PDU(NDS, PDU_OFFSET, N_BYTES, REF) \
+	(*(NDS)->ndo->ndo_pad_pdu)(NDS, PDU_OFFSET, N_BYTES, REF)
+#define	NDS_GET_PDU(NDS, PDU_OFFSET, N_BYTES, BUF, SWAP, REF) \
+	(*(NDS)->ndo->ndo_get_pdu)(NDS, PDU_OFFSET, N_BYTES, BUF, SWAP, REF)
+#define	NDS_PUT_PDU(NDS, PDU_OFFSET, N_BYTES, BUF, SWAP, REF) \
+	(*(NDS)->ndo->ndo_put_pdu)(NDS, PDU_OFFSET, N_BYTES, BUF, SWAP, REF)
+#define	NDS_TATTLE(NDS, WHAT, REF) \
+	(*(NDS)->ndo->ndo_tattle)(NDS, WHAT, REF)
+#define	NDS_TATTLE_ERROR(NDS, WHAT, REF) \
+	(*(NDS)->ndo->ndo_tattle_error)(NDS, REF)
+#define	NDS_RESET(NDS)		(*(NDS)->ndo->ndo_reset)(NDS)
+#define	NDS_DESTRUCT(NDS)	(*(NDS)->ndo->ndo_destruct)(NDS)
+
+typedef struct ndr_stream {
+	unsigned long		pdu_size;
+	unsigned long		pdu_max_size;
+	unsigned long		pdu_base_offset;
+	unsigned long		pdu_scan_offset;
+	unsigned char		*pdu_base_addr;
+
+	ndr_stream_ops_t	*ndo;
+
+	unsigned char		m_op;
+	unsigned char		dir;
+	unsigned char		swap;		/* native/net endian swap */
+	unsigned char		flags;
+	short			error;
+	short			error_ref;
+
+	ndr_ref_t *outer_queue_head;
+	ndr_ref_t **outer_queue_tailp;
+	ndr_ref_t *outer_current;
+	struct ndr_heap *heap;
+} ndr_stream_t;
+
+#define	NDR_M_OP_NONE		0x00
+#define	NDR_M_OP_MARSHALL	0x01	/* data moving from datum to PDU */
+#define	NDR_M_OP_UNMARSHALL	0x02	/* data moving from PDU to datum */
+
+#define	NDR_DIR_NONE		0x00
+#define	NDR_DIR_IN		0x10	/* data moving from caller to callee */
+#define	NDR_DIR_OUT		0x20	/* data moving from callee to caller */
+
+#define	NDR_MODE_CALL_SEND	(NDR_M_OP_MARSHALL + NDR_DIR_IN)
+#define	NDR_MODE_CALL_RECV	(NDR_M_OP_UNMARSHALL + NDR_DIR_IN)
+#define	NDR_MODE_RETURN_SEND	(NDR_M_OP_MARSHALL + NDR_DIR_OUT)
+#define	NDR_MODE_RETURN_RECV	(NDR_M_OP_UNMARSHALL + NDR_DIR_OUT)
+#define	NDR_MODE_BUF_ENCODE	NDR_MODE_CALL_SEND
+#define	NDR_MODE_BUF_DECODE	NDR_MODE_RETURN_RECV
+
+#define	NDR_MODE_TO_M_OP(MODE)	((MODE) & 0x0F)
+#define	NDR_MODE_TO_DIR(MODE)	((MODE) & 0xF0)
+#define	NDR_M_OP_AND_DIR_TO_MODE(M_OP, DIR)	((M_OP)|(DIR))
+
+#define	NDR_MODE_MATCH(NDS, MODE) \
+	(NDR_M_OP_AND_DIR_TO_MODE((NDS)->m_op, (NDS)->dir) == (MODE))
+
+#define	NDR_IS_FIRST_FRAG(F)	((F) & NDR_PFC_FIRST_FRAG)
+#define	NDR_IS_LAST_FRAG(F)	((F) & NDR_PFC_LAST_FRAG)
+#define	NDR_IS_SINGLE_FRAG(F)	\
+	(NDR_IS_FIRST_FRAG((F)) && NDR_IS_LAST_FRAG((F)))
+
+#define	NDS_F_NONE		0x00
+#define	NDS_F_NOTERM		0x01	/* strings are not null terminated */
+#define	NDS_F_NONULL		0x02	/* strings: no null on size_is */
+#define	NDS_SETF(S, F)		((S)->flags |= (F))
+#define	NDS_CLEARF(S, F)	((S)->flags &= ~(F))
+
+#define	NDR_ERR_MALLOC_FAILED		-1
+#define	NDR_ERR_M_OP_INVALID		-2
+#define	NDR_ERR_UNDERFLOW		-3
+#define	NDR_ERR_GROW_FAILED		-4	/* overflow */
+#define	NDR_ERR_PAD_FAILED		-5	/* couldn't possibly happen */
+#define	NDR_ERR_OUTER_HEADER_BAD	-6
+#define	NDR_ERR_SWITCH_VALUE_ILLEGAL	-7
+#define	NDR_ERR_SWITCH_VALUE_INVALID	-8
+#define	NDR_ERR_SWITCH_VALUE_MISSING	-9
+#define	NDR_ERR_SIZE_IS_MISMATCH_PDU	-10
+#define	NDR_ERR_SIZE_IS_MISMATCH_AFTER	-11
+#define	NDR_ERR_SIZE_IS_UNEXPECTED	-12
+#define	NDR_ERR_SIZE_IS_DUPLICATED	-13
+#define	NDR_ERR_OUTER_PARAMS_MISMATCH	-14
+#define	NDR_ERR_ARRAY_VARLEN_ILLEGAL	-15
+#define	NDR_ERR_ARRAY_UNION_ILLEGAL	-16
+#define	NDR_ERR_OUTER_PARAMS_BAD	-17
+#define	NDR_ERR_OUTER_UNION_ILLEGAL	-18
+#define	NDR_ERR_TOPMOST_UNION_ILLEGAL	-19
+#define	NDR_ERR_TOPMOST_VARLEN_ILLEGAL	-20
+#define	NDR_ERR_INNER_PARAMS_BAD	-21
+#define	NDR_ERR_UNIMPLEMENTED		-22
+#define	NDR_ERR_NOT_AN_INTERFACE	-23
+#define	NDR_ERR_STRLEN			-24
+#define	NDR_ERR_STRING_SIZING		-25
+#define	NDR_ERR_BOUNDS_CHECK		-26
+
+#define	NDR_SET_ERROR(REF, ERROR)			\
+	((REF)->stream->error = (ERROR),		\
+	(REF)->stream->error_ref = __LINE__,		\
+	NDS_TATTLE_ERROR((REF)->stream, 0, REF))
+
+#define	NDR_TATTLE(REF, WHAT) \
+	(*(REF)->stream->ndo->ndo_tattle)((REF)->stream, WHAT, REF)
+
+#define	MEMBER_STR(MEMBER) #MEMBER
+
+#define	NDR_DIR_IS_IN  (encl_ref->stream->dir == NDR_DIR_IN)
+#define	NDR_DIR_IS_OUT (encl_ref->stream->dir == NDR_DIR_OUT)
+
+#define	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET, \
+		ARGFLAGS, ARGMEM, ARGVAL) { \
+		myref.pdu_offset = encl_ref->pdu_offset + (OFFSET);	\
+		myref.name = MEMBER_STR(MEMBER);			\
+		myref.datum = (char *)&val->MEMBER;			\
+		myref.inner_flags = ARGFLAGS;				\
+		myref.ti = &ndt_##TYPE;					\
+		myref.ARGMEM = ARGVAL;					\
+		if (!ndr_inner(&myref))					\
+			return (0);					\
+	}
+
+#define	NDR_MEMBER(TYPE, MEMBER, OFFSET) \
+	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET, \
+		NDR_F_NONE, size_is, 0)
+
+#define	NDR_MEMBER_ARR_WITH_SIZE_IS(TYPE, MEMBER, OFFSET, SIZE_IS) \
+	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET, \
+		NDR_F_SIZE_IS, size_is, SIZE_IS)
+
+#define	NDR_MEMBER_ARR_WITH_DIMENSION(TYPE, MEMBER, OFFSET, SIZE_IS) \
+	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET, \
+		NDR_F_DIMENSION_IS, dimension_is, SIZE_IS)
+
+#define	NDR_MEMBER_PTR_WITH_SIZE_IS(TYPE, MEMBER, OFFSET, SIZE_IS) \
+	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET, \
+		NDR_F_SIZE_IS+NDR_F_IS_POINTER, size_is, SIZE_IS)
+
+#define	NDR_MEMBER_PTR(TYPE, MEMBER, OFFSET)		\
+	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET,	\
+		NDR_F_IS_POINTER, size_is, 0)
+
+#define	NDR_MEMBER_WITH_SWITCH_IS(TYPE, MEMBER, OFFSET, SWITCH_IS)	\
+	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET,			\
+		NDR_F_SWITCH_IS, switch_is, SWITCH_IS)
+
+
+#define	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER, \
+		ARGFLAGS, ARGMEM, ARGVAL) { \
+		myref.pdu_offset = -1;					\
+		myref.name = MEMBER_STR(MEMBER);			\
+		myref.datum = (char *)&val->MEMBER;			\
+		myref.inner_flags = ARGFLAGS;				\
+		myref.ti = &ndt_##TYPE;					\
+		myref.ARGMEM = ARGVAL;					\
+		if (!ndr_topmost(&myref))				\
+			return (0);					\
+	}
+
+#define	NDR_TOPMOST_MEMBER(TYPE, MEMBER)	   			\
+	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,			\
+		NDR_F_NONE, size_is, 0)
+
+#define	NDR_TOPMOST_MEMBER_ARR_WITH_SIZE_IS(TYPE, MEMBER, SIZE_IS)	\
+	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,		    	\
+		NDR_F_SIZE_IS, size_is, SIZE_IS)
+
+#define	NDR_TOPMOST_MEMBER_ARR_WITH_DIMENSION(TYPE, MEMBER, SIZE_IS)	\
+	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,		      	\
+		NDR_F_DIMENSION_IS, dimension_is, SIZE_IS)
+
+#define	NDR_TOPMOST_MEMBER_PTR_WITH_SIZE_IS(TYPE, MEMBER, SIZE_IS)	\
+	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,			\
+		NDR_F_SIZE_IS+NDR_F_IS_POINTER, size_is, SIZE_IS)
+
+#define	NDR_TOPMOST_MEMBER_PTR(TYPE, MEMBER)		\
+	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,	\
+		NDR_F_IS_POINTER, size_is, 0)
+
+#define	NDR_TOPMOST_MEMBER_REF(TYPE, MEMBER)		\
+	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,	\
+		NDR_F_IS_REFERENCE, size_is, 0)
+
+#define	NDR_TOPMOST_MEMBER_REF_WITH_SIZE_IS(TYPE, MEMBER, SIZE_IS)	\
+	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,			\
+		NDR_F_SIZE_IS+NDR_F_IS_REFERENCE, size_is, SIZE_IS)
+
+#define	NDR_TOPMOST_MEMBER_WITH_SWITCH_IS(TYPE, MEMBER, SWITCH_IS)	\
+	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,			\
+		NDR_F_SWITCH_IS, switch_is, SWITCH_IS)
+
+/* this is assuming offset+0 */
+#define	NDR_PARAMS_MEMBER_WITH_ARG(TYPE, MEMBER, ARGFLAGS, \
+	ARGMEM, ARGVAL) { \
+		myref.pdu_offset = encl_ref->pdu_offset;		\
+		myref.name = MEMBER_STR(MEMBER);			\
+		myref.datum = (char *)&val->MEMBER;			\
+		myref.inner_flags = ARGFLAGS;				\
+		myref.ti = &ndt_##TYPE;					\
+		myref.ARGMEM = ARGVAL;					\
+		if (!ndr_params(&myref))				\
+			return (0);					\
+	}
+
+#define	NDR_PARAMS_MEMBER(TYPE, MEMBER)			\
+	NDR_PARAMS_MEMBER_WITH_ARG(TYPE, MEMBER,	\
+	NDR_F_NONE, size_is, 0)
+
+#define	NDR_STRING_DIM		1
+#define	NDR_ANYSIZE_DIM		1
+
+int ndo_process(struct ndr_stream *, ndr_typeinfo_t *, char *);
+int ndo_operation(struct ndr_stream *, ndr_typeinfo_t *, int opnum, char *);
+void ndo_printf(struct ndr_stream *, ndr_ref_t *, const char *, ...);
+void ndo_trace(const char *);
+void ndo_fmt(struct ndr_stream *, ndr_ref_t *, char *);
+
+int ndr_params(ndr_ref_t *);
+int ndr_topmost(ndr_ref_t *);
+int ndr_run_outer_queue(struct ndr_stream *);
+int ndr_outer(ndr_ref_t *);
+int ndr_outer_fixed(ndr_ref_t *);
+int ndr_outer_fixed_array(ndr_ref_t *);
+int ndr_outer_conformant_array(ndr_ref_t *);
+int ndr_outer_conformant_construct(ndr_ref_t *);
+int ndr_size_is(ndr_ref_t *);
+int ndr_outer_string(ndr_ref_t *);
+int ndr_outer_peek_sizing(ndr_ref_t *, unsigned, unsigned long *);
+int ndr_outer_poke_sizing(ndr_ref_t *, unsigned, unsigned long *);
+int ndr_outer_align(ndr_ref_t *);
+int ndr_outer_grow(ndr_ref_t *, unsigned);
+int ndr_inner(ndr_ref_t *);
+int ndr_inner_pointer(ndr_ref_t *);
+int ndr_inner_reference(ndr_ref_t *);
+int ndr_inner_array(ndr_ref_t *);
+
+size_t ndr_mbstowcs(struct ndr_stream *, ndr_wchar_t *, const char *, size_t);
+
+void nds_bswap(void *src, void *dst, size_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SMBSRV_NDR_H */
--- old/usr/src/lib/smbsrv/libmlrpc/common/ndr_client.c	Sun Mar 18 01:13:16 2018
+++ /dev/null	Sun Mar 18 01:13:16 2018
@@ -1,333 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <sys/errno.h>
-#include <string.h>
-#include <strings.h>
-
-#include <smbsrv/libsmb.h>
-#include <smbsrv/libmlrpc.h>
-
-#define	NDR_DEFAULT_FRAGSZ	8192
-#define	NDR_MULTI_FRAGSZ	(60 * 1024)
-
-static void ndr_clnt_init_hdr(ndr_client_t *, ndr_xa_t *);
-static int ndr_clnt_get_frags(ndr_client_t *, ndr_xa_t *);
-static int ndr_clnt_get_frag(ndr_client_t *, ndr_xa_t *, ndr_common_header_t *);
-
-int
-ndr_clnt_bind(ndr_client_t *clnt, const char *service_name,
-    ndr_binding_t **ret_binding_p)
-{
-	ndr_service_t		*msvc;
-	ndr_binding_t		*mbind;
-	ndr_xa_t		mxa;
-	ndr_bind_hdr_t		*bhdr;
-	ndr_p_cont_elem_t 	*pce;
-	ndr_bind_ack_hdr_t	*bahdr;
-	ndr_p_result_t		*pre;
-	int			rc;
-
-	bzero(&mxa, sizeof (mxa));
-
-	msvc = ndr_svc_lookup_name(service_name);
-	if (msvc == NULL)
-		return (NDR_DRC_FAULT_API_SERVICE_INVALID);
-
-	mxa.binding_list = clnt->binding_list;
-	if ((mbind = ndr_svc_new_binding(&mxa)) == NULL)
-		return (NDR_DRC_FAULT_API_BIND_NO_SLOTS);
-
-	ndr_clnt_init_hdr(clnt, &mxa);
-
-	bhdr = &mxa.send_hdr.bind_hdr;
-	bhdr->common_hdr.ptype = NDR_PTYPE_BIND;
-	bhdr->common_hdr.frag_length = sizeof (*bhdr);
-	bhdr->max_xmit_frag = NDR_DEFAULT_FRAGSZ;
-	bhdr->max_recv_frag = NDR_DEFAULT_FRAGSZ;
-	bhdr->assoc_group_id = 0;
-	bhdr->p_context_elem.n_context_elem = 1;
-
-	/* Assign presentation context id */
-	pce = &bhdr->p_context_elem.p_cont_elem[0];
-	pce->p_cont_id = clnt->next_p_cont_id++;
-	pce->n_transfer_syn = 1;
-
-	/* Set up UUIDs and versions from the service */
-	pce->abstract_syntax.if_version = msvc->abstract_syntax_version;
-	rc = ndr_uuid_parse(msvc->abstract_syntax_uuid,
-	    &pce->abstract_syntax.if_uuid);
-	if (rc != 0)
-		return (NDR_DRC_FAULT_API_SERVICE_INVALID);
-
-	pce->transfer_syntaxes[0].if_version = msvc->transfer_syntax_version;
-	rc = ndr_uuid_parse(msvc->transfer_syntax_uuid,
-	    &pce->transfer_syntaxes[0].if_uuid);
-	if (rc != 0)
-		return (NDR_DRC_FAULT_API_SERVICE_INVALID);
-
-	/* Format and exchange the PDU */
-
-	if ((*clnt->xa_init)(clnt, &mxa) < 0)
-		return (NDR_DRC_FAULT_OUT_OF_MEMORY);
-
-	rc = ndr_encode_pdu_hdr(&mxa);
-	if (NDR_DRC_IS_FAULT(rc))
-		goto fault_exit;
-
-	if ((*clnt->xa_exchange)(clnt, &mxa) < 0) {
-		rc = NDR_DRC_FAULT_SEND_FAILED;
-		goto fault_exit;
-	}
-
-	rc = ndr_decode_pdu_hdr(&mxa);
-	if (NDR_DRC_IS_FAULT(rc))
-		goto fault_exit;
-
-	/* done with buffers */
-	(*clnt->xa_destruct)(clnt, &mxa);
-
-	bahdr = &mxa.recv_hdr.bind_ack_hdr;
-
-	if (mxa.ptype != NDR_PTYPE_BIND_ACK)
-		return (NDR_DRC_FAULT_RECEIVED_MALFORMED);
-
-	if (bahdr->p_result_list.n_results != 1)
-		return (NDR_DRC_FAULT_RECEIVED_MALFORMED);
-
-	pre = &bahdr->p_result_list.p_results[0];
-
-	if (pre->result != NDR_PCDR_ACCEPTANCE)
-		return (NDR_DRC_FAULT_RECEIVED_MALFORMED);
-
-	mbind->p_cont_id = pce->p_cont_id;
-	mbind->which_side = NDR_BIND_SIDE_CLIENT;
-	mbind->clnt = clnt;
-	mbind->service = msvc;
-	mbind->instance_specific = 0;
-
-	*ret_binding_p = mbind;
-	return (NDR_DRC_OK);
-
-fault_exit:
-	(*clnt->xa_destruct)(clnt, &mxa);
-	return (rc);
-}
-
-int
-ndr_clnt_call(ndr_binding_t *mbind, int opnum, void *params)
-{
-	ndr_client_t		*clnt = mbind->clnt;
-	ndr_service_t		*msvc = mbind->service;
-	ndr_xa_t		mxa;
-	ndr_request_hdr_t	*reqhdr;
-	ndr_common_header_t	*rsphdr;
-	unsigned long		recv_pdu_scan_offset;
-	int			rc;
-
-	if (ndr_svc_lookup_name(msvc->name) == NULL)
-		return (NDR_DRC_FAULT_API_SERVICE_INVALID);
-
-	bzero(&mxa, sizeof (mxa));
-	mxa.ptype = NDR_PTYPE_REQUEST;
-	mxa.opnum = opnum;
-	mxa.binding = mbind;
-
-	ndr_clnt_init_hdr(clnt, &mxa);
-
-	reqhdr = &mxa.send_hdr.request_hdr;
-	reqhdr->common_hdr.ptype = NDR_PTYPE_REQUEST;
-	reqhdr->p_cont_id = mbind->p_cont_id;
-	reqhdr->opnum = opnum;
-
-	rc = (*clnt->xa_init)(clnt, &mxa);
-	if (NDR_DRC_IS_FAULT(rc))
-		return (rc);
-
-	/* Reserve room for hdr */
-	mxa.send_nds.pdu_scan_offset = sizeof (*reqhdr);
-
-	rc = ndr_encode_call(&mxa, params);
-	if (!NDR_DRC_IS_OK(rc))
-		goto fault_exit;
-
-	mxa.send_nds.pdu_scan_offset = 0;
-
-	/*
-	 * Now we have the PDU size, we need to set up the
-	 * frag_length and calculate the alloc_hint.
-	 */
-	mxa.send_hdr.common_hdr.frag_length = mxa.send_nds.pdu_size;
-	reqhdr->alloc_hint = mxa.send_nds.pdu_size -
-	    sizeof (ndr_request_hdr_t);
-
-	rc = ndr_encode_pdu_hdr(&mxa);
-	if (NDR_DRC_IS_FAULT(rc))
-		goto fault_exit;
-
-	rc = (*clnt->xa_exchange)(clnt, &mxa);
-	if (NDR_DRC_IS_FAULT(rc))
-		goto fault_exit;
-
-	rc = ndr_decode_pdu_hdr(&mxa);
-	if (NDR_DRC_IS_FAULT(rc))
-		goto fault_exit;
-
-	if (mxa.ptype != NDR_PTYPE_RESPONSE) {
-		rc = NDR_DRC_FAULT_RECEIVED_MALFORMED;
-		goto fault_exit;
-	}
-
-	rsphdr = &mxa.recv_hdr.common_hdr;
-
-	if (!NDR_IS_LAST_FRAG(rsphdr->pfc_flags)) {
-		/*
-		 * This is a multi-fragment response.
-		 * Preserve the current scan offset while getting
-		 * fragments so that we can continue afterward
-		 * as if we had received the entire response as
-		 * a single PDU.
-		 */
-		(void) NDS_GROW_PDU(&mxa.recv_nds, NDR_MULTI_FRAGSZ, NULL);
-
-		recv_pdu_scan_offset = mxa.recv_nds.pdu_scan_offset;
-		mxa.recv_nds.pdu_scan_offset = rsphdr->frag_length;
-		mxa.recv_nds.pdu_size = rsphdr->frag_length;
-
-		if (ndr_clnt_get_frags(clnt, &mxa) < 0) {
-			rc = NDR_DRC_FAULT_RECEIVED_MALFORMED;
-			goto fault_exit;
-		}
-
-		mxa.recv_nds.pdu_scan_offset = recv_pdu_scan_offset;
-	}
-
-	rc = ndr_decode_return(&mxa, params);
-	if (NDR_DRC_IS_FAULT(rc))
-		goto fault_exit;
-
-	(*clnt->xa_preserve)(clnt, &mxa);
-	(*clnt->xa_destruct)(clnt, &mxa);
-	return (NDR_DRC_OK);
-
-fault_exit:
-	(*clnt->xa_destruct)(clnt, &mxa);
-	return (rc);
-}
-
-void
-ndr_clnt_free_heap(ndr_client_t *clnt)
-{
-	(*clnt->xa_release)(clnt);
-}
-
-static void
-ndr_clnt_init_hdr(ndr_client_t *clnt, ndr_xa_t *mxa)
-{
-	ndr_common_header_t *hdr = &mxa->send_hdr.common_hdr;
-
-	hdr->rpc_vers = 5;
-	hdr->rpc_vers_minor = 0;
-	hdr->pfc_flags = NDR_PFC_FIRST_FRAG + NDR_PFC_LAST_FRAG;
-	hdr->packed_drep.intg_char_rep = NDR_REPLAB_CHAR_ASCII;
-#ifndef _BIG_ENDIAN
-	hdr->packed_drep.intg_char_rep |= NDR_REPLAB_INTG_LITTLE_ENDIAN;
-#endif
-	/* hdr->frag_length */
-	hdr->auth_length = 0;
-	hdr->call_id = clnt->next_call_id++;
-}
-
-/*
- * ndr_clnt_get_frags
- *
- * A DCE RPC message that is larger than a single fragment is transmitted
- * as a series of fragments: 5280 bytes for Windows NT and 4280 bytes for
- * both Windows 2000 and 2003.
- *
- * Collect RPC fragments and append them to the receive stream buffer.
- * Each received fragment has a header, which we need to remove as we
- * build the full RPC PDU.  The scan offset is used to track frag headers.
- */
-static int
-ndr_clnt_get_frags(ndr_client_t *clnt, ndr_xa_t *mxa)
-{
-	ndr_stream_t *nds = &mxa->recv_nds;
-	ndr_common_header_t hdr;
-	int frag_size;
-	int last_frag;
-
-	do {
-		if (ndr_clnt_get_frag(clnt, mxa, &hdr) < 0) {
-			nds_show_state(nds);
-			return (-1);
-		}
-
-		last_frag = NDR_IS_LAST_FRAG(hdr.pfc_flags);
-		frag_size = hdr.frag_length;
-
-		if (frag_size > (nds->pdu_size - nds->pdu_scan_offset)) {
-			nds_show_state(nds);
-			return (-1);
-		}
-
-		ndr_remove_frag_hdr(nds);
-		nds->pdu_scan_offset += frag_size - NDR_RSP_HDR_SIZE;
-	} while (!last_frag);
-
-	return (0);
-}
-
-/*
- * Read the next RPC fragment.  The xa_read() calls correspond to SmbReadX
- * requests.  Note that there is no correspondence between SmbReadX buffering
- * and DCE RPC fragment alignment.
- */
-static int
-ndr_clnt_get_frag(ndr_client_t *clnt, ndr_xa_t *mxa, ndr_common_header_t *hdr)
-{
-	ndr_stream_t		*nds = &mxa->recv_nds;
-	unsigned long		available;
-	int			nbytes = 0;
-
-	available = nds->pdu_size - nds->pdu_scan_offset;
-
-	while (available < NDR_RSP_HDR_SIZE) {
-		if ((nbytes += (*clnt->xa_read)(clnt, mxa)) <= 0)
-			return (-1);
-		available += nbytes;
-	}
-
-	ndr_decode_frag_hdr(nds, hdr);
-	ndr_show_hdr(hdr);
-
-	while (available < hdr->frag_length) {
-		if ((nbytes = (*clnt->xa_read)(clnt, mxa)) <= 0)
-			return (-1);
-		available += nbytes;
-	}
-
-	return (nbytes);
-}
--- /dev/null	Sun Mar 18 01:13:16 2018
+++ new/usr/src/lib/libmlrpc/common/ndr_client.c	Sun Mar 18 01:13:16 2018
@@ -0,0 +1,325 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+#include <sys/errno.h>
+#include <string.h>
+#include <strings.h>
+
+#include <libmlrpc.h>
+
+#define	NDR_DEFAULT_FRAGSZ	8192
+#define	NDR_MULTI_FRAGSZ	(60 * 1024)
+
+static void ndr_clnt_init_hdr(ndr_client_t *, ndr_xa_t *);
+static int ndr_clnt_get_frags(ndr_client_t *, ndr_xa_t *);
+static int ndr_clnt_get_frag(ndr_client_t *, ndr_xa_t *, ndr_common_header_t *);
+
+int
+ndr_clnt_bind(ndr_client_t *clnt, ndr_service_t *msvc,
+    ndr_binding_t **ret_binding_p)
+{
+	ndr_binding_t		*mbind;
+	ndr_xa_t		mxa;
+	ndr_bind_hdr_t		*bhdr;
+	ndr_p_cont_elem_t 	*pce;
+	ndr_bind_ack_hdr_t	*bahdr;
+	ndr_p_result_t		*pre;
+	int			rc;
+
+	bzero(&mxa, sizeof (mxa));
+
+	mxa.binding_list = clnt->binding_list;
+	if ((mbind = ndr_svc_new_binding(&mxa)) == NULL)
+		return (NDR_DRC_FAULT_API_BIND_NO_SLOTS);
+
+	ndr_clnt_init_hdr(clnt, &mxa);
+
+	bhdr = &mxa.send_hdr.bind_hdr;
+	bhdr->common_hdr.ptype = NDR_PTYPE_BIND;
+	bhdr->common_hdr.frag_length = sizeof (*bhdr);
+	bhdr->max_xmit_frag = NDR_DEFAULT_FRAGSZ;
+	bhdr->max_recv_frag = NDR_DEFAULT_FRAGSZ;
+	bhdr->assoc_group_id = 0;
+	bhdr->p_context_elem.n_context_elem = 1;
+
+	/* Assign presentation context id */
+	pce = &bhdr->p_context_elem.p_cont_elem[0];
+	pce->p_cont_id = clnt->next_p_cont_id++;
+	pce->n_transfer_syn = 1;
+
+	/* Set up UUIDs and versions from the service */
+	pce->abstract_syntax.if_version = msvc->abstract_syntax_version;
+	rc = ndr_uuid_parse(msvc->abstract_syntax_uuid,
+	    &pce->abstract_syntax.if_uuid);
+	if (rc != 0)
+		return (NDR_DRC_FAULT_API_SERVICE_INVALID);
+
+	pce->transfer_syntaxes[0].if_version = msvc->transfer_syntax_version;
+	rc = ndr_uuid_parse(msvc->transfer_syntax_uuid,
+	    &pce->transfer_syntaxes[0].if_uuid);
+	if (rc != 0)
+		return (NDR_DRC_FAULT_API_SERVICE_INVALID);
+
+	/* Format and exchange the PDU */
+
+	if ((*clnt->xa_init)(clnt, &mxa) < 0)
+		return (NDR_DRC_FAULT_OUT_OF_MEMORY);
+
+	rc = ndr_encode_pdu_hdr(&mxa);
+	if (NDR_DRC_IS_FAULT(rc))
+		goto fault_exit;
+
+	if ((*clnt->xa_exchange)(clnt, &mxa) < 0) {
+		rc = NDR_DRC_FAULT_SEND_FAILED;
+		goto fault_exit;
+	}
+
+	rc = ndr_decode_pdu_hdr(&mxa);
+	if (NDR_DRC_IS_FAULT(rc))
+		goto fault_exit;
+
+	/* done with buffers */
+	(*clnt->xa_destruct)(clnt, &mxa);
+
+	bahdr = &mxa.recv_hdr.bind_ack_hdr;
+
+	if (mxa.ptype != NDR_PTYPE_BIND_ACK)
+		return (NDR_DRC_FAULT_RECEIVED_MALFORMED);
+
+	if (bahdr->p_result_list.n_results != 1)
+		return (NDR_DRC_FAULT_RECEIVED_MALFORMED);
+
+	pre = &bahdr->p_result_list.p_results[0];
+
+	if (pre->result != NDR_PCDR_ACCEPTANCE)
+		return (NDR_DRC_FAULT_RECEIVED_MALFORMED);
+
+	mbind->p_cont_id = pce->p_cont_id;
+	mbind->which_side = NDR_BIND_SIDE_CLIENT;
+	mbind->clnt = clnt;
+	mbind->service = msvc;
+	mbind->instance_specific = 0;
+
+	*ret_binding_p = mbind;
+	return (NDR_DRC_OK);
+
+fault_exit:
+	(*clnt->xa_destruct)(clnt, &mxa);
+	return (rc);
+}
+
+int
+ndr_clnt_call(ndr_binding_t *mbind, int opnum, void *params)
+{
+	ndr_client_t		*clnt = mbind->clnt;
+	ndr_xa_t		mxa;
+	ndr_request_hdr_t	*reqhdr;
+	ndr_common_header_t	*rsphdr;
+	unsigned long		recv_pdu_scan_offset;
+	int			rc;
+
+	bzero(&mxa, sizeof (mxa));
+	mxa.ptype = NDR_PTYPE_REQUEST;
+	mxa.opnum = opnum;
+	mxa.binding = mbind;
+
+	ndr_clnt_init_hdr(clnt, &mxa);
+
+	reqhdr = &mxa.send_hdr.request_hdr;
+	reqhdr->common_hdr.ptype = NDR_PTYPE_REQUEST;
+	reqhdr->p_cont_id = mbind->p_cont_id;
+	reqhdr->opnum = opnum;
+
+	rc = (*clnt->xa_init)(clnt, &mxa);
+	if (NDR_DRC_IS_FAULT(rc))
+		return (rc);
+
+	/* Reserve room for hdr */
+	mxa.send_nds.pdu_scan_offset = sizeof (*reqhdr);
+
+	rc = ndr_encode_call(&mxa, params);
+	if (!NDR_DRC_IS_OK(rc))
+		goto fault_exit;
+
+	mxa.send_nds.pdu_scan_offset = 0;
+
+	/*
+	 * Now we have the PDU size, we need to set up the
+	 * frag_length and calculate the alloc_hint.
+	 */
+	mxa.send_hdr.common_hdr.frag_length = mxa.send_nds.pdu_size;
+	reqhdr->alloc_hint = mxa.send_nds.pdu_size -
+	    sizeof (ndr_request_hdr_t);
+
+	rc = ndr_encode_pdu_hdr(&mxa);
+	if (NDR_DRC_IS_FAULT(rc))
+		goto fault_exit;
+
+	rc = (*clnt->xa_exchange)(clnt, &mxa);
+	if (NDR_DRC_IS_FAULT(rc))
+		goto fault_exit;
+
+	rc = ndr_decode_pdu_hdr(&mxa);
+	if (NDR_DRC_IS_FAULT(rc))
+		goto fault_exit;
+
+	if (mxa.ptype != NDR_PTYPE_RESPONSE) {
+		rc = NDR_DRC_FAULT_RECEIVED_MALFORMED;
+		goto fault_exit;
+	}
+
+	rsphdr = &mxa.recv_hdr.common_hdr;
+
+	if (!NDR_IS_LAST_FRAG(rsphdr->pfc_flags)) {
+		/*
+		 * This is a multi-fragment response.
+		 * Preserve the current scan offset while getting
+		 * fragments so that we can continue afterward
+		 * as if we had received the entire response as
+		 * a single PDU.
+		 */
+		(void) NDS_GROW_PDU(&mxa.recv_nds, NDR_MULTI_FRAGSZ, NULL);
+
+		recv_pdu_scan_offset = mxa.recv_nds.pdu_scan_offset;
+		mxa.recv_nds.pdu_scan_offset = rsphdr->frag_length;
+		mxa.recv_nds.pdu_size = rsphdr->frag_length;
+
+		if (ndr_clnt_get_frags(clnt, &mxa) < 0) {
+			rc = NDR_DRC_FAULT_RECEIVED_MALFORMED;
+			goto fault_exit;
+		}
+
+		mxa.recv_nds.pdu_scan_offset = recv_pdu_scan_offset;
+	}
+
+	rc = ndr_decode_return(&mxa, params);
+	if (NDR_DRC_IS_FAULT(rc))
+		goto fault_exit;
+
+	(*clnt->xa_preserve)(clnt, &mxa);
+	(*clnt->xa_destruct)(clnt, &mxa);
+	return (NDR_DRC_OK);
+
+fault_exit:
+	(*clnt->xa_destruct)(clnt, &mxa);
+	return (rc);
+}
+
+void
+ndr_clnt_free_heap(ndr_client_t *clnt)
+{
+	(*clnt->xa_release)(clnt);
+}
+
+static void
+ndr_clnt_init_hdr(ndr_client_t *clnt, ndr_xa_t *mxa)
+{
+	ndr_common_header_t *hdr = &mxa->send_hdr.common_hdr;
+
+	hdr->rpc_vers = 5;
+	hdr->rpc_vers_minor = 0;
+	hdr->pfc_flags = NDR_PFC_FIRST_FRAG + NDR_PFC_LAST_FRAG;
+	hdr->packed_drep.intg_char_rep = NDR_REPLAB_CHAR_ASCII;
+#ifndef _BIG_ENDIAN
+	hdr->packed_drep.intg_char_rep |= NDR_REPLAB_INTG_LITTLE_ENDIAN;
+#endif
+	/* hdr->frag_length */
+	hdr->auth_length = 0;
+	hdr->call_id = clnt->next_call_id++;
+}
+
+/*
+ * ndr_clnt_get_frags
+ *
+ * A DCE RPC message that is larger than a single fragment is transmitted
+ * as a series of fragments: 5280 bytes for Windows NT and 4280 bytes for
+ * both Windows 2000 and 2003.
+ *
+ * Collect RPC fragments and append them to the receive stream buffer.
+ * Each received fragment has a header, which we need to remove as we
+ * build the full RPC PDU.  The scan offset is used to track frag headers.
+ */
+static int
+ndr_clnt_get_frags(ndr_client_t *clnt, ndr_xa_t *mxa)
+{
+	ndr_stream_t *nds = &mxa->recv_nds;
+	ndr_common_header_t hdr;
+	int frag_size;
+	int last_frag;
+
+	do {
+		if (ndr_clnt_get_frag(clnt, mxa, &hdr) < 0) {
+			nds_show_state(nds);
+			return (-1);
+		}
+
+		last_frag = NDR_IS_LAST_FRAG(hdr.pfc_flags);
+		frag_size = hdr.frag_length;
+
+		if (frag_size > (nds->pdu_size - nds->pdu_scan_offset)) {
+			nds_show_state(nds);
+			return (-1);
+		}
+
+		ndr_remove_frag_hdr(nds);
+		nds->pdu_scan_offset += frag_size - NDR_RSP_HDR_SIZE;
+	} while (!last_frag);
+
+	return (0);
+}
+
+/*
+ * Read the next RPC fragment.  The xa_read() calls correspond to SmbReadX
+ * requests.  Note that there is no correspondence between SmbReadX buffering
+ * and DCE RPC fragment alignment.
+ */
+static int
+ndr_clnt_get_frag(ndr_client_t *clnt, ndr_xa_t *mxa, ndr_common_header_t *hdr)
+{
+	ndr_stream_t		*nds = &mxa->recv_nds;
+	unsigned long		available;
+	int			nbytes = 0;
+
+	available = nds->pdu_size - nds->pdu_scan_offset;
+
+	while (available < NDR_RSP_HDR_SIZE) {
+		if ((nbytes += (*clnt->xa_read)(clnt, mxa)) <= 0)
+			return (-1);
+		available += nbytes;
+	}
+
+	ndr_decode_frag_hdr(nds, hdr);
+	ndr_show_hdr(hdr);
+
+	while (available < hdr->frag_length) {
+		if ((nbytes = (*clnt->xa_read)(clnt, mxa)) <= 0)
+			return (-1);
+		available += nbytes;
+	}
+
+	return (nbytes);
+}
--- old/usr/src/lib/smbsrv/libmlrpc/common/ndr_heap.c	Sun Mar 18 01:13:16 2018
+++ /dev/null	Sun Mar 18 01:13:16 2018
@@ -1,297 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * NDR heap management. The heap is used for temporary storage by
- * both the client and server side library routines.  In order to
- * support the different requirements of the various RPCs, the heap
- * can grow dynamically if required.  We start with a single block
- * and perform sub-allocations from it.  If an RPC requires more space
- * we will continue to add it a block at a time.  This means that we
- * don't hog lots of memory on every call to support the few times
- * that we actually need a lot heap space.
- *
- * Note that there is no individual free function.  Once space has been
- * allocated, it remains allocated until the heap is destroyed.  This
- * shouldn't be an issue because the heap is being filled with data to
- * be marshalled or unmarshalled and we need it all to be there until
- * the point that the entire heap is no longer required.
- */
-
-#include <sys/errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <sys/uio.h>
-
-#include <smbsrv/libsmb.h>
-#include <smbsrv/libmlrpc.h>
-#include <smbsrv/smb_sid.h>
-
-/*
- * Allocate a heap structure and the first heap block.  For many RPC
- * operations this will be the only time we need to malloc memory
- * in this instance of the heap.  The only point of note here is that
- * we put the heap management data in the first block to avoid a
- * second malloc. Make sure that sizeof(ndr_heap_t) is smaller
- * than NDR_HEAP_BLKSZ.
- *
- * Note that the heap management data is at the start of the first block.
- *
- * Returns a pointer to the newly created heap, which is used like an
- * opaque handle with the rest of the heap management interface..
- */
-ndr_heap_t *
-ndr_heap_create(void)
-{
-	ndr_heap_t *heap;
-	char *base;
-	size_t allocsize = sizeof (ndr_heap_t) + NDR_HEAP_BLKSZ;
-
-	if ((heap = malloc(allocsize)) == NULL)
-		return (NULL);
-
-	base = (char *)heap;
-	bzero(heap, sizeof (ndr_heap_t));
-
-	heap->iovcnt = NDR_HEAP_MAXIOV;
-	heap->iov = heap->iovec;
-	heap->iov->iov_base = base;
-	heap->iov->iov_len = sizeof (ndr_heap_t);
-	heap->top = base + allocsize;
-	heap->next = base + sizeof (ndr_heap_t);
-
-	return (heap);
-}
-
-/*
- * Deallocate all of the memory associated with a heap.  This is the
- * only way to deallocate heap memory, it isn't possible to free the
- * space obtained by individual malloc calls.
- *
- * Note that the first block contains the heap management data, which
- * is deleted last.
- */
-void
-ndr_heap_destroy(ndr_heap_t *heap)
-{
-	int i;
-	char *p;
-
-	if (heap) {
-		for (i = 1; i < NDR_HEAP_MAXIOV; ++i) {
-			if ((p = heap->iovec[i].iov_base) != NULL)
-				free(p);
-		}
-
-		free(heap);
-	}
-}
-
-/*
- * Allocate space in the specified heap.  All requests are padded, if
- * required, to ensure dword alignment.  If the current iov will be
- * exceeded, we allocate a new block and setup the next iov.  Otherwise
- * all we have to do is move the next pointer and update the current
- * iov length.
- *
- * On success, a pointer to the allocated (dword aligned) area is
- * returned.  Otherwise a null pointer is returned.
- */
-void *
-ndr_heap_malloc(ndr_heap_t *heap, unsigned size)
-{
-	char *p;
-	int incr_size;
-
-	size += NDR_ALIGN4(size);
-
-	if (heap == NULL || size == 0)
-		return (NULL);
-
-	p = heap->next;
-
-	if (p + size > heap->top) {
-		if ((heap->iovcnt == 0) || ((--heap->iovcnt) == 0))
-			return (NULL);
-
-		incr_size = (size < NDR_HEAP_BLKSZ) ? NDR_HEAP_BLKSZ : size;
-
-		if ((p = (char *)malloc(incr_size)) == NULL)
-			return (NULL);
-
-		++heap->iov;
-		heap->iov->iov_base = p;
-		heap->iov->iov_len = 0;
-		heap->top = p + incr_size;
-	}
-
-	heap->next = p + size;
-	heap->iov->iov_len += size;
-	return ((void *)p);
-}
-
-/*
- * Convenience function to do heap strdup.
- */
-void *
-ndr_heap_strdup(ndr_heap_t *heap, const char *s)
-{
-	int len;
-	void *p;
-
-	if (s == NULL)
-		return (NULL);
-
-	/*
-	 * We don't need to clutter the heap with empty strings.
-	 */
-	if ((len = strlen(s)) == 0)
-		return ("");
-
-	if ((p = ndr_heap_malloc(heap, len+1)) != NULL)
-		(void) strcpy((char *)p, s);
-
-	return (p);
-}
-
-/*
- * Make an ndr_mstring_t from a regular string.
- */
-int
-ndr_heap_mstring(ndr_heap_t *heap, const char *s, ndr_mstring_t *out)
-{
-	if (s == NULL || out == NULL)
-		return (-1);
-
-	out->length = smb_wcequiv_strlen(s);
-	out->allosize = out->length + sizeof (smb_wchar_t);
-
-	if ((out->str = ndr_heap_strdup(heap, s)) == NULL)
-		return (-1);
-
-	return (0);
-}
-
-/*
- * Our regular string marshalling always creates null terminated strings
- * but some Windows clients and servers are pedantic about the string
- * formats they will accept and require non-null terminated strings.
- * This function can be used to build a wide-char, non-null terminated
- * string in the heap as a varying/conformant array.  We need to do the
- * wide-char conversion here because the marshalling code won't be
- * aware that this is really a string.
- */
-void
-ndr_heap_mkvcs(ndr_heap_t *heap, char *s, ndr_vcstr_t *vc)
-{
-	int mlen;
-
-	vc->wclen = smb_wcequiv_strlen(s);
-	vc->wcsize = vc->wclen;
-
-	mlen = sizeof (ndr_vcs_t) + vc->wcsize + sizeof (smb_wchar_t);
-
-	vc->vcs = ndr_heap_malloc(heap, mlen);
-
-	if (vc->vcs) {
-		vc->vcs->vc_first_is = 0;
-		vc->vcs->vc_length_is = vc->wclen / sizeof (smb_wchar_t);
-		(void) smb_mbstowcs((smb_wchar_t *)vc->vcs->buffer, s,
-		    vc->vcs->vc_length_is);
-	}
-}
-
-void
-ndr_heap_mkvcb(ndr_heap_t *heap, uint8_t *data, uint32_t datalen,
-    ndr_vcbuf_t *vcbuf)
-{
-	int mlen;
-
-	if (data == NULL || datalen == 0) {
-		bzero(vcbuf, sizeof (ndr_vcbuf_t));
-		return;
-	}
-
-	vcbuf->len = datalen;
-	vcbuf->size = datalen;
-
-	mlen = sizeof (ndr_vcbuf_t) + datalen;
-
-	vcbuf->vcb = ndr_heap_malloc(heap, mlen);
-
-	if (vcbuf->vcb) {
-		vcbuf->vcb->vc_first_is = 0;
-		vcbuf->vcb->vc_length_is = datalen;
-		bcopy(data, vcbuf->vcb->buffer, datalen);
-	}
-}
-
-/*
- * Duplcate a SID in the heap.
- */
-smb_sid_t *
-ndr_heap_siddup(ndr_heap_t *heap, smb_sid_t *sid)
-{
-	smb_sid_t *new_sid;
-	unsigned size;
-
-	if (sid == NULL)
-		return (NULL);
-
-	size = smb_sid_len(sid);
-
-	if ((new_sid = ndr_heap_malloc(heap, size)) == NULL)
-		return (NULL);
-
-	bcopy(sid, new_sid, size);
-	return (new_sid);
-}
-
-int
-ndr_heap_used(ndr_heap_t *heap)
-{
-	int used = 0;
-	int i;
-
-	for (i = 0; i < NDR_HEAP_MAXIOV; ++i)
-		used += heap->iovec[i].iov_len;
-
-	return (used);
-}
-
-int
-ndr_heap_avail(ndr_heap_t *heap)
-{
-	int avail;
-	int count;
-
-	count = (heap->iovcnt == 0) ? 0 : (heap->iovcnt - 1);
-
-	avail = count * NDR_HEAP_BLKSZ;
-	avail += (heap->top - heap->next);
-
-	return (avail);
-}
--- /dev/null	Sun Mar 18 01:13:16 2018
+++ new/usr/src/lib/libmlrpc/common/ndr_heap.c	Sun Mar 18 01:13:16 2018
@@ -0,0 +1,318 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+/*
+ * NDR heap management. The heap is used for temporary storage by
+ * both the client and server side library routines.  In order to
+ * support the different requirements of the various RPCs, the heap
+ * can grow dynamically if required.  We start with a single block
+ * and perform sub-allocations from it.  If an RPC requires more space
+ * we will continue to add it a block at a time.  This means that we
+ * don't hog lots of memory on every call to support the few times
+ * that we actually need a lot heap space.
+ *
+ * Note that there is no individual free function.  Once space has been
+ * allocated, it remains allocated until the heap is destroyed.  This
+ * shouldn't be an issue because the heap is being filled with data to
+ * be marshalled or unmarshalled and we need it all to be there until
+ * the point that the entire heap is no longer required.
+ */
+
+#include <sys/errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/uio.h>
+
+#include <libmlrpc.h>
+#include <ndr_wchar.h>
+
+/*
+ * Allocate a heap structure and the first heap block.  For many RPC
+ * operations this will be the only time we need to malloc memory
+ * in this instance of the heap.  The only point of note here is that
+ * we put the heap management data in the first block to avoid a
+ * second malloc. Make sure that sizeof(ndr_heap_t) is smaller
+ * than NDR_HEAP_BLKSZ.
+ *
+ * Note that the heap management data is at the start of the first block.
+ *
+ * Returns a pointer to the newly created heap, which is used like an
+ * opaque handle with the rest of the heap management interface..
+ */
+ndr_heap_t *
+ndr_heap_create(void)
+{
+	ndr_heap_t *heap;
+	char *base;
+	size_t allocsize = sizeof (ndr_heap_t) + NDR_HEAP_BLKSZ;
+
+	if ((heap = malloc(allocsize)) == NULL)
+		return (NULL);
+
+	base = (char *)heap;
+	bzero(heap, sizeof (ndr_heap_t));
+
+	heap->iovcnt = NDR_HEAP_MAXIOV;
+	heap->iov = heap->iovec;
+	heap->iov->iov_base = base;
+	heap->iov->iov_len = sizeof (ndr_heap_t);
+	heap->top = base + allocsize;
+	heap->next = base + sizeof (ndr_heap_t);
+
+	return (heap);
+}
+
+/*
+ * Deallocate all of the memory associated with a heap.  This is the
+ * only way to deallocate heap memory, it isn't possible to free the
+ * space obtained by individual malloc calls.
+ *
+ * Note that the first block contains the heap management data, which
+ * is deleted last.
+ */
+void
+ndr_heap_destroy(ndr_heap_t *heap)
+{
+	int i;
+	char *p;
+
+	if (heap) {
+		for (i = 1; i < NDR_HEAP_MAXIOV; ++i) {
+			if ((p = heap->iovec[i].iov_base) != NULL)
+				free(p);
+		}
+
+		free(heap);
+	}
+}
+
+/*
+ * Allocate space in the specified heap.  All requests are padded, if
+ * required, to ensure dword alignment.  If the current iov will be
+ * exceeded, we allocate a new block and setup the next iov.  Otherwise
+ * all we have to do is move the next pointer and update the current
+ * iov length.
+ *
+ * On success, a pointer to the allocated (dword aligned) area is
+ * returned.  Otherwise a null pointer is returned.
+ */
+void *
+ndr_heap_malloc(ndr_heap_t *heap, unsigned size)
+{
+	char *p;
+	int incr_size;
+
+	size += NDR_ALIGN4(size);
+
+	if (heap == NULL || size == 0)
+		return (NULL);
+
+	p = heap->next;
+
+	if (p + size > heap->top) {
+		if ((heap->iovcnt == 0) || ((--heap->iovcnt) == 0))
+			return (NULL);
+
+		incr_size = (size < NDR_HEAP_BLKSZ) ? NDR_HEAP_BLKSZ : size;
+
+		if ((p = (char *)malloc(incr_size)) == NULL)
+			return (NULL);
+
+		++heap->iov;
+		heap->iov->iov_base = p;
+		heap->iov->iov_len = 0;
+		heap->top = p + incr_size;
+	}
+
+	heap->next = p + size;
+	heap->iov->iov_len += size;
+	return ((void *)p);
+}
+
+/*
+ * Convenience function to copy some memory into the heap.
+ */
+void *
+ndr_heap_dupmem(ndr_heap_t *heap, const void *mem, size_t len)
+{
+	void *p;
+
+	if (mem == NULL)
+		return (NULL);
+
+	if ((p = ndr_heap_malloc(heap, len)) != NULL)
+		(void) memcpy(p, mem, len);
+
+	return (p);
+}
+
+/*
+ * Convenience function to do heap strdup.
+ */
+void *
+ndr_heap_strdup(ndr_heap_t *heap, const char *s)
+{
+	int len;
+	void *p;
+
+	if (s == NULL)
+		return (NULL);
+
+	/*
+	 * We don't need to clutter the heap with empty strings.
+	 */
+	if ((len = strlen(s)) == 0)
+		return ("");
+
+	p = ndr_heap_dupmem(heap, s, len+1);
+
+	return (p);
+}
+
+/*
+ * Make an ndr_mstring_t from a regular string.
+ */
+int
+ndr_heap_mstring(ndr_heap_t *heap, const char *s, ndr_mstring_t *out)
+{
+	size_t slen;
+
+	if (s == NULL || out == NULL)
+		return (-1);
+
+	/*
+	 * Determine the WC strlen of s
+	 * Was ndr__wcequiv_strlen(s)
+	 */
+	slen = ndr__mbstowcs(NULL, s, NDR_STRING_MAX);
+	if (slen == (size_t)-1)
+		return (-1);
+
+	out->length = slen * sizeof (ndr_wchar_t);
+	out->allosize = out->length + sizeof (ndr_wchar_t);
+
+	if ((out->str = ndr_heap_strdup(heap, s)) == NULL)
+		return (-1);
+
+	return (0);
+}
+
+/*
+ * Our regular string marshalling always creates null terminated strings
+ * but some Windows clients and servers are pedantic about the string
+ * formats they will accept and require non-null terminated strings.
+ * This function can be used to build a wide-char, non-null terminated
+ * string in the heap as a varying/conformant array.  We need to do the
+ * wide-char conversion here because the marshalling code won't be
+ * aware that this is really a string.
+ */
+void
+ndr_heap_mkvcs(ndr_heap_t *heap, char *s, ndr_vcstr_t *vc)
+{
+	size_t slen;
+	int mlen;
+
+	/*
+	 * Determine the WC strlen of s
+	 * Was ndr__wcequiv_strlen(s)
+	 */
+	slen = ndr__mbstowcs(NULL, s, NDR_STRING_MAX);
+	if (slen == (size_t)-1)
+		slen = 0;
+
+	vc->wclen = slen * sizeof (ndr_wchar_t);
+	vc->wcsize = vc->wclen;
+
+	/*
+	 * alloc one extra wchar for a null
+	 * See slen + 1 arg for mbstowcs
+	 */
+	mlen = sizeof (ndr_vcs_t) + vc->wcsize + sizeof (ndr_wchar_t);
+	vc->vcs = ndr_heap_malloc(heap, mlen);
+
+	if (vc->vcs) {
+		vc->vcs->vc_first_is = 0;
+		vc->vcs->vc_length_is = slen;
+		(void) ndr__mbstowcs(vc->vcs->buffer, s, slen + 1);
+	}
+}
+
+void
+ndr_heap_mkvcb(ndr_heap_t *heap, uint8_t *data, uint32_t datalen,
+    ndr_vcbuf_t *vcbuf)
+{
+	int mlen;
+
+	if (data == NULL || datalen == 0) {
+		bzero(vcbuf, sizeof (ndr_vcbuf_t));
+		return;
+	}
+
+	vcbuf->len = datalen;
+	vcbuf->size = datalen;
+
+	mlen = sizeof (ndr_vcbuf_t) + datalen;
+
+	vcbuf->vcb = ndr_heap_malloc(heap, mlen);
+
+	if (vcbuf->vcb) {
+		vcbuf->vcb->vc_first_is = 0;
+		vcbuf->vcb->vc_length_is = datalen;
+		bcopy(data, vcbuf->vcb->buffer, datalen);
+	}
+}
+
+/*
+ * Removed ndr_heap_siddup(), now using ndr_heap_dupmem().
+ */
+
+int
+ndr_heap_used(ndr_heap_t *heap)
+{
+	int used = 0;
+	int i;
+
+	for (i = 0; i < NDR_HEAP_MAXIOV; ++i)
+		used += heap->iovec[i].iov_len;
+
+	return (used);
+}
+
+int
+ndr_heap_avail(ndr_heap_t *heap)
+{
+	int avail;
+	int count;
+
+	count = (heap->iovcnt == 0) ? 0 : (heap->iovcnt - 1);
+
+	avail = count * NDR_HEAP_BLKSZ;
+	avail += (heap->top - heap->next);
+
+	return (avail);
+}
--- old/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c	Sun Mar 18 01:13:16 2018
+++ /dev/null	Sun Mar 18 01:13:16 2018
@@ -1,648 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-#include <assert.h>
-#include <strings.h>
-#include <sys/param.h>
-
-#include <smbsrv/libsmb.h>
-#include <smbsrv/libmlrpc.h>
-
-#ifdef _BIG_ENDIAN
-static const int ndr_native_byte_order = NDR_REPLAB_INTG_BIG_ENDIAN;
-#else
-static const int ndr_native_byte_order = NDR_REPLAB_INTG_LITTLE_ENDIAN;
-#endif
-
-static int ndr_decode_hdr_common(ndr_stream_t *, ndr_common_header_t *);
-static int ndr_decode_pac_hdr(ndr_stream_t *, ndr_pac_hdr_t *);
-
-static int
-ndr_encode_decode_common(ndr_stream_t *nds, unsigned opnum,
-    ndr_typeinfo_t *ti, void *datum)
-{
-	int rc;
-
-	/*
-	 * Perform the (un)marshalling
-	 */
-	if (ndo_operation(nds, ti, opnum, datum))
-		return (NDR_DRC_OK);
-
-	switch (nds->error) {
-	case NDR_ERR_MALLOC_FAILED:
-		rc = NDR_DRC_FAULT_OUT_OF_MEMORY;
-		break;
-
-	case NDR_ERR_SWITCH_VALUE_INVALID:
-		rc = NDR_DRC_FAULT_PARAM_0_INVALID;
-		break;
-
-	case NDR_ERR_UNDERFLOW:
-		rc = NDR_DRC_FAULT_RECEIVED_RUNT;
-		break;
-
-	case NDR_ERR_GROW_FAILED:
-		rc = NDR_DRC_FAULT_ENCODE_TOO_BIG;
-		break;
-
-	default:
-		if (nds->m_op == NDR_M_OP_MARSHALL)
-			rc = NDR_DRC_FAULT_ENCODE_FAILED;
-		else
-			rc = NDR_DRC_FAULT_DECODE_FAILED;
-		break;
-	}
-
-	return (rc);
-}
-
-ndr_buf_t *
-ndr_buf_init(ndr_typeinfo_t *ti)
-{
-	ndr_buf_t		*nbuf;
-
-	if ((nbuf = calloc(1, sizeof (ndr_buf_t))) == NULL)
-		return (NULL);
-
-	if ((nbuf->nb_heap = ndr_heap_create()) == NULL) {
-		free(nbuf);
-		return (NULL);
-	}
-
-	nbuf->nb_ti = ti;
-	nbuf->nb_magic = NDR_BUF_MAGIC;
-	return (nbuf);
-}
-
-void
-ndr_buf_fini(ndr_buf_t *nbuf)
-{
-	assert(nbuf->nb_magic == NDR_BUF_MAGIC);
-
-	nds_destruct(&nbuf->nb_nds);
-	ndr_heap_destroy(nbuf->nb_heap);
-	nbuf->nb_magic = 0;
-	free(nbuf);
-}
-
-/*
- * Decode an NDR encoded buffer.  The buffer is expected to contain
- * a single fragment packet with a valid PDU header followed by NDR
- * encoded data.  The structure to which result points should be
- * of the appropriate type to hold the decoded output.  For example:
- *
- *	pac_info_t info;
- *
- * 	if ((nbuf = ndr_buf_init(&TYPEINFO(ndr_pac)) != NULL) {
- *		rc = ndr_decode_buf(nbuf, opnum, data, datalen, &info);
- *		...
- *		ndr_buf_fini(nbuf);
- *	}
- */
-int
-ndr_buf_decode(ndr_buf_t *nbuf, unsigned hdr_type, unsigned opnum,
-    const char *data, size_t datalen, void *result)
-{
-	ndr_common_header_t	hdr;
-	ndr_pac_hdr_t		pac_hdr;
-	unsigned		pdu_size_hint;
-	int			rc;
-
-	assert(nbuf->nb_magic == NDR_BUF_MAGIC);
-	assert(nbuf->nb_heap != NULL);
-	assert(nbuf->nb_ti != NULL);
-
-	if (datalen < NDR_PDU_SIZE_HINT_DEFAULT)
-		pdu_size_hint = NDR_PDU_SIZE_HINT_DEFAULT;
-	else
-		pdu_size_hint = datalen;
-
-	rc = nds_initialize(&nbuf->nb_nds, pdu_size_hint, NDR_MODE_BUF_DECODE,
-	    nbuf->nb_heap);
-	if (NDR_DRC_IS_FAULT(rc))
-		return (rc);
-
-	bcopy(data, nbuf->nb_nds.pdu_base_addr, datalen);
-
-	switch (hdr_type) {
-	case NDR_PTYPE_COMMON:
-		rc = ndr_decode_hdr_common(&nbuf->nb_nds, &hdr);
-		if (NDR_DRC_IS_FAULT(rc))
-			return (rc);
-
-		if (!NDR_IS_SINGLE_FRAG(hdr.pfc_flags))
-			return (NDR_DRC_FAULT_DECODE_FAILED);
-		break;
-
-	case NDR_PTYPE_PAC:
-		rc = ndr_decode_pac_hdr(&nbuf->nb_nds, &pac_hdr);
-		if (NDR_DRC_IS_FAULT(rc))
-			return (rc);
-
-		if (pac_hdr.common_hdr.hdrlen != sizeof (ndr_serialtype1_hdr_t))
-			return (NDR_DRC_FAULT_DECODE_FAILED);
-		break;
-
-	default:
-		return (NDR_ERR_UNIMPLEMENTED);
-	}
-
-	rc = ndr_encode_decode_common(&nbuf->nb_nds, opnum, nbuf->nb_ti,
-	    result);
-	return (rc);
-}
-
-/*
- * Use the receive stream to unmarshall data (NDR_MODE_CALL_RECV).
- */
-int
-ndr_decode_call(ndr_xa_t *mxa, void *params)
-{
-	ndr_stream_t	*nds = &mxa->recv_nds;
-	int		rc;
-
-	if (!NDR_MODE_MATCH(nds, NDR_MODE_CALL_RECV))
-		return (NDR_DRC_FAULT_MODE_MISMATCH);
-
-	rc = ndr_encode_decode_common(nds, mxa->opnum,
-	    mxa->binding->service->interface_ti, params);
-
-	return (rc + NDR_PTYPE_REQUEST);
-}
-
-/*
- * Use the send stream to marshall data (NDR_MODE_RETURN_SEND).
- */
-int
-ndr_encode_return(ndr_xa_t *mxa, void *params)
-{
-	ndr_stream_t	*nds = &mxa->send_nds;
-	int		rc;
-
-	if (!NDR_MODE_MATCH(nds, NDR_MODE_RETURN_SEND))
-		return (NDR_DRC_FAULT_MODE_MISMATCH);
-
-	rc = ndr_encode_decode_common(nds, mxa->opnum,
-	    mxa->binding->service->interface_ti, params);
-
-	return (rc + NDR_PTYPE_RESPONSE);
-}
-
-/*
- * Use the send stream to marshall data (NDR_MODE_CALL_SEND).
- */
-int
-ndr_encode_call(ndr_xa_t *mxa, void *params)
-{
-	ndr_stream_t	*nds = &mxa->send_nds;
-	int		rc;
-
-	if (!NDR_MODE_MATCH(nds, NDR_MODE_CALL_SEND))
-		return (NDR_DRC_FAULT_MODE_MISMATCH);
-
-	rc = ndr_encode_decode_common(nds, mxa->opnum,
-	    mxa->binding->service->interface_ti, params);
-
-	return (rc + NDR_PTYPE_REQUEST);
-}
-
-/*
- * Use the receive stream to unmarshall data (NDR_MODE_RETURN_RECV).
- */
-int
-ndr_decode_return(ndr_xa_t *mxa, void *params)
-{
-	ndr_stream_t	*nds = &mxa->recv_nds;
-	int		rc;
-
-	if (!NDR_MODE_MATCH(nds, NDR_MODE_RETURN_RECV))
-		return (NDR_DRC_FAULT_MODE_MISMATCH);
-
-	rc = ndr_encode_decode_common(nds, mxa->opnum,
-	    mxa->binding->service->interface_ti, params);
-
-	return (rc + NDR_PTYPE_RESPONSE);
-}
-
-int
-ndr_decode_pdu_hdr(ndr_xa_t *mxa)
-{
-	ndr_common_header_t	*hdr = &mxa->recv_hdr.common_hdr;
-	ndr_stream_t		*nds = &mxa->recv_nds;
-	int			rc;
-
-	rc = ndr_decode_hdr_common(nds, hdr);
-	if (NDR_DRC_IS_FAULT(rc))
-		return (rc);
-
-	/*
-	 * Verify the protocol version.
-	 */
-	if ((hdr->rpc_vers != 5) || (hdr->rpc_vers_minor != 0))
-		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
-
-	mxa->ptype = hdr->ptype;
-	return (NDR_DRC_OK);
-}
-
-static int
-ndr_decode_hdr_common(ndr_stream_t *nds, ndr_common_header_t *hdr)
-{
-	int			ptype;
-	int			rc;
-	int			charset;
-	int			byte_order;
-
-	if (nds->m_op != NDR_M_OP_UNMARSHALL)
-		return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH);
-
-	/*
-	 * All PDU headers are at least this big
-	 */
-	rc = NDS_GROW_PDU(nds, sizeof (ndr_common_header_t), 0);
-	if (!rc)
-		return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT);
-
-	/*
-	 * Peek at the first eight bytes to figure out what we're doing.
-	 */
-	rc = NDS_GET_PDU(nds, 0, 8, (char *)hdr, 0, 0);
-	if (!rc)
-		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
-
-	/*
-	 * Check for ASCII as the character set.  This is an ASCII
-	 * versus EBCDIC option and has nothing to do with Unicode.
-	 */
-	charset = hdr->packed_drep.intg_char_rep & NDR_REPLAB_CHAR_MASK;
-	if (charset != NDR_REPLAB_CHAR_ASCII)
-		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
-
-	/*
-	 * Set the byte swap flag if the PDU byte-order
-	 * is different from the local byte-order.
-	 */
-	byte_order = hdr->packed_drep.intg_char_rep & NDR_REPLAB_INTG_MASK;
-	nds->swap = (byte_order != ndr_native_byte_order) ? 1 : 0;
-
-	ptype = hdr->ptype;
-	if (ptype == NDR_PTYPE_REQUEST &&
-	    (hdr->pfc_flags & NDR_PFC_OBJECT_UUID) != 0) {
-		ptype = NDR_PTYPE_REQUEST_WITH;	/* fake for sizing */
-	}
-
-	rc = ndr_encode_decode_common(nds, ptype, &TYPEINFO(ndr_hdr), hdr);
-
-	return (NDR_DRC_PTYPE_RPCHDR(rc));
-}
-
-static int
-ndr_decode_pac_hdr(ndr_stream_t *nds, ndr_pac_hdr_t *hdr)
-{
-	int	rc;
-
-	if (nds->m_op != NDR_M_OP_UNMARSHALL)
-		return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH);
-
-	/*
-	 * All PDU headers are at least this big
-	 */
-	rc = NDS_GROW_PDU(nds, sizeof (ndr_pac_hdr_t), 0);
-	if (!rc)
-		return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT);
-
-	/*
-	 * Peek at the first eight bytes to figure out what we're doing.
-	 */
-	rc = NDS_GET_PDU(nds, 0, 8, (char *)hdr, 0, 0);
-	if (!rc)
-		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
-
-	/* Must be set to 1 to indicate type serialization version 1. */
-	if (hdr->common_hdr.version != 1)
-		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
-
-	/*
-	 * Set the byte swap flag if the PDU byte-order
-	 * is different from the local byte-order.
-	 */
-	nds->swap =
-	    (hdr->common_hdr.endianness != ndr_native_byte_order) ? 1 : 0;
-
-	rc = ndr_encode_decode_common(nds, NDR_PTYPE_PAC,
-	    &TYPEINFO(ndr_hdr), hdr);
-
-	return (NDR_DRC_PTYPE_RPCHDR(rc));
-}
-
-/*
- * Decode an RPC fragment header.  Use ndr_decode_pdu_hdr() to process
- * the first fragment header then this function to process additional
- * fragment headers.
- */
-void
-ndr_decode_frag_hdr(ndr_stream_t *nds, ndr_common_header_t *hdr)
-{
-	ndr_common_header_t *tmp;
-	uint8_t *pdu;
-	int byte_order;
-
-	pdu = (uint8_t *)nds->pdu_base_offset + nds->pdu_scan_offset;
-	bcopy(pdu, hdr, NDR_RSP_HDR_SIZE);
-
-	/*
-	 * Swap non-byte fields if the PDU byte-order
-	 * is different from the local byte-order.
-	 */
-	byte_order = hdr->packed_drep.intg_char_rep & NDR_REPLAB_INTG_MASK;
-
-	if (byte_order != ndr_native_byte_order) {
-		/*LINTED E_BAD_PTR_CAST_ALIGN*/
-		tmp = (ndr_common_header_t *)pdu;
-
-		nds_bswap(&tmp->frag_length, &hdr->frag_length,
-		    sizeof (WORD));
-		nds_bswap(&tmp->auth_length, &hdr->auth_length,
-		    sizeof (WORD));
-		nds_bswap(&tmp->call_id, &hdr->call_id, sizeof (DWORD));
-	}
-}
-
-/*
- * Remove an RPC fragment header from the received data stream.
- *
- * NDR stream on entry:
- *
- *                |<--- frag --->|
- * +-----+--------+-----+--------+-----+---------+-----+
- * | hdr |  data  | hdr |  data  | hdr |  data   | ... |
- * +-----+--------+-----+--------+-----+---------+-----+
- *                 <----
- *
- * NDR stream on return:
- *
- * +-----+----------------+-----+---------+-----+
- * | hdr |       data     | hdr |  data   | ... |
- * +-----+----------------+-----+---------+-----+
- */
-void
-ndr_remove_frag_hdr(ndr_stream_t *nds)
-{
-	char	*hdr;
-	char	*data;
-	int	nbytes;
-
-	hdr = (char *)nds->pdu_base_offset + nds->pdu_scan_offset;
-	data = hdr + NDR_RSP_HDR_SIZE;
-	nbytes = nds->pdu_size - nds->pdu_scan_offset - NDR_RSP_HDR_SIZE;
-
-	bcopy(data, hdr, nbytes);
-	nds->pdu_size -= NDR_RSP_HDR_SIZE;
-}
-
-void
-ndr_show_hdr(ndr_common_header_t *hdr)
-{
-	char	*fragtype;
-
-	if (hdr == NULL) {
-		ndo_printf(NULL, NULL, "ndr hdr: <null>");
-		return;
-	}
-
-	if (NDR_IS_SINGLE_FRAG(hdr->pfc_flags))
-		fragtype = "single";
-	else if (NDR_IS_FIRST_FRAG(hdr->pfc_flags))
-		fragtype = "first";
-	else if (NDR_IS_LAST_FRAG(hdr->pfc_flags))
-		fragtype = "last";
-	else
-		fragtype = "intermediate";
-
-	ndo_printf(NULL, NULL,
-	    "ndr hdr: %d.%d ptype=%d, %s frag (flags=0x%08x) len=%d",
-	    hdr->rpc_vers, hdr->rpc_vers_minor, hdr->ptype,
-	    fragtype, hdr->pfc_flags, hdr->frag_length);
-}
-
-int
-ndr_encode_pdu_hdr(ndr_xa_t *mxa)
-{
-	ndr_common_header_t	*hdr = &mxa->send_hdr.common_hdr;
-	ndr_stream_t		*nds = &mxa->send_nds;
-	int			ptype;
-	int			rc;
-
-	if (nds->m_op != NDR_M_OP_MARSHALL)
-		return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH);
-
-	ptype = hdr->ptype;
-	if (ptype == NDR_PTYPE_REQUEST &&
-	    (hdr->pfc_flags & NDR_PFC_OBJECT_UUID) != 0) {
-		ptype = NDR_PTYPE_REQUEST_WITH;	/* fake for sizing */
-	}
-
-	rc = ndr_encode_decode_common(nds, ptype, &TYPEINFO(ndr_hdr), hdr);
-
-	return (NDR_DRC_PTYPE_RPCHDR(rc));
-}
-
-/*
- * This is a hand-coded derivative of the automatically generated
- * (un)marshalling routine for bind_ack headers. bind_ack headers
- * have an interior conformant array, which is inconsistent with
- * IDL/NDR rules.
- */
-extern struct ndr_typeinfo ndt__uchar;
-extern struct ndr_typeinfo ndt__ushort;
-extern struct ndr_typeinfo ndt__ulong;
-
-int ndr__ndr_bind_ack_hdr(ndr_ref_t *encl_ref);
-ndr_typeinfo_t ndt__ndr_bind_ack_hdr = {
-    1,		/* NDR version */
-    3,		/* alignment */
-    NDR_F_STRUCT,	/* flags */
-    ndr__ndr_bind_ack_hdr,	/* ndr_func */
-    68,		/* pdu_size_fixed_part */
-    0,		/* pdu_size_variable_part */
-    68,		/* c_size_fixed_part */
-    0,		/* c_size_variable_part */
-};
-
-/*
- * [_no_reorder]
- */
-int
-ndr__ndr_bind_ack_hdr(ndr_ref_t *encl_ref)
-{
-	ndr_stream_t		*nds = encl_ref->stream;
-	struct ndr_bind_ack_hdr	*val = /*LINTED E_BAD_PTR_CAST_ALIGN*/
-	    (struct ndr_bind_ack_hdr *)encl_ref->datum;
-	ndr_ref_t		myref;
-	unsigned long		offset;
-
-	bzero(&myref, sizeof (myref));
-	myref.enclosing = encl_ref;
-	myref.stream = encl_ref->stream;
-	myref.packed_alignment = 0;
-
-	/* do all members in order */
-	NDR_MEMBER(_ndr_common_header, common_hdr, 0UL);
-	NDR_MEMBER(_ushort, max_xmit_frag, 16UL);
-	NDR_MEMBER(_ushort, max_recv_frag, 18UL);
-	NDR_MEMBER(_ulong, assoc_group_id, 20UL);
-
-	/* port any is the conformant culprit */
-	offset = 24UL;
-
-	switch (nds->m_op) {
-	case NDR_M_OP_MARSHALL:
-		val->sec_addr.length =
-		    strlen((char *)val->sec_addr.port_spec) + 1;
-		break;
-
-	case NDR_M_OP_UNMARSHALL:
-		break;
-
-	default:
-		NDR_SET_ERROR(encl_ref, NDR_ERR_M_OP_INVALID);
-		return (0);
-	}
-
-	NDR_MEMBER(_ushort, sec_addr.length, offset);
-	NDR_MEMBER_ARR_WITH_DIMENSION(_uchar, sec_addr.port_spec,
-	    offset+2UL, val->sec_addr.length);
-
-	offset += 2;
-	offset += val->sec_addr.length;
-	offset += NDR_ALIGN4(offset);
-
-	NDR_MEMBER(_ndr_p_result_list, p_result_list, offset);
-	return (1);
-}
-
-/*
- * Assume a single presentation context element in the result list.
- */
-unsigned
-ndr_bind_ack_hdr_size(ndr_xa_t *mxa)
-{
-	ndr_bind_ack_hdr_t *bahdr = &mxa->send_hdr.bind_ack_hdr;
-	unsigned	offset;
-	unsigned	length;
-
-	/* port any is the conformant culprit */
-	offset = 24UL;
-
-	length = strlen((char *)bahdr->sec_addr.port_spec) + 1;
-
-	offset += 2;
-	offset += length;
-	offset += NDR_ALIGN4(offset);
-	offset += sizeof (ndr_p_result_list_t);
-	return (offset);
-}
-
-/*
- * This is a hand-coded derivative of the automatically generated
- * (un)marshalling routine for alter_context_rsp headers.
- * Alter context response headers have an interior conformant array,
- * which is inconsistent with IDL/NDR rules.
- */
-int ndr__ndr_alter_context_rsp_hdr(ndr_ref_t *encl_ref);
-ndr_typeinfo_t ndt__ndr_alter_context_rsp_hdr = {
-    1,			/* NDR version */
-    3,			/* alignment */
-    NDR_F_STRUCT,	/* flags */
-    ndr__ndr_alter_context_rsp_hdr,	/* ndr_func */
-    56,			/* pdu_size_fixed_part */
-    0,			/* pdu_size_variable_part */
-    56,			/* c_size_fixed_part */
-    0,			/* c_size_variable_part */
-};
-
-/*
- * [_no_reorder]
- */
-int
-ndr__ndr_alter_context_rsp_hdr(ndr_ref_t *encl_ref)
-{
-	ndr_stream_t		*nds = encl_ref->stream;
-	ndr_alter_context_rsp_hdr_t *val = /*LINTED E_BAD_PTR_CAST_ALIGN*/
-	    (ndr_alter_context_rsp_hdr_t *)encl_ref->datum;
-	ndr_ref_t		myref;
-	unsigned long		offset;
-
-	bzero(&myref, sizeof (myref));
-	myref.enclosing = encl_ref;
-	myref.stream = encl_ref->stream;
-	myref.packed_alignment = 0;
-
-	/* do all members in order */
-	NDR_MEMBER(_ndr_common_header, common_hdr, 0UL);
-	NDR_MEMBER(_ushort, max_xmit_frag, 16UL);
-	NDR_MEMBER(_ushort, max_recv_frag, 18UL);
-	NDR_MEMBER(_ulong, assoc_group_id, 20UL);
-
-	offset = 24UL;	/* offset of sec_addr */
-
-	switch (nds->m_op) {
-	case NDR_M_OP_MARSHALL:
-		val->sec_addr.length = 0;
-		break;
-
-	case NDR_M_OP_UNMARSHALL:
-		break;
-
-	default:
-		NDR_SET_ERROR(encl_ref, NDR_ERR_M_OP_INVALID);
-		return (0);
-	}
-
-	NDR_MEMBER(_ushort, sec_addr.length, offset);
-	NDR_MEMBER_ARR_WITH_DIMENSION(_uchar, sec_addr.port_spec,
-	    offset+2UL, val->sec_addr.length);
-
-	offset += 2;	/* sizeof (sec_addr.length) */
-	offset += NDR_ALIGN4(offset);
-
-	NDR_MEMBER(_ndr_p_result_list, p_result_list, offset);
-	return (1);
-}
-
-/*
- * Assume a single presentation context element in the result list.
- */
-unsigned
-ndr_alter_context_rsp_hdr_size(void)
-{
-	unsigned	offset;
-
-	offset = 24UL;	/* offset of sec_addr */
-	offset += 2;	/* sizeof (sec_addr.length) */
-	offset += NDR_ALIGN4(offset);
-	offset += sizeof (ndr_p_result_list_t);
-	return (offset);
-}
--- /dev/null	Sun Mar 18 01:13:16 2018
+++ new/usr/src/lib/libmlrpc/common/ndr_marshal.c	Sun Mar 18 01:13:16 2018
@@ -0,0 +1,648 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+#include <assert.h>
+#include <strings.h>
+#include <sys/param.h>
+
+#include <libmlrpc.h>
+
+#ifdef _BIG_ENDIAN
+static const int ndr_native_byte_order = NDR_REPLAB_INTG_BIG_ENDIAN;
+#else
+static const int ndr_native_byte_order = NDR_REPLAB_INTG_LITTLE_ENDIAN;
+#endif
+
+static int ndr_decode_hdr_common(ndr_stream_t *, ndr_common_header_t *);
+static int ndr_decode_pac_hdr(ndr_stream_t *, ndr_pac_hdr_t *);
+
+static int
+ndr_encode_decode_common(ndr_stream_t *nds, unsigned opnum,
+    ndr_typeinfo_t *ti, void *datum)
+{
+	int rc;
+
+	/*
+	 * Perform the (un)marshalling
+	 */
+	if (ndo_operation(nds, ti, opnum, datum))
+		return (NDR_DRC_OK);
+
+	switch (nds->error) {
+	case NDR_ERR_MALLOC_FAILED:
+		rc = NDR_DRC_FAULT_OUT_OF_MEMORY;
+		break;
+
+	case NDR_ERR_SWITCH_VALUE_INVALID:
+		rc = NDR_DRC_FAULT_PARAM_0_INVALID;
+		break;
+
+	case NDR_ERR_UNDERFLOW:
+		rc = NDR_DRC_FAULT_RECEIVED_RUNT;
+		break;
+
+	case NDR_ERR_GROW_FAILED:
+		rc = NDR_DRC_FAULT_ENCODE_TOO_BIG;
+		break;
+
+	default:
+		if (nds->m_op == NDR_M_OP_MARSHALL)
+			rc = NDR_DRC_FAULT_ENCODE_FAILED;
+		else
+			rc = NDR_DRC_FAULT_DECODE_FAILED;
+		break;
+	}
+
+	return (rc);
+}
+
+ndr_buf_t *
+ndr_buf_init(ndr_typeinfo_t *ti)
+{
+	ndr_buf_t		*nbuf;
+
+	if ((nbuf = calloc(1, sizeof (ndr_buf_t))) == NULL)
+		return (NULL);
+
+	if ((nbuf->nb_heap = ndr_heap_create()) == NULL) {
+		free(nbuf);
+		return (NULL);
+	}
+
+	nbuf->nb_ti = ti;
+	nbuf->nb_magic = NDR_BUF_MAGIC;
+	return (nbuf);
+}
+
+void
+ndr_buf_fini(ndr_buf_t *nbuf)
+{
+	assert(nbuf->nb_magic == NDR_BUF_MAGIC);
+
+	nds_destruct(&nbuf->nb_nds);
+	ndr_heap_destroy(nbuf->nb_heap);
+	nbuf->nb_magic = 0;
+	free(nbuf);
+}
+
+/*
+ * Decode an NDR encoded buffer.  The buffer is expected to contain
+ * a single fragment packet with a valid PDU header followed by NDR
+ * encoded data.  The structure to which result points should be
+ * of the appropriate type to hold the decoded output.  For example:
+ *
+ *	pac_info_t info;
+ *
+ * 	if ((nbuf = ndr_buf_init(&TYPEINFO(ndr_pac)) != NULL) {
+ *		rc = ndr_decode_buf(nbuf, opnum, data, datalen, &info);
+ *		...
+ *		ndr_buf_fini(nbuf);
+ *	}
+ */
+int
+ndr_buf_decode(ndr_buf_t *nbuf, unsigned hdr_type, unsigned opnum,
+    const char *data, size_t datalen, void *result)
+{
+	ndr_common_header_t	hdr;
+	ndr_pac_hdr_t		pac_hdr;
+	unsigned		pdu_size_hint;
+	int			rc;
+
+	assert(nbuf->nb_magic == NDR_BUF_MAGIC);
+	assert(nbuf->nb_heap != NULL);
+	assert(nbuf->nb_ti != NULL);
+
+	if (datalen < NDR_PDU_SIZE_HINT_DEFAULT)
+		pdu_size_hint = NDR_PDU_SIZE_HINT_DEFAULT;
+	else
+		pdu_size_hint = datalen;
+
+	rc = nds_initialize(&nbuf->nb_nds, pdu_size_hint, NDR_MODE_BUF_DECODE,
+	    nbuf->nb_heap);
+	if (NDR_DRC_IS_FAULT(rc))
+		return (rc);
+
+	bcopy(data, nbuf->nb_nds.pdu_base_addr, datalen);
+
+	switch (hdr_type) {
+	case NDR_PTYPE_COMMON:
+		rc = ndr_decode_hdr_common(&nbuf->nb_nds, &hdr);
+		if (NDR_DRC_IS_FAULT(rc))
+			return (rc);
+
+		if (!NDR_IS_SINGLE_FRAG(hdr.pfc_flags))
+			return (NDR_DRC_FAULT_DECODE_FAILED);
+		break;
+
+	case NDR_PTYPE_PAC:
+		rc = ndr_decode_pac_hdr(&nbuf->nb_nds, &pac_hdr);
+		if (NDR_DRC_IS_FAULT(rc))
+			return (rc);
+
+		if (pac_hdr.common_hdr.hdrlen != sizeof (ndr_serialtype1_hdr_t))
+			return (NDR_DRC_FAULT_DECODE_FAILED);
+		break;
+
+	default:
+		return (NDR_ERR_UNIMPLEMENTED);
+	}
+
+	rc = ndr_encode_decode_common(&nbuf->nb_nds, opnum, nbuf->nb_ti,
+	    result);
+	return (rc);
+}
+
+/*
+ * Use the receive stream to unmarshall data (NDR_MODE_CALL_RECV).
+ */
+int
+ndr_decode_call(ndr_xa_t *mxa, void *params)
+{
+	ndr_stream_t	*nds = &mxa->recv_nds;
+	int		rc;
+
+	if (!NDR_MODE_MATCH(nds, NDR_MODE_CALL_RECV))
+		return (NDR_DRC_FAULT_MODE_MISMATCH);
+
+	rc = ndr_encode_decode_common(nds, mxa->opnum,
+	    mxa->binding->service->interface_ti, params);
+
+	return (rc + NDR_PTYPE_REQUEST);
+}
+
+/*
+ * Use the send stream to marshall data (NDR_MODE_RETURN_SEND).
+ */
+int
+ndr_encode_return(ndr_xa_t *mxa, void *params)
+{
+	ndr_stream_t	*nds = &mxa->send_nds;
+	int		rc;
+
+	if (!NDR_MODE_MATCH(nds, NDR_MODE_RETURN_SEND))
+		return (NDR_DRC_FAULT_MODE_MISMATCH);
+
+	rc = ndr_encode_decode_common(nds, mxa->opnum,
+	    mxa->binding->service->interface_ti, params);
+
+	return (rc + NDR_PTYPE_RESPONSE);
+}
+
+/*
+ * Use the send stream to marshall data (NDR_MODE_CALL_SEND).
+ */
+int
+ndr_encode_call(ndr_xa_t *mxa, void *params)
+{
+	ndr_stream_t	*nds = &mxa->send_nds;
+	int		rc;
+
+	if (!NDR_MODE_MATCH(nds, NDR_MODE_CALL_SEND))
+		return (NDR_DRC_FAULT_MODE_MISMATCH);
+
+	rc = ndr_encode_decode_common(nds, mxa->opnum,
+	    mxa->binding->service->interface_ti, params);
+
+	return (rc + NDR_PTYPE_REQUEST);
+}
+
+/*
+ * Use the receive stream to unmarshall data (NDR_MODE_RETURN_RECV).
+ */
+int
+ndr_decode_return(ndr_xa_t *mxa, void *params)
+{
+	ndr_stream_t	*nds = &mxa->recv_nds;
+	int		rc;
+
+	if (!NDR_MODE_MATCH(nds, NDR_MODE_RETURN_RECV))
+		return (NDR_DRC_FAULT_MODE_MISMATCH);
+
+	rc = ndr_encode_decode_common(nds, mxa->opnum,
+	    mxa->binding->service->interface_ti, params);
+
+	return (rc + NDR_PTYPE_RESPONSE);
+}
+
+int
+ndr_decode_pdu_hdr(ndr_xa_t *mxa)
+{
+	ndr_common_header_t	*hdr = &mxa->recv_hdr.common_hdr;
+	ndr_stream_t		*nds = &mxa->recv_nds;
+	int			rc;
+
+	rc = ndr_decode_hdr_common(nds, hdr);
+	if (NDR_DRC_IS_FAULT(rc))
+		return (rc);
+
+	/*
+	 * Verify the protocol version.
+	 */
+	if ((hdr->rpc_vers != 5) || (hdr->rpc_vers_minor != 0))
+		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
+
+	mxa->ptype = hdr->ptype;
+	return (NDR_DRC_OK);
+}
+
+static int
+ndr_decode_hdr_common(ndr_stream_t *nds, ndr_common_header_t *hdr)
+{
+	int			ptype;
+	int			rc;
+	int			charset;
+	int			byte_order;
+
+	if (nds->m_op != NDR_M_OP_UNMARSHALL)
+		return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH);
+
+	/*
+	 * All PDU headers are at least this big
+	 */
+	rc = NDS_GROW_PDU(nds, sizeof (ndr_common_header_t), 0);
+	if (!rc)
+		return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT);
+
+	/*
+	 * Peek at the first eight bytes to figure out what we're doing.
+	 */
+	rc = NDS_GET_PDU(nds, 0, 8, (char *)hdr, 0, 0);
+	if (!rc)
+		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
+
+	/*
+	 * Check for ASCII as the character set.  This is an ASCII
+	 * versus EBCDIC option and has nothing to do with Unicode.
+	 */
+	charset = hdr->packed_drep.intg_char_rep & NDR_REPLAB_CHAR_MASK;
+	if (charset != NDR_REPLAB_CHAR_ASCII)
+		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
+
+	/*
+	 * Set the byte swap flag if the PDU byte-order
+	 * is different from the local byte-order.
+	 */
+	byte_order = hdr->packed_drep.intg_char_rep & NDR_REPLAB_INTG_MASK;
+	nds->swap = (byte_order != ndr_native_byte_order) ? 1 : 0;
+
+	ptype = hdr->ptype;
+	if (ptype == NDR_PTYPE_REQUEST &&
+	    (hdr->pfc_flags & NDR_PFC_OBJECT_UUID) != 0) {
+		ptype = NDR_PTYPE_REQUEST_WITH;	/* fake for sizing */
+	}
+
+	rc = ndr_encode_decode_common(nds, ptype, &TYPEINFO(ndr_hdr), hdr);
+
+	return (NDR_DRC_PTYPE_RPCHDR(rc));
+}
+
+static int
+ndr_decode_pac_hdr(ndr_stream_t *nds, ndr_pac_hdr_t *hdr)
+{
+	int	rc;
+
+	if (nds->m_op != NDR_M_OP_UNMARSHALL)
+		return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH);
+
+	/*
+	 * All PDU headers are at least this big
+	 */
+	rc = NDS_GROW_PDU(nds, sizeof (ndr_pac_hdr_t), 0);
+	if (!rc)
+		return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT);
+
+	/*
+	 * Peek at the first eight bytes to figure out what we're doing.
+	 */
+	rc = NDS_GET_PDU(nds, 0, 8, (char *)hdr, 0, 0);
+	if (!rc)
+		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
+
+	/* Must be set to 1 to indicate type serialization version 1. */
+	if (hdr->common_hdr.version != 1)
+		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
+
+	/*
+	 * Set the byte swap flag if the PDU byte-order
+	 * is different from the local byte-order.
+	 */
+	nds->swap =
+	    (hdr->common_hdr.endianness != ndr_native_byte_order) ? 1 : 0;
+
+	rc = ndr_encode_decode_common(nds, NDR_PTYPE_PAC,
+	    &TYPEINFO(ndr_hdr), hdr);
+
+	return (NDR_DRC_PTYPE_RPCHDR(rc));
+}
+
+/*
+ * Decode an RPC fragment header.  Use ndr_decode_pdu_hdr() to process
+ * the first fragment header then this function to process additional
+ * fragment headers.
+ */
+void
+ndr_decode_frag_hdr(ndr_stream_t *nds, ndr_common_header_t *hdr)
+{
+	ndr_common_header_t *tmp;
+	uint8_t *pdu;
+	int byte_order;
+
+	pdu = (uint8_t *)nds->pdu_base_offset + nds->pdu_scan_offset;
+	bcopy(pdu, hdr, NDR_RSP_HDR_SIZE);
+
+	/*
+	 * Swap non-byte fields if the PDU byte-order
+	 * is different from the local byte-order.
+	 */
+	byte_order = hdr->packed_drep.intg_char_rep & NDR_REPLAB_INTG_MASK;
+
+	if (byte_order != ndr_native_byte_order) {
+		/*LINTED E_BAD_PTR_CAST_ALIGN*/
+		tmp = (ndr_common_header_t *)pdu;
+
+		nds_bswap(&tmp->frag_length, &hdr->frag_length,
+		    sizeof (WORD));
+		nds_bswap(&tmp->auth_length, &hdr->auth_length,
+		    sizeof (WORD));
+		nds_bswap(&tmp->call_id, &hdr->call_id, sizeof (DWORD));
+	}
+}
+
+/*
+ * Remove an RPC fragment header from the received data stream.
+ *
+ * NDR stream on entry:
+ *
+ *                |<--- frag --->|
+ * +-----+--------+-----+--------+-----+---------+-----+
+ * | hdr |  data  | hdr |  data  | hdr |  data   | ... |
+ * +-----+--------+-----+--------+-----+---------+-----+
+ *                 <----
+ *
+ * NDR stream on return:
+ *
+ * +-----+----------------+-----+---------+-----+
+ * | hdr |       data     | hdr |  data   | ... |
+ * +-----+----------------+-----+---------+-----+
+ */
+void
+ndr_remove_frag_hdr(ndr_stream_t *nds)
+{
+	char	*hdr;
+	char	*data;
+	int	nbytes;
+
+	hdr = (char *)nds->pdu_base_offset + nds->pdu_scan_offset;
+	data = hdr + NDR_RSP_HDR_SIZE;
+	nbytes = nds->pdu_size - nds->pdu_scan_offset - NDR_RSP_HDR_SIZE;
+
+	bcopy(data, hdr, nbytes);
+	nds->pdu_size -= NDR_RSP_HDR_SIZE;
+}
+
+void
+ndr_show_hdr(ndr_common_header_t *hdr)
+{
+	char	*fragtype;
+
+	if (hdr == NULL) {
+		ndo_printf(NULL, NULL, "ndr hdr: <null>");
+		return;
+	}
+
+	if (NDR_IS_SINGLE_FRAG(hdr->pfc_flags))
+		fragtype = "single";
+	else if (NDR_IS_FIRST_FRAG(hdr->pfc_flags))
+		fragtype = "first";
+	else if (NDR_IS_LAST_FRAG(hdr->pfc_flags))
+		fragtype = "last";
+	else
+		fragtype = "intermediate";
+
+	ndo_printf(NULL, NULL,
+	    "ndr hdr: %d.%d ptype=%d, %s frag (flags=0x%08x) len=%d",
+	    hdr->rpc_vers, hdr->rpc_vers_minor, hdr->ptype,
+	    fragtype, hdr->pfc_flags, hdr->frag_length);
+}
+
+int
+ndr_encode_pdu_hdr(ndr_xa_t *mxa)
+{
+	ndr_common_header_t	*hdr = &mxa->send_hdr.common_hdr;
+	ndr_stream_t		*nds = &mxa->send_nds;
+	int			ptype;
+	int			rc;
+
+	if (nds->m_op != NDR_M_OP_MARSHALL)
+		return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH);
+
+	ptype = hdr->ptype;
+	if (ptype == NDR_PTYPE_REQUEST &&
+	    (hdr->pfc_flags & NDR_PFC_OBJECT_UUID) != 0) {
+		ptype = NDR_PTYPE_REQUEST_WITH;	/* fake for sizing */
+	}
+
+	rc = ndr_encode_decode_common(nds, ptype, &TYPEINFO(ndr_hdr), hdr);
+
+	return (NDR_DRC_PTYPE_RPCHDR(rc));
+}
+
+/*
+ * This is a hand-coded derivative of the automatically generated
+ * (un)marshalling routine for bind_ack headers. bind_ack headers
+ * have an interior conformant array, which is inconsistent with
+ * IDL/NDR rules.
+ */
+extern struct ndr_typeinfo ndt__uchar;
+extern struct ndr_typeinfo ndt__ushort;
+extern struct ndr_typeinfo ndt__ulong;
+
+int ndr__ndr_bind_ack_hdr(ndr_ref_t *encl_ref);
+ndr_typeinfo_t ndt__ndr_bind_ack_hdr = {
+    1,		/* NDR version */
+    3,		/* alignment */
+    NDR_F_STRUCT,	/* flags */
+    ndr__ndr_bind_ack_hdr,	/* ndr_func */
+    68,		/* pdu_size_fixed_part */
+    0,		/* pdu_size_variable_part */
+    68,		/* c_size_fixed_part */
+    0,		/* c_size_variable_part */
+};
+
+/*
+ * [_no_reorder]
+ */
+int
+ndr__ndr_bind_ack_hdr(ndr_ref_t *encl_ref)
+{
+	ndr_stream_t		*nds = encl_ref->stream;
+	struct ndr_bind_ack_hdr	*val = /*LINTED E_BAD_PTR_CAST_ALIGN*/
+	    (struct ndr_bind_ack_hdr *)encl_ref->datum;
+	ndr_ref_t		myref;
+	unsigned long		offset;
+
+	bzero(&myref, sizeof (myref));
+	myref.enclosing = encl_ref;
+	myref.stream = encl_ref->stream;
+	myref.packed_alignment = 0;
+
+	/* do all members in order */
+	NDR_MEMBER(_ndr_common_header, common_hdr, 0UL);
+	NDR_MEMBER(_ushort, max_xmit_frag, 16UL);
+	NDR_MEMBER(_ushort, max_recv_frag, 18UL);
+	NDR_MEMBER(_ulong, assoc_group_id, 20UL);
+
+	/* port any is the conformant culprit */
+	offset = 24UL;
+
+	switch (nds->m_op) {
+	case NDR_M_OP_MARSHALL:
+		val->sec_addr.length =
+		    strlen((char *)val->sec_addr.port_spec) + 1;
+		break;
+
+	case NDR_M_OP_UNMARSHALL:
+		break;
+
+	default:
+		NDR_SET_ERROR(encl_ref, NDR_ERR_M_OP_INVALID);
+		return (0);
+	}
+
+	NDR_MEMBER(_ushort, sec_addr.length, offset);
+	NDR_MEMBER_ARR_WITH_DIMENSION(_uchar, sec_addr.port_spec,
+	    offset+2UL, val->sec_addr.length);
+
+	offset += 2;
+	offset += val->sec_addr.length;
+	offset += NDR_ALIGN4(offset);
+
+	NDR_MEMBER(_ndr_p_result_list, p_result_list, offset);
+	return (1);
+}
+
+/*
+ * Assume a single presentation context element in the result list.
+ */
+unsigned
+ndr_bind_ack_hdr_size(ndr_xa_t *mxa)
+{
+	ndr_bind_ack_hdr_t *bahdr = &mxa->send_hdr.bind_ack_hdr;
+	unsigned	offset;
+	unsigned	length;
+
+	/* port any is the conformant culprit */
+	offset = 24UL;
+
+	length = strlen((char *)bahdr->sec_addr.port_spec) + 1;
+
+	offset += 2;
+	offset += length;
+	offset += NDR_ALIGN4(offset);
+	offset += sizeof (ndr_p_result_list_t);
+	return (offset);
+}
+
+/*
+ * This is a hand-coded derivative of the automatically generated
+ * (un)marshalling routine for alter_context_rsp headers.
+ * Alter context response headers have an interior conformant array,
+ * which is inconsistent with IDL/NDR rules.
+ */
+int ndr__ndr_alter_context_rsp_hdr(ndr_ref_t *encl_ref);
+ndr_typeinfo_t ndt__ndr_alter_context_rsp_hdr = {
+    1,			/* NDR version */
+    3,			/* alignment */
+    NDR_F_STRUCT,	/* flags */
+    ndr__ndr_alter_context_rsp_hdr,	/* ndr_func */
+    56,			/* pdu_size_fixed_part */
+    0,			/* pdu_size_variable_part */
+    56,			/* c_size_fixed_part */
+    0,			/* c_size_variable_part */
+};
+
+/*
+ * [_no_reorder]
+ */
+int
+ndr__ndr_alter_context_rsp_hdr(ndr_ref_t *encl_ref)
+{
+	ndr_stream_t		*nds = encl_ref->stream;
+	ndr_alter_context_rsp_hdr_t *val = /*LINTED E_BAD_PTR_CAST_ALIGN*/
+	    (ndr_alter_context_rsp_hdr_t *)encl_ref->datum;
+	ndr_ref_t		myref;
+	unsigned long		offset;
+
+	bzero(&myref, sizeof (myref));
+	myref.enclosing = encl_ref;
+	myref.stream = encl_ref->stream;
+	myref.packed_alignment = 0;
+
+	/* do all members in order */
+	NDR_MEMBER(_ndr_common_header, common_hdr, 0UL);
+	NDR_MEMBER(_ushort, max_xmit_frag, 16UL);
+	NDR_MEMBER(_ushort, max_recv_frag, 18UL);
+	NDR_MEMBER(_ulong, assoc_group_id, 20UL);
+
+	offset = 24UL;	/* offset of sec_addr */
+
+	switch (nds->m_op) {
+	case NDR_M_OP_MARSHALL:
+		val->sec_addr.length = 0;
+		break;
+
+	case NDR_M_OP_UNMARSHALL:
+		break;
+
+	default:
+		NDR_SET_ERROR(encl_ref, NDR_ERR_M_OP_INVALID);
+		return (0);
+	}
+
+	NDR_MEMBER(_ushort, sec_addr.length, offset);
+	NDR_MEMBER_ARR_WITH_DIMENSION(_uchar, sec_addr.port_spec,
+	    offset+2UL, val->sec_addr.length);
+
+	offset += 2;	/* sizeof (sec_addr.length) */
+	offset += NDR_ALIGN4(offset);
+
+	NDR_MEMBER(_ndr_p_result_list, p_result_list, offset);
+	return (1);
+}
+
+/*
+ * Assume a single presentation context element in the result list.
+ */
+unsigned
+ndr_alter_context_rsp_hdr_size(void)
+{
+	unsigned	offset;
+
+	offset = 24UL;	/* offset of sec_addr */
+	offset += 2;	/* sizeof (sec_addr.length) */
+	offset += NDR_ALIGN4(offset);
+	offset += sizeof (ndr_p_result_list_t);
+	return (offset);
+}
--- old/usr/src/lib/smbsrv/libmlrpc/common/ndr_ops.c	Sun Mar 18 01:13:16 2018
+++ /dev/null	Sun Mar 18 01:13:16 2018
@@ -1,557 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
- */
-
-/*
- * Server-side NDR stream (PDU) operations. Stream operations should
- * return TRUE (non-zero) on success or FALSE (zero or a null pointer)
- * on failure. When an operation returns FALSE, including ndo_malloc()
- * returning NULL, it should set the nds->error to indicate what went
- * wrong.
- *
- * When available, the relevant ndr reference is passed to the
- * operation but keep in mind that it may be a null pointer.
- *
- * Functions ndo_get_pdu(), ndo_put_pdu(), and ndo_pad_pdu()
- * must never grow the PDU data. A request for out-of-bounds data is
- * an error. The swap_bytes flag is 1 if NDR knows that the byte-
- * order in the PDU is different from the local system.
- */
-
-#include <sys/types.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <string.h>
-#include <assert.h>
-
-#include <smbsrv/libsmb.h>
-#include <smbsrv/libmlrpc.h>
-
-#define	NDOBUFSZ		128
-
-#define	NDR_PDU_BLOCK_SIZE	(4*1024)
-#define	NDR_PDU_BLOCK_MASK	(NDR_PDU_BLOCK_SIZE - 1)
-#define	NDR_PDU_ALIGN(N) \
-	(((N) + NDR_PDU_BLOCK_SIZE) & ~NDR_PDU_BLOCK_MASK)
-#define	NDR_PDU_MAX_SIZE		(64*1024*1024)
-
-static char *ndo_malloc(ndr_stream_t *, unsigned, ndr_ref_t *);
-static int ndo_free(ndr_stream_t *, char *, ndr_ref_t *);
-static int ndo_grow_pdu(ndr_stream_t *, unsigned long, ndr_ref_t *);
-static int ndo_pad_pdu(ndr_stream_t *, unsigned long, unsigned long,
-    ndr_ref_t *);
-static int ndo_get_pdu(ndr_stream_t *, unsigned long, unsigned long,
-    char *, int, ndr_ref_t *);
-static int ndo_put_pdu(ndr_stream_t *, unsigned long, unsigned long,
-    char *, int, ndr_ref_t *);
-static void ndo_tattle(ndr_stream_t *, char *, ndr_ref_t *);
-static void ndo_tattle_error(ndr_stream_t *, ndr_ref_t *);
-static int ndo_reset(ndr_stream_t *);
-static void ndo_destruct(ndr_stream_t *);
-static void ndo_hexfmt(uint8_t *, int, int, char *, int);
-
-/*
- * The ndr stream operations table.
- */
-static ndr_stream_ops_t nds_ops = {
-    ndo_malloc,
-    ndo_free,
-    ndo_grow_pdu,
-    ndo_pad_pdu,
-    ndo_get_pdu,
-    ndo_put_pdu,
-    ndo_tattle,
-    ndo_tattle_error,
-    ndo_reset,
-    ndo_destruct
-};
-
-/*
- * nds_bswap
- *
- * Copies len bytes from src to dst such that dst contains the bytes
- * from src in reverse order.
- *
- * We expect to be dealing with bytes, words, dwords etc. So the
- * length must be non-zero and a power of 2.
- */
-void
-nds_bswap(void *srcbuf, void *dstbuf, size_t len)
-{
-	uint8_t *src = (uint8_t *)srcbuf;
-	uint8_t *dst = (uint8_t *)dstbuf;
-
-	if ((len != 0) && ((len & (len - 1)) == 0)) {
-		src += len;
-
-		while (len--)
-			*dst++ = *(--src);
-	}
-}
-
-/*
- * nds_initialize
- *
- * Initialize a stream. Sets up the PDU parameters and assigns the stream
- * operations and the reference to the heap. An external heap is provided
- * to the stream, rather than each stream creating its own heap.
- */
-int
-nds_initialize(ndr_stream_t *nds, unsigned pdu_size_hint,
-    int composite_op, ndr_heap_t *heap)
-{
-	unsigned size;
-
-	assert(nds);
-	assert(heap);
-
-	bzero(nds, sizeof (*nds));
-	nds->ndo = &nds_ops;
-	nds->heap = (struct ndr_heap *)heap;
-
-	if (pdu_size_hint > NDR_PDU_MAX_SIZE) {
-		nds->error = NDR_ERR_BOUNDS_CHECK;
-		nds->error_ref = __LINE__;
-		NDS_TATTLE_ERROR(nds, NULL, NULL);
-		return (NDR_DRC_FAULT_RESOURCE_1);
-	}
-
-	size = (pdu_size_hint == 0) ? NDR_PDU_BLOCK_SIZE : pdu_size_hint;
-
-	if ((nds->pdu_base_addr = malloc(size)) == NULL) {
-		nds->error = NDR_ERR_MALLOC_FAILED;
-		nds->error_ref = __LINE__;
-		NDS_TATTLE_ERROR(nds, NULL, NULL);
-		return (NDR_DRC_FAULT_OUT_OF_MEMORY);
-	}
-
-	nds->pdu_max_size = size;
-	nds->pdu_size = 0;
-	nds->pdu_base_offset = (unsigned long)nds->pdu_base_addr;
-
-	nds->m_op = NDR_MODE_TO_M_OP(composite_op);
-	nds->dir  = NDR_MODE_TO_DIR(composite_op);
-
-	nds->outer_queue_tailp = &nds->outer_queue_head;
-	return (0);
-}
-
-/*
- * nds_destruct
- *
- * Destroy a stream. This is an external interface to provide access to
- * the stream's destruct operation.
- */
-void
-nds_destruct(ndr_stream_t *nds)
-{
-	if ((nds == NULL) || (nds->ndo == NULL))
-		return;
-
-	NDS_DESTRUCT(nds);
-}
-
-/*
- * Print NDR stream state.
- */
-void
-nds_show_state(ndr_stream_t *nds)
-{
-	if (nds == NULL) {
-		ndo_printf(NULL, NULL, "nds: <null");
-		return;
-	}
-
-	ndo_printf(NULL, NULL, "nds: base=0x%x, size=%d, max=%d, scan=%d",
-	    nds->pdu_base_offset, nds->pdu_size, nds->pdu_max_size,
-	    nds->pdu_scan_offset);
-}
-
-/*
- * ndo_malloc
- *
- * Allocate memory from the stream heap.
- */
-/*ARGSUSED*/
-static char *
-ndo_malloc(ndr_stream_t *nds, unsigned len, ndr_ref_t *ref)
-{
-	return (ndr_heap_malloc((ndr_heap_t *)nds->heap, len));
-}
-
-/*
- * ndo_free
- *
- * Always succeeds: cannot free individual stream allocations.
- */
-/*ARGSUSED*/
-static int
-ndo_free(ndr_stream_t *nds, char *p, ndr_ref_t *ref)
-{
-	return (1);
-}
-
-/*
- * ndo_grow_pdu
- *
- * This is the only place that should change the size of the PDU. If the
- * desired offset is beyond the current PDU size, we realloc the PDU
- * buffer to accommodate the request. For efficiency, the PDU is always
- * extended to a NDR_PDU_BLOCK_SIZE boundary. Requests to grow the PDU
- * beyond NDR_PDU_MAX_SIZE are rejected.
- *
- * Returns 1 to indicate success. Otherwise 0 to indicate failure.
- */
-static int
-ndo_grow_pdu(ndr_stream_t *nds, unsigned long want_end_offset, ndr_ref_t *ref)
-{
-	unsigned char *pdu_addr;
-	unsigned pdu_max_size;
-
-	ndo_printf(nds, ref, "grow %d", want_end_offset);
-
-	pdu_max_size = nds->pdu_max_size;
-
-	if (want_end_offset > pdu_max_size) {
-		pdu_max_size = NDR_PDU_ALIGN(want_end_offset);
-
-		if (pdu_max_size >= NDR_PDU_MAX_SIZE)
-			return (0);
-
-		pdu_addr = realloc(nds->pdu_base_addr, pdu_max_size);
-		if (pdu_addr == 0)
-			return (0);
-
-		nds->pdu_max_size = pdu_max_size;
-		nds->pdu_base_addr = pdu_addr;
-		nds->pdu_base_offset = (unsigned long)pdu_addr;
-	}
-
-	nds->pdu_size = want_end_offset;
-	return (1);
-}
-
-static int
-ndo_pad_pdu(ndr_stream_t *nds, unsigned long pdu_offset,
-    unsigned long n_bytes, ndr_ref_t *ref)
-{
-	unsigned char *data;
-
-	data = (unsigned char *)nds->pdu_base_offset;
-	data += pdu_offset;
-
-	ndo_printf(nds, ref, "pad %d@%-3d", n_bytes, pdu_offset);
-
-	bzero(data, n_bytes);
-	return (1);
-}
-
-/*
- * ndo_get_pdu
- *
- * The swap flag is 1 if NDR knows that the byte-order in the PDU
- * is different from the local system.
- *
- * Returns 1 on success or 0 to indicate failure.
- */
-static int
-ndo_get_pdu(ndr_stream_t *nds, unsigned long pdu_offset,
-    unsigned long n_bytes, char *buf, int swap_bytes, ndr_ref_t *ref)
-{
-	unsigned char *data;
-	char hexbuf[NDOBUFSZ];
-
-	data = (unsigned char *)nds->pdu_base_offset;
-	data += pdu_offset;
-
-	ndo_hexfmt(data, n_bytes, swap_bytes, hexbuf, NDOBUFSZ);
-
-	ndo_printf(nds, ref, "get %d@%-3d = %s",
-	    n_bytes, pdu_offset, hexbuf);
-
-	if (!swap_bytes)
-		bcopy(data, buf, n_bytes);
-	else
-		nds_bswap(data, (unsigned char *)buf, n_bytes);
-
-	return (1);
-}
-
-/*
- * ndo_put_pdu
- *
- * This is a receiver makes right protocol. So we do not need
- * to be concerned about the byte-order of an outgoing PDU.
- */
-/*ARGSUSED*/
-static int
-ndo_put_pdu(ndr_stream_t *nds, unsigned long pdu_offset,
-    unsigned long n_bytes, char *buf, int swap_bytes, ndr_ref_t *ref)
-{
-	unsigned char *data;
-	char hexbuf[NDOBUFSZ];
-
-	data = (unsigned char *)nds->pdu_base_offset;
-	data += pdu_offset;
-
-	ndo_hexfmt((uint8_t *)buf, n_bytes, 0, hexbuf, NDOBUFSZ);
-
-	ndo_printf(nds, ref, "put %d@%-3d = %s",
-	    n_bytes, pdu_offset, hexbuf);
-
-	bcopy(buf, data, n_bytes);
-	return (1);
-}
-
-static void
-ndo_tattle(ndr_stream_t *nds, char *what, ndr_ref_t *ref)
-{
-	ndo_printf(nds, ref, what);
-}
-
-static void
-ndo_tattle_error(ndr_stream_t *nds, ndr_ref_t *ref)
-{
-	unsigned char *data;
-	char hexbuf[NDOBUFSZ];
-
-	if (nds->pdu_base_addr != NULL) {
-		data = (unsigned char *)nds->pdu_base_offset;
-		if (ref)
-			data += ref->pdu_offset;
-		else
-			data += nds->pdu_scan_offset;
-
-		ndo_hexfmt(data, 16, 0, hexbuf, NDOBUFSZ);
-	} else {
-		bzero(hexbuf, NDOBUFSZ);
-	}
-
-	ndo_printf(nds, ref, "ERROR=%d REF=%d OFFSET=%d SIZE=%d/%d",
-	    nds->error, nds->error_ref, nds->pdu_scan_offset,
-	    nds->pdu_size, nds->pdu_max_size);
-	ndo_printf(nds, ref, "      %s", hexbuf);
-}
-
-/*
- * ndo_reset
- *
- * Reset a stream: zap the outer_queue. We don't need to tamper
- * with the stream heap: it's handled externally to the stream.
- */
-static int
-ndo_reset(ndr_stream_t *nds)
-{
-	ndo_printf(nds, 0, "reset");
-
-	nds->pdu_size = 0;
-	nds->pdu_scan_offset = 0;
-	nds->outer_queue_head = 0;
-	nds->outer_current = 0;
-	nds->outer_queue_tailp = &nds->outer_queue_head;
-
-	return (1);
-}
-
-/*
- * ndo_destruct
- *
- * Destruct a stream: zap the outer_queue.
- * Note: heap management (creation/destruction) is external to the stream.
- */
-static void
-ndo_destruct(ndr_stream_t *nds)
-{
-
-	ndo_printf(nds, 0, "destruct");
-
-	if (nds == NULL)
-		return;
-
-	if (nds->pdu_base_addr != NULL) {
-		free(nds->pdu_base_addr);
-		nds->pdu_base_addr = NULL;
-		nds->pdu_base_offset = 0;
-	}
-
-	nds->outer_queue_head = 0;
-	nds->outer_current = 0;
-	nds->outer_queue_tailp = &nds->outer_queue_head;
-}
-
-/*
- * Printf style formatting for NDR operations.
- */
-void
-ndo_printf(ndr_stream_t *nds, ndr_ref_t *ref, const char *fmt, ...)
-{
-	va_list ap;
-	char buf[NDOBUFSZ];
-
-	va_start(ap, fmt);
-	(void) vsnprintf(buf, NDOBUFSZ, fmt, ap);
-	va_end(ap);
-
-	if (nds)
-		ndo_fmt(nds, ref, buf);
-	else
-		ndo_trace(buf);
-}
-
-/*
- * Main output formatter for NDR operations.
- *
- *	UI 03 ... rpc_vers           get 1@0   =    5 {05}
- *	UI 03 ... rpc_vers_minor     get 1@1   =    0 {00}
- *
- *	U       Marshalling flag (M=marshal, U=unmarshal)
- *	I       Direction flag (I=in, O=out)
- *	...     Field name
- *	get     PDU operation (get or put)
- *	1@0	Bytes @ offset (i.e. 1 byte at offset 0)
- *	{05}    Value
- */
-void
-ndo_fmt(ndr_stream_t *nds, ndr_ref_t *ref, char *note)
-{
-	ndr_ref_t	*p;
-	int		indent;
-	char		ref_name[NDOBUFSZ];
-	char		buf[NDOBUFSZ];
-	int		m_op_c = '?', dir_c = '?';
-
-	switch (nds->m_op) {
-	case 0:				m_op_c = '-';	break;
-	case NDR_M_OP_MARSHALL:		m_op_c = 'M';	break;
-	case NDR_M_OP_UNMARSHALL:	m_op_c = 'U';	break;
-	default:			m_op_c = '?';	break;
-	}
-
-	switch (nds->dir) {
-	case 0:				dir_c = '-';	break;
-	case NDR_DIR_IN:		dir_c = 'I';	break;
-	case NDR_DIR_OUT:		dir_c = 'O';	break;
-	default:			dir_c = '?';	break;
-	}
-
-	for (indent = 0, p = ref; p; p = p->enclosing)
-		indent++;
-
-	if (ref && ref->name) {
-		if (*ref->name == '[' && ref->enclosing) {
-			indent--;
-			(void) snprintf(ref_name, NDOBUFSZ, "%s%s",
-			    ref->enclosing->name, ref->name);
-		} else {
-			(void) strlcpy(ref_name, ref->name, NDOBUFSZ);
-		}
-	} else {
-		(void) strlcpy(ref_name, "----", NDOBUFSZ);
-	}
-
-	(void) snprintf(buf, NDOBUFSZ, "%c%c %-.*s %-*s  %s",
-	    m_op_c, dir_c, indent,
-	    "....+....+....+....+....+....",
-	    20 - indent, ref_name, note);
-
-	ndo_trace(buf);
-}
-
-/*ARGSUSED*/
-void
-ndo_trace(const char *s)
-{
-	/*
-	 * Temporary fbt for dtrace until user space sdt enabled.
-	 */
-}
-
-/*
- * Format data as hex bytes (limit is 10 bytes):
- *
- *	1188689424 {10 f6 d9 46}
- *
- * If the input data is greater than 10 bytes, an ellipsis will
- * be inserted before the closing brace.
- */
-static void
-ndo_hexfmt(uint8_t *data, int size, int swap_bytes, char *buf, int len)
-{
-	char *p = buf;
-	int interp = 1;
-	uint32_t c;
-	int n;
-	int i;
-
-	n = (size > 10) ? 10 : size;
-	if (n > len-1)
-		n = len-1;
-
-	switch (size) {
-	case 1:
-		c = *(uint8_t *)data;
-		break;
-	case 2:
-		if (swap_bytes == 0) /*LINTED E_BAD_PTR_CAST_ALIGN*/
-			c = *(uint16_t *)data;
-		else
-			c = (data[0] << 8) | data[1];
-		break;
-	case 4:
-		if (swap_bytes == 0) { /*LINTED E_BAD_PTR_CAST_ALIGN*/
-			c = *(uint32_t *)data;
-		} else {
-			c = (data[0] << 24) | (data[1] << 16)
-			    | (data[2] << 8) | data[3];
-		}
-		break;
-	default:
-		c = 0;
-		interp = 0;
-		break;
-	}
-
-	if (interp)
-		p += sprintf(p, "%4u {", c);
-	else
-		p += sprintf(p, " {");
-
-	p += sprintf(p, "%02x", data[0]);
-	for (i = 1; i < n; i++)
-		p += sprintf(p, " %02x", data[i]);
-	if (size > 10)
-		p += sprintf(p, " ...}");
-	else
-		p += sprintf(p, "}");
-
-	/*
-	 * Show c if it's a printable character or wide-char.
-	 */
-	if (size < 4 && isprint((uint8_t)c))
-		(void) sprintf(p, " %c", (uint8_t)c);
-}
--- /dev/null	Sun Mar 18 01:13:16 2018
+++ new/usr/src/lib/libmlrpc/common/ndr_ops.c	Sun Mar 18 01:13:16 2018
@@ -0,0 +1,556 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+/*
+ * Server-side NDR stream (PDU) operations. Stream operations should
+ * return TRUE (non-zero) on success or FALSE (zero or a null pointer)
+ * on failure. When an operation returns FALSE, including ndo_malloc()
+ * returning NULL, it should set the nds->error to indicate what went
+ * wrong.
+ *
+ * When available, the relevant ndr reference is passed to the
+ * operation but keep in mind that it may be a null pointer.
+ *
+ * Functions ndo_get_pdu(), ndo_put_pdu(), and ndo_pad_pdu()
+ * must never grow the PDU data. A request for out-of-bounds data is
+ * an error. The swap_bytes flag is 1 if NDR knows that the byte-
+ * order in the PDU is different from the local system.
+ */
+
+#include <sys/types.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <string.h>
+#include <assert.h>
+
+#include <libmlrpc.h>
+
+#define	NDOBUFSZ		128
+
+#define	NDR_PDU_BLOCK_SIZE	(4*1024)
+#define	NDR_PDU_BLOCK_MASK	(NDR_PDU_BLOCK_SIZE - 1)
+#define	NDR_PDU_ALIGN(N) \
+	(((N) + NDR_PDU_BLOCK_SIZE) & ~NDR_PDU_BLOCK_MASK)
+#define	NDR_PDU_MAX_SIZE		(64*1024*1024)
+
+static char *ndo_malloc(ndr_stream_t *, unsigned, ndr_ref_t *);
+static int ndo_free(ndr_stream_t *, char *, ndr_ref_t *);
+static int ndo_grow_pdu(ndr_stream_t *, unsigned long, ndr_ref_t *);
+static int ndo_pad_pdu(ndr_stream_t *, unsigned long, unsigned long,
+    ndr_ref_t *);
+static int ndo_get_pdu(ndr_stream_t *, unsigned long, unsigned long,
+    char *, int, ndr_ref_t *);
+static int ndo_put_pdu(ndr_stream_t *, unsigned long, unsigned long,
+    char *, int, ndr_ref_t *);
+static void ndo_tattle(ndr_stream_t *, char *, ndr_ref_t *);
+static void ndo_tattle_error(ndr_stream_t *, ndr_ref_t *);
+static int ndo_reset(ndr_stream_t *);
+static void ndo_destruct(ndr_stream_t *);
+static void ndo_hexfmt(uint8_t *, int, int, char *, int);
+
+/*
+ * The ndr stream operations table.
+ */
+static ndr_stream_ops_t nds_ops = {
+    ndo_malloc,
+    ndo_free,
+    ndo_grow_pdu,
+    ndo_pad_pdu,
+    ndo_get_pdu,
+    ndo_put_pdu,
+    ndo_tattle,
+    ndo_tattle_error,
+    ndo_reset,
+    ndo_destruct
+};
+
+/*
+ * nds_bswap
+ *
+ * Copies len bytes from src to dst such that dst contains the bytes
+ * from src in reverse order.
+ *
+ * We expect to be dealing with bytes, words, dwords etc. So the
+ * length must be non-zero and a power of 2.
+ */
+void
+nds_bswap(void *srcbuf, void *dstbuf, size_t len)
+{
+	uint8_t *src = (uint8_t *)srcbuf;
+	uint8_t *dst = (uint8_t *)dstbuf;
+
+	if ((len != 0) && ((len & (len - 1)) == 0)) {
+		src += len;
+
+		while (len--)
+			*dst++ = *(--src);
+	}
+}
+
+/*
+ * nds_initialize
+ *
+ * Initialize a stream. Sets up the PDU parameters and assigns the stream
+ * operations and the reference to the heap. An external heap is provided
+ * to the stream, rather than each stream creating its own heap.
+ */
+int
+nds_initialize(ndr_stream_t *nds, unsigned pdu_size_hint,
+    int composite_op, ndr_heap_t *heap)
+{
+	unsigned size;
+
+	assert(nds);
+	assert(heap);
+
+	bzero(nds, sizeof (*nds));
+	nds->ndo = &nds_ops;
+	nds->heap = (struct ndr_heap *)heap;
+
+	if (pdu_size_hint > NDR_PDU_MAX_SIZE) {
+		nds->error = NDR_ERR_BOUNDS_CHECK;
+		nds->error_ref = __LINE__;
+		NDS_TATTLE_ERROR(nds, NULL, NULL);
+		return (NDR_DRC_FAULT_RESOURCE_1);
+	}
+
+	size = (pdu_size_hint == 0) ? NDR_PDU_BLOCK_SIZE : pdu_size_hint;
+
+	if ((nds->pdu_base_addr = malloc(size)) == NULL) {
+		nds->error = NDR_ERR_MALLOC_FAILED;
+		nds->error_ref = __LINE__;
+		NDS_TATTLE_ERROR(nds, NULL, NULL);
+		return (NDR_DRC_FAULT_OUT_OF_MEMORY);
+	}
+
+	nds->pdu_max_size = size;
+	nds->pdu_size = 0;
+	nds->pdu_base_offset = (unsigned long)nds->pdu_base_addr;
+
+	nds->m_op = NDR_MODE_TO_M_OP(composite_op);
+	nds->dir  = NDR_MODE_TO_DIR(composite_op);
+
+	nds->outer_queue_tailp = &nds->outer_queue_head;
+	return (0);
+}
+
+/*
+ * nds_destruct
+ *
+ * Destroy a stream. This is an external interface to provide access to
+ * the stream's destruct operation.
+ */
+void
+nds_destruct(ndr_stream_t *nds)
+{
+	if ((nds == NULL) || (nds->ndo == NULL))
+		return;
+
+	NDS_DESTRUCT(nds);
+}
+
+/*
+ * Print NDR stream state.
+ */
+void
+nds_show_state(ndr_stream_t *nds)
+{
+	if (nds == NULL) {
+		ndo_printf(NULL, NULL, "nds: <null");
+		return;
+	}
+
+	ndo_printf(NULL, NULL, "nds: base=0x%x, size=%d, max=%d, scan=%d",
+	    nds->pdu_base_offset, nds->pdu_size, nds->pdu_max_size,
+	    nds->pdu_scan_offset);
+}
+
+/*
+ * ndo_malloc
+ *
+ * Allocate memory from the stream heap.
+ */
+/*ARGSUSED*/
+static char *
+ndo_malloc(ndr_stream_t *nds, unsigned len, ndr_ref_t *ref)
+{
+	return (ndr_heap_malloc((ndr_heap_t *)nds->heap, len));
+}
+
+/*
+ * ndo_free
+ *
+ * Always succeeds: cannot free individual stream allocations.
+ */
+/*ARGSUSED*/
+static int
+ndo_free(ndr_stream_t *nds, char *p, ndr_ref_t *ref)
+{
+	return (1);
+}
+
+/*
+ * ndo_grow_pdu
+ *
+ * This is the only place that should change the size of the PDU. If the
+ * desired offset is beyond the current PDU size, we realloc the PDU
+ * buffer to accommodate the request. For efficiency, the PDU is always
+ * extended to a NDR_PDU_BLOCK_SIZE boundary. Requests to grow the PDU
+ * beyond NDR_PDU_MAX_SIZE are rejected.
+ *
+ * Returns 1 to indicate success. Otherwise 0 to indicate failure.
+ */
+static int
+ndo_grow_pdu(ndr_stream_t *nds, unsigned long want_end_offset, ndr_ref_t *ref)
+{
+	unsigned char *pdu_addr;
+	unsigned pdu_max_size;
+
+	ndo_printf(nds, ref, "grow %d", want_end_offset);
+
+	pdu_max_size = nds->pdu_max_size;
+
+	if (want_end_offset > pdu_max_size) {
+		pdu_max_size = NDR_PDU_ALIGN(want_end_offset);
+
+		if (pdu_max_size >= NDR_PDU_MAX_SIZE)
+			return (0);
+
+		pdu_addr = realloc(nds->pdu_base_addr, pdu_max_size);
+		if (pdu_addr == 0)
+			return (0);
+
+		nds->pdu_max_size = pdu_max_size;
+		nds->pdu_base_addr = pdu_addr;
+		nds->pdu_base_offset = (unsigned long)pdu_addr;
+	}
+
+	nds->pdu_size = want_end_offset;
+	return (1);
+}
+
+static int
+ndo_pad_pdu(ndr_stream_t *nds, unsigned long pdu_offset,
+    unsigned long n_bytes, ndr_ref_t *ref)
+{
+	unsigned char *data;
+
+	data = (unsigned char *)nds->pdu_base_offset;
+	data += pdu_offset;
+
+	ndo_printf(nds, ref, "pad %d@%-3d", n_bytes, pdu_offset);
+
+	bzero(data, n_bytes);
+	return (1);
+}
+
+/*
+ * ndo_get_pdu
+ *
+ * The swap flag is 1 if NDR knows that the byte-order in the PDU
+ * is different from the local system.
+ *
+ * Returns 1 on success or 0 to indicate failure.
+ */
+static int
+ndo_get_pdu(ndr_stream_t *nds, unsigned long pdu_offset,
+    unsigned long n_bytes, char *buf, int swap_bytes, ndr_ref_t *ref)
+{
+	unsigned char *data;
+	char hexbuf[NDOBUFSZ];
+
+	data = (unsigned char *)nds->pdu_base_offset;
+	data += pdu_offset;
+
+	ndo_hexfmt(data, n_bytes, swap_bytes, hexbuf, NDOBUFSZ);
+
+	ndo_printf(nds, ref, "get %d@%-3d = %s",
+	    n_bytes, pdu_offset, hexbuf);
+
+	if (!swap_bytes)
+		bcopy(data, buf, n_bytes);
+	else
+		nds_bswap(data, (unsigned char *)buf, n_bytes);
+
+	return (1);
+}
+
+/*
+ * ndo_put_pdu
+ *
+ * This is a receiver makes right protocol. So we do not need
+ * to be concerned about the byte-order of an outgoing PDU.
+ */
+/*ARGSUSED*/
+static int
+ndo_put_pdu(ndr_stream_t *nds, unsigned long pdu_offset,
+    unsigned long n_bytes, char *buf, int swap_bytes, ndr_ref_t *ref)
+{
+	unsigned char *data;
+	char hexbuf[NDOBUFSZ];
+
+	data = (unsigned char *)nds->pdu_base_offset;
+	data += pdu_offset;
+
+	ndo_hexfmt((uint8_t *)buf, n_bytes, 0, hexbuf, NDOBUFSZ);
+
+	ndo_printf(nds, ref, "put %d@%-3d = %s",
+	    n_bytes, pdu_offset, hexbuf);
+
+	bcopy(buf, data, n_bytes);
+	return (1);
+}
+
+static void
+ndo_tattle(ndr_stream_t *nds, char *what, ndr_ref_t *ref)
+{
+	ndo_printf(nds, ref, what);
+}
+
+static void
+ndo_tattle_error(ndr_stream_t *nds, ndr_ref_t *ref)
+{
+	unsigned char *data;
+	char hexbuf[NDOBUFSZ];
+
+	if (nds->pdu_base_addr != NULL) {
+		data = (unsigned char *)nds->pdu_base_offset;
+		if (ref)
+			data += ref->pdu_offset;
+		else
+			data += nds->pdu_scan_offset;
+
+		ndo_hexfmt(data, 16, 0, hexbuf, NDOBUFSZ);
+	} else {
+		bzero(hexbuf, NDOBUFSZ);
+	}
+
+	ndo_printf(nds, ref, "ERROR=%d REF=%d OFFSET=%d SIZE=%d/%d",
+	    nds->error, nds->error_ref, nds->pdu_scan_offset,
+	    nds->pdu_size, nds->pdu_max_size);
+	ndo_printf(nds, ref, "      %s", hexbuf);
+}
+
+/*
+ * ndo_reset
+ *
+ * Reset a stream: zap the outer_queue. We don't need to tamper
+ * with the stream heap: it's handled externally to the stream.
+ */
+static int
+ndo_reset(ndr_stream_t *nds)
+{
+	ndo_printf(nds, 0, "reset");
+
+	nds->pdu_size = 0;
+	nds->pdu_scan_offset = 0;
+	nds->outer_queue_head = 0;
+	nds->outer_current = 0;
+	nds->outer_queue_tailp = &nds->outer_queue_head;
+
+	return (1);
+}
+
+/*
+ * ndo_destruct
+ *
+ * Destruct a stream: zap the outer_queue.
+ * Note: heap management (creation/destruction) is external to the stream.
+ */
+static void
+ndo_destruct(ndr_stream_t *nds)
+{
+
+	ndo_printf(nds, 0, "destruct");
+
+	if (nds == NULL)
+		return;
+
+	if (nds->pdu_base_addr != NULL) {
+		free(nds->pdu_base_addr);
+		nds->pdu_base_addr = NULL;
+		nds->pdu_base_offset = 0;
+	}
+
+	nds->outer_queue_head = 0;
+	nds->outer_current = 0;
+	nds->outer_queue_tailp = &nds->outer_queue_head;
+}
+
+/*
+ * Printf style formatting for NDR operations.
+ */
+void
+ndo_printf(ndr_stream_t *nds, ndr_ref_t *ref, const char *fmt, ...)
+{
+	va_list ap;
+	char buf[NDOBUFSZ];
+
+	va_start(ap, fmt);
+	(void) vsnprintf(buf, NDOBUFSZ, fmt, ap);
+	va_end(ap);
+
+	if (nds)
+		ndo_fmt(nds, ref, buf);
+	else
+		ndo_trace(buf);
+}
+
+/*
+ * Main output formatter for NDR operations.
+ *
+ *	UI 03 ... rpc_vers           get 1@0   =    5 {05}
+ *	UI 03 ... rpc_vers_minor     get 1@1   =    0 {00}
+ *
+ *	U       Marshalling flag (M=marshal, U=unmarshal)
+ *	I       Direction flag (I=in, O=out)
+ *	...     Field name
+ *	get     PDU operation (get or put)
+ *	1@0	Bytes @ offset (i.e. 1 byte at offset 0)
+ *	{05}    Value
+ */
+void
+ndo_fmt(ndr_stream_t *nds, ndr_ref_t *ref, char *note)
+{
+	ndr_ref_t	*p;
+	int		indent;
+	char		ref_name[NDOBUFSZ];
+	char		buf[NDOBUFSZ];
+	int		m_op_c = '?', dir_c = '?';
+
+	switch (nds->m_op) {
+	case 0:				m_op_c = '-';	break;
+	case NDR_M_OP_MARSHALL:		m_op_c = 'M';	break;
+	case NDR_M_OP_UNMARSHALL:	m_op_c = 'U';	break;
+	default:			m_op_c = '?';	break;
+	}
+
+	switch (nds->dir) {
+	case 0:				dir_c = '-';	break;
+	case NDR_DIR_IN:		dir_c = 'I';	break;
+	case NDR_DIR_OUT:		dir_c = 'O';	break;
+	default:			dir_c = '?';	break;
+	}
+
+	for (indent = 0, p = ref; p; p = p->enclosing)
+		indent++;
+
+	if (ref && ref->name) {
+		if (*ref->name == '[' && ref->enclosing) {
+			indent--;
+			(void) snprintf(ref_name, NDOBUFSZ, "%s%s",
+			    ref->enclosing->name, ref->name);
+		} else {
+			(void) strlcpy(ref_name, ref->name, NDOBUFSZ);
+		}
+	} else {
+		(void) strlcpy(ref_name, "----", NDOBUFSZ);
+	}
+
+	(void) snprintf(buf, NDOBUFSZ, "%c%c %-.*s %-*s  %s",
+	    m_op_c, dir_c, indent,
+	    "....+....+....+....+....+....",
+	    20 - indent, ref_name, note);
+
+	ndo_trace(buf);
+}
+
+/*ARGSUSED*/
+void
+ndo_trace(const char *s)
+{
+	/*
+	 * Temporary fbt for dtrace until user space sdt enabled.
+	 */
+}
+
+/*
+ * Format data as hex bytes (limit is 10 bytes):
+ *
+ *	1188689424 {10 f6 d9 46}
+ *
+ * If the input data is greater than 10 bytes, an ellipsis will
+ * be inserted before the closing brace.
+ */
+static void
+ndo_hexfmt(uint8_t *data, int size, int swap_bytes, char *buf, int len)
+{
+	char *p = buf;
+	int interp = 1;
+	uint32_t c;
+	int n;
+	int i;
+
+	n = (size > 10) ? 10 : size;
+	if (n > len-1)
+		n = len-1;
+
+	switch (size) {
+	case 1:
+		c = *(uint8_t *)data;
+		break;
+	case 2:
+		if (swap_bytes == 0) /*LINTED E_BAD_PTR_CAST_ALIGN*/
+			c = *(uint16_t *)data;
+		else
+			c = (data[0] << 8) | data[1];
+		break;
+	case 4:
+		if (swap_bytes == 0) { /*LINTED E_BAD_PTR_CAST_ALIGN*/
+			c = *(uint32_t *)data;
+		} else {
+			c = (data[0] << 24) | (data[1] << 16)
+			    | (data[2] << 8) | data[3];
+		}
+		break;
+	default:
+		c = 0;
+		interp = 0;
+		break;
+	}
+
+	if (interp)
+		p += sprintf(p, "%4u {", c);
+	else
+		p += sprintf(p, " {");
+
+	p += sprintf(p, "%02x", data[0]);
+	for (i = 1; i < n; i++)
+		p += sprintf(p, " %02x", data[i]);
+	if (size > 10)
+		p += sprintf(p, " ...}");
+	else
+		p += sprintf(p, "}");
+
+	/*
+	 * Show c if it's a printable character or wide-char.
+	 */
+	if (size < 4 && isprint((uint8_t)c))
+		(void) sprintf(p, " %c", (uint8_t)c);
+}
--- old/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c	Sun Mar 18 01:13:16 2018
+++ /dev/null	Sun Mar 18 01:13:16 2018
@@ -1,2047 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- * Copyright 2012 Milan Jurik. All rights reserved.
- */
-
-/*
- * Network Data Representation (NDR) is a compatible subset of the DCE RPC
- * and MSRPC NDR.  NDR is used to move parameters consisting of
- * complicated trees of data constructs between an RPC client and server.
- */
-
-#include <sys/byteorder.h>
-#include <strings.h>
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <smbsrv/libsmb.h>
-#include <smbsrv/string.h>
-#include <smbsrv/libmlrpc.h>
-
-#define	NDR_STRING_MAX		4096
-
-#define	NDR_IS_UNION(T)	\
-	(((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_UNION)
-#define	NDR_IS_STRING(T)	\
-	(((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_STRING)
-
-extern ndr_typeinfo_t ndt_s_wchar;
-
-/*
- * The following synopsis describes the terms TOP-MOST, OUTER and INNER.
- *
- * Each parameter (call arguments and return values) is a TOP-MOST item.
- * A TOP-MOST item consists of one or more OUTER items.  An OUTER item
- * consists of one or more INNER items.  There are important differences
- * between each kind, which, primarily, have to do with the allocation
- * of memory to contain data structures and the order of processing.
- *
- * This is most easily demonstrated with a short example.
- * Consider these structures:
- *
- *	struct top_param {
- *		long		level;
- *		struct list *	head;
- *		long		count;
- *	};
- *
- *	struct list {
- *		struct list *	next;
- *		char *		str; // a string
- *	};
- *
- * Now, consider an instance tree like this:
- *
- *	+---------+       +-------+       +-------+
- *	|top_param|  +--->|list #1|  +--->|list #2|
- *	+---------+  |    +-------+  |    +-------+
- *	| level   |  |    | next ----+    | next --->(NULL)
- *	| head   ----+    | str  -->"foo" | str  -->"bar"
- *	| count   |       | flag  |       | flag  |
- *	+---------+       +-------+       +-------+
- *
- * The DCE(MS)/RPC Stub Data encoding for the tree is the following.
- * The vertical bars (|) indicate OUTER construct boundaries.
- *
- *   +-----+----------------------+----------------------+-----+-----+-----+
- *   |level|#1.next #1.str #1.flag|#2.next #2.str #2.flag|"bar"|"foo"|count|
- *   +-----+----------------------+----------------------+-----+-----+-----+
- *   level |<----------------------- head -------------------------->|count
- *   TOP    TOP                                                       TOP
- *
- * Here's what to notice:
- *
- * - The members of the TOP-MOST construct are scattered through the Stub
- *   Data in the order they occur.  This example shows a TOP-MOST construct
- *   consisting of atomic types (pointers and integers).  A construct
- *   (struct) within the TOP-MOST construct would be contiguous and not
- *   scattered.
- *
- * - The members of OUTER constructs are contiguous, which allows for
- *   non-copied relocated (fixed-up) data structures at the packet's
- *   destination.  We don't do fix-ups here.  The pointers within the
- *   OUTER constructs are processed depth-first in the order that they
- *   occur.  If they were processed breadth first, the sequence would
- *   be #1,"foo",#2,"bar".  This is tricky because OUTER constructs may
- *   be variable length, and pointers are often encountered before the
- *   size(s) is known.
- *
- * - The INNER constructs are simply the members of an OUTER construct.
- *
- * For comparison, consider how ONC RPC would handle the same tree of
- * data.  ONC requires very little buffering, while DCE requires enough
- * buffer space for the entire message.  ONC does atom-by-atom depth-first
- * (de)serialization and copy, while DCE allows for constructs to be
- * "fixed-up" (relocated) in place at the destination.  The packet data
- * for the same tree processed by ONC RPC would look like this:
- *
- *   +---------------------------------------------------------------------+
- *   |level #1.next #2.next #2.str "bar" #2.flag #1.str "foo" #1.flag count|
- *   +---------------------------------------------------------------------+
- *   TOP    #1      #2      #2     bar   #2      #1     foo   #1      TOP
- *
- * More details about each TOP-MOST, OUTER, and INNER constructs appear
- * throughout this source file near where such constructs are processed.
- *
- * NDR_REFERENCE
- *
- * The primary object for NDR is the ndr_ref_t.
- *
- * An ndr reference indicates the local datum (i.e. native "C" data
- * format), and the element within the Stub Data (contained within the
- * RPC PDU (protocol data unit).  An ndr reference also indicates,
- * largely as a debugging aid, something about the type of the
- * element/datum, and the enclosing construct for the element. The
- * ndr reference's are typically allocated on the stack as locals,
- * and the chain of ndr-reference.enclosing references is in reverse
- * order of the call graph.
- *
- * The ndr-reference.datum is a pointer to the local memory that
- * contains/receives the value. The ndr-reference.pdu_offset indicates
- * where in the Stub Data the value is to be stored/retrieved.
- *
- * The ndr-reference also contains various parameters to the NDR
- * process, such as ndr-reference.size_is, which indicates the size
- * of variable length data, or ndr-reference.switch_is, which
- * indicates the arm of a union to use.
- *
- * QUEUE OF OUTER REFERENCES
- *
- * Some OUTER constructs are variable size.  Sometimes (often) we don't
- * know the size of the OUTER construct until after pointers have been
- * encountered. Hence, we can not begin processing the referent of the
- * pointer until after the referring OUTER construct is completely
- * processed, i.e. we don't know where to find/put the referent in the
- * Stub Data until we know the size of all its predecessors.
- *
- * This is managed using the queue of OUTER references.  The queue is
- * anchored in ndr_stream.outer_queue_head.  At any time,
- * ndr_stream.outer_queue_tailp indicates where to put the
- * ndr-reference for the next encountered pointer.
- *
- * Refer to the example above as we illustrate the queue here.  In these
- * illustrations, the queue entries are not the data structures themselves.
- * Rather, they are ndr-reference entries which **refer** to the data
- * structures in both the PDU and local memory.
- *
- * During some point in the processing, the queue looks like this:
- *
- *   outer_current -------v
- *   outer_queue_head --> list#1 --0
- *   outer_queue_tailp ---------&
- *
- * When the pointer #1.next is encountered, and entry is added to the
- * queue,
- *
- *   outer_current -------v
- *   outer_queue_head --> list#1 --> list#2 --0
- *   outer_queue_tailp --------------------&
- *
- * and the members of #1 continue to be processed, which encounters
- * #1.str:
- *
- *   outer_current -------v
- *   outer_queue_head --> list#1 --> list#2 --> "foo" --0
- *   outer_queue_tailp ------------------------------&
- *
- * Upon the completion of list#1, the processing continues by moving to
- * ndr_stream.outer_current->next, and the tail is set to this outer member:
- *
- *   outer_current ------------------v
- *   outer_queue_head --> list#1 --> list#2 --> "foo" --0
- *   outer_queue_tailp --------------------&
- *
- * Space for list#2 is allocated, either in the Stub Data or of local
- * memory.  When #2.next is encountered, it is found to be the null
- * pointer and no reference is added to the queue.  When #2.str is
- * encountered, it is found to be valid, and a reference is added:
- *
- *   outer_current ------------------v
- *   outer_queue_head --> list#1 --> list#2 --> "bar" --> "foo" --0
- *   outer_queue_tailp ------------------------------&
- *
- * Processing continues in a similar fashion with the string "bar",
- * which is variable-length.  At this point, memory for "bar" may be
- * malloc()ed during NDR_M_OP_UNMARSHALL:
- *
- *   outer_current -----------------------------v
- *   outer_queue_head --> list#1 --> list#2 --> "bar" --> "foo" --0
- *   outer_queue_tailp ------------------------------&
- *
- * And finishes on string "foo".  Notice that because "bar" is a
- * variable length string, and we don't know the PDU offset for "foo"
- * until we reach this point.
- *
- * When the queue is drained (current->next==0), processing continues
- * with the next TOP-MOST member.
- *
- * The queue of OUTER constructs manages the variable-length semantics
- * of OUTER constructs and satisfies the depth-first requirement.
- * We allow the queue to linger until the entire TOP-MOST structure is
- * processed as an aid to debugging.
- */
-
-static ndr_ref_t *ndr_enter_outer_queue(ndr_ref_t *);
-extern int ndr__ulong(ndr_ref_t *);
-
-/*
- * TOP-MOST ELEMENTS
- *
- * This is fundamentally the first OUTER construct of the parameter,
- * possibly followed by more OUTER constructs due to pointers.  The
- * datum (local memory) for TOP-MOST constructs (structs) is allocated
- * by the caller of NDR.
- *
- * After the element is transferred, the outer_queue is drained.
- *
- * All we have to do is add an entry to the outer_queue for this
- * top-most member, and commence the outer_queue processing.
- */
-int
-ndo_process(ndr_stream_t *nds, ndr_typeinfo_t *ti, char *datum)
-{
-	ndr_ref_t	myref;
-
-	bzero(&myref, sizeof (myref));
-	myref.stream = nds;
-	myref.datum = datum;
-	myref.name = "PROCESS";
-	myref.ti = ti;
-
-	return (ndr_topmost(&myref));
-}
-
-int
-ndo_operation(ndr_stream_t *nds, ndr_typeinfo_t *ti, int opnum, char *datum)
-{
-	ndr_ref_t	myref;
-
-	bzero(&myref, sizeof (myref));
-	myref.stream = nds;
-	myref.datum = datum;
-	myref.name = "OPERATION";
-	myref.ti = ti;
-	myref.inner_flags = NDR_F_SWITCH_IS;
-	myref.switch_is = opnum;
-
-	if (ti->type_flags != NDR_F_INTERFACE) {
-		NDR_SET_ERROR(&myref, NDR_ERR_NOT_AN_INTERFACE);
-		return (0);
-	}
-
-	return ((*ti->ndr_func)(&myref));
-}
-
-int
-ndr_params(ndr_ref_t *params_ref)
-{
-	ndr_typeinfo_t *ti = params_ref->ti;
-
-	if (ti->type_flags == NDR_F_OPERATION)
-		return (*ti->ndr_func) (params_ref);
-	else
-		return (ndr_topmost(params_ref));
-}
-
-int
-ndr_topmost(ndr_ref_t *top_ref)
-{
-	ndr_stream_t *nds;
-	ndr_typeinfo_t *ti;
-	ndr_ref_t *outer_ref = 0;
-	int	is_varlen;
-	int	is_string;
-	int	error;
-	int	rc;
-	unsigned n_fixed;
-	int	params;
-
-	assert(top_ref);
-	assert(top_ref->stream);
-	assert(top_ref->ti);
-
-	nds = top_ref->stream;
-	ti = top_ref->ti;
-
-	is_varlen = ti->pdu_size_variable_part;
-	is_string = NDR_IS_STRING(ti);
-
-	assert(nds->outer_queue_tailp && !*nds->outer_queue_tailp);
-	assert(!nds->outer_current);
-
-	params = top_ref->inner_flags & NDR_F_PARAMS_MASK;
-
-	switch (params) {
-	case NDR_F_NONE:
-	case NDR_F_SWITCH_IS:
-		if (is_string || is_varlen) {
-			error = NDR_ERR_TOPMOST_VARLEN_ILLEGAL;
-			NDR_SET_ERROR(outer_ref, error);
-			return (0);
-		}
-		n_fixed = ti->pdu_size_fixed_part;
-		break;
-
-	case NDR_F_SIZE_IS:
-		error = NDR_ERR_TOPMOST_VARLEN_ILLEGAL;
-		NDR_SET_ERROR(outer_ref, error);
-		return (0);
-
-	case NDR_F_DIMENSION_IS:
-		if (is_varlen) {
-			error = NDR_ERR_ARRAY_VARLEN_ILLEGAL;
-			NDR_SET_ERROR(outer_ref, error);
-			return (0);
-		}
-		n_fixed = ti->pdu_size_fixed_part * top_ref->dimension_is;
-		break;
-
-	case NDR_F_IS_POINTER:
-	case NDR_F_IS_POINTER+NDR_F_SIZE_IS:
-		n_fixed = 4;
-		break;
-
-	case NDR_F_IS_REFERENCE:
-	case NDR_F_IS_REFERENCE+NDR_F_SIZE_IS:
-		n_fixed = 0;
-		break;
-
-	default:
-		error = NDR_ERR_OUTER_PARAMS_BAD;
-		NDR_SET_ERROR(outer_ref, error);
-		return (0);
-	}
-
-	outer_ref = ndr_enter_outer_queue(top_ref);
-	if (!outer_ref)
-		return (0);	/* error already set */
-
-	/*
-	 * Hand-craft the first OUTER construct and directly call
-	 * ndr_inner(). Then, run the outer_queue. We do this
-	 * because ndr_outer() wants to malloc() memory for
-	 * the construct, and we already have the memory.
-	 */
-
-	/* move the flags, etc, around again, undoes enter_outer_queue() */
-	outer_ref->inner_flags = top_ref->inner_flags;
-	outer_ref->outer_flags = 0;
-	outer_ref->datum = top_ref->datum;
-
-	/* All outer constructs start on a mod4 (longword) boundary */
-	if (!ndr_outer_align(outer_ref))
-		return (0);		/* error already set */
-
-	/* Regardless of what it is, this is where it starts */
-	outer_ref->pdu_offset = nds->pdu_scan_offset;
-
-	rc = ndr_outer_grow(outer_ref, n_fixed);
-	if (!rc)
-		return (0);		/* error already set */
-
-	outer_ref->pdu_end_offset = outer_ref->pdu_offset + n_fixed;
-
-	/* set-up outer_current, as though run_outer_queue() was doing it */
-	nds->outer_current = outer_ref;
-	nds->outer_queue_tailp = &nds->outer_current->next;
-	nds->pdu_scan_offset = outer_ref->pdu_end_offset;
-
-	/* do the topmost member */
-	rc = ndr_inner(outer_ref);
-	if (!rc)
-		return (0);		/* error already set */
-
-	nds->pdu_scan_offset = outer_ref->pdu_end_offset;
-
-	/* advance, as though run_outer_queue() was doing it */
-	nds->outer_current = nds->outer_current->next;
-	return (ndr_run_outer_queue(nds));
-}
-
-static ndr_ref_t *
-ndr_enter_outer_queue(ndr_ref_t *arg_ref)
-{
-	ndr_stream_t	*nds = arg_ref->stream;
-	ndr_ref_t	*outer_ref;
-
-	/*LINTED E_BAD_PTR_CAST_ALIGN*/
-	outer_ref = (ndr_ref_t *)NDS_MALLOC(nds, sizeof (*outer_ref), arg_ref);
-	if (!outer_ref) {
-		NDR_SET_ERROR(arg_ref, NDR_ERR_MALLOC_FAILED);
-		return (0);
-	}
-
-	*outer_ref = *arg_ref;
-
-	/* move advice in inner_flags to outer_flags */
-	outer_ref->outer_flags = arg_ref->inner_flags & NDR_F_PARAMS_MASK;
-	outer_ref->inner_flags = 0;
-	outer_ref->enclosing = nds->outer_current;
-	outer_ref->backptr = 0;
-	outer_ref->datum = 0;
-
-	assert(nds->outer_queue_tailp);
-
-	outer_ref->next = *nds->outer_queue_tailp;
-	*nds->outer_queue_tailp = outer_ref;
-	nds->outer_queue_tailp = &outer_ref->next;
-	return (outer_ref);
-}
-
-int
-ndr_run_outer_queue(ndr_stream_t *nds)
-{
-	while (nds->outer_current) {
-		nds->outer_queue_tailp = &nds->outer_current->next;
-
-		if (!ndr_outer(nds->outer_current))
-			return (0);
-
-		nds->outer_current = nds->outer_current->next;
-	}
-
-	return (1);
-}
-
-/*
- * OUTER CONSTRUCTS
- *
- * OUTER constructs are where the real work is, which stems from the
- * variable-length potential.
- *
- * DCE(MS)/RPC VARIABLE LENGTH -- CONFORMANT, VARYING, VARYING/CONFORMANT
- *
- * DCE(MS)/RPC provides for three forms of variable length: CONFORMANT,
- * VARYING, and VARYING/CONFORMANT.
- *
- * What makes this so tough is that the variable-length array may be well
- * encapsulated within the outer construct.  Further, because DCE(MS)/RPC
- * tries to keep the constructs contiguous in the data stream, the sizing
- * information precedes the entire OUTER construct.  The sizing information
- * must be used at the appropriate time, which can be after many, many,
- * many fixed-length elements.  During IDL type analysis, we know in
- * advance constructs that encapsulate variable-length constructs.  So,
- * we know when we have a sizing header and when we don't.  The actual
- * semantics of the header are largely deferred.
- *
- * Currently, VARYING constructs are not implemented but they are described
- * here in case they have to be implemented in the future.  Similarly,
- * DCE(MS)/RPC provides for multi-dimensional arrays, which are currently
- * not implemented.  Only one-dimensional, variable-length arrays are
- * supported.
- *
- * CONFORMANT CONSTRUCTS -- VARIABLE LENGTH ARRAYS START THE SHOW
- *
- * All variable-length values are arrays.  These arrays may be embedded
- * well within another construct.  However, a variable-length construct
- * may ONLY appear as the last member of an enclosing construct.  Example:
- *
- *	struct credentials {
- *		ulong	uid, gid;
- *		ulong	n_gids;
- *	    [size_is(n_gids)]
- *		ulong	gids[*];    // variable-length.
- *	};
- *
- * CONFORMANT constructs have a dynamic size in local memory and in the
- * PDU.  The CONFORMANT quality is indicated by the [size_is()] advice.
- * CONFORMANT constructs have the following header:
- *
- *	struct conformant_header {
- *		ulong		size_is;
- *	};
- *
- * (Multi-dimensional CONFORMANT arrays have a similar header for each
- * dimension - not implemented).
- *
- * Example CONFORMANT construct:
- *
- *	struct user {
- *		char *			name;
- *		struct credentials	cred;	// see above
- *	};
- *
- * Consider the data tree:
- *
- *    +--------+
- *    |  user  |
- *    +--------+
- *    | name  ----> "fred" (the string is a different OUTER)
- *    | uid    |
- *    | gid    |
- *    | n_gids |    for example, 3
- *    | gids[0]|
- *    | gids[1]|
- *    | gids[2]|
- *    +--------+
- *
- * The OUTER construct in the Stub Data would be:
- *
- *    +---+---------+---------------------------------------------+
- *    |pad|size_is=3 name uid gid n_gids=3 gids[0] gids[1] gids[2]|
- *    +---+---------+---------------------------------------------+
- *         szing hdr|user |<-------------- user.cred ------------>|
- *                  |<--- fixed-size ---->|<----- conformant ---->|
- *
- * The ndr_typeinfo for struct user will have:
- *	pdu_fixed_size_part = 16	four long words (name uid gid n_gids)
- *	pdu_variable_size_part = 4	per element, sizeof gids[0]
- *
- * VARYING CONSTRUCTS -- NOT IMPLEMENTED
- *
- * VARYING constructs have the following header:
- *
- *	struct varying_header {
- *		ulong		first_is;
- *		ulong		length_is;
- *	};
- *
- * This indicates which interval of an array is significant.
- * Non-intersecting elements of the array are undefined and usually
- * zero-filled.  The first_is parameter for C arrays is always 0 for
- * the first element.
- *
- * N.B. Constructs may contain one CONFORMANT element, which is always
- * last, but may contain many VARYING elements, which can be anywhere.
- *
- * VARYING CONFORMANT constructs have the sizing headers arranged like
- * this:
- *
- *	struct conformant_header	all_conformant[N_CONFORMANT_DIM];
- *	struct varying_header		all_varying[N_VARYING_ELEMS_AND_DIMS];
- *
- * The sizing header is immediately followed by the values for the
- * construct.  Again, we don't support more than one dimension and
- * we don't support VARYING constructs at this time.
- *
- * A good example of a VARYING/CONFORMANT data structure is the UNIX
- * directory entry:
- *
- *	struct dirent {
- *		ushort		reclen;
- *		ushort		namlen;
- *		ulong		inum;
- *	    [size_is(reclen-8) length_is(namlen+1)] // -(2+2+4), +1 for NUL
- *		uchar		name[*];
- *	};
- *
- *
- * STRINGS ARE A SPECIAL CASE
- *
- * Strings are handled specially.  MS/RPC uses VARYING/CONFORMANT structures
- * for strings.  This is a simple one-dimensional variable-length array,
- * typically with its last element all zeroes.  We handle strings with the
- * header:
- *
- *	struct string_header {
- *		ulong		size_is;
- *		ulong		first_is;	// always 0
- *		ulong		length_is;	// always same as size_is
- *	};
- *
- * If general support for VARYING and VARYING/CONFORMANT mechanisms is
- * implemented, we probably won't need the strings special case.
- */
-int
-ndr_outer(ndr_ref_t *outer_ref)
-{
-	ndr_stream_t 	*nds = outer_ref->stream;
-	ndr_typeinfo_t	*ti = outer_ref->ti;
-	int	is_varlen = ti->pdu_size_variable_part;
-	int	is_union = NDR_IS_UNION(ti);
-	int	is_string = NDR_IS_STRING(ti);
-	int	error = NDR_ERR_OUTER_PARAMS_BAD;
-	int	params;
-
-	params = outer_ref->outer_flags & NDR_F_PARAMS_MASK;
-
-	NDR_TATTLE(outer_ref, "--OUTER--");
-
-	/* All outer constructs start on a mod4 (longword) boundary */
-	if (!ndr_outer_align(outer_ref))
-		return (0);		/* error already set */
-
-	/* Regardless of what it is, this is where it starts */
-	outer_ref->pdu_offset = nds->pdu_scan_offset;
-
-	if (is_union) {
-		error = NDR_ERR_OUTER_UNION_ILLEGAL;
-		NDR_SET_ERROR(outer_ref, error);
-		return (0);
-	}
-
-	switch (params) {
-	case NDR_F_NONE:
-		if (is_string)
-			return (ndr_outer_string(outer_ref));
-		if (is_varlen)
-			return (ndr_outer_conformant_construct(outer_ref));
-
-		return (ndr_outer_fixed(outer_ref));
-
-	case NDR_F_SIZE_IS:
-	case NDR_F_DIMENSION_IS:
-	case NDR_F_IS_POINTER+NDR_F_SIZE_IS:
-	case NDR_F_IS_REFERENCE+NDR_F_SIZE_IS:
-		if (is_varlen) {
-			error = NDR_ERR_ARRAY_VARLEN_ILLEGAL;
-			break;
-		}
-
-		if (params & NDR_F_SIZE_IS)
-			return (ndr_outer_conformant_array(outer_ref));
-		else
-			return (ndr_outer_fixed_array(outer_ref));
-
-	default:
-		error = NDR_ERR_OUTER_PARAMS_BAD;
-		break;
-	}
-
-	/*
-	 * If we get here, something is wrong. Most likely,
-	 * the params flags do not match.
-	 */
-	NDR_SET_ERROR(outer_ref, error);
-	return (0);
-}
-
-int
-ndr_outer_fixed(ndr_ref_t *outer_ref)
-{
-	ndr_stream_t	*nds = outer_ref->stream;
-	ndr_typeinfo_t	*ti = outer_ref->ti;
-	ndr_ref_t	myref;
-	char 		*valp = NULL;
-	int		is_varlen = ti->pdu_size_variable_part;
-	int		is_union = NDR_IS_UNION(ti);
-	int		is_string = NDR_IS_STRING(ti);
-	int		rc;
-	unsigned	n_hdr;
-	unsigned	n_fixed;
-	unsigned	n_variable;
-	unsigned	n_alloc;
-	unsigned	n_pdu_total;
-	int		params;
-
-	params = outer_ref->outer_flags & NDR_F_PARAMS_MASK;
-
-	assert(!is_varlen && !is_string && !is_union);
-	assert(params == NDR_F_NONE);
-
-	/* no header for this */
-	n_hdr = 0;
-
-	/* fixed part -- exactly one of these */
-	n_fixed = ti->pdu_size_fixed_part;
-	assert(n_fixed > 0);
-
-	/* variable part -- exactly none of these */
-	n_variable = 0;
-
-	/* sum them up to determine the PDU space required */
-	n_pdu_total = n_hdr + n_fixed + n_variable;
-
-	/* similar sum to determine how much local memory is required */
-	n_alloc = n_fixed + n_variable;
-
-	rc = ndr_outer_grow(outer_ref, n_pdu_total);
-	if (!rc)
-		return (rc);		/* error already set */
-
-	switch (nds->m_op) {
-	case NDR_M_OP_MARSHALL:
-		valp = outer_ref->datum;
-		if (!valp) {
-			NDR_SET_ERROR(outer_ref, NDR_ERR_OUTER_PARAMS_BAD);
-			return (0);
-		}
-		if (outer_ref->backptr)
-			assert(valp == *outer_ref->backptr);
-		break;
-
-	case NDR_M_OP_UNMARSHALL:
-		valp = NDS_MALLOC(nds, n_alloc, outer_ref);
-		if (!valp) {
-			NDR_SET_ERROR(outer_ref, NDR_ERR_MALLOC_FAILED);
-			return (0);
-		}
-		if (outer_ref->backptr)
-			*outer_ref->backptr = valp;
-		outer_ref->datum = valp;
-		break;
-
-	default:
-		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
-		return (0);
-	}
-
-	bzero(&myref, sizeof (myref));
-	myref.stream = nds;
-	myref.enclosing = outer_ref;
-	myref.ti = outer_ref->ti;
-	myref.datum = outer_ref->datum;
-	myref.name = "FIXED-VALUE";
-	myref.outer_flags = NDR_F_NONE;
-	myref.inner_flags = NDR_F_NONE;
-
-	myref.pdu_offset = outer_ref->pdu_offset;
-	outer_ref->pdu_end_offset = outer_ref->pdu_offset + n_pdu_total;
-
-	rc = ndr_inner(&myref);
-	if (!rc)
-		return (rc);		/* error already set */
-
-	nds->pdu_scan_offset = outer_ref->pdu_end_offset;
-	return (1);
-}
-
-int
-ndr_outer_fixed_array(ndr_ref_t *outer_ref)
-{
-	ndr_stream_t	*nds = outer_ref->stream;
-	ndr_typeinfo_t	*ti = outer_ref->ti;
-	ndr_ref_t	myref;
-	char 		*valp = NULL;
-	int		is_varlen = ti->pdu_size_variable_part;
-	int		is_union = NDR_IS_UNION(ti);
-	int		is_string = NDR_IS_STRING(ti);
-	int		rc;
-	unsigned	n_hdr;
-	unsigned	n_fixed;
-	unsigned	n_variable;
-	unsigned	n_alloc;
-	unsigned	n_pdu_total;
-	int		params;
-
-	params = outer_ref->outer_flags & NDR_F_PARAMS_MASK;
-
-	assert(!is_varlen && !is_string && !is_union);
-	assert(params == NDR_F_DIMENSION_IS);
-
-	/* no header for this */
-	n_hdr = 0;
-
-	/* fixed part -- exactly dimension_is of these */
-	n_fixed = ti->pdu_size_fixed_part * outer_ref->dimension_is;
-	assert(n_fixed > 0);
-
-	/* variable part -- exactly none of these */
-	n_variable = 0;
-
-	/* sum them up to determine the PDU space required */
-	n_pdu_total = n_hdr + n_fixed + n_variable;
-
-	/* similar sum to determine how much local memory is required */
-	n_alloc = n_fixed + n_variable;
-
-	rc = ndr_outer_grow(outer_ref, n_pdu_total);
-	if (!rc)
-		return (rc);		/* error already set */
-
-	switch (nds->m_op) {
-	case NDR_M_OP_MARSHALL:
-		valp = outer_ref->datum;
-		if (!valp) {
-			NDR_SET_ERROR(outer_ref, NDR_ERR_OUTER_PARAMS_BAD);
-			return (0);
-		}
-		if (outer_ref->backptr)
-			assert(valp == *outer_ref->backptr);
-		break;
-
-	case NDR_M_OP_UNMARSHALL:
-		valp = NDS_MALLOC(nds, n_alloc, outer_ref);
-		if (!valp) {
-			NDR_SET_ERROR(outer_ref, NDR_ERR_MALLOC_FAILED);
-			return (0);
-		}
-		if (outer_ref->backptr)
-			*outer_ref->backptr = valp;
-		outer_ref->datum = valp;
-		break;
-
-	default:
-		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
-		return (0);
-	}
-
-	bzero(&myref, sizeof (myref));
-	myref.stream = nds;
-	myref.enclosing = outer_ref;
-	myref.ti = outer_ref->ti;
-	myref.datum = outer_ref->datum;
-	myref.name = "FIXED-ARRAY";
-	myref.outer_flags = NDR_F_NONE;
-	myref.inner_flags = NDR_F_DIMENSION_IS;
-	myref.dimension_is = outer_ref->dimension_is;
-
-	myref.pdu_offset = outer_ref->pdu_offset;
-	outer_ref->pdu_end_offset = outer_ref->pdu_offset + n_pdu_total;
-
-	rc = ndr_inner(&myref);
-	if (!rc)
-		return (rc);		/* error already set */
-
-	nds->pdu_scan_offset = outer_ref->pdu_end_offset;
-	return (1);
-}
-
-int
-ndr_outer_conformant_array(ndr_ref_t *outer_ref)
-{
-	ndr_stream_t	*nds = outer_ref->stream;
-	ndr_typeinfo_t	*ti = outer_ref->ti;
-	ndr_ref_t	myref;
-	char 		*valp = NULL;
-	int		is_varlen = ti->pdu_size_variable_part;
-	int		is_union = NDR_IS_UNION(ti);
-	int		is_string = NDR_IS_STRING(ti);
-	unsigned long	size_is;
-	int		rc;
-	unsigned	n_hdr;
-	unsigned	n_fixed;
-	unsigned	n_variable;
-	unsigned	n_alloc;
-	unsigned	n_pdu_total;
-	unsigned	n_ptr_offset;
-	int		params;
-
-	params = outer_ref->outer_flags & NDR_F_PARAMS_MASK;
-
-	assert(!is_varlen && !is_string && !is_union);
-	assert(params & NDR_F_SIZE_IS);
-
-	/* conformant header for this */
-	n_hdr = 4;
-
-	/* fixed part -- exactly none of these */
-	n_fixed = 0;
-
-	/* variable part -- exactly size_of of these */
-	/* notice that it is the **fixed** size of the ti */
-	n_variable = ti->pdu_size_fixed_part * outer_ref->size_is;
-
-	/* sum them up to determine the PDU space required */
-	n_pdu_total = n_hdr + n_fixed + n_variable;
-
-	/* similar sum to determine how much local memory is required */
-	n_alloc = n_fixed + n_variable;
-
-	rc = ndr_outer_grow(outer_ref, n_pdu_total);
-	if (!rc)
-		return (rc);		/* error already set */
-
-	switch (nds->m_op) {
-	case NDR_M_OP_MARSHALL:
-		size_is = outer_ref->size_is;
-		rc = ndr_outer_poke_sizing(outer_ref, 0, &size_is);
-		if (!rc)
-			return (0);	/* error already set */
-
-		valp = outer_ref->datum;
-		if (!valp) {
-			NDR_SET_ERROR(outer_ref, NDR_ERR_OUTER_PARAMS_BAD);
-			return (0);
-		}
-		if (outer_ref->backptr)
-			assert(valp == *outer_ref->backptr);
-		n_ptr_offset = 4;
-		break;
-
-	case NDR_M_OP_UNMARSHALL:
-		if (params & NDR_F_IS_REFERENCE) {
-			size_is = outer_ref->size_is;
-			n_ptr_offset = 0;
-		} else {
-			/* NDR_F_IS_POINTER */
-			rc = ndr_outer_peek_sizing(outer_ref, 0, &size_is);
-			if (!rc)
-				return (0);	/* error already set */
-
-			if (size_is != outer_ref->size_is) {
-				NDR_SET_ERROR(outer_ref,
-				    NDR_ERR_SIZE_IS_MISMATCH_PDU);
-				return (0);
-			}
-
-			n_ptr_offset = 4;
-		}
-
-		if (size_is > 0) {
-			valp = NDS_MALLOC(nds, n_alloc, outer_ref);
-			if (!valp) {
-				NDR_SET_ERROR(outer_ref, NDR_ERR_MALLOC_FAILED);
-				return (0);
-			}
-		}
-
-		if (outer_ref->backptr)
-			*outer_ref->backptr = valp;
-		outer_ref->datum = valp;
-		break;
-
-	default:
-		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
-		return (0);
-	}
-
-	outer_ref->pdu_end_offset = outer_ref->pdu_offset + n_pdu_total;
-	outer_ref->type_flags = NDR_F_NONE;
-	outer_ref->inner_flags = NDR_F_NONE;
-
-	if (size_is > 0) {
-		bzero(&myref, sizeof (myref));
-		myref.stream = nds;
-		myref.enclosing = outer_ref;
-		myref.ti = outer_ref->ti;
-		myref.datum = outer_ref->datum;
-		myref.name = "CONFORMANT-ARRAY";
-		myref.outer_flags = NDR_F_NONE;
-		myref.inner_flags = NDR_F_SIZE_IS;
-		myref.size_is = outer_ref->size_is;
-
-		myref.inner_flags = NDR_F_DIMENSION_IS;		/* convenient */
-		myref.dimension_is = outer_ref->size_is;	/* convenient */
-
-		myref.pdu_offset = outer_ref->pdu_offset + n_ptr_offset;
-
-		rc = ndr_inner(&myref);
-		if (!rc)
-			return (rc);		/* error already set */
-	}
-
-	nds->pdu_scan_offset = outer_ref->pdu_end_offset;
-	return (1);
-}
-
-int
-ndr_outer_conformant_construct(ndr_ref_t *outer_ref)
-{
-	ndr_stream_t	*nds = outer_ref->stream;
-	ndr_typeinfo_t	*ti = outer_ref->ti;
-	ndr_ref_t	myref;
-	char 		*valp = NULL;
-	int		is_varlen = ti->pdu_size_variable_part;
-	int		is_union = NDR_IS_UNION(ti);
-	int		is_string = NDR_IS_STRING(ti);
-	unsigned long	size_is;
-	int		rc;
-	unsigned	n_hdr;
-	unsigned	n_fixed;
-	unsigned	n_variable;
-	unsigned	n_alloc;
-	unsigned	n_pdu_total;
-	int		params;
-
-	params = outer_ref->outer_flags & NDR_F_PARAMS_MASK;
-
-	assert(is_varlen && !is_string && !is_union);
-	assert(params == NDR_F_NONE);
-
-	/* conformant header for this */
-	n_hdr = 4;
-
-	/* fixed part -- exactly one of these */
-	n_fixed = ti->pdu_size_fixed_part;
-
-	/* variable part -- exactly size_of of these */
-	n_variable = 0;		/* 0 for the moment */
-
-	/* sum them up to determine the PDU space required */
-	n_pdu_total = n_hdr + n_fixed + n_variable;
-
-	/* similar sum to determine how much local memory is required */
-	n_alloc = n_fixed + n_variable;
-
-	/* For the moment, grow enough for the fixed-size part */
-	rc = ndr_outer_grow(outer_ref, n_pdu_total);
-	if (!rc)
-		return (rc);		/* error already set */
-
-	switch (nds->m_op) {
-	case NDR_M_OP_MARSHALL:
-		/*
-		 * We don't know the size yet. We have to wait for
-		 * it. Proceed with the fixed-size part, and await
-		 * the call to ndr_size_is().
-		 */
-		size_is = 0;
-		rc = ndr_outer_poke_sizing(outer_ref, 0, &size_is);
-		if (!rc)
-			return (0);	/* error already set */
-
-		valp = outer_ref->datum;
-		if (!valp) {
-			NDR_SET_ERROR(outer_ref, NDR_ERR_OUTER_PARAMS_BAD);
-			return (0);
-		}
-		if (outer_ref->backptr)
-			assert(valp == *outer_ref->backptr);
-		break;
-
-	case NDR_M_OP_UNMARSHALL:
-		/*
-		 * We know the size of the variable part because
-		 * of the CONFORMANT header. We will verify
-		 * the header against the [size_is(X)] advice
-		 * later when ndr_size_is() is called.
-		 */
-		rc = ndr_outer_peek_sizing(outer_ref, 0, &size_is);
-		if (!rc)
-			return (0);	/* error already set */
-
-		/* recalculate metrics */
-		n_variable = size_is * ti->pdu_size_variable_part;
-		n_pdu_total = n_hdr + n_fixed + n_variable;
-		n_alloc = n_fixed + n_variable;
-
-		rc = ndr_outer_grow(outer_ref, n_pdu_total);
-		if (!rc)
-			return (rc);		/* error already set */
-
-		outer_ref->size_is = size_is; /* verified later */
-
-		valp = NDS_MALLOC(nds, n_alloc, outer_ref);
-		if (!valp) {
-			NDR_SET_ERROR(outer_ref, NDR_ERR_MALLOC_FAILED);
-			return (0);
-		}
-		if (outer_ref->backptr)
-			*outer_ref->backptr = valp;
-		outer_ref->datum = valp;
-		break;
-
-	default:
-		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
-		return (0);
-	}
-
-	outer_ref->pdu_end_offset = outer_ref->pdu_offset + n_pdu_total;
-	outer_ref->type_flags = NDR_F_SIZE_IS; /* indicate pending */
-	outer_ref->inner_flags = NDR_F_NONE;   /* indicate pending */
-
-	bzero(&myref, sizeof (myref));
-	myref.stream = nds;
-	myref.enclosing = outer_ref;
-	myref.ti = outer_ref->ti;
-	myref.datum = outer_ref->datum;
-	myref.name = "CONFORMANT-CONSTRUCT";
-	myref.outer_flags = NDR_F_NONE;
-	myref.inner_flags = NDR_F_NONE;
-	myref.size_is = outer_ref->size_is;
-
-	myref.pdu_offset = outer_ref->pdu_offset + 4;
-
-	rc = ndr_inner(&myref);
-	if (!rc)
-		return (rc);		/* error already set */
-
-	nds->pdu_scan_offset = outer_ref->pdu_end_offset;
-
-	if (outer_ref->inner_flags != NDR_F_SIZE_IS) {
-		NDR_SET_ERROR(&myref, NDR_ERR_SIZE_IS_MISMATCH_AFTER);
-		return (0);
-	}
-
-	return (1);
-}
-
-int
-ndr_size_is(ndr_ref_t *ref)
-{
-	ndr_stream_t 		*nds = ref->stream;
-	ndr_ref_t 		*outer_ref = nds->outer_current;
-	ndr_typeinfo_t		*ti = outer_ref->ti;
-	unsigned long		size_is;
-	int			rc;
-	unsigned		n_hdr;
-	unsigned		n_fixed;
-	unsigned		n_variable;
-	unsigned		n_pdu_total;
-
-	assert(ref->inner_flags & NDR_F_SIZE_IS);
-	size_is = ref->size_is;
-
-	if (outer_ref->type_flags != NDR_F_SIZE_IS) {
-		NDR_SET_ERROR(ref, NDR_ERR_SIZE_IS_UNEXPECTED);
-		return (0);
-	}
-
-	if (outer_ref->inner_flags & NDR_F_SIZE_IS) {
-		NDR_SET_ERROR(ref, NDR_ERR_SIZE_IS_DUPLICATED);
-		return (0);
-	}
-
-	/* repeat metrics, see ndr_conformant_construct() above */
-	n_hdr = 4;
-	n_fixed = ti->pdu_size_fixed_part;
-	n_variable = size_is * ti->pdu_size_variable_part;
-	n_pdu_total = n_hdr + n_fixed + n_variable;
-
-	rc = ndr_outer_grow(outer_ref, n_pdu_total);
-	if (!rc)
-		return (rc);		/* error already set */
-
-	switch (nds->m_op) {
-	case NDR_M_OP_MARSHALL:
-		/*
-		 * We have to set the sizing header and extend
-		 * the size of the PDU (already done).
-		 */
-		rc = ndr_outer_poke_sizing(outer_ref, 0, &size_is);
-		if (!rc)
-			return (0);	/* error already set */
-		break;
-
-	case NDR_M_OP_UNMARSHALL:
-		/*
-		 * Allocation done during ndr_conformant_construct().
-		 * All we are doing here is verifying that the
-		 * intended size (ref->size_is) matches the sizing header.
-		 */
-		if (size_is != outer_ref->size_is) {
-			NDR_SET_ERROR(ref, NDR_ERR_SIZE_IS_MISMATCH_PDU);
-			return (0);
-		}
-		break;
-
-	default:
-		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
-		return (0);
-	}
-
-	outer_ref->inner_flags |= NDR_F_SIZE_IS;
-	outer_ref->size_is = ref->size_is;
-	return (1);
-}
-
-int
-ndr_outer_string(ndr_ref_t *outer_ref)
-{
-	ndr_stream_t	*nds = outer_ref->stream;
-	ndr_typeinfo_t 	*ti = outer_ref->ti;
-	ndr_ref_t	myref;
-	char 		*valp = NULL;
-	unsigned	is_varlen = ti->pdu_size_variable_part;
-	int		is_union = NDR_IS_UNION(ti);
-	int		is_string = NDR_IS_STRING(ti);
-	int		rc;
-	unsigned	n_zeroes;
-	unsigned	ix;
-	unsigned long	size_is;
-	unsigned long	first_is;
-	unsigned long	length_is;
-	unsigned	n_hdr;
-	unsigned	n_fixed;
-	unsigned	n_variable;
-	unsigned	n_alloc;
-	unsigned	n_pdu_total;
-	int		params;
-
-	params = outer_ref->outer_flags & NDR_F_PARAMS_MASK;
-
-	assert(is_varlen && is_string && !is_union);
-	assert(params == NDR_F_NONE);
-
-	/* string header for this: size_is first_is length_is */
-	n_hdr = 12;
-
-	/* fixed part -- exactly none of these */
-	n_fixed = 0;
-
-	if (!ndr_outer_grow(outer_ref, n_hdr))
-		return (0);		/* error already set */
-
-	switch (nds->m_op) {
-	case NDR_M_OP_MARSHALL:
-		valp = outer_ref->datum;
-		if (!valp) {
-			NDR_SET_ERROR(outer_ref, NDR_ERR_OUTER_PARAMS_BAD);
-			return (0);
-		}
-
-		if (outer_ref->backptr)
-			assert(valp == *outer_ref->backptr);
-
-		if (ti == &ndt_s_wchar) {
-			/*
-			 * size_is is the number of characters in the
-			 * (multibyte) string, including the null.
-			 */
-			size_is = smb_wcequiv_strlen(valp) /
-			    sizeof (smb_wchar_t);
-
-			if (!(nds->flags & NDS_F_NONULL))
-				++size_is;
-
-			if (size_is > NDR_STRING_MAX) {
-				NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
-				return (0);
-			}
-		} else {
-			valp = outer_ref->datum;
-			n_zeroes = 0;
-			for (ix = 0; ix < NDR_STRING_MAX; ix++) {
-				if (valp[ix] == 0) {
-					n_zeroes++;
-					if (n_zeroes >= is_varlen &&
-					    ix % is_varlen == 0) {
-						break;
-					}
-				} else {
-					n_zeroes = 0;
-				}
-			}
-			if (ix >= NDR_STRING_MAX) {
-				NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
-				return (0);
-			}
-			size_is = ix+1;
-		}
-
-		first_is = 0;
-
-		if (nds->flags & NDS_F_NOTERM)
-			length_is = size_is - 1;
-		else
-			length_is = size_is;
-
-		if (!ndr_outer_poke_sizing(outer_ref, 0, &size_is) ||
-		    !ndr_outer_poke_sizing(outer_ref, 4, &first_is) ||
-		    !ndr_outer_poke_sizing(outer_ref, 8, &length_is))
-			return (0);		/* error already set */
-		break;
-
-	case NDR_M_OP_UNMARSHALL:
-		if (!ndr_outer_peek_sizing(outer_ref, 0, &size_is) ||
-		    !ndr_outer_peek_sizing(outer_ref, 4, &first_is) ||
-		    !ndr_outer_peek_sizing(outer_ref, 8, &length_is))
-			return (0);		/* error already set */
-
-		/*
-		 * In addition to the first_is check, we used to check that
-		 * size_is or size_is-1 was equal to length_is but Windows95
-		 * doesn't conform to this "rule" (see variable part below).
-		 * The srvmgr tool for Windows95 sent the following values
-		 * for a path string:
-		 *
-		 *	size_is   = 261 (0x105)
-		 *	first_is  = 0
-		 *	length_is = 53  (0x35)
-		 *
-		 * The length_is was correct (for the given path) but the
-		 * size_is was the maximum path length rather than being
-		 * related to length_is.
-		 */
-		if (first_is != 0) {
-			NDR_SET_ERROR(outer_ref, NDR_ERR_STRING_SIZING);
-			return (0);
-		}
-
-		if (ti == &ndt_s_wchar) {
-			/*
-			 * Decoding Unicode to UTF-8; we need to allow
-			 * for the maximum possible char size. It would
-			 * be nice to use mbequiv_strlen but the string
-			 * may not be null terminated.
-			 */
-			n_alloc = (size_is + 1) * MTS_MB_CHAR_MAX;
-		} else {
-			n_alloc = (size_is + 1) * is_varlen;
-		}
-
-		valp = NDS_MALLOC(nds, n_alloc, outer_ref);
-		if (!valp) {
-			NDR_SET_ERROR(outer_ref, NDR_ERR_MALLOC_FAILED);
-			return (0);
-		}
-
-		bzero(valp, (size_is+1) * is_varlen);
-
-		if (outer_ref->backptr)
-			*outer_ref->backptr = valp;
-		outer_ref->datum = valp;
-		break;
-
-	default:
-		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
-		return (0);
-	}
-
-	/*
-	 * Variable part - exactly length_is of these.
-	 *
-	 * Usually, length_is is same as size_is and includes nul.
-	 * Some protocols use length_is = size_is-1, and length_is does
-	 * not include the nul (which is more consistent with DCE spec).
-	 * If the length_is is 0, there is no data following the
-	 * sizing header, regardless of size_is.
-	 */
-	n_variable = length_is * is_varlen;
-
-	/* sum them up to determine the PDU space required */
-	n_pdu_total = n_hdr + n_fixed + n_variable;
-
-	/* similar sum to determine how much local memory is required */
-	n_alloc = n_fixed + n_variable;
-
-	rc = ndr_outer_grow(outer_ref, n_pdu_total);
-	if (!rc)
-		return (rc);		/* error already set */
-
-	if (length_is > 0) {
-		bzero(&myref, sizeof (myref));
-		myref.stream = nds;
-		myref.enclosing = outer_ref;
-		myref.ti = outer_ref->ti;
-		myref.datum = outer_ref->datum;
-		myref.name = "OUTER-STRING";
-		myref.outer_flags = NDR_F_IS_STRING;
-		myref.inner_flags = NDR_F_NONE;
-
-		/*
-		 * Set up size_is and strlen_is for ndr_s_wchar.
-		 */
-		myref.size_is = size_is;
-		myref.strlen_is = length_is;
-	}
-
-	myref.pdu_offset = outer_ref->pdu_offset + 12;
-
-	/*
-	 * Don't try to decode empty strings.
-	 */
-	if ((size_is == 0) && (first_is == 0) && (length_is == 0)) {
-		nds->pdu_scan_offset = outer_ref->pdu_end_offset;
-		return (1);
-	}
-
-	if ((size_is != 0) && (length_is != 0)) {
-		rc = ndr_inner(&myref);
-		if (!rc)
-			return (rc);		/* error already set */
-	}
-
-	nds->pdu_scan_offset = outer_ref->pdu_end_offset;
-	return (1);
-}
-
-int
-ndr_outer_peek_sizing(ndr_ref_t *outer_ref, unsigned offset,
-    unsigned long *sizing_p)
-{
-	ndr_stream_t 	*nds = outer_ref->stream;
-	unsigned long	pdu_offset;
-	int		rc;
-
-	pdu_offset = outer_ref->pdu_offset + offset;
-
-	if (pdu_offset < nds->outer_current->pdu_offset ||
-	    pdu_offset > nds->outer_current->pdu_end_offset ||
-	    pdu_offset+4 > nds->outer_current->pdu_end_offset) {
-		NDR_SET_ERROR(outer_ref, NDR_ERR_BOUNDS_CHECK);
-		return (0);
-	}
-
-	switch (nds->m_op) {
-	case NDR_M_OP_MARSHALL:
-		NDR_SET_ERROR(outer_ref, NDR_ERR_UNIMPLEMENTED);
-		return (0);
-
-	case NDR_M_OP_UNMARSHALL:
-		rc = NDS_GET_PDU(nds, pdu_offset, 4, (char *)sizing_p,
-		    nds->swap, outer_ref);
-		break;
-
-	default:
-		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
-		return (0);
-	}
-
-	return (rc);
-}
-
-int
-ndr_outer_poke_sizing(ndr_ref_t *outer_ref, unsigned offset,
-    unsigned long *sizing_p)
-{
-	ndr_stream_t 	*nds = outer_ref->stream;
-	unsigned long	pdu_offset;
-	int		rc;
-
-	pdu_offset = outer_ref->pdu_offset + offset;
-
-	if (pdu_offset < nds->outer_current->pdu_offset ||
-	    pdu_offset > nds->outer_current->pdu_end_offset ||
-	    pdu_offset+4 > nds->outer_current->pdu_end_offset) {
-		NDR_SET_ERROR(outer_ref, NDR_ERR_BOUNDS_CHECK);
-		return (0);
-	}
-
-	switch (nds->m_op) {
-	case NDR_M_OP_MARSHALL:
-		rc = NDS_PUT_PDU(nds, pdu_offset, 4, (char *)sizing_p,
-		    nds->swap, outer_ref);
-		break;
-
-	case NDR_M_OP_UNMARSHALL:
-		NDR_SET_ERROR(outer_ref, NDR_ERR_UNIMPLEMENTED);
-		return (0);
-
-	default:
-		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
-		return (0);
-	}
-
-	return (rc);
-}
-
-/*
- * All OUTER constructs begin on a mod4 (dword) boundary - except
- * for the ones that don't: some MSRPC calls appear to use word or
- * packed alignment.  Strings appear to be dword aligned.
- */
-int
-ndr_outer_align(ndr_ref_t *outer_ref)
-{
-	ndr_stream_t 	*nds = outer_ref->stream;
-	int		rc;
-	unsigned	n_pad;
-	unsigned	align;
-
-	if (outer_ref->packed_alignment && outer_ref->ti != &ndt_s_wchar) {
-		align = outer_ref->ti->alignment;
-		n_pad = ((align + 1) - nds->pdu_scan_offset) & align;
-	} else {
-		n_pad = NDR_ALIGN4(nds->pdu_scan_offset);
-	}
-
-	if (n_pad == 0)
-		return (1);	/* already aligned, often the case */
-
-	if (!ndr_outer_grow(outer_ref, n_pad))
-		return (0);	/* error already set */
-
-	switch (nds->m_op) {
-	case NDR_M_OP_MARSHALL:
-		rc = NDS_PAD_PDU(nds, nds->pdu_scan_offset, n_pad, outer_ref);
-		if (!rc) {
-			NDR_SET_ERROR(outer_ref, NDR_ERR_PAD_FAILED);
-			return (0);
-		}
-		break;
-
-	case NDR_M_OP_UNMARSHALL:
-		break;
-
-	default:
-		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
-		return (0);
-	}
-
-	nds->pdu_scan_offset += n_pad;
-	return (1);
-}
-
-int
-ndr_outer_grow(ndr_ref_t *outer_ref, unsigned n_total)
-{
-	ndr_stream_t 	*nds = outer_ref->stream;
-	unsigned long	pdu_want_size;
-	int		rc, is_ok = 0;
-
-	pdu_want_size = nds->pdu_scan_offset + n_total;
-
-	if (pdu_want_size <= nds->pdu_max_size) {
-		is_ok = 1;
-	}
-
-	switch (nds->m_op) {
-	case NDR_M_OP_MARSHALL:
-		if (is_ok)
-			break;
-		rc = NDS_GROW_PDU(nds, pdu_want_size, outer_ref);
-		if (!rc) {
-			NDR_SET_ERROR(outer_ref, NDR_ERR_GROW_FAILED);
-			return (0);
-		}
-		break;
-
-	case NDR_M_OP_UNMARSHALL:
-		if (is_ok)
-			break;
-		NDR_SET_ERROR(outer_ref, NDR_ERR_UNDERFLOW);
-		return (0);
-
-	default:
-		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
-		return (0);
-	}
-
-	if (nds->pdu_size < pdu_want_size)
-		nds->pdu_size = pdu_want_size;
-
-	outer_ref->pdu_end_offset = pdu_want_size;
-	return (1);
-}
-
-/*
- * INNER ELEMENTS
- *
- * The local datum (arg_ref->datum) already exists, there is no need to
- * malloc() it.  The datum should point at a member of a structure.
- *
- * For the most part, ndr_inner() and its helpers are just a sanity
- * check.  The underlying ti->ndr_func() could be called immediately
- * for non-pointer elements.  For the sake of robustness, we detect
- * run-time errors here.  Most of the situations this protects against
- * have already been checked by the IDL compiler.  This is also a
- * common point for processing of all data, and so is a convenient
- * place to work from for debugging.
- */
-int
-ndr_inner(ndr_ref_t *arg_ref)
-{
-	ndr_typeinfo_t 	*ti = arg_ref->ti;
-	int	is_varlen = ti->pdu_size_variable_part;
-	int	is_union = NDR_IS_UNION(ti);
-	int	error = NDR_ERR_INNER_PARAMS_BAD;
-	int	params;
-
-	params = arg_ref->inner_flags & NDR_F_PARAMS_MASK;
-
-	switch (params) {
-	case NDR_F_NONE:
-		if (is_union) {
-			error = NDR_ERR_SWITCH_VALUE_MISSING;
-			break;
-		}
-		return (*ti->ndr_func)(arg_ref);
-
-	case NDR_F_SIZE_IS:
-	case NDR_F_DIMENSION_IS:
-	case NDR_F_IS_POINTER+NDR_F_SIZE_IS:   /* pointer to something */
-	case NDR_F_IS_REFERENCE+NDR_F_SIZE_IS: /* pointer to something */
-		if (is_varlen) {
-			error = NDR_ERR_ARRAY_VARLEN_ILLEGAL;
-			break;
-		}
-		if (is_union) {
-			error = NDR_ERR_ARRAY_UNION_ILLEGAL;
-			break;
-		}
-		if (params & NDR_F_IS_POINTER)
-			return (ndr_inner_pointer(arg_ref));
-		else if (params & NDR_F_IS_REFERENCE)
-			return (ndr_inner_reference(arg_ref));
-		else
-			return (ndr_inner_array(arg_ref));
-
-	case NDR_F_IS_POINTER:	/* type is pointer to one something */
-		if (is_union) {
-			error = NDR_ERR_ARRAY_UNION_ILLEGAL;
-			break;
-		}
-		return (ndr_inner_pointer(arg_ref));
-
-	case NDR_F_IS_REFERENCE:	/* type is pointer to one something */
-		if (is_union) {
-			error = NDR_ERR_ARRAY_UNION_ILLEGAL;
-			break;
-		}
-		return (ndr_inner_reference(arg_ref));
-
-	case NDR_F_SWITCH_IS:
-		if (!is_union) {
-			error = NDR_ERR_SWITCH_VALUE_ILLEGAL;
-			break;
-		}
-		return (*ti->ndr_func)(arg_ref);
-
-	default:
-		error = NDR_ERR_INNER_PARAMS_BAD;
-		break;
-	}
-
-	/*
-	 * If we get here, something is wrong. Most likely,
-	 * the params flags do not match
-	 */
-	NDR_SET_ERROR(arg_ref, error);
-	return (0);
-}
-
-int
-ndr_inner_pointer(ndr_ref_t *arg_ref)
-{
-	ndr_stream_t	*nds = arg_ref->stream;
-	/*LINTED E_BAD_PTR_CAST_ALIGN*/
-	char 		**valpp = (char **)arg_ref->datum;
-	ndr_ref_t 	*outer_ref;
-
-	if (!ndr__ulong(arg_ref))
-		return (0);	/* error */
-	if (!*valpp)
-		return (1);	/* NULL pointer */
-
-	outer_ref = ndr_enter_outer_queue(arg_ref);
-	if (!outer_ref)
-		return (0);	/* error already set */
-
-	/*
-	 * Move advice in inner_flags to outer_flags.
-	 * Retain pointer flag for conformant arrays.
-	 */
-	outer_ref->outer_flags = arg_ref->inner_flags & NDR_F_PARAMS_MASK;
-	if ((outer_ref->outer_flags & NDR_F_SIZE_IS) == 0)
-		outer_ref->outer_flags &= ~NDR_F_IS_POINTER;
-#ifdef NDR_INNER_PTR_NOT_YET
-	outer_ref->outer_flags |= NDR_F_BACKPTR;
-	if (outer_ref->outer_flags & NDR_F_SIZE_IS) {
-		outer_ref->outer_flags |= NDR_F_ARRAY+NDR_F_CONFORMANT;
-	}
-#endif /* NDR_INNER_PTR_NOT_YET */
-
-	outer_ref->backptr = valpp;
-
-	switch (nds->m_op) {
-	case NDR_M_OP_MARSHALL:
-		outer_ref->datum = *valpp;
-		break;
-
-	case NDR_M_OP_UNMARSHALL:
-		/*
-		 * This is probably wrong if the application allocated
-		 * memory in advance.  Indicate no value for now.
-		 * ONC RPC handles this case.
-		 */
-		*valpp = 0;
-		outer_ref->datum = 0;
-		break;
-	}
-
-	return (1);		/* pointer dereference scheduled */
-}
-
-int
-ndr_inner_reference(ndr_ref_t *arg_ref)
-{
-	ndr_stream_t	*nds = arg_ref->stream;
-	/*LINTED E_BAD_PTR_CAST_ALIGN*/
-	char		**valpp = (char **)arg_ref->datum;
-	ndr_ref_t	*outer_ref;
-
-	outer_ref = ndr_enter_outer_queue(arg_ref);
-	if (!outer_ref)
-		return (0);	/* error already set */
-
-	/*
-	 * Move advice in inner_flags to outer_flags.
-	 * Retain reference flag for conformant arrays.
-	 */
-	outer_ref->outer_flags = arg_ref->inner_flags & NDR_F_PARAMS_MASK;
-	if ((outer_ref->outer_flags & NDR_F_SIZE_IS) == 0)
-		outer_ref->outer_flags &= ~NDR_F_IS_REFERENCE;
-#ifdef NDR_INNER_REF_NOT_YET
-	outer_ref->outer_flags |= NDR_F_BACKPTR;
-	if (outer_ref->outer_flags & NDR_F_SIZE_IS) {
-		outer_ref->outer_flags |= NDR_F_ARRAY+NDR_F_CONFORMANT;
-	}
-#endif /* NDR_INNER_REF_NOT_YET */
-
-	outer_ref->backptr = valpp;
-
-	switch (nds->m_op) {
-	case NDR_M_OP_MARSHALL:
-		outer_ref->datum = *valpp;
-		break;
-
-	case NDR_M_OP_UNMARSHALL:
-		/*
-		 * This is probably wrong if the application allocated
-		 * memory in advance.  Indicate no value for now.
-		 * ONC RPC handles this case.
-		 */
-		*valpp = 0;
-		outer_ref->datum = 0;
-		break;
-	}
-
-	return (1);		/* pointer dereference scheduled */
-}
-
-int
-ndr_inner_array(ndr_ref_t *encl_ref)
-{
-	ndr_typeinfo_t		*ti = encl_ref->ti;
-	ndr_ref_t		myref;
-	unsigned long		pdu_offset = encl_ref->pdu_offset;
-	unsigned long		n_elem;
-	unsigned long		i;
-	char			name[30];
-
-	if (encl_ref->inner_flags & NDR_F_SIZE_IS) {
-		/* now is the time to check/set size */
-		if (!ndr_size_is(encl_ref))
-			return (0);	/* error already set */
-		n_elem = encl_ref->size_is;
-	} else {
-		assert(encl_ref->inner_flags & NDR_F_DIMENSION_IS);
-		n_elem = encl_ref->dimension_is;
-	}
-
-	bzero(&myref, sizeof (myref));
-	myref.enclosing = encl_ref;
-	myref.stream = encl_ref->stream;
-	myref.packed_alignment = 0;
-	myref.ti = ti;
-	myref.inner_flags = NDR_F_NONE;
-
-	for (i = 0; i < n_elem; i++) {
-		(void) sprintf(name, "[%lu]", i);
-		myref.name = name;
-		myref.pdu_offset = pdu_offset + i * ti->pdu_size_fixed_part;
-		myref.datum = encl_ref->datum + i * ti->c_size_fixed_part;
-
-		if (!ndr_inner(&myref))
-			return (0);
-	}
-
-	return (1);
-}
-
-
-/*
- * BASIC TYPES
- */
-#define	MAKE_BASIC_TYPE_BASE(TYPE, SIZE) \
-    extern int ndr_##TYPE(struct ndr_reference *encl_ref); \
-    ndr_typeinfo_t ndt_##TYPE = { \
-	1,		/* NDR version */ \
-	(SIZE)-1,	/* alignment */ \
-	NDR_F_NONE,	/* flags */ \
-	ndr_##TYPE,	/* ndr_func */ \
-	SIZE,		/* pdu_size_fixed_part */ \
-	0,		/* pdu_size_variable_part */ \
-	SIZE,		/* c_size_fixed_part */ \
-	0,		/* c_size_variable_part */ \
-	}; \
-    int ndr_##TYPE(struct ndr_reference *ref) { \
-	return (ndr_basic_integer(ref, SIZE)); \
-}
-
-#define	MAKE_BASIC_TYPE_STRING(TYPE, SIZE) \
-    extern int ndr_s##TYPE(struct ndr_reference *encl_ref); \
-    ndr_typeinfo_t ndt_s##TYPE = { \
-	1,		/* NDR version */ \
-	(SIZE)-1,	/* alignment */ \
-	NDR_F_STRING,	/* flags */ \
-	ndr_s##TYPE,	/* ndr_func */ \
-	0,		/* pdu_size_fixed_part */ \
-	SIZE,		/* pdu_size_variable_part */ \
-	0,		/* c_size_fixed_part */ \
-	SIZE,		/* c_size_variable_part */ \
-	}; \
-    int ndr_s##TYPE(struct ndr_reference *ref) { \
-	return (ndr_string_basic_integer(ref, &ndt_##TYPE)); \
-}
-
-#define	MAKE_BASIC_TYPE(TYPE, SIZE) \
-	MAKE_BASIC_TYPE_BASE(TYPE, SIZE) \
-	MAKE_BASIC_TYPE_STRING(TYPE, SIZE)
-
-int ndr_basic_integer(ndr_ref_t *, unsigned);
-int ndr_string_basic_integer(ndr_ref_t *, ndr_typeinfo_t *);
-
-
-MAKE_BASIC_TYPE(_char, 1)
-MAKE_BASIC_TYPE(_uchar, 1)
-MAKE_BASIC_TYPE(_short, 2)
-MAKE_BASIC_TYPE(_ushort, 2)
-MAKE_BASIC_TYPE(_long, 4)
-MAKE_BASIC_TYPE(_ulong, 4)
-
-MAKE_BASIC_TYPE_BASE(_wchar, 2)
-
-int
-ndr_basic_integer(ndr_ref_t *ref, unsigned size)
-{
-	ndr_stream_t 	*nds = ref->stream;
-	char 		*valp = (char *)ref->datum;
-	int		rc;
-
-	switch (nds->m_op) {
-	case NDR_M_OP_MARSHALL:
-		rc = NDS_PUT_PDU(nds, ref->pdu_offset, size,
-		    valp, nds->swap, ref);
-		break;
-
-	case NDR_M_OP_UNMARSHALL:
-		rc = NDS_GET_PDU(nds, ref->pdu_offset, size,
-		    valp, nds->swap, ref);
-		break;
-
-	default:
-		NDR_SET_ERROR(ref, NDR_ERR_M_OP_INVALID);
-		return (0);
-	}
-
-	return (rc);
-}
-
-int
-ndr_string_basic_integer(ndr_ref_t *encl_ref, ndr_typeinfo_t *type_under)
-{
-	unsigned long		pdu_offset = encl_ref->pdu_offset;
-	unsigned		size = type_under->pdu_size_fixed_part;
-	char			*valp;
-	ndr_ref_t		myref;
-	unsigned long		i;
-	long			sense = 0;
-	char			name[30];
-
-	assert(size != 0);
-
-	bzero(&myref, sizeof (myref));
-	myref.enclosing = encl_ref;
-	myref.stream = encl_ref->stream;
-	myref.packed_alignment = 0;
-	myref.ti = type_under;
-	myref.inner_flags = NDR_F_NONE;
-	myref.name = name;
-
-	for (i = 0; i < NDR_STRING_MAX; i++) {
-		(void) sprintf(name, "[%lu]", i);
-		myref.pdu_offset = pdu_offset + i * size;
-		valp = encl_ref->datum + i * size;
-		myref.datum = valp;
-
-		if (!ndr_inner(&myref))
-			return (0);
-
-		switch (size) {
-		case 1:		sense = *valp; break;
-		/*LINTED E_BAD_PTR_CAST_ALIGN*/
-		case 2:		sense = *(short *)valp; break;
-		/*LINTED E_BAD_PTR_CAST_ALIGN*/
-		case 4:		sense = *(long *)valp; break;
-		}
-
-		if (!sense)
-			break;
-	}
-
-	return (1);
-}
-
-
-extern int ndr_s_wchar(ndr_ref_t *encl_ref);
-ndr_typeinfo_t ndt_s_wchar = {
-	1,		/* NDR version */
-	2-1,		/* alignment */
-	NDR_F_STRING,	/* flags */
-	ndr_s_wchar,	/* ndr_func */
-	0,		/* pdu_size_fixed_part */
-	2,		/* pdu_size_variable_part */
-	0,		/* c_size_fixed_part */
-	1,		/* c_size_variable_part */
-};
-
-
-/*
- * Hand coded wchar function because all strings are transported
- * as wide characters. During NDR_M_OP_MARSHALL, we convert from
- * multi-byte to wide characters. During NDR_M_OP_UNMARSHALL, we
- * convert from wide characters to multi-byte.
- *
- * It appeared that NT would sometimes leave a spurious character
- * in the data stream before the null wide_char, which would get
- * included in the string decode because we processed until the
- * null character. It now looks like NT does not always terminate
- * RPC Unicode strings and the terminating null is a side effect
- * of field alignment. So now we rely on the strlen_is (set up in
- * ndr_outer_string) of the enclosing reference. This may or may
- * not include the null but it doesn't matter, the algorithm will
- * get it right.
- */
-int
-ndr_s_wchar(ndr_ref_t *encl_ref)
-{
-	ndr_stream_t		*nds = encl_ref->stream;
-	unsigned short		wide_char;
-	char 			*valp;
-	ndr_ref_t		myref;
-	unsigned long		i;
-	char			name[30];
-	int			count;
-	int			char_count = 0;
-
-	if (nds->m_op == NDR_M_OP_UNMARSHALL) {
-		/*
-		 * To avoid problems with zero length strings
-		 * we can just null terminate here and be done.
-		 */
-		if (encl_ref->strlen_is == 0) {
-			encl_ref->datum[0] = '\0';
-			return (1);
-		}
-	}
-
-	bzero(&myref, sizeof (myref));
-	myref.enclosing = encl_ref;
-	myref.stream = encl_ref->stream;
-	myref.packed_alignment = 0;
-	myref.ti = &ndt__wchar;
-	myref.inner_flags = NDR_F_NONE;
-	myref.datum = (char *)&wide_char;
-	myref.name = name;
-	myref.pdu_offset = encl_ref->pdu_offset;
-
-	valp = encl_ref->datum;
-	count = 0;
-
-	for (i = 0; i < NDR_STRING_MAX; i++) {
-		(void) sprintf(name, "[%lu]", i);
-
-		if (nds->m_op == NDR_M_OP_MARSHALL) {
-			count = smb_mbtowc((smb_wchar_t *)&wide_char, valp,
-			    MTS_MB_CHAR_MAX);
-			if (count < 0) {
-				return (0);
-			} else if (count == 0) {
-				if (encl_ref->strlen_is != encl_ref->size_is)
-					break;
-
-				/*
-				 * If the input char is 0, mbtowc
-				 * returns 0 without setting wide_char.
-				 * Set wide_char to 0 and a count of 1.
-				 */
-				wide_char = *valp;
-				count = 1;
-			}
-		}
-
-		if (!ndr_inner(&myref))
-			return (0);
-
-		if (nds->m_op == NDR_M_OP_UNMARSHALL) {
-			count = smb_wctomb(valp, wide_char);
-
-			if ((++char_count) == encl_ref->strlen_is) {
-				valp += count;
-				*valp = '\0';
-				break;
-			}
-		}
-
-		if (!wide_char)
-			break;
-
-		myref.pdu_offset += sizeof (wide_char);
-		valp += count;
-	}
-
-	return (1);
-}
-
-/*
- * Converts a multibyte character string to a little-endian, wide-char
- * string.  No more than nwchars wide characters are stored.
- * A terminating null wide character is appended if there is room.
- *
- * Returns the number of wide characters converted, not counting
- * any terminating null wide character.  Returns -1 if an invalid
- * multibyte character is encountered.
- */
-size_t
-ndr_mbstowcs(ndr_stream_t *nds, smb_wchar_t *wcs, const char *mbs,
-    size_t nwchars)
-{
-	smb_wchar_t *start = wcs;
-	int nbytes;
-
-	while (nwchars--) {
-		nbytes = ndr_mbtowc(nds, wcs, mbs, MTS_MB_CHAR_MAX);
-		if (nbytes < 0) {
-			*wcs = 0;
-			return ((size_t)-1);
-		}
-
-		if (*mbs == 0)
-			break;
-
-		++wcs;
-		mbs += nbytes;
-	}
-
-	return (wcs - start);
-}
-
-/*
- * Converts a multibyte character to a little-endian, wide-char, which
- * is stored in wcharp.  Up to nbytes bytes are examined.
- *
- * If mbchar is valid, returns the number of bytes processed in mbchar.
- * If mbchar is invalid, returns -1.  See also smb_mbtowc().
- */
-/*ARGSUSED*/
-int
-ndr_mbtowc(ndr_stream_t *nds, smb_wchar_t *wcharp, const char *mbchar,
-    size_t nbytes)
-{
-	int rc;
-
-	if ((rc = smb_mbtowc(wcharp, mbchar, nbytes)) < 0)
-		return (rc);
-
-#ifdef _BIG_ENDIAN
-	if (nds == NULL || NDR_MODE_MATCH(nds, NDR_MODE_RETURN_SEND))
-		*wcharp = BSWAP_16(*wcharp);
-#endif
-
-	return (rc);
-}
--- /dev/null	Sun Mar 18 01:13:16 2018
+++ new/usr/src/lib/libmlrpc/common/ndr_process.c	Sun Mar 18 01:13:16 2018
@@ -0,0 +1,2021 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ * Copyright 2012 Milan Jurik. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+/*
+ * Network Data Representation (NDR) is a compatible subset of the DCE RPC
+ * and MSRPC NDR.  NDR is used to move parameters consisting of
+ * complicated trees of data constructs between an RPC client and server.
+ */
+
+#include <sys/byteorder.h>
+#include <strings.h>
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <libmlrpc.h>
+#include <ndr_wchar.h>
+
+#define	NDR_IS_UNION(T)	\
+	(((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_UNION)
+#define	NDR_IS_STRING(T)	\
+	(((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_STRING)
+
+extern ndr_typeinfo_t ndt_s_wchar;
+
+/*
+ * The following synopsis describes the terms TOP-MOST, OUTER and INNER.
+ *
+ * Each parameter (call arguments and return values) is a TOP-MOST item.
+ * A TOP-MOST item consists of one or more OUTER items.  An OUTER item
+ * consists of one or more INNER items.  There are important differences
+ * between each kind, which, primarily, have to do with the allocation
+ * of memory to contain data structures and the order of processing.
+ *
+ * This is most easily demonstrated with a short example.
+ * Consider these structures:
+ *
+ *	struct top_param {
+ *		long		level;
+ *		struct list *	head;
+ *		long		count;
+ *	};
+ *
+ *	struct list {
+ *		struct list *	next;
+ *		char *		str; // a string
+ *	};
+ *
+ * Now, consider an instance tree like this:
+ *
+ *	+---------+       +-------+       +-------+
+ *	|top_param|  +--->|list #1|  +--->|list #2|
+ *	+---------+  |    +-------+  |    +-------+
+ *	| level   |  |    | next ----+    | next --->(NULL)
+ *	| head   ----+    | str  -->"foo" | str  -->"bar"
+ *	| count   |       | flag  |       | flag  |
+ *	+---------+       +-------+       +-------+
+ *
+ * The DCE(MS)/RPC Stub Data encoding for the tree is the following.
+ * The vertical bars (|) indicate OUTER construct boundaries.
+ *
+ *   +-----+----------------------+----------------------+-----+-----+-----+
+ *   |level|#1.next #1.str #1.flag|#2.next #2.str #2.flag|"bar"|"foo"|count|
+ *   +-----+----------------------+----------------------+-----+-----+-----+
+ *   level |<----------------------- head -------------------------->|count
+ *   TOP    TOP                                                       TOP
+ *
+ * Here's what to notice:
+ *
+ * - The members of the TOP-MOST construct are scattered through the Stub
+ *   Data in the order they occur.  This example shows a TOP-MOST construct
+ *   consisting of atomic types (pointers and integers).  A construct
+ *   (struct) within the TOP-MOST construct would be contiguous and not
+ *   scattered.
+ *
+ * - The members of OUTER constructs are contiguous, which allows for
+ *   non-copied relocated (fixed-up) data structures at the packet's
+ *   destination.  We don't do fix-ups here.  The pointers within the
+ *   OUTER constructs are processed depth-first in the order that they
+ *   occur.  If they were processed breadth first, the sequence would
+ *   be #1,"foo",#2,"bar".  This is tricky because OUTER constructs may
+ *   be variable length, and pointers are often encountered before the
+ *   size(s) is known.
+ *
+ * - The INNER constructs are simply the members of an OUTER construct.
+ *
+ * For comparison, consider how ONC RPC would handle the same tree of
+ * data.  ONC requires very little buffering, while DCE requires enough
+ * buffer space for the entire message.  ONC does atom-by-atom depth-first
+ * (de)serialization and copy, while DCE allows for constructs to be
+ * "fixed-up" (relocated) in place at the destination.  The packet data
+ * for the same tree processed by ONC RPC would look like this:
+ *
+ *   +---------------------------------------------------------------------+
+ *   |level #1.next #2.next #2.str "bar" #2.flag #1.str "foo" #1.flag count|
+ *   +---------------------------------------------------------------------+
+ *   TOP    #1      #2      #2     bar   #2      #1     foo   #1      TOP
+ *
+ * More details about each TOP-MOST, OUTER, and INNER constructs appear
+ * throughout this source file near where such constructs are processed.
+ *
+ * NDR_REFERENCE
+ *
+ * The primary object for NDR is the ndr_ref_t.
+ *
+ * An ndr reference indicates the local datum (i.e. native "C" data
+ * format), and the element within the Stub Data (contained within the
+ * RPC PDU (protocol data unit).  An ndr reference also indicates,
+ * largely as a debugging aid, something about the type of the
+ * element/datum, and the enclosing construct for the element. The
+ * ndr reference's are typically allocated on the stack as locals,
+ * and the chain of ndr-reference.enclosing references is in reverse
+ * order of the call graph.
+ *
+ * The ndr-reference.datum is a pointer to the local memory that
+ * contains/receives the value. The ndr-reference.pdu_offset indicates
+ * where in the Stub Data the value is to be stored/retrieved.
+ *
+ * The ndr-reference also contains various parameters to the NDR
+ * process, such as ndr-reference.size_is, which indicates the size
+ * of variable length data, or ndr-reference.switch_is, which
+ * indicates the arm of a union to use.
+ *
+ * QUEUE OF OUTER REFERENCES
+ *
+ * Some OUTER constructs are variable size.  Sometimes (often) we don't
+ * know the size of the OUTER construct until after pointers have been
+ * encountered. Hence, we can not begin processing the referent of the
+ * pointer until after the referring OUTER construct is completely
+ * processed, i.e. we don't know where to find/put the referent in the
+ * Stub Data until we know the size of all its predecessors.
+ *
+ * This is managed using the queue of OUTER references.  The queue is
+ * anchored in ndr_stream.outer_queue_head.  At any time,
+ * ndr_stream.outer_queue_tailp indicates where to put the
+ * ndr-reference for the next encountered pointer.
+ *
+ * Refer to the example above as we illustrate the queue here.  In these
+ * illustrations, the queue entries are not the data structures themselves.
+ * Rather, they are ndr-reference entries which **refer** to the data
+ * structures in both the PDU and local memory.
+ *
+ * During some point in the processing, the queue looks like this:
+ *
+ *   outer_current -------v
+ *   outer_queue_head --> list#1 --0
+ *   outer_queue_tailp ---------&
+ *
+ * When the pointer #1.next is encountered, and entry is added to the
+ * queue,
+ *
+ *   outer_current -------v
+ *   outer_queue_head --> list#1 --> list#2 --0
+ *   outer_queue_tailp --------------------&
+ *
+ * and the members of #1 continue to be processed, which encounters
+ * #1.str:
+ *
+ *   outer_current -------v
+ *   outer_queue_head --> list#1 --> list#2 --> "foo" --0
+ *   outer_queue_tailp ------------------------------&
+ *
+ * Upon the completion of list#1, the processing continues by moving to
+ * ndr_stream.outer_current->next, and the tail is set to this outer member:
+ *
+ *   outer_current ------------------v
+ *   outer_queue_head --> list#1 --> list#2 --> "foo" --0
+ *   outer_queue_tailp --------------------&
+ *
+ * Space for list#2 is allocated, either in the Stub Data or of local
+ * memory.  When #2.next is encountered, it is found to be the null
+ * pointer and no reference is added to the queue.  When #2.str is
+ * encountered, it is found to be valid, and a reference is added:
+ *
+ *   outer_current ------------------v
+ *   outer_queue_head --> list#1 --> list#2 --> "bar" --> "foo" --0
+ *   outer_queue_tailp ------------------------------&
+ *
+ * Processing continues in a similar fashion with the string "bar",
+ * which is variable-length.  At this point, memory for "bar" may be
+ * malloc()ed during NDR_M_OP_UNMARSHALL:
+ *
+ *   outer_current -----------------------------v
+ *   outer_queue_head --> list#1 --> list#2 --> "bar" --> "foo" --0
+ *   outer_queue_tailp ------------------------------&
+ *
+ * And finishes on string "foo".  Notice that because "bar" is a
+ * variable length string, and we don't know the PDU offset for "foo"
+ * until we reach this point.
+ *
+ * When the queue is drained (current->next==0), processing continues
+ * with the next TOP-MOST member.
+ *
+ * The queue of OUTER constructs manages the variable-length semantics
+ * of OUTER constructs and satisfies the depth-first requirement.
+ * We allow the queue to linger until the entire TOP-MOST structure is
+ * processed as an aid to debugging.
+ */
+
+static ndr_ref_t *ndr_enter_outer_queue(ndr_ref_t *);
+extern int ndr__ulong(ndr_ref_t *);
+
+/*
+ * TOP-MOST ELEMENTS
+ *
+ * This is fundamentally the first OUTER construct of the parameter,
+ * possibly followed by more OUTER constructs due to pointers.  The
+ * datum (local memory) for TOP-MOST constructs (structs) is allocated
+ * by the caller of NDR.
+ *
+ * After the element is transferred, the outer_queue is drained.
+ *
+ * All we have to do is add an entry to the outer_queue for this
+ * top-most member, and commence the outer_queue processing.
+ */
+int
+ndo_process(ndr_stream_t *nds, ndr_typeinfo_t *ti, char *datum)
+{
+	ndr_ref_t	myref;
+
+	bzero(&myref, sizeof (myref));
+	myref.stream = nds;
+	myref.datum = datum;
+	myref.name = "PROCESS";
+	myref.ti = ti;
+
+	return (ndr_topmost(&myref));
+}
+
+int
+ndo_operation(ndr_stream_t *nds, ndr_typeinfo_t *ti, int opnum, char *datum)
+{
+	ndr_ref_t	myref;
+
+	bzero(&myref, sizeof (myref));
+	myref.stream = nds;
+	myref.datum = datum;
+	myref.name = "OPERATION";
+	myref.ti = ti;
+	myref.inner_flags = NDR_F_SWITCH_IS;
+	myref.switch_is = opnum;
+
+	if (ti->type_flags != NDR_F_INTERFACE) {
+		NDR_SET_ERROR(&myref, NDR_ERR_NOT_AN_INTERFACE);
+		return (0);
+	}
+
+	return ((*ti->ndr_func)(&myref));
+}
+
+int
+ndr_params(ndr_ref_t *params_ref)
+{
+	ndr_typeinfo_t *ti = params_ref->ti;
+
+	if (ti->type_flags == NDR_F_OPERATION)
+		return (*ti->ndr_func) (params_ref);
+	else
+		return (ndr_topmost(params_ref));
+}
+
+int
+ndr_topmost(ndr_ref_t *top_ref)
+{
+	ndr_stream_t *nds;
+	ndr_typeinfo_t *ti;
+	ndr_ref_t *outer_ref = 0;
+	int	is_varlen;
+	int	is_string;
+	int	error;
+	int	rc;
+	unsigned n_fixed;
+	int	params;
+
+	assert(top_ref);
+	assert(top_ref->stream);
+	assert(top_ref->ti);
+
+	nds = top_ref->stream;
+	ti = top_ref->ti;
+
+	is_varlen = ti->pdu_size_variable_part;
+	is_string = NDR_IS_STRING(ti);
+
+	assert(nds->outer_queue_tailp && !*nds->outer_queue_tailp);
+	assert(!nds->outer_current);
+
+	params = top_ref->inner_flags & NDR_F_PARAMS_MASK;
+
+	switch (params) {
+	case NDR_F_NONE:
+	case NDR_F_SWITCH_IS:
+		if (is_string || is_varlen) {
+			error = NDR_ERR_TOPMOST_VARLEN_ILLEGAL;
+			NDR_SET_ERROR(outer_ref, error);
+			return (0);
+		}
+		n_fixed = ti->pdu_size_fixed_part;
+		break;
+
+	case NDR_F_SIZE_IS:
+		error = NDR_ERR_TOPMOST_VARLEN_ILLEGAL;
+		NDR_SET_ERROR(outer_ref, error);
+		return (0);
+
+	case NDR_F_DIMENSION_IS:
+		if (is_varlen) {
+			error = NDR_ERR_ARRAY_VARLEN_ILLEGAL;
+			NDR_SET_ERROR(outer_ref, error);
+			return (0);
+		}
+		n_fixed = ti->pdu_size_fixed_part * top_ref->dimension_is;
+		break;
+
+	case NDR_F_IS_POINTER:
+	case NDR_F_IS_POINTER+NDR_F_SIZE_IS:
+		n_fixed = 4;
+		break;
+
+	case NDR_F_IS_REFERENCE:
+	case NDR_F_IS_REFERENCE+NDR_F_SIZE_IS:
+		n_fixed = 0;
+		break;
+
+	default:
+		error = NDR_ERR_OUTER_PARAMS_BAD;
+		NDR_SET_ERROR(outer_ref, error);
+		return (0);
+	}
+
+	outer_ref = ndr_enter_outer_queue(top_ref);
+	if (!outer_ref)
+		return (0);	/* error already set */
+
+	/*
+	 * Hand-craft the first OUTER construct and directly call
+	 * ndr_inner(). Then, run the outer_queue. We do this
+	 * because ndr_outer() wants to malloc() memory for
+	 * the construct, and we already have the memory.
+	 */
+
+	/* move the flags, etc, around again, undoes enter_outer_queue() */
+	outer_ref->inner_flags = top_ref->inner_flags;
+	outer_ref->outer_flags = 0;
+	outer_ref->datum = top_ref->datum;
+
+	/* All outer constructs start on a mod4 (longword) boundary */
+	if (!ndr_outer_align(outer_ref))
+		return (0);		/* error already set */
+
+	/* Regardless of what it is, this is where it starts */
+	outer_ref->pdu_offset = nds->pdu_scan_offset;
+
+	rc = ndr_outer_grow(outer_ref, n_fixed);
+	if (!rc)
+		return (0);		/* error already set */
+
+	outer_ref->pdu_end_offset = outer_ref->pdu_offset + n_fixed;
+
+	/* set-up outer_current, as though run_outer_queue() was doing it */
+	nds->outer_current = outer_ref;
+	nds->outer_queue_tailp = &nds->outer_current->next;
+	nds->pdu_scan_offset = outer_ref->pdu_end_offset;
+
+	/* do the topmost member */
+	rc = ndr_inner(outer_ref);
+	if (!rc)
+		return (0);		/* error already set */
+
+	nds->pdu_scan_offset = outer_ref->pdu_end_offset;
+
+	/* advance, as though run_outer_queue() was doing it */
+	nds->outer_current = nds->outer_current->next;
+	return (ndr_run_outer_queue(nds));
+}
+
+static ndr_ref_t *
+ndr_enter_outer_queue(ndr_ref_t *arg_ref)
+{
+	ndr_stream_t	*nds = arg_ref->stream;
+	ndr_ref_t	*outer_ref;
+
+	/*LINTED E_BAD_PTR_CAST_ALIGN*/
+	outer_ref = (ndr_ref_t *)NDS_MALLOC(nds, sizeof (*outer_ref), arg_ref);
+	if (!outer_ref) {
+		NDR_SET_ERROR(arg_ref, NDR_ERR_MALLOC_FAILED);
+		return (0);
+	}
+
+	*outer_ref = *arg_ref;
+
+	/* move advice in inner_flags to outer_flags */
+	outer_ref->outer_flags = arg_ref->inner_flags & NDR_F_PARAMS_MASK;
+	outer_ref->inner_flags = 0;
+	outer_ref->enclosing = nds->outer_current;
+	outer_ref->backptr = 0;
+	outer_ref->datum = 0;
+
+	assert(nds->outer_queue_tailp);
+
+	outer_ref->next = *nds->outer_queue_tailp;
+	*nds->outer_queue_tailp = outer_ref;
+	nds->outer_queue_tailp = &outer_ref->next;
+	return (outer_ref);
+}
+
+int
+ndr_run_outer_queue(ndr_stream_t *nds)
+{
+	while (nds->outer_current) {
+		nds->outer_queue_tailp = &nds->outer_current->next;
+
+		if (!ndr_outer(nds->outer_current))
+			return (0);
+
+		nds->outer_current = nds->outer_current->next;
+	}
+
+	return (1);
+}
+
+/*
+ * OUTER CONSTRUCTS
+ *
+ * OUTER constructs are where the real work is, which stems from the
+ * variable-length potential.
+ *
+ * DCE(MS)/RPC VARIABLE LENGTH -- CONFORMANT, VARYING, VARYING/CONFORMANT
+ *
+ * DCE(MS)/RPC provides for three forms of variable length: CONFORMANT,
+ * VARYING, and VARYING/CONFORMANT.
+ *
+ * What makes this so tough is that the variable-length array may be well
+ * encapsulated within the outer construct.  Further, because DCE(MS)/RPC
+ * tries to keep the constructs contiguous in the data stream, the sizing
+ * information precedes the entire OUTER construct.  The sizing information
+ * must be used at the appropriate time, which can be after many, many,
+ * many fixed-length elements.  During IDL type analysis, we know in
+ * advance constructs that encapsulate variable-length constructs.  So,
+ * we know when we have a sizing header and when we don't.  The actual
+ * semantics of the header are largely deferred.
+ *
+ * Currently, VARYING constructs are not implemented but they are described
+ * here in case they have to be implemented in the future.  Similarly,
+ * DCE(MS)/RPC provides for multi-dimensional arrays, which are currently
+ * not implemented.  Only one-dimensional, variable-length arrays are
+ * supported.
+ *
+ * CONFORMANT CONSTRUCTS -- VARIABLE LENGTH ARRAYS START THE SHOW
+ *
+ * All variable-length values are arrays.  These arrays may be embedded
+ * well within another construct.  However, a variable-length construct
+ * may ONLY appear as the last member of an enclosing construct.  Example:
+ *
+ *	struct credentials {
+ *		ulong	uid, gid;
+ *		ulong	n_gids;
+ *	    [size_is(n_gids)]
+ *		ulong	gids[*];    // variable-length.
+ *	};
+ *
+ * CONFORMANT constructs have a dynamic size in local memory and in the
+ * PDU.  The CONFORMANT quality is indicated by the [size_is()] advice.
+ * CONFORMANT constructs have the following header:
+ *
+ *	struct conformant_header {
+ *		ulong		size_is;
+ *	};
+ *
+ * (Multi-dimensional CONFORMANT arrays have a similar header for each
+ * dimension - not implemented).
+ *
+ * Example CONFORMANT construct:
+ *
+ *	struct user {
+ *		char *			name;
+ *		struct credentials	cred;	// see above
+ *	};
+ *
+ * Consider the data tree:
+ *
+ *    +--------+
+ *    |  user  |
+ *    +--------+
+ *    | name  ----> "fred" (the string is a different OUTER)
+ *    | uid    |
+ *    | gid    |
+ *    | n_gids |    for example, 3
+ *    | gids[0]|
+ *    | gids[1]|
+ *    | gids[2]|
+ *    +--------+
+ *
+ * The OUTER construct in the Stub Data would be:
+ *
+ *    +---+---------+---------------------------------------------+
+ *    |pad|size_is=3 name uid gid n_gids=3 gids[0] gids[1] gids[2]|
+ *    +---+---------+---------------------------------------------+
+ *         szing hdr|user |<-------------- user.cred ------------>|
+ *                  |<--- fixed-size ---->|<----- conformant ---->|
+ *
+ * The ndr_typeinfo for struct user will have:
+ *	pdu_fixed_size_part = 16	four long words (name uid gid n_gids)
+ *	pdu_variable_size_part = 4	per element, sizeof gids[0]
+ *
+ * VARYING CONSTRUCTS -- NOT IMPLEMENTED
+ *
+ * VARYING constructs have the following header:
+ *
+ *	struct varying_header {
+ *		ulong		first_is;
+ *		ulong		length_is;
+ *	};
+ *
+ * This indicates which interval of an array is significant.
+ * Non-intersecting elements of the array are undefined and usually
+ * zero-filled.  The first_is parameter for C arrays is always 0 for
+ * the first element.
+ *
+ * N.B. Constructs may contain one CONFORMANT element, which is always
+ * last, but may contain many VARYING elements, which can be anywhere.
+ *
+ * VARYING CONFORMANT constructs have the sizing headers arranged like
+ * this:
+ *
+ *	struct conformant_header	all_conformant[N_CONFORMANT_DIM];
+ *	struct varying_header		all_varying[N_VARYING_ELEMS_AND_DIMS];
+ *
+ * The sizing header is immediately followed by the values for the
+ * construct.  Again, we don't support more than one dimension and
+ * we don't support VARYING constructs at this time.
+ *
+ * A good example of a VARYING/CONFORMANT data structure is the UNIX
+ * directory entry:
+ *
+ *	struct dirent {
+ *		ushort		reclen;
+ *		ushort		namlen;
+ *		ulong		inum;
+ *	    [size_is(reclen-8) length_is(namlen+1)] // -(2+2+4), +1 for NUL
+ *		uchar		name[*];
+ *	};
+ *
+ *
+ * STRINGS ARE A SPECIAL CASE
+ *
+ * Strings are handled specially.  MS/RPC uses VARYING/CONFORMANT structures
+ * for strings.  This is a simple one-dimensional variable-length array,
+ * typically with its last element all zeroes.  We handle strings with the
+ * header:
+ *
+ *	struct string_header {
+ *		ulong		size_is;
+ *		ulong		first_is;	// always 0
+ *		ulong		length_is;	// always same as size_is
+ *	};
+ *
+ * If general support for VARYING and VARYING/CONFORMANT mechanisms is
+ * implemented, we probably won't need the strings special case.
+ */
+int
+ndr_outer(ndr_ref_t *outer_ref)
+{
+	ndr_stream_t 	*nds = outer_ref->stream;
+	ndr_typeinfo_t	*ti = outer_ref->ti;
+	int	is_varlen = ti->pdu_size_variable_part;
+	int	is_union = NDR_IS_UNION(ti);
+	int	is_string = NDR_IS_STRING(ti);
+	int	error = NDR_ERR_OUTER_PARAMS_BAD;
+	int	params;
+
+	params = outer_ref->outer_flags & NDR_F_PARAMS_MASK;
+
+	NDR_TATTLE(outer_ref, "--OUTER--");
+
+	/* All outer constructs start on a mod4 (longword) boundary */
+	if (!ndr_outer_align(outer_ref))
+		return (0);		/* error already set */
+
+	/* Regardless of what it is, this is where it starts */
+	outer_ref->pdu_offset = nds->pdu_scan_offset;
+
+	if (is_union) {
+		error = NDR_ERR_OUTER_UNION_ILLEGAL;
+		NDR_SET_ERROR(outer_ref, error);
+		return (0);
+	}
+
+	switch (params) {
+	case NDR_F_NONE:
+		if (is_string)
+			return (ndr_outer_string(outer_ref));
+		if (is_varlen)
+			return (ndr_outer_conformant_construct(outer_ref));
+
+		return (ndr_outer_fixed(outer_ref));
+
+	case NDR_F_SIZE_IS:
+	case NDR_F_DIMENSION_IS:
+	case NDR_F_IS_POINTER+NDR_F_SIZE_IS:
+	case NDR_F_IS_REFERENCE+NDR_F_SIZE_IS:
+		if (is_varlen) {
+			error = NDR_ERR_ARRAY_VARLEN_ILLEGAL;
+			break;
+		}
+
+		if (params & NDR_F_SIZE_IS)
+			return (ndr_outer_conformant_array(outer_ref));
+		else
+			return (ndr_outer_fixed_array(outer_ref));
+
+	default:
+		error = NDR_ERR_OUTER_PARAMS_BAD;
+		break;
+	}
+
+	/*
+	 * If we get here, something is wrong. Most likely,
+	 * the params flags do not match.
+	 */
+	NDR_SET_ERROR(outer_ref, error);
+	return (0);
+}
+
+int
+ndr_outer_fixed(ndr_ref_t *outer_ref)
+{
+	ndr_stream_t	*nds = outer_ref->stream;
+	ndr_typeinfo_t	*ti = outer_ref->ti;
+	ndr_ref_t	myref;
+	char 		*valp = NULL;
+	int		is_varlen = ti->pdu_size_variable_part;
+	int		is_union = NDR_IS_UNION(ti);
+	int		is_string = NDR_IS_STRING(ti);
+	int		rc;
+	unsigned	n_hdr;
+	unsigned	n_fixed;
+	unsigned	n_variable;
+	unsigned	n_alloc;
+	unsigned	n_pdu_total;
+	int		params;
+
+	params = outer_ref->outer_flags & NDR_F_PARAMS_MASK;
+
+	assert(!is_varlen && !is_string && !is_union);
+	assert(params == NDR_F_NONE);
+
+	/* no header for this */
+	n_hdr = 0;
+
+	/* fixed part -- exactly one of these */
+	n_fixed = ti->pdu_size_fixed_part;
+	assert(n_fixed > 0);
+
+	/* variable part -- exactly none of these */
+	n_variable = 0;
+
+	/* sum them up to determine the PDU space required */
+	n_pdu_total = n_hdr + n_fixed + n_variable;
+
+	/* similar sum to determine how much local memory is required */
+	n_alloc = n_fixed + n_variable;
+
+	rc = ndr_outer_grow(outer_ref, n_pdu_total);
+	if (!rc)
+		return (rc);		/* error already set */
+
+	switch (nds->m_op) {
+	case NDR_M_OP_MARSHALL:
+		valp = outer_ref->datum;
+		if (!valp) {
+			NDR_SET_ERROR(outer_ref, NDR_ERR_OUTER_PARAMS_BAD);
+			return (0);
+		}
+		if (outer_ref->backptr)
+			assert(valp == *outer_ref->backptr);
+		break;
+
+	case NDR_M_OP_UNMARSHALL:
+		valp = NDS_MALLOC(nds, n_alloc, outer_ref);
+		if (!valp) {
+			NDR_SET_ERROR(outer_ref, NDR_ERR_MALLOC_FAILED);
+			return (0);
+		}
+		if (outer_ref->backptr)
+			*outer_ref->backptr = valp;
+		outer_ref->datum = valp;
+		break;
+
+	default:
+		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
+		return (0);
+	}
+
+	bzero(&myref, sizeof (myref));
+	myref.stream = nds;
+	myref.enclosing = outer_ref;
+	myref.ti = outer_ref->ti;
+	myref.datum = outer_ref->datum;
+	myref.name = "FIXED-VALUE";
+	myref.outer_flags = NDR_F_NONE;
+	myref.inner_flags = NDR_F_NONE;
+
+	myref.pdu_offset = outer_ref->pdu_offset;
+	outer_ref->pdu_end_offset = outer_ref->pdu_offset + n_pdu_total;
+
+	rc = ndr_inner(&myref);
+	if (!rc)
+		return (rc);		/* error already set */
+
+	nds->pdu_scan_offset = outer_ref->pdu_end_offset;
+	return (1);
+}
+
+int
+ndr_outer_fixed_array(ndr_ref_t *outer_ref)
+{
+	ndr_stream_t	*nds = outer_ref->stream;
+	ndr_typeinfo_t	*ti = outer_ref->ti;
+	ndr_ref_t	myref;
+	char 		*valp = NULL;
+	int		is_varlen = ti->pdu_size_variable_part;
+	int		is_union = NDR_IS_UNION(ti);
+	int		is_string = NDR_IS_STRING(ti);
+	int		rc;
+	unsigned	n_hdr;
+	unsigned	n_fixed;
+	unsigned	n_variable;
+	unsigned	n_alloc;
+	unsigned	n_pdu_total;
+	int		params;
+
+	params = outer_ref->outer_flags & NDR_F_PARAMS_MASK;
+
+	assert(!is_varlen && !is_string && !is_union);
+	assert(params == NDR_F_DIMENSION_IS);
+
+	/* no header for this */
+	n_hdr = 0;
+
+	/* fixed part -- exactly dimension_is of these */
+	n_fixed = ti->pdu_size_fixed_part * outer_ref->dimension_is;
+	assert(n_fixed > 0);
+
+	/* variable part -- exactly none of these */
+	n_variable = 0;
+
+	/* sum them up to determine the PDU space required */
+	n_pdu_total = n_hdr + n_fixed + n_variable;
+
+	/* similar sum to determine how much local memory is required */
+	n_alloc = n_fixed + n_variable;
+
+	rc = ndr_outer_grow(outer_ref, n_pdu_total);
+	if (!rc)
+		return (rc);		/* error already set */
+
+	switch (nds->m_op) {
+	case NDR_M_OP_MARSHALL:
+		valp = outer_ref->datum;
+		if (!valp) {
+			NDR_SET_ERROR(outer_ref, NDR_ERR_OUTER_PARAMS_BAD);
+			return (0);
+		}
+		if (outer_ref->backptr)
+			assert(valp == *outer_ref->backptr);
+		break;
+
+	case NDR_M_OP_UNMARSHALL:
+		valp = NDS_MALLOC(nds, n_alloc, outer_ref);
+		if (!valp) {
+			NDR_SET_ERROR(outer_ref, NDR_ERR_MALLOC_FAILED);
+			return (0);
+		}
+		if (outer_ref->backptr)
+			*outer_ref->backptr = valp;
+		outer_ref->datum = valp;
+		break;
+
+	default:
+		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
+		return (0);
+	}
+
+	bzero(&myref, sizeof (myref));
+	myref.stream = nds;
+	myref.enclosing = outer_ref;
+	myref.ti = outer_ref->ti;
+	myref.datum = outer_ref->datum;
+	myref.name = "FIXED-ARRAY";
+	myref.outer_flags = NDR_F_NONE;
+	myref.inner_flags = NDR_F_DIMENSION_IS;
+	myref.dimension_is = outer_ref->dimension_is;
+
+	myref.pdu_offset = outer_ref->pdu_offset;
+	outer_ref->pdu_end_offset = outer_ref->pdu_offset + n_pdu_total;
+
+	rc = ndr_inner(&myref);
+	if (!rc)
+		return (rc);		/* error already set */
+
+	nds->pdu_scan_offset = outer_ref->pdu_end_offset;
+	return (1);
+}
+
+int
+ndr_outer_conformant_array(ndr_ref_t *outer_ref)
+{
+	ndr_stream_t	*nds = outer_ref->stream;
+	ndr_typeinfo_t	*ti = outer_ref->ti;
+	ndr_ref_t	myref;
+	char 		*valp = NULL;
+	int		is_varlen = ti->pdu_size_variable_part;
+	int		is_union = NDR_IS_UNION(ti);
+	int		is_string = NDR_IS_STRING(ti);
+	unsigned long	size_is;
+	int		rc;
+	unsigned	n_hdr;
+	unsigned	n_fixed;
+	unsigned	n_variable;
+	unsigned	n_alloc;
+	unsigned	n_pdu_total;
+	unsigned	n_ptr_offset;
+	int		params;
+
+	params = outer_ref->outer_flags & NDR_F_PARAMS_MASK;
+
+	assert(!is_varlen && !is_string && !is_union);
+	assert(params & NDR_F_SIZE_IS);
+
+	/* conformant header for this */
+	n_hdr = 4;
+
+	/* fixed part -- exactly none of these */
+	n_fixed = 0;
+
+	/* variable part -- exactly size_of of these */
+	/* notice that it is the **fixed** size of the ti */
+	n_variable = ti->pdu_size_fixed_part * outer_ref->size_is;
+
+	/* sum them up to determine the PDU space required */
+	n_pdu_total = n_hdr + n_fixed + n_variable;
+
+	/* similar sum to determine how much local memory is required */
+	n_alloc = n_fixed + n_variable;
+
+	rc = ndr_outer_grow(outer_ref, n_pdu_total);
+	if (!rc)
+		return (rc);		/* error already set */
+
+	switch (nds->m_op) {
+	case NDR_M_OP_MARSHALL:
+		size_is = outer_ref->size_is;
+		rc = ndr_outer_poke_sizing(outer_ref, 0, &size_is);
+		if (!rc)
+			return (0);	/* error already set */
+
+		valp = outer_ref->datum;
+		if (!valp) {
+			NDR_SET_ERROR(outer_ref, NDR_ERR_OUTER_PARAMS_BAD);
+			return (0);
+		}
+		if (outer_ref->backptr)
+			assert(valp == *outer_ref->backptr);
+		n_ptr_offset = 4;
+		break;
+
+	case NDR_M_OP_UNMARSHALL:
+		if (params & NDR_F_IS_REFERENCE) {
+			size_is = outer_ref->size_is;
+			n_ptr_offset = 0;
+		} else {
+			/* NDR_F_IS_POINTER */
+			rc = ndr_outer_peek_sizing(outer_ref, 0, &size_is);
+			if (!rc)
+				return (0);	/* error already set */
+
+			if (size_is != outer_ref->size_is) {
+				NDR_SET_ERROR(outer_ref,
+				    NDR_ERR_SIZE_IS_MISMATCH_PDU);
+				return (0);
+			}
+
+			n_ptr_offset = 4;
+		}
+
+		if (size_is > 0) {
+			valp = NDS_MALLOC(nds, n_alloc, outer_ref);
+			if (!valp) {
+				NDR_SET_ERROR(outer_ref, NDR_ERR_MALLOC_FAILED);
+				return (0);
+			}
+		}
+
+		if (outer_ref->backptr)
+			*outer_ref->backptr = valp;
+		outer_ref->datum = valp;
+		break;
+
+	default:
+		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
+		return (0);
+	}
+
+	outer_ref->pdu_end_offset = outer_ref->pdu_offset + n_pdu_total;
+	outer_ref->type_flags = NDR_F_NONE;
+	outer_ref->inner_flags = NDR_F_NONE;
+
+	if (size_is > 0) {
+		bzero(&myref, sizeof (myref));
+		myref.stream = nds;
+		myref.enclosing = outer_ref;
+		myref.ti = outer_ref->ti;
+		myref.datum = outer_ref->datum;
+		myref.name = "CONFORMANT-ARRAY";
+		myref.outer_flags = NDR_F_NONE;
+		myref.inner_flags = NDR_F_SIZE_IS;
+		myref.size_is = outer_ref->size_is;
+
+		myref.inner_flags = NDR_F_DIMENSION_IS;		/* convenient */
+		myref.dimension_is = outer_ref->size_is;	/* convenient */
+
+		myref.pdu_offset = outer_ref->pdu_offset + n_ptr_offset;
+
+		rc = ndr_inner(&myref);
+		if (!rc)
+			return (rc);		/* error already set */
+	}
+
+	nds->pdu_scan_offset = outer_ref->pdu_end_offset;
+	return (1);
+}
+
+int
+ndr_outer_conformant_construct(ndr_ref_t *outer_ref)
+{
+	ndr_stream_t	*nds = outer_ref->stream;
+	ndr_typeinfo_t	*ti = outer_ref->ti;
+	ndr_ref_t	myref;
+	char 		*valp = NULL;
+	int		is_varlen = ti->pdu_size_variable_part;
+	int		is_union = NDR_IS_UNION(ti);
+	int		is_string = NDR_IS_STRING(ti);
+	unsigned long	size_is;
+	int		rc;
+	unsigned	n_hdr;
+	unsigned	n_fixed;
+	unsigned	n_variable;
+	unsigned	n_alloc;
+	unsigned	n_pdu_total;
+	int		params;
+
+	params = outer_ref->outer_flags & NDR_F_PARAMS_MASK;
+
+	assert(is_varlen && !is_string && !is_union);
+	assert(params == NDR_F_NONE);
+
+	/* conformant header for this */
+	n_hdr = 4;
+
+	/* fixed part -- exactly one of these */
+	n_fixed = ti->pdu_size_fixed_part;
+
+	/* variable part -- exactly size_of of these */
+	n_variable = 0;		/* 0 for the moment */
+
+	/* sum them up to determine the PDU space required */
+	n_pdu_total = n_hdr + n_fixed + n_variable;
+
+	/* similar sum to determine how much local memory is required */
+	n_alloc = n_fixed + n_variable;
+
+	/* For the moment, grow enough for the fixed-size part */
+	rc = ndr_outer_grow(outer_ref, n_pdu_total);
+	if (!rc)
+		return (rc);		/* error already set */
+
+	switch (nds->m_op) {
+	case NDR_M_OP_MARSHALL:
+		/*
+		 * We don't know the size yet. We have to wait for
+		 * it. Proceed with the fixed-size part, and await
+		 * the call to ndr_size_is().
+		 */
+		size_is = 0;
+		rc = ndr_outer_poke_sizing(outer_ref, 0, &size_is);
+		if (!rc)
+			return (0);	/* error already set */
+
+		valp = outer_ref->datum;
+		if (!valp) {
+			NDR_SET_ERROR(outer_ref, NDR_ERR_OUTER_PARAMS_BAD);
+			return (0);
+		}
+		if (outer_ref->backptr)
+			assert(valp == *outer_ref->backptr);
+		break;
+
+	case NDR_M_OP_UNMARSHALL:
+		/*
+		 * We know the size of the variable part because
+		 * of the CONFORMANT header. We will verify
+		 * the header against the [size_is(X)] advice
+		 * later when ndr_size_is() is called.
+		 */
+		rc = ndr_outer_peek_sizing(outer_ref, 0, &size_is);
+		if (!rc)
+			return (0);	/* error already set */
+
+		/* recalculate metrics */
+		n_variable = size_is * ti->pdu_size_variable_part;
+		n_pdu_total = n_hdr + n_fixed + n_variable;
+		n_alloc = n_fixed + n_variable;
+
+		rc = ndr_outer_grow(outer_ref, n_pdu_total);
+		if (!rc)
+			return (rc);		/* error already set */
+
+		outer_ref->size_is = size_is; /* verified later */
+
+		valp = NDS_MALLOC(nds, n_alloc, outer_ref);
+		if (!valp) {
+			NDR_SET_ERROR(outer_ref, NDR_ERR_MALLOC_FAILED);
+			return (0);
+		}
+		if (outer_ref->backptr)
+			*outer_ref->backptr = valp;
+		outer_ref->datum = valp;
+		break;
+
+	default:
+		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
+		return (0);
+	}
+
+	outer_ref->pdu_end_offset = outer_ref->pdu_offset + n_pdu_total;
+	outer_ref->type_flags = NDR_F_SIZE_IS; /* indicate pending */
+	outer_ref->inner_flags = NDR_F_NONE;   /* indicate pending */
+
+	bzero(&myref, sizeof (myref));
+	myref.stream = nds;
+	myref.enclosing = outer_ref;
+	myref.ti = outer_ref->ti;
+	myref.datum = outer_ref->datum;
+	myref.name = "CONFORMANT-CONSTRUCT";
+	myref.outer_flags = NDR_F_NONE;
+	myref.inner_flags = NDR_F_NONE;
+	myref.size_is = outer_ref->size_is;
+
+	myref.pdu_offset = outer_ref->pdu_offset + 4;
+
+	rc = ndr_inner(&myref);
+	if (!rc)
+		return (rc);		/* error already set */
+
+	nds->pdu_scan_offset = outer_ref->pdu_end_offset;
+
+	if (outer_ref->inner_flags != NDR_F_SIZE_IS) {
+		NDR_SET_ERROR(&myref, NDR_ERR_SIZE_IS_MISMATCH_AFTER);
+		return (0);
+	}
+
+	return (1);
+}
+
+int
+ndr_size_is(ndr_ref_t *ref)
+{
+	ndr_stream_t 		*nds = ref->stream;
+	ndr_ref_t 		*outer_ref = nds->outer_current;
+	ndr_typeinfo_t		*ti = outer_ref->ti;
+	unsigned long		size_is;
+	int			rc;
+	unsigned		n_hdr;
+	unsigned		n_fixed;
+	unsigned		n_variable;
+	unsigned		n_pdu_total;
+
+	assert(ref->inner_flags & NDR_F_SIZE_IS);
+	size_is = ref->size_is;
+
+	if (outer_ref->type_flags != NDR_F_SIZE_IS) {
+		NDR_SET_ERROR(ref, NDR_ERR_SIZE_IS_UNEXPECTED);
+		return (0);
+	}
+
+	if (outer_ref->inner_flags & NDR_F_SIZE_IS) {
+		NDR_SET_ERROR(ref, NDR_ERR_SIZE_IS_DUPLICATED);
+		return (0);
+	}
+
+	/* repeat metrics, see ndr_conformant_construct() above */
+	n_hdr = 4;
+	n_fixed = ti->pdu_size_fixed_part;
+	n_variable = size_is * ti->pdu_size_variable_part;
+	n_pdu_total = n_hdr + n_fixed + n_variable;
+
+	rc = ndr_outer_grow(outer_ref, n_pdu_total);
+	if (!rc)
+		return (rc);		/* error already set */
+
+	switch (nds->m_op) {
+	case NDR_M_OP_MARSHALL:
+		/*
+		 * We have to set the sizing header and extend
+		 * the size of the PDU (already done).
+		 */
+		rc = ndr_outer_poke_sizing(outer_ref, 0, &size_is);
+		if (!rc)
+			return (0);	/* error already set */
+		break;
+
+	case NDR_M_OP_UNMARSHALL:
+		/*
+		 * Allocation done during ndr_conformant_construct().
+		 * All we are doing here is verifying that the
+		 * intended size (ref->size_is) matches the sizing header.
+		 */
+		if (size_is != outer_ref->size_is) {
+			NDR_SET_ERROR(ref, NDR_ERR_SIZE_IS_MISMATCH_PDU);
+			return (0);
+		}
+		break;
+
+	default:
+		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
+		return (0);
+	}
+
+	outer_ref->inner_flags |= NDR_F_SIZE_IS;
+	outer_ref->size_is = ref->size_is;
+	return (1);
+}
+
+int
+ndr_outer_string(ndr_ref_t *outer_ref)
+{
+	ndr_stream_t	*nds = outer_ref->stream;
+	ndr_typeinfo_t 	*ti = outer_ref->ti;
+	ndr_ref_t	myref;
+	char 		*valp = NULL;
+	unsigned	is_varlen = ti->pdu_size_variable_part;
+	int		is_union = NDR_IS_UNION(ti);
+	int		is_string = NDR_IS_STRING(ti);
+	int		rc;
+	unsigned	n_zeroes;
+	unsigned	ix;
+	unsigned long	size_is;
+	unsigned long	first_is;
+	unsigned long	length_is;
+	unsigned	n_hdr;
+	unsigned	n_fixed;
+	unsigned	n_variable;
+	unsigned	n_alloc;
+	unsigned	n_pdu_total;
+	int		params;
+
+	params = outer_ref->outer_flags & NDR_F_PARAMS_MASK;
+
+	assert(is_varlen && is_string && !is_union);
+	assert(params == NDR_F_NONE);
+
+	/* string header for this: size_is first_is length_is */
+	n_hdr = 12;
+
+	/* fixed part -- exactly none of these */
+	n_fixed = 0;
+
+	if (!ndr_outer_grow(outer_ref, n_hdr))
+		return (0);		/* error already set */
+
+	switch (nds->m_op) {
+	case NDR_M_OP_MARSHALL:
+		valp = outer_ref->datum;
+		if (!valp) {
+			NDR_SET_ERROR(outer_ref, NDR_ERR_OUTER_PARAMS_BAD);
+			return (0);
+		}
+
+		if (outer_ref->backptr)
+			assert(valp == *outer_ref->backptr);
+
+		if (ti == &ndt_s_wchar) {
+			/*
+			 * size_is is the number of characters in the
+			 * (multibyte) string, including the null.
+			 * In other words, symbols, not bytes.
+			 */
+			size_t wlen;
+			wlen = ndr__mbstowcs(NULL, valp, NDR_STRING_MAX);
+			if (wlen == (size_t)-1) {
+				/* illegal sequence error? */
+				NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
+				return (0);
+			}
+			if ((nds->flags & NDS_F_NONULL) == 0)
+				wlen++;
+			if (wlen > NDR_STRING_MAX) {
+				NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
+				return (0);
+			}
+			size_is = wlen;
+		} else {
+			valp = outer_ref->datum;
+			n_zeroes = 0;
+			for (ix = 0; ix < NDR_STRING_MAX; ix++) {
+				if (valp[ix] == 0) {
+					n_zeroes++;
+					if (n_zeroes >= is_varlen &&
+					    ix % is_varlen == 0) {
+						break;
+					}
+				} else {
+					n_zeroes = 0;
+				}
+			}
+			if (ix >= NDR_STRING_MAX) {
+				NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
+				return (0);
+			}
+			size_is = ix+1;
+		}
+
+		first_is = 0;
+
+		if (nds->flags & NDS_F_NOTERM)
+			length_is = size_is - 1;
+		else
+			length_is = size_is;
+
+		if (!ndr_outer_poke_sizing(outer_ref, 0, &size_is) ||
+		    !ndr_outer_poke_sizing(outer_ref, 4, &first_is) ||
+		    !ndr_outer_poke_sizing(outer_ref, 8, &length_is))
+			return (0);		/* error already set */
+		break;
+
+	case NDR_M_OP_UNMARSHALL:
+		if (!ndr_outer_peek_sizing(outer_ref, 0, &size_is) ||
+		    !ndr_outer_peek_sizing(outer_ref, 4, &first_is) ||
+		    !ndr_outer_peek_sizing(outer_ref, 8, &length_is))
+			return (0);		/* error already set */
+
+		/*
+		 * In addition to the first_is check, we used to check that
+		 * size_is or size_is-1 was equal to length_is but Windows95
+		 * doesn't conform to this "rule" (see variable part below).
+		 * The srvmgr tool for Windows95 sent the following values
+		 * for a path string:
+		 *
+		 *	size_is   = 261 (0x105)
+		 *	first_is  = 0
+		 *	length_is = 53  (0x35)
+		 *
+		 * The length_is was correct (for the given path) but the
+		 * size_is was the maximum path length rather than being
+		 * related to length_is.
+		 */
+		if (first_is != 0) {
+			NDR_SET_ERROR(outer_ref, NDR_ERR_STRING_SIZING);
+			return (0);
+		}
+
+		if (ti == &ndt_s_wchar) {
+			/*
+			 * Decoding Unicode to UTF-8; we need to allow
+			 * for the maximum possible char size. It would
+			 * be nice to use mbequiv_strlen but the string
+			 * may not be null terminated.
+			 */
+			n_alloc = (size_is + 1) * NDR_MB_CHAR_MAX;
+		} else {
+			n_alloc = (size_is + 1) * is_varlen;
+		}
+
+		valp = NDS_MALLOC(nds, n_alloc, outer_ref);
+		if (!valp) {
+			NDR_SET_ERROR(outer_ref, NDR_ERR_MALLOC_FAILED);
+			return (0);
+		}
+
+		bzero(valp, (size_is+1) * is_varlen);
+
+		if (outer_ref->backptr)
+			*outer_ref->backptr = valp;
+		outer_ref->datum = valp;
+		break;
+
+	default:
+		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
+		return (0);
+	}
+
+	/*
+	 * Variable part - exactly length_is of these.
+	 *
+	 * Usually, length_is is same as size_is and includes nul.
+	 * Some protocols use length_is = size_is-1, and length_is does
+	 * not include the nul (which is more consistent with DCE spec).
+	 * If the length_is is 0, there is no data following the
+	 * sizing header, regardless of size_is.
+	 */
+	n_variable = length_is * is_varlen;
+
+	/* sum them up to determine the PDU space required */
+	n_pdu_total = n_hdr + n_fixed + n_variable;
+
+	/* similar sum to determine how much local memory is required */
+	n_alloc = n_fixed + n_variable;
+
+	rc = ndr_outer_grow(outer_ref, n_pdu_total);
+	if (!rc)
+		return (rc);		/* error already set */
+
+	if (length_is > 0) {
+		bzero(&myref, sizeof (myref));
+		myref.stream = nds;
+		myref.enclosing = outer_ref;
+		myref.ti = outer_ref->ti;
+		myref.datum = outer_ref->datum;
+		myref.name = "OUTER-STRING";
+		myref.outer_flags = NDR_F_IS_STRING;
+		myref.inner_flags = NDR_F_NONE;
+
+		/*
+		 * Set up size_is and strlen_is for ndr_s_wchar.
+		 */
+		myref.size_is = size_is;
+		myref.strlen_is = length_is;
+	}
+
+	myref.pdu_offset = outer_ref->pdu_offset + 12;
+
+	/*
+	 * Don't try to decode empty strings.
+	 */
+	if ((size_is == 0) && (first_is == 0) && (length_is == 0)) {
+		nds->pdu_scan_offset = outer_ref->pdu_end_offset;
+		return (1);
+	}
+
+	if ((size_is != 0) && (length_is != 0)) {
+		rc = ndr_inner(&myref);
+		if (!rc)
+			return (rc);		/* error already set */
+	}
+
+	nds->pdu_scan_offset = outer_ref->pdu_end_offset;
+	return (1);
+}
+
+int
+ndr_outer_peek_sizing(ndr_ref_t *outer_ref, unsigned offset,
+    unsigned long *sizing_p)
+{
+	ndr_stream_t 	*nds = outer_ref->stream;
+	unsigned long	pdu_offset;
+	int		rc;
+
+	pdu_offset = outer_ref->pdu_offset + offset;
+
+	if (pdu_offset < nds->outer_current->pdu_offset ||
+	    pdu_offset > nds->outer_current->pdu_end_offset ||
+	    pdu_offset+4 > nds->outer_current->pdu_end_offset) {
+		NDR_SET_ERROR(outer_ref, NDR_ERR_BOUNDS_CHECK);
+		return (0);
+	}
+
+	switch (nds->m_op) {
+	case NDR_M_OP_MARSHALL:
+		NDR_SET_ERROR(outer_ref, NDR_ERR_UNIMPLEMENTED);
+		return (0);
+
+	case NDR_M_OP_UNMARSHALL:
+		rc = NDS_GET_PDU(nds, pdu_offset, 4, (char *)sizing_p,
+		    nds->swap, outer_ref);
+		break;
+
+	default:
+		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
+		return (0);
+	}
+
+	return (rc);
+}
+
+int
+ndr_outer_poke_sizing(ndr_ref_t *outer_ref, unsigned offset,
+    unsigned long *sizing_p)
+{
+	ndr_stream_t 	*nds = outer_ref->stream;
+	unsigned long	pdu_offset;
+	int		rc;
+
+	pdu_offset = outer_ref->pdu_offset + offset;
+
+	if (pdu_offset < nds->outer_current->pdu_offset ||
+	    pdu_offset > nds->outer_current->pdu_end_offset ||
+	    pdu_offset+4 > nds->outer_current->pdu_end_offset) {
+		NDR_SET_ERROR(outer_ref, NDR_ERR_BOUNDS_CHECK);
+		return (0);
+	}
+
+	switch (nds->m_op) {
+	case NDR_M_OP_MARSHALL:
+		rc = NDS_PUT_PDU(nds, pdu_offset, 4, (char *)sizing_p,
+		    nds->swap, outer_ref);
+		break;
+
+	case NDR_M_OP_UNMARSHALL:
+		NDR_SET_ERROR(outer_ref, NDR_ERR_UNIMPLEMENTED);
+		return (0);
+
+	default:
+		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
+		return (0);
+	}
+
+	return (rc);
+}
+
+/*
+ * All OUTER constructs begin on a mod4 (dword) boundary - except
+ * for the ones that don't: some MSRPC calls appear to use word or
+ * packed alignment.  Strings appear to be dword aligned.
+ */
+int
+ndr_outer_align(ndr_ref_t *outer_ref)
+{
+	ndr_stream_t 	*nds = outer_ref->stream;
+	int		rc;
+	unsigned	n_pad;
+	unsigned	align;
+
+	if (outer_ref->packed_alignment && outer_ref->ti != &ndt_s_wchar) {
+		align = outer_ref->ti->alignment;
+		n_pad = ((align + 1) - nds->pdu_scan_offset) & align;
+	} else {
+		n_pad = NDR_ALIGN4(nds->pdu_scan_offset);
+	}
+
+	if (n_pad == 0)
+		return (1);	/* already aligned, often the case */
+
+	if (!ndr_outer_grow(outer_ref, n_pad))
+		return (0);	/* error already set */
+
+	switch (nds->m_op) {
+	case NDR_M_OP_MARSHALL:
+		rc = NDS_PAD_PDU(nds, nds->pdu_scan_offset, n_pad, outer_ref);
+		if (!rc) {
+			NDR_SET_ERROR(outer_ref, NDR_ERR_PAD_FAILED);
+			return (0);
+		}
+		break;
+
+	case NDR_M_OP_UNMARSHALL:
+		break;
+
+	default:
+		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
+		return (0);
+	}
+
+	nds->pdu_scan_offset += n_pad;
+	return (1);
+}
+
+int
+ndr_outer_grow(ndr_ref_t *outer_ref, unsigned n_total)
+{
+	ndr_stream_t 	*nds = outer_ref->stream;
+	unsigned long	pdu_want_size;
+	int		rc, is_ok = 0;
+
+	pdu_want_size = nds->pdu_scan_offset + n_total;
+
+	if (pdu_want_size <= nds->pdu_max_size) {
+		is_ok = 1;
+	}
+
+	switch (nds->m_op) {
+	case NDR_M_OP_MARSHALL:
+		if (is_ok)
+			break;
+		rc = NDS_GROW_PDU(nds, pdu_want_size, outer_ref);
+		if (!rc) {
+			NDR_SET_ERROR(outer_ref, NDR_ERR_GROW_FAILED);
+			return (0);
+		}
+		break;
+
+	case NDR_M_OP_UNMARSHALL:
+		if (is_ok)
+			break;
+		NDR_SET_ERROR(outer_ref, NDR_ERR_UNDERFLOW);
+		return (0);
+
+	default:
+		NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
+		return (0);
+	}
+
+	if (nds->pdu_size < pdu_want_size)
+		nds->pdu_size = pdu_want_size;
+
+	outer_ref->pdu_end_offset = pdu_want_size;
+	return (1);
+}
+
+/*
+ * INNER ELEMENTS
+ *
+ * The local datum (arg_ref->datum) already exists, there is no need to
+ * malloc() it.  The datum should point at a member of a structure.
+ *
+ * For the most part, ndr_inner() and its helpers are just a sanity
+ * check.  The underlying ti->ndr_func() could be called immediately
+ * for non-pointer elements.  For the sake of robustness, we detect
+ * run-time errors here.  Most of the situations this protects against
+ * have already been checked by the IDL compiler.  This is also a
+ * common point for processing of all data, and so is a convenient
+ * place to work from for debugging.
+ */
+int
+ndr_inner(ndr_ref_t *arg_ref)
+{
+	ndr_typeinfo_t 	*ti = arg_ref->ti;
+	int	is_varlen = ti->pdu_size_variable_part;
+	int	is_union = NDR_IS_UNION(ti);
+	int	error = NDR_ERR_INNER_PARAMS_BAD;
+	int	params;
+
+	params = arg_ref->inner_flags & NDR_F_PARAMS_MASK;
+
+	switch (params) {
+	case NDR_F_NONE:
+		if (is_union) {
+			error = NDR_ERR_SWITCH_VALUE_MISSING;
+			break;
+		}
+		return (*ti->ndr_func)(arg_ref);
+
+	case NDR_F_SIZE_IS:
+	case NDR_F_DIMENSION_IS:
+	case NDR_F_IS_POINTER+NDR_F_SIZE_IS:   /* pointer to something */
+	case NDR_F_IS_REFERENCE+NDR_F_SIZE_IS: /* pointer to something */
+		if (is_varlen) {
+			error = NDR_ERR_ARRAY_VARLEN_ILLEGAL;
+			break;
+		}
+		if (is_union) {
+			error = NDR_ERR_ARRAY_UNION_ILLEGAL;
+			break;
+		}
+		if (params & NDR_F_IS_POINTER)
+			return (ndr_inner_pointer(arg_ref));
+		else if (params & NDR_F_IS_REFERENCE)
+			return (ndr_inner_reference(arg_ref));
+		else
+			return (ndr_inner_array(arg_ref));
+
+	case NDR_F_IS_POINTER:	/* type is pointer to one something */
+		if (is_union) {
+			error = NDR_ERR_ARRAY_UNION_ILLEGAL;
+			break;
+		}
+		return (ndr_inner_pointer(arg_ref));
+
+	case NDR_F_IS_REFERENCE:	/* type is pointer to one something */
+		if (is_union) {
+			error = NDR_ERR_ARRAY_UNION_ILLEGAL;
+			break;
+		}
+		return (ndr_inner_reference(arg_ref));
+
+	case NDR_F_SWITCH_IS:
+		if (!is_union) {
+			error = NDR_ERR_SWITCH_VALUE_ILLEGAL;
+			break;
+		}
+		return (*ti->ndr_func)(arg_ref);
+
+	default:
+		error = NDR_ERR_INNER_PARAMS_BAD;
+		break;
+	}
+
+	/*
+	 * If we get here, something is wrong. Most likely,
+	 * the params flags do not match
+	 */
+	NDR_SET_ERROR(arg_ref, error);
+	return (0);
+}
+
+int
+ndr_inner_pointer(ndr_ref_t *arg_ref)
+{
+	ndr_stream_t	*nds = arg_ref->stream;
+	/*LINTED E_BAD_PTR_CAST_ALIGN*/
+	char 		**valpp = (char **)arg_ref->datum;
+	ndr_ref_t 	*outer_ref;
+
+	if (!ndr__ulong(arg_ref))
+		return (0);	/* error */
+	if (!*valpp)
+		return (1);	/* NULL pointer */
+
+	outer_ref = ndr_enter_outer_queue(arg_ref);
+	if (!outer_ref)
+		return (0);	/* error already set */
+
+	/*
+	 * Move advice in inner_flags to outer_flags.
+	 * Retain pointer flag for conformant arrays.
+	 */
+	outer_ref->outer_flags = arg_ref->inner_flags & NDR_F_PARAMS_MASK;
+	if ((outer_ref->outer_flags & NDR_F_SIZE_IS) == 0)
+		outer_ref->outer_flags &= ~NDR_F_IS_POINTER;
+#ifdef NDR_INNER_PTR_NOT_YET
+	outer_ref->outer_flags |= NDR_F_BACKPTR;
+	if (outer_ref->outer_flags & NDR_F_SIZE_IS) {
+		outer_ref->outer_flags |= NDR_F_ARRAY+NDR_F_CONFORMANT;
+	}
+#endif /* NDR_INNER_PTR_NOT_YET */
+
+	outer_ref->backptr = valpp;
+
+	switch (nds->m_op) {
+	case NDR_M_OP_MARSHALL:
+		outer_ref->datum = *valpp;
+		break;
+
+	case NDR_M_OP_UNMARSHALL:
+		/*
+		 * This is probably wrong if the application allocated
+		 * memory in advance.  Indicate no value for now.
+		 * ONC RPC handles this case.
+		 */
+		*valpp = 0;
+		outer_ref->datum = 0;
+		break;
+	}
+
+	return (1);		/* pointer dereference scheduled */
+}
+
+int
+ndr_inner_reference(ndr_ref_t *arg_ref)
+{
+	ndr_stream_t	*nds = arg_ref->stream;
+	/*LINTED E_BAD_PTR_CAST_ALIGN*/
+	char		**valpp = (char **)arg_ref->datum;
+	ndr_ref_t	*outer_ref;
+
+	outer_ref = ndr_enter_outer_queue(arg_ref);
+	if (!outer_ref)
+		return (0);	/* error already set */
+
+	/*
+	 * Move advice in inner_flags to outer_flags.
+	 * Retain reference flag for conformant arrays.
+	 */
+	outer_ref->outer_flags = arg_ref->inner_flags & NDR_F_PARAMS_MASK;
+	if ((outer_ref->outer_flags & NDR_F_SIZE_IS) == 0)
+		outer_ref->outer_flags &= ~NDR_F_IS_REFERENCE;
+#ifdef NDR_INNER_REF_NOT_YET
+	outer_ref->outer_flags |= NDR_F_BACKPTR;
+	if (outer_ref->outer_flags & NDR_F_SIZE_IS) {
+		outer_ref->outer_flags |= NDR_F_ARRAY+NDR_F_CONFORMANT;
+	}
+#endif /* NDR_INNER_REF_NOT_YET */
+
+	outer_ref->backptr = valpp;
+
+	switch (nds->m_op) {
+	case NDR_M_OP_MARSHALL:
+		outer_ref->datum = *valpp;
+		break;
+
+	case NDR_M_OP_UNMARSHALL:
+		/*
+		 * This is probably wrong if the application allocated
+		 * memory in advance.  Indicate no value for now.
+		 * ONC RPC handles this case.
+		 */
+		*valpp = 0;
+		outer_ref->datum = 0;
+		break;
+	}
+
+	return (1);		/* pointer dereference scheduled */
+}
+
+int
+ndr_inner_array(ndr_ref_t *encl_ref)
+{
+	ndr_typeinfo_t		*ti = encl_ref->ti;
+	ndr_ref_t		myref;
+	unsigned long		pdu_offset = encl_ref->pdu_offset;
+	unsigned long		n_elem;
+	unsigned long		i;
+	char			name[30];
+
+	if (encl_ref->inner_flags & NDR_F_SIZE_IS) {
+		/* now is the time to check/set size */
+		if (!ndr_size_is(encl_ref))
+			return (0);	/* error already set */
+		n_elem = encl_ref->size_is;
+	} else {
+		assert(encl_ref->inner_flags & NDR_F_DIMENSION_IS);
+		n_elem = encl_ref->dimension_is;
+	}
+
+	bzero(&myref, sizeof (myref));
+	myref.enclosing = encl_ref;
+	myref.stream = encl_ref->stream;
+	myref.packed_alignment = 0;
+	myref.ti = ti;
+	myref.inner_flags = NDR_F_NONE;
+
+	for (i = 0; i < n_elem; i++) {
+		(void) snprintf(name, sizeof (name), "[%lu]", i);
+		myref.name = name;
+		myref.pdu_offset = pdu_offset + i * ti->pdu_size_fixed_part;
+		myref.datum = encl_ref->datum + i * ti->c_size_fixed_part;
+
+		if (!ndr_inner(&myref))
+			return (0);
+	}
+
+	return (1);
+}
+
+
+/*
+ * BASIC TYPES
+ */
+#define	MAKE_BASIC_TYPE_BASE(TYPE, SIZE) \
+    extern int ndr_##TYPE(struct ndr_reference *encl_ref); \
+    ndr_typeinfo_t ndt_##TYPE = { \
+	1,		/* NDR version */ \
+	(SIZE)-1,	/* alignment */ \
+	NDR_F_NONE,	/* flags */ \
+	ndr_##TYPE,	/* ndr_func */ \
+	SIZE,		/* pdu_size_fixed_part */ \
+	0,		/* pdu_size_variable_part */ \
+	SIZE,		/* c_size_fixed_part */ \
+	0,		/* c_size_variable_part */ \
+	}; \
+    int ndr_##TYPE(struct ndr_reference *ref) { \
+	return (ndr_basic_integer(ref, SIZE)); \
+}
+
+#define	MAKE_BASIC_TYPE_STRING(TYPE, SIZE) \
+    extern int ndr_s##TYPE(struct ndr_reference *encl_ref); \
+    ndr_typeinfo_t ndt_s##TYPE = { \
+	1,		/* NDR version */ \
+	(SIZE)-1,	/* alignment */ \
+	NDR_F_STRING,	/* flags */ \
+	ndr_s##TYPE,	/* ndr_func */ \
+	0,		/* pdu_size_fixed_part */ \
+	SIZE,		/* pdu_size_variable_part */ \
+	0,		/* c_size_fixed_part */ \
+	SIZE,		/* c_size_variable_part */ \
+	}; \
+    int ndr_s##TYPE(struct ndr_reference *ref) { \
+	return (ndr_string_basic_integer(ref, &ndt_##TYPE)); \
+}
+
+#define	MAKE_BASIC_TYPE(TYPE, SIZE) \
+	MAKE_BASIC_TYPE_BASE(TYPE, SIZE) \
+	MAKE_BASIC_TYPE_STRING(TYPE, SIZE)
+
+int ndr_basic_integer(ndr_ref_t *, unsigned);
+int ndr_string_basic_integer(ndr_ref_t *, ndr_typeinfo_t *);
+
+/* Comments to be nice to those searching for these types. */
+MAKE_BASIC_TYPE(_char, 1)	/* ndt__char,  ndt_s_char */
+MAKE_BASIC_TYPE(_uchar, 1)	/* ndt__uchar, ndt_s_uchar */
+MAKE_BASIC_TYPE(_short, 2)	/* ndt__short, ndt_s_short */
+MAKE_BASIC_TYPE(_ushort, 2)	/* ndt__ushort, ndt_s_ushort */
+MAKE_BASIC_TYPE(_long, 4)	/* ndt__long,  ndt_s_long */
+MAKE_BASIC_TYPE(_ulong, 4)	/* ndt__ulong, ndt_s_ulong */
+
+MAKE_BASIC_TYPE_BASE(_wchar, 2)	/* ndt__wchar, ndt_s_wchar */
+
+int
+ndr_basic_integer(ndr_ref_t *ref, unsigned size)
+{
+	ndr_stream_t 	*nds = ref->stream;
+	char 		*valp = (char *)ref->datum;
+	int		rc;
+
+	switch (nds->m_op) {
+	case NDR_M_OP_MARSHALL:
+		rc = NDS_PUT_PDU(nds, ref->pdu_offset, size,
+		    valp, nds->swap, ref);
+		break;
+
+	case NDR_M_OP_UNMARSHALL:
+		rc = NDS_GET_PDU(nds, ref->pdu_offset, size,
+		    valp, nds->swap, ref);
+		break;
+
+	default:
+		NDR_SET_ERROR(ref, NDR_ERR_M_OP_INVALID);
+		return (0);
+	}
+
+	return (rc);
+}
+
+int
+ndr_string_basic_integer(ndr_ref_t *encl_ref, ndr_typeinfo_t *type_under)
+{
+	unsigned long		pdu_offset = encl_ref->pdu_offset;
+	unsigned		size = type_under->pdu_size_fixed_part;
+	char			*valp;
+	ndr_ref_t		myref;
+	unsigned long		i;
+	long			sense = 0;
+	char			name[30];
+
+	assert(size != 0);
+
+	bzero(&myref, sizeof (myref));
+	myref.enclosing = encl_ref;
+	myref.stream = encl_ref->stream;
+	myref.packed_alignment = 0;
+	myref.ti = type_under;
+	myref.inner_flags = NDR_F_NONE;
+	myref.name = name;
+
+	for (i = 0; i < NDR_STRING_MAX; i++) {
+		(void) snprintf(name, sizeof (name), "[%lu]", i);
+		myref.pdu_offset = pdu_offset + i * size;
+		valp = encl_ref->datum + i * size;
+		myref.datum = valp;
+
+		if (!ndr_inner(&myref))
+			return (0);
+
+		switch (size) {
+		case 1:		sense = *valp; break;
+		/*LINTED E_BAD_PTR_CAST_ALIGN*/
+		case 2:		sense = *(short *)valp; break;
+		/*LINTED E_BAD_PTR_CAST_ALIGN*/
+		case 4:		sense = *(long *)valp; break;
+		}
+
+		if (!sense)
+			break;
+	}
+
+	return (1);
+}
+
+
+extern int ndr_s_wchar(ndr_ref_t *encl_ref);
+ndr_typeinfo_t ndt_s_wchar = {
+	1,		/* NDR version */
+	2-1,		/* alignment */
+	NDR_F_STRING,	/* flags */
+	ndr_s_wchar,	/* ndr_func */
+	0,		/* pdu_size_fixed_part */
+	2,		/* pdu_size_variable_part */
+	0,		/* c_size_fixed_part */
+	1,		/* c_size_variable_part */
+};
+
+
+/*
+ * Hand coded wchar function because all strings are transported
+ * as wide characters. During NDR_M_OP_MARSHALL, we convert from
+ * multi-byte to wide characters. During NDR_M_OP_UNMARSHALL, we
+ * convert from wide characters to multi-byte.
+ *
+ * The most critical thing to get right in this function is to
+ * marshall or unmarshall _exactly_ the number of elements the
+ * OtW length specifies, as saved by the caller in: strlen_is.
+ * Doing otherwise would leave us positioned at the wrong place
+ * in the data stream for whatever follows this.  Note that the
+ * string data covered by strlen_is may or may not include any
+ * null termination, but the converted string provided by the
+ * caller or returned always has a null terminator.
+ */
+int
+ndr_s_wchar(ndr_ref_t *encl_ref)
+{
+	ndr_stream_t		*nds = encl_ref->stream;
+	char 			*valp = encl_ref->datum;
+	ndr_ref_t		myref;
+	char			name[30];
+	ndr_wchar_t		wcs[NDR_STRING_MAX+1];
+	size_t			i, slen, wlen;
+
+	/* This is enforced in ndr_outer_string() */
+	assert(encl_ref->strlen_is <= NDR_STRING_MAX);
+
+	if (nds->m_op == NDR_M_OP_UNMARSHALL) {
+		/*
+		 * To avoid problems with zero length strings
+		 * we can just null terminate here and be done.
+		 */
+		if (encl_ref->strlen_is == 0) {
+			encl_ref->datum[0] = '\0';
+			return (1);
+		}
+	}
+
+	/*
+	 * If we're marshalling, convert the given string
+	 * from UTF-8 into a local UCS-2 string.
+	 */
+	if (nds->m_op == NDR_M_OP_MARSHALL) {
+		wlen = ndr__mbstowcs(wcs, valp, NDR_STRING_MAX);
+		if (wlen == (size_t)-1)
+			return (0);
+		/*
+		 * Add a nulls to make strlen_is.
+		 * (always zero or one of them)
+		 * Then null terminate at wlen,
+		 * just for debug convenience.
+		 */
+		while (wlen < encl_ref->strlen_is)
+			wcs[wlen++] = 0;
+		wcs[wlen] = 0;
+	}
+
+	/*
+	 * Copy wire data to or from the local wc string.
+	 * Always exactly strlen_is elements.
+	 */
+	bzero(&myref, sizeof (myref));
+	myref.enclosing = encl_ref;
+	myref.stream = encl_ref->stream;
+	myref.packed_alignment = 0;
+	myref.ti = &ndt__wchar;
+	myref.inner_flags = NDR_F_NONE;
+	myref.name = name;
+	myref.pdu_offset = encl_ref->pdu_offset;
+	myref.datum = (char *)wcs;
+	wlen = encl_ref->strlen_is;
+
+	for (i = 0; i < wlen; i++) {
+		(void) snprintf(name, sizeof (name), "[%lu]", i);
+		if (!ndr_inner(&myref))
+			return (0);
+		myref.pdu_offset += sizeof (ndr_wchar_t);
+		myref.datum	 += sizeof (ndr_wchar_t);
+	}
+
+	/*
+	 * If this is unmarshall, convert the local UCS-2 string
+	 * into a UTF-8 string in the caller's buffer.  The caller
+	 * previously determined the space required and provides a
+	 * buffer of sufficient size.
+	 */
+	if (nds->m_op == NDR_M_OP_UNMARSHALL) {
+		wcs[wlen] = 0;
+		slen = ndr__wcstombs(valp, wcs, wlen);
+		if (slen == (size_t)-1)
+			return (0);
+		valp[slen] = '\0';
+	}
+
+	return (1);
+}
+
+/*
+ * Converts a multibyte character string to a little-endian, wide-char
+ * string.  No more than nwchars wide characters are stored.
+ * A terminating null wide character is appended if there is room.
+ *
+ * Returns the number of wide characters converted, not counting
+ * any terminating null wide character.  Returns -1 if an invalid
+ * multibyte character is encountered.
+ */
+/* ARGSUSED */
+size_t
+ndr_mbstowcs(ndr_stream_t *nds, ndr_wchar_t *wcs, const char *mbs,
+    size_t nwchars)
+{
+	size_t len;
+
+#ifdef _BIG_ENDIAN
+	if (nds == NULL || NDR_MODE_MATCH(nds, NDR_MODE_RETURN_SEND)) {
+		/* Make WC string in LE order. */
+		len = ndr__mbstowcs_le(wcs, mbs, nwchars);
+	} else
+#endif
+		len = ndr__mbstowcs(wcs, mbs, nwchars);
+
+	return (len);
+}
--- old/usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c	Sun Mar 18 01:13:17 2018
+++ /dev/null	Sun Mar 18 01:13:16 2018
@@ -1,838 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
- */
-
-/*
- * Server side RPC handler.
- */
-
-#include <sys/byteorder.h>
-#include <sys/uio.h>
-#include <errno.h>
-#include <synch.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <string.h>
-#include <thread.h>
-
-#include <smbsrv/libsmb.h>
-#include <smbsrv/libmlrpc.h>
-#include <smbsrv/ntaccess.h>
-
-#define	NDR_PIPE_SEND(np, buf, len) \
-	((np)->np_send)((np), (buf), (len))
-#define	NDR_PIPE_RECV(np, buf, len) \
-	((np)->np_recv)((np), (buf), (len))
-
-static int ndr_svc_process(ndr_xa_t *);
-static int ndr_svc_bind(ndr_xa_t *);
-static int ndr_svc_request(ndr_xa_t *);
-static void ndr_reply_prepare_hdr(ndr_xa_t *);
-static int ndr_svc_alter_context(ndr_xa_t *);
-static void ndr_reply_fault(ndr_xa_t *, unsigned long);
-
-static int ndr_recv_request(ndr_xa_t *mxa);
-static int ndr_recv_frag(ndr_xa_t *mxa);
-static int ndr_send_reply(ndr_xa_t *);
-
-static int ndr_pipe_process(ndr_pipe_t *, ndr_xa_t *);
-
-/*
- * External entry point called by smbd.
- */
-void
-ndr_pipe_worker(ndr_pipe_t *np)
-{
-	ndr_xa_t	*mxa;
-	int rc;
-
-	ndr_svc_binding_pool_init(&np->np_binding, np->np_binding_pool,
-	    NDR_N_BINDING_POOL);
-
-	if ((mxa = malloc(sizeof (*mxa))) == NULL)
-		return;
-
-	do {
-		bzero(mxa, sizeof (*mxa));
-		rc = ndr_pipe_process(np, mxa);
-	} while (rc == 0);
-
-	free(mxa);
-
-	/*
-	 * Ensure that there are no RPC service policy handles
-	 * (associated with this fid) left around.
-	 */
-	ndr_hdclose(np);
-}
-
-/*
- * Process one server-side RPC request.
- */
-static int
-ndr_pipe_process(ndr_pipe_t *np, ndr_xa_t *mxa)
-{
-	ndr_stream_t	*recv_nds;
-	ndr_stream_t	*send_nds;
-	int		rc = ENOMEM;
-
-	mxa->pipe = np;
-	mxa->binding_list = np->np_binding;
-
-	if ((mxa->heap = ndr_heap_create()) == NULL)
-		goto out1;
-
-	recv_nds = &mxa->recv_nds;
-	rc = nds_initialize(recv_nds, 0, NDR_MODE_CALL_RECV, mxa->heap);
-	if (rc != 0)
-		goto out2;
-
-	send_nds = &mxa->send_nds;
-	rc = nds_initialize(send_nds, 0, NDR_MODE_RETURN_SEND, mxa->heap);
-	if (rc != 0)
-		goto out3;
-
-	rc = ndr_recv_request(mxa);
-	if (rc != 0)
-		goto out4;
-
-	(void) ndr_svc_process(mxa);
-	(void) ndr_send_reply(mxa);
-	rc = 0;
-
-out4:
-	nds_destruct(&mxa->send_nds);
-out3:
-	nds_destruct(&mxa->recv_nds);
-out2:
-	ndr_heap_destroy(mxa->heap);
-out1:
-	return (rc);
-}
-
-/*
- * Check whether or not the specified user has administrator privileges,
- * i.e. is a member of Domain Admins or Administrators.
- * Returns true if the user is an administrator, otherwise returns false.
- */
-boolean_t
-ndr_is_admin(ndr_xa_t *xa)
-{
-	smb_netuserinfo_t *ctx = xa->pipe->np_user;
-
-	return (ctx->ui_flags & SMB_ATF_ADMIN);
-}
-
-/*
- * Check whether or not the specified user has power-user privileges,
- * i.e. is a member of Domain Admins, Administrators or Power Users.
- * This is typically required for operations such as managing shares.
- * Returns true if the user is a power user, otherwise returns false.
- */
-boolean_t
-ndr_is_poweruser(ndr_xa_t *xa)
-{
-	smb_netuserinfo_t *ctx = xa->pipe->np_user;
-
-	return ((ctx->ui_flags & SMB_ATF_ADMIN) ||
-	    (ctx->ui_flags & SMB_ATF_POWERUSER));
-}
-
-int32_t
-ndr_native_os(ndr_xa_t *xa)
-{
-	smb_netuserinfo_t *ctx = xa->pipe->np_user;
-
-	return (ctx->ui_native_os);
-}
-
-/*
- * Receive an entire RPC request (all fragments)
- * Returns zero or an NDR fault code.
- */
-static int
-ndr_recv_request(ndr_xa_t *mxa)
-{
-	ndr_common_header_t	*hdr = &mxa->recv_hdr.common_hdr;
-	ndr_stream_t		*nds = &mxa->recv_nds;
-	unsigned long		saved_size;
-	int			rc;
-
-	rc = ndr_recv_frag(mxa);
-	if (rc != 0)
-		return (rc);
-	if (!NDR_IS_FIRST_FRAG(hdr->pfc_flags))
-		return (NDR_DRC_FAULT_DECODE_FAILED);
-
-	while (!NDR_IS_LAST_FRAG(hdr->pfc_flags)) {
-		rc = ndr_recv_frag(mxa);
-		if (rc != 0)
-			return (rc);
-	}
-	nds->pdu_scan_offset = 0;
-
-	/*
-	 * This whacks nds->pdu_size, so save/restore.
-	 * It leaves scan_offset after the header.
-	 */
-	saved_size = nds->pdu_size;
-	rc = ndr_decode_pdu_hdr(mxa);
-	nds->pdu_size = saved_size;
-
-	return (rc);
-}
-
-/*
- * Read one fragment, leaving the decoded frag header in
- * recv_hdr.common_hdr, and the data in the recv_nds.
- *
- * Returns zero or an NDR fault code.
- *
- * If a first frag, the header is included in the data
- * placed in recv_nds (because it's not fully decoded
- * until later - we only decode the common part here).
- * Additional frags are placed in the recv_nds without
- * the header, so that after the first frag header,
- * the remaining data will be contiguous.  We do this
- * by simply not advancing the offset in recv_nds after
- * reading and decoding these additional fragments, so
- * the payload of such frags will overwrite what was
- * (temporarily) the frag header.
- */
-static int
-ndr_recv_frag(ndr_xa_t *mxa)
-{
-	ndr_common_header_t	*hdr = &mxa->recv_hdr.common_hdr;
-	ndr_stream_t		*nds = &mxa->recv_nds;
-	unsigned char		*data;
-	unsigned long		next_offset;
-	unsigned long		pay_size;
-	int			rc;
-
-	/* Make room for the frag header. */
-	next_offset = nds->pdu_scan_offset + NDR_RSP_HDR_SIZE;
-	if (!NDS_GROW_PDU(nds, next_offset, 0))
-		return (NDR_DRC_FAULT_OUT_OF_MEMORY);
-
-	/* Read the frag header. */
-	data = nds->pdu_base_addr + nds->pdu_scan_offset;
-	rc = NDR_PIPE_RECV(mxa->pipe, data, NDR_RSP_HDR_SIZE);
-	if (rc != 0)
-		return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT);
-
-	/*
-	 * Decode the frag header, get the length.
-	 * NB: It uses nds->pdu_scan_offset
-	 */
-	ndr_decode_frag_hdr(nds, hdr);
-	ndr_show_hdr(hdr);
-	if (hdr->frag_length < NDR_RSP_HDR_SIZE ||
-	    hdr->frag_length > mxa->pipe->np_max_xmit_frag)
-		return (NDR_DRC_FAULT_DECODE_FAILED);
-
-	if (nds->pdu_scan_offset == 0) {
-		/* First frag: header stays in the data. */
-		nds->pdu_scan_offset = next_offset;
-	} /* else overwrite with the payload */
-
-	/* Make room for the payload. */
-	pay_size = hdr->frag_length - NDR_RSP_HDR_SIZE;
-	next_offset = nds->pdu_scan_offset + pay_size;
-	if (!NDS_GROW_PDU(nds, next_offset, 0))
-		return (NDR_DRC_FAULT_OUT_OF_MEMORY);
-
-	/* Read the payload. */
-	data = nds->pdu_base_addr + nds->pdu_scan_offset;
-	rc = NDR_PIPE_RECV(mxa->pipe, data, pay_size);
-	if (rc != 0)
-		return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT);
-	nds->pdu_scan_offset = next_offset;
-
-	return (NDR_DRC_OK);
-}
-
-/*
- * This is the entry point for all server-side RPC processing.
- * It is assumed that the PDU has already been received.
- */
-static int
-ndr_svc_process(ndr_xa_t *mxa)
-{
-	int			rc;
-
-	(void) ndr_reply_prepare_hdr(mxa);
-
-	switch (mxa->ptype) {
-	case NDR_PTYPE_BIND:
-		rc = ndr_svc_bind(mxa);
-		break;
-
-	case NDR_PTYPE_REQUEST:
-		rc = ndr_svc_request(mxa);
-		break;
-
-	case NDR_PTYPE_ALTER_CONTEXT:
-		rc = ndr_svc_alter_context(mxa);
-		break;
-
-	default:
-		rc = NDR_DRC_FAULT_RPCHDR_PTYPE_INVALID;
-		break;
-	}
-
-	if (NDR_DRC_IS_FAULT(rc))
-		ndr_reply_fault(mxa, rc);
-
-	return (rc);
-}
-
-/*
- * Multiple p_cont_elem[]s, multiple transfer_syntaxes[] and multiple
- * p_results[] not supported.
- */
-static int
-ndr_svc_bind(ndr_xa_t *mxa)
-{
-	ndr_p_cont_list_t	*cont_list;
-	ndr_p_result_list_t	*result_list;
-	ndr_p_result_t		*result;
-	unsigned		p_cont_id;
-	ndr_binding_t		*mbind;
-	ndr_uuid_t		*as_uuid;
-	ndr_uuid_t		*ts_uuid;
-	int			as_vers;
-	int			ts_vers;
-	ndr_service_t		*msvc;
-	int			rc;
-	ndr_port_any_t		*sec_addr;
-
-	/* acquire targets */
-	cont_list = &mxa->recv_hdr.bind_hdr.p_context_elem;
-	result_list = &mxa->send_hdr.bind_ack_hdr.p_result_list;
-	result = &result_list->p_results[0];
-
-	/*
-	 * Set up temporary secondary address port.
-	 * We will correct this later (below).
-	 */
-	sec_addr = &mxa->send_hdr.bind_ack_hdr.sec_addr;
-	sec_addr->length = 13;
-	(void) strcpy((char *)sec_addr->port_spec, "\\PIPE\\ntsvcs");
-
-	result_list->n_results = 1;
-	result_list->reserved = 0;
-	result_list->reserved2 = 0;
-	result->result = NDR_PCDR_ACCEPTANCE;
-	result->reason = 0;
-	bzero(&result->transfer_syntax, sizeof (result->transfer_syntax));
-
-	/* sanity check */
-	if (cont_list->n_context_elem != 1 ||
-	    cont_list->p_cont_elem[0].n_transfer_syn != 1) {
-		ndo_trace("ndr_svc_bind: warning: multiple p_cont_elem");
-	}
-
-	p_cont_id = cont_list->p_cont_elem[0].p_cont_id;
-
-	if ((mbind = ndr_svc_find_binding(mxa, p_cont_id)) != NULL) {
-		/*
-		 * Duplicate presentation context id.
-		 */
-		ndo_trace("ndr_svc_bind: duplicate binding");
-		return (NDR_DRC_FAULT_BIND_PCONT_BUSY);
-	}
-
-	if ((mbind = ndr_svc_new_binding(mxa)) == NULL) {
-		/*
-		 * No free binding slot
-		 */
-		result->result = NDR_PCDR_PROVIDER_REJECTION;
-		result->reason = NDR_PPR_LOCAL_LIMIT_EXCEEDED;
-		ndo_trace("ndr_svc_bind: no resources");
-		return (NDR_DRC_OK);
-	}
-
-	as_uuid = &cont_list->p_cont_elem[0].abstract_syntax.if_uuid;
-	as_vers = cont_list->p_cont_elem[0].abstract_syntax.if_version;
-
-	ts_uuid = &cont_list->p_cont_elem[0].transfer_syntaxes[0].if_uuid;
-	ts_vers = cont_list->p_cont_elem[0].transfer_syntaxes[0].if_version;
-
-	msvc = ndr_svc_lookup_uuid(as_uuid, as_vers, ts_uuid, ts_vers);
-	if (msvc == NULL) {
-		result->result = NDR_PCDR_PROVIDER_REJECTION;
-		result->reason = NDR_PPR_ABSTRACT_SYNTAX_NOT_SUPPORTED;
-		return (NDR_DRC_OK);
-	}
-
-	/*
-	 * We can now use the correct secondary address port.
-	 */
-	sec_addr = &mxa->send_hdr.bind_ack_hdr.sec_addr;
-	sec_addr->length = strlen(msvc->sec_addr_port) + 1;
-	(void) strlcpy((char *)sec_addr->port_spec, msvc->sec_addr_port,
-	    NDR_PORT_ANY_MAX_PORT_SPEC);
-
-	mbind->p_cont_id = p_cont_id;
-	mbind->which_side = NDR_BIND_SIDE_SERVER;
-	/* mbind->context set by app */
-	mbind->service = msvc;
-	mbind->instance_specific = 0;
-
-	mxa->binding = mbind;
-
-	if (msvc->bind_req) {
-		/*
-		 * Call the service-specific bind() handler.  If
-		 * this fails, we shouild send a specific error
-		 * on the bind ack.
-		 */
-		rc = (msvc->bind_req)(mxa);
-		if (NDR_DRC_IS_FAULT(rc)) {
-			mbind->service = 0;	/* free binding slot */
-			mbind->which_side = 0;
-			mbind->p_cont_id = 0;
-			mbind->instance_specific = 0;
-			return (rc);
-		}
-	}
-
-	result->transfer_syntax =
-	    cont_list->p_cont_elem[0].transfer_syntaxes[0];
-
-	return (NDR_DRC_BINDING_MADE);
-}
-
-/*
- * ndr_svc_alter_context
- *
- * The alter context request is used to request additional presentation
- * context for another interface and/or version.  It is very similar to
- * a bind request.
- */
-static int
-ndr_svc_alter_context(ndr_xa_t *mxa)
-{
-	ndr_p_result_list_t *result_list;
-	ndr_p_result_t *result;
-	ndr_p_cont_list_t *cont_list;
-	ndr_binding_t *mbind;
-	ndr_service_t *msvc;
-	unsigned p_cont_id;
-	ndr_uuid_t *as_uuid;
-	ndr_uuid_t *ts_uuid;
-	int as_vers;
-	int ts_vers;
-	ndr_port_any_t *sec_addr;
-
-	result_list = &mxa->send_hdr.alter_context_rsp_hdr.p_result_list;
-	result_list->n_results = 1;
-	result_list->reserved = 0;
-	result_list->reserved2 = 0;
-
-	result = &result_list->p_results[0];
-	result->result = NDR_PCDR_ACCEPTANCE;
-	result->reason = 0;
-	bzero(&result->transfer_syntax, sizeof (result->transfer_syntax));
-
-	cont_list = &mxa->recv_hdr.alter_context_hdr.p_context_elem;
-	p_cont_id = cont_list->p_cont_elem[0].p_cont_id;
-
-	if (ndr_svc_find_binding(mxa, p_cont_id) != NULL)
-		return (NDR_DRC_FAULT_BIND_PCONT_BUSY);
-
-	if ((mbind = ndr_svc_new_binding(mxa)) == NULL) {
-		result->result = NDR_PCDR_PROVIDER_REJECTION;
-		result->reason = NDR_PPR_LOCAL_LIMIT_EXCEEDED;
-		return (NDR_DRC_OK);
-	}
-
-	as_uuid = &cont_list->p_cont_elem[0].abstract_syntax.if_uuid;
-	as_vers = cont_list->p_cont_elem[0].abstract_syntax.if_version;
-
-	ts_uuid = &cont_list->p_cont_elem[0].transfer_syntaxes[0].if_uuid;
-	ts_vers = cont_list->p_cont_elem[0].transfer_syntaxes[0].if_version;
-
-	msvc = ndr_svc_lookup_uuid(as_uuid, as_vers, ts_uuid, ts_vers);
-	if (msvc == NULL) {
-		result->result = NDR_PCDR_PROVIDER_REJECTION;
-		result->reason = NDR_PPR_ABSTRACT_SYNTAX_NOT_SUPPORTED;
-		return (NDR_DRC_OK);
-	}
-
-	mbind->p_cont_id = p_cont_id;
-	mbind->which_side = NDR_BIND_SIDE_SERVER;
-	/* mbind->context set by app */
-	mbind->service = msvc;
-	mbind->instance_specific = 0;
-	mxa->binding = mbind;
-
-	sec_addr = &mxa->send_hdr.alter_context_rsp_hdr.sec_addr;
-	sec_addr->length = 0;
-	bzero(sec_addr->port_spec, NDR_PORT_ANY_MAX_PORT_SPEC);
-
-	result->transfer_syntax =
-	    cont_list->p_cont_elem[0].transfer_syntaxes[0];
-
-	return (NDR_DRC_BINDING_MADE);
-}
-
-static int
-ndr_svc_request(ndr_xa_t *mxa)
-{
-	ndr_binding_t	*mbind;
-	ndr_service_t	*msvc;
-	unsigned	p_cont_id;
-	int		rc;
-
-	mxa->opnum = mxa->recv_hdr.request_hdr.opnum;
-	p_cont_id = mxa->recv_hdr.request_hdr.p_cont_id;
-
-	if ((mbind = ndr_svc_find_binding(mxa, p_cont_id)) == NULL)
-		return (NDR_DRC_FAULT_REQUEST_PCONT_INVALID);
-
-	mxa->binding = mbind;
-	msvc = mbind->service;
-
-	/*
-	 * Make room for the response hdr.
-	 */
-	mxa->send_nds.pdu_scan_offset = NDR_RSP_HDR_SIZE;
-
-	if (msvc->call_stub)
-		rc = (*msvc->call_stub)(mxa);
-	else
-		rc = ndr_generic_call_stub(mxa);
-
-	if (NDR_DRC_IS_FAULT(rc)) {
-		ndo_printf(0, 0, "%s[0x%02x]: 0x%04x",
-		    msvc->name, mxa->opnum, rc);
-	}
-
-	return (rc);
-}
-
-/*
- * The transaction and the two nds streams use the same heap, which
- * should already exist at this point.  The heap will also be available
- * to the stub.
- */
-int
-ndr_generic_call_stub(ndr_xa_t *mxa)
-{
-	ndr_binding_t 		*mbind = mxa->binding;
-	ndr_service_t		*msvc = mbind->service;
-	ndr_typeinfo_t		*intf_ti = msvc->interface_ti;
-	ndr_stub_table_t	*ste;
-	int			opnum = mxa->opnum;
-	unsigned		p_len = intf_ti->c_size_fixed_part;
-	char 			*param;
-	int			rc;
-
-	if (mxa->heap == NULL) {
-		ndo_printf(0, 0, "%s[0x%02x]: no heap", msvc->name, opnum);
-		return (NDR_DRC_FAULT_OUT_OF_MEMORY);
-	}
-
-	if ((ste = ndr_svc_find_stub(msvc, opnum)) == NULL) {
-		ndo_printf(0, 0, "%s[0x%02x]: invalid opnum",
-		    msvc->name, opnum);
-		return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID);
-	}
-
-	if ((param = ndr_heap_malloc(mxa->heap, p_len)) == NULL)
-		return (NDR_DRC_FAULT_OUT_OF_MEMORY);
-
-	bzero(param, p_len);
-
-	rc = ndr_decode_call(mxa, param);
-	if (!NDR_DRC_IS_OK(rc))
-		return (rc);
-
-	rc = (*ste->func)(param, mxa);
-	if (rc == NDR_DRC_OK)
-		rc = ndr_encode_return(mxa, param);
-
-	return (rc);
-}
-
-/*
- * We can perform some initial setup of the response header here.
- * We also need to cache some of the information from the bind
- * negotiation for use during subsequent RPC calls.
- */
-static void
-ndr_reply_prepare_hdr(ndr_xa_t *mxa)
-{
-	ndr_common_header_t *rhdr = &mxa->recv_hdr.common_hdr;
-	ndr_common_header_t *hdr = &mxa->send_hdr.common_hdr;
-
-	hdr->rpc_vers = 5;
-	hdr->rpc_vers_minor = 0;
-	hdr->pfc_flags = NDR_PFC_FIRST_FRAG + NDR_PFC_LAST_FRAG;
-	hdr->packed_drep = rhdr->packed_drep;
-	hdr->frag_length = 0;
-	hdr->auth_length = 0;
-	hdr->call_id = rhdr->call_id;
-#ifdef _BIG_ENDIAN
-	hdr->packed_drep.intg_char_rep = NDR_REPLAB_CHAR_ASCII
-	    | NDR_REPLAB_INTG_BIG_ENDIAN;
-#else
-	hdr->packed_drep.intg_char_rep = NDR_REPLAB_CHAR_ASCII
-	    | NDR_REPLAB_INTG_LITTLE_ENDIAN;
-#endif
-
-	switch (mxa->ptype) {
-	case NDR_PTYPE_BIND:
-		/*
-		 * Compute the maximum fragment sizes for xmit/recv
-		 * and store in the pipe endpoint.  Note "xmit" is
-		 * client-to-server; "recv" is server-to-client.
-		 */
-		if (mxa->pipe->np_max_xmit_frag >
-		    mxa->recv_hdr.bind_hdr.max_xmit_frag)
-			mxa->pipe->np_max_xmit_frag =
-			    mxa->recv_hdr.bind_hdr.max_xmit_frag;
-		if (mxa->pipe->np_max_recv_frag >
-		    mxa->recv_hdr.bind_hdr.max_recv_frag)
-			mxa->pipe->np_max_recv_frag =
-			    mxa->recv_hdr.bind_hdr.max_recv_frag;
-
-		hdr->ptype = NDR_PTYPE_BIND_ACK;
-		mxa->send_hdr.bind_ack_hdr.max_xmit_frag =
-		    mxa->pipe->np_max_xmit_frag;
-		mxa->send_hdr.bind_ack_hdr.max_recv_frag =
-		    mxa->pipe->np_max_recv_frag;
-
-		/*
-		 * We're supposed to assign a unique "assoc group"
-		 * (identifies this connection for the client).
-		 * Using the pipe address is adequate.
-		 */
-		mxa->send_hdr.bind_ack_hdr.assoc_group_id =
-		    mxa->recv_hdr.bind_hdr.assoc_group_id;
-		if (mxa->send_hdr.bind_ack_hdr.assoc_group_id == 0)
-			mxa->send_hdr.bind_ack_hdr.assoc_group_id =
-			    (DWORD)(uintptr_t)mxa->pipe;
-
-		break;
-
-	case NDR_PTYPE_REQUEST:
-		hdr->ptype = NDR_PTYPE_RESPONSE;
-		/* mxa->send_hdr.response_hdr.alloc_hint */
-		mxa->send_hdr.response_hdr.p_cont_id =
-		    mxa->recv_hdr.request_hdr.p_cont_id;
-		mxa->send_hdr.response_hdr.cancel_count = 0;
-		mxa->send_hdr.response_hdr.reserved = 0;
-		break;
-
-	case NDR_PTYPE_ALTER_CONTEXT:
-		hdr->ptype = NDR_PTYPE_ALTER_CONTEXT_RESP;
-		/*
-		 * The max_xmit_frag, max_recv_frag and assoc_group_id are
-		 * ignored by the client but it's useful to fill them in.
-		 */
-		mxa->send_hdr.alter_context_rsp_hdr.max_xmit_frag =
-		    mxa->recv_hdr.alter_context_hdr.max_xmit_frag;
-		mxa->send_hdr.alter_context_rsp_hdr.max_recv_frag =
-		    mxa->recv_hdr.alter_context_hdr.max_recv_frag;
-		mxa->send_hdr.alter_context_rsp_hdr.assoc_group_id =
-		    mxa->recv_hdr.alter_context_hdr.assoc_group_id;
-		break;
-
-	default:
-		hdr->ptype = 0xFF;
-	}
-}
-
-/*
- * Signal an RPC fault. The stream is reset and we overwrite whatever
- * was in the response header with the fault information.
- */
-static void
-ndr_reply_fault(ndr_xa_t *mxa, unsigned long drc)
-{
-	ndr_common_header_t *rhdr = &mxa->recv_hdr.common_hdr;
-	ndr_common_header_t *hdr = &mxa->send_hdr.common_hdr;
-	ndr_stream_t *nds = &mxa->send_nds;
-	unsigned long fault_status;
-
-	NDS_RESET(nds);
-
-	hdr->rpc_vers = 5;
-	hdr->rpc_vers_minor = 0;
-	hdr->pfc_flags = NDR_PFC_FIRST_FRAG + NDR_PFC_LAST_FRAG;
-	hdr->packed_drep = rhdr->packed_drep;
-	hdr->frag_length = sizeof (mxa->send_hdr.fault_hdr);
-	hdr->auth_length = 0;
-	hdr->call_id = rhdr->call_id;
-#ifdef _BIG_ENDIAN
-	hdr->packed_drep.intg_char_rep = NDR_REPLAB_CHAR_ASCII
-	    | NDR_REPLAB_INTG_BIG_ENDIAN;
-#else
-	hdr->packed_drep.intg_char_rep = NDR_REPLAB_CHAR_ASCII
-	    | NDR_REPLAB_INTG_LITTLE_ENDIAN;
-#endif
-
-	switch (drc & NDR_DRC_MASK_SPECIFIER) {
-	case NDR_DRC_FAULT_OUT_OF_MEMORY:
-	case NDR_DRC_FAULT_ENCODE_TOO_BIG:
-		fault_status = NDR_FAULT_NCA_OUT_ARGS_TOO_BIG;
-		break;
-
-	case NDR_DRC_FAULT_REQUEST_PCONT_INVALID:
-		fault_status = NDR_FAULT_NCA_INVALID_PRES_CONTEXT_ID;
-		break;
-
-	case NDR_DRC_FAULT_REQUEST_OPNUM_INVALID:
-		fault_status = NDR_FAULT_NCA_OP_RNG_ERROR;
-		break;
-
-	case NDR_DRC_FAULT_DECODE_FAILED:
-	case NDR_DRC_FAULT_ENCODE_FAILED:
-		fault_status = NDR_FAULT_NCA_PROTO_ERROR;
-		break;
-
-	default:
-		fault_status = NDR_FAULT_NCA_UNSPEC_REJECT;
-		break;
-	}
-
-	mxa->send_hdr.fault_hdr.common_hdr.ptype = NDR_PTYPE_FAULT;
-	mxa->send_hdr.fault_hdr.status = fault_status;
-	mxa->send_hdr.response_hdr.alloc_hint = hdr->frag_length;
-}
-
-/*
- * Note that the frag_length for bind ack and alter context is
- * non-standard.
- */
-static int
-ndr_send_reply(ndr_xa_t *mxa)
-{
-	ndr_common_header_t *hdr = &mxa->send_hdr.common_hdr;
-	ndr_stream_t *nds = &mxa->send_nds;
-	uint8_t *pdu_buf;
-	unsigned long pdu_size;
-	unsigned long frag_size;
-	unsigned long pdu_data_size;
-	unsigned long frag_data_size;
-
-	frag_size = mxa->pipe->np_max_recv_frag;
-	pdu_size = nds->pdu_size;
-	pdu_buf = nds->pdu_base_addr;
-
-	if (pdu_size <= frag_size) {
-		/*
-		 * Single fragment response. The PDU size may be zero
-		 * here (i.e. bind or fault response). So don't make
-		 * any assumptions about it until after the header is
-		 * encoded.
-		 */
-		switch (hdr->ptype) {
-		case NDR_PTYPE_BIND_ACK:
-			hdr->frag_length = ndr_bind_ack_hdr_size(mxa);
-			break;
-
-		case NDR_PTYPE_FAULT:
-			/* already setup */
-			break;
-
-		case NDR_PTYPE_RESPONSE:
-			hdr->frag_length = pdu_size;
-			mxa->send_hdr.response_hdr.alloc_hint =
-			    hdr->frag_length;
-			break;
-
-		case NDR_PTYPE_ALTER_CONTEXT_RESP:
-			hdr->frag_length = ndr_alter_context_rsp_hdr_size();
-			break;
-
-		default:
-			hdr->frag_length = pdu_size;
-			break;
-		}
-
-		nds->pdu_scan_offset = 0;
-		(void) ndr_encode_pdu_hdr(mxa);
-		pdu_size = nds->pdu_size;
-		(void) NDR_PIPE_SEND(mxa->pipe, pdu_buf, pdu_size);
-		return (0);
-	}
-
-	/*
-	 * Multiple fragment response.
-	 *
-	 * We need to update the RPC header for every fragment.
-	 *
-	 * pdu_data_size:	total data remaining to be handled
-	 * frag_size:		total fragment size including header
-	 * frag_data_size:	data in fragment
-	 *			(i.e. frag_size - NDR_RSP_HDR_SIZE)
-	 */
-	pdu_data_size = pdu_size - NDR_RSP_HDR_SIZE;
-	frag_data_size = frag_size - NDR_RSP_HDR_SIZE;
-
-	/*
-	 * Send the first frag.
-	 */
-	hdr->pfc_flags = NDR_PFC_FIRST_FRAG;
-	hdr->frag_length = frag_size;
-	mxa->send_hdr.response_hdr.alloc_hint = pdu_data_size;
-	nds->pdu_scan_offset = 0;
-	(void) ndr_encode_pdu_hdr(mxa);
-	(void) NDR_PIPE_SEND(mxa->pipe, pdu_buf, frag_size);
-	pdu_data_size -= frag_data_size;
-	pdu_buf += frag_data_size;
-
-	/*
-	 * Send "middle" (full-sized) fragments...
-	 */
-	hdr->pfc_flags = 0;
-	while (pdu_data_size > frag_data_size) {
-
-		hdr->frag_length = frag_size;
-		mxa->send_hdr.response_hdr.alloc_hint = pdu_data_size;
-		nds->pdu_scan_offset = 0;
-		(void) ndr_encode_pdu_hdr(mxa);
-		bcopy(nds->pdu_base_addr, pdu_buf, NDR_RSP_HDR_SIZE);
-		(void) NDR_PIPE_SEND(mxa->pipe, pdu_buf, frag_size);
-		pdu_data_size -= frag_data_size;
-		pdu_buf += frag_data_size;
-	}
-
-	/*
-	 * Last frag (pdu_data_size <= frag_data_size)
-	 */
-	hdr->pfc_flags = NDR_PFC_LAST_FRAG;
-	frag_size = pdu_data_size + NDR_RSP_HDR_SIZE;
-	hdr->frag_length = frag_size;
-	mxa->send_hdr.response_hdr.alloc_hint = pdu_data_size;
-	nds->pdu_scan_offset = 0;
-	(void) ndr_encode_pdu_hdr(mxa);
-	bcopy(nds->pdu_base_addr, pdu_buf, NDR_RSP_HDR_SIZE);
-	(void) NDR_PIPE_SEND(mxa->pipe, pdu_buf, frag_size);
-
-	return (0);
-}
--- /dev/null	Sun Mar 18 01:13:16 2018
+++ new/usr/src/lib/libmlrpc/common/ndr_server.c	Sun Mar 18 01:13:17 2018
@@ -0,0 +1,800 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+/*
+ * Server side RPC handler.
+ */
+
+#include <sys/byteorder.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <synch.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <string.h>
+#include <thread.h>
+
+#include <libmlrpc.h>
+
+#define	NDR_PIPE_SEND(np, buf, len) \
+	((np)->np_send)((np), (buf), (len))
+#define	NDR_PIPE_RECV(np, buf, len) \
+	((np)->np_recv)((np), (buf), (len))
+
+static int ndr_svc_process(ndr_xa_t *);
+static int ndr_svc_bind(ndr_xa_t *);
+static int ndr_svc_request(ndr_xa_t *);
+static void ndr_reply_prepare_hdr(ndr_xa_t *);
+static int ndr_svc_alter_context(ndr_xa_t *);
+static void ndr_reply_fault(ndr_xa_t *, unsigned long);
+
+static int ndr_recv_request(ndr_xa_t *mxa);
+static int ndr_recv_frag(ndr_xa_t *mxa);
+static int ndr_send_reply(ndr_xa_t *);
+
+static int ndr_pipe_process(ndr_pipe_t *, ndr_xa_t *);
+
+/*
+ * External entry point called by smbd.
+ */
+void
+ndr_pipe_worker(ndr_pipe_t *np)
+{
+	ndr_xa_t	*mxa;
+	int rc;
+
+	ndr_svc_binding_pool_init(&np->np_binding, np->np_binding_pool,
+	    NDR_N_BINDING_POOL);
+
+	if ((mxa = malloc(sizeof (*mxa))) == NULL)
+		return;
+
+	do {
+		bzero(mxa, sizeof (*mxa));
+		rc = ndr_pipe_process(np, mxa);
+	} while (rc == 0);
+
+	free(mxa);
+
+	/*
+	 * Ensure that there are no RPC service policy handles
+	 * (associated with this fid) left around.
+	 */
+	ndr_hdclose(np);
+}
+
+/*
+ * Process one server-side RPC request.
+ */
+static int
+ndr_pipe_process(ndr_pipe_t *np, ndr_xa_t *mxa)
+{
+	ndr_stream_t	*recv_nds;
+	ndr_stream_t	*send_nds;
+	int		rc = ENOMEM;
+
+	mxa->pipe = np;
+	mxa->binding_list = np->np_binding;
+
+	if ((mxa->heap = ndr_heap_create()) == NULL)
+		goto out1;
+
+	recv_nds = &mxa->recv_nds;
+	rc = nds_initialize(recv_nds, 0, NDR_MODE_CALL_RECV, mxa->heap);
+	if (rc != 0)
+		goto out2;
+
+	send_nds = &mxa->send_nds;
+	rc = nds_initialize(send_nds, 0, NDR_MODE_RETURN_SEND, mxa->heap);
+	if (rc != 0)
+		goto out3;
+
+	rc = ndr_recv_request(mxa);
+	if (rc != 0)
+		goto out4;
+
+	(void) ndr_svc_process(mxa);
+	(void) ndr_send_reply(mxa);
+	rc = 0;
+
+out4:
+	nds_destruct(&mxa->send_nds);
+out3:
+	nds_destruct(&mxa->recv_nds);
+out2:
+	ndr_heap_destroy(mxa->heap);
+out1:
+	return (rc);
+}
+
+/*
+ * Receive an entire RPC request (all fragments)
+ * Returns zero or an NDR fault code.
+ */
+static int
+ndr_recv_request(ndr_xa_t *mxa)
+{
+	ndr_common_header_t	*hdr = &mxa->recv_hdr.common_hdr;
+	ndr_stream_t		*nds = &mxa->recv_nds;
+	unsigned long		saved_size;
+	int			rc;
+
+	rc = ndr_recv_frag(mxa);
+	if (rc != 0)
+		return (rc);
+	if (!NDR_IS_FIRST_FRAG(hdr->pfc_flags))
+		return (NDR_DRC_FAULT_DECODE_FAILED);
+
+	while (!NDR_IS_LAST_FRAG(hdr->pfc_flags)) {
+		rc = ndr_recv_frag(mxa);
+		if (rc != 0)
+			return (rc);
+	}
+	nds->pdu_scan_offset = 0;
+
+	/*
+	 * This whacks nds->pdu_size, so save/restore.
+	 * It leaves scan_offset after the header.
+	 */
+	saved_size = nds->pdu_size;
+	rc = ndr_decode_pdu_hdr(mxa);
+	nds->pdu_size = saved_size;
+
+	return (rc);
+}
+
+/*
+ * Read one fragment, leaving the decoded frag header in
+ * recv_hdr.common_hdr, and the data in the recv_nds.
+ *
+ * Returns zero or an NDR fault code.
+ *
+ * If a first frag, the header is included in the data
+ * placed in recv_nds (because it's not fully decoded
+ * until later - we only decode the common part here).
+ * Additional frags are placed in the recv_nds without
+ * the header, so that after the first frag header,
+ * the remaining data will be contiguous.  We do this
+ * by simply not advancing the offset in recv_nds after
+ * reading and decoding these additional fragments, so
+ * the payload of such frags will overwrite what was
+ * (temporarily) the frag header.
+ */
+static int
+ndr_recv_frag(ndr_xa_t *mxa)
+{
+	ndr_common_header_t	*hdr = &mxa->recv_hdr.common_hdr;
+	ndr_stream_t		*nds = &mxa->recv_nds;
+	unsigned char		*data;
+	unsigned long		next_offset;
+	unsigned long		pay_size;
+	int			rc;
+
+	/* Make room for the frag header. */
+	next_offset = nds->pdu_scan_offset + NDR_RSP_HDR_SIZE;
+	if (!NDS_GROW_PDU(nds, next_offset, 0))
+		return (NDR_DRC_FAULT_OUT_OF_MEMORY);
+
+	/* Read the frag header. */
+	data = nds->pdu_base_addr + nds->pdu_scan_offset;
+	rc = NDR_PIPE_RECV(mxa->pipe, data, NDR_RSP_HDR_SIZE);
+	if (rc != 0)
+		return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT);
+
+	/*
+	 * Decode the frag header, get the length.
+	 * NB: It uses nds->pdu_scan_offset
+	 */
+	ndr_decode_frag_hdr(nds, hdr);
+	ndr_show_hdr(hdr);
+	if (hdr->frag_length < NDR_RSP_HDR_SIZE ||
+	    hdr->frag_length > mxa->pipe->np_max_xmit_frag)
+		return (NDR_DRC_FAULT_DECODE_FAILED);
+
+	if (nds->pdu_scan_offset == 0) {
+		/* First frag: header stays in the data. */
+		nds->pdu_scan_offset = next_offset;
+	} /* else overwrite with the payload */
+
+	/* Make room for the payload. */
+	pay_size = hdr->frag_length - NDR_RSP_HDR_SIZE;
+	next_offset = nds->pdu_scan_offset + pay_size;
+	if (!NDS_GROW_PDU(nds, next_offset, 0))
+		return (NDR_DRC_FAULT_OUT_OF_MEMORY);
+
+	/* Read the payload. */
+	data = nds->pdu_base_addr + nds->pdu_scan_offset;
+	rc = NDR_PIPE_RECV(mxa->pipe, data, pay_size);
+	if (rc != 0)
+		return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT);
+	nds->pdu_scan_offset = next_offset;
+
+	return (NDR_DRC_OK);
+}
+
+/*
+ * This is the entry point for all server-side RPC processing.
+ * It is assumed that the PDU has already been received.
+ */
+static int
+ndr_svc_process(ndr_xa_t *mxa)
+{
+	int			rc;
+
+	(void) ndr_reply_prepare_hdr(mxa);
+
+	switch (mxa->ptype) {
+	case NDR_PTYPE_BIND:
+		rc = ndr_svc_bind(mxa);
+		break;
+
+	case NDR_PTYPE_REQUEST:
+		rc = ndr_svc_request(mxa);
+		break;
+
+	case NDR_PTYPE_ALTER_CONTEXT:
+		rc = ndr_svc_alter_context(mxa);
+		break;
+
+	default:
+		rc = NDR_DRC_FAULT_RPCHDR_PTYPE_INVALID;
+		break;
+	}
+
+	if (NDR_DRC_IS_FAULT(rc))
+		ndr_reply_fault(mxa, rc);
+
+	return (rc);
+}
+
+/*
+ * Multiple p_cont_elem[]s, multiple transfer_syntaxes[] and multiple
+ * p_results[] not supported.
+ */
+static int
+ndr_svc_bind(ndr_xa_t *mxa)
+{
+	ndr_p_cont_list_t	*cont_list;
+	ndr_p_result_list_t	*result_list;
+	ndr_p_result_t		*result;
+	unsigned		p_cont_id;
+	ndr_binding_t		*mbind;
+	ndr_uuid_t		*as_uuid;
+	ndr_uuid_t		*ts_uuid;
+	int			as_vers;
+	int			ts_vers;
+	ndr_service_t		*msvc;
+	int			rc;
+	ndr_port_any_t		*sec_addr;
+
+	/* acquire targets */
+	cont_list = &mxa->recv_hdr.bind_hdr.p_context_elem;
+	result_list = &mxa->send_hdr.bind_ack_hdr.p_result_list;
+	result = &result_list->p_results[0];
+
+	/*
+	 * Set up temporary secondary address port.
+	 * We will correct this later (below).
+	 */
+	sec_addr = &mxa->send_hdr.bind_ack_hdr.sec_addr;
+	sec_addr->length = 13;
+	(void) strcpy((char *)sec_addr->port_spec, "\\PIPE\\ntsvcs");
+
+	result_list->n_results = 1;
+	result_list->reserved = 0;
+	result_list->reserved2 = 0;
+	result->result = NDR_PCDR_ACCEPTANCE;
+	result->reason = 0;
+	bzero(&result->transfer_syntax, sizeof (result->transfer_syntax));
+
+	/* sanity check */
+	if (cont_list->n_context_elem != 1 ||
+	    cont_list->p_cont_elem[0].n_transfer_syn != 1) {
+		ndo_trace("ndr_svc_bind: warning: multiple p_cont_elem");
+	}
+
+	p_cont_id = cont_list->p_cont_elem[0].p_cont_id;
+
+	if ((mbind = ndr_svc_find_binding(mxa, p_cont_id)) != NULL) {
+		/*
+		 * Duplicate presentation context id.
+		 */
+		ndo_trace("ndr_svc_bind: duplicate binding");
+		return (NDR_DRC_FAULT_BIND_PCONT_BUSY);
+	}
+
+	if ((mbind = ndr_svc_new_binding(mxa)) == NULL) {
+		/*
+		 * No free binding slot
+		 */
+		result->result = NDR_PCDR_PROVIDER_REJECTION;
+		result->reason = NDR_PPR_LOCAL_LIMIT_EXCEEDED;
+		ndo_trace("ndr_svc_bind: no resources");
+		return (NDR_DRC_OK);
+	}
+
+	as_uuid = &cont_list->p_cont_elem[0].abstract_syntax.if_uuid;
+	as_vers = cont_list->p_cont_elem[0].abstract_syntax.if_version;
+
+	ts_uuid = &cont_list->p_cont_elem[0].transfer_syntaxes[0].if_uuid;
+	ts_vers = cont_list->p_cont_elem[0].transfer_syntaxes[0].if_version;
+
+	msvc = ndr_svc_lookup_uuid(as_uuid, as_vers, ts_uuid, ts_vers);
+	if (msvc == NULL) {
+		result->result = NDR_PCDR_PROVIDER_REJECTION;
+		result->reason = NDR_PPR_ABSTRACT_SYNTAX_NOT_SUPPORTED;
+		return (NDR_DRC_OK);
+	}
+
+	/*
+	 * We can now use the correct secondary address port.
+	 */
+	sec_addr = &mxa->send_hdr.bind_ack_hdr.sec_addr;
+	sec_addr->length = strlen(msvc->sec_addr_port) + 1;
+	(void) strlcpy((char *)sec_addr->port_spec, msvc->sec_addr_port,
+	    NDR_PORT_ANY_MAX_PORT_SPEC);
+
+	mbind->p_cont_id = p_cont_id;
+	mbind->which_side = NDR_BIND_SIDE_SERVER;
+	/* mbind->context set by app */
+	mbind->service = msvc;
+	mbind->instance_specific = 0;
+
+	mxa->binding = mbind;
+
+	if (msvc->bind_req) {
+		/*
+		 * Call the service-specific bind() handler.  If
+		 * this fails, we shouild send a specific error
+		 * on the bind ack.
+		 */
+		rc = (msvc->bind_req)(mxa);
+		if (NDR_DRC_IS_FAULT(rc)) {
+			mbind->service = 0;	/* free binding slot */
+			mbind->which_side = 0;
+			mbind->p_cont_id = 0;
+			mbind->instance_specific = 0;
+			return (rc);
+		}
+	}
+
+	result->transfer_syntax =
+	    cont_list->p_cont_elem[0].transfer_syntaxes[0];
+
+	return (NDR_DRC_BINDING_MADE);
+}
+
+/*
+ * ndr_svc_alter_context
+ *
+ * The alter context request is used to request additional presentation
+ * context for another interface and/or version.  It is very similar to
+ * a bind request.
+ */
+static int
+ndr_svc_alter_context(ndr_xa_t *mxa)
+{
+	ndr_p_result_list_t *result_list;
+	ndr_p_result_t *result;
+	ndr_p_cont_list_t *cont_list;
+	ndr_binding_t *mbind;
+	ndr_service_t *msvc;
+	unsigned p_cont_id;
+	ndr_uuid_t *as_uuid;
+	ndr_uuid_t *ts_uuid;
+	int as_vers;
+	int ts_vers;
+	ndr_port_any_t *sec_addr;
+
+	result_list = &mxa->send_hdr.alter_context_rsp_hdr.p_result_list;
+	result_list->n_results = 1;
+	result_list->reserved = 0;
+	result_list->reserved2 = 0;
+
+	result = &result_list->p_results[0];
+	result->result = NDR_PCDR_ACCEPTANCE;
+	result->reason = 0;
+	bzero(&result->transfer_syntax, sizeof (result->transfer_syntax));
+
+	cont_list = &mxa->recv_hdr.alter_context_hdr.p_context_elem;
+	p_cont_id = cont_list->p_cont_elem[0].p_cont_id;
+
+	if (ndr_svc_find_binding(mxa, p_cont_id) != NULL)
+		return (NDR_DRC_FAULT_BIND_PCONT_BUSY);
+
+	if ((mbind = ndr_svc_new_binding(mxa)) == NULL) {
+		result->result = NDR_PCDR_PROVIDER_REJECTION;
+		result->reason = NDR_PPR_LOCAL_LIMIT_EXCEEDED;
+		return (NDR_DRC_OK);
+	}
+
+	as_uuid = &cont_list->p_cont_elem[0].abstract_syntax.if_uuid;
+	as_vers = cont_list->p_cont_elem[0].abstract_syntax.if_version;
+
+	ts_uuid = &cont_list->p_cont_elem[0].transfer_syntaxes[0].if_uuid;
+	ts_vers = cont_list->p_cont_elem[0].transfer_syntaxes[0].if_version;
+
+	msvc = ndr_svc_lookup_uuid(as_uuid, as_vers, ts_uuid, ts_vers);
+	if (msvc == NULL) {
+		result->result = NDR_PCDR_PROVIDER_REJECTION;
+		result->reason = NDR_PPR_ABSTRACT_SYNTAX_NOT_SUPPORTED;
+		return (NDR_DRC_OK);
+	}
+
+	mbind->p_cont_id = p_cont_id;
+	mbind->which_side = NDR_BIND_SIDE_SERVER;
+	/* mbind->context set by app */
+	mbind->service = msvc;
+	mbind->instance_specific = 0;
+	mxa->binding = mbind;
+
+	sec_addr = &mxa->send_hdr.alter_context_rsp_hdr.sec_addr;
+	sec_addr->length = 0;
+	bzero(sec_addr->port_spec, NDR_PORT_ANY_MAX_PORT_SPEC);
+
+	result->transfer_syntax =
+	    cont_list->p_cont_elem[0].transfer_syntaxes[0];
+
+	return (NDR_DRC_BINDING_MADE);
+}
+
+static int
+ndr_svc_request(ndr_xa_t *mxa)
+{
+	ndr_binding_t	*mbind;
+	ndr_service_t	*msvc;
+	unsigned	p_cont_id;
+	int		rc;
+
+	mxa->opnum = mxa->recv_hdr.request_hdr.opnum;
+	p_cont_id = mxa->recv_hdr.request_hdr.p_cont_id;
+
+	if ((mbind = ndr_svc_find_binding(mxa, p_cont_id)) == NULL)
+		return (NDR_DRC_FAULT_REQUEST_PCONT_INVALID);
+
+	mxa->binding = mbind;
+	msvc = mbind->service;
+
+	/*
+	 * Make room for the response hdr.
+	 */
+	mxa->send_nds.pdu_scan_offset = NDR_RSP_HDR_SIZE;
+
+	if (msvc->call_stub)
+		rc = (*msvc->call_stub)(mxa);
+	else
+		rc = ndr_generic_call_stub(mxa);
+
+	if (NDR_DRC_IS_FAULT(rc)) {
+		ndo_printf(0, 0, "%s[0x%02x]: 0x%04x",
+		    msvc->name, mxa->opnum, rc);
+	}
+
+	return (rc);
+}
+
+/*
+ * The transaction and the two nds streams use the same heap, which
+ * should already exist at this point.  The heap will also be available
+ * to the stub.
+ */
+int
+ndr_generic_call_stub(ndr_xa_t *mxa)
+{
+	ndr_binding_t 		*mbind = mxa->binding;
+	ndr_service_t		*msvc = mbind->service;
+	ndr_typeinfo_t		*intf_ti = msvc->interface_ti;
+	ndr_stub_table_t	*ste;
+	int			opnum = mxa->opnum;
+	unsigned		p_len = intf_ti->c_size_fixed_part;
+	char 			*param;
+	int			rc;
+
+	if (mxa->heap == NULL) {
+		ndo_printf(0, 0, "%s[0x%02x]: no heap", msvc->name, opnum);
+		return (NDR_DRC_FAULT_OUT_OF_MEMORY);
+	}
+
+	if ((ste = ndr_svc_find_stub(msvc, opnum)) == NULL) {
+		ndo_printf(0, 0, "%s[0x%02x]: invalid opnum",
+		    msvc->name, opnum);
+		return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID);
+	}
+
+	if ((param = ndr_heap_malloc(mxa->heap, p_len)) == NULL)
+		return (NDR_DRC_FAULT_OUT_OF_MEMORY);
+
+	bzero(param, p_len);
+
+	rc = ndr_decode_call(mxa, param);
+	if (!NDR_DRC_IS_OK(rc))
+		return (rc);
+
+	rc = (*ste->func)(param, mxa);
+	if (rc == NDR_DRC_OK)
+		rc = ndr_encode_return(mxa, param);
+
+	return (rc);
+}
+
+/*
+ * We can perform some initial setup of the response header here.
+ * We also need to cache some of the information from the bind
+ * negotiation for use during subsequent RPC calls.
+ */
+static void
+ndr_reply_prepare_hdr(ndr_xa_t *mxa)
+{
+	ndr_common_header_t *rhdr = &mxa->recv_hdr.common_hdr;
+	ndr_common_header_t *hdr = &mxa->send_hdr.common_hdr;
+
+	hdr->rpc_vers = 5;
+	hdr->rpc_vers_minor = 0;
+	hdr->pfc_flags = NDR_PFC_FIRST_FRAG + NDR_PFC_LAST_FRAG;
+	hdr->packed_drep = rhdr->packed_drep;
+	hdr->frag_length = 0;
+	hdr->auth_length = 0;
+	hdr->call_id = rhdr->call_id;
+#ifdef _BIG_ENDIAN
+	hdr->packed_drep.intg_char_rep = NDR_REPLAB_CHAR_ASCII
+	    | NDR_REPLAB_INTG_BIG_ENDIAN;
+#else
+	hdr->packed_drep.intg_char_rep = NDR_REPLAB_CHAR_ASCII
+	    | NDR_REPLAB_INTG_LITTLE_ENDIAN;
+#endif
+
+	switch (mxa->ptype) {
+	case NDR_PTYPE_BIND:
+		/*
+		 * Compute the maximum fragment sizes for xmit/recv
+		 * and store in the pipe endpoint.  Note "xmit" is
+		 * client-to-server; "recv" is server-to-client.
+		 */
+		if (mxa->pipe->np_max_xmit_frag >
+		    mxa->recv_hdr.bind_hdr.max_xmit_frag)
+			mxa->pipe->np_max_xmit_frag =
+			    mxa->recv_hdr.bind_hdr.max_xmit_frag;
+		if (mxa->pipe->np_max_recv_frag >
+		    mxa->recv_hdr.bind_hdr.max_recv_frag)
+			mxa->pipe->np_max_recv_frag =
+			    mxa->recv_hdr.bind_hdr.max_recv_frag;
+
+		hdr->ptype = NDR_PTYPE_BIND_ACK;
+		mxa->send_hdr.bind_ack_hdr.max_xmit_frag =
+		    mxa->pipe->np_max_xmit_frag;
+		mxa->send_hdr.bind_ack_hdr.max_recv_frag =
+		    mxa->pipe->np_max_recv_frag;
+
+		/*
+		 * We're supposed to assign a unique "assoc group"
+		 * (identifies this connection for the client).
+		 * Using the pipe address is adequate.
+		 */
+		mxa->send_hdr.bind_ack_hdr.assoc_group_id =
+		    mxa->recv_hdr.bind_hdr.assoc_group_id;
+		if (mxa->send_hdr.bind_ack_hdr.assoc_group_id == 0)
+			mxa->send_hdr.bind_ack_hdr.assoc_group_id =
+			    (DWORD)(uintptr_t)mxa->pipe;
+
+		break;
+
+	case NDR_PTYPE_REQUEST:
+		hdr->ptype = NDR_PTYPE_RESPONSE;
+		/* mxa->send_hdr.response_hdr.alloc_hint */
+		mxa->send_hdr.response_hdr.p_cont_id =
+		    mxa->recv_hdr.request_hdr.p_cont_id;
+		mxa->send_hdr.response_hdr.cancel_count = 0;
+		mxa->send_hdr.response_hdr.reserved = 0;
+		break;
+
+	case NDR_PTYPE_ALTER_CONTEXT:
+		hdr->ptype = NDR_PTYPE_ALTER_CONTEXT_RESP;
+		/*
+		 * The max_xmit_frag, max_recv_frag and assoc_group_id are
+		 * ignored by the client but it's useful to fill them in.
+		 */
+		mxa->send_hdr.alter_context_rsp_hdr.max_xmit_frag =
+		    mxa->recv_hdr.alter_context_hdr.max_xmit_frag;
+		mxa->send_hdr.alter_context_rsp_hdr.max_recv_frag =
+		    mxa->recv_hdr.alter_context_hdr.max_recv_frag;
+		mxa->send_hdr.alter_context_rsp_hdr.assoc_group_id =
+		    mxa->recv_hdr.alter_context_hdr.assoc_group_id;
+		break;
+
+	default:
+		hdr->ptype = 0xFF;
+	}
+}
+
+/*
+ * Signal an RPC fault. The stream is reset and we overwrite whatever
+ * was in the response header with the fault information.
+ */
+static void
+ndr_reply_fault(ndr_xa_t *mxa, unsigned long drc)
+{
+	ndr_common_header_t *rhdr = &mxa->recv_hdr.common_hdr;
+	ndr_common_header_t *hdr = &mxa->send_hdr.common_hdr;
+	ndr_stream_t *nds = &mxa->send_nds;
+	unsigned long fault_status;
+
+	NDS_RESET(nds);
+
+	hdr->rpc_vers = 5;
+	hdr->rpc_vers_minor = 0;
+	hdr->pfc_flags = NDR_PFC_FIRST_FRAG + NDR_PFC_LAST_FRAG;
+	hdr->packed_drep = rhdr->packed_drep;
+	hdr->frag_length = sizeof (mxa->send_hdr.fault_hdr);
+	hdr->auth_length = 0;
+	hdr->call_id = rhdr->call_id;
+#ifdef _BIG_ENDIAN
+	hdr->packed_drep.intg_char_rep = NDR_REPLAB_CHAR_ASCII
+	    | NDR_REPLAB_INTG_BIG_ENDIAN;
+#else
+	hdr->packed_drep.intg_char_rep = NDR_REPLAB_CHAR_ASCII
+	    | NDR_REPLAB_INTG_LITTLE_ENDIAN;
+#endif
+
+	switch (drc & NDR_DRC_MASK_SPECIFIER) {
+	case NDR_DRC_FAULT_OUT_OF_MEMORY:
+	case NDR_DRC_FAULT_ENCODE_TOO_BIG:
+		fault_status = NDR_FAULT_NCA_OUT_ARGS_TOO_BIG;
+		break;
+
+	case NDR_DRC_FAULT_REQUEST_PCONT_INVALID:
+		fault_status = NDR_FAULT_NCA_INVALID_PRES_CONTEXT_ID;
+		break;
+
+	case NDR_DRC_FAULT_REQUEST_OPNUM_INVALID:
+		fault_status = NDR_FAULT_NCA_OP_RNG_ERROR;
+		break;
+
+	case NDR_DRC_FAULT_DECODE_FAILED:
+	case NDR_DRC_FAULT_ENCODE_FAILED:
+		fault_status = NDR_FAULT_NCA_PROTO_ERROR;
+		break;
+
+	default:
+		fault_status = NDR_FAULT_NCA_UNSPEC_REJECT;
+		break;
+	}
+
+	mxa->send_hdr.fault_hdr.common_hdr.ptype = NDR_PTYPE_FAULT;
+	mxa->send_hdr.fault_hdr.status = fault_status;
+	mxa->send_hdr.response_hdr.alloc_hint = hdr->frag_length;
+}
+
+/*
+ * Note that the frag_length for bind ack and alter context is
+ * non-standard.
+ */
+static int
+ndr_send_reply(ndr_xa_t *mxa)
+{
+	ndr_common_header_t *hdr = &mxa->send_hdr.common_hdr;
+	ndr_stream_t *nds = &mxa->send_nds;
+	uint8_t *pdu_buf;
+	unsigned long pdu_size;
+	unsigned long frag_size;
+	unsigned long pdu_data_size;
+	unsigned long frag_data_size;
+
+	frag_size = mxa->pipe->np_max_recv_frag;
+	pdu_size = nds->pdu_size;
+	pdu_buf = nds->pdu_base_addr;
+
+	if (pdu_size <= frag_size) {
+		/*
+		 * Single fragment response. The PDU size may be zero
+		 * here (i.e. bind or fault response). So don't make
+		 * any assumptions about it until after the header is
+		 * encoded.
+		 */
+		switch (hdr->ptype) {
+		case NDR_PTYPE_BIND_ACK:
+			hdr->frag_length = ndr_bind_ack_hdr_size(mxa);
+			break;
+
+		case NDR_PTYPE_FAULT:
+			/* already setup */
+			break;
+
+		case NDR_PTYPE_RESPONSE:
+			hdr->frag_length = pdu_size;
+			mxa->send_hdr.response_hdr.alloc_hint =
+			    hdr->frag_length;
+			break;
+
+		case NDR_PTYPE_ALTER_CONTEXT_RESP:
+			hdr->frag_length = ndr_alter_context_rsp_hdr_size();
+			break;
+
+		default:
+			hdr->frag_length = pdu_size;
+			break;
+		}
+
+		nds->pdu_scan_offset = 0;
+		(void) ndr_encode_pdu_hdr(mxa);
+		pdu_size = nds->pdu_size;
+		(void) NDR_PIPE_SEND(mxa->pipe, pdu_buf, pdu_size);
+		return (0);
+	}
+
+	/*
+	 * Multiple fragment response.
+	 *
+	 * We need to update the RPC header for every fragment.
+	 *
+	 * pdu_data_size:	total data remaining to be handled
+	 * frag_size:		total fragment size including header
+	 * frag_data_size:	data in fragment
+	 *			(i.e. frag_size - NDR_RSP_HDR_SIZE)
+	 */
+	pdu_data_size = pdu_size - NDR_RSP_HDR_SIZE;
+	frag_data_size = frag_size - NDR_RSP_HDR_SIZE;
+
+	/*
+	 * Send the first frag.
+	 */
+	hdr->pfc_flags = NDR_PFC_FIRST_FRAG;
+	hdr->frag_length = frag_size;
+	mxa->send_hdr.response_hdr.alloc_hint = pdu_data_size;
+	nds->pdu_scan_offset = 0;
+	(void) ndr_encode_pdu_hdr(mxa);
+	(void) NDR_PIPE_SEND(mxa->pipe, pdu_buf, frag_size);
+	pdu_data_size -= frag_data_size;
+	pdu_buf += frag_data_size;
+
+	/*
+	 * Send "middle" (full-sized) fragments...
+	 */
+	hdr->pfc_flags = 0;
+	while (pdu_data_size > frag_data_size) {
+
+		hdr->frag_length = frag_size;
+		mxa->send_hdr.response_hdr.alloc_hint = pdu_data_size;
+		nds->pdu_scan_offset = 0;
+		(void) ndr_encode_pdu_hdr(mxa);
+		bcopy(nds->pdu_base_addr, pdu_buf, NDR_RSP_HDR_SIZE);
+		(void) NDR_PIPE_SEND(mxa->pipe, pdu_buf, frag_size);
+		pdu_data_size -= frag_data_size;
+		pdu_buf += frag_data_size;
+	}
+
+	/*
+	 * Last frag (pdu_data_size <= frag_data_size)
+	 */
+	hdr->pfc_flags = NDR_PFC_LAST_FRAG;
+	frag_size = pdu_data_size + NDR_RSP_HDR_SIZE;
+	hdr->frag_length = frag_size;
+	mxa->send_hdr.response_hdr.alloc_hint = pdu_data_size;
+	nds->pdu_scan_offset = 0;
+	(void) ndr_encode_pdu_hdr(mxa);
+	bcopy(nds->pdu_base_addr, pdu_buf, NDR_RSP_HDR_SIZE);
+	(void) NDR_PIPE_SEND(mxa->pipe, pdu_buf, frag_size);
+
+	return (0);
+}
--- old/usr/src/lib/smbsrv/libmlrpc/common/ndr_svc.c	Sun Mar 18 01:13:17 2018
+++ /dev/null	Sun Mar 18 01:13:16 2018
@@ -1,476 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
- */
-
-#include <uuid/uuid.h>
-#include <ctype.h>
-#include <synch.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <strings.h>
-#include <assert.h>
-
-#include <smbsrv/libsmb.h>
-#include <smbsrv/libmlrpc.h>
-
-
-/*
- * Global list of allocated handles.  Handles are used in various
- * server-side RPC functions: typically, issued when a service is
- * opened and obsoleted when it is closed.  Clients should treat
- * handles as opaque data.
- */
-static ndr_handle_t *ndr_handle_list;
-static mutex_t ndr_handle_lock;
-
-/*
- * Table of registered services.
- */
-#define	NDR_MAX_SERVICES	32
-static ndr_service_t *ndr_services[NDR_MAX_SERVICES];
-
-/*
- * Register a service.
- *
- * Returns:
- *	0	Success
- *	-1	Duplicate service
- *	-2	Duplicate name
- *	-3	Table overflow
- */
-int
-ndr_svc_register(ndr_service_t *svc)
-{
-	ndr_service_t 	*p;
-	int		free_slot = -1;
-	int		i;
-
-	for (i = 0; i < NDR_MAX_SERVICES; i++) {
-		if ((p = ndr_services[i]) == NULL) {
-			if (free_slot < 0)
-				free_slot = i;
-			continue;
-		}
-
-		if (p == svc)
-			return (-1);
-
-		if (strcasecmp(p->name, svc->name) == 0)
-			return (-2);
-	}
-
-	if (free_slot < 0)
-		return (-3);
-
-	ndr_services[free_slot] = svc;
-	return (0);
-}
-
-void
-ndr_svc_unregister(ndr_service_t *svc)
-{
-	int i;
-
-	for (i = 0; i < NDR_MAX_SERVICES; i++) {
-		if (ndr_services[i] == svc)
-			ndr_services[i] = NULL;
-	}
-}
-
-ndr_stub_table_t *
-ndr_svc_find_stub(ndr_service_t *svc, int opnum)
-{
-	ndr_stub_table_t *ste;
-
-	for (ste = svc->stub_table; ste->func; ste++) {
-		if (ste->opnum == opnum)
-			return (ste);
-	}
-
-	return (NULL);
-}
-
-ndr_service_t *
-ndr_svc_lookup_name(const char *name)
-{
-	ndr_service_t 	*svc;
-	int			i;
-
-	for (i = 0; i < NDR_MAX_SERVICES; i++) {
-		if ((svc = ndr_services[i]) == NULL)
-			continue;
-
-		if (strcasecmp(name, svc->name) != 0)
-			continue;
-
-		ndo_printf(0, 0, "%s %s", svc->name, svc->desc);
-		return (svc);
-	}
-
-	return (NULL);
-}
-
-ndr_service_t *
-ndr_svc_lookup_uuid(ndr_uuid_t *as_uuid, int as_vers,
-    ndr_uuid_t *ts_uuid, int ts_vers)
-{
-	ndr_service_t *svc;
-	char abstract_syntax[UUID_PRINTABLE_STRING_LENGTH];
-	char transfer_syntax[UUID_PRINTABLE_STRING_LENGTH];
-	int i;
-
-	if (as_uuid)
-		ndr_uuid_unparse(as_uuid, abstract_syntax);
-
-	if (ts_uuid)
-		ndr_uuid_unparse(ts_uuid, transfer_syntax);
-
-	for (i = 0; i < NDR_MAX_SERVICES; i++) {
-		if ((svc = ndr_services[i]) == NULL)
-			continue;
-
-		if (as_uuid) {
-			if (svc->abstract_syntax_uuid == 0)
-				continue;
-
-			if (svc->abstract_syntax_version != as_vers)
-				continue;
-
-			if (strcasecmp(abstract_syntax,
-			    svc->abstract_syntax_uuid))
-				continue;
-		}
-
-		if (ts_uuid) {
-			if (svc->transfer_syntax_uuid == 0)
-				continue;
-
-			if (svc->transfer_syntax_version != ts_vers)
-				continue;
-
-			if (strcasecmp(transfer_syntax,
-			    svc->transfer_syntax_uuid))
-				continue;
-		}
-
-		ndo_printf(0, 0, "%s %s", svc->name, svc->desc);
-		return (svc);
-	}
-
-	ndo_printf(0, 0, "ndr_svc_lookup_uuid: unknown service");
-	ndo_printf(0, 0, "abstract=%s v%d, transfer=%s v%d",
-	    abstract_syntax, as_vers, transfer_syntax, ts_vers);
-	return (NULL);
-}
-
-/*
- * Allocate a handle for use with the server-side RPC functions.
- *
- * An arbitrary caller context can be associated with the handle
- * via data; it will not be dereferenced by the handle API.
- */
-ndr_hdid_t *
-ndr_hdalloc(const ndr_xa_t *xa, const void *data)
-{
-	static ndr_hdid_t id;
-	ndr_handle_t *hd;
-	uuid_t uu;
-
-	if ((hd = malloc(sizeof (ndr_handle_t))) == NULL)
-		return (NULL);
-
-	if (id.data2 == 0) {
-		uuid_generate_random(uu);
-		bcopy(uu, &id.data2, sizeof (uuid_t));
-		id.data1 = 0;
-		id.data2 = 0;
-	}
-
-	++id.data2;
-
-	bcopy(&id, &hd->nh_id, sizeof (ndr_hdid_t));
-	hd->nh_pipe = xa->pipe;
-	hd->nh_svc = xa->binding->service;
-	hd->nh_data = (void *)data;
-	hd->nh_data_free = NULL;
-
-	(void) mutex_lock(&ndr_handle_lock);
-	hd->nh_next = ndr_handle_list;
-	ndr_handle_list = hd;
-	(void) mutex_unlock(&ndr_handle_lock);
-
-	return (&hd->nh_id);
-}
-
-/*
- * Remove a handle from the global list and free it.
- */
-void
-ndr_hdfree(const ndr_xa_t *xa, const ndr_hdid_t *id)
-{
-	ndr_service_t *svc = xa->binding->service;
-	ndr_handle_t *hd;
-	ndr_handle_t **pphd;
-
-	assert(id);
-
-	(void) mutex_lock(&ndr_handle_lock);
-	pphd = &ndr_handle_list;
-
-	while (*pphd) {
-		hd = *pphd;
-
-		if (bcmp(&hd->nh_id, id, sizeof (ndr_hdid_t)) == 0) {
-			if (hd->nh_svc == svc) {
-				*pphd = hd->nh_next;
-				free(hd);
-			}
-			break;
-		}
-
-		pphd = &(*pphd)->nh_next;
-	}
-
-	(void) mutex_unlock(&ndr_handle_lock);
-}
-
-/*
- * Lookup a handle by id.  If the handle is in the list and it matches
- * the specified service, a pointer to it is returned.  Otherwise a null
- * pointer is returned.
- */
-ndr_handle_t *
-ndr_hdlookup(const ndr_xa_t *xa, const ndr_hdid_t *id)
-{
-	ndr_service_t *svc = xa->binding->service;
-	ndr_handle_t *hd;
-
-	assert(id);
-	(void) mutex_lock(&ndr_handle_lock);
-	hd = ndr_handle_list;
-
-	while (hd) {
-		if (bcmp(&hd->nh_id, id, sizeof (ndr_hdid_t)) == 0) {
-			if (hd->nh_svc != svc)
-				break;
-			(void) mutex_unlock(&ndr_handle_lock);
-			return (hd);
-		}
-
-		hd = hd->nh_next;
-	}
-
-	(void) mutex_unlock(&ndr_handle_lock);
-	return (NULL);
-}
-
-/*
- * Called when a pipe is closed to release any associated handles.
- */
-void
-ndr_hdclose(ndr_pipe_t *pipe)
-{
-	ndr_handle_t *hd;
-	ndr_handle_t **pphd;
-
-	(void) mutex_lock(&ndr_handle_lock);
-	pphd = &ndr_handle_list;
-
-	while (*pphd) {
-		hd = *pphd;
-
-		if (hd->nh_pipe == pipe) {
-			*pphd = hd->nh_next;
-
-			if (hd->nh_data_free)
-				(*hd->nh_data_free)(hd->nh_data);
-
-			free(hd);
-			continue;
-		}
-
-		pphd = &(*pphd)->nh_next;
-	}
-
-	(void) mutex_unlock(&ndr_handle_lock);
-}
-
-/*
- * Convert a UUID to a string.
- */
-void
-ndr_uuid_unparse(ndr_uuid_t *uuid, char *out)
-{
-	(void) sprintf(out, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-	    uuid->data1, uuid->data2, uuid->data3,
-	    uuid->data4[0], uuid->data4[1],
-	    uuid->data4[2], uuid->data4[3],
-	    uuid->data4[4], uuid->data4[5],
-	    uuid->data4[6], uuid->data4[7]);
-}
-
-/*
- * Convert a string to a UUID.
- */
-int
-ndr_uuid_parse(char *in, ndr_uuid_t *uuid)
-{
-	char 		*p = in;
-	char 		*q;
-	char		buf[4];
-	int		i;
-
-	if (strlen(in) != UUID_PRINTABLE_STRING_LENGTH - 1)
-		return (-1);
-
-	uuid->data1 = strtoul(p, &p, 16);
-	if (*p != '-')
-		return (-1);
-	p++;
-
-	uuid->data2 = strtol(p, &p, 16);
-	if (*p != '-')
-		return (-1);
-	p++;
-
-	uuid->data3 = strtol(p, &p, 16);
-	if (*p != '-')
-		return (-1);
-	p++;
-
-	for (i = 0; i < 8; i++) {
-		if (*p ==  '-')
-			p++;
-
-		if (p[0] == 0 || p[1] == 0)
-			return (-1);
-
-		buf[0] = *p++;
-		buf[1] = *p++;
-		buf[2] = 0;
-		uuid->data4[i] = strtol(buf, &q, 16);
-		if (*q != 0)
-			return (-1);
-	}
-
-	if (*p != 0)
-		return (-1);
-
-	return (0);
-}
-
-void
-ndr_svc_binding_pool_init(ndr_binding_t **headpp, ndr_binding_t pool[],
-    int n_pool)
-{
-	ndr_binding_t	*head = NULL;
-	int		ix;
-
-	for (ix = n_pool - 1; ix >= 0; ix--) {
-		pool[ix].next = head;
-		pool[ix].service = NULL;
-		pool[ix].p_cont_id = 0xffff;
-		pool[ix].instance_specific = 0;
-		head = &pool[ix];
-	}
-
-	*headpp = head;
-}
-
-ndr_binding_t *
-ndr_svc_find_binding(ndr_xa_t *mxa, ndr_p_context_id_t p_cont_id)
-{
-	ndr_binding_t *mbind;
-
-	for (mbind = mxa->binding_list; mbind; mbind = mbind->next) {
-		if (mbind->service != NULL &&
-		    mbind->which_side == NDR_BIND_SIDE_SERVER &&
-		    mbind->p_cont_id == p_cont_id)
-			break;
-	}
-
-	return (mbind);
-}
-
-ndr_binding_t *
-ndr_svc_new_binding(ndr_xa_t *mxa)
-{
-	ndr_binding_t *mbind;
-
-	for (mbind = mxa->binding_list; mbind; mbind = mbind->next) {
-		if (mbind->service == NULL)
-			break;
-	}
-
-	return (mbind);
-}
-
-/*
- * Move bytes between a buffer and a uio structure.
- * The transfer direction is controlled by rw:
- *	UIO_READ:  transfer from buf to uio
- *	UIO_WRITE: transfer from uio to buf
- *
- * Returns the number of bytes moved.
- */
-ssize_t
-ndr_uiomove(caddr_t buf, size_t buflen, enum uio_rw rw, struct uio *uio)
-{
-	struct iovec *iov;
-	int reading = (rw == UIO_READ);
-	size_t nbytes;
-	size_t nxfer = 0;
-
-	assert(rw == UIO_READ || rw == UIO_WRITE);
-
-	while (buflen && uio->uio_resid && uio->uio_iovcnt) {
-		iov = uio->uio_iov;
-		if ((nbytes = iov->iov_len) == 0) {
-			uio->uio_iov++;
-			uio->uio_iovcnt--;
-			continue;
-		}
-
-		if (nbytes > buflen)
-			nbytes = buflen;
-
-		if (reading)
-			bcopy(buf, iov->iov_base, nbytes);
-		else
-			bcopy(iov->iov_base, buf, nbytes);
-
-		iov->iov_base += nbytes;
-		iov->iov_len -= nbytes;
-		uio->uio_resid -= nbytes;
-		uio->uio_offset += nbytes;
-		buf += nbytes;
-		buflen -= nbytes;
-		nxfer += nbytes;
-	}
-
-	return (nxfer);
-}
--- /dev/null	Sun Mar 18 01:13:16 2018
+++ new/usr/src/lib/libmlrpc/common/ndr_svc.c	Sun Mar 18 01:13:17 2018
@@ -0,0 +1,475 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+#include <uuid/uuid.h>
+#include <ctype.h>
+#include <synch.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <strings.h>
+#include <assert.h>
+
+#include <libmlrpc.h>
+
+
+/*
+ * Global list of allocated handles.  Handles are used in various
+ * server-side RPC functions: typically, issued when a service is
+ * opened and obsoleted when it is closed.  Clients should treat
+ * handles as opaque data.
+ */
+static ndr_handle_t *ndr_handle_list;
+static mutex_t ndr_handle_lock;
+
+/*
+ * Table of registered services.
+ */
+#define	NDR_MAX_SERVICES	32
+static ndr_service_t *ndr_services[NDR_MAX_SERVICES];
+
+/*
+ * Register a service.
+ *
+ * Returns:
+ *	0	Success
+ *	-1	Duplicate service
+ *	-2	Duplicate name
+ *	-3	Table overflow
+ */
+int
+ndr_svc_register(ndr_service_t *svc)
+{
+	ndr_service_t 	*p;
+	int		free_slot = -1;
+	int		i;
+
+	for (i = 0; i < NDR_MAX_SERVICES; i++) {
+		if ((p = ndr_services[i]) == NULL) {
+			if (free_slot < 0)
+				free_slot = i;
+			continue;
+		}
+
+		if (p == svc)
+			return (-1);
+
+		if (strcasecmp(p->name, svc->name) == 0)
+			return (-2);
+	}
+
+	if (free_slot < 0)
+		return (-3);
+
+	ndr_services[free_slot] = svc;
+	return (0);
+}
+
+void
+ndr_svc_unregister(ndr_service_t *svc)
+{
+	int i;
+
+	for (i = 0; i < NDR_MAX_SERVICES; i++) {
+		if (ndr_services[i] == svc)
+			ndr_services[i] = NULL;
+	}
+}
+
+ndr_stub_table_t *
+ndr_svc_find_stub(ndr_service_t *svc, int opnum)
+{
+	ndr_stub_table_t *ste;
+
+	for (ste = svc->stub_table; ste->func; ste++) {
+		if (ste->opnum == opnum)
+			return (ste);
+	}
+
+	return (NULL);
+}
+
+ndr_service_t *
+ndr_svc_lookup_name(const char *name)
+{
+	ndr_service_t 	*svc;
+	int			i;
+
+	for (i = 0; i < NDR_MAX_SERVICES; i++) {
+		if ((svc = ndr_services[i]) == NULL)
+			continue;
+
+		if (strcasecmp(name, svc->name) != 0)
+			continue;
+
+		ndo_printf(0, 0, "%s %s", svc->name, svc->desc);
+		return (svc);
+	}
+
+	return (NULL);
+}
+
+ndr_service_t *
+ndr_svc_lookup_uuid(ndr_uuid_t *as_uuid, int as_vers,
+    ndr_uuid_t *ts_uuid, int ts_vers)
+{
+	ndr_service_t *svc;
+	char abstract_syntax[UUID_PRINTABLE_STRING_LENGTH];
+	char transfer_syntax[UUID_PRINTABLE_STRING_LENGTH];
+	int i;
+
+	if (as_uuid)
+		ndr_uuid_unparse(as_uuid, abstract_syntax);
+
+	if (ts_uuid)
+		ndr_uuid_unparse(ts_uuid, transfer_syntax);
+
+	for (i = 0; i < NDR_MAX_SERVICES; i++) {
+		if ((svc = ndr_services[i]) == NULL)
+			continue;
+
+		if (as_uuid) {
+			if (svc->abstract_syntax_uuid == 0)
+				continue;
+
+			if (svc->abstract_syntax_version != as_vers)
+				continue;
+
+			if (strcasecmp(abstract_syntax,
+			    svc->abstract_syntax_uuid))
+				continue;
+		}
+
+		if (ts_uuid) {
+			if (svc->transfer_syntax_uuid == 0)
+				continue;
+
+			if (svc->transfer_syntax_version != ts_vers)
+				continue;
+
+			if (strcasecmp(transfer_syntax,
+			    svc->transfer_syntax_uuid))
+				continue;
+		}
+
+		ndo_printf(0, 0, "%s %s", svc->name, svc->desc);
+		return (svc);
+	}
+
+	ndo_printf(0, 0, "ndr_svc_lookup_uuid: unknown service");
+	ndo_printf(0, 0, "abstract=%s v%d, transfer=%s v%d",
+	    abstract_syntax, as_vers, transfer_syntax, ts_vers);
+	return (NULL);
+}
+
+/*
+ * Allocate a handle for use with the server-side RPC functions.
+ *
+ * An arbitrary caller context can be associated with the handle
+ * via data; it will not be dereferenced by the handle API.
+ */
+ndr_hdid_t *
+ndr_hdalloc(const ndr_xa_t *xa, const void *data)
+{
+	static ndr_hdid_t id;
+	ndr_handle_t *hd;
+	uuid_t uu;
+
+	if ((hd = malloc(sizeof (ndr_handle_t))) == NULL)
+		return (NULL);
+
+	if (id.data2 == 0) {
+		uuid_generate_random(uu);
+		bcopy(uu, &id.data2, sizeof (uuid_t));
+		id.data1 = 0;
+		id.data2 = 0;
+	}
+
+	++id.data2;
+
+	bcopy(&id, &hd->nh_id, sizeof (ndr_hdid_t));
+	hd->nh_pipe = xa->pipe;
+	hd->nh_svc = xa->binding->service;
+	hd->nh_data = (void *)data;
+	hd->nh_data_free = NULL;
+
+	(void) mutex_lock(&ndr_handle_lock);
+	hd->nh_next = ndr_handle_list;
+	ndr_handle_list = hd;
+	(void) mutex_unlock(&ndr_handle_lock);
+
+	return (&hd->nh_id);
+}
+
+/*
+ * Remove a handle from the global list and free it.
+ */
+void
+ndr_hdfree(const ndr_xa_t *xa, const ndr_hdid_t *id)
+{
+	ndr_service_t *svc = xa->binding->service;
+	ndr_handle_t *hd;
+	ndr_handle_t **pphd;
+
+	assert(id);
+
+	(void) mutex_lock(&ndr_handle_lock);
+	pphd = &ndr_handle_list;
+
+	while (*pphd) {
+		hd = *pphd;
+
+		if (bcmp(&hd->nh_id, id, sizeof (ndr_hdid_t)) == 0) {
+			if (hd->nh_svc == svc) {
+				*pphd = hd->nh_next;
+				free(hd);
+			}
+			break;
+		}
+
+		pphd = &(*pphd)->nh_next;
+	}
+
+	(void) mutex_unlock(&ndr_handle_lock);
+}
+
+/*
+ * Lookup a handle by id.  If the handle is in the list and it matches
+ * the specified service, a pointer to it is returned.  Otherwise a null
+ * pointer is returned.
+ */
+ndr_handle_t *
+ndr_hdlookup(const ndr_xa_t *xa, const ndr_hdid_t *id)
+{
+	ndr_service_t *svc = xa->binding->service;
+	ndr_handle_t *hd;
+
+	assert(id);
+	(void) mutex_lock(&ndr_handle_lock);
+	hd = ndr_handle_list;
+
+	while (hd) {
+		if (bcmp(&hd->nh_id, id, sizeof (ndr_hdid_t)) == 0) {
+			if (hd->nh_svc != svc)
+				break;
+			(void) mutex_unlock(&ndr_handle_lock);
+			return (hd);
+		}
+
+		hd = hd->nh_next;
+	}
+
+	(void) mutex_unlock(&ndr_handle_lock);
+	return (NULL);
+}
+
+/*
+ * Called when a pipe is closed to release any associated handles.
+ */
+void
+ndr_hdclose(ndr_pipe_t *pipe)
+{
+	ndr_handle_t *hd;
+	ndr_handle_t **pphd;
+
+	(void) mutex_lock(&ndr_handle_lock);
+	pphd = &ndr_handle_list;
+
+	while (*pphd) {
+		hd = *pphd;
+
+		if (hd->nh_pipe == pipe) {
+			*pphd = hd->nh_next;
+
+			if (hd->nh_data_free)
+				(*hd->nh_data_free)(hd->nh_data);
+
+			free(hd);
+			continue;
+		}
+
+		pphd = &(*pphd)->nh_next;
+	}
+
+	(void) mutex_unlock(&ndr_handle_lock);
+}
+
+/*
+ * Convert a UUID to a string.
+ */
+void
+ndr_uuid_unparse(ndr_uuid_t *uuid, char *out)
+{
+	(void) sprintf(out, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+	    uuid->data1, uuid->data2, uuid->data3,
+	    uuid->data4[0], uuid->data4[1],
+	    uuid->data4[2], uuid->data4[3],
+	    uuid->data4[4], uuid->data4[5],
+	    uuid->data4[6], uuid->data4[7]);
+}
+
+/*
+ * Convert a string to a UUID.
+ */
+int
+ndr_uuid_parse(char *in, ndr_uuid_t *uuid)
+{
+	char 		*p = in;
+	char 		*q;
+	char		buf[4];
+	int		i;
+
+	if (strlen(in) != UUID_PRINTABLE_STRING_LENGTH - 1)
+		return (-1);
+
+	uuid->data1 = strtoul(p, &p, 16);
+	if (*p != '-')
+		return (-1);
+	p++;
+
+	uuid->data2 = strtol(p, &p, 16);
+	if (*p != '-')
+		return (-1);
+	p++;
+
+	uuid->data3 = strtol(p, &p, 16);
+	if (*p != '-')
+		return (-1);
+	p++;
+
+	for (i = 0; i < 8; i++) {
+		if (*p ==  '-')
+			p++;
+
+		if (p[0] == 0 || p[1] == 0)
+			return (-1);
+
+		buf[0] = *p++;
+		buf[1] = *p++;
+		buf[2] = 0;
+		uuid->data4[i] = strtol(buf, &q, 16);
+		if (*q != 0)
+			return (-1);
+	}
+
+	if (*p != 0)
+		return (-1);
+
+	return (0);
+}
+
+void
+ndr_svc_binding_pool_init(ndr_binding_t **headpp, ndr_binding_t pool[],
+    int n_pool)
+{
+	ndr_binding_t	*head = NULL;
+	int		ix;
+
+	for (ix = n_pool - 1; ix >= 0; ix--) {
+		pool[ix].next = head;
+		pool[ix].service = NULL;
+		pool[ix].p_cont_id = 0xffff;
+		pool[ix].instance_specific = 0;
+		head = &pool[ix];
+	}
+
+	*headpp = head;
+}
+
+ndr_binding_t *
+ndr_svc_find_binding(ndr_xa_t *mxa, ndr_p_context_id_t p_cont_id)
+{
+	ndr_binding_t *mbind;
+
+	for (mbind = mxa->binding_list; mbind; mbind = mbind->next) {
+		if (mbind->service != NULL &&
+		    mbind->which_side == NDR_BIND_SIDE_SERVER &&
+		    mbind->p_cont_id == p_cont_id)
+			break;
+	}
+
+	return (mbind);
+}
+
+ndr_binding_t *
+ndr_svc_new_binding(ndr_xa_t *mxa)
+{
+	ndr_binding_t *mbind;
+
+	for (mbind = mxa->binding_list; mbind; mbind = mbind->next) {
+		if (mbind->service == NULL)
+			break;
+	}
+
+	return (mbind);
+}
+
+/*
+ * Move bytes between a buffer and a uio structure.
+ * The transfer direction is controlled by rw:
+ *	UIO_READ:  transfer from buf to uio
+ *	UIO_WRITE: transfer from uio to buf
+ *
+ * Returns the number of bytes moved.
+ */
+ssize_t
+ndr_uiomove(caddr_t buf, size_t buflen, enum uio_rw rw, struct uio *uio)
+{
+	struct iovec *iov;
+	int reading = (rw == UIO_READ);
+	size_t nbytes;
+	size_t nxfer = 0;
+
+	assert(rw == UIO_READ || rw == UIO_WRITE);
+
+	while (buflen && uio->uio_resid && uio->uio_iovcnt) {
+		iov = uio->uio_iov;
+		if ((nbytes = iov->iov_len) == 0) {
+			uio->uio_iov++;
+			uio->uio_iovcnt--;
+			continue;
+		}
+
+		if (nbytes > buflen)
+			nbytes = buflen;
+
+		if (reading)
+			bcopy(buf, iov->iov_base, nbytes);
+		else
+			bcopy(iov->iov_base, buf, nbytes);
+
+		iov->iov_base += nbytes;
+		iov->iov_len -= nbytes;
+		uio->uio_resid -= nbytes;
+		uio->uio_offset += nbytes;
+		buf += nbytes;
+		buflen -= nbytes;
+		nxfer += nbytes;
+	}
+
+	return (nxfer);
+}
--- /dev/null	Sun Mar 18 01:13:17 2018
+++ new/usr/src/lib/libmlrpc/common/ndr_wchar.c	Sun Mar 18 01:13:17 2018
@@ -0,0 +1,162 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+/*
+ * Some wchar support functions used by this library.
+ * Mostlly just wrappers that call sys/u8_textprep.h
+ * functions: uconv_u8tou16, uconv_u16tou8.
+ */
+
+#include <sys/types.h>
+#include <sys/u8_textprep.h>
+#include <string.h>
+
+#include "ndr_wchar.h"
+
+/*
+ * When we just want lengths, we need an output buffer to pass to the
+ * uconv_... functions.  Nothing ever reads this output, so we can
+ * use shared space for the unwanted output.
+ */
+static uint16_t junk_wcs[NDR_STRING_MAX];
+static char junk_mbs[NDR_MB_CUR_MAX * NDR_STRING_MAX];
+
+static size_t
+ndr__mbstowcs_x(uint16_t *, const char *, size_t, int);
+
+/*
+ * Like mbstowcs(3C), but with UCS-2 wchar_t
+ */
+size_t
+ndr__mbstowcs(uint16_t *wcs, const char *mbs, size_t nwchars)
+{
+	return (ndr__mbstowcs_x(wcs, mbs, nwchars,
+	    UCONV_OUT_SYSTEM_ENDIAN));
+}
+
+/*
+ * Like above, but put UCS-2 little-endian.
+ */
+size_t
+ndr__mbstowcs_le(uint16_t *wcs, const char *mbs, size_t nwchars)
+{
+	return (ndr__mbstowcs_x(wcs, mbs, nwchars,
+	    UCONV_OUT_LITTLE_ENDIAN));
+}
+
+/*
+ * Like mbstowcs(3C), but with UCS-2 wchar_t, and
+ * one extra arg for the byte order flags.
+ */
+static size_t
+ndr__mbstowcs_x(uint16_t *wcs, const char *mbs, size_t nwchars, int flags)
+{
+	size_t obytes, mbslen, wcslen;
+	int err;
+
+	/* NULL or empty input is allowed. */
+	if (mbs == NULL || *mbs == '\0') {
+		if (wcs != NULL && nwchars > 0)
+			*wcs = 0;
+		return (0);
+	}
+
+	/*
+	 * If wcs == NULL, caller just wants the length.
+	 * Convert into some throw-away space.
+	 */
+	obytes = nwchars * 2;
+	if (wcs == NULL) {
+		if (obytes > sizeof (junk_wcs))
+			return ((size_t)-1);
+		wcs = junk_wcs;
+	}
+
+	mbslen = strlen(mbs);
+	wcslen = nwchars;
+	err = uconv_u8tou16((const uchar_t *)mbs, &mbslen,
+	    wcs, &wcslen, flags);
+	if (err != 0)
+		return ((size_t)-1);
+
+	if (wcslen < nwchars)
+		wcs[wcslen] = 0;
+
+	return (wcslen);
+}
+
+/*
+ * Like wcstombs(3C), but with UCS-2 wchar_t.
+ */
+size_t
+ndr__wcstombs(char *mbs, const uint16_t *wcs, size_t nbytes)
+{
+	size_t mbslen, wcslen;
+	int err;
+
+	/* NULL or empty input is allowed. */
+	if (wcs == NULL || *wcs == 0) {
+		if (mbs != NULL && nbytes > 0)
+			*mbs = '\0';
+		return (0);
+	}
+
+	/*
+	 * If mbs == NULL, caller just wants the length.
+	 * Convert into some throw-away space.
+	 */
+	if (mbs == NULL) {
+		if (nbytes > sizeof (junk_mbs))
+			return ((size_t)-1);
+		mbs = junk_mbs;
+	}
+
+	wcslen = ndr__wcslen(wcs);
+	mbslen = nbytes;
+	err = uconv_u16tou8(wcs, &wcslen,
+	    (uchar_t *)mbs, &mbslen, UCONV_IN_SYSTEM_ENDIAN);
+	if (err != 0)
+		return ((size_t)-1);
+
+	if (mbslen < nbytes)
+		mbs[mbslen] = '\0';
+
+	return (mbslen);
+}
+
+/*
+ * Like wcslen(3C), but with UCS-2 wchar_t.
+ */
+size_t
+ndr__wcslen(const uint16_t *wc)
+{
+	size_t len = 0;
+	while (*wc++)
+		len++;
+	return (len);
+}
--- /dev/null	Sun Mar 18 01:13:17 2018
+++ new/usr/src/lib/libmlrpc/common/ndr_wchar.h	Sun Mar 18 01:13:17 2018
@@ -0,0 +1,46 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+#ifndef _NDR_WCHAR_H
+#define	_NDR_WCHAR_H
+
+/*
+ * Some ndr_wchar_t support stuff.
+ */
+
+#define	NDR_MB_CUR_MAX		3
+#define	NDR_MB_CHAR_MAX		NDR_MB_CUR_MAX
+#define	NDR_STRING_MAX		4096
+
+size_t ndr__mbstowcs(uint16_t *, const char *, size_t);
+size_t ndr__mbstowcs_le(uint16_t *, const char *, size_t);
+
+size_t ndr__wcslen(const uint16_t *);
+size_t ndr__wcstombs(char *, const uint16_t *, size_t);
+
+#endif /* _NDR_WCHAR_H */
--- old/usr/src/uts/common/smbsrv/ndl/ndrtypes.ndl	Sun Mar 18 01:13:17 2018
+++ /dev/null	Sun Mar 18 01:13:17 2018
@@ -1,170 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _NDR_TYPES_NDL_
-#define _NDR_TYPES_NDL_
-
-#define TYPEINFO(TYPE)  ndt__##TYPE
-
-#ifdef NDRGEN
-
-#define ALIGN(X)	[align(X)]
-#define OPERATION(X)	[operation(X)]
-#define IN		[in]
-#define OUT		[out]
-#define INOUT		[in out]
-
-#define STRING		[string]
-#define SIZE_IS(X)	[size_is(X)]
-
-#define SWITCH(X)	[switch_is(X)]
-#define CASE(X)		[case(X)]
-#define DEFAULT		[default]
-
-#define INTERFACE(X)	[interface(X)]
-#define UUID(X)		[uuid(X)]
-
-#define ARG_IS(X)	[arg_is(X)]
-
-#define REFERENCE	[reference]
-#define REF		[reference]
-#define UNIQUE		[unique]
-#define PTR		[ptr]
-#define POINTER_DEFAULT(X)	[pointer_default(X)]
-
-#define ANY_SIZE_ARRAY	*
-
-#define IMPORT_EXTERN	[extern]
-
-#define BYTE	uchar
-#define WORD	ushort
-#define DWORD	ulong
-#define ntstatus_t	ulong
-
-#define LPTSTR	STRING wchar *
-
-#define LPBYTE  uchar *
-#define LPWORD  ushort *
-#define LPDWORD ulong *
-
-/*
- * Opaque context handle.
- */
-#ifndef CONTEXT_HANDLE
-#define CONTEXT_HANDLE(NAME)	\
-	struct NAME {		\
-		DWORD data1;    \
-		DWORD data2;    \
-		WORD  data3[2]; \
-		BYTE  data4[8];	\
-	};			\
-	typedef struct NAME
-#endif /* CONTEXT_HANDLE */
-
-#define EXTERNTYPEINFO(TYPE)
-
-#else /* NDRGEN */
-
-#define ALIGN(X)
-#define OPERATION(X)
-#define IN
-#define OUT
-#define INOUT
-
-#define STRING
-#define SIZE_IS(X)
-
-#define SWITCH(X)
-#define CASE(X)
-#define DEFAULT
-
-#define INTERFACE(X)
-#define UUID(X)
-
-#define ARG_IS(X)
-
-#define REFERENCE
-#define REF
-#define UNIQUE
-#define PTR
-#define POINTER_DEFAULT(X)
-
-#define IMPORT_EXTERN
-
-/*
- * When not using ndrgen, get BYTE, WORD, DWORD definitions from wintypes.h.
- */
-#include <smbsrv/wintypes.h>
-
-#define EXTERNTYPEINFO(TYPE)	extern struct ndr_typeinfo TYPEINFO(TYPE);
-
-
-/*
- ***********************************************************************
- * There is a bug in the way that midl and the marshalling code handles
- * unions so we need to fix some of the data offsets at runtime. The
- * following macros and the fixup function handle the correction.
- ***********************************************************************
- */
-
-/*
- * DECL_FIXUP_STRUCT allows us to declare external references to data
- * structures generated by ndrgen in the _ndr.c file.
- */
-#define DECL_FIXUP_STRUCT(NAME)	extern struct ndr_typeinfo ndt__##NAME
-
-/*
- * CASE_INFO_ENT is intended to simplify the declaration of the case
- * statement in the fixup function. Assuming you have followed the
- * convention for naming the individual structures all you have to do
- * is add a single line to the fixup function for each new case.
- */
-#define CASE_INFO_ENT(NAME,N) \
-			case N: size1 = sizeof (struct NAME##N); \
-			break
-
-/*
- * FIXUP_PDU_SIZE is used to patch the appropriate structures (identified
- * by DECL_FIXUP_STRUCT) at runtime. The values are based on the
- * switch_index.
- */
-#define FIXUP_PDU_SIZE(NAME,SIZE) { \
-	ndt__##NAME.pdu_size_fixed_part = SIZE; \
-	ndt__##NAME.c_size_fixed_part = SIZE; \
-}
-
-
-#endif /* NDRGEN */
-
-/*
- * UNION_INFO_ENT is intended to simplify adding new entries to a union.
- * If the entry structures are named using the form FunctionNameX,
- * where X is the sitch_value, you can just add a single line. Note
- * that you must also update the fixup function in mlsvc_xxx.c.
- */
-#define UNION_INFO_ENT(N,NAME) CASE(N) struct NAME##N info##N
-#define UNION_INFO_PTR(N,NAME) CASE(N) struct NAME##N *info##N
-
-#endif /* _NDR_TYPES_NDL_ */
--- /dev/null	Sun Mar 18 01:13:17 2018
+++ new/usr/src/lib/libmlrpc/common/ndrtypes.ndl	Sun Mar 18 01:13:17 2018
@@ -0,0 +1,177 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+#ifndef _NDRTYPES_NDL_
+#define _NDRTYPES_NDL_
+
+/*
+ * Type definitions (and related) used in NDL files and the
+ * NDL run-time support libraries.  See also: libmlrpc.h
+ */
+
+#define TYPEINFO(TYPE)  ndt__##TYPE
+
+#ifdef NDRGEN
+
+#define ALIGN(X)	[align(X)]
+#define OPERATION(X)	[operation(X)]
+#define IN		[in]
+#define OUT		[out]
+#define INOUT		[in out]
+
+#define STRING		[string]
+#define SIZE_IS(X)	[size_is(X)]
+
+#define SWITCH(X)	[switch_is(X)]
+#define CASE(X)		[case(X)]
+#define DEFAULT		[default]
+
+#define INTERFACE(X)	[interface(X)]
+#define UUID(X)		[uuid(X)]
+
+#define ARG_IS(X)	[arg_is(X)]
+
+#define REFERENCE	[reference]
+#define REF		[reference]
+#define UNIQUE		[unique]
+#define PTR		[ptr]
+#define POINTER_DEFAULT(X)	[pointer_default(X)]
+
+#define ANY_SIZE_ARRAY	*
+
+#define IMPORT_EXTERN	[extern]
+
+#define BYTE	uchar
+#define WORD	ushort
+#define DWORD	ulong
+#define ntstatus_t	ulong
+
+#define LPTSTR	STRING wchar *
+
+#define LPBYTE  uchar *
+#define LPWORD  ushort *
+#define LPDWORD ulong *
+
+#define EXTERNTYPEINFO(TYPE)
+
+#else /* NDRGEN */
+
+#define ALIGN(X)
+#define OPERATION(X)
+#define IN
+#define OUT
+#define INOUT
+
+#define STRING
+#define SIZE_IS(X)
+
+#define SWITCH(X)
+#define CASE(X)
+#define DEFAULT
+
+#define INTERFACE(X)
+#define UUID(X)
+
+#define ARG_IS(X)
+
+#define REFERENCE
+#define REF
+#define UNIQUE
+#define PTR
+#define POINTER_DEFAULT(X)
+
+#define IMPORT_EXTERN
+
+/*
+ * When not using ndrgen, get BYTE, WORD, DWORD definitions from wintypes.h.
+ */
+#include <smb/wintypes.h>
+
+#define EXTERNTYPEINFO(TYPE)	extern struct ndr_typeinfo TYPEINFO(TYPE);
+
+
+/*
+ ***********************************************************************
+ * There is a bug in the way that midl and the marshalling code handles
+ * unions so we need to fix some of the data offsets at runtime. The
+ * following macros and the fixup function handle the correction.
+ ***********************************************************************
+ */
+
+/*
+ * DECL_FIXUP_STRUCT allows us to declare external references to data
+ * structures generated by ndrgen in the _ndr.c file.
+ */
+#define DECL_FIXUP_STRUCT(NAME)	extern struct ndr_typeinfo ndt__##NAME
+
+/*
+ * CASE_INFO_ENT is intended to simplify the declaration of the case
+ * statement in the fixup function. Assuming you have followed the
+ * convention for naming the individual structures all you have to do
+ * is add a single line to the fixup function for each new case.
+ */
+#define CASE_INFO_ENT(NAME,N) \
+			case N: size1 = sizeof (struct NAME##N); \
+			break
+
+/*
+ * FIXUP_PDU_SIZE is used to patch the appropriate structures (identified
+ * by DECL_FIXUP_STRUCT) at runtime. The values are based on the
+ * switch_index.
+ */
+#define FIXUP_PDU_SIZE(NAME,SIZE) { \
+	ndt__##NAME.pdu_size_fixed_part = SIZE; \
+	ndt__##NAME.c_size_fixed_part = SIZE; \
+}
+
+
+#endif /* NDRGEN */
+
+/*
+ * UNION_INFO_ENT is intended to simplify adding new entries to a union.
+ * If the entry structures are named using the form FunctionNameX,
+ * where X is the sitch_value, you can just add a single line. Note
+ * that you must also update the fixup function in mlsvc_xxx.c.
+ */
+#define UNION_INFO_ENT(N,NAME) CASE(N) struct NAME##N info##N
+#define UNION_INFO_PTR(N,NAME) CASE(N) struct NAME##N *info##N
+
+/*
+ * Opaque context handle.
+ */
+#ifndef CONTEXT_HANDLE
+#define CONTEXT_HANDLE(NAME)	\
+	struct NAME {		\
+		DWORD data1;    \
+		DWORD data2;    \
+		WORD  data3[2]; \
+		BYTE  data4[8];	\
+	};			\
+	typedef struct NAME
+#endif /* CONTEXT_HANDLE */
+
+#endif /* _NDRTYPES_NDL_ */
--- old/usr/src/uts/common/smbsrv/ndl/rpcpdu.ndl	Sun Mar 18 01:13:17 2018
+++ /dev/null	Sun Mar 18 01:13:17 2018
@@ -1,665 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-#ifndef _RPCPDU_NDL_
-#define _RPCPDU_NDL_
-
-#include "ndrtypes.ndl"
-
-/*
- * Normally, constructs are (un)marshalled atoms first, then
- * constructs, then pointers. This can be confusing sometimes
- * when debugging. We know that everything in here can be
- * safely (un)marshalled in member order, so we say so.
- */
-#ifdef NDRGEN
-#define _NO_REORDER_ [_no_reorder]
-#else
-#define _NO_REORDER_
-#endif
-
-#define NDR_TRANSFER_SYNTAX_UUID	"8a885d04-1ceb-11c9-9fe8-08002b104860"
-
-/*
- * UUID (Universal Unique IDentifier)
- */
-/* (X/Open CAE Spec Appendix A) */
-struct ndr_dce_uuid {
-	DWORD		time_low;
-	WORD		time_mid;
-	WORD		time_hi_and_version;
-	BYTE		clock_seq_hi_and_reserved;
-	BYTE		clock_seq_low;
-	BYTE		node[6];
-};
-
-struct ndr_uuid {
-	DWORD		data1;
-	WORD		data2;
-	WORD		data3;
-	BYTE		data4[8];
-};
-typedef struct ndr_uuid ndr_uuid_t;
-
-/*
- * Representation label -- needed for RPC header
- * (X/Open CAE Spec Chapter 14.1)
- *
- * Bits   Data Type   Description
- * ----   ---------   -----------
- * 0-3    charset     0=ASCII
- *                    1=EBCDIC
- * 4-7    byte-order  0=big-endian
- *                    1=little-endian
- * 8-15   float       0=IEEE
- *                    1=VAX
- *                    2=Cray
- *                    3=IBM
- * 16-31  reserved
- */
-#define NDR_REPLAB_CHAR_MASK		0x0F	/* low nibble of intg_char */
-#define NDR_REPLAB_CHAR_ASCII		0x00	/* ASCII */
-#define NDR_REPLAB_CHAR_EBCDIC		0x01	/* EBCDIC (never happen) */
-#define NDR_REPLAB_INTG_MASK		0xF0	/* hi nibble of intg_char */
-#define NDR_REPLAB_INTG_BIG_ENDIAN	0x00	/* big endian */
-#define NDR_REPLAB_INTG_LITTLE_ENDIAN	0x10	/* little endian (x86) */
-#define NDR_REPLAB_FLOAT_IEEE		0x00
-#define NDR_REPLAB_FLOAT_VAX		0x01
-#define NDR_REPLAB_FLOAT_CRAY		0x02
-#define NDR_REPLAB_FLOAT_IBM		0x03
-
-struct ndr_representation_label {
-	BYTE		intg_char_rep;		/* integer and charset */
-	BYTE		float_rep;
-	BYTE		_spare[2];
-};
-typedef struct ndr_representation_label	ndr_replab_t;
-
-
-
-/*
- * RPC PDU (Protocol Data Unit) types
- ****************************************************************
- * (X/Open CAE Spec 12.1)
- */
-
-#define NDR_PTYPE_REQUEST		0x00	/* CO/CL */
-#define NDR_PTYPE_PING			0x01	/*    CL */
-#define NDR_PTYPE_RESPONSE		0x02	/* CO/CL */
-#define NDR_PTYPE_FAULT			0x03	/* CL/CL */
-#define NDR_PTYPE_WORKING		0x04	/*    CL */
-#define NDR_PTYPE_NOCALL		0x05	/*    CL */
-#define NDR_PTYPE_REJECT		0x06	/*    CL */
-#define NDR_PTYPE_ACK			0x07	/*    CL */
-#define NDR_PTYPE_CL_CANCEL		0x08	/*    CL */
-#define NDR_PTYPE_FACK			0x09	/*    CL */
-#define NDR_PTYPE_CANCEL_ACK		0x0A	/*    CL */
-#define NDR_PTYPE_BIND			0x0B	/* CO    */
-#define NDR_PTYPE_BIND_ACK		0x0C	/* CO    */
-#define NDR_PTYPE_BIND_NAK		0x0D	/* CO    */
-#define NDR_PTYPE_ALTER_CONTEXT		0x0E	/* CO    */
-#define NDR_PTYPE_ALTER_CONTEXT_RESP	0x0F	/* CO    */
-						/* 0x10 missing from DCE/RPC */
-#define NDR_PTYPE_SHUTDOWN		0x11	/* CO    */
-#define NDR_PTYPE_CO_CANCEL		0x12	/* CO    */
-#define NDR_PTYPE_ORPHANED		0x13	/* CO    */
-
-/*
- * Flags in the RPC header for Connection-oriented PDU data types
- * (X/Open CAE Spec 12.6.3.1)
- *
- * MS-RPCE 2.2.2.3 PFC_SUPPORT_HEADER_SIGN
- * For PDU types bind, bind_ack, alter_context and alter_context_resp,
- * 0x04 means PFC_SUPPORT_HEADER_SIGN.
- * For other PDU types 0x04 means PFC_PENDING_CANCEL. 
- */
-#define NDR_PFC_FIRST_FRAG		0x01	/* First fragment */
-#define NDR_PFC_LAST_FRAG		0x02	/* Last framgent */
-#define NDR_PFC_PENDING_CANCEL		0x04	/* Cancel was pending@sender*/
-#define NDR_PFC_SUPPORT_HEADER_SIGN	NDR_PFC_PENDING_CANCEL
-#define NDR_PFC_RESERVED_1		0x08	/* */
-#define NDR_PFC_CONC_MPX		0x10	/* supports concurrent muxing
-						 * of single connection */
-#define NDR_PFC_DID_NOT_EXECUTE		0x20	/* for PTYPE_FAULT, guarantee
-						 * call did not execute */
-#define NDR_PFC_MAYBE			0x40	/* "maybe" semantics req'ed*/
-#define NDR_PFC_OBJECT_UUID		0x80	/* */
-
-/*
- * Security Providers
- * MS-RPCE 2.2.1.1.6
- */
-#define	NDR_C_AUTHN_NONE			0x00	/* No authentication */
-#define	NDR_C_AUTHN_GSS_NEGOTIATE		0x09	/* SPNEGO */
-#define	NDR_C_AUTHN_WINNT			0x0A	/* NTLM */
-#define	NDR_C_AUTHN_GSS_KERBEROS		0x10	/* Kerberos */
-#define	NDR_C_AUTHN_GSS_NETLOGON		0x44	/* Netlogon */
-#define	NDR_C_AUTHN_GSS_DEFAULT			0xFF	/* Default is NTLM */
-
-/*
- * Encoding protection levels
- * X/Open CAE Spec 13.1.2.1
- * MS-RPCE 2.2.1.1.7
- */
-#define	NDR_C_AUTHN_LEVEL_DEFAULT		0x00	/* Same as Connect */
-#define	NDR_C_AUTHN_LEVEL_NONE			0x01
-#define	NDR_C_AUTHN_LEVEL_CONNECT		0x02
-#define	NDR_C_AUTHN_LEVEL_CALL			0x03
-#define	NDR_C_AUTHN_LEVEL_PKT			0x04
-#define	NDR_C_AUTHN_LEVEL_PKT_INTEGRITY		0x05
-#define	NDR_C_AUTHN_LEVEL_PKT_PRIVACY		0x06
-
-/*
- * Header common to all Connection-oriented RPC PDUs
- * (X/Open CAE Spec 12.6.3.1)
- */
-_NO_REORDER_
-struct ndr_p_syntax_id {
-	ndr_uuid_t	if_uuid;
-	DWORD		if_version;
-};
-typedef struct ndr_p_syntax_id	ndr_p_syntax_id_t;
-
-_NO_REORDER_
-struct ndr_common_header {
-	BYTE		rpc_vers;	/* 00:01 5 */
-	BYTE		rpc_vers_minor;	/* 01:01 0 */
-	BYTE		ptype;		/* 02:01 NDR_PTYPE_... */
-	BYTE		pfc_flags;	/* 03:01 NDR_PFC_... */
-	struct ndr_representation_label
-			packed_drep;	/* 04:04 NDR representation label */
-	WORD		frag_length;	/* 08:02 total length of frag */
-	WORD		auth_length;	/* 10:02 length of auth_value */
-	DWORD		call_id;	/* 12:04 call identifier */
-					/* 16: */
-};
-typedef struct ndr_common_header	ndr_common_header_t;
-EXTERNTYPEINFO(ndr_common_header)
-
-/*
- * MS-RPCE 2.2.6 Type Serialization Version 1 extensions to IDL/+ pickle
- * One header per serialization stream: the header must be little endian.
- * The filler must be set to 0xcccccccc during marshaling and ignored
- * during unmarshaling.
- */ 
-_NO_REORDER_
-struct ndr_serialtype1_hdr {
-	BYTE		version;	/* 00:01 1 */
-	BYTE		endianness;	/* 01:01 0=big, 1=little */
-	WORD		hdrlen;		/* 02:02 8 */
-	DWORD		filler;		/* 04:04 0xcccccccc */
-					/* 8: */
-};
-typedef struct ndr_serialtype1_hdr  ndr_serialtype1_hdr_t;
-EXTERNTYPEINFO(ndr_serialtype1_hdr)
-
-/*
- * Type Serialization Version 1 Private Header.
- * A private header must precede a top-level NDR constructed type.
- */
-_NO_REORDER_
-struct ndr_serialtype1_priv_hdr {
-	DWORD		buflen;		/* 00:04 */
-	DWORD		filler;		/* 04:04 must be zero */
-					/* 8: */
-};
-typedef struct ndr_serialtype1_priv_hdr	ndr_serialtype1_priv_hdr_t;
-EXTERNTYPEINFO(ndr_serialtype1_priv_hdr)
-
-/*
- * MS-RPCE 2.2.7 Type Serialization Version 2 extensions Version 1 (2.2.6).
- * The header must be little endian.
- * The endianinfo and reserved fields must be set to 0xcccccccc during
- * marshaling and ignored during unmarshaling.
- */ 
-_NO_REORDER_
-struct ndr_serialtype2_hdr {
-	BYTE		version;	/* 00:01 1 */
-	BYTE		endianness;	/* 01:01 0=big, 1=little */
-	WORD		hdrlen;		/* 02:02 8 */
-	DWORD		endianinfo;	/* 04:04 0xcccccccc */
-	DWORD		reserved[4];	/* 08:16 0xcccccccc */
-	ndr_p_syntax_id_t	transfer_syntax;	/* 24:20 */
-	ndr_p_syntax_id_t	interface_id;		/* 44:20 */
-					/* 64: */
-};
-typedef struct ndr_serialtype2_hdr  ndr_serialtype2_hdr_t;
-EXTERNTYPEINFO(ndr_serialtype2_hdr)
-
-/*
- * Type Serialization Version 2 Private Header.
- * A private header must precede a top-level NDR constructed type.
- */
-_NO_REORDER_
-struct ndr_serialtype2_priv_hdr {
-	DWORD		buflen;		/* 00:04 */
-	DWORD		filler[3];	/* 04:12 must be zero */
-					/* 16: */
-};
-typedef struct ndr_serialtype2_priv_hdr	ndr_serialtype2_priv_hdr_t;
-EXTERNTYPEINFO(ndr_serialtype2_priv_hdr)
-
-/*
- * This header comes before the NDR-encoded KERB_VALIDATION_INFO structure,
- * which can be found in one of the info buffers of the PAC.
- */
-_NO_REORDER_
-struct ndr_pac_hdr {
-	ndr_serialtype1_hdr_t		common_hdr;
-	ndr_serialtype1_priv_hdr_t	priv_hdr;
-	DWORD				ref_pointer;
-};
-typedef struct ndr_pac_hdr	ndr_pac_hdr_t;
-EXTERNTYPEINFO(ndr_pac_hdr)
-
-/*
- * Supporting types (X/Open CAE Spec 12.6.3.1)
- */
-typedef WORD	ndr_p_context_id_t;
-
-_NO_REORDER_
-struct ndr_p_cont_elem {
-	ndr_p_context_id_t	p_cont_id;
-	BYTE			n_transfer_syn;
-	BYTE			_reserved;
-	ndr_p_syntax_id_t	abstract_syntax;
-    /*SIZE_IS(n_transfer_syn)*/
-	ndr_p_syntax_id_t	transfer_syntaxes[1];
-};
-typedef struct ndr_p_cont_elem	ndr_p_cont_elem_t;
-EXTERNTYPEINFO(ndr_p_cont_elem)
-
-_NO_REORDER_
-struct ndr_p_cont_list {
-	BYTE		n_context_elem;
-	BYTE		_reserved;
-	WORD		_reserved2;
-    /*SIZE_IS(n_context_elem)*/
-	ndr_p_cont_elem_t p_cont_elem[1];
-};
-typedef struct ndr_p_cont_list	ndr_p_cont_list_t;
-EXTERNTYPEINFO(ndr_p_cont_list)
-
-typedef WORD	ndr_p_cont_def_result_t;
-#define NDR_PCDR_ACCEPTANCE					0
-#define NDR_PCDR_USER_REJECTION					1
-#define NDR_PCDR_PROVIDER_REJECTION				2
-
-/*
- * Reasons for provider rejection.
- * X/Open CAE Spec 12.6.3.1
- */
-typedef WORD	ndr_p_provider_reason_t;
-#define	NDR_PPR_REASON_NOT_SPECIFIED				0
-#define	NDR_PPR_ABSTRACT_SYNTAX_NOT_SUPPORTED			1
-#define	NDR_PPR_PROPOSED_TRANSFER_SYNTAXES_NOT_SUPPORTED	2
-#define	NDR_PPR_LOCAL_LIMIT_EXCEEDED				3
-
-_NO_REORDER_
-struct ndr_p_result {
-	ndr_p_cont_def_result_t	result;		/* NDR_PCDR_... */
-	ndr_p_provider_reason_t	reason;		/* NDR_PPR_... */
-	ndr_p_syntax_id_t	transfer_syntax; /* 0-fill if result!=ACCEPT */
-};
-typedef struct ndr_p_result		ndr_p_result_t;
-EXTERNTYPEINFO(ndr_p_result)
-
-_NO_REORDER_
-struct ndr_p_result_list {
-	BYTE		n_results;
-	BYTE		reserved;
-	WORD		reserved2;
-    /*SIZE_IS(n_results)*/
-	ndr_p_result_t p_results[1];
-};
-typedef struct ndr_p_result_list	ndr_p_result_list_t;
-EXTERNTYPEINFO(ndr_p_result_list)
-
-#define NDR_PORT_ANY_MAX_PORT_SPEC	30
-_NO_REORDER_
-struct ndr_port_any {
-	WORD		length;		/* always 18 */
-    /*SIZE_IS(length)*/
-	BYTE		port_spec[NDR_PORT_ANY_MAX_PORT_SPEC];
-					/* \PIPE\ntsvcs */
-	/* We cheat by using 18, and pad on the right with zeroes */
-};
-typedef struct ndr_port_any		ndr_port_any_t;
-EXTERNTYPEINFO(ndr_port_any)
-
-/*
- * Reasons for rejecting an association in the bind_nak PDU.
- * X/Open CAE Spec 12.6.3.1
- * MS-RPCE 2.2.2.5
- */
-#define	NDR_REASON_NOT_SPECIFIED				0
-#define NDR_TEMPORARY_CONGESTION				1
-#define NDR_LOCAL_LIMIT_EXCEEDED				2
-#define NDR_CALLED_PADDR_UNKNOWN				3
-#define NDR_PROTOCOL_VERSION_NOT_SUPPORTED			4
-#define NDR_DEFAULT_CONTEXT_NOT_SUPPORTED			5
-#define NDR_USER_DATA_NOT_READABLE				6
-#define NDR_NO_PSAP_AVAILABLE					7
-#define NDR_AUTH_TYPE_NOT_RECOGNIZED				8
-#define NDR_INAVLID_CHECKSUM					9
-
-/*
- * Alter Context PDU (0x0E)
- * (X/Open CAE Spec 12.6.4.1)
- */
-_NO_REORDER_
-struct ndr_alter_context_hdr {
-	ndr_common_header_t common_hdr; /* 00:16 (see above) */
-
-	WORD max_xmit_frag;		/* 16:02 ignored */
-	WORD max_recv_frag;		/* 18:02 ignored */
-	DWORD assoc_group_id;		/* 20:04 ignored */
-
-	/* 
-	 * Presentation context list (see bind hdr comments).
-	 */
-	ndr_p_cont_list_t p_context_elem;	/* 24: */
-
-	/* optional authentication verifier if auth_length != 0 */
-	/* auth_verifier_co_t auth_verifier; */
-};
-typedef struct ndr_alter_context_hdr ndr_alter_context_hdr_t;
-
-
-/*
- * Alter Context Response PDU (0x0F)
- * (X/Open CAE Spec 12.6.4.2)
- *
- * We can't automatically generate an alter context response header because
- * the sec_addr is an interior conformant (variable length) array, which is
- * inconsistent with IDL/NDR rules.  We mark this import-extern and provide
- * a hand-coded marshalling function.
- */
-IMPORT_EXTERN
-_NO_REORDER_
-struct ndr_alter_context_rsp_hdr {
-	ndr_common_header_t common_hdr; /* 00:16 (see above) */
-
-	WORD max_xmit_frag;		/* 16:02 ignored */
-	WORD max_recv_frag;		/* 18:02 ignored */
-	DWORD assoc_group_id;		/* 20:04 ignored */
-	ndr_port_any_t sec_addr;	/* 24:20 ignored */
-
-	/* 
-	 * Presentation context list (see bind hdr comments).
-	 */
-	ndr_p_result_list_t p_result_list; /* 44:nn */
-
-	/* optional authentication verifier if auth_length != 0 */
-	/* auth_verifier_co_t auth_verifier; */
-};
-typedef struct ndr_alter_context_rsp_hdr ndr_alter_context_rsp_hdr_t;
-
-
-/*
- * Bind PDU (0x0B)
- * (X/Open CAE Spec 12.6.4.3)
- */
-_NO_REORDER_
-struct ndr_bind_hdr {
-	ndr_common_header_t	common_hdr; /* 00:16 (see above) */
-
-	WORD		max_xmit_frag;	/* 16:02 max xmit frag size, bytes */
-	WORD		max_recv_frag;	/* 18:02 max recv frag size, bytes */
-	DWORD		assoc_group_id;	/* 20:04 association group */
-					/* 24: */
-
-	/* presentation, a variable**2 list, of presentation contexts */
-	ndr_p_cont_list_t p_context_elem;
-
-	/*
-	 * This could be followed by more transfer_syntaxes[] for the
-	 * p_cont_elem[0], and subsequently followed by more p_cont_elem[],
-	 * each with one or more transfer_syntaxes[].  A single
-	 * p_cont_elem[] with a single transfer_syntaxes[] is so common,
-	 * though, we embed it in the bind_hdr but the bind processor must
-	 * walk through this tail if there is one.
-	 */
-
-	/* optional authentication verifier iff auth_length != 0 */
-	/* auth_verifier_co_t	auth_verifier; */
-};
-typedef struct ndr_bind_hdr	ndr_bind_hdr_t;
-
-
-/*
- * Bind_Ack PDU (0x0C)
- * (X/Open CAE Spec 12.6.4.4)
- *
- * We can't automatically generate a bind ack header because the sec_addr
- * is an interior conformant (variable length) array, which is inconsistent
- * with IDL/NDR rules.  We mark this import-extern and provide a hand-coded
- * marshalling function.
- */
-IMPORT_EXTERN
-_NO_REORDER_
-struct ndr_bind_ack_hdr {
-	ndr_common_header_t	common_hdr; /* 00:16 (see above) */
-
-	WORD		max_xmit_frag;	/* 16:02 max xmit frag size, bytes */
-	WORD		max_recv_frag;	/* 18:02 max recv frag size, bytes */
-	DWORD		assoc_group_id;	/* 20:04 association group */
-	ndr_port_any_t	sec_addr;	/* 24:20 */
-
-	ndr_p_result_list_t p_result_list; /* 44:nn */
-	/* This could be followed by more. See bind_hdr above */
-
-	/* optional authentication verifier iff auth_length != 0 */
-	/* auth_verifier_co_t	auth_verifier; */
-};
-typedef struct ndr_bind_ack_hdr	ndr_bind_ack_hdr_t;
-
-
-/*
- * Request PDU (0x00)
- ****************************************************************
- * Two flavors, selected based on PFC_OBJECT_UUID in hdr.pfc_flags
- *	one without the "object" (flag clear)
- *	one with the "object" (flag set)
- * (X/Open CAE Spec 12.6.4.9)
- */
-
-_NO_REORDER_
-struct ndr_request_hdr {
-	ndr_common_header_t	common_hdr; /* 00:16 (see above) */
-
-	/* needed for request, response, or fault */
-	DWORD		alloc_hint;	/* 16:04 allocation hint */
-	ndr_p_context_id_t p_cont_id;	/* 20:02 pres context, i.e. data rep */
-	WORD		opnum;		/* 22:02 op number w/i interface */
-
-	/* optional field if PFC_OBJECT_UUID, not present */
-	/* ndr_uuid_t	object; */
-
-	/* stub-data, 8-octet aligned */ /* 24:nn */
-	/* nn = frag_len - sizeof(common_header) - auth_len */
-
-	/* optional authentication verifier iff auth_length != 0 */
-	/* auth_verifier_co_t	auth_verifier; */
-};
-typedef struct ndr_request_hdr	ndr_request_hdr_t;
-
-_NO_REORDER_
-struct ndr_request_hdr_with_object {
-	ndr_common_header_t	common_hdr; /* 00:16 (see above) */
-
-	/* needed for request, response, or fault */
-	DWORD		alloc_hint;	/* 16:04 allocation hint */
-	ndr_p_context_id_t p_cont_id;	/* 20:02 pres context, i.e. data rep */
-	WORD		opnum;		/* 22:02 op number w/i interface */
-
-	/* optional field if PFC_OBJECT_UUID, is present */
-	ndr_uuid_t	object;		/* 24:16 object UUID, unknown purpose*/
-
-	/* stub-data, 8-octet aligned */ /* 28:nn */
-	/* nn = frag_len - sizeof(common_header) - auth_len */
-	/* nn -= sizeof(ndr_uuid_t); */
-
-	/* optional authentication verifier iff auth_length != 0 */
-	/* auth_verifier_co_t	auth_verifier; */
-};
-
-
-/*
- * Convenient for response header sizing and multi-fragment responses.
- * We know the header is going to be 24 bytes.
- */
-#define NDR_RSP_HDR_SIZE			24
-
-
-/*
- * Response PDU (0x02)
- * (X/Open CAE Spec 12.6.4.10)
- */
-
-_NO_REORDER_
-struct ndr_response_hdr {
-	ndr_common_header_t	common_hdr; /* 00:16 (see above) */
-
-	/* needed for request, response, or fault */
-	DWORD		alloc_hint;	/* 16:04 allocation hint */
-	ndr_p_context_id_t p_cont_id;	/* 20:02 pres context, i.e. data rep */
-
-	/* needed for response or fault */
-	BYTE		cancel_count;	/* 22:01 cancel count */
-	BYTE		reserved;	/* 23:01 mbz */
-
-	/* stub-data, 8-octet aligned */ /* 24:nn */
-	/* nn = frag_len - sizeof(common_header) - auth_len */
-
-	/* optional authentication verifier iff auth_length != 0 */
-	/* auth_verifier_co_t	auth_verifier; */
-};
-typedef struct ndr_response_hdr	ndr_response_hdr_t;
-
-
-/*
- * Fault PDU (0x03)
- * (X/Open CAE Spec 12.6.4.7)
- */
-
-_NO_REORDER_
-struct ndr_fault_hdr {
-	ndr_common_header_t	common_hdr; /* 00:16 (see above) */
-
-	DWORD		alloc_hint;	/* 16:04 allocation hint */
-	ndr_p_context_id_t p_cont_id;	/* 20:02 pres context, i.e. data rep */
-
-	/* needed for response or fault */
-	BYTE		cancel_count;	/* 22:01 cancel count */
-	BYTE		reserved;	/* 23:01 mbz */
-
-	/* fault code */
-	DWORD		status;		/* 24:04 run-time fault code or 0 */
-
-	/* pad to 8-byte alignment */
-	BYTE		reserved2[4];	/* 28:04 must-be-zero */
-
-	/* stub-data here if status==0. We do not use this mode. */
-
-	/* optional authentication verifier iff auth_length != 0 */
-	/* auth_verifier_co_t	auth_verifier; */
-};
-typedef struct ndr_fault_hdr	ndr_fault_hdr_t;
-
-
-/* Fault status code (X/Open CAE Spec Appendix E) */
-#define NDR_FAULT_NCA_RPC_VERSION_MISMATCH	0x1c000008	/* CO/CL */
-#define NDR_FAULT_NCA_UNSPEC_REJECT		0x1c000009	/* CO/CL */
-#define NDR_FAULT_NCA_S_BAD_ACTID		0x1c00000A	/*    CL */
-#define NDR_FAULT_NCA_WHO_ARE_YOU_FAILED	0x1c00000B	/*    CL */
-#define NDR_FAULT_NCA_MANAGER_NOT_ENTERED	0x1c00000C	/* CO/CL */
-#define NDR_FAULT_NCA_OP_RNG_ERROR		0x1c010002	/* CO/CL */
-#define NDR_FAULT_NCA_UNK_IF			0x1c010003	/* CO/CL */
-#define NDR_FAULT_NCA_WRONG_BOOT_TIME		0x1c010006	/*    CL */
-#define NDR_FAULT_NCA_S_YOU_CRASHED		0x1c010009	/*    CL */
-#define NDR_FAULT_NCA_PROTO_ERROR		0x1c01000B	/* CO/CL */
-#define NDR_FAULT_NCA_OUT_ARGS_TOO_BIG		0x1c010013	/* CO/CL */
-#define NDR_FAULT_NCA_SERVER_TOO_BUSY		0x1c010014	/* CO/CL */
-#define NDR_FAULT_NCA_UNSUPPORTED_TYPE		0x1c010017	/* CO/CL */
-#define NDR_FAULT_NCA_INVALID_PRES_CONTEXT_ID	0x1c00001c	/* CO    */
-#define NDR_FAULT_NCA_UNSUPPORTED_AUTHN_LEVEL	0x1c00001d	/* CO/CL */
-#define NDR_FAULT_NCA_INVALID_CHECKSUM		0x1c00001f	/* CO/CL */
-#define NDR_FAULT_NCA_INVALID_CRC		0x1c000020	/* CO/CL */
-
-
-/*
- * The Header Union/Switch
- ****************************************************************
- */
-
-#define NDR_PTYPE_COMMON		999
-#define NDR_PTYPE_REQUEST_WITH		998
-#define	NDR_PTYPE_SERIALTYPE_V1		997
-#define	NDR_PTYPE_SERIALTYPE_V2		996
-#define	NDR_PTYPE_PAC			995
-
-INTERFACE(0)
-union ndr_hdr {
-    CASE(NDR_PTYPE_COMMON)	/* exceeds BYTE range, obtains common hdr */
-	struct ndr_common_header		common_hdr;
-
-    CASE(NDR_PTYPE_BIND)
-	struct ndr_bind_hdr			bind_hdr;
-
-    CASE(NDR_PTYPE_BIND_ACK)
-	struct ndr_bind_ack_hdr			bind_ack_hdr;
-
-    CASE(NDR_PTYPE_REQUEST)
-	struct ndr_request_hdr			request_hdr;
-
-    CASE(NDR_PTYPE_REQUEST_WITH)	/* exceeds BYTE range, ... */
-	struct ndr_request_hdr_with_object	request_hdr_with;
-
-    CASE(NDR_PTYPE_RESPONSE)
-	struct ndr_response_hdr			response_hdr;
-
-    CASE(NDR_PTYPE_ALTER_CONTEXT)
-	struct ndr_alter_context_hdr		alter_context_hdr;
-
-    CASE(NDR_PTYPE_ALTER_CONTEXT_RESP)
-	struct ndr_alter_context_rsp_hdr	alter_context_rsp_hdr;
-
-    CASE(NDR_PTYPE_SERIALTYPE_V1)
-	struct ndr_serialtype1_hdr		serialtype1_hdr;
-
-    CASE(NDR_PTYPE_SERIALTYPE_V2)
-	struct ndr_serialtype2_hdr		serialtype2_hdr;
-
-    CASE(NDR_PTYPE_PAC)
-	struct ndr_pac_hdr			pac_hdr;
-
-    CASE(NDR_PTYPE_FAULT)
-	struct ndr_fault_hdr			fault_hdr;
-};
-typedef union ndr_hdr	ndr_hdr_t;
-EXTERNTYPEINFO(ndr_hdr)
-
-#endif /* _RPCPDU_NDL_ */
-
--- /dev/null	Sun Mar 18 01:13:17 2018
+++ new/usr/src/lib/libmlrpc/common/rpcpdu.ndl	Sun Mar 18 01:13:17 2018
@@ -0,0 +1,666 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+#ifndef _RPCPDU_NDL_
+#define _RPCPDU_NDL_
+
+#include "ndrtypes.ndl"
+
+/*
+ * Normally, constructs are (un)marshalled atoms first, then
+ * constructs, then pointers. This can be confusing sometimes
+ * when debugging. We know that everything in here can be
+ * safely (un)marshalled in member order, so we say so.
+ */
+#ifdef NDRGEN
+#define _NO_REORDER_ [_no_reorder]
+#else
+#define _NO_REORDER_
+#endif
+
+#define NDR_TRANSFER_SYNTAX_UUID	"8a885d04-1ceb-11c9-9fe8-08002b104860"
+
+/*
+ * UUID (Universal Unique IDentifier)
+ */
+/* (X/Open CAE Spec Appendix A) */
+struct ndr_dce_uuid {
+	DWORD		time_low;
+	WORD		time_mid;
+	WORD		time_hi_and_version;
+	BYTE		clock_seq_hi_and_reserved;
+	BYTE		clock_seq_low;
+	BYTE		node[6];
+};
+
+struct ndr_uuid {
+	DWORD		data1;
+	WORD		data2;
+	WORD		data3;
+	BYTE		data4[8];
+};
+typedef struct ndr_uuid ndr_uuid_t;
+
+/*
+ * Representation label -- needed for RPC header
+ * (X/Open CAE Spec Chapter 14.1)
+ *
+ * Bits   Data Type   Description
+ * ----   ---------   -----------
+ * 0-3    charset     0=ASCII
+ *                    1=EBCDIC
+ * 4-7    byte-order  0=big-endian
+ *                    1=little-endian
+ * 8-15   float       0=IEEE
+ *                    1=VAX
+ *                    2=Cray
+ *                    3=IBM
+ * 16-31  reserved
+ */
+#define NDR_REPLAB_CHAR_MASK		0x0F	/* low nibble of intg_char */
+#define NDR_REPLAB_CHAR_ASCII		0x00	/* ASCII */
+#define NDR_REPLAB_CHAR_EBCDIC		0x01	/* EBCDIC (never happen) */
+#define NDR_REPLAB_INTG_MASK		0xF0	/* hi nibble of intg_char */
+#define NDR_REPLAB_INTG_BIG_ENDIAN	0x00	/* big endian */
+#define NDR_REPLAB_INTG_LITTLE_ENDIAN	0x10	/* little endian (x86) */
+#define NDR_REPLAB_FLOAT_IEEE		0x00
+#define NDR_REPLAB_FLOAT_VAX		0x01
+#define NDR_REPLAB_FLOAT_CRAY		0x02
+#define NDR_REPLAB_FLOAT_IBM		0x03
+
+struct ndr_representation_label {
+	BYTE		intg_char_rep;		/* integer and charset */
+	BYTE		float_rep;
+	BYTE		_spare[2];
+};
+typedef struct ndr_representation_label	ndr_replab_t;
+
+
+
+/*
+ * RPC PDU (Protocol Data Unit) types
+ ****************************************************************
+ * (X/Open CAE Spec 12.1)
+ */
+
+#define NDR_PTYPE_REQUEST		0x00	/* CO/CL */
+#define NDR_PTYPE_PING			0x01	/*    CL */
+#define NDR_PTYPE_RESPONSE		0x02	/* CO/CL */
+#define NDR_PTYPE_FAULT			0x03	/* CL/CL */
+#define NDR_PTYPE_WORKING		0x04	/*    CL */
+#define NDR_PTYPE_NOCALL		0x05	/*    CL */
+#define NDR_PTYPE_REJECT		0x06	/*    CL */
+#define NDR_PTYPE_ACK			0x07	/*    CL */
+#define NDR_PTYPE_CL_CANCEL		0x08	/*    CL */
+#define NDR_PTYPE_FACK			0x09	/*    CL */
+#define NDR_PTYPE_CANCEL_ACK		0x0A	/*    CL */
+#define NDR_PTYPE_BIND			0x0B	/* CO    */
+#define NDR_PTYPE_BIND_ACK		0x0C	/* CO    */
+#define NDR_PTYPE_BIND_NAK		0x0D	/* CO    */
+#define NDR_PTYPE_ALTER_CONTEXT		0x0E	/* CO    */
+#define NDR_PTYPE_ALTER_CONTEXT_RESP	0x0F	/* CO    */
+						/* 0x10 missing from DCE/RPC */
+#define NDR_PTYPE_SHUTDOWN		0x11	/* CO    */
+#define NDR_PTYPE_CO_CANCEL		0x12	/* CO    */
+#define NDR_PTYPE_ORPHANED		0x13	/* CO    */
+
+/*
+ * Flags in the RPC header for Connection-oriented PDU data types
+ * (X/Open CAE Spec 12.6.3.1)
+ *
+ * MS-RPCE 2.2.2.3 PFC_SUPPORT_HEADER_SIGN
+ * For PDU types bind, bind_ack, alter_context and alter_context_resp,
+ * 0x04 means PFC_SUPPORT_HEADER_SIGN.
+ * For other PDU types 0x04 means PFC_PENDING_CANCEL. 
+ */
+#define NDR_PFC_FIRST_FRAG		0x01	/* First fragment */
+#define NDR_PFC_LAST_FRAG		0x02	/* Last framgent */
+#define NDR_PFC_PENDING_CANCEL		0x04	/* Cancel was pending@sender*/
+#define NDR_PFC_SUPPORT_HEADER_SIGN	NDR_PFC_PENDING_CANCEL
+#define NDR_PFC_RESERVED_1		0x08	/* */
+#define NDR_PFC_CONC_MPX		0x10	/* supports concurrent muxing
+						 * of single connection */
+#define NDR_PFC_DID_NOT_EXECUTE		0x20	/* for PTYPE_FAULT, guarantee
+						 * call did not execute */
+#define NDR_PFC_MAYBE			0x40	/* "maybe" semantics req'ed*/
+#define NDR_PFC_OBJECT_UUID		0x80	/* */
+
+/*
+ * Security Providers
+ * MS-RPCE 2.2.1.1.6
+ */
+#define	NDR_C_AUTHN_NONE			0x00	/* No authentication */
+#define	NDR_C_AUTHN_GSS_NEGOTIATE		0x09	/* SPNEGO */
+#define	NDR_C_AUTHN_WINNT			0x0A	/* NTLM */
+#define	NDR_C_AUTHN_GSS_KERBEROS		0x10	/* Kerberos */
+#define	NDR_C_AUTHN_GSS_NETLOGON		0x44	/* Netlogon */
+#define	NDR_C_AUTHN_GSS_DEFAULT			0xFF	/* Default is NTLM */
+
+/*
+ * Encoding protection levels
+ * X/Open CAE Spec 13.1.2.1
+ * MS-RPCE 2.2.1.1.7
+ */
+#define	NDR_C_AUTHN_LEVEL_DEFAULT		0x00	/* Same as Connect */
+#define	NDR_C_AUTHN_LEVEL_NONE			0x01
+#define	NDR_C_AUTHN_LEVEL_CONNECT		0x02
+#define	NDR_C_AUTHN_LEVEL_CALL			0x03
+#define	NDR_C_AUTHN_LEVEL_PKT			0x04
+#define	NDR_C_AUTHN_LEVEL_PKT_INTEGRITY		0x05
+#define	NDR_C_AUTHN_LEVEL_PKT_PRIVACY		0x06
+
+/*
+ * Header common to all Connection-oriented RPC PDUs
+ * (X/Open CAE Spec 12.6.3.1)
+ */
+_NO_REORDER_
+struct ndr_p_syntax_id {
+	ndr_uuid_t	if_uuid;
+	DWORD		if_version;
+};
+typedef struct ndr_p_syntax_id	ndr_p_syntax_id_t;
+
+_NO_REORDER_
+struct ndr_common_header {
+	BYTE		rpc_vers;	/* 00:01 5 */
+	BYTE		rpc_vers_minor;	/* 01:01 0 */
+	BYTE		ptype;		/* 02:01 NDR_PTYPE_... */
+	BYTE		pfc_flags;	/* 03:01 NDR_PFC_... */
+	struct ndr_representation_label
+			packed_drep;	/* 04:04 NDR representation label */
+	WORD		frag_length;	/* 08:02 total length of frag */
+	WORD		auth_length;	/* 10:02 length of auth_value */
+	DWORD		call_id;	/* 12:04 call identifier */
+					/* 16: */
+};
+typedef struct ndr_common_header	ndr_common_header_t;
+EXTERNTYPEINFO(ndr_common_header)
+
+/*
+ * MS-RPCE 2.2.6 Type Serialization Version 1 extensions to IDL/+ pickle
+ * One header per serialization stream: the header must be little endian.
+ * The filler must be set to 0xcccccccc during marshaling and ignored
+ * during unmarshaling.
+ */ 
+_NO_REORDER_
+struct ndr_serialtype1_hdr {
+	BYTE		version;	/* 00:01 1 */
+	BYTE		endianness;	/* 01:01 0=big, 1=little */
+	WORD		hdrlen;		/* 02:02 8 */
+	DWORD		filler;		/* 04:04 0xcccccccc */
+					/* 8: */
+};
+typedef struct ndr_serialtype1_hdr  ndr_serialtype1_hdr_t;
+EXTERNTYPEINFO(ndr_serialtype1_hdr)
+
+/*
+ * Type Serialization Version 1 Private Header.
+ * A private header must precede a top-level NDR constructed type.
+ */
+_NO_REORDER_
+struct ndr_serialtype1_priv_hdr {
+	DWORD		buflen;		/* 00:04 */
+	DWORD		filler;		/* 04:04 must be zero */
+					/* 8: */
+};
+typedef struct ndr_serialtype1_priv_hdr	ndr_serialtype1_priv_hdr_t;
+EXTERNTYPEINFO(ndr_serialtype1_priv_hdr)
+
+/*
+ * MS-RPCE 2.2.7 Type Serialization Version 2 extensions Version 1 (2.2.6).
+ * The header must be little endian.
+ * The endianinfo and reserved fields must be set to 0xcccccccc during
+ * marshaling and ignored during unmarshaling.
+ */ 
+_NO_REORDER_
+struct ndr_serialtype2_hdr {
+	BYTE		version;	/* 00:01 1 */
+	BYTE		endianness;	/* 01:01 0=big, 1=little */
+	WORD		hdrlen;		/* 02:02 8 */
+	DWORD		endianinfo;	/* 04:04 0xcccccccc */
+	DWORD		reserved[4];	/* 08:16 0xcccccccc */
+	ndr_p_syntax_id_t	transfer_syntax;	/* 24:20 */
+	ndr_p_syntax_id_t	interface_id;		/* 44:20 */
+					/* 64: */
+};
+typedef struct ndr_serialtype2_hdr  ndr_serialtype2_hdr_t;
+EXTERNTYPEINFO(ndr_serialtype2_hdr)
+
+/*
+ * Type Serialization Version 2 Private Header.
+ * A private header must precede a top-level NDR constructed type.
+ */
+_NO_REORDER_
+struct ndr_serialtype2_priv_hdr {
+	DWORD		buflen;		/* 00:04 */
+	DWORD		filler[3];	/* 04:12 must be zero */
+					/* 16: */
+};
+typedef struct ndr_serialtype2_priv_hdr	ndr_serialtype2_priv_hdr_t;
+EXTERNTYPEINFO(ndr_serialtype2_priv_hdr)
+
+/*
+ * This header comes before the NDR-encoded KERB_VALIDATION_INFO structure,
+ * which can be found in one of the info buffers of the PAC.
+ */
+_NO_REORDER_
+struct ndr_pac_hdr {
+	ndr_serialtype1_hdr_t		common_hdr;
+	ndr_serialtype1_priv_hdr_t	priv_hdr;
+	DWORD				ref_pointer;
+};
+typedef struct ndr_pac_hdr	ndr_pac_hdr_t;
+EXTERNTYPEINFO(ndr_pac_hdr)
+
+/*
+ * Supporting types (X/Open CAE Spec 12.6.3.1)
+ */
+typedef WORD	ndr_p_context_id_t;
+
+_NO_REORDER_
+struct ndr_p_cont_elem {
+	ndr_p_context_id_t	p_cont_id;
+	BYTE			n_transfer_syn;
+	BYTE			_reserved;
+	ndr_p_syntax_id_t	abstract_syntax;
+    /*SIZE_IS(n_transfer_syn)*/
+	ndr_p_syntax_id_t	transfer_syntaxes[1];
+};
+typedef struct ndr_p_cont_elem	ndr_p_cont_elem_t;
+EXTERNTYPEINFO(ndr_p_cont_elem)
+
+_NO_REORDER_
+struct ndr_p_cont_list {
+	BYTE		n_context_elem;
+	BYTE		_reserved;
+	WORD		_reserved2;
+    /*SIZE_IS(n_context_elem)*/
+	ndr_p_cont_elem_t p_cont_elem[1];
+};
+typedef struct ndr_p_cont_list	ndr_p_cont_list_t;
+EXTERNTYPEINFO(ndr_p_cont_list)
+
+typedef WORD	ndr_p_cont_def_result_t;
+#define NDR_PCDR_ACCEPTANCE					0
+#define NDR_PCDR_USER_REJECTION					1
+#define NDR_PCDR_PROVIDER_REJECTION				2
+
+/*
+ * Reasons for provider rejection.
+ * X/Open CAE Spec 12.6.3.1
+ */
+typedef WORD	ndr_p_provider_reason_t;
+#define	NDR_PPR_REASON_NOT_SPECIFIED				0
+#define	NDR_PPR_ABSTRACT_SYNTAX_NOT_SUPPORTED			1
+#define	NDR_PPR_PROPOSED_TRANSFER_SYNTAXES_NOT_SUPPORTED	2
+#define	NDR_PPR_LOCAL_LIMIT_EXCEEDED				3
+
+_NO_REORDER_
+struct ndr_p_result {
+	ndr_p_cont_def_result_t	result;		/* NDR_PCDR_... */
+	ndr_p_provider_reason_t	reason;		/* NDR_PPR_... */
+	ndr_p_syntax_id_t	transfer_syntax; /* 0-fill if result!=ACCEPT */
+};
+typedef struct ndr_p_result		ndr_p_result_t;
+EXTERNTYPEINFO(ndr_p_result)
+
+_NO_REORDER_
+struct ndr_p_result_list {
+	BYTE		n_results;
+	BYTE		reserved;
+	WORD		reserved2;
+    /*SIZE_IS(n_results)*/
+	ndr_p_result_t p_results[1];
+};
+typedef struct ndr_p_result_list	ndr_p_result_list_t;
+EXTERNTYPEINFO(ndr_p_result_list)
+
+#define NDR_PORT_ANY_MAX_PORT_SPEC	30
+_NO_REORDER_
+struct ndr_port_any {
+	WORD		length;		/* always 18 */
+    /*SIZE_IS(length)*/
+	BYTE		port_spec[NDR_PORT_ANY_MAX_PORT_SPEC];
+					/* \PIPE\ntsvcs */
+	/* We cheat by using 18, and pad on the right with zeroes */
+};
+typedef struct ndr_port_any		ndr_port_any_t;
+EXTERNTYPEINFO(ndr_port_any)
+
+/*
+ * Reasons for rejecting an association in the bind_nak PDU.
+ * X/Open CAE Spec 12.6.3.1
+ * MS-RPCE 2.2.2.5
+ */
+#define	NDR_REASON_NOT_SPECIFIED				0
+#define NDR_TEMPORARY_CONGESTION				1
+#define NDR_LOCAL_LIMIT_EXCEEDED				2
+#define NDR_CALLED_PADDR_UNKNOWN				3
+#define NDR_PROTOCOL_VERSION_NOT_SUPPORTED			4
+#define NDR_DEFAULT_CONTEXT_NOT_SUPPORTED			5
+#define NDR_USER_DATA_NOT_READABLE				6
+#define NDR_NO_PSAP_AVAILABLE					7
+#define NDR_AUTH_TYPE_NOT_RECOGNIZED				8
+#define NDR_INAVLID_CHECKSUM					9
+
+/*
+ * Alter Context PDU (0x0E)
+ * (X/Open CAE Spec 12.6.4.1)
+ */
+_NO_REORDER_
+struct ndr_alter_context_hdr {
+	ndr_common_header_t common_hdr; /* 00:16 (see above) */
+
+	WORD max_xmit_frag;		/* 16:02 ignored */
+	WORD max_recv_frag;		/* 18:02 ignored */
+	DWORD assoc_group_id;		/* 20:04 ignored */
+
+	/* 
+	 * Presentation context list (see bind hdr comments).
+	 */
+	ndr_p_cont_list_t p_context_elem;	/* 24: */
+
+	/* optional authentication verifier if auth_length != 0 */
+	/* auth_verifier_co_t auth_verifier; */
+};
+typedef struct ndr_alter_context_hdr ndr_alter_context_hdr_t;
+
+
+/*
+ * Alter Context Response PDU (0x0F)
+ * (X/Open CAE Spec 12.6.4.2)
+ *
+ * We can't automatically generate an alter context response header because
+ * the sec_addr is an interior conformant (variable length) array, which is
+ * inconsistent with IDL/NDR rules.  We mark this import-extern and provide
+ * a hand-coded marshalling function.
+ */
+IMPORT_EXTERN
+_NO_REORDER_
+struct ndr_alter_context_rsp_hdr {
+	ndr_common_header_t common_hdr; /* 00:16 (see above) */
+
+	WORD max_xmit_frag;		/* 16:02 ignored */
+	WORD max_recv_frag;		/* 18:02 ignored */
+	DWORD assoc_group_id;		/* 20:04 ignored */
+	ndr_port_any_t sec_addr;	/* 24:20 ignored */
+
+	/* 
+	 * Presentation context list (see bind hdr comments).
+	 */
+	ndr_p_result_list_t p_result_list; /* 44:nn */
+
+	/* optional authentication verifier if auth_length != 0 */
+	/* auth_verifier_co_t auth_verifier; */
+};
+typedef struct ndr_alter_context_rsp_hdr ndr_alter_context_rsp_hdr_t;
+
+
+/*
+ * Bind PDU (0x0B)
+ * (X/Open CAE Spec 12.6.4.3)
+ */
+_NO_REORDER_
+struct ndr_bind_hdr {
+	ndr_common_header_t	common_hdr; /* 00:16 (see above) */
+
+	WORD		max_xmit_frag;	/* 16:02 max xmit frag size, bytes */
+	WORD		max_recv_frag;	/* 18:02 max recv frag size, bytes */
+	DWORD		assoc_group_id;	/* 20:04 association group */
+					/* 24: */
+
+	/* presentation, a variable**2 list, of presentation contexts */
+	ndr_p_cont_list_t p_context_elem;
+
+	/*
+	 * This could be followed by more transfer_syntaxes[] for the
+	 * p_cont_elem[0], and subsequently followed by more p_cont_elem[],
+	 * each with one or more transfer_syntaxes[].  A single
+	 * p_cont_elem[] with a single transfer_syntaxes[] is so common,
+	 * though, we embed it in the bind_hdr but the bind processor must
+	 * walk through this tail if there is one.
+	 */
+
+	/* optional authentication verifier iff auth_length != 0 */
+	/* auth_verifier_co_t	auth_verifier; */
+};
+typedef struct ndr_bind_hdr	ndr_bind_hdr_t;
+
+
+/*
+ * Bind_Ack PDU (0x0C)
+ * (X/Open CAE Spec 12.6.4.4)
+ *
+ * We can't automatically generate a bind ack header because the sec_addr
+ * is an interior conformant (variable length) array, which is inconsistent
+ * with IDL/NDR rules.  We mark this import-extern and provide a hand-coded
+ * marshalling function.
+ */
+IMPORT_EXTERN
+_NO_REORDER_
+struct ndr_bind_ack_hdr {
+	ndr_common_header_t	common_hdr; /* 00:16 (see above) */
+
+	WORD		max_xmit_frag;	/* 16:02 max xmit frag size, bytes */
+	WORD		max_recv_frag;	/* 18:02 max recv frag size, bytes */
+	DWORD		assoc_group_id;	/* 20:04 association group */
+	ndr_port_any_t	sec_addr;	/* 24:20 */
+
+	ndr_p_result_list_t p_result_list; /* 44:nn */
+	/* This could be followed by more. See bind_hdr above */
+
+	/* optional authentication verifier iff auth_length != 0 */
+	/* auth_verifier_co_t	auth_verifier; */
+};
+typedef struct ndr_bind_ack_hdr	ndr_bind_ack_hdr_t;
+
+
+/*
+ * Request PDU (0x00)
+ ****************************************************************
+ * Two flavors, selected based on PFC_OBJECT_UUID in hdr.pfc_flags
+ *	one without the "object" (flag clear)
+ *	one with the "object" (flag set)
+ * (X/Open CAE Spec 12.6.4.9)
+ */
+
+_NO_REORDER_
+struct ndr_request_hdr {
+	ndr_common_header_t	common_hdr; /* 00:16 (see above) */
+
+	/* needed for request, response, or fault */
+	DWORD		alloc_hint;	/* 16:04 allocation hint */
+	ndr_p_context_id_t p_cont_id;	/* 20:02 pres context, i.e. data rep */
+	WORD		opnum;		/* 22:02 op number w/i interface */
+
+	/* optional field if PFC_OBJECT_UUID, not present */
+	/* ndr_uuid_t	object; */
+
+	/* stub-data, 8-octet aligned */ /* 24:nn */
+	/* nn = frag_len - sizeof(common_header) - auth_len */
+
+	/* optional authentication verifier iff auth_length != 0 */
+	/* auth_verifier_co_t	auth_verifier; */
+};
+typedef struct ndr_request_hdr	ndr_request_hdr_t;
+
+_NO_REORDER_
+struct ndr_request_hdr_with_object {
+	ndr_common_header_t	common_hdr; /* 00:16 (see above) */
+
+	/* needed for request, response, or fault */
+	DWORD		alloc_hint;	/* 16:04 allocation hint */
+	ndr_p_context_id_t p_cont_id;	/* 20:02 pres context, i.e. data rep */
+	WORD		opnum;		/* 22:02 op number w/i interface */
+
+	/* optional field if PFC_OBJECT_UUID, is present */
+	ndr_uuid_t	object;		/* 24:16 object UUID, unknown purpose*/
+
+	/* stub-data, 8-octet aligned */ /* 28:nn */
+	/* nn = frag_len - sizeof(common_header) - auth_len */
+	/* nn -= sizeof(ndr_uuid_t); */
+
+	/* optional authentication verifier iff auth_length != 0 */
+	/* auth_verifier_co_t	auth_verifier; */
+};
+
+
+/*
+ * Convenient for response header sizing and multi-fragment responses.
+ * We know the header is going to be 24 bytes.
+ */
+#define NDR_RSP_HDR_SIZE			24
+
+
+/*
+ * Response PDU (0x02)
+ * (X/Open CAE Spec 12.6.4.10)
+ */
+
+_NO_REORDER_
+struct ndr_response_hdr {
+	ndr_common_header_t	common_hdr; /* 00:16 (see above) */
+
+	/* needed for request, response, or fault */
+	DWORD		alloc_hint;	/* 16:04 allocation hint */
+	ndr_p_context_id_t p_cont_id;	/* 20:02 pres context, i.e. data rep */
+
+	/* needed for response or fault */
+	BYTE		cancel_count;	/* 22:01 cancel count */
+	BYTE		reserved;	/* 23:01 mbz */
+
+	/* stub-data, 8-octet aligned */ /* 24:nn */
+	/* nn = frag_len - sizeof(common_header) - auth_len */
+
+	/* optional authentication verifier iff auth_length != 0 */
+	/* auth_verifier_co_t	auth_verifier; */
+};
+typedef struct ndr_response_hdr	ndr_response_hdr_t;
+
+
+/*
+ * Fault PDU (0x03)
+ * (X/Open CAE Spec 12.6.4.7)
+ */
+
+_NO_REORDER_
+struct ndr_fault_hdr {
+	ndr_common_header_t	common_hdr; /* 00:16 (see above) */
+
+	DWORD		alloc_hint;	/* 16:04 allocation hint */
+	ndr_p_context_id_t p_cont_id;	/* 20:02 pres context, i.e. data rep */
+
+	/* needed for response or fault */
+	BYTE		cancel_count;	/* 22:01 cancel count */
+	BYTE		reserved;	/* 23:01 mbz */
+
+	/* fault code */
+	DWORD		status;		/* 24:04 run-time fault code or 0 */
+
+	/* pad to 8-byte alignment */
+	BYTE		reserved2[4];	/* 28:04 must-be-zero */
+
+	/* stub-data here if status==0. We do not use this mode. */
+
+	/* optional authentication verifier iff auth_length != 0 */
+	/* auth_verifier_co_t	auth_verifier; */
+};
+typedef struct ndr_fault_hdr	ndr_fault_hdr_t;
+
+
+/* Fault status code (X/Open CAE Spec Appendix E) */
+#define NDR_FAULT_NCA_RPC_VERSION_MISMATCH	0x1c000008	/* CO/CL */
+#define NDR_FAULT_NCA_UNSPEC_REJECT		0x1c000009	/* CO/CL */
+#define NDR_FAULT_NCA_S_BAD_ACTID		0x1c00000A	/*    CL */
+#define NDR_FAULT_NCA_WHO_ARE_YOU_FAILED	0x1c00000B	/*    CL */
+#define NDR_FAULT_NCA_MANAGER_NOT_ENTERED	0x1c00000C	/* CO/CL */
+#define NDR_FAULT_NCA_OP_RNG_ERROR		0x1c010002	/* CO/CL */
+#define NDR_FAULT_NCA_UNK_IF			0x1c010003	/* CO/CL */
+#define NDR_FAULT_NCA_WRONG_BOOT_TIME		0x1c010006	/*    CL */
+#define NDR_FAULT_NCA_S_YOU_CRASHED		0x1c010009	/*    CL */
+#define NDR_FAULT_NCA_PROTO_ERROR		0x1c01000B	/* CO/CL */
+#define NDR_FAULT_NCA_OUT_ARGS_TOO_BIG		0x1c010013	/* CO/CL */
+#define NDR_FAULT_NCA_SERVER_TOO_BUSY		0x1c010014	/* CO/CL */
+#define NDR_FAULT_NCA_UNSUPPORTED_TYPE		0x1c010017	/* CO/CL */
+#define NDR_FAULT_NCA_INVALID_PRES_CONTEXT_ID	0x1c00001c	/* CO    */
+#define NDR_FAULT_NCA_UNSUPPORTED_AUTHN_LEVEL	0x1c00001d	/* CO/CL */
+#define NDR_FAULT_NCA_INVALID_CHECKSUM		0x1c00001f	/* CO/CL */
+#define NDR_FAULT_NCA_INVALID_CRC		0x1c000020	/* CO/CL */
+
+
+/*
+ * The Header Union/Switch
+ ****************************************************************
+ */
+
+#define NDR_PTYPE_COMMON		999
+#define NDR_PTYPE_REQUEST_WITH		998
+#define	NDR_PTYPE_SERIALTYPE_V1		997
+#define	NDR_PTYPE_SERIALTYPE_V2		996
+#define	NDR_PTYPE_PAC			995
+
+INTERFACE(0)
+union ndr_hdr {
+    CASE(NDR_PTYPE_COMMON)	/* exceeds BYTE range, obtains common hdr */
+	struct ndr_common_header		common_hdr;
+
+    CASE(NDR_PTYPE_BIND)
+	struct ndr_bind_hdr			bind_hdr;
+
+    CASE(NDR_PTYPE_BIND_ACK)
+	struct ndr_bind_ack_hdr			bind_ack_hdr;
+
+    CASE(NDR_PTYPE_REQUEST)
+	struct ndr_request_hdr			request_hdr;
+
+    CASE(NDR_PTYPE_REQUEST_WITH)	/* exceeds BYTE range, ... */
+	struct ndr_request_hdr_with_object	request_hdr_with;
+
+    CASE(NDR_PTYPE_RESPONSE)
+	struct ndr_response_hdr			response_hdr;
+
+    CASE(NDR_PTYPE_ALTER_CONTEXT)
+	struct ndr_alter_context_hdr		alter_context_hdr;
+
+    CASE(NDR_PTYPE_ALTER_CONTEXT_RESP)
+	struct ndr_alter_context_rsp_hdr	alter_context_rsp_hdr;
+
+    CASE(NDR_PTYPE_SERIALTYPE_V1)
+	struct ndr_serialtype1_hdr		serialtype1_hdr;
+
+    CASE(NDR_PTYPE_SERIALTYPE_V2)
+	struct ndr_serialtype2_hdr		serialtype2_hdr;
+
+    CASE(NDR_PTYPE_PAC)
+	struct ndr_pac_hdr			pac_hdr;
+
+    CASE(NDR_PTYPE_FAULT)
+	struct ndr_fault_hdr			fault_hdr;
+};
+typedef union ndr_hdr	ndr_hdr_t;
+EXTERNTYPEINFO(ndr_hdr)
+
+#endif /* _RPCPDU_NDL_ */
+
--- old/usr/src/lib/smbsrv/libmlrpc/i386/Makefile	Sun Mar 18 01:13:17 2018
+++ /dev/null	Sun Mar 18 01:13:17 2018
@@ -1,32 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-include ../Makefile.com
-
-DYNFLAGS +=	-R/usr/lib/smbsrv
-
-install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- /dev/null	Sun Mar 18 01:13:17 2018
+++ new/usr/src/lib/libmlrpc/i386/Makefile	Sun Mar 18 01:13:17 2018
@@ -0,0 +1,28 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- old/usr/src/lib/smbsrv/libmlrpc/sparc/Makefile	Sun Mar 18 01:13:17 2018
+++ /dev/null	Sun Mar 18 01:13:17 2018
@@ -1,32 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-include ../Makefile.com
-
-DYNFLAGS +=	-R/usr/lib/smbsrv
-
-install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- /dev/null	Sun Mar 18 01:13:17 2018
+++ new/usr/src/lib/libmlrpc/sparc/Makefile	Sun Mar 18 01:13:17 2018
@@ -0,0 +1,28 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- old/usr/src/lib/smbsrv/libmlrpc/sparcv9/Makefile	Sun Mar 18 01:13:18 2018
+++ /dev/null	Sun Mar 18 01:13:17 2018
@@ -1,35 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-MACH_LDLIBS +=	-L$(ROOT)/usr/lib/smbsrv/$(MACH64)
-
-include ../Makefile.com
-include ../../../Makefile.lib.64
-
-DYNFLAGS +=	-R/usr/lib/smbsrv/$(MACH64)
-
-install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
--- /dev/null	Sun Mar 18 01:13:17 2018
+++ new/usr/src/lib/libmlrpc/sparcv9/Makefile	Sun Mar 18 01:13:18 2018
@@ -0,0 +1,31 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+MACH_LDLIBS +=	-L$(ROOT)/usr/lib/smbsrv/$(MACH64)
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
--- old/usr/src/lib/libsmbfs/Makefile.com	Sun Mar 18 01:13:18 2018
+++ new/usr/src/lib/libsmbfs/Makefile.com	Sun Mar 18 01:13:18 2018
@@ -59,7 +59,6 @@
 	nb_ssn.o \
 	nbns_rq.o \
 	negprot.o \
-	netshareenum.o \
 	newvc.o \
 	nls.o \
 	ntlm.o \
--- old/usr/src/lib/libsmbfs/netsmb/smb_netshareenum.h	Sun Mar 18 01:13:18 2018
+++ /dev/null	Sun Mar 18 01:13:17 2018
@@ -1,18 +0,0 @@
-
-#ifndef _NETSMB_SMB_NETSHAREENUM_H_
-#define	_NETSMB_SMB_NETSHAREENUM_H_
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/* This is from Apple.  See ../smb/netshareenum.c */
-
-struct share_info {
-	uint16_t	type;
-	char		*netname;
-	char		*remark;
-};
-typedef struct share_info share_info_t;
-
-int  smb_netshareenum(struct smb_ctx *, int *, int *, struct share_info **);
-
-#endif /* _NETSMB_SMB_NETSHAREENUM_H_ */
--- old/usr/src/lib/libsmbfs/smb/llib-lsmbfs	Sun Mar 18 01:13:18 2018
+++ new/usr/src/lib/libsmbfs/smb/llib-lsmbfs	Sun Mar 18 01:13:18 2018
@@ -34,7 +34,6 @@
 
 #include <netsmb/smb_lib.h>
 #include <netsmb/smb_keychain.h>
-#include <netsmb/smb_netshareenum.h>
 #include <netsmb/smb_rap.h>
 #include <netsmb/spnego.h>
 
--- old/usr/src/lib/libsmbfs/smb/mapfile-vers	Sun Mar 18 01:13:18 2018
+++ new/usr/src/lib/libsmbfs/smb/mapfile-vers	Sun Mar 18 01:13:18 2018
@@ -111,7 +111,6 @@
 	smb_iod_start;
 	smb_iod_work;
 	smb_lib_init;
-	smb_netshareenum;	# will move to libnetapi
 	smb_open_printer;
 	smb_open_rcfile;
 	smb_simplecrypt;
--- old/usr/src/lib/libsmbfs/smb/netshareenum.c	Sun Mar 18 01:13:18 2018
+++ /dev/null	Sun Mar 18 01:13:17 2018
@@ -1,378 +0,0 @@
-/*
- * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License').  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License."
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-/* BEGIN CSTYLED */
-/*
- *      @(#)ui.c      *
- *      (c) 2004   Apple Computer, Inc.  All Rights Reserved
- *
- *
- *      netshareenum.c -- Routines for getting a list of share information
- *			  from a server.
- *
- *      MODIFICATION HISTORY:
- *       27-Nov-2004     Guy Harris	New today
- */
-/* END CSTYLED */
-
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include <netsmb/mchain.h>
-#include <netsmb/smb.h>
-#include <netsmb/smb_lib.h>
-#include <netsmb/smb_rap.h>
-#include <netsmb/smb_netshareenum.h>
-#include <smb/charsets.h>
-
-#if 0 /* XXX see below */
-#include <dce/exc_handling.h>
-#include <rpc/attrb.h>
-#include "srvsvc.h"
-#endif
-
-/*
- * Don't want RPC client-side code in here.
- * It's good code; just doesn't belong here.
- *
- * The API provided by this library should be
- * just files and pipes (and not much more).
- * It MAY be useful to provide some of the
- * RAP (remote API) functions functions like
- * rap_netshareenum below...
- *
- * XXX: Not sure this file belongs here at all.
- * smb_rap.h looks like a reasonable API
- * for this library to export.
- */
-#if 0 /* XXX */
-
-static int
-rpc_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp,
-    struct share_info **entries_listp)
-{
-	char ctx_string[2+16+1];	/* enough for 64-bit pointer, in hex */
-	unsigned_char_p_t binding;
-	unsigned32 binding_status;
-	rpc_binding_handle_t binding_h;
-	int error, i, entries;
-	char *addrstr, *srvnamestr;
-	unsigned short *usrvnamestr;
-	unsigned32 level;
-	SHARE_ENUM_STRUCT share_info;
-	SHARE_INFO_1_CONTAINER share_info_1_container;
-	SHARE_INFO_1 *shares, *share;
-	unsigned32 total_entries;
-	unsigned32 status, free_status;
-	struct share_info *entry_list, *elp;
-	static EXCEPTION rpc_x_connect_rejected;
-	static int exceptions_initialized;
-
-	sprintf(ctx_string, "%p", ctx);
-	rpc_string_binding_compose(NULL, "ncacn_np", ctx_string,
-	    "srvsvc", NULL, &binding, &binding_status);
-	if (binding_status != rpc_s_ok) {
-		smb_error(dgettext(TEXT_DOMAIN,
-		    "rpc_string_binding_compose failed with %d"),
-		    0, binding_status);
-		return (EINVAL);
-	}
-	rpc_binding_from_string_binding(binding, &binding_h, &status);
-	rpc_string_free(&binding, (unsigned32 *)&free_status);
-	if (binding_status != rpc_s_ok) {
-		smb_error(dgettext(TEXT_DOMAIN,
-		    "rpc_binding_from_string_binding failed with %d"), 0,
-		    binding_status);
-		return (EINVAL);
-	}
-	level = 1;
-	share_info.share_union.level = 1;
-	share_info.share_union.tagged_union.share1 = &share_info_1_container;
-	share_info_1_container.share_count = 0;
-	share_info_1_container.shares = NULL;
-	/*
-	 * Convert the server IP address to a string, and send that as
-	 * the "server name" - that's what Windows appears to do, and
-	 * that avoids problems with NetBIOS names containing
-	 * non-ASCII characters.
-	 */
-	addrstr = inet_ntoa(ctx->ct_srvinaddr.sin_addr);
-	srvnamestr = malloc(strlen(addrstr) + 3);
-	if (srvnamestr == NULL) {
-		status = errno;
-		smb_error(dgettext(TEXT_DOMAIN,
-		    "can't allocate string for server address"), status);
-		rpc_binding_free(&binding_h, &free_status);
-		return (status);
-	}
-	strcpy(srvnamestr, "\\\\");
-	strcat(srvnamestr, addrstr);
-	usrvnamestr = convert_utf8_to_leunicode(srvnamestr);
-	if (usrvnamestr == NULL) {
-		smb_error(dgettext(TEXT_DOMAIN,
-		    "can't convert string for server address to Unicode"), 0);
-		rpc_binding_free(&binding_h, &free_status);
-		free(srvnamestr);
-		return (EINVAL);
-	}
-	if (!exceptions_initialized) {
-		EXCEPTION_INIT(rpc_x_connect_rejected);
-		exc_set_status(&rpc_x_connect_rejected, rpc_s_connect_rejected);
-		exceptions_initialized = 1;
-	}
-	/* printf("Calling NetrShareEnum.."); XXX */
-	TRY
-		status = NetrShareEnum(binding_h, usrvnamestr, &level,
-		    &share_info, 4294967295U, &total_entries, NULL);
-		if (status != 0)
-			smb_error(dgettext(TEXT_DOMAIN,
-			    "error from NetrShareEnum call: status = 0x%08x"),
-			    0, status);
-	/*CSTYLED*/
-	CATCH (rpc_x_connect_rejected)
-		/*
-		 * This is what we get if we can't open the pipe.
-		 * That's a normal occurrence when we're talking
-		 * to a system that (presumably) doesn't support
-		 * DCE RPC on the server side, such as Windows 95/98/Me,
-		 * so we don't log an error.
-		 */
-		/*CSTYLED*/
-		status = ENOTSUP;
-	CATCH_ALL
-		/*
-		 * XXX - should we handle some exceptions differently,
-		 * returning different errors, and try RAP only for
-		 * ENOTSUP?
-		 */
-		smb_error(dgettext(TEXT_DOMAIN,
-		    "error from NetrShareEnum call: exception = %u"),
-		    0, THIS_CATCH->match.value);
-		status = ENOTSUP;
-	ENDTRY
-	rpc_binding_free(&binding_h, &free_status);
-	free(srvnamestr);
-	free(usrvnamestr);
-	if (status != 0)
-		return (ENOTSUP);
-
-	/*
-	 * XXX - if the IDL is correct, it's not clear whether the
-	 * unmarshalling code will properly handle the case where
-	 * a packet where "share_count" and the max count for the
-	 * array of shares don't match; a valid DCE RPC implementation
-	 * won't marshal something like that, but there's no guarantee
-	 * that the server we're talking to has a valid implementation
-	 * (which could be a *malicious* implementation!).
-	 */
-	entries = share_info.share_union.tagged_union.share1->share_count;
-	shares = share_info.share_union.tagged_union.share1->shares;
-	entry_list = calloc(entries, sizeof (struct share_info));
-	if (entry_list == NULL) {
-		error = errno;
-		goto cleanup_and_return;
-	}
-	for (share = shares, elp = entry_list, i = 0; i < entries;
-	    i++, share++) {
-		elp->type = share->shi1_type;
-		elp->netname = convert_unicode_to_utf8(share->shi1_share);
-		if (elp->netname == NULL)
-			goto fail;
-		elp->remark = convert_unicode_to_utf8(share->shi1_remark);
-		if (elp->remark == NULL)
-			goto fail;
-		elp++;
-	}
-	*entriesp = entries;
-	*totalp = total_entries;
-	*entries_listp = entry_list;
-	error = 0;
-	goto cleanup_and_return;
-
-fail:
-	error = errno;
-	for (elp = entry_list, i = 0; i < entries; i++, elp++) {
-		/*
-		 * elp->netname is set before elp->remark, so if
-		 * elp->netname is null, elp->remark is also null.
-		 * If either of them is null, we haven't done anything
-		 * to any entries after this one.
-		 */
-		if (elp->netname == NULL)
-			break;
-		free(elp->netname);
-		if (elp->remark == NULL)
-			break;
-		free(elp->remark);
-	}
-	free(entry_list);
-
-cleanup_and_return:
-	for (share = shares, i = 0; i < entries; i++, share++) {
-		free(share->shi1_share);
-		free(share->shi1_remark);
-	}
-	free(shares);
-	/*
-	 * XXX - "share1" should be a unique pointer, but we haven't
-	 * changed the marshalling code to support non-full pointers
-	 * in unions, so we leave it as a full pointer.
-	 *
-	 * That means that this might, or might not, be changed from
-	 * pointing to "share_info_1_container" to pointing to a
-	 * mallocated structure, according to the DCE RPC 1.1 IDL spec;
-	 * we free it only if it's changed.
-	 */
-	if (share_info.share_union.tagged_union.share1 !=
-	    &share_info_1_container)
-		free(share_info.share_union.tagged_union.share1);
-	return (error);
-}
-#endif /* XXX */
-
-/*
- * Enumerate shares using RAP
- */
-
-struct smb_share_info_1 {
-	char		shi1_netname[13];
-	char		shi1_pad;
-	uint16_t	shi1_type;
-	uint32_t	shi1_remark;		/* char * */
-};
-
-static int
-smb_rap_NetShareEnum(struct smb_ctx *ctx, int sLevel, void *pbBuffer,
-	int *cbBuffer, int *pcEntriesRead, int *pcTotalAvail)
-{
-	struct smb_rap *rap;
-	long lval = -1;
-	int error;
-
-	error = smb_rap_create(0, "WrLeh", "B13BWz", &rap);
-	if (error)
-		return (error);
-	(void) smb_rap_setNparam(rap, sLevel);		/* W - sLevel */
-	(void) smb_rap_setPparam(rap, pbBuffer);	/* r - pbBuffer */
-	(void) smb_rap_setNparam(rap, *cbBuffer);	/* L - cbBuffer */
-	error = smb_rap_request(rap, ctx);
-	if (error == 0) {
-		*pcEntriesRead = rap->r_entries;
-		error = smb_rap_getNparam(rap, &lval);
-		*pcTotalAvail = lval;
-		/* Copy the data length into the IN/OUT variable. */
-		*cbBuffer = rap->r_rcvbuflen;
-	}
-	error = smb_rap_error(rap, error);
-	smb_rap_done(rap);
-	return (error);
-}
-
-static int
-rap_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp,
-    struct share_info **entries_listp)
-{
-	int error, bufsize, i, entries, total, nreturned;
-	struct smb_share_info_1 *rpbuf, *ep;
-	struct share_info *entry_list, *elp;
-	char *cp;
-	int lbound, rbound;
-
-	bufsize = 0xffe0;	/* samba notes win2k bug for 65535 */
-	rpbuf = malloc(bufsize);
-	if (rpbuf == NULL)
-		return (errno);
-
-	error = smb_rap_NetShareEnum(ctx, 1, rpbuf, &bufsize, &entries, &total);
-	if (error &&
-	    error != (ERROR_MORE_DATA | SMB_RAP_ERROR)) {
-		free(rpbuf);
-		return (error);
-	}
-	entry_list = malloc(entries * sizeof (struct share_info));
-	if (entry_list == NULL) {
-		error = errno;
-		free(rpbuf);
-		return (error);
-	}
-	lbound = entries * (sizeof (struct smb_share_info_1));
-	rbound = bufsize;
-	for (ep = rpbuf, elp = entry_list, i = 0, nreturned = 0; i < entries;
-	    i++, ep++) {
-		elp->type = letohs(ep->shi1_type);
-		ep->shi1_pad = '\0'; /* ensure null termination */
-		elp->netname = convert_wincs_to_utf8(ep->shi1_netname);
-		if (elp->netname == NULL)
-			continue;	/* punt on this entry */
-		/*
-		 * Check for validity of offset.
-		 */
-		if (ep->shi1_remark >= lbound && ep->shi1_remark < rbound) {
-			cp = (char *)rpbuf + ep->shi1_remark;
-			elp->remark = convert_wincs_to_utf8(cp);
-		} else
-			elp->remark = NULL;
-		elp++;
-		nreturned++;
-	}
-	*entriesp = nreturned;
-	*totalp = total;
-	*entries_listp = entry_list;
-	free(rpbuf);
-	return (0);
-}
-
-/*
- * First we try the RPC-based NetrShareEnum, and, if that fails, we fall
- * back on the RAP-based NetShareEnum.
- */
-int
-smb_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp,
-    struct share_info **entry_listp)
-{
-	int error;
-
-#ifdef NOTYETDEFINED
-	/*
-	 * Try getting a list of shares with the SRVSVC RPC service.
-	 */
-	error = rpc_netshareenum(ctx, entriesp, totalp, entry_listp);
-	if (error == 0)
-		return (0);
-#endif
-
-	/*
-	 * OK, that didn't work - try RAP.
-	 * XXX - do so only if it failed because we couldn't open
-	 * the pipe?
-	 */
-	error = rap_netshareenum(ctx, entriesp, totalp, entry_listp);
-	return (error);
-}
--- old/usr/src/lib/smbsrv/Makefile	Sun Mar 18 01:13:18 2018
+++ new/usr/src/lib/smbsrv/Makefile	Sun Mar 18 01:13:18 2018
@@ -29,7 +29,6 @@
 SUBDIRS = \
 	libfksmbsrv \
 	libmlsvc \
-	libmlrpc \
 	libsmb \
 	libsmbns \
 	libsmbrp
@@ -36,7 +35,6 @@
 
 include ./Makefile.subdirs
 
-libmlrpc: libsmb
 libsmbns: libsmb
-libmlsvc: libsmb libmlrpc libsmbns
+libmlsvc: libsmb libsmbns
 libfksmbsrv: libsmb
--- old/usr/src/lib/smbsrv/Makefile.targ	Sun Mar 18 01:13:18 2018
+++ new/usr/src/lib/smbsrv/Makefile.targ	Sun Mar 18 01:13:18 2018
@@ -22,7 +22,8 @@
 # Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-#ident	"%Z%%M%	%I%	%E% SMI"
+# Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+#
 
 #
 # Common targets for smbsrv Makefiles
@@ -29,12 +30,14 @@
 #
 
 %_ndr.c: $(NDLDIR)/%.ndl
-	$(NDRGEN) -Y $(CC) $<
+	$(NDRGEN) -Y $(ANSI_CPP) $(CPPFLAGS) $<
 
 pics/%.o:	$(SRC)/common/smbsrv/%.c
 	$(COMPILE.c) -o $@ $<
 	$(POST_PROCESS_O)
 
+pics/%.o := CPPFLAGS += -I$(ROOTSMBHDRDIR)/ndl
+
 .KEEP_STATE:
 
 all: $(LIBS)
--- old/usr/src/lib/smbsrv/libmlrpc/Makefile	Sun Mar 18 01:13:18 2018
+++ /dev/null	Sun Mar 18 01:13:17 2018
@@ -1,30 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-HDRS=	libmlrpc.h
-
-include ../Makefile.smbsrv
--- old/usr/src/lib/smbsrv/libmlrpc/Makefile.com	Sun Mar 18 01:13:18 2018
+++ /dev/null	Sun Mar 18 01:13:17 2018
@@ -1,56 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-
-LIBRARY =	libmlrpc.a
-VERS =		.1
-
-OBJS_COMMON = 			\
-	ndr_client.o		\
-	ndr_heap.o		\
-	ndr_marshal.o		\
-	ndr_ops.o		\
-	ndr_process.o		\
-	ndr_server.o		\
-	ndr_svc.o
-
-NDLLIST = rpcpdu
-
-OBJECTS=	$(OBJS_COMMON) $(OBJS_SHARED) $(NDLLIST:%=%_ndr.o)
-
-include ../../../Makefile.lib
-include ../../Makefile.lib
-
-INCS += -I$(SRC)/common/smbsrv
-
-LDLIBS +=	$(MACH_LDLIBS)
-LDLIBS +=	-lsmb -luuid -lc
-
-CPPFLAGS += $(INCS) -D_REENTRANT
-
-SRCS=   $(OBJS_COMMON:%.o=$(SRCDIR)/%.c)		\
-	$(OBJS_SHARED:%.o=$(SRC)/common/smbsrv/%.c)
-
-include ../../Makefile.targ
-include ../../../Makefile.targ
--- old/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers	Sun Mar 18 01:13:18 2018
+++ /dev/null	Sun Mar 18 01:13:17 2018
@@ -1,88 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
-#
-#
-
-#
-# MAPFILE HEADER START
-#
-# WARNING:  STOP NOW.  DO NOT MODIFY THIS FILE.
-# Object versioning must comply with the rules detailed in
-#
-#	usr/src/lib/README.mapfiles
-#
-# You should not be making modifications here until you've read the most current
-# copy of that file. If you need help, contact a gatekeeper for guidance.
-#
-# MAPFILE HEADER END
-#
-
-$mapfile_version 2
-
-SYMBOL_VERSION SUNWprivate {
-    global:
-        ndr_buf_decode;
-        ndr_buf_fini;
-        ndr_buf_init;
-        ndr_clnt_bind;
-        ndr_clnt_call;
-        ndr_clnt_free_heap;
-	ndr_generic_call_stub;
-        ndr_heap_avail;
-        ndr_heap_create;
-        ndr_heap_destroy;
-        ndr_heap_malloc;
-        ndr_heap_mkvcb;
-        ndr_heap_mkvcs;
-	ndr_heap_mstring;
-	ndr_heap_siddup;
-        ndr_heap_strdup;
-        ndr_heap_used;
-	ndr_hdalloc;
-	ndr_hdfree;
-	ndr_hdlookup;
-        ndr_inner;
-	ndr_is_admin;
-	ndr_is_poweruser;
-	ndr_mbstowcs;
-	ndr_mbtowc;
-	ndr_native_os;
-        ndr_params;
-	ndr_pipe_worker;
-        ndr_svc_binding_pool_init;
-	ndr_svc_lookup_name;
-        ndr_svc_register;
-        ndr_topmost;
-	ndr_uuid_parse;
-	ndr_uuid_unparse;
-        nds_destruct;
-        nds_initialize;
-        ndt__char;
-        ndt_s_wchar;
-        ndt__uchar;
-        ndt__ulong;
-        ndt__ushort;
-    local:
-	*;
-};
--- old/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c	Sun Mar 18 01:13:18 2018
+++ new/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c	Sun Mar 18 01:13:18 2018
@@ -29,7 +29,7 @@
 
 #include <string.h>
 #include <strings.h>
-#include <smbsrv/wintypes.h>
+#include <smb/wintypes.h>
 #include <smbsrv/libsmb.h>
 #include <smbsrv/ndl/dssetup.ndl>
 #include <smbsrv/libmlsvc.h>
--- old/usr/src/lib/smbsrv/libmlsvc/common/dssetup_svc.c	Sun Mar 18 01:13:19 2018
+++ new/usr/src/lib/smbsrv/libmlsvc/common/dssetup_svc.c	Sun Mar 18 01:13:19 2018
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -32,8 +33,8 @@
 #include <stdlib.h>
 #include <netdb.h>
 
+#include <libmlrpc/libmlrpc.h>
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libmlrpc.h>
 #include <smbsrv/libmlsvc.h>
 #include <smbsrv/ndl/dssetup.ndl>
 #include <smbsrv/smbinfo.h>
--- old/usr/src/lib/smbsrv/libmlsvc/common/eventlog_svc.c	Sun Mar 18 01:13:19 2018
+++ new/usr/src/lib/smbsrv/libmlsvc/common/eventlog_svc.c	Sun Mar 18 01:13:19 2018
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -29,8 +30,8 @@
 #include <sys/utsname.h>
 #include <unistd.h>
 #include <strings.h>
+#include <libmlrpc/libmlrpc.h>
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libmlrpc.h>
 #include <smbsrv/nmpipes.h>
 #include <smbsrv/libmlsvc.h>
 #include <smbsrv/ndl/eventlog.ndl>
--- old/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h	Sun Mar 18 01:13:19 2018
+++ new/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h	Sun Mar 18 01:13:19 2018
@@ -26,17 +26,22 @@
 #ifndef	_LIBMLSVC_H
 #define	_LIBMLSVC_H
 
-#include <uuid/uuid.h>
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/uio.h>
 #include <sys/ksynch.h>
+#include <uuid/uuid.h>
+
 #include <time.h>
 #include <stdio.h>
 #include <string.h>
+#include <syslog.h>
 #include <netdb.h>
 #include <libuutil.h>
-#include <smbsrv/wintypes.h>
+
+#include <smb/wintypes.h>
+#include <libmlrpc/libmlrpc.h>
+
 #include <smbsrv/hash_table.h>
 #include <smbsrv/smb_token.h>
 #include <smbsrv/smb_privilege.h>
@@ -44,8 +49,6 @@
 #include <smbsrv/smb_xdr.h>
 #include <smbsrv/smb_dfs.h>
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libmlrpc.h>
-#include <smbsrv/ndl/lsarpc.ndl>
 
 #ifdef	__cplusplus
 extern "C" {
@@ -128,24 +131,6 @@
 } ms_luid_t;
 
 /*
- * Information about a server as reported by NetServerGetInfo.
- * The SV_PLATFORM and SV_TYPE definitions are in srvsvc.ndl.
- */
-typedef struct srvsvc_server_info {
-	uint32_t	sv_platform_id;
-	char		*sv_name;
-	uint32_t	sv_version_major;
-	uint32_t	sv_version_minor;
-	uint32_t	sv_type;
-	char		*sv_comment;
-	uint32_t	sv_os;
-} srvsvc_server_info_t;
-
-int srvsvc_net_server_getinfo(char *, char *, srvsvc_server_info_t *);
-int srvsvc_net_remote_tod(char *, char *, struct timeval *, struct tm *);
-
-
-/*
  * A client_t is created while binding a client connection to hold the
  * context for calls made using that connection.
  *
@@ -153,29 +138,23 @@
  * ensure that each handle has a pointer to the client_t.  When the top
  * level (bind) handle is released, we close the connection.
  */
-typedef struct mlsvc_handle {
-	ndr_hdid_t			handle;
-	ndr_client_t			*clnt;
-	srvsvc_server_info_t		svinfo;
-} mlsvc_handle_t;
+typedef struct mlrpc_handle mlsvc_handle_t;
 
+/* mlsvc_client.c */
 void ndr_rpc_init(void);
 void ndr_rpc_fini(void);
 uint32_t ndr_rpc_bind(mlsvc_handle_t *, char *, char *, char *, const char *);
 void ndr_rpc_unbind(mlsvc_handle_t *);
-int ndr_rpc_call(mlsvc_handle_t *, int, void *);
-void ndr_rpc_set_nonull(mlsvc_handle_t *);
-const srvsvc_server_info_t *ndr_rpc_server_info(mlsvc_handle_t *);
-uint32_t ndr_rpc_server_os(mlsvc_handle_t *);
-int ndr_rpc_get_ssnkey(mlsvc_handle_t *, unsigned char *, size_t);
-void *ndr_rpc_malloc(mlsvc_handle_t *, size_t);
-ndr_heap_t *ndr_rpc_get_heap(mlsvc_handle_t *);
-void ndr_rpc_release(mlsvc_handle_t *);
-boolean_t ndr_is_null_handle(mlsvc_handle_t *);
-boolean_t ndr_is_bind_handle(mlsvc_handle_t *);
-void ndr_inherit_handle(mlsvc_handle_t *, mlsvc_handle_t *);
 void ndr_rpc_status(mlsvc_handle_t *, int, uint32_t);
 
+/* These three get info about the connected client. */
+boolean_t ndr_is_admin(ndr_xa_t *);
+boolean_t ndr_is_poweruser(ndr_xa_t *);
+int32_t ndr_native_os(ndr_xa_t *);
+
+/* SRVSVC */
+int srvsvc_net_remote_tod(char *, char *, struct timeval *, struct tm *);
+
 /* SVCCTL service */
 /*
  * Calculate the wide-char equivalent string length required to
--- old/usr/src/lib/smbsrv/libmlsvc/common/lsar_clnt.c	Sun Mar 18 01:13:19 2018
+++ new/usr/src/lib/smbsrv/libmlsvc/common/lsar_clnt.c	Sun Mar 18 01:13:19 2018
@@ -383,7 +383,6 @@
 		lsar_lookup_names1
 	};
 
-	const srvsvc_server_info_t	*svinfo;
 	lsa_names_t	names;
 	char		*p;
 	uint32_t	length;
@@ -396,20 +395,15 @@
 
 	bzero(info, sizeof (smb_account_t));
 
-	svinfo = ndr_rpc_server_info(lsa_handle);
-	if (svinfo->sv_os == NATIVE_OS_WIN2000 &&
-	    svinfo->sv_version_major == 5 && svinfo->sv_version_minor == 0) {
-		/*
-		 * Windows 2000 doesn't like an LSA lookup for
-		 * DOMAIN\Administrator.
-		 */
-		if ((p = strchr(name, '\\')) != 0) {
-			++p;
+	/*
+	 * Windows 2000 (or later) doesn't like an LSA lookup for
+	 * DOMAIN\Administrator.
+	 */
+	if ((p = strchr(name, '\\')) != 0) {
+		++p;
 
-			if (strcasecmp(p, "administrator") == 0)
-				name = p;
-		}
-
+		if (strcasecmp(p, "administrator") == 0)
+			name = p;
 	}
 
 	length = smb_wcequiv_strlen(name);
@@ -418,17 +412,12 @@
 	names.name[0].str = (unsigned char *)name;
 	names.n_entry = 1;
 
-	if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) {
-		for (i = 0; i < n_op; ++i) {
-			ndr_rpc_set_nonull(lsa_handle);
-			status = (*ops[i])(lsa_handle, &names, info);
-
-			if (status != NT_STATUS_INVALID_PARAMETER)
-				break;
-		}
-	} else {
+	for (i = 0; i < n_op; ++i) {
 		ndr_rpc_set_nonull(lsa_handle);
-		status = lsar_lookup_names1(lsa_handle, &names, info);
+		status = (*ops[i])(lsa_handle, &names, info);
+
+		if (status != NT_STATUS_INVALID_PARAMETER)
+			break;
 	}
 
 	if (status == NT_STATUS_SUCCESS) {
@@ -726,10 +715,8 @@
 	smb_sid_tostr(sid, sidbuf);
 	smb_tracef("%s", sidbuf);
 
-	if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000)
-		status = lsar_lookup_sids2(lsa_handle, (lsa_sid_t *)sid,
-		    account);
-	else
+	status = lsar_lookup_sids2(lsa_handle, (lsa_sid_t *)sid, account);
+	if (status == RPC_NT_PROCNUM_OUT_OF_RANGE)
 		status = lsar_lookup_sids1(lsa_handle, (lsa_sid_t *)sid,
 		    account);
 
@@ -1167,8 +1154,7 @@
 	(void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
 
 	length = smb_wcequiv_strlen(name);
-	if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000)
-		length += sizeof (smb_wchar_t);
+	length += sizeof (smb_wchar_t);
 
 	arg.name.length = length;
 	arg.name.allosize = length;
--- old/usr/src/lib/smbsrv/libmlsvc/common/lsar_svc.c	Sun Mar 18 01:13:19 2018
+++ new/usr/src/lib/smbsrv/libmlsvc/common/lsar_svc.c	Sun Mar 18 01:13:19 2018
@@ -33,8 +33,8 @@
 #include <pwd.h>
 #include <grp.h>
 
+#include <libmlrpc/libmlrpc.h>
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libmlrpc.h>
 #include <smbsrv/libmlsvc.h>
 #include <smbsrv/ndl/lsarpc.ndl>
 #include <lsalib.h>
--- old/usr/src/lib/smbsrv/libmlsvc/common/mlsvc.h	Sun Mar 18 01:13:19 2018
+++ new/usr/src/lib/smbsrv/libmlsvc/common/mlsvc.h	Sun Mar 18 01:13:19 2018
@@ -46,7 +46,6 @@
 void samr_initialize(void);
 void svcctl_initialize(void);
 void winreg_initialize(void);
-int srvsvc_gettime(unsigned long *);
 void msgsvcsend_initialize(void);
 void spoolss_initialize(void);
 void netdfs_initialize(void);
@@ -64,7 +63,8 @@
     struct netr_authenticator *);
 DWORD netr_validate_chain(struct netr_info *, struct netr_authenticator *);
 
-void ndr_srvsvc_timecheck(char *, char *);
+int srvsvc_gettime(unsigned long *);
+void srvsvc_timecheck(char *, char *);
 
 /* Generic functions to get/set windows Security Descriptors */
 uint32_t srvsvc_sd_get(smb_share_t *, uint8_t *, uint32_t *);
--- old/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c	Sun Mar 18 01:13:19 2018
+++ new/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c	Sun Mar 18 01:13:19 2018
@@ -31,33 +31,23 @@
 #include <sys/types.h>
 #include <sys/errno.h>
 #include <sys/fcntl.h>
-#include <sys/tzfile.h>
 #include <time.h>
 #include <strings.h>
 #include <assert.h>
 #include <errno.h>
 #include <thread.h>
-#include <unistd.h>
 #include <syslog.h>
 #include <synch.h>
 
+#include <libmlrpc/libmlrpc.h>
 #include <netsmb/smbfs_api.h>
+
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libsmbns.h>
-#include <smbsrv/libmlrpc.h>
 #include <smbsrv/libmlsvc.h>
-#include <smbsrv/ndl/srvsvc.ndl>
 #include <libsmbrdr.h>
 #include <mlsvc.h>
 
-static int ndr_xa_init(ndr_client_t *, ndr_xa_t *);
-static int ndr_xa_exchange(ndr_client_t *, ndr_xa_t *);
-static int ndr_xa_read(ndr_client_t *, ndr_xa_t *);
-static void ndr_xa_preserve(ndr_client_t *, ndr_xa_t *);
-static void ndr_xa_destruct(ndr_client_t *, ndr_xa_t *);
-static void ndr_xa_release(ndr_client_t *);
 
-
 /*
  * This call must be made to initialize an RPC client structure and bind
  * to the remote service before any RPCs can be exchanged with that service.
@@ -71,13 +61,15 @@
  * unbind and teardown the connection.  As each handle is initialized it
  * will inherit a reference to the client context.
  *
- * Returns 0 or an NT_STATUS:
+ * Returns 0 or an NT_STATUS:		(failed in...)
+ *
  *	NT_STATUS_BAD_NETWORK_PATH	(get server addr)
  *	NT_STATUS_NETWORK_ACCESS_DENIED	(connect, auth)
- *	NT_STATUS_BAD_NETWORK_NAME	(tcon, open)
+ *	NT_STATUS_BAD_NETWORK_NAME	(tcon)
+ *	RPC_NT_SERVER_TOO_BUSY		(open pipe)
+ *	RPC_NT_SERVER_UNAVAILABLE	(open pipe)
  *	NT_STATUS_ACCESS_DENIED		(open pipe)
  *	NT_STATUS_INVALID_PARAMETER	(rpc bind)
- *
  *	NT_STATUS_INTERNAL_ERROR	(bad args etc)
  *	NT_STATUS_NO_MEMORY
  */
@@ -86,11 +78,8 @@
     char *username, const char *service)
 {
 	struct smb_ctx		*ctx = NULL;
-	ndr_client_t		*clnt = NULL;
 	ndr_service_t		*svc;
-	srvsvc_server_info_t	svinfo;
 	DWORD			status;
-	int			fd = -1;
 	int			rc;
 
 	if (handle == NULL || server == NULL || server[0] == '\0' ||
@@ -102,19 +91,6 @@
 		return (NT_STATUS_INTERNAL_ERROR);
 
 	/*
-	 * Set the default based on the assumption that most
-	 * servers will be Windows 2000 or later.  This used to
-	 * try to get the actual server version, but that RPC
-	 * is not necessarily allowed anymore, so don't bother.
-	 */
-	bzero(&svinfo, sizeof (srvsvc_server_info_t));
-	svinfo.sv_platform_id = SV_PLATFORM_ID_NT;
-	svinfo.sv_version_major = 5;
-	svinfo.sv_version_minor = 0;
-	svinfo.sv_type = SV_TYPE_DEFAULT;
-	svinfo.sv_os = NATIVE_OS_WIN2000;
-
-	/*
 	 * Some callers pass this when they want a NULL session.
 	 * Todo: have callers pass an empty string for that.
 	 */
@@ -136,297 +112,83 @@
 		    "(Srv=%s Dom=%s User=%s), %s (0x%x)",
 		    server, domain, username,
 		    xlate_nt_status(status), status);
-		/* Tell the DC Locator this DC failed. */
-		smb_ddiscover_bad_dc(server);
-		goto errout;
-	}
-
-	/*
-	 * Open the named pipe.
-	 */
-	fd = smb_fh_open(ctx, svc->endpoint, O_RDWR);
-	if (fd < 0) {
-		rc = errno;
-		syslog(LOG_DEBUG, "ndr_rpc_bind: "
-		    "smb_fh_open (%s) err=%d",
-		    svc->endpoint, rc);
-		switch (rc) {
-		case EACCES:
-			status = NT_STATUS_ACCESS_DENIED;
-			break;
+		/*
+		 * If the error is one where changing to a new DC
+		 * might help, try looking for a different DC.
+		 */
+		switch (status) {
+		case NT_STATUS_BAD_NETWORK_PATH:
+		case NT_STATUS_BAD_NETWORK_NAME:
+			/* Look for a new DC */
+			smb_ddiscover_bad_dc(server);
 		default:
-			status = NT_STATUS_BAD_NETWORK_NAME;
 			break;
 		}
-		goto errout;
+		return (status);
 	}
 
 	/*
 	 * Setup the RPC client handle.
 	 */
-	if ((clnt = malloc(sizeof (ndr_client_t))) == NULL) {
-		status = NT_STATUS_NO_MEMORY;
-		goto errout;
+	rc = mlrpc_clh_create(handle, ctx);
+	if (rc != 0) {
+		syslog(LOG_ERR, "ndr_rpc_bind: mlrpc_clh_create: rc=%d", rc);
+		smbrdr_ctx_free(ctx);
+		switch (rc) {
+		case ENOMEM:
+			return (NT_STATUS_NO_MEMORY);
+		case EINVAL:
+			return (NT_STATUS_INVALID_PARAMETER);
+		default:
+			return (NT_STATUS_INTERNAL_ERROR);
+		}
 	}
-	bzero(clnt, sizeof (ndr_client_t));
 
-	clnt->handle = &handle->handle;
-	clnt->xa_init = ndr_xa_init;
-	clnt->xa_exchange = ndr_xa_exchange;
-	clnt->xa_read = ndr_xa_read;
-	clnt->xa_preserve = ndr_xa_preserve;
-	clnt->xa_destruct = ndr_xa_destruct;
-	clnt->xa_release = ndr_xa_release;
-	clnt->xa_private = ctx;
-	clnt->xa_fd = fd;
-
-	ndr_svc_binding_pool_init(&clnt->binding_list,
-	    clnt->binding_pool, NDR_N_BINDING_POOL);
-
-	if ((clnt->heap = ndr_heap_create()) == NULL) {
-		status = NT_STATUS_NO_MEMORY;
-		goto errout;
-	}
-
 	/*
-	 * Fill in the caller's handle.
+	 * This does the pipe open and OtW RPC bind.
+	 * Handles pipe open retries.
 	 */
-	bzero(&handle->handle, sizeof (ndr_hdid_t));
-	handle->clnt = clnt;
-	bcopy(&svinfo, &handle->svinfo, sizeof (srvsvc_server_info_t));
-
-	/*
-	 * Do the OtW RPC bind.
-	 */
-	rc = ndr_clnt_bind(clnt, service, &clnt->binding);
-	switch (rc) {
-	case NDR_DRC_FAULT_OUT_OF_MEMORY:
-		status = NT_STATUS_NO_MEMORY;
-		break;
-	case NDR_DRC_FAULT_API_SERVICE_INVALID:	/* not registered */
-		status = NT_STATUS_INTERNAL_ERROR;
-		break;
-	default:
-		if (NDR_DRC_IS_FAULT(rc)) {
-			status = NT_STATUS_INVALID_PARAMETER;
+	status = mlrpc_clh_bind(handle, svc);
+	if (status != 0) {
+		syslog(LOG_DEBUG, "ndr_rpc_bind: "
+		    "mlrpc_clh_bind, %s (0x%x)",
+		    xlate_nt_status(status), status);
+		switch (status) {
+		case RPC_NT_SERVER_TOO_BUSY:
+			/* Look for a new DC */
+			smb_ddiscover_bad_dc(server);
 			break;
+		default:
+			break;
 		}
-		/* FALLTHROUGH */
-	case NDR_DRC_OK:
-		return (NT_STATUS_SUCCESS);
+		ctx = mlrpc_clh_free(handle);
+		if (ctx != NULL) {
+			smbrdr_ctx_free(ctx);
+		}
 	}
 
-	syslog(LOG_DEBUG, "ndr_rpc_bind: "
-	    "ndr_clnt_bind, %s (0x%x)",
-	    xlate_nt_status(status), status);
-
-errout:
-	handle->clnt = NULL;
-	if (clnt != NULL) {
-		ndr_heap_destroy(clnt->heap);
-		free(clnt);
-	}
-	if (ctx != NULL) {
-		if (fd != -1)
-			(void) smb_fh_close(fd);
-		smbrdr_ctx_free(ctx);
-	}
-
 	return (status);
 }
 
 /*
- * Unbind and close the pipe to an RPC service.
+ * Unbind and close the pipe to an RPC service
+ * and cleanup the smb_ctx.
  *
- * If the heap has been preserved we need to go through an xa release.
- * The heap is preserved during an RPC call because that's where data
- * returned from the server is stored.
- *
- * Otherwise we destroy the heap directly.
+ * The heap may or may not be destroyed (see mlrpc_clh_free)
  */
 void
 ndr_rpc_unbind(mlsvc_handle_t *handle)
 {
-	ndr_client_t *clnt = handle->clnt;
-	struct smb_ctx *ctx = clnt->xa_private;
+	struct smb_ctx *ctx;
 
-	if (clnt->heap_preserved)
-		ndr_clnt_free_heap(clnt);
-	else
-		ndr_heap_destroy(clnt->heap);
+	ctx = mlrpc_clh_free(handle);
+	if (ctx != NULL)
+		smbrdr_ctx_free(ctx);
 
-	(void) smb_fh_close(clnt->xa_fd);
-	smbrdr_ctx_free(ctx);
-	free(clnt);
 	bzero(handle, sizeof (mlsvc_handle_t));
 }
 
-/*
- * Call the RPC function identified by opnum.  The remote service is
- * identified by the handle, which should have been initialized by
- * ndr_rpc_bind.
- *
- * If the RPC call is successful (returns 0), the caller must call
- * ndr_rpc_release to release the heap.  Otherwise, we release the
- * heap here.
- */
-int
-ndr_rpc_call(mlsvc_handle_t *handle, int opnum, void *params)
-{
-	ndr_client_t *clnt = handle->clnt;
-	int rc;
-
-	if (ndr_rpc_get_heap(handle) == NULL)
-		return (-1);
-
-	rc = ndr_clnt_call(clnt->binding, opnum, params);
-
-	/*
-	 * Always clear the nonull flag to ensure
-	 * it is not applied to subsequent calls.
-	 */
-	clnt->nonull = B_FALSE;
-
-	if (NDR_DRC_IS_FAULT(rc)) {
-		ndr_rpc_release(handle);
-		return (-1);
-	}
-
-	return (0);
-}
-
-/*
- * Outgoing strings should not be null terminated.
- */
 void
-ndr_rpc_set_nonull(mlsvc_handle_t *handle)
-{
-	handle->clnt->nonull = B_TRUE;
-}
-
-/*
- * Return a reference to the server info.
- */
-const srvsvc_server_info_t *
-ndr_rpc_server_info(mlsvc_handle_t *handle)
-{
-	return (&handle->svinfo);
-}
-
-/*
- * Return the RPC server OS level.
- */
-uint32_t
-ndr_rpc_server_os(mlsvc_handle_t *handle)
-{
-	return (handle->svinfo.sv_os);
-}
-
-/*
- * Get the session key from a bound RPC client handle.
- *
- * The key returned is the 16-byte "user session key"
- * established by the underlying authentication protocol
- * (either Kerberos or NTLM).  This key is needed for
- * SAM RPC calls such as SamrSetInformationUser, etc.
- * See [MS-SAMR] sections: 2.2.3.3, 2.2.7.21, 2.2.7.25.
- *
- * Returns zero (success) or an errno.
- */
-int
-ndr_rpc_get_ssnkey(mlsvc_handle_t *handle,
-	unsigned char *ssn_key, size_t len)
-{
-	ndr_client_t *clnt = handle->clnt;
-	int rc;
-
-	if (clnt == NULL)
-		return (EINVAL);
-
-	rc = smb_fh_getssnkey(clnt->xa_fd, ssn_key, len);
-	return (rc);
-}
-
-void *
-ndr_rpc_malloc(mlsvc_handle_t *handle, size_t size)
-{
-	ndr_heap_t *heap;
-
-	if ((heap = ndr_rpc_get_heap(handle)) == NULL)
-		return (NULL);
-
-	return (ndr_heap_malloc(heap, size));
-}
-
-ndr_heap_t *
-ndr_rpc_get_heap(mlsvc_handle_t *handle)
-{
-	ndr_client_t *clnt = handle->clnt;
-
-	if (clnt->heap == NULL)
-		clnt->heap = ndr_heap_create();
-
-	return (clnt->heap);
-}
-
-/*
- * Must be called by RPC clients to free the heap after a successful RPC
- * call, i.e. ndr_rpc_call returned 0.  The caller should take a copy
- * of any data returned by the RPC prior to calling this function because
- * returned data is in the heap.
- */
-void
-ndr_rpc_release(mlsvc_handle_t *handle)
-{
-	ndr_client_t *clnt = handle->clnt;
-
-	if (clnt->heap_preserved)
-		ndr_clnt_free_heap(clnt);
-	else
-		ndr_heap_destroy(clnt->heap);
-
-	clnt->heap = NULL;
-}
-
-/*
- * Returns true if the handle is null.
- * Otherwise returns false.
- */
-boolean_t
-ndr_is_null_handle(mlsvc_handle_t *handle)
-{
-	static ndr_hdid_t zero_handle;
-
-	if (handle == NULL || handle->clnt == NULL)
-		return (B_TRUE);
-
-	if (!memcmp(&handle->handle, &zero_handle, sizeof (ndr_hdid_t)))
-		return (B_TRUE);
-
-	return (B_FALSE);
-}
-
-/*
- * Returns true if the handle is the top level bind handle.
- * Otherwise returns false.
- */
-boolean_t
-ndr_is_bind_handle(mlsvc_handle_t *handle)
-{
-	return (handle->clnt->handle == &handle->handle);
-}
-
-/*
- * Pass the client reference from parent to child.
- */
-void
-ndr_inherit_handle(mlsvc_handle_t *child, mlsvc_handle_t *parent)
-{
-	child->clnt = parent->clnt;
-	bcopy(&parent->svinfo, &child->svinfo, sizeof (srvsvc_server_info_t));
-}
-
-void
 ndr_rpc_status(mlsvc_handle_t *handle, int opnum, DWORD status)
 {
 	ndr_service_t *svc;
@@ -455,194 +217,4 @@
 
 	smb_tracef("%s[0x%02x]: %s: %s (0x%08x)",
 	    name, opnum, s, xlate_nt_status(status), status);
-}
-
-/*
- * The following functions provide the client callback interface.
- * If the caller hasn't provided a heap, create one here.
- */
-static int
-ndr_xa_init(ndr_client_t *clnt, ndr_xa_t *mxa)
-{
-	ndr_stream_t	*recv_nds = &mxa->recv_nds;
-	ndr_stream_t	*send_nds = &mxa->send_nds;
-	ndr_heap_t	*heap = clnt->heap;
-	int		rc;
-
-	if (heap == NULL) {
-		if ((heap = ndr_heap_create()) == NULL)
-			return (-1);
-
-		clnt->heap = heap;
-	}
-
-	mxa->heap = heap;
-
-	rc = nds_initialize(send_nds, 0, NDR_MODE_CALL_SEND, heap);
-	if (rc == 0)
-		rc = nds_initialize(recv_nds, NDR_PDU_SIZE_HINT_DEFAULT,
-		    NDR_MODE_RETURN_RECV, heap);
-
-	if (rc != 0) {
-		nds_destruct(&mxa->recv_nds);
-		nds_destruct(&mxa->send_nds);
-		ndr_heap_destroy(mxa->heap);
-		mxa->heap = NULL;
-		clnt->heap = NULL;
-		return (-1);
-	}
-
-	if (clnt->nonull)
-		NDS_SETF(send_nds, NDS_F_NONULL);
-
-	return (0);
-}
-
-/*
- * This is the entry pointy for an RPC client call exchange with
- * a server, which will result in an smbrdr SmbTransact request.
- *
- * SmbTransact should return the number of bytes received, which
- * we record as the PDU size, or a negative error code.
- */
-static int
-ndr_xa_exchange(ndr_client_t *clnt, ndr_xa_t *mxa)
-{
-	ndr_stream_t *recv_nds = &mxa->recv_nds;
-	ndr_stream_t *send_nds = &mxa->send_nds;
-	int err, more, nbytes;
-
-	nbytes = recv_nds->pdu_max_size;
-	err = smb_fh_xactnp(clnt->xa_fd,
-	    send_nds->pdu_size, (char *)send_nds->pdu_base_offset,
-	    &nbytes, (char *)recv_nds->pdu_base_offset, &more);
-	if (err) {
-		recv_nds->pdu_size = 0;
-		return (-1);
-	}
-
-	recv_nds->pdu_size = nbytes;
-	return (0);
-}
-
-/*
- * This entry point will be invoked if the xa-exchange response contained
- * only the first fragment of a multi-fragment response.  The RPC client
- * code will then make repeated xa-read requests to obtain the remaining
- * fragments, which will result in smbrdr SmbReadX requests.
- *
- * SmbReadX should return the number of bytes received, in which case we
- * expand the PDU size to include the received data, or a negative error
- * code.
- */
-static int
-ndr_xa_read(ndr_client_t *clnt, ndr_xa_t *mxa)
-{
-	ndr_stream_t *nds = &mxa->recv_nds;
-	int len;
-	int nbytes;
-
-	if ((len = (nds->pdu_max_size - nds->pdu_size)) < 0)
-		return (-1);
-
-	nbytes = smb_fh_read(clnt->xa_fd, 0, len,
-	    (char *)nds->pdu_base_offset + nds->pdu_size);
-
-	if (nbytes < 0)
-		return (-1);
-
-	nds->pdu_size += nbytes;
-
-	if (nds->pdu_size > nds->pdu_max_size) {
-		nds->pdu_size = nds->pdu_max_size;
-		return (-1);
-	}
-
-	return (nbytes);
-}
-
-/*
- * Preserve the heap so that the client application has access to data
- * returned from the server after an RPC call.
- */
-static void
-ndr_xa_preserve(ndr_client_t *clnt, ndr_xa_t *mxa)
-{
-	assert(clnt->heap == mxa->heap);
-
-	clnt->heap_preserved = B_TRUE;
-	mxa->heap = NULL;
-}
-
-/*
- * Dispose of the transaction streams.  If the heap has not been
- * preserved, we can destroy it here.
- */
-static void
-ndr_xa_destruct(ndr_client_t *clnt, ndr_xa_t *mxa)
-{
-	nds_destruct(&mxa->recv_nds);
-	nds_destruct(&mxa->send_nds);
-
-	if (!clnt->heap_preserved) {
-		ndr_heap_destroy(mxa->heap);
-		mxa->heap = NULL;
-		clnt->heap = NULL;
-	}
-}
-
-/*
- * Dispose of a preserved heap.
- */
-static void
-ndr_xa_release(ndr_client_t *clnt)
-{
-	if (clnt->heap_preserved) {
-		ndr_heap_destroy(clnt->heap);
-		clnt->heap = NULL;
-		clnt->heap_preserved = B_FALSE;
-	}
-}
-
-
-/*
- * Compare the time here with the remote time on the server
- * and report clock skew.
- */
-void
-ndr_srvsvc_timecheck(char *server, char *domain)
-{
-	char			hostname[MAXHOSTNAMELEN];
-	struct timeval		dc_tv;
-	struct tm		dc_tm;
-	struct tm		*tm;
-	time_t			tnow;
-	time_t			tdiff;
-	int			priority;
-
-	if (srvsvc_net_remote_tod(server, domain, &dc_tv, &dc_tm) < 0) {
-		syslog(LOG_DEBUG, "srvsvc_net_remote_tod failed");
-		return;
-	}
-
-	tnow = time(NULL);
-
-	if (tnow > dc_tv.tv_sec)
-		tdiff = (tnow - dc_tv.tv_sec) / SECSPERMIN;
-	else
-		tdiff = (dc_tv.tv_sec - tnow) / SECSPERMIN;
-
-	if (tdiff != 0) {
-		(void) strlcpy(hostname, "localhost", MAXHOSTNAMELEN);
-		(void) gethostname(hostname, MAXHOSTNAMELEN);
-
-		priority = (tdiff > 2) ? LOG_NOTICE : LOG_DEBUG;
-		syslog(priority, "DC [%s] clock skew detected: %u minutes",
-		    server, tdiff);
-
-		tm = gmtime(&dc_tv.tv_sec);
-		syslog(priority, "%-8s  UTC: %s", server, asctime(tm));
-		tm = gmtime(&tnow);
-		syslog(priority, "%-8s  UTC: %s", hostname, asctime(tm));
-	}
 }
--- old/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c	Sun Mar 18 01:13:19 2018
+++ new/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c	Sun Mar 18 01:13:19 2018
@@ -111,7 +111,7 @@
 		if (!smb_domain_getinfo(&di))
 			continue;
 
-		ndr_srvsvc_timecheck(di.d_dci.dc_name,
+		srvsvc_timecheck(di.d_dci.dc_name,
 		    di.d_primary.di_nbname);
 	}
 
--- old/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c	Sun Mar 18 01:13:20 2018
+++ new/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c	Sun Mar 18 01:13:20 2018
@@ -425,3 +425,43 @@
 {
 	smbrdr_disconnect(server);
 }
+
+/*
+ * A few more helper functions for RPC services.
+ */
+
+/*
+ * Check whether or not the specified user has administrator privileges,
+ * i.e. is a member of Domain Admins or Administrators.
+ * Returns true if the user is an administrator, otherwise returns false.
+ */
+boolean_t
+ndr_is_admin(ndr_xa_t *xa)
+{
+	smb_netuserinfo_t *ctx = xa->pipe->np_user;
+
+	return (ctx->ui_flags & SMB_ATF_ADMIN);
+}
+
+/*
+ * Check whether or not the specified user has power-user privileges,
+ * i.e. is a member of Domain Admins, Administrators or Power Users.
+ * This is typically required for operations such as managing shares.
+ * Returns true if the user is a power user, otherwise returns false.
+ */
+boolean_t
+ndr_is_poweruser(ndr_xa_t *xa)
+{
+	smb_netuserinfo_t *ctx = xa->pipe->np_user;
+
+	return ((ctx->ui_flags & SMB_ATF_ADMIN) ||
+	    (ctx->ui_flags & SMB_ATF_POWERUSER));
+}
+
+int32_t
+ndr_native_os(ndr_xa_t *xa)
+{
+	smb_netuserinfo_t *ctx = xa->pipe->np_user;
+
+	return (ctx->ui_native_os);
+}
--- old/usr/src/lib/smbsrv/libmlsvc/common/msgsvc_svc.c	Sun Mar 18 01:13:20 2018
+++ new/usr/src/lib/smbsrv/libmlsvc/common/msgsvc_svc.c	Sun Mar 18 01:13:20 2018
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -30,8 +31,8 @@
 #include <syslog.h>
 #include <stdlib.h>
 
+#include <libmlrpc/libmlrpc.h>
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libmlrpc.h>
 #include <smbsrv/libmlsvc.h>
 #include <smbsrv/ndl/msgsvc.ndl>
 #include <smbsrv/smbinfo.h>
--- old/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c	Sun Mar 18 01:13:20 2018
+++ new/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c	Sun Mar 18 01:13:20 2018
@@ -191,6 +191,10 @@
 	return (0);
 }
 
+uint32_t netr_server_auth2_flags =
+    NETR_NEGOTIATE_BASE_FLAGS |
+    NETR_NEGOTIATE_STRONGKEY_FLAG;
+
 /*
  * netr_server_authenticate2
  */
@@ -216,10 +220,9 @@
 	arg.account_name = (unsigned char *)account_name;
 	arg.account_type = NETR_WKSTA_TRUST_ACCOUNT_TYPE;
 	arg.hostname = (unsigned char *)netr_info->hostname;
-	arg.negotiate_flags = NETR_NEGOTIATE_BASE_FLAGS;
+	arg.negotiate_flags = netr_server_auth2_flags;
 
-	if (ndr_rpc_server_os(netr_handle) == NATIVE_OS_WIN2000) {
-		arg.negotiate_flags |= NETR_NEGOTIATE_STRONGKEY_FLAG;
+	if (arg.negotiate_flags & NETR_NEGOTIATE_STRONGKEY_FLAG) {
 		if (netr_gen_skey128(netr_info) != SMBAUTH_SUCCESS)
 			return (-1);
 	} else {
--- old/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c	Sun Mar 18 01:13:20 2018
+++ new/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c	Sun Mar 18 01:13:20 2018
@@ -37,8 +37,8 @@
 #include <netdb.h>
 #include <thread.h>
 
+#include <libmlrpc/libmlrpc.h>
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libmlrpc.h>
 #include <smbsrv/libmlsvc.h>
 #include <smbsrv/ndl/netlogon.ndl>
 #include <smbsrv/netrauth.h>
--- old/usr/src/lib/smbsrv/libmlsvc/common/samr_clnt.c	Sun Mar 18 01:13:20 2018
+++ new/usr/src/lib/smbsrv/libmlsvc/common/samr_clnt.c	Sun Mar 18 01:13:20 2018
@@ -44,8 +44,8 @@
 #include <netdb.h>
 #include <sys/param.h>
 
+#include <libmlrpc/libmlrpc.h>
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libmlrpc.h>
 #include <smbsrv/libmlsvc.h>
 #include <smbsrv/smbinfo.h>
 #include <smbsrv/ntaccess.h>
--- old/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c	Sun Mar 18 01:13:20 2018
+++ new/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c	Sun Mar 18 01:13:20 2018
@@ -39,8 +39,8 @@
 #include <netdb.h>
 #include <assert.h>
 #include <grp.h>
+#include <libmlrpc/libmlrpc.h>
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libmlrpc.h>
 #include <smbsrv/libmlsvc.h>
 #include <smbsrv/smbinfo.h>
 #include <smbsrv/nmpipes.h>
--- old/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c	Sun Mar 18 01:13:20 2018
+++ new/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c	Sun Mar 18 01:13:20 2018
@@ -35,8 +35,8 @@
 #include <strings.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <libmlrpc/libmlrpc.h>
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libmlrpc.h>
 #include <smbsrv/libmlsvc.h>
 #include <smbsrv/smb.h>
 #include <smbsrv/ndl/spoolss.ndl>
--- old/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_clnt.c	Sun Mar 18 01:13:21 2018
+++ new/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_clnt.c	Sun Mar 18 01:13:21 2018
@@ -34,9 +34,11 @@
  */
 
 #include <sys/errno.h>
+#include <sys/tzfile.h>
 #include <stdio.h>
 #include <time.h>
 #include <strings.h>
+#include <unistd.h>
 
 #include <smbsrv/libsmb.h>
 #include <smbsrv/libmlsvc.h>
@@ -348,65 +350,45 @@
 }
 
 /*
- * Windows 95+ and Windows NT4.0 both report the version as 4.0.
- * Windows 2000+ reports the version as 5.x.
+ * Compare the time here with the remote time on the server
+ * and report clock skew.
  */
-int
-srvsvc_net_server_getinfo(char *server, char *domain,
-    srvsvc_server_info_t *svinfo)
+void
+srvsvc_timecheck(char *server, char *domain)
 {
-	mlsvc_handle_t handle;
-	struct mslm_NetServerGetInfo arg;
-	struct mslm_SERVER_INFO_101 *sv101;
-	int len, opnum, rc;
-	char user[SMB_USERNAME_MAXLEN];
+	char			hostname[MAXHOSTNAMELEN];
+	struct timeval		dc_tv;
+	struct tm		dc_tm;
+	struct tm		*tm;
+	time_t			tnow;
+	time_t			tdiff;
+	int			priority;
 
-	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
+	if (srvsvc_net_remote_tod(server, domain, &dc_tv, &dc_tm) < 0) {
+		syslog(LOG_DEBUG, "srvsvc_net_remote_tod failed");
+		return;
+	}
 
-	if (srvsvc_open(server, domain, user, &handle) != 0)
-		return (-1);
+	tnow = time(NULL);
 
-	opnum = SRVSVC_OPNUM_NetServerGetInfo;
-	bzero(&arg, sizeof (arg));
+	if (tnow > dc_tv.tv_sec)
+		tdiff = (tnow - dc_tv.tv_sec) / SECSPERMIN;
+	else
+		tdiff = (dc_tv.tv_sec - tnow) / SECSPERMIN;
 
-	len = strlen(server) + 4;
-	arg.servername = ndr_rpc_malloc(&handle, len);
-	if (arg.servername == NULL)
-		return (-1);
+	if (tdiff != 0) {
+		(void) strlcpy(hostname, "localhost", MAXHOSTNAMELEN);
+		(void) gethostname(hostname, MAXHOSTNAMELEN);
 
-	(void) snprintf((char *)arg.servername, len, "\\\\%s", server);
-	arg.level = 101;
+		priority = (tdiff > 2) ? LOG_NOTICE : LOG_DEBUG;
+		syslog(priority, "DC [%s] clock skew detected: %u minutes",
+		    server, tdiff);
 
-	rc = ndr_rpc_call(&handle, opnum, &arg);
-	if ((rc != 0) || (arg.status != 0)) {
-		srvsvc_close(&handle);
-		return (-1);
+		tm = gmtime(&dc_tv.tv_sec);
+		syslog(priority, "%-8s  UTC: %s", server, asctime(tm));
+		tm = gmtime(&tnow);
+		syslog(priority, "%-8s  UTC: %s", hostname, asctime(tm));
 	}
-
-	sv101 = arg.result.bufptr.bufptr101;
-
-	bzero(svinfo, sizeof (srvsvc_server_info_t));
-	svinfo->sv_platform_id = sv101->sv101_platform_id;
-	svinfo->sv_version_major = sv101->sv101_version_major;
-	svinfo->sv_version_minor = sv101->sv101_version_minor;
-	svinfo->sv_type = sv101->sv101_type;
-	if (sv101->sv101_name)
-		svinfo->sv_name = strdup((char *)sv101->sv101_name);
-	if (sv101->sv101_comment)
-		svinfo->sv_comment = strdup((char *)sv101->sv101_comment);
-
-	if (svinfo->sv_type & SV_TYPE_WFW)
-		svinfo->sv_os = NATIVE_OS_WIN95;
-	if (svinfo->sv_type & SV_TYPE_WINDOWS)
-		svinfo->sv_os = NATIVE_OS_WIN95;
-	if ((svinfo->sv_type & SV_TYPE_NT) ||
-	    (svinfo->sv_type & SV_TYPE_SERVER_NT))
-		svinfo->sv_os = NATIVE_OS_WINNT;
-	if (svinfo->sv_version_major > 4)
-		svinfo->sv_os = NATIVE_OS_WIN2000;
-
-	srvsvc_close(&handle);
-	return (0);
 }
 
 /*
@@ -543,40 +525,4 @@
 
 	srvsvc_close(&handle);
 	return (0);
-}
-
-void
-srvsvc_net_test(char *server, char *domain, char *netname)
-{
-	smb_domainex_t di;
-	srvsvc_server_info_t svinfo;
-
-	(void) smb_tracef("%s %s %s", server, domain, netname);
-
-	if (smb_domain_getinfo(&di)) {
-		server = di.d_dci.dc_name;
-		domain = di.d_primary.di_nbname;
-	}
-
-	if (srvsvc_net_server_getinfo(server, domain, &svinfo) == 0) {
-		smb_tracef("NetServerGetInfo: %s %s (%d.%d) id=%d type=0x%08x",
-		    svinfo.sv_name ? svinfo.sv_name : "NULL",
-		    svinfo.sv_comment ? svinfo.sv_comment : "NULL",
-		    svinfo.sv_version_major, svinfo.sv_version_minor,
-		    svinfo.sv_platform_id, svinfo.sv_type);
-
-		free(svinfo.sv_name);
-		free(svinfo.sv_comment);
-	}
-
-	(void) srvsvc_net_share_get_info(server, domain, netname);
-#if 0
-	/*
-	 * The NetSessionEnum server-side definition was updated.
-	 * Disabled until the client-side has been updated.
-	 */
-	(void) srvsvc_net_session_enum(server, domain, netname);
-#endif
-	(void) srvsvc_net_connect_enum(server, domain, netname, 0);
-	(void) srvsvc_net_connect_enum(server, domain, netname, 1);
 }
--- old/usr/src/lib/smbsrv/libsmb/common/libsmb.h	Sun Mar 18 01:13:21 2018
+++ new/usr/src/lib/smbsrv/libsmb/common/libsmb.h	Sun Mar 18 01:13:21 2018
@@ -44,17 +44,18 @@
 #include <synch.h>
 #include <stdarg.h>
 
+#include <smb/nterror.h>
+#include <smb/ntstatus.h>
+#include <smb/wintypes.h>
+
 #include <smbsrv/string.h>
 #include <smbsrv/smb_idmap.h>
 #include <smbsrv/netbios.h>
 #include <smbsrv/smb_share.h>
-#include <smb/nterror.h>
-#include <smb/ntstatus.h>
 #include <smbsrv/smb_door.h>
 #include <smbsrv/alloc.h>
 #include <smbsrv/hash_table.h>
 #include <smbsrv/msgbuf.h>
-#include <smbsrv/wintypes.h>
 #include <smbsrv/smb_xdr.h>
 #include <smbsrv/smbinfo.h>
 #include <smbsrv/ntifs.h>
--- old/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c	Sun Mar 18 01:13:21 2018
+++ new/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c	Sun Mar 18 01:13:21 2018
@@ -33,8 +33,8 @@
 #include <unistd.h>
 #include <errno.h>
 #include <sys/mman.h>
+#include <smb/wintypes.h>
 #include <smbsrv/libsmb.h>
-#include <smbsrv/wintypes.h>
 #include <smbsrv/smb_door.h>
 
 static int smb_door_call(uint32_t, void *, xdrproc_t, void *, xdrproc_t);
--- old/usr/src/pkg/manifests/service-file-system-smb.mf	Sun Mar 18 01:13:21 2018
+++ new/usr/src/pkg/manifests/service-file-system-smb.mf	Sun Mar 18 01:13:21 2018
@@ -83,7 +83,6 @@
 file path=usr/lib/smbsrv/dtrace/smbnode.d mode=0555
 file path=usr/lib/smbsrv/dtrace/smbsrv.d mode=0555
 file path=usr/lib/smbsrv/dtrace/smbvfs.d mode=0555
-file path=usr/lib/smbsrv/libmlrpc.so.1
 file path=usr/lib/smbsrv/libmlsvc.so.1
 file path=usr/lib/smbsrv/libsmb.so.1
 file path=usr/lib/smbsrv/libsmbns.so.1
@@ -109,7 +108,3 @@
 license lic_CDDL license=lic_CDDL
 link path=usr/lib/reparse/libreparse_smb.so target=libreparse_smb.so.1
 link path=usr/lib/security/pam_smb_passwd.so target=pam_smb_passwd.so.1
-link path=usr/lib/smbsrv/libmlrpc.so target=libmlrpc.so.1
-link path=usr/lib/smbsrv/libmlsvc.so target=libmlsvc.so.1
-link path=usr/lib/smbsrv/libsmb.so target=libsmb.so.1
-link path=usr/lib/smbsrv/libsmbns.so target=libsmbns.so.1
--- old/usr/src/pkg/manifests/system-file-system-smb.mf	Sun Mar 18 01:13:21 2018
+++ new/usr/src/pkg/manifests/system-file-system-smb.mf	Sun Mar 18 01:13:21 2018
@@ -79,6 +79,7 @@
 file path=usr/lib/fs/smbfs/share mode=0555
 file path=usr/lib/fs/smbfs/umount mode=4555
 file path=usr/lib/fs/smbfs/unshare mode=0555
+file path=usr/lib/libmlrpc.so.2
 file path=usr/lib/libsmbfs.so.1
 file path=usr/lib/mdb/kvm/$(ARCH64)/nsmb.so mode=0555
 file path=usr/lib/mdb/kvm/$(ARCH64)/smbfs.so mode=0555
--- old/usr/src/tools/ndrgen/ndrgen.sh	Sun Mar 18 01:13:21 2018
+++ new/usr/src/tools/ndrgen/ndrgen.sh	Sun Mar 18 01:13:21 2018
@@ -19,17 +19,25 @@
 #
 # CDDL HEADER END
 #
+
 #
 # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
+# Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+#
 
 # This is a wrapper script around the ndrgen compiler (ndrgen1).
-# CC must be defined in the environment or on the command line.
 
-NDRPROG="${0%/*}/ndrgen1"
-INCDIR=${ROOT}/usr/include/smbsrv
+NDRPROG="${0}1"
 
+# Note: most *.ndl files require an ANSI-compatible cpp,
+# so we can NOT use /usr/lib/cpp or /usr/ccs/lib/cpp
+# Wish there was an easier way to get an ANSI cpp.
+CPP="${CC} -E"
+CPPFLAGS="-DNDRGEN"
+V_FLAG=
+
 PROGNAME=`basename $0`
 
 ndrgen_usage()
@@ -38,62 +46,63 @@
 		print "$PROGNAME: ERROR: $1"
 	fi
 
-	echo "usage: $PROGNAME [-Y cpp-path] file [file]..."
+	echo "usage: $PROGNAME [options] file.ndl [file.ndl]..."
+	echo "	options: -Y cc-path -Ddefine -Iinclude"
 	exit 1
 }
 
-# Copy header text from the input ndl file to the generated ndr C file.
-ndrgen_copy_header()
+# Process the input ndl file ($1) generating C code on stdout.
+process()
 {
-	ndl_file=$1
-	ndr_file=$2
 
+	# Put the standard top matter
+	#
+	# Want the include directive to have just
+	# include "file.ndl" (no path) so...
+	inc_ndl=`basename $1`
+	cat - << EOF
+/*
+ * Please do not edit this file.
+ * It was generated using ndrgen.
+ */
+
+#include <strings.h>
+#include <libmlrpc/ndr.h>
+#include "$inc_ndl"
+EOF
+
+	# Put optional custom top matter
 	nawk 'BEGIN { copy=0; }
 	/^\/\* NDRGEN_HEADER_BEGIN \*\// { copy=1; next; }
 	/^\/\* NDRGEN_HEADER_END \*\// { copy=0; next; }
-	/./ { if (copy==1) print; }' < $ndl_file > $ndr_file
+	/./ { if (copy==1) print; }' $1
+
+	# now the real ndrgen output
+	[ -n "$V_FLAG" ] &&
+	  echo "$CPP $CPPFLAGS $1 | $NDRPROG" >&2
+	$CPP $CPPFLAGS $1 | $NDRPROG
 }
 
-if [[ $# -lt 1 ]] ; then
-	ndrgen_usage
-fi
 
-while getopts "Y" FLAG $*; do
+while getopts "D:I:Y:V" FLAG
+do
 	case $FLAG in
-	Y)
-		CC_FLAG="y"
-		;;
-	*)
-		ndrgen_usage
-		;;
+	D|I)	CPPFLAGS="$CPPFLAGS -${FLAG}${OPTARG}";;
+	Y)	CPP="$OPTARG";;
+	V)	V_FLAG="V";;
+	*)	ndrgen_usage;;
 	esac
 done
+shift $(($OPTIND - 1))
 
-if [[ $CC_FLAG = "y" ]] ; then
-	shift $(($OPTIND - 1))
-
-	if [[ $# -lt 1 ]] ; then
-		ndrgen_usage "C pre-processor path is missing"
-	else
-		CC=$1
-		shift $(($OPTIND - 1))
-
-		# Check for cw being invoked with -_cc or -_gcc
-		if [[ $1 = "-_cc" || $1 = "-_gcc" ]] ; then
-			CC_ARG=$1
-			shift $(($OPTIND - 1))
-		fi
-	fi
+if [[ $# -lt 1 ]] ; then
+	ndrgen_usage
 fi
 
-if [[ $CC = "" ]] ; then
-	ndrgen_usage "C pre-processor is not defined"
+if [ ! -x $CPP ] ; then
+	ndrgen_usage "cannot run $CPP"
 fi
 
-if [ ! -f $CC ] || [ ! -x $CC ] ; then
-	ndrgen_usage "cannot run $CC"
-fi
-
 for i
 do
 	if [[ ! -r $i ]] ; then
@@ -101,36 +110,9 @@
 		exit 1
 	fi
 
-	BASENAME=`basename $i .ndl`
-	TMP_NAME=$BASENAME.ndl.c
-
-	cp $i $TMP_NAME
-
-	if $CC $CC_ARG -E  -D__a64 -D__EXTENSIONS__ -D_FILE_OFFSET_BITS=64 \
-		-I. -I${INCDIR} -I${INCDIR}/ndl -DNDRGEN $TMP_NAME | \
-		$NDRPROG > $BASENAME.raw
-	then
-		touch ${BASENAME}_ndr.c
-		ndrgen_copy_header $i ${BASENAME}_ndr.c
-
-		cat - << EOF >> ${BASENAME}_ndr.c
-/*
- * Please do not edit this file.
- * It was generated using ndrgen.
- */
-
-#include <strings.h>
-#include <smbsrv/ndr.h>
-#include <smbsrv/ndl/$BASENAME.ndl>
-EOF
-
-		cat $BASENAME.raw >> ${BASENAME}_ndr.c
-
-		rm -f $BASENAME.raw
-		rm -f $TMP_NAME
-	else
-		rm -f $BASENAME.raw
-		rm -f $TMP_NAME
-		exit 1
-	fi
+	base=`basename $i .ndl`
+	process $i > ${base}_ndr.c || {
+	  echo "ndrgen error";
+	  rm ${base}_ndr.c;
+	}
 done
--- /dev/null	Sun Mar 18 01:13:21 2018
+++ new/usr/src/tools/quick/make-smbclnt	Sun Mar 18 01:13:21 2018
@@ -0,0 +1,303 @@
+#!/bin/ksh
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+#
+
+# Use distributed make (dmake) by default.
+make=${MAKE:-dmake}
+
+CLOSED_IS_PRESENT=no
+export CLOSED_IS_PRESENT
+
+# Do this if you want to use dbx or gdb
+# export SOURCEDEBUG=yes
+
+[ -n "$SRC" ] || {
+  echo "SRC not set.  Run 'ws' or 'bldenv' first."
+  exit 1
+}
+
+cpu=`uname -p`
+case $cpu in
+i386)
+	x=intel
+	kmdb_arch="amd64"
+	mdb_arch="ia32 amd64"
+	arch64=amd64
+	;;
+sparc)
+	x=sparc
+	kmdb_arch=v9
+	mdb_arch="v7 v9"
+	arch64=sparcv9
+	;;
+*)  echo "Huh?" ; exit 1;;
+esac
+
+################################################################
+
+build_tools() {
+  test -f $SRC/tools/proto/root_i386-nd/opt/onbld/bin/genoffsets ||
+    (cd $SRC/tools && $make install)
+  (cd $SRC/common/mapfiles; $make install)
+}
+
+clobber_tools() {
+  (cd $SRC/tools && $make clobber)
+  (cd $SRC/common/mapfiles; $make clobber)
+}
+
+################################################################
+
+do_hdrs() {
+
+targ=$1
+if [ "$targ" = clobber ]
+then
+  (cd $SRC/uts && $make -k clobber_h)
+  (cd $SRC/head && $make clobber)
+fi
+
+if [ "$targ" = install ]
+then
+  targ=install_h
+
+  # Just the parts of "make sgs" we need, and
+  # skip them if they appear to be done.
+  # ... stuff under $SRC
+  test -f $SRC/uts/common/sys/priv_names.h ||
+    (cd $SRC/uts && $make -k all_h)
+
+  test -f $SRC/head/rpcsvc/nispasswd.h ||
+    (cd $SRC/head && $make -k install_h)
+
+  # ... stuff under $ROOT (proto area)
+  test -d $ROOT/usr/include/sys ||
+    (cd $SRC && $make rootdirs)
+  test -f $ROOT/usr/include/sys/types.h ||
+    (cd $SRC/uts && $make -k install_h)
+  test -f $ROOT/usr/include/rpcsvc/daemon_utils.h ||
+    (cd $SRC/head && $make install_h)
+
+  # always update the netsmb headers to be safe
+  (cd $SRC/uts/common/sys && $make -k install_h)
+
+fi
+
+# Need some library headers too...
+for lib in \
+  libcryptoutil \
+  libpam \
+  libsec \
+  libshare \
+  libsmbfs \
+  passwdutil
+do
+  (cd $SRC/lib/$lib && $make $targ)
+done
+}
+
+################################################################
+
+do_kern() {
+  case $1 in
+  lint) targ=modlintlib ;;
+  *) targ=$1 ;;
+  esac
+  ( unset SOURCEDEBUG ;
+  (cd $SRC/uts/$x/nsmb && $make $targ) ;
+  (cd $SRC/uts/$x/smbfs && $make $targ) )
+}
+
+################################################################
+
+# Note lib1 builds prerequisite libraries not delivered by the
+# tar file we create below.  To accelerate clean/install, we
+# skip these on clean (but still nuke them for clobber)
+
+do_lib1() {
+  :
+}
+
+# lib2 builds stuff we include in the tar file,
+# or that we don't mind rebuilding after clean.
+
+do_lib2() {
+
+(cd $SRC/lib/libsmbfs && $make $1)
+[ "$1" = install ] &&
+  (cd $SRC/lib/libsmbfs && $make _msg)
+(cd $SRC/lib/libmlrpc && $make $1)
+(cd $SRC/lib/libshare && $make $1 PLUGINS=smbfs)
+(cd $SRC/lib/passwdutil && $make $1)
+(cd $SRC/lib/pam_modules/smbfs && $make $1)
+
+}
+
+################################################################
+
+do_cmds() {
+
+case $1 in
+install)
+  # mount programs need fslib.o
+  (cd $SRC/cmd/fs.d && $make fslib.o)
+  (cd $SRC/cmd/fs.d/smbclnt && $make $1 catalog)
+  ;;
+clean|clobber)
+  (cd $SRC/cmd/fs.d/smbclnt && $make $1)
+  (cd $SRC/cmd/fs.d && $make ${1}_local)
+  ;;
+esac
+
+# Build the MDB modules, WITH the linktest
+(cd $SRC/cmd/mdb/tools && $make $1)
+
+# kmdb_arch is 64-bit only
+for a in $kmdb_arch
+do
+  case $1 in
+  install|lint)
+    (cd $SRC/cmd/mdb/$x/$a/kmdb &&
+	$make kmdb_modlinktest.o )
+    ;;
+  clean|clobber)
+    (cd $SRC/cmd/mdb/$x/$a/kmdb &&
+	$make -k $1 )
+    ;;
+  esac
+
+  (cd $SRC/cmd/mdb/$x/$a/nsmb &&
+	$make $1 KMDB_LINKTEST_ENABLE= )
+  (cd $SRC/cmd/mdb/$x/$a/smbfs &&
+	$make $1 KMDB_LINKTEST_ENABLE= )
+done
+}
+
+
+################################################################
+# This builds $SRC/TAGS (and cscope.files) in a helpful order.
+
+do_tags() {
+	(cd $SRC ;
+	find uts/common/sys -name '*.[ch]' -print |sort
+	find uts/common/net -name '*.[ch]' -print |sort
+	find uts/common/netinet -name '*.[ch]' -print |sort
+	find uts/common/smb -name '*.[ch]' -print |sort
+	find uts/common/netsmb -name '*.[ch]' -print |sort
+	find uts/common/fs/smbclnt -name '*.[ch]' -print |sort
+	find head -name '*.h' -print |sort
+	find lib/libsmbfs -name '*.[ch]' -print |sort
+	find cmd/fs.d/smbclnt -name '*.[ch]' -print |sort
+	find common/smbclnt -name '*.[ch]' -print |sort
+	) > $SRC/cscope.files
+
+	(cd $SRC ;
+	exctags -e --langmap=c:+.ndl -h ndl -L - < cscope.files
+	cscope -b )
+}
+
+################################################################
+# This creates a tarfile one can use to update a test machine.
+
+do_tar() {
+	git_rev=`git rev-parse --short=8 HEAD`
+	files="
+lib/svc/manifest/network/smb/client.xml
+lib/svc/method/smb-client
+opt/smbcl-tests/tests/srvenum
+opt/smbcl-tests/tests/srvinfo
+opt/smbcl-tests/tests/tconn
+usr/bin/smbutil
+usr/kernel/drv/$arch64/nsmb
+usr/kernel/fs/$arch64/smbfs
+usr/kernel/kmdb/$arch64/nsmb
+usr/kernel/kmdb/$arch64/smbfs
+usr/lib/$arch64/libsmbfs.so.1
+usr/lib/fs/smbfs/$arch64/libshare_smbfs.so.1
+usr/lib/fs/smbfs/chacl
+usr/lib/fs/smbfs/dfshares
+usr/lib/fs/smbfs/libshare_smbfs.so.1
+usr/lib/fs/smbfs/lsacl
+usr/lib/fs/smbfs/mount
+usr/lib/fs/smbfs/share
+usr/lib/fs/smbfs/umount
+usr/lib/fs/smbfs/unshare
+usr/lib/libmlrpc.so.1
+usr/lib/libsmbfs.so.1
+usr/lib/mdb/kvm/$arch64/nsmb.so
+usr/lib/mdb/kvm/$arch64/smbfs.so
+usr/lib/mdb/kvm/nsmb.so
+usr/lib/mdb/kvm/smbfs.so
+usr/lib/security/$arch64/pam_smbfs_login.so.1
+usr/lib/security/pam_smbfs_login.so.1
+usr/lib/smbfs/smbiod
+usr/lib/smbfs/smbiod-svc
+"
+
+	(cd $ROOT && tar cfj ../../smbclnt-${git_rev}.tar.bz2 $files)
+}
+
+################################################################
+
+if [ "$1" = "" ]; then
+  set '?' # force usage
+fi
+
+set -x
+
+for arg
+do
+  case "$arg" in
+  install)
+    build_tools
+    set -e
+    do_hdrs $arg
+    do_kern $arg
+    do_lib1 $arg
+    do_lib2 $arg
+    do_cmds $arg
+    ;;
+  lint)
+    do_kern $arg
+    do_lib1 $arg
+    do_lib2 $arg
+    do_cmds $arg
+    ;;
+  clean)
+    # intentionally skip: lib1, hdrs, tools
+    do_cmds $arg
+    do_lib2 $arg
+    do_kern $arg
+    ;;
+  clobber)
+    do_cmds $arg
+    do_lib2 $arg
+    do_lib1 $arg
+    do_kern $arg
+    do_hdrs $arg
+    clobber_tools
+    ;;
+  tags)
+    do_tags
+    ;;
+  tar)
+    do_tar
+    ;;
+  *)
+    echo "Usage: $0 {install|lint|clean|clobber|tags|tar}";
+    exit 1;
+    ;;
+  esac
+done
--- old/usr/src/tools/quick/make-smbsrv	Sun Mar 18 01:13:21 2018
+++ new/usr/src/tools/quick/make-smbsrv	Sun Mar 18 01:13:21 2018
@@ -287,7 +287,7 @@
 usr/lib/reparse/libreparse_smb.so.1
 usr/lib/security/pam_smb_passwd.so.1
 usr/lib/smbsrv/dtrace
-usr/lib/smbsrv/libmlrpc.so.1
+usr/lib/libmlrpc.so.1
 usr/lib/smbsrv/libmlsvc.so.1
 usr/lib/smbsrv/libsmb.so.1
 usr/lib/smbsrv/libsmbns.so.1
--- old/usr/src/uts/common/smb/Makefile	Sun Mar 18 01:13:22 2018
+++ new/usr/src/uts/common/smb/Makefile	Sun Mar 18 01:13:22 2018
@@ -21,6 +21,7 @@
 
 #
 # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
 #
 
 include ../../../Makefile.master
@@ -29,7 +30,8 @@
 	doserror.h		\
 	lmerr.h			\
 	nterror.h		\
-	ntstatus.h
+	ntstatus.h		\
+	wintypes.h
 
 
 ROOTDIR= $(ROOT)/usr/include/smb
--- old/usr/src/uts/common/smbsrv/wintypes.h	Sun Mar 18 01:13:22 2018
+++ /dev/null	Sun Mar 18 01:13:21 2018
@@ -1,77 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _SMBSRV_WINTYPES_H
-#define	_SMBSRV_WINTYPES_H
-
-#include <sys/types.h>
-
-/*
- * Standard win32 types and definitions.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef UNSIGNED_TYPES_DEFINED
-#define	UNSIGNED_TYPES_DEFINED
-
-typedef	uint8_t BYTE;
-typedef	uint16_t WORD;
-typedef	uint32_t DWORD;
-typedef	uint32_t ntstatus_t;
-typedef	uint8_t *LPTSTR;
-typedef	uint8_t *LPBYTE;
-typedef	uint16_t *LPWORD;
-typedef	uint32_t *LPDWORD;
-
-#endif /* UNSIGNED_TYPES_DEFINED */
-
-
-#ifndef ANY_SIZE_ARRAY
-#define	ANY_SIZE_ARRAY  1
-#endif /* ANY_SIZE_ARRAY */
-
-/*
- * Opaque context handle.
- */
-#ifndef CONTEXT_HANDLE
-#define	CONTEXT_HANDLE(NAME)	\
-	struct NAME {		\
-		DWORD data1;    \
-		DWORD data2;    \
-		WORD  data3[2]; \
-		BYTE  data4[8];	\
-	};			\
-	typedef struct NAME
-#endif /* CONTEXT_HANDLE */
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SMBSRV_WINTYPES_H */
--- /dev/null	Sun Mar 18 01:13:21 2018
+++ new/usr/src/uts/common/smb/wintypes.h	Sun Mar 18 01:13:22 2018
@@ -0,0 +1,72 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+#ifndef _SMB_WINTYPES_H
+#define	_SMB_WINTYPES_H
+
+#include <sys/types.h>
+
+/*
+ * Standard win32 types and definitions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef UNSIGNED_TYPES_DEFINED
+#define	UNSIGNED_TYPES_DEFINED
+
+typedef	uint8_t BYTE;
+typedef	uint16_t WORD;
+typedef	uint32_t DWORD;
+typedef	DWORD ntstatus_t;
+
+/* pointers to those types */
+typedef	BYTE *LPBYTE;
+typedef	WORD *LPWORD;
+typedef	DWORD *LPDWORD;
+
+/* Note: Internally, this is always a UTF-8 string. */
+typedef	uint8_t *LPTSTR;
+
+#endif /* UNSIGNED_TYPES_DEFINED */
+
+
+/* XXX This does not really belong here... */
+#ifndef ANY_SIZE_ARRAY
+#define	ANY_SIZE_ARRAY  1
+#endif /* ANY_SIZE_ARRAY */
+
+/* CONTEXT_HANDLE now in ndrtypes.ndl */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SMB_WINTYPES_H */
--- old/usr/src/uts/common/smbsrv/Makefile	Sun Mar 18 01:13:22 2018
+++ new/usr/src/uts/common/smbsrv/Makefile	Sun Mar 18 01:13:22 2018
@@ -33,7 +33,6 @@
 	mailslot.h		\
 	mbuf.h			\
 	msgbuf.h		\
-	ndr.h			\
 	netbios.h		\
 	netrauth.h		\
 	nmpipes.h		\
@@ -63,8 +62,7 @@
 	string.h		\
 	svrapi.h		\
 	winioctl.h		\
-	winsvc.h		\
-	wintypes.h
+	winsvc.h
 
 NDLHDRS= dssetup.ndl		\
 	eventlog.ndl		\
@@ -71,10 +69,8 @@
 	llsrpc.ndl		\
 	lsarpc.ndl		\
 	msgsvc.ndl		\
-	ndrtypes.ndl		\
 	netdfs.ndl		\
 	netlogon.ndl		\
-	rpcpdu.ndl		\
 	samrpc.ndl		\
 	security.ndl		\
 	spoolss.ndl		\
--- old/usr/src/uts/common/smbsrv/ndl/dssetup.ndl	Sun Mar 18 01:13:22 2018
+++ new/usr/src/uts/common/smbsrv/ndl/dssetup.ndl	Sun Mar 18 01:13:22 2018
@@ -21,6 +21,8 @@
 /*
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _DSSETUP_NDL_
@@ -34,7 +36,7 @@
  * except DsRoleGetPrimaryDomainInfo have been deprecated (MS04-011).
  */
 
-#include "ndrtypes.ndl"
+#include <libmlrpc/ndrtypes.ndl>
 
 
 #define	DSSETUP_OPNUM_DsRoleGetPrimaryDomainInfo	0x00
--- old/usr/src/uts/common/smbsrv/ndl/eventlog.ndl	Sun Mar 18 01:13:22 2018
+++ new/usr/src/uts/common/smbsrv/ndl/eventlog.ndl	Sun Mar 18 01:13:22 2018
@@ -21,6 +21,8 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _MLSVC_LOGR_NDL_
@@ -34,7 +36,7 @@
  ***********************************************************************
  */
 
-#include "ndrtypes.ndl"
+#include <libmlrpc/ndrtypes.ndl>
 
 #define LOGR_OPNUM_EventLogClose		0x02
 #define LOGR_OPNUM_EventLogQueryCount		0x04
--- old/usr/src/uts/common/smbsrv/ndl/llsrpc.ndl	Sun Mar 18 01:13:22 2018
+++ new/usr/src/uts/common/smbsrv/ndl/llsrpc.ndl	Sun Mar 18 01:13:22 2018
@@ -21,6 +21,8 @@
 /*
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _MLSVC_LLSR_NDL_
@@ -41,7 +43,7 @@
  *	0x3b	closes the handle obtained via 0x3a
  */
 
-#include "ndrtypes.ndl"
+#include <libmlrpc/ndrtypes.ndl>
 
 #define LLSR_OPNUM_Open			0x00
 #define LLSR_OPNUM_Close		0x01
--- old/usr/src/uts/common/smbsrv/ndl/lsarpc.ndl	Sun Mar 18 01:13:22 2018
+++ new/usr/src/uts/common/smbsrv/ndl/lsarpc.ndl	Sun Mar 18 01:13:22 2018
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _MLSVC_LSA_NDL_
@@ -38,7 +39,7 @@
  * user principal name (UPN) form, such as john@example.com.
  */
 
-#include "ndrtypes.ndl"
+#include <libmlrpc/ndrtypes.ndl>
 
 
 #define	LSARPC_OPNUM_CloseHandle			0x00
--- old/usr/src/uts/common/smbsrv/ndl/msgsvc.ndl	Sun Mar 18 01:13:22 2018
+++ new/usr/src/uts/common/smbsrv/ndl/msgsvc.ndl	Sun Mar 18 01:13:22 2018
@@ -21,6 +21,8 @@
 /*
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _MSGSVC_NDL_
@@ -30,7 +32,7 @@
  * Message Service
  */
 
-#include "ndrtypes.ndl"
+#include <libmlrpc/ndrtypes.ndl>
 
 #define	MSGSVCSEND_OPNUM_NetrSendMessage	0x00
 
--- old/usr/src/uts/common/smbsrv/ndl/netdfs.ndl	Sun Mar 18 01:13:22 2018
+++ new/usr/src/uts/common/smbsrv/ndl/netdfs.ndl	Sun Mar 18 01:13:22 2018
@@ -21,6 +21,8 @@
 /*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _NETDFS_NDL_
@@ -30,7 +32,7 @@
  * NT Distributed File Service (NETDFS) RPC interface definition.
  */
 
-#include "ndrtypes.ndl"
+#include <libmlrpc/ndrtypes.ndl>
 
 
 #define	NETDFS_ABSTRACT_UUID		"4fc742e0-4a10-11cf-8273-00aa004ae673"
--- old/usr/src/uts/common/smbsrv/ndl/netlogon.ndl	Sun Mar 18 01:13:23 2018
+++ new/usr/src/uts/common/smbsrv/ndl/netlogon.ndl	Sun Mar 18 01:13:23 2018
@@ -36,7 +36,7 @@
  ***********************************************************************
  */
 
-#include "ndrtypes.ndl"
+#include <libmlrpc/ndrtypes.ndl>
 
 
 #define NETR_OPNUM_UasLogon			0x00
--- old/usr/src/uts/common/smbsrv/ndl/samrpc.ndl	Sun Mar 18 01:13:23 2018
+++ new/usr/src/uts/common/smbsrv/ndl/samrpc.ndl	Sun Mar 18 01:13:23 2018
@@ -31,7 +31,7 @@
  * Security Accounts Manager RPC (SAMR) interface definition.
  */
 
-#include "ndrtypes.ndl"
+#include <libmlrpc/ndrtypes.ndl>
 
 /* Windows NT */
 #define SAMR_OPNUM_Connect			0x00	/* SamrConnect */
@@ -363,7 +363,7 @@
 #ifndef	NDRGEN
 #define SAMR_USER_PWLEN	256
 struct samr_user_password {
-	smb_wchar_t	Buffer[SAMR_USER_PWLEN];
+	ndr_wchar_t	Buffer[SAMR_USER_PWLEN];
 	DWORD Length;
 };
 #endif	/* NDRGEN */
--- old/usr/src/uts/common/smbsrv/ndl/spoolss.ndl	Sun Mar 18 01:13:23 2018
+++ new/usr/src/uts/common/smbsrv/ndl/spoolss.ndl	Sun Mar 18 01:13:23 2018
@@ -20,12 +20,13 @@
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _SPOOLSS_NDL_
 #define	_SPOOLSS_NDL_
 
-#include "ndrtypes.ndl"
+#include <libmlrpc/ndrtypes.ndl>
 #include "security.ndl"
 
 #define TABLE_STRING 1
--- old/usr/src/uts/common/smbsrv/ndl/srvsvc.ndl	Sun Mar 18 01:13:23 2018
+++ new/usr/src/uts/common/smbsrv/ndl/srvsvc.ndl	Sun Mar 18 01:13:23 2018
@@ -21,6 +21,8 @@
 /*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _MLSVC_LANMAN_NDL_
@@ -30,7 +32,7 @@
  * LanMan RPC (WKSSVC and SRVSVC) interface definitions.
  */
 
-#include "ndrtypes.ndl"
+#include <libmlrpc/ndrtypes.ndl>
 
 /*
  * WARNING: The cpp(1) macros in this file are not understood by
--- old/usr/src/uts/common/smbsrv/ndl/svcctl.ndl	Sun Mar 18 01:13:23 2018
+++ new/usr/src/uts/common/smbsrv/ndl/svcctl.ndl	Sun Mar 18 01:13:23 2018
@@ -21,6 +21,8 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _MLSVC_SVCCTL_NDL_
@@ -32,7 +34,7 @@
  * stop services.
  */
 
-#include "ndrtypes.ndl"
+#include <libmlrpc/ndrtypes.ndl>
 
 /* Windows NT */
 #define SVCCTL_OPNUM_Close			0x00
--- old/usr/src/uts/common/smbsrv/ndl/winreg.ndl	Sun Mar 18 01:13:23 2018
+++ new/usr/src/uts/common/smbsrv/ndl/winreg.ndl	Sun Mar 18 01:13:23 2018
@@ -21,6 +21,8 @@
 /*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _MLSVC_WINREG_NDL_
@@ -43,7 +45,7 @@
  * HKEY_PERFORMANCE_NLS  (HKPN)	Runtime performance information.
  */
 
-#include "ndrtypes.ndl"
+#include <libmlrpc/ndrtypes.ndl>
 
 /* Windows NT */
 #define WINREG_OPNUM_OpenHKCR		0x00
--- old/usr/src/uts/common/smbsrv/netrauth.h	Sun Mar 18 01:13:23 2018
+++ new/usr/src/uts/common/smbsrv/netrauth.h	Sun Mar 18 01:13:23 2018
@@ -33,7 +33,7 @@
  */
 
 #include <sys/types.h>
-#include <smbsrv/wintypes.h>
+#include <smb/wintypes.h>
 #include <smbsrv/netbios.h>
 #include <smbsrv/smbinfo.h>
 #include <netdb.h>
--- old/usr/src/uts/common/smbsrv/smb_door.h	Sun Mar 18 01:13:24 2018
+++ new/usr/src/uts/common/smbsrv/smb_door.h	Sun Mar 18 01:13:24 2018
@@ -27,7 +27,7 @@
 #define	_SMBSRV_SMB_DOOR_H
 
 #include <sys/door.h>
-#include <smbsrv/wintypes.h>
+#include <smb/wintypes.h>
 #include <smbsrv/smb_xdr.h>
 #include <smbsrv/smb_token.h>
 
--- old/usr/src/uts/common/smbsrv/smb_privilege.h	Sun Mar 18 01:13:24 2018
+++ new/usr/src/uts/common/smbsrv/smb_privilege.h	Sun Mar 18 01:13:24 2018
@@ -28,7 +28,7 @@
 #ifndef _SMB_PRIVILEGE_H
 #define	_SMB_PRIVILEGE_H
 
-#include <smbsrv/wintypes.h>
+#include <smb/wintypes.h>
 
 #ifdef __cplusplus
 extern "C" {
--- old/usr/src/uts/common/smbsrv/smb_share.h	Sun Mar 18 01:13:24 2018
+++ new/usr/src/uts/common/smbsrv/smb_share.h	Sun Mar 18 01:13:24 2018
@@ -29,11 +29,11 @@
 #define	_SMB_SHARE_H
 
 #include <sys/param.h>
+#include <smb/lmerr.h>
+#include <smb/wintypes.h>
 #include <smbsrv/string.h>
 #include <smbsrv/smb_inet.h>
 #include <smbsrv/hash_table.h>
-#include <smbsrv/wintypes.h>
-#include <smb/lmerr.h>
 
 #if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
 #include <libshare.h>
--- old/usr/src/uts/common/smbsrv/smb_sid.h	Sun Mar 18 01:13:24 2018
+++ new/usr/src/uts/common/smbsrv/smb_sid.h	Sun Mar 18 01:13:24 2018
@@ -29,7 +29,7 @@
 /*
  * Security Identifier (SID) interface definition.
  */
-#include <smbsrv/wintypes.h>
+#include <smb/wintypes.h>
 
 #ifdef __cplusplus
 extern "C" {
--- old/usr/src/uts/common/smbsrv/smb_xdr.h	Sun Mar 18 01:13:24 2018
+++ new/usr/src/uts/common/smbsrv/smb_xdr.h	Sun Mar 18 01:13:24 2018
@@ -34,7 +34,7 @@
 #include <sys/param.h>
 #include <sys/avl.h>
 #include <sys/list.h>
-#include <smbsrv/wintypes.h>
+#include <smb/wintypes.h>
 #include <smbsrv/smb_sid.h>
 #include <smbsrv/smbinfo.h>
 #include <smbsrv/smb_ioctl.h>
@@ -41,7 +41,6 @@
 #include <smbsrv/smb_sid.h>
 #include <smbsrv/smb_share.h>
 #include <smbsrv/smb_dfs.h>
-#include <smbsrv/wintypes.h>
 
 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
 #include <sys/sysmacros.h>
