diff options
Diffstat (limited to 'usr/src')
111 files changed, 3328 insertions, 1832 deletions
diff --git a/usr/src/Makefile.master b/usr/src/Makefile.master index 2e5fd4b51b..70faac9962 100644 --- a/usr/src/Makefile.master +++ b/usr/src/Makefile.master @@ -178,6 +178,7 @@ FLEX= /usr/bin/flex YACC= /usr/ccs/bin/yacc BISON= /usr/bin/bison 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 diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/Makefile b/usr/src/cmd/fs.d/smbclnt/smbutil/Makefile index 5b751cce22..e20054c772 100644 --- a/usr/src/cmd/fs.d/smbclnt/smbutil/Makefile +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/Makefile @@ -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 login.o lookup.o print.o status.o view.o +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 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 @@ $(POFILE): $(POFILES) lint: lint_SRCS -clean : - $(RM) $(OBJS) - -.KEEP_STATE: +clean: + $(RM) $(OBJS) $(CLEANFILES) include ../../../Makefile.targ + +srvsvc1_ndr.c : srvsvc1.ndl + $(NDRGEN) -Y $(ANSI_CPP) $(CPPFLAGS) srvsvc1.ndl + +.KEEP_STATE: diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/common.h b/usr/src/cmd/fs.d/smbclnt/smbutil/common.h index 24cb1436a0..aea093c0ea 100644 --- a/usr/src/cmd/fs.d/smbclnt/smbutil/common.h +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/common.h @@ -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 @@ extern "C" { 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_print(int argc, char *argv[]); 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 print_usage(void); 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 } diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/info.c b/usr/src/cmd/fs.d/smbclnt/smbutil/info.c new file mode 100644 index 0000000000..600df1c1b9 --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/info.c @@ -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); +} diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/shares_rap.c b/usr/src/cmd/fs.d/smbclnt/smbutil/shares_rap.c new file mode 100644 index 0000000000..f2235e2880 --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/shares_rap.c @@ -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); +} diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/shares_rpc.c b/usr/src/cmd/fs.d/smbclnt/smbutil/shares_rpc.c new file mode 100644 index 0000000000..221d6f077b --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/shares_rpc.c @@ -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); +} diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/smbutil.c b/usr/src/cmd/fs.d/smbclnt/smbutil/smbutil.c index 20cb3a2c86..9b09b87d64 100644 --- a/usr/src/cmd/fs.d/smbclnt/smbutil/smbutil.c +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/smbutil.c @@ -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> @@ -65,10 +67,11 @@ static struct commands { const char *name; cmd_fn_t *fn; cmd_usage_t *usage; - int flags; + int flags; } 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}, @@ -187,13 +190,14 @@ help(void) { printf(gettext("where subcommands are:\n" " crypt slightly obscure password\n" " help display help on specified subcommand\n" - /* " lc display active connections\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" + " logout logout from specified host\n" " logoutall logout all users (requires privilege)\n" - " lookup resolve NetBIOS name to IP address\n" + " lookup resolve NetBIOS name to IP address\n" " print print file to the specified remote printer\n" - " status resolve IP address or DNS name to NetBIOS names\n" + " status resolve IP address or DNS name to NetBIOS names\n" " view list resources on specified host\n" "\n")); exit(1); diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1.ndl b/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1.ndl new file mode 100644 index 0000000000..6712f05020 --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1.ndl @@ -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) diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1_clnt.c b/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1_clnt.c new file mode 100644 index 0000000000..7ebe614ab6 --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1_clnt.c @@ -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); +} diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1_clnt.h b/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1_clnt.h new file mode 100644 index 0000000000..66e50a8ab5 --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1_clnt.h @@ -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 */ diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/view.c b/usr/src/cmd/fs.d/smbclnt/smbutil/view.c index baad53b00c..8622fb14be 100644 --- a/usr/src/cmd/fs.d/smbclnt/smbutil/view.c +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/view.c @@ -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 @@ cmd_view(int argc, char *argv[]) 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 @@ cmd_view(int argc, char *argv[]) */ error = smb_ctx_resolve(ctx); if (error) - return (error); + goto out; /* * Have server, share, etc. from above: @@ -118,24 +125,26 @@ again: if (error) { smb_error(gettext("//%s: login failed"), error, ctx->ct_fullserver); - return (error); + 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); - 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); } @@ -145,7 +154,7 @@ static char *shtype[] = { gettext("disk"), gettext("printer"), gettext("device"), /* Communications device */ - gettext("IPC"), /* Inter process communication */ + gettext("IPC"), /* Inter process communication */ gettext("unknown") }; #else @@ -153,53 +162,34 @@ static char *shtype[] = { "disk", "printer", "device", /* Communications device */ - "IPC", /* IPC Inter process communication */ + "IPC", /* IPC Inter process communication */ "unknown" }; #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; - - printf(gettext("Share Type Comment\n")); - printf("-------------------------------\n"); - - 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); + stindex = type & STYPE_MASK; + if (stindex > STYPE_UNKNOWN) + stindex = STYPE_UNKNOWN; + stname = gettext(shtype[stindex]); + + if (comment == NULL) + comment = ""; - free(share_info); + printf("%-12s %-10s %s\n", share, stname, comment); } diff --git a/usr/src/cmd/mdb/common/modules/zfs/zfs.c b/usr/src/cmd/mdb/common/modules/zfs/zfs.c index 5d3af7ff3c..ad66d688ea 100644 --- a/usr/src/cmd/mdb/common/modules/zfs/zfs.c +++ b/usr/src/cmd/mdb/common/modules/zfs/zfs.c @@ -21,8 +21,8 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. * Copyright (c) 2017, Joyent, Inc. All rights reserved. - * Copyright (c) 2011, 2017 by Delphix. All rights reserved. */ /* Portions Copyright 2010 Robert Milkowski */ @@ -1727,6 +1727,7 @@ typedef struct mdb_metaslab_alloc_trace { uint64_t mat_weight; uint64_t mat_offset; uint32_t mat_dva_id; + int mat_allocator; } mdb_metaslab_alloc_trace_t; static void @@ -1799,8 +1800,9 @@ metaslab_trace(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) } if (!(flags & DCMD_PIPE_OUT) && DCMD_HDRSPEC(flags)) { - mdb_printf("%<u>%6s %6s %8s %11s %18s %18s%</u>\n", - "MSID", "DVA", "ASIZE", "WEIGHT", "RESULT", "VDEV"); + mdb_printf("%<u>%6s %6s %8s %11s %11s %18s %18s%</u>\n", + "MSID", "DVA", "ASIZE", "ALLOCATOR", "WEIGHT", "RESULT", + "VDEV"); } if (mat.mat_msp != NULL) { @@ -1815,7 +1817,8 @@ metaslab_trace(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) mdb_printf("%6s ", "-"); } - mdb_printf("%6d %8llx ", mat.mat_dva_id, mat.mat_size); + mdb_printf("%6d %8llx %11llx ", mat.mat_dva_id, mat.mat_size, + mat.mat_allocator); metaslab_print_weight(mat.mat_weight); diff --git a/usr/src/common/smbsrv/smb_door_legacy.c b/usr/src/common/smbsrv/smb_door_legacy.c index 985b83eb7a..ae1e557db8 100644 --- a/usr/src/common/smbsrv/smb_door_legacy.c +++ b/usr/src/common/smbsrv/smb_door_legacy.c @@ -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> diff --git a/usr/src/common/smbsrv/smb_token_xdr.c b/usr/src/common/smbsrv/smb_token_xdr.c index fdad7ed5ca..b2f5a92352 100644 --- a/usr/src/common/smbsrv/smb_token_xdr.c +++ b/usr/src/common/smbsrv/smb_token_xdr.c @@ -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> diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile index 0054c41e6d..445238f973 100644 --- a/usr/src/lib/Makefile +++ b/usr/src/lib/Makefile @@ -166,6 +166,7 @@ SUBDIRS += \ libmapid \ libmapmalloc \ libmd5 \ + libmlrpc \ libmtmalloc \ libmvec \ libndmp \ @@ -432,6 +433,7 @@ HDRSUBDIRS= \ libmail \ libmapid \ libmd \ + libmlrpc \ libmtmalloc \ libndmp \ libnsctl \ @@ -642,6 +644,7 @@ libkmf: libcryptoutil pkcs11 libkvm: ../cmd/sgs/libelf libldap5: libsasl libmapid: libresolv2 libscf +libmlrpc: libsmbfs libuuid libndmp: libscf libnisdb: libldap5 libnwam: libscf libbsm libdladm libipadm @@ -714,7 +717,7 @@ sasl_plugins: pkcs11 libgss libsasl 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 diff --git a/usr/src/lib/libmlrpc/Makefile b/usr/src/lib/libmlrpc/Makefile new file mode 100644 index 0000000000..ae458ebc7a --- /dev/null +++ b/usr/src/lib/libmlrpc/Makefile @@ -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 diff --git a/usr/src/lib/smbsrv/libmlrpc/Makefile.com b/usr/src/lib/libmlrpc/Makefile.com index fa45211464..1a2ecb4ddd 100644 --- a/usr/src/lib/smbsrv/libmlrpc/Makefile.com +++ b/usr/src/lib/libmlrpc/Makefile.com @@ -18,39 +18,58 @@ # # 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 = .1 +VERS = .2 -OBJS_COMMON = \ +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_svc.o \ + ndr_wchar.o NDLLIST = rpcpdu -OBJECTS= $(OBJS_COMMON) $(OBJS_SHARED) $(NDLLIST:%=%_ndr.o) +OBJECTS= $(OBJS_COMMON) $(NDLLIST:%=%_ndr.o) +CLEANFILES += $(NDLLIST:%=%_ndr.c) -include ../../../Makefile.lib include ../../Makefile.lib -INCS += -I$(SRC)/common/smbsrv +LIBS= $(DYNLIB) $(LINTLIB) + +LDLIBS += -lsmbfs -luuid -lc + +SRCDIR= ../common +SRCS= $(OBJS_COMMON:%.o=$(SRCDIR)/%.c) +$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) -LDLIBS += $(MACH_LDLIBS) -LDLIBS += -lsmb -luuid -lc +NDLDIR = $(SRCDIR) +CFLAGS += $(CCVERBOSE) +INCS = -I. -I$(SRCDIR) CPPFLAGS += $(INCS) -D_REENTRANT -SRCS= $(OBJS_COMMON:%.o=$(SRCDIR)/%.c) \ - $(OBJS_SHARED:%.o=$(SRC)/common/smbsrv/%.c) +all: $(LIBS) + +lint: lintcheck include ../../Makefile.targ -include ../../../Makefile.targ + +objs/%_ndr.o pics/%_ndr.o : %_ndr.c + +%_ndr.c : $(NDLDIR)/%.ndl + $(NDRGEN) -Y $(ANSI_CPP) $(CPPFLAGS) $< + +.KEEP_STATE: diff --git a/usr/src/lib/smbsrv/libmlrpc/amd64/Makefile b/usr/src/lib/libmlrpc/amd64/Makefile index b3c4916b0c..087f0e1107 100644 --- a/usr/src/lib/smbsrv/libmlrpc/amd64/Makefile +++ b/usr/src/lib/libmlrpc/amd64/Makefile @@ -22,14 +22,10 @@ # 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) +include ../../Makefile.lib.64 install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/smbsrv/libmlrpc/common/libmlrpc.h b/usr/src/lib/libmlrpc/common/libmlrpc.h index 5b55ce4c54..d020532cbe 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/libmlrpc.h +++ b/usr/src/lib/libmlrpc/common/libmlrpc.h @@ -28,10 +28,9 @@ #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> + +#include <smb/wintypes.h> +#include <libmlrpc/ndr.h> #ifdef __cplusplus extern "C" { @@ -247,9 +246,9 @@ typedef struct ndr_binding { #define NDR_N_BINDING_POOL 2 typedef struct ndr_pipe { - void *np_listener; + void *np_listener; const char *np_endpoint; - smb_netuserinfo_t *np_user; + 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; @@ -402,12 +401,12 @@ typedef struct ndr_vcbuf { 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 *); -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 *); @@ -416,7 +415,7 @@ int ndr_heap_avail(ndr_heap_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)) +#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 */ @@ -488,7 +487,7 @@ 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_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 *); @@ -514,10 +513,6 @@ 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 *); @@ -538,6 +533,38 @@ 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 diff --git a/usr/src/lib/smbsrv/libmlrpc/common/llib-lmlrpc b/usr/src/lib/libmlrpc/common/llib-lmlrpc index 1621e3c2f6..3345e6129a 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/llib-lmlrpc +++ b/usr/src/lib/libmlrpc/common/llib-lmlrpc @@ -21,11 +21,11 @@ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /*LINTLIBRARY*/ /*PROTOLIB1*/ -#include <smbsrv/libmlrpc.h> +#include <libmlrpc.h> diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers b/usr/src/lib/libmlrpc/common/mapfile-vers index 5822d32711..241d8309d0 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers +++ b/usr/src/lib/libmlrpc/common/mapfile-vers @@ -42,47 +42,74 @@ $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; + 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_malloc; - ndr_heap_mkvcb; - ndr_heap_mkvcs; + 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_siddup; - ndr_heap_strdup; - ndr_heap_used; + ndr_heap_strdup; + ndr_heap_used; ndr_hdalloc; + ndr_hdclose; ndr_hdfree; ndr_hdlookup; - ndr_inner; - ndr_is_admin; - ndr_is_poweruser; + ndr_inherit_handle; + ndr_inner; + ndr_is_bind_handle; + ndr_is_null_handle; ndr_mbstowcs; - ndr_mbtowc; - ndr_native_os; - ndr_params; + ndr_params; ndr_pipe_worker; - ndr_svc_binding_pool_init; + 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_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; + + 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: *; }; diff --git a/usr/src/lib/libmlrpc/common/mlrpc_clh.c b/usr/src/lib/libmlrpc/common/mlrpc_clh.c new file mode 100644 index 0000000000..72c051d675 --- /dev/null +++ b/usr/src/lib/libmlrpc/common/mlrpc_clh.c @@ -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; + } +} diff --git a/usr/src/uts/common/smbsrv/ndr.h b/usr/src/lib/libmlrpc/common/ndr.h index 584c0798e4..f6af9a22cf 100644 --- a/usr/src/uts/common/smbsrv/ndr.h +++ b/usr/src/lib/libmlrpc/common/ndr.h @@ -40,18 +40,14 @@ * 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 */ + +#include <smb/wintypes.h> +#include <libmlrpc/ndrtypes.ndl> +#include <libmlrpc/rpcpdu.ndl> #ifdef __cplusplus extern "C" { @@ -455,8 +451,7 @@ 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); +size_t ndr_mbstowcs(struct ndr_stream *, ndr_wchar_t *, const char *, size_t); void nds_bswap(void *src, void *dst, size_t len); diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_client.c b/usr/src/lib/libmlrpc/common/ndr_client.c index 7aaa35e6b5..56cc1847ef 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_client.c +++ b/usr/src/lib/libmlrpc/common/ndr_client.c @@ -21,14 +21,15 @@ /* * 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 <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> +#include <libmlrpc.h> #define NDR_DEFAULT_FRAGSZ 8192 #define NDR_MULTI_FRAGSZ (60 * 1024) @@ -38,24 +39,19 @@ 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_clnt_bind(ndr_client_t *clnt, ndr_service_t *msvc, 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_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); @@ -140,16 +136,12 @@ 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; diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_heap.c b/usr/src/lib/libmlrpc/common/ndr_heap.c index 73a453b00e..5ec8a5aa77 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_heap.c +++ b/usr/src/lib/libmlrpc/common/ndr_heap.c @@ -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. */ /* @@ -46,9 +48,8 @@ #include <strings.h> #include <sys/uio.h> -#include <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> -#include <smbsrv/smb_sid.h> +#include <libmlrpc.h> +#include <ndr_wchar.h> /* * Allocate a heap structure and the first heap block. For many RPC @@ -154,6 +155,23 @@ ndr_heap_malloc(ndr_heap_t *heap, unsigned size) } /* + * 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 * @@ -171,8 +189,7 @@ ndr_heap_strdup(ndr_heap_t *heap, const char *s) if ((len = strlen(s)) == 0) return (""); - if ((p = ndr_heap_malloc(heap, len+1)) != NULL) - (void) strcpy((char *)p, s); + p = ndr_heap_dupmem(heap, s, len+1); return (p); } @@ -183,11 +200,21 @@ ndr_heap_strdup(ndr_heap_t *heap, const char *s) 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); - out->length = smb_wcequiv_strlen(s); - out->allosize = out->length + sizeof (smb_wchar_t); + /* + * 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); @@ -207,20 +234,31 @@ ndr_heap_mstring(ndr_heap_t *heap, const char *s, ndr_mstring_t *out) void ndr_heap_mkvcs(ndr_heap_t *heap, char *s, ndr_vcstr_t *vc) { + size_t slen; int mlen; - vc->wclen = smb_wcequiv_strlen(s); - vc->wcsize = vc->wclen; + /* + * 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; - mlen = sizeof (ndr_vcs_t) + vc->wcsize + sizeof (smb_wchar_t); + 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 = vc->wclen / sizeof (smb_wchar_t); - (void) smb_mbstowcs((smb_wchar_t *)vc->vcs->buffer, s, - vc->vcs->vc_length_is); + vc->vcs->vc_length_is = slen; + (void) ndr__mbstowcs(vc->vcs->buffer, s, slen + 1); } } @@ -250,25 +288,8 @@ ndr_heap_mkvcb(ndr_heap_t *heap, uint8_t *data, uint32_t datalen, } /* - * Duplcate a SID in the heap. + * Removed ndr_heap_siddup(), now using ndr_heap_dupmem(). */ -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) diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c b/usr/src/lib/libmlrpc/common/ndr_marshal.c index a690dfb2e9..4d34030d2a 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c +++ b/usr/src/lib/libmlrpc/common/ndr_marshal.c @@ -20,14 +20,14 @@ */ /* * 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 <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> +#include <libmlrpc.h> #ifdef _BIG_ENDIAN static const int ndr_native_byte_order = NDR_REPLAB_INTG_BIG_ENDIAN; diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_ops.c b/usr/src/lib/libmlrpc/common/ndr_ops.c index 0cbcdc6e90..4ca1cb6295 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_ops.c +++ b/usr/src/lib/libmlrpc/common/ndr_ops.c @@ -49,8 +49,7 @@ #include <string.h> #include <assert.h> -#include <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> +#include <libmlrpc.h> #define NDOBUFSZ 128 diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c b/usr/src/lib/libmlrpc/common/ndr_process.c index 945b02e699..3188500a8b 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c +++ b/usr/src/lib/libmlrpc/common/ndr_process.c @@ -22,6 +22,7 @@ * 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. */ /* @@ -34,13 +35,11 @@ #include <strings.h> #include <assert.h> #include <string.h> +#include <stdio.h> #include <stdlib.h> -#include <smbsrv/libsmb.h> -#include <smbsrv/string.h> -#include <smbsrv/libmlrpc.h> - -#define NDR_STRING_MAX 4096 +#include <libmlrpc.h> +#include <ndr_wchar.h> #define NDR_IS_UNION(T) \ (((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_UNION) @@ -1210,17 +1209,22 @@ ndr_outer_string(ndr_ref_t *outer_ref) /* * size_is is the number of characters in the * (multibyte) string, including the null. + * In other words, symbols, not bytes. */ - size_is = smb_wcequiv_strlen(valp) / - sizeof (smb_wchar_t); - - if (!(nds->flags & NDS_F_NONULL)) - ++size_is; - - if (size_is > NDR_STRING_MAX) { + 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; @@ -1288,7 +1292,7 @@ ndr_outer_string(ndr_ref_t *outer_ref) * be nice to use mbequiv_strlen but the string * may not be null terminated. */ - n_alloc = (size_is + 1) * MTS_MB_CHAR_MAX; + n_alloc = (size_is + 1) * NDR_MB_CHAR_MAX; } else { n_alloc = (size_is + 1) * is_varlen; } @@ -1741,7 +1745,7 @@ ndr_inner_array(ndr_ref_t *encl_ref) myref.inner_flags = NDR_F_NONE; for (i = 0; i < n_elem; i++) { - (void) sprintf(name, "[%lu]", 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; @@ -1796,20 +1800,20 @@ ndr_inner_array(ndr_ref_t *encl_ref) 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(_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) +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; + ndr_stream_t *nds = ref->stream; char *valp = (char *)ref->datum; int rc; @@ -1854,7 +1858,7 @@ ndr_string_basic_integer(ndr_ref_t *encl_ref, ndr_typeinfo_t *type_under) myref.name = name; for (i = 0; i < NDR_STRING_MAX; i++) { - (void) sprintf(name, "[%lu]", i); + (void) snprintf(name, sizeof (name), "[%lu]", i); myref.pdu_offset = pdu_offset + i * size; valp = encl_ref->datum + i * size; myref.datum = valp; @@ -1897,27 +1901,27 @@ ndr_typeinfo_t ndt_s_wchar = { * 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. + * 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; - unsigned short wide_char; - char *valp; + char *valp = encl_ref->datum; ndr_ref_t myref; - unsigned long i; char name[30]; - int count; - int char_count = 0; + 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) { /* @@ -1930,59 +1934,60 @@ ndr_s_wchar(ndr_ref_t *encl_ref) } } + /* + * 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.datum = (char *)&wide_char; myref.name = name; myref.pdu_offset = encl_ref->pdu_offset; + myref.datum = (char *)wcs; + wlen = encl_ref->strlen_is; - 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; - } - } - + 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 (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; + /* + * 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); @@ -1997,51 +2002,20 @@ ndr_s_wchar(ndr_ref_t *encl_ref) * any terminating null wide character. Returns -1 if an invalid * multibyte character is encountered. */ +/* ARGSUSED */ size_t -ndr_mbstowcs(ndr_stream_t *nds, smb_wchar_t *wcs, const char *mbs, +ndr_mbstowcs(ndr_stream_t *nds, ndr_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); + size_t len; #ifdef _BIG_ENDIAN - if (nds == NULL || NDR_MODE_MATCH(nds, NDR_MODE_RETURN_SEND)) - *wcharp = BSWAP_16(*wcharp); + 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 (rc); + return (len); } diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c b/usr/src/lib/libmlrpc/common/ndr_server.c index 198daa7d55..4a1e2c177a 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c +++ b/usr/src/lib/libmlrpc/common/ndr_server.c @@ -36,9 +36,7 @@ #include <string.h> #include <thread.h> -#include <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> -#include <smbsrv/ntaccess.h> +#include <libmlrpc.h> #define NDR_PIPE_SEND(np, buf, len) \ ((np)->np_send)((np), (buf), (len)) @@ -132,42 +130,6 @@ out1: } /* - * 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. */ diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_svc.c b/usr/src/lib/libmlrpc/common/ndr_svc.c index d5c5f95f01..1e000a27f1 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_svc.c +++ b/usr/src/lib/libmlrpc/common/ndr_svc.c @@ -34,8 +34,7 @@ #include <strings.h> #include <assert.h> -#include <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> +#include <libmlrpc.h> /* diff --git a/usr/src/lib/libmlrpc/common/ndr_wchar.c b/usr/src/lib/libmlrpc/common/ndr_wchar.c new file mode 100644 index 0000000000..81886f3250 --- /dev/null +++ b/usr/src/lib/libmlrpc/common/ndr_wchar.c @@ -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); +} diff --git a/usr/src/lib/libmlrpc/common/ndr_wchar.h b/usr/src/lib/libmlrpc/common/ndr_wchar.h new file mode 100644 index 0000000000..e5fe8a1054 --- /dev/null +++ b/usr/src/lib/libmlrpc/common/ndr_wchar.h @@ -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 */ diff --git a/usr/src/uts/common/smbsrv/ndl/ndrtypes.ndl b/usr/src/lib/libmlrpc/common/ndrtypes.ndl index 16bb4b8135..b7d5fdb716 100644 --- a/usr/src/uts/common/smbsrv/ndl/ndrtypes.ndl +++ b/usr/src/lib/libmlrpc/common/ndrtypes.ndl @@ -21,10 +21,17 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ -#ifndef _NDR_TYPES_NDL_ -#define _NDR_TYPES_NDL_ +#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 @@ -69,20 +76,6 @@ #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 */ @@ -116,7 +109,7 @@ /* * When not using ndrgen, get BYTE, WORD, DWORD definitions from wintypes.h. */ -#include <smbsrv/wintypes.h> +#include <smb/wintypes.h> #define EXTERNTYPEINFO(TYPE) extern struct ndr_typeinfo TYPEINFO(TYPE); @@ -167,4 +160,18 @@ #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_ */ +/* + * 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_ */ diff --git a/usr/src/uts/common/smbsrv/ndl/rpcpdu.ndl b/usr/src/lib/libmlrpc/common/rpcpdu.ndl index f1ea15cf00..f1ea15cf00 100644 --- a/usr/src/uts/common/smbsrv/ndl/rpcpdu.ndl +++ b/usr/src/lib/libmlrpc/common/rpcpdu.ndl diff --git a/usr/src/lib/smbsrv/libmlrpc/i386/Makefile b/usr/src/lib/libmlrpc/i386/Makefile index 710c9eb3dd..6589e9941a 100644 --- a/usr/src/lib/smbsrv/libmlrpc/i386/Makefile +++ b/usr/src/lib/libmlrpc/i386/Makefile @@ -22,11 +22,7 @@ # 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) diff --git a/usr/src/lib/smbsrv/libmlrpc/sparc/Makefile b/usr/src/lib/libmlrpc/sparc/Makefile index 710c9eb3dd..6589e9941a 100644 --- a/usr/src/lib/smbsrv/libmlrpc/sparc/Makefile +++ b/usr/src/lib/libmlrpc/sparc/Makefile @@ -22,11 +22,7 @@ # 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) diff --git a/usr/src/lib/smbsrv/libmlrpc/sparcv9/Makefile b/usr/src/lib/libmlrpc/sparcv9/Makefile index b3c4916b0c..087f0e1107 100644 --- a/usr/src/lib/smbsrv/libmlrpc/sparcv9/Makefile +++ b/usr/src/lib/libmlrpc/sparcv9/Makefile @@ -22,14 +22,10 @@ # 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) +include ../../Makefile.lib.64 install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/libsmbfs/Makefile.com b/usr/src/lib/libsmbfs/Makefile.com index 0521eba951..8f8b118128 100644 --- a/usr/src/lib/libsmbfs/Makefile.com +++ b/usr/src/lib/libsmbfs/Makefile.com @@ -59,7 +59,6 @@ OBJ_LIB=\ nb_ssn.o \ nbns_rq.o \ negprot.o \ - netshareenum.o \ newvc.o \ nls.o \ ntlm.o \ diff --git a/usr/src/lib/libsmbfs/netsmb/smb_netshareenum.h b/usr/src/lib/libsmbfs/netsmb/smb_netshareenum.h deleted file mode 100644 index 14f2594df7..0000000000 --- a/usr/src/lib/libsmbfs/netsmb/smb_netshareenum.h +++ /dev/null @@ -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_ */ diff --git a/usr/src/lib/libsmbfs/netsmb/smbfs_api.h b/usr/src/lib/libsmbfs/netsmb/smbfs_api.h index 8436318b4c..b1f4b1e198 100644 --- a/usr/src/lib/libsmbfs/netsmb/smbfs_api.h +++ b/usr/src/lib/libsmbfs/netsmb/smbfs_api.h @@ -140,8 +140,8 @@ typedef void (*smb_ctx_close_hook_t)(struct smb_ctx *); void smb_ctx_set_close_hook(smb_ctx_close_hook_t); int smb_fh_close(int); int smb_fh_open(struct smb_ctx *ctx, const char *, int); -int smb_fh_read(int, off_t, size_t, char *); -int smb_fh_write(int, off_t, size_t, const char *); +int smb_fh_read(int, off64_t, size_t, char *); +int smb_fh_write(int, off64_t, size_t, const char *); int smb_fh_xactnp(int, int, const char *, int *, char *, int *); int smb_fh_getssnkey(int, uchar_t *, size_t); diff --git a/usr/src/lib/libsmbfs/smb/file.c b/usr/src/lib/libsmbfs/smb/file.c index 1c09532d61..8ca9d2cee1 100644 --- a/usr/src/lib/libsmbfs/smb/file.c +++ b/usr/src/lib/libsmbfs/smb/file.c @@ -204,7 +204,7 @@ smb_fh_open(struct smb_ctx *ctx, const char *path, int oflag) } int -smb_fh_read(int fd, off_t offset, size_t count, +smb_fh_read(int fd, off64_t offset, size_t count, char *dst) { struct smbioc_rw rwrq; @@ -221,7 +221,7 @@ smb_fh_read(int fd, off_t offset, size_t count, } int -smb_fh_write(int fd, off_t offset, size_t count, +smb_fh_write(int fd, off64_t offset, size_t count, const char *src) { struct smbioc_rw rwrq; diff --git a/usr/src/lib/libsmbfs/smb/llib-lsmbfs b/usr/src/lib/libsmbfs/smb/llib-lsmbfs index 1096482541..7459db63be 100644 --- a/usr/src/lib/libsmbfs/smb/llib-lsmbfs +++ b/usr/src/lib/libsmbfs/smb/llib-lsmbfs @@ -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> diff --git a/usr/src/lib/libsmbfs/smb/mapfile-vers b/usr/src/lib/libsmbfs/smb/mapfile-vers index 24bffec63d..68b38f46ed 100644 --- a/usr/src/lib/libsmbfs/smb/mapfile-vers +++ b/usr/src/lib/libsmbfs/smb/mapfile-vers @@ -111,7 +111,6 @@ SYMBOL_VERSION SUNWprivate { smb_iod_start; smb_iod_work; smb_lib_init; - smb_netshareenum; # will move to libnetapi smb_open_printer; smb_open_rcfile; smb_simplecrypt; diff --git a/usr/src/lib/libsmbfs/smb/netshareenum.c b/usr/src/lib/libsmbfs/smb/netshareenum.c deleted file mode 100644 index af5a0bb9bd..0000000000 --- a/usr/src/lib/libsmbfs/smb/netshareenum.c +++ /dev/null @@ -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); -} diff --git a/usr/src/lib/smbsrv/Makefile b/usr/src/lib/smbsrv/Makefile index 4213133a56..68353f10fe 100644 --- a/usr/src/lib/smbsrv/Makefile +++ b/usr/src/lib/smbsrv/Makefile @@ -29,14 +29,12 @@ include ../Makefile.lib SUBDIRS = \ libfksmbsrv \ libmlsvc \ - libmlrpc \ libsmb \ libsmbns \ libsmbrp include ./Makefile.subdirs -libmlrpc: libsmb libsmbns: libsmb -libmlsvc: libsmb libmlrpc libsmbns +libmlsvc: libsmb libsmbns libfksmbsrv: libsmb diff --git a/usr/src/lib/smbsrv/Makefile.targ b/usr/src/lib/smbsrv/Makefile.targ index 92a05ef243..9305212b3c 100644 --- a/usr/src/lib/smbsrv/Makefile.targ +++ b/usr/src/lib/smbsrv/Makefile.targ @@ -22,19 +22,22 @@ # 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 # %_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) diff --git a/usr/src/lib/smbsrv/libmlrpc/Makefile b/usr/src/lib/smbsrv/libmlrpc/Makefile deleted file mode 100644 index c5a61203cd..0000000000 --- a/usr/src/lib/smbsrv/libmlrpc/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 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 diff --git a/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c b/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c index 02b57b9328..f77c0bdf01 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c @@ -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> diff --git a/usr/src/lib/smbsrv/libmlsvc/common/dssetup_svc.c b/usr/src/lib/smbsrv/libmlsvc/common/dssetup_svc.c index 07986c2c93..24b999e7c3 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/dssetup_svc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/dssetup_svc.c @@ -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> diff --git a/usr/src/lib/smbsrv/libmlsvc/common/eventlog_svc.c b/usr/src/lib/smbsrv/libmlsvc/common/eventlog_svc.c index 34438c6cae..35f9c856e9 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/eventlog_svc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/eventlog_svc.c @@ -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> diff --git a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h index 381a2ea98c..838353b8e9 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h +++ b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h @@ -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 @@ typedef struct ms_luid { } 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 @@ int srvsvc_net_remote_tod(char *, char *, struct timeval *, struct tm *); * 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 diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lsar_clnt.c b/usr/src/lib/smbsrv/libmlsvc/common/lsar_clnt.c index eeab7745f2..7524e2db55 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/lsar_clnt.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/lsar_clnt.c @@ -383,7 +383,6 @@ lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_account_t *info) lsar_lookup_names1 }; - const srvsvc_server_info_t *svinfo; lsa_names_t names; char *p; uint32_t length; @@ -396,20 +395,15 @@ lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_account_t *info) 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; - - if (strcasecmp(p, "administrator") == 0) - name = 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; } length = smb_wcequiv_strlen(name); @@ -418,17 +412,12 @@ lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_account_t *info) 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 @@ lsar_lookup_sids(mlsvc_handle_t *lsa_handle, smb_sid_t *sid, 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 @@ lsar_lookup_priv_value(mlsvc_handle_t *lsa_handle, char *name, (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; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lsar_svc.c b/usr/src/lib/smbsrv/libmlsvc/common/lsar_svc.c index 3864260e2c..28d5e73948 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/lsar_svc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/lsar_svc.c @@ -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> diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc.h b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc.h index dcf2c5f0e7..2afc62a02d 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc.h +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc.h @@ -46,7 +46,6 @@ void netr_initialize(void); 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 @@ int netr_setup_authenticator(struct netr_info *, struct netr_authenticator *, 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 *); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c index ef3ca34bcd..c8879837b1 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c @@ -31,32 +31,22 @@ #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 @@ -71,13 +61,15 @@ static void ndr_xa_release(ndr_client_t *); * 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 @@ ndr_rpc_bind(mlsvc_handle_t *handle, char *server, char *domain, 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 @@ ndr_rpc_bind(mlsvc_handle_t *handle, char *server, char *domain, 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,296 +112,82 @@ ndr_rpc_bind(mlsvc_handle_t *handle, char *server, char *domain, "(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; - } - 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; + 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); + } } /* - * 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); - } - - 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); + ctx = mlrpc_clh_free(handle); + if (ctx != NULL) { + smbrdr_ctx_free(ctx); + } } return (status); } /* - * Unbind and close the pipe to an RPC service. - * - * 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. + * Unbind and close the pipe to an RPC service + * and cleanup the smb_ctx. * - * 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) { @@ -456,193 +218,3 @@ ndr_rpc_status(mlsvc_handle_t *handle, int opnum, DWORD status) 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)); - } -} diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c index 794e6c9576..cdb6478f5b 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c @@ -111,7 +111,7 @@ mlsvc_timecheck(void *arg) 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); } diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c index ad3565699b..b46cf99f87 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c @@ -425,3 +425,43 @@ mlsvc_disconnect(const char *server) { 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); +} diff --git a/usr/src/lib/smbsrv/libmlsvc/common/msgsvc_svc.c b/usr/src/lib/smbsrv/libmlsvc/common/msgsvc_svc.c index 78538e6291..b49a3946ad 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/msgsvc_svc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/msgsvc_svc.c @@ -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> diff --git a/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c b/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c index ea31c935ed..2b22744304 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c @@ -191,6 +191,10 @@ netr_server_req_challenge(mlsvc_handle_t *netr_handle, netr_info_t *netr_info) return (0); } +uint32_t netr_server_auth2_flags = + NETR_NEGOTIATE_BASE_FLAGS | + NETR_NEGOTIATE_STRONGKEY_FLAG; + /* * netr_server_authenticate2 */ @@ -216,10 +220,9 @@ netr_server_authenticate2(mlsvc_handle_t *netr_handle, netr_info_t *netr_info) 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 { diff --git a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c index ab99db75f8..6fdd3a9ca4 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c @@ -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> diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samr_clnt.c b/usr/src/lib/smbsrv/libmlsvc/common/samr_clnt.c index 289e8470cf..dd15469c15 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/samr_clnt.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/samr_clnt.c @@ -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> diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c b/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c index 8835a8e00f..43ae0568e9 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c @@ -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> diff --git a/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c b/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c index ba1c9caece..302c7fb278 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c @@ -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> diff --git a/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_clnt.c b/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_clnt.c index def8ced54a..c7e5d60a6b 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_clnt.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_clnt.c @@ -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 @@ srvsvc_net_connect_enum(char *server, char *domain, char *netname, int level) } /* - * 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; + + if (srvsvc_net_remote_tod(server, domain, &dc_tv, &dc_tm) < 0) { + syslog(LOG_DEBUG, "srvsvc_net_remote_tod failed"); + return; + } - smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); + tnow = time(NULL); - if (srvsvc_open(server, domain, user, &handle) != 0) - return (-1); + if (tnow > dc_tv.tv_sec) + tdiff = (tnow - dc_tv.tv_sec) / SECSPERMIN; + else + tdiff = (dc_tv.tv_sec - tnow) / SECSPERMIN; - opnum = SRVSVC_OPNUM_NetServerGetInfo; - bzero(&arg, sizeof (arg)); + if (tdiff != 0) { + (void) strlcpy(hostname, "localhost", MAXHOSTNAMELEN); + (void) gethostname(hostname, MAXHOSTNAMELEN); - len = strlen(server) + 4; - arg.servername = ndr_rpc_malloc(&handle, len); - if (arg.servername == NULL) - return (-1); + priority = (tdiff > 2) ? LOG_NOTICE : LOG_DEBUG; + syslog(priority, "DC [%s] clock skew detected: %u minutes", + server, tdiff); - (void) snprintf((char *)arg.servername, len, "\\\\%s", server); - arg.level = 101; - - 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); } /* @@ -544,39 +526,3 @@ srvsvc_net_remote_tod(char *server, char *domain, struct timeval *tv, 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); -} diff --git a/usr/src/lib/smbsrv/libsmb/common/libsmb.h b/usr/src/lib/smbsrv/libsmb/common/libsmb.h index fdda80dc2a..82d6bc1cc3 100644 --- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h +++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h @@ -44,17 +44,18 @@ extern "C" { #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> diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c b/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c index e51f8bbca1..dfbbfd0483 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c @@ -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); diff --git a/usr/src/pkg/manifests/driver-storage-mpt_sas.mf b/usr/src/pkg/manifests/driver-storage-mpt_sas.mf index ae55dc9422..c0506e3307 100644 --- a/usr/src/pkg/manifests/driver-storage-mpt_sas.mf +++ b/usr/src/pkg/manifests/driver-storage-mpt_sas.mf @@ -71,8 +71,25 @@ driver name=mpt_sas class=scsi-self-identifying \ alias=pciex1000,95 \ alias=pciex1000,96 \ alias=pciex1000,97 \ + alias=pciex1000,aa \ + alias=pciex1000,ab \ + alias=pciex1000,ac \ + alias=pciex1000,ad \ + alias=pciex1000,ae \ + alias=pciex1000,af \ + alias=pciex1000,c0 \ + alias=pciex1000,c1 \ + alias=pciex1000,c2 \ + alias=pciex1000,c3 \ alias=pciex1000,c4 \ - alias=pciex1000,c9 + alias=pciex1000,c5 \ + alias=pciex1000,c6 \ + alias=pciex1000,c7 \ + alias=pciex1000,c8 \ + alias=pciex1000,c9 \ + alias=pciex1000,d0 \ + alias=pciex1000,d1 \ + alias=pciex1000,d2 file path=kernel/drv/$(ARCH64)/mpt_sas group=sys file path=kernel/drv/mpt_sas.conf group=sys \ original_name=SUNWmptsas:kernel/drv/mpt_sas.conf preserve=true @@ -81,3 +98,5 @@ legacy pkg=SUNWmptsas desc="LSI MPT SAS 2.0/2.5 Controller HBA Driver" \ name="LSI MPT SAS 2.0/2.5 Controller HBA Driver" license cr_Sun license=cr_Sun license lic_CDDL license=lic_CDDL +license usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE \ + license=usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE diff --git a/usr/src/pkg/manifests/service-file-system-smb.mf b/usr/src/pkg/manifests/service-file-system-smb.mf index 4b349a26bc..ba5dedcd6d 100644 --- a/usr/src/pkg/manifests/service-file-system-smb.mf +++ b/usr/src/pkg/manifests/service-file-system-smb.mf @@ -83,7 +83,6 @@ file path=usr/lib/smbsrv/dtrace/smbd-pipesvc.d mode=0555 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 cr_Sun license=cr_Sun 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 diff --git a/usr/src/pkg/manifests/system-file-system-smb.mf b/usr/src/pkg/manifests/system-file-system-smb.mf index b68191317a..b5ff30e5ad 100644 --- a/usr/src/pkg/manifests/system-file-system-smb.mf +++ b/usr/src/pkg/manifests/system-file-system-smb.mf @@ -79,6 +79,7 @@ file path=usr/lib/fs/smbfs/mount mode=4555 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 diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_config_changed.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_config_changed.ksh index 7b5870b8d6..1e86a66b7c 100644 --- a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_config_changed.ksh +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_config_changed.ksh @@ -12,7 +12,7 @@ # # -# Copyright (c) 2017 by Delphix. All rights reserved. +# Copyright (c) 2016, 2018 by Delphix. All rights reserved. # . $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib @@ -49,6 +49,7 @@ function custom_cleanup set_vdev_validate_skip 0 cleanup log_must mdb_ctf_set_int vdev_min_ms_count 0t16 + log_must mdb_ctf_set_int spa_allocators 0t4 } log_onexit custom_cleanup @@ -207,6 +208,10 @@ increase_device_sizes $(( FILE_SIZE * 4 )) # reduce the chance of reusing a metaslab that holds old MOS metadata. log_must mdb_ctf_set_int vdev_min_ms_count 0t150 +# Decrease the number of allocators for pools created during this test, +# to increase the odds that metadata survives from old txgs. +log_must mdb_ctf_set_int spa_allocators 0t1 + # Part of the rewind test is to see how it reacts to path changes typeset pathstochange="$VDEV0 $VDEV1 $VDEV2 $VDEV3" diff --git a/usr/src/test/zfs-tests/tests/functional/slog/slog_014_pos.ksh b/usr/src/test/zfs-tests/tests/functional/slog/slog_014_pos.ksh index b9dbc6c97e..621ac23aa9 100644 --- a/usr/src/test/zfs-tests/tests/functional/slog/slog_014_pos.ksh +++ b/usr/src/test/zfs-tests/tests/functional/slog/slog_014_pos.ksh @@ -26,7 +26,7 @@ # # -# Copyright (c) 2013, 2016 by Delphix. All rights reserved. +# Copyright (c) 2013, 2018 by Delphix. All rights reserved. # . $STF_SUITE/tests/functional/slog/slog.kshlib @@ -52,9 +52,19 @@ do log_must zpool create $TESTPOOL $type $VDEV $spare $SDEV \ log $LDEV + # Create a file to be corrupted + dd if=/dev/urandom of=/$TESTPOOL/filler bs=1024k count=50 + + # + # Ensure the file has been synced out before attempting to + # corrupt its contents. + # + sync + + # # Corrupt a pool device to make the pool DEGRADED - dd if=/dev/urandom of=/$TESTPOOL/filler bs=1024k count=50 # The oseek value below is to skip past the vdev label. + # log_must dd if=/dev/urandom of=$VDIR/a bs=1024k oseek=4 \ conv=notrunc count=50 log_must zpool scrub $TESTPOOL diff --git a/usr/src/tools/ndrgen/ndrgen.sh b/usr/src/tools/ndrgen/ndrgen.sh index c74253b6d2..19dbb9f8e5 100644 --- a/usr/src/tools/ndrgen/ndrgen.sh +++ b/usr/src/tools/ndrgen/ndrgen.sh @@ -19,16 +19,24 @@ # # 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` @@ -38,60 +46,61 @@ ndrgen_usage() 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 -fi - -if [[ $CC = "" ]] ; then - ndrgen_usage "C pre-processor is not defined" +if [[ $# -lt 1 ]] ; then + ndrgen_usage fi -if [ ! -f $CC ] || [ ! -x $CC ] ; then - ndrgen_usage "cannot run $CC" +if [ ! -x $CPP ] ; then + ndrgen_usage "cannot run $CPP" fi for i @@ -101,36 +110,9 @@ do 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 diff --git a/usr/src/tools/quick/make-smbclnt b/usr/src/tools/quick/make-smbclnt new file mode 100755 index 0000000000..1b65f50a71 --- /dev/null +++ b/usr/src/tools/quick/make-smbclnt @@ -0,0 +1,304 @@ +#!/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 smb headers to be safe + (cd $SRC/uts/common/smb && $make -k install_h) + +fi + +# Need some library headers too... +for lib in \ + libcryptoutil \ + libmlrpc \ + 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.2 +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 diff --git a/usr/src/tools/quick/make-smbsrv b/usr/src/tools/quick/make-smbsrv index e808bffee2..18c1baddcf 100755 --- a/usr/src/tools/quick/make-smbsrv +++ b/usr/src/tools/quick/make-smbsrv @@ -107,8 +107,9 @@ for lib in \ libdevid \ libfakekernel \ libgss \ - libkrb5 \ libidmap \ + libkrb5 \ + libmlrpc \ libpam \ libsec \ libscf \ @@ -164,7 +165,8 @@ do_lib2() { for lib in \ libfakekernel \ libads \ - libsmbfs + libsmbfs \ + libmlrpc do (cd $SRC/lib/$lib && $make $1) done @@ -287,7 +289,7 @@ usr/lib/mdb/kvm/$arch64/smbsrv.so 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.2 usr/lib/smbsrv/libmlsvc.so.1 usr/lib/smbsrv/libsmb.so.1 usr/lib/smbsrv/libsmbns.so.1 diff --git a/usr/src/uts/common/fs/zfs/metaslab.c b/usr/src/uts/common/fs/zfs/metaslab.c index 82ca2d6cbf..1f5a7fbd26 100644 --- a/usr/src/uts/common/fs/zfs/metaslab.c +++ b/usr/src/uts/common/fs/zfs/metaslab.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2015 by Delphix. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. * Copyright (c) 2014 Integros [integros.com] */ @@ -217,6 +217,8 @@ static uint64_t metaslab_weight(metaslab_t *); static void metaslab_set_fragmentation(metaslab_t *); static void metaslab_free_impl(vdev_t *, uint64_t, uint64_t, boolean_t); static void metaslab_check_free_impl(vdev_t *, uint64_t, uint64_t); +static void metaslab_passivate(metaslab_t *msp, uint64_t weight); +static uint64_t metaslab_weight_from_range_tree(metaslab_t *msp); kmem_cache_t *metaslab_alloc_trace_cache; @@ -236,7 +238,12 @@ metaslab_class_create(spa_t *spa, metaslab_ops_t *ops) mc->mc_rotor = NULL; mc->mc_ops = ops; mutex_init(&mc->mc_lock, NULL, MUTEX_DEFAULT, NULL); - refcount_create_tracked(&mc->mc_alloc_slots); + mc->mc_alloc_slots = kmem_zalloc(spa->spa_alloc_count * + sizeof (refcount_t), KM_SLEEP); + mc->mc_alloc_max_slots = kmem_zalloc(spa->spa_alloc_count * + sizeof (uint64_t), KM_SLEEP); + for (int i = 0; i < spa->spa_alloc_count; i++) + refcount_create_tracked(&mc->mc_alloc_slots[i]); return (mc); } @@ -250,7 +257,12 @@ metaslab_class_destroy(metaslab_class_t *mc) ASSERT(mc->mc_space == 0); ASSERT(mc->mc_dspace == 0); - refcount_destroy(&mc->mc_alloc_slots); + for (int i = 0; i < mc->mc_spa->spa_alloc_count; i++) + refcount_destroy(&mc->mc_alloc_slots[i]); + kmem_free(mc->mc_alloc_slots, mc->mc_spa->spa_alloc_count * + sizeof (refcount_t)); + kmem_free(mc->mc_alloc_max_slots, mc->mc_spa->spa_alloc_count * + sizeof (uint64_t)); mutex_destroy(&mc->mc_lock); kmem_free(mc, sizeof (metaslab_class_t)); } @@ -447,6 +459,30 @@ metaslab_compare(const void *x1, const void *x2) const metaslab_t *m1 = x1; const metaslab_t *m2 = x2; + int sort1 = 0; + int sort2 = 0; + if (m1->ms_allocator != -1 && m1->ms_primary) + sort1 = 1; + else if (m1->ms_allocator != -1 && !m1->ms_primary) + sort1 = 2; + if (m2->ms_allocator != -1 && m2->ms_primary) + sort2 = 1; + else if (m2->ms_allocator != -1 && !m2->ms_primary) + sort2 = 2; + + /* + * Sort inactive metaslabs first, then primaries, then secondaries. When + * selecting a metaslab to allocate from, an allocator first tries its + * primary, then secondary active metaslab. If it doesn't have active + * metaslabs, or can't allocate from them, it searches for an inactive + * metaslab to activate. If it can't find a suitable one, it will steal + * a primary or secondary metaslab from another allocator. + */ + if (sort1 < sort2) + return (-1); + if (sort1 > sort2) + return (1); + if (m1->ms_weight < m2->ms_weight) return (1); if (m1->ms_weight > m2->ms_weight) @@ -598,12 +634,16 @@ metaslab_group_alloc_update(metaslab_group_t *mg) } metaslab_group_t * -metaslab_group_create(metaslab_class_t *mc, vdev_t *vd) +metaslab_group_create(metaslab_class_t *mc, vdev_t *vd, int allocators) { metaslab_group_t *mg; mg = kmem_zalloc(sizeof (metaslab_group_t), KM_SLEEP); mutex_init(&mg->mg_lock, NULL, MUTEX_DEFAULT, NULL); + mg->mg_primaries = kmem_zalloc(allocators * sizeof (metaslab_t *), + KM_SLEEP); + mg->mg_secondaries = kmem_zalloc(allocators * sizeof (metaslab_t *), + KM_SLEEP); avl_create(&mg->mg_metaslab_tree, metaslab_compare, sizeof (metaslab_t), offsetof(struct metaslab, ms_group_node)); mg->mg_vd = vd; @@ -611,7 +651,16 @@ metaslab_group_create(metaslab_class_t *mc, vdev_t *vd) mg->mg_activation_count = 0; mg->mg_initialized = B_FALSE; mg->mg_no_free_space = B_TRUE; - refcount_create_tracked(&mg->mg_alloc_queue_depth); + mg->mg_allocators = allocators; + + mg->mg_alloc_queue_depth = kmem_zalloc(allocators * sizeof (refcount_t), + KM_SLEEP); + mg->mg_cur_max_alloc_queue_depth = kmem_zalloc(allocators * + sizeof (uint64_t), KM_SLEEP); + for (int i = 0; i < allocators; i++) { + refcount_create_tracked(&mg->mg_alloc_queue_depth[i]); + mg->mg_cur_max_alloc_queue_depth[i] = 0; + } mg->mg_taskq = taskq_create("metaslab_group_taskq", metaslab_load_pct, minclsyspri, 10, INT_MAX, TASKQ_THREADS_CPU_PCT); @@ -633,8 +682,20 @@ metaslab_group_destroy(metaslab_group_t *mg) taskq_destroy(mg->mg_taskq); avl_destroy(&mg->mg_metaslab_tree); + kmem_free(mg->mg_primaries, mg->mg_allocators * sizeof (metaslab_t *)); + kmem_free(mg->mg_secondaries, mg->mg_allocators * + sizeof (metaslab_t *)); mutex_destroy(&mg->mg_lock); - refcount_destroy(&mg->mg_alloc_queue_depth); + + for (int i = 0; i < mg->mg_allocators; i++) { + refcount_destroy(&mg->mg_alloc_queue_depth[i]); + mg->mg_cur_max_alloc_queue_depth[i] = 0; + } + kmem_free(mg->mg_alloc_queue_depth, mg->mg_allocators * + sizeof (refcount_t)); + kmem_free(mg->mg_cur_max_alloc_queue_depth, mg->mg_allocators * + sizeof (uint64_t)); + kmem_free(mg, sizeof (metaslab_group_t)); } @@ -713,6 +774,22 @@ metaslab_group_passivate(metaslab_group_t *mg) taskq_wait(mg->mg_taskq); spa_config_enter(spa, locks & ~(SCL_ZIO - 1), spa, RW_WRITER); metaslab_group_alloc_update(mg); + for (int i = 0; i < mg->mg_allocators; i++) { + metaslab_t *msp = mg->mg_primaries[i]; + if (msp != NULL) { + mutex_enter(&msp->ms_lock); + metaslab_passivate(msp, + metaslab_weight_from_range_tree(msp)); + mutex_exit(&msp->ms_lock); + } + msp = mg->mg_secondaries[i]; + if (msp != NULL) { + mutex_enter(&msp->ms_lock); + metaslab_passivate(msp, + metaslab_weight_from_range_tree(msp)); + mutex_exit(&msp->ms_lock); + } + } mgprev = mg->mg_prev; mgnext = mg->mg_next; @@ -853,6 +930,17 @@ metaslab_group_remove(metaslab_group_t *mg, metaslab_t *msp) } static void +metaslab_group_sort_impl(metaslab_group_t *mg, metaslab_t *msp, uint64_t weight) +{ + ASSERT(MUTEX_HELD(&mg->mg_lock)); + ASSERT(msp->ms_group == mg); + avl_remove(&mg->mg_metaslab_tree, msp); + msp->ms_weight = weight; + avl_add(&mg->mg_metaslab_tree, msp); + +} + +static void metaslab_group_sort(metaslab_group_t *mg, metaslab_t *msp, uint64_t weight) { /* @@ -863,10 +951,7 @@ metaslab_group_sort(metaslab_group_t *mg, metaslab_t *msp, uint64_t weight) ASSERT(MUTEX_HELD(&msp->ms_lock)); mutex_enter(&mg->mg_lock); - ASSERT(msp->ms_group == mg); - avl_remove(&mg->mg_metaslab_tree, msp); - msp->ms_weight = weight; - avl_add(&mg->mg_metaslab_tree, msp); + metaslab_group_sort_impl(mg, msp, weight); mutex_exit(&mg->mg_lock); } @@ -914,7 +999,7 @@ metaslab_group_fragmentation(metaslab_group_t *mg) */ static boolean_t metaslab_group_allocatable(metaslab_group_t *mg, metaslab_group_t *rotor, - uint64_t psize) + uint64_t psize, int allocator) { spa_t *spa = mg->mg_vd->vdev_spa; metaslab_class_t *mc = mg->mg_class; @@ -943,7 +1028,7 @@ metaslab_group_allocatable(metaslab_group_t *mg, metaslab_group_t *rotor, if (mg->mg_allocatable) { metaslab_group_t *mgp; int64_t qdepth; - uint64_t qmax = mg->mg_max_alloc_queue_depth; + uint64_t qmax = mg->mg_cur_max_alloc_queue_depth[allocator]; if (!mc->mc_alloc_throttle_enabled) return (B_TRUE); @@ -955,7 +1040,7 @@ metaslab_group_allocatable(metaslab_group_t *mg, metaslab_group_t *rotor, if (mg->mg_no_free_space) return (B_FALSE); - qdepth = refcount_count(&mg->mg_alloc_queue_depth); + qdepth = refcount_count(&mg->mg_alloc_queue_depth[allocator]); /* * If this metaslab group is below its qmax or it's @@ -974,9 +1059,10 @@ metaslab_group_allocatable(metaslab_group_t *mg, metaslab_group_t *rotor, * groups at the same time when we make this check. */ for (mgp = mg->mg_next; mgp != rotor; mgp = mgp->mg_next) { - qmax = mgp->mg_max_alloc_queue_depth; + qmax = mgp->mg_cur_max_alloc_queue_depth[allocator]; - qdepth = refcount_count(&mgp->mg_alloc_queue_depth); + qdepth = refcount_count( + &mgp->mg_alloc_queue_depth[allocator]); /* * If there is another metaslab group that @@ -1463,6 +1549,8 @@ metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object, uint64_t txg, ms->ms_id = id; ms->ms_start = id << vd->vdev_ms_shift; ms->ms_size = 1ULL << vd->vdev_ms_shift; + ms->ms_allocator = -1; + ms->ms_new = B_TRUE; /* * We only open space map objects that already exist. All others @@ -1558,6 +1646,7 @@ metaslab_fini(metaslab_t *msp) cv_destroy(&msp->ms_load_cv); mutex_destroy(&msp->ms_lock); mutex_destroy(&msp->ms_sync_lock); + ASSERT3U(msp->ms_allocator, ==, -1); kmem_free(msp, sizeof (metaslab_t)); } @@ -1954,19 +2043,59 @@ metaslab_weight(metaslab_t *msp) } static int -metaslab_activate(metaslab_t *msp, uint64_t activation_weight) +metaslab_activate_allocator(metaslab_group_t *mg, metaslab_t *msp, + int allocator, uint64_t activation_weight) +{ + /* + * If we're activating for the claim code, we don't want to actually + * set the metaslab up for a specific allocator. + */ + if (activation_weight == METASLAB_WEIGHT_CLAIM) + return (0); + metaslab_t **arr = (activation_weight == METASLAB_WEIGHT_PRIMARY ? + mg->mg_primaries : mg->mg_secondaries); + + ASSERT(MUTEX_HELD(&msp->ms_lock)); + mutex_enter(&mg->mg_lock); + if (arr[allocator] != NULL) { + mutex_exit(&mg->mg_lock); + return (EEXIST); + } + + arr[allocator] = msp; + ASSERT3S(msp->ms_allocator, ==, -1); + msp->ms_allocator = allocator; + msp->ms_primary = (activation_weight == METASLAB_WEIGHT_PRIMARY); + mutex_exit(&mg->mg_lock); + + return (0); +} + +static int +metaslab_activate(metaslab_t *msp, int allocator, uint64_t activation_weight) { ASSERT(MUTEX_HELD(&msp->ms_lock)); if ((msp->ms_weight & METASLAB_ACTIVE_MASK) == 0) { + int error = 0; metaslab_load_wait(msp); if (!msp->ms_loaded) { - int error = metaslab_load(msp); - if (error) { + if ((error = metaslab_load(msp)) != 0) { metaslab_group_sort(msp->ms_group, msp, 0); return (error); } } + if ((msp->ms_weight & METASLAB_ACTIVE_MASK) != 0) { + /* + * The metaslab was activated for another allocator + * while we were waiting, we should reselect. + */ + return (EBUSY); + } + if ((error = metaslab_activate_allocator(msp->ms_group, msp, + allocator, activation_weight)) != 0) { + return (error); + } msp->ms_activation_weight = msp->ms_weight; metaslab_group_sort(msp->ms_group, msp, @@ -1979,6 +2108,34 @@ metaslab_activate(metaslab_t *msp, uint64_t activation_weight) } static void +metaslab_passivate_allocator(metaslab_group_t *mg, metaslab_t *msp, + uint64_t weight) +{ + ASSERT(MUTEX_HELD(&msp->ms_lock)); + if (msp->ms_weight & METASLAB_WEIGHT_CLAIM) { + metaslab_group_sort(mg, msp, weight); + return; + } + + mutex_enter(&mg->mg_lock); + ASSERT3P(msp->ms_group, ==, mg); + if (msp->ms_primary) { + ASSERT3U(0, <=, msp->ms_allocator); + ASSERT3U(msp->ms_allocator, <, mg->mg_allocators); + ASSERT3P(mg->mg_primaries[msp->ms_allocator], ==, msp); + ASSERT(msp->ms_weight & METASLAB_WEIGHT_PRIMARY); + mg->mg_primaries[msp->ms_allocator] = NULL; + } else { + ASSERT(msp->ms_weight & METASLAB_WEIGHT_SECONDARY); + ASSERT3P(mg->mg_secondaries[msp->ms_allocator], ==, msp); + mg->mg_secondaries[msp->ms_allocator] = NULL; + } + msp->ms_allocator = -1; + metaslab_group_sort_impl(mg, msp, weight); + mutex_exit(&mg->mg_lock); +} + +static void metaslab_passivate(metaslab_t *msp, uint64_t weight) { uint64_t size = weight & ~METASLAB_WEIGHT_TYPE; @@ -1993,7 +2150,7 @@ metaslab_passivate(metaslab_t *msp, uint64_t weight) ASSERT0(weight & METASLAB_ACTIVE_MASK); msp->ms_activation_weight = 0; - metaslab_group_sort(msp->ms_group, msp, weight); + metaslab_passivate_allocator(msp->ms_group, msp, weight); ASSERT((msp->ms_weight & METASLAB_ACTIVE_MASK) == 0); } @@ -2550,11 +2707,18 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg) vdev_dirty(vd, VDD_METASLAB, msp, txg + 1); } + if (msp->ms_new) { + msp->ms_new = B_FALSE; + mutex_enter(&mg->mg_lock); + mg->mg_ms_ready++; + mutex_exit(&mg->mg_lock); + } /* * Calculate the new weights before unloading any metaslabs. * This will give us the most accurate weighting. */ - metaslab_group_sort(mg, msp, metaslab_weight(msp)); + metaslab_group_sort(mg, msp, metaslab_weight(msp) | + (msp->ms_weight & METASLAB_ACTIVE_MASK)); /* * If the metaslab is loaded and we've not tried to load or allocate @@ -2566,6 +2730,10 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg) VERIFY0(range_tree_space( msp->ms_allocating[(txg + t) & TXG_MASK])); } + if (msp->ms_allocator != -1) { + metaslab_passivate(msp, msp->ms_weight & + ~METASLAB_ACTIVE_MASK); + } if (!metaslab_debug_unload) metaslab_unload(msp); @@ -2659,7 +2827,8 @@ metaslab_alloc_trace_fini(void) */ static void metaslab_trace_add(zio_alloc_list_t *zal, metaslab_group_t *mg, - metaslab_t *msp, uint64_t psize, uint32_t dva_id, uint64_t offset) + metaslab_t *msp, uint64_t psize, uint32_t dva_id, uint64_t offset, + int allocator) { if (!metaslab_trace_enabled) return; @@ -2692,6 +2861,7 @@ metaslab_trace_add(zio_alloc_list_t *zal, metaslab_group_t *mg, mat->mat_dva_id = dva_id; mat->mat_offset = offset; mat->mat_weight = 0; + mat->mat_allocator = allocator; if (msp != NULL) mat->mat_weight = msp->ms_weight; @@ -2732,35 +2902,56 @@ metaslab_trace_fini(zio_alloc_list_t *zal) */ static void -metaslab_group_alloc_increment(spa_t *spa, uint64_t vdev, void *tag, int flags) +metaslab_group_alloc_increment(spa_t *spa, uint64_t vdev, void *tag, int flags, + int allocator) { if (!(flags & METASLAB_ASYNC_ALLOC) || - flags & METASLAB_DONT_THROTTLE) + (flags & METASLAB_DONT_THROTTLE)) return; metaslab_group_t *mg = vdev_lookup_top(spa, vdev)->vdev_mg; if (!mg->mg_class->mc_alloc_throttle_enabled) return; - (void) refcount_add(&mg->mg_alloc_queue_depth, tag); + (void) refcount_add(&mg->mg_alloc_queue_depth[allocator], tag); +} + +static void +metaslab_group_increment_qdepth(metaslab_group_t *mg, int allocator) +{ + uint64_t max = mg->mg_max_alloc_queue_depth; + uint64_t cur = mg->mg_cur_max_alloc_queue_depth[allocator]; + while (cur < max) { + if (atomic_cas_64(&mg->mg_cur_max_alloc_queue_depth[allocator], + cur, cur + 1) == cur) { + atomic_inc_64( + &mg->mg_class->mc_alloc_max_slots[allocator]); + return; + } + cur = mg->mg_cur_max_alloc_queue_depth[allocator]; + } } void -metaslab_group_alloc_decrement(spa_t *spa, uint64_t vdev, void *tag, int flags) +metaslab_group_alloc_decrement(spa_t *spa, uint64_t vdev, void *tag, int flags, + int allocator, boolean_t io_complete) { if (!(flags & METASLAB_ASYNC_ALLOC) || - flags & METASLAB_DONT_THROTTLE) + (flags & METASLAB_DONT_THROTTLE)) return; metaslab_group_t *mg = vdev_lookup_top(spa, vdev)->vdev_mg; if (!mg->mg_class->mc_alloc_throttle_enabled) return; - (void) refcount_remove(&mg->mg_alloc_queue_depth, tag); + (void) refcount_remove(&mg->mg_alloc_queue_depth[allocator], tag); + if (io_complete) + metaslab_group_increment_qdepth(mg, allocator); } void -metaslab_group_alloc_verify(spa_t *spa, const blkptr_t *bp, void *tag) +metaslab_group_alloc_verify(spa_t *spa, const blkptr_t *bp, void *tag, + int allocator) { #ifdef ZFS_DEBUG const dva_t *dva = bp->blk_dva; @@ -2769,7 +2960,8 @@ metaslab_group_alloc_verify(spa_t *spa, const blkptr_t *bp, void *tag) for (int d = 0; d < ndvas; d++) { uint64_t vdev = DVA_GET_VDEV(&dva[d]); metaslab_group_t *mg = vdev_lookup_top(spa, vdev)->vdev_mg; - VERIFY(refcount_not_held(&mg->mg_alloc_queue_depth, tag)); + VERIFY(refcount_not_held(&mg->mg_alloc_queue_depth[allocator], + tag)); } #endif } @@ -2811,91 +3003,146 @@ metaslab_block_alloc(metaslab_t *msp, uint64_t size, uint64_t txg) return (start); } +/* + * Find the metaslab with the highest weight that is less than what we've + * already tried. In the common case, this means that we will examine each + * metaslab at most once. Note that concurrent callers could reorder metaslabs + * by activation/passivation once we have dropped the mg_lock. If a metaslab is + * activated by another thread, and we fail to allocate from the metaslab we + * have selected, we may not try the newly-activated metaslab, and instead + * activate another metaslab. This is not optimal, but generally does not cause + * any problems (a possible exception being if every metaslab is completely full + * except for the the newly-activated metaslab which we fail to examine). + */ +static metaslab_t * +find_valid_metaslab(metaslab_group_t *mg, uint64_t activation_weight, + dva_t *dva, int d, uint64_t min_distance, uint64_t asize, int allocator, + zio_alloc_list_t *zal, metaslab_t *search, boolean_t *was_active) +{ + avl_index_t idx; + avl_tree_t *t = &mg->mg_metaslab_tree; + metaslab_t *msp = avl_find(t, search, &idx); + if (msp == NULL) + msp = avl_nearest(t, idx, AVL_AFTER); + + for (; msp != NULL; msp = AVL_NEXT(t, msp)) { + int i; + if (!metaslab_should_allocate(msp, asize)) { + metaslab_trace_add(zal, mg, msp, asize, d, + TRACE_TOO_SMALL, allocator); + continue; + } + + /* + * If the selected metaslab is condensing, skip it. + */ + if (msp->ms_condensing) + continue; + + *was_active = msp->ms_allocator != -1; + /* + * If we're activating as primary, this is our first allocation + * from this disk, so we don't need to check how close we are. + * If the metaslab under consideration was already active, + * we're getting desperate enough to steal another allocator's + * metaslab, so we still don't care about distances. + */ + if (activation_weight == METASLAB_WEIGHT_PRIMARY || *was_active) + break; + + uint64_t target_distance = min_distance + + (space_map_allocated(msp->ms_sm) != 0 ? 0 : + min_distance >> 1); + + for (i = 0; i < d; i++) { + if (metaslab_distance(msp, &dva[i]) < target_distance) + break; + } + if (i == d) + break; + } + + if (msp != NULL) { + search->ms_weight = msp->ms_weight; + search->ms_start = msp->ms_start + 1; + search->ms_allocator = msp->ms_allocator; + search->ms_primary = msp->ms_primary; + } + return (msp); +} + +/* ARGSUSED */ static uint64_t metaslab_group_alloc_normal(metaslab_group_t *mg, zio_alloc_list_t *zal, - uint64_t asize, uint64_t txg, uint64_t min_distance, dva_t *dva, int d) + uint64_t asize, uint64_t txg, uint64_t min_distance, dva_t *dva, int d, + int allocator) { metaslab_t *msp = NULL; uint64_t offset = -1ULL; uint64_t activation_weight; - uint64_t target_distance; - int i; + boolean_t tertiary = B_FALSE; activation_weight = METASLAB_WEIGHT_PRIMARY; - for (i = 0; i < d; i++) { - if (DVA_GET_VDEV(&dva[i]) == mg->mg_vd->vdev_id) { + for (int i = 0; i < d; i++) { + if (activation_weight == METASLAB_WEIGHT_PRIMARY && + DVA_GET_VDEV(&dva[i]) == mg->mg_vd->vdev_id) { activation_weight = METASLAB_WEIGHT_SECONDARY; + } else if (activation_weight == METASLAB_WEIGHT_SECONDARY && + DVA_GET_VDEV(&dva[i]) == mg->mg_vd->vdev_id) { + tertiary = B_TRUE; break; } } + /* + * If we don't have enough metaslabs active to fill the entire array, we + * just use the 0th slot. + */ + if (mg->mg_ms_ready < mg->mg_allocators * 2) { + tertiary = B_FALSE; + allocator = 0; + } + + ASSERT3U(mg->mg_vd->vdev_ms_count, >=, 2); + metaslab_t *search = kmem_alloc(sizeof (*search), KM_SLEEP); search->ms_weight = UINT64_MAX; search->ms_start = 0; + /* + * At the end of the metaslab tree are the already-active metaslabs, + * first the primaries, then the secondaries. When we resume searching + * through the tree, we need to consider ms_allocator and ms_primary so + * we start in the location right after where we left off, and don't + * accidentally loop forever considering the same metaslabs. + */ + search->ms_allocator = -1; + search->ms_primary = B_TRUE; for (;;) { - boolean_t was_active; - avl_tree_t *t = &mg->mg_metaslab_tree; - avl_index_t idx; + boolean_t was_active = B_FALSE; mutex_enter(&mg->mg_lock); - /* - * Find the metaslab with the highest weight that is less - * than what we've already tried. In the common case, this - * means that we will examine each metaslab at most once. - * Note that concurrent callers could reorder metaslabs - * by activation/passivation once we have dropped the mg_lock. - * If a metaslab is activated by another thread, and we fail - * to allocate from the metaslab we have selected, we may - * not try the newly-activated metaslab, and instead activate - * another metaslab. This is not optimal, but generally - * does not cause any problems (a possible exception being - * if every metaslab is completely full except for the - * the newly-activated metaslab which we fail to examine). - */ - msp = avl_find(t, search, &idx); - if (msp == NULL) - msp = avl_nearest(t, idx, AVL_AFTER); - for (; msp != NULL; msp = AVL_NEXT(t, msp)) { - - if (!metaslab_should_allocate(msp, asize)) { - metaslab_trace_add(zal, mg, msp, asize, d, - TRACE_TOO_SMALL); - continue; - } - - /* - * If the selected metaslab is condensing, skip it. - */ - if (msp->ms_condensing) - continue; - - was_active = msp->ms_weight & METASLAB_ACTIVE_MASK; - if (activation_weight == METASLAB_WEIGHT_PRIMARY) - break; - - target_distance = min_distance + - (space_map_allocated(msp->ms_sm) != 0 ? 0 : - min_distance >> 1); - - for (i = 0; i < d; i++) { - if (metaslab_distance(msp, &dva[i]) < - target_distance) - break; - } - if (i == d) - break; + if (activation_weight == METASLAB_WEIGHT_PRIMARY && + mg->mg_primaries[allocator] != NULL) { + msp = mg->mg_primaries[allocator]; + was_active = B_TRUE; + } else if (activation_weight == METASLAB_WEIGHT_SECONDARY && + mg->mg_secondaries[allocator] != NULL && !tertiary) { + msp = mg->mg_secondaries[allocator]; + was_active = B_TRUE; + } else { + msp = find_valid_metaslab(mg, activation_weight, dva, d, + min_distance, asize, allocator, zal, search, + &was_active); } + mutex_exit(&mg->mg_lock); if (msp == NULL) { kmem_free(search, sizeof (*search)); return (-1ULL); } - search->ms_weight = msp->ms_weight; - search->ms_start = msp->ms_start + 1; mutex_enter(&msp->ms_lock); - /* * Ensure that the metaslab we have selected is still * capable of handling our request. It's possible that @@ -2909,18 +3156,32 @@ metaslab_group_alloc_normal(metaslab_group_t *mg, zio_alloc_list_t *zal, continue; } - if ((msp->ms_weight & METASLAB_WEIGHT_SECONDARY) && - activation_weight == METASLAB_WEIGHT_PRIMARY) { - metaslab_passivate(msp, - msp->ms_weight & ~METASLAB_ACTIVE_MASK); + /* + * If the metaslab is freshly activated for an allocator that + * isn't the one we're allocating from, or if it's a primary and + * we're seeking a secondary (or vice versa), we go back and + * select a new metaslab. + */ + if (!was_active && (msp->ms_weight & METASLAB_ACTIVE_MASK) && + (msp->ms_allocator != -1) && + (msp->ms_allocator != allocator || ((activation_weight == + METASLAB_WEIGHT_PRIMARY) != msp->ms_primary))) { mutex_exit(&msp->ms_lock); continue; } - if (metaslab_activate(msp, activation_weight) != 0) { + if (msp->ms_weight & METASLAB_WEIGHT_CLAIM) { + metaslab_passivate(msp, msp->ms_weight & + ~METASLAB_WEIGHT_CLAIM); mutex_exit(&msp->ms_lock); continue; } + + if (metaslab_activate(msp, allocator, activation_weight) != 0) { + mutex_exit(&msp->ms_lock); + continue; + } + msp->ms_selected_txg = txg; /* @@ -2933,7 +3194,7 @@ metaslab_group_alloc_normal(metaslab_group_t *mg, zio_alloc_list_t *zal, if (!metaslab_should_allocate(msp, asize)) { /* Passivate this metaslab and select a new one. */ metaslab_trace_add(zal, mg, msp, asize, d, - TRACE_TOO_SMALL); + TRACE_TOO_SMALL, allocator); goto next; } @@ -2944,13 +3205,15 @@ metaslab_group_alloc_normal(metaslab_group_t *mg, zio_alloc_list_t *zal, */ if (msp->ms_condensing) { metaslab_trace_add(zal, mg, msp, asize, d, - TRACE_CONDENSING); + TRACE_CONDENSING, allocator); + metaslab_passivate(msp, msp->ms_weight & + ~METASLAB_ACTIVE_MASK); mutex_exit(&msp->ms_lock); continue; } offset = metaslab_block_alloc(msp, asize, txg); - metaslab_trace_add(zal, mg, msp, asize, d, offset); + metaslab_trace_add(zal, mg, msp, asize, d, offset, allocator); if (offset != -1ULL) { /* Proactively passivate the metaslab, if needed */ @@ -3006,19 +3269,20 @@ next: static uint64_t metaslab_group_alloc(metaslab_group_t *mg, zio_alloc_list_t *zal, - uint64_t asize, uint64_t txg, uint64_t min_distance, dva_t *dva, int d) + uint64_t asize, uint64_t txg, uint64_t min_distance, dva_t *dva, int d, + int allocator) { uint64_t offset; ASSERT(mg->mg_initialized); offset = metaslab_group_alloc_normal(mg, zal, asize, txg, - min_distance, dva, d); + min_distance, dva, d, allocator); mutex_enter(&mg->mg_lock); if (offset == -1ULL) { mg->mg_failed_allocations++; metaslab_trace_add(zal, mg, NULL, asize, d, - TRACE_GROUP_FAILURE); + TRACE_GROUP_FAILURE, allocator); if (asize == SPA_GANGBLOCKSIZE) { /* * This metaslab group was unable to allocate @@ -3053,7 +3317,7 @@ int ditto_same_vdev_distance_shift = 3; int metaslab_alloc_dva(spa_t *spa, metaslab_class_t *mc, uint64_t psize, dva_t *dva, int d, dva_t *hintdva, uint64_t txg, int flags, - zio_alloc_list_t *zal) + zio_alloc_list_t *zal, int allocator) { metaslab_group_t *mg, *rotor; vdev_t *vd; @@ -3065,7 +3329,8 @@ metaslab_alloc_dva(spa_t *spa, metaslab_class_t *mc, uint64_t psize, * For testing, make some blocks above a certain size be gang blocks. */ if (psize >= metaslab_force_ganging && (ddi_get_lbolt() & 3) == 0) { - metaslab_trace_add(zal, NULL, NULL, psize, d, TRACE_FORCE_GANG); + metaslab_trace_add(zal, NULL, NULL, psize, d, TRACE_FORCE_GANG, + allocator); return (SET_ERROR(ENOSPC)); } @@ -3151,12 +3416,12 @@ top: */ if (allocatable && !GANG_ALLOCATION(flags) && !try_hard) { allocatable = metaslab_group_allocatable(mg, rotor, - psize); + psize, allocator); } if (!allocatable) { metaslab_trace_add(zal, mg, NULL, psize, d, - TRACE_NOT_ALLOCATABLE); + TRACE_NOT_ALLOCATABLE, allocator); goto next; } @@ -3171,7 +3436,7 @@ top: vd->vdev_state < VDEV_STATE_HEALTHY) && d == 0 && !try_hard && vd->vdev_children == 0) { metaslab_trace_add(zal, mg, NULL, psize, d, - TRACE_VDEV_ERROR); + TRACE_VDEV_ERROR, allocator); goto next; } @@ -3195,7 +3460,7 @@ top: ASSERT(P2PHASE(asize, 1ULL << vd->vdev_ashift) == 0); uint64_t offset = metaslab_group_alloc(mg, zal, asize, txg, - distance, dva, d); + distance, dva, d, allocator); if (offset != -1ULL) { /* @@ -3258,7 +3523,7 @@ next: bzero(&dva[d], sizeof (dva_t)); - metaslab_trace_add(zal, rotor, NULL, psize, d, TRACE_ENOSPC); + metaslab_trace_add(zal, rotor, NULL, psize, d, TRACE_ENOSPC, allocator); return (SET_ERROR(ENOSPC)); } @@ -3559,18 +3824,20 @@ metaslab_free_dva(spa_t *spa, const dva_t *dva, boolean_t checkpoint) * the reservation. */ boolean_t -metaslab_class_throttle_reserve(metaslab_class_t *mc, int slots, zio_t *zio, - int flags) +metaslab_class_throttle_reserve(metaslab_class_t *mc, int slots, int allocator, + zio_t *zio, int flags) { uint64_t available_slots = 0; boolean_t slot_reserved = B_FALSE; + uint64_t max = mc->mc_alloc_max_slots[allocator]; ASSERT(mc->mc_alloc_throttle_enabled); mutex_enter(&mc->mc_lock); - uint64_t reserved_slots = refcount_count(&mc->mc_alloc_slots); - if (reserved_slots < mc->mc_alloc_max_slots) - available_slots = mc->mc_alloc_max_slots - reserved_slots; + uint64_t reserved_slots = + refcount_count(&mc->mc_alloc_slots[allocator]); + if (reserved_slots < max) + available_slots = max - reserved_slots; if (slots <= available_slots || GANG_ALLOCATION(flags)) { /* @@ -3578,7 +3845,9 @@ metaslab_class_throttle_reserve(metaslab_class_t *mc, int slots, zio_t *zio, * them individually when an I/O completes. */ for (int d = 0; d < slots; d++) { - reserved_slots = refcount_add(&mc->mc_alloc_slots, zio); + reserved_slots = + refcount_add(&mc->mc_alloc_slots[allocator], + zio); } zio->io_flags |= ZIO_FLAG_IO_ALLOCATING; slot_reserved = B_TRUE; @@ -3589,12 +3858,14 @@ metaslab_class_throttle_reserve(metaslab_class_t *mc, int slots, zio_t *zio, } void -metaslab_class_throttle_unreserve(metaslab_class_t *mc, int slots, zio_t *zio) +metaslab_class_throttle_unreserve(metaslab_class_t *mc, int slots, + int allocator, zio_t *zio) { ASSERT(mc->mc_alloc_throttle_enabled); mutex_enter(&mc->mc_lock); for (int d = 0; d < slots; d++) { - (void) refcount_remove(&mc->mc_alloc_slots, zio); + (void) refcount_remove(&mc->mc_alloc_slots[allocator], + zio); } mutex_exit(&mc->mc_lock); } @@ -3616,7 +3887,13 @@ metaslab_claim_concrete(vdev_t *vd, uint64_t offset, uint64_t size, mutex_enter(&msp->ms_lock); if ((txg != 0 && spa_writeable(spa)) || !msp->ms_loaded) - error = metaslab_activate(msp, METASLAB_WEIGHT_SECONDARY); + error = metaslab_activate(msp, 0, METASLAB_WEIGHT_CLAIM); + /* + * No need to fail in that case; someone else has activated the + * metaslab, but that doesn't preclude us from using it. + */ + if (error == EBUSY) + error = 0; if (error == 0 && !range_tree_contains(msp->ms_allocatable, offset, size)) @@ -3721,7 +3998,7 @@ metaslab_claim_dva(spa_t *spa, const dva_t *dva, uint64_t txg) int metaslab_alloc(spa_t *spa, metaslab_class_t *mc, uint64_t psize, blkptr_t *bp, int ndvas, uint64_t txg, blkptr_t *hintbp, int flags, - zio_alloc_list_t *zal, zio_t *zio) + zio_alloc_list_t *zal, zio_t *zio, int allocator) { dva_t *dva = bp->blk_dva; dva_t *hintdva = hintbp->blk_dva; @@ -3744,12 +4021,13 @@ metaslab_alloc(spa_t *spa, metaslab_class_t *mc, uint64_t psize, blkptr_t *bp, for (int d = 0; d < ndvas; d++) { error = metaslab_alloc_dva(spa, mc, psize, dva, d, hintdva, - txg, flags, zal); + txg, flags, zal, allocator); if (error != 0) { for (d--; d >= 0; d--) { metaslab_unalloc_dva(spa, &dva[d], txg); metaslab_group_alloc_decrement(spa, - DVA_GET_VDEV(&dva[d]), zio, flags); + DVA_GET_VDEV(&dva[d]), zio, flags, + allocator, B_FALSE); bzero(&dva[d], sizeof (dva_t)); } spa_config_exit(spa, SCL_ALLOC, FTAG); @@ -3760,7 +4038,7 @@ metaslab_alloc(spa_t *spa, metaslab_class_t *mc, uint64_t psize, blkptr_t *bp, * based on the newly allocated dva. */ metaslab_group_alloc_increment(spa, - DVA_GET_VDEV(&dva[d]), zio, flags); + DVA_GET_VDEV(&dva[d]), zio, flags, allocator); } } diff --git a/usr/src/uts/common/fs/zfs/spa.c b/usr/src/uts/common/fs/zfs/spa.c index 064e4411db..163f5e054e 100644 --- a/usr/src/uts/common/fs/zfs/spa.c +++ b/usr/src/uts/common/fs/zfs/spa.c @@ -7398,9 +7398,11 @@ spa_sync(spa_t *spa, uint64_t txg) spa->spa_syncing_txg = txg; spa->spa_sync_pass = 0; - mutex_enter(&spa->spa_alloc_lock); - VERIFY0(avl_numnodes(&spa->spa_alloc_tree)); - mutex_exit(&spa->spa_alloc_lock); + for (int i = 0; i < spa->spa_alloc_count; i++) { + mutex_enter(&spa->spa_alloc_locks[i]); + VERIFY0(avl_numnodes(&spa->spa_alloc_trees[i])); + mutex_exit(&spa->spa_alloc_locks[i]); + } /* * If there are any pending vdev state changes, convert them @@ -7459,7 +7461,7 @@ spa_sync(spa_t *spa, uint64_t txg) * The max queue depth will not change in the middle of syncing * out this txg. */ - uint64_t queue_depth_total = 0; + uint64_t slots_per_allocator = 0; for (int c = 0; c < rvd->vdev_children; c++) { vdev_t *tvd = rvd->vdev_child[c]; metaslab_group_t *mg = tvd->vdev_mg; @@ -7473,18 +7475,23 @@ spa_sync(spa_t *spa, uint64_t txg) * allocations look at mg_max_alloc_queue_depth, and async * allocations all happen from spa_sync(). */ - ASSERT0(refcount_count(&mg->mg_alloc_queue_depth)); + for (int i = 0; i < spa->spa_alloc_count; i++) + ASSERT0(refcount_count(&(mg->mg_alloc_queue_depth[i]))); mg->mg_max_alloc_queue_depth = max_queue_depth; - queue_depth_total += mg->mg_max_alloc_queue_depth; + + for (int i = 0; i < spa->spa_alloc_count; i++) { + mg->mg_cur_max_alloc_queue_depth[i] = + zfs_vdev_def_queue_depth; + } + slots_per_allocator += zfs_vdev_def_queue_depth; } metaslab_class_t *mc = spa_normal_class(spa); - ASSERT0(refcount_count(&mc->mc_alloc_slots)); - mc->mc_alloc_max_slots = queue_depth_total; + for (int i = 0; i < spa->spa_alloc_count; i++) { + ASSERT0(refcount_count(&mc->mc_alloc_slots[i])); + mc->mc_alloc_max_slots[i] = slots_per_allocator; + } mc->mc_alloc_throttle_enabled = zio_dva_throttle_enabled; - ASSERT3U(mc->mc_alloc_max_slots, <=, - max_queue_depth * rvd->vdev_children); - for (int c = 0; c < rvd->vdev_children; c++) { vdev_t *vd = rvd->vdev_child[c]; vdev_indirect_state_sync_verify(vd); @@ -7661,9 +7668,11 @@ spa_sync(spa_t *spa, uint64_t txg) dsl_pool_sync_done(dp, txg); - mutex_enter(&spa->spa_alloc_lock); - VERIFY0(avl_numnodes(&spa->spa_alloc_tree)); - mutex_exit(&spa->spa_alloc_lock); + for (int i = 0; i < spa->spa_alloc_count; i++) { + mutex_enter(&spa->spa_alloc_locks[i]); + VERIFY0(avl_numnodes(&spa->spa_alloc_trees[i])); + mutex_exit(&spa->spa_alloc_locks[i]); + } /* * Update usable space statistics. diff --git a/usr/src/uts/common/fs/zfs/spa_misc.c b/usr/src/uts/common/fs/zfs/spa_misc.c index efb4993c0a..fe0971a720 100644 --- a/usr/src/uts/common/fs/zfs/spa_misc.c +++ b/usr/src/uts/common/fs/zfs/spa_misc.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2017 by Delphix. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. * Copyright 2015 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. * Copyright 2013 Saso Kiselkov. All rights reserved. @@ -357,6 +357,8 @@ int spa_asize_inflation = 24; int spa_slop_shift = 5; uint64_t spa_min_slop = 128 * 1024 * 1024; +int spa_allocators = 4; + /*PRINTFLIKE2*/ void spa_load_failed(spa_t *spa, const char *fmt, ...) @@ -607,7 +609,6 @@ spa_add(const char *name, nvlist_t *config, const char *altroot) mutex_init(&spa->spa_suspend_lock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&spa->spa_vdev_top_lock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&spa->spa_iokstat_lock, NULL, MUTEX_DEFAULT, NULL); - mutex_init(&spa->spa_alloc_lock, NULL, MUTEX_DEFAULT, NULL); cv_init(&spa->spa_async_cv, NULL, CV_DEFAULT, NULL); cv_init(&spa->spa_evicting_os_cv, NULL, CV_DEFAULT, NULL); @@ -658,8 +659,16 @@ spa_add(const char *name, nvlist_t *config, const char *altroot) spa_active_count++; } - avl_create(&spa->spa_alloc_tree, zio_bookmark_compare, - sizeof (zio_t), offsetof(zio_t, io_alloc_node)); + spa->spa_alloc_count = spa_allocators; + spa->spa_alloc_locks = kmem_zalloc(spa->spa_alloc_count * + sizeof (kmutex_t), KM_SLEEP); + spa->spa_alloc_trees = kmem_zalloc(spa->spa_alloc_count * + sizeof (avl_tree_t), KM_SLEEP); + for (int i = 0; i < spa->spa_alloc_count; i++) { + mutex_init(&spa->spa_alloc_locks[i], NULL, MUTEX_DEFAULT, NULL); + avl_create(&spa->spa_alloc_trees[i], zio_bookmark_compare, + sizeof (zio_t), offsetof(zio_t, io_alloc_node)); + } /* * Every pool starts with the default cachefile @@ -746,7 +755,15 @@ spa_remove(spa_t *spa) kmem_free(dp, sizeof (spa_config_dirent_t)); } - avl_destroy(&spa->spa_alloc_tree); + for (int i = 0; i < spa->spa_alloc_count; i++) { + avl_destroy(&spa->spa_alloc_trees[i]); + mutex_destroy(&spa->spa_alloc_locks[i]); + } + kmem_free(spa->spa_alloc_locks, spa->spa_alloc_count * + sizeof (kmutex_t)); + kmem_free(spa->spa_alloc_trees, spa->spa_alloc_count * + sizeof (avl_tree_t)); + list_destroy(&spa->spa_config_list); nvlist_free(spa->spa_label_features); @@ -777,7 +794,6 @@ spa_remove(spa_t *spa) cv_destroy(&spa->spa_scrub_io_cv); cv_destroy(&spa->spa_suspend_cv); - mutex_destroy(&spa->spa_alloc_lock); mutex_destroy(&spa->spa_async_lock); mutex_destroy(&spa->spa_errlist_lock); mutex_destroy(&spa->spa_errlog_lock); diff --git a/usr/src/uts/common/fs/zfs/sys/metaslab.h b/usr/src/uts/common/fs/zfs/sys/metaslab.h index a76d344d21..32a19ca645 100644 --- a/usr/src/uts/common/fs/zfs/sys/metaslab.h +++ b/usr/src/uts/common/fs/zfs/sys/metaslab.h @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2017 by Delphix. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. */ #ifndef _SYS_METASLAB_H @@ -65,9 +65,10 @@ uint64_t metaslab_block_maxsize(metaslab_t *); #define METASLAB_DONT_THROTTLE 0x10 int metaslab_alloc(spa_t *, metaslab_class_t *, uint64_t, - blkptr_t *, int, uint64_t, blkptr_t *, int, zio_alloc_list_t *, zio_t *); + blkptr_t *, int, uint64_t, blkptr_t *, int, zio_alloc_list_t *, zio_t *, + int); int metaslab_alloc_dva(spa_t *, metaslab_class_t *, uint64_t, - dva_t *, int, dva_t *, uint64_t, int, zio_alloc_list_t *); + dva_t *, int, dva_t *, uint64_t, int, zio_alloc_list_t *, int); void metaslab_free(spa_t *, const blkptr_t *, uint64_t, boolean_t); void metaslab_free_concrete(vdev_t *, uint64_t, uint64_t, boolean_t); void metaslab_free_dva(spa_t *, const dva_t *, boolean_t); @@ -88,9 +89,9 @@ int metaslab_class_validate(metaslab_class_t *); void metaslab_class_histogram_verify(metaslab_class_t *); uint64_t metaslab_class_fragmentation(metaslab_class_t *); uint64_t metaslab_class_expandable_space(metaslab_class_t *); -boolean_t metaslab_class_throttle_reserve(metaslab_class_t *, int, +boolean_t metaslab_class_throttle_reserve(metaslab_class_t *, int, int, zio_t *, int); -void metaslab_class_throttle_unreserve(metaslab_class_t *, int, zio_t *); +void metaslab_class_throttle_unreserve(metaslab_class_t *, int, int, zio_t *); void metaslab_class_space_update(metaslab_class_t *, int64_t, int64_t, int64_t, int64_t); @@ -99,7 +100,7 @@ uint64_t metaslab_class_get_space(metaslab_class_t *); uint64_t metaslab_class_get_dspace(metaslab_class_t *); uint64_t metaslab_class_get_deferred(metaslab_class_t *); -metaslab_group_t *metaslab_group_create(metaslab_class_t *, vdev_t *); +metaslab_group_t *metaslab_group_create(metaslab_class_t *, vdev_t *, int); void metaslab_group_destroy(metaslab_group_t *); void metaslab_group_activate(metaslab_group_t *); void metaslab_group_passivate(metaslab_group_t *); @@ -108,8 +109,9 @@ uint64_t metaslab_group_get_space(metaslab_group_t *); void metaslab_group_histogram_verify(metaslab_group_t *); uint64_t metaslab_group_fragmentation(metaslab_group_t *); void metaslab_group_histogram_remove(metaslab_group_t *, metaslab_t *); -void metaslab_group_alloc_decrement(spa_t *, uint64_t, void *, int); -void metaslab_group_alloc_verify(spa_t *, const blkptr_t *, void *); +void metaslab_group_alloc_decrement(spa_t *, uint64_t, void *, int, int, + boolean_t); +void metaslab_group_alloc_verify(spa_t *, const blkptr_t *, void *, int); #ifdef __cplusplus } diff --git a/usr/src/uts/common/fs/zfs/sys/metaslab_impl.h b/usr/src/uts/common/fs/zfs/sys/metaslab_impl.h index a6673fbe06..6a02f7c800 100644 --- a/usr/src/uts/common/fs/zfs/sys/metaslab_impl.h +++ b/usr/src/uts/common/fs/zfs/sys/metaslab_impl.h @@ -24,7 +24,7 @@ */ /* - * Copyright (c) 2011, 2017 by Delphix. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. */ #ifndef _SYS_METASLAB_IMPL_H @@ -52,6 +52,7 @@ typedef struct metaslab_alloc_trace { uint64_t mat_weight; uint32_t mat_dva_id; uint64_t mat_offset; + int mat_allocator; } metaslab_alloc_trace_t; /* @@ -72,9 +73,11 @@ typedef enum trace_alloc_type { #define METASLAB_WEIGHT_PRIMARY (1ULL << 63) #define METASLAB_WEIGHT_SECONDARY (1ULL << 62) -#define METASLAB_WEIGHT_TYPE (1ULL << 61) +#define METASLAB_WEIGHT_CLAIM (1ULL << 61) +#define METASLAB_WEIGHT_TYPE (1ULL << 60) #define METASLAB_ACTIVE_MASK \ - (METASLAB_WEIGHT_PRIMARY | METASLAB_WEIGHT_SECONDARY) + (METASLAB_WEIGHT_PRIMARY | METASLAB_WEIGHT_SECONDARY | \ + METASLAB_WEIGHT_CLAIM) /* * The metaslab weight is used to encode the amount of free space in a @@ -97,37 +100,39 @@ typedef enum trace_alloc_type { * * 64 56 48 40 32 24 16 8 0 * +-------+-------+-------+-------+-------+-------+-------+-------+ - * |PS1| weighted-free space | + * |PSC1| weighted-free space | * +-------+-------+-------+-------+-------+-------+-------+-------+ * * PS - indicates primary and secondary activation + * C - indicates activation for claimed block zio * space - the fragmentation-weighted space * * Segment-based weight: * * 64 56 48 40 32 24 16 8 0 * +-------+-------+-------+-------+-------+-------+-------+-------+ - * |PS0| idx| count of segments in region | + * |PSC0| idx| count of segments in region | * +-------+-------+-------+-------+-------+-------+-------+-------+ * * PS - indicates primary and secondary activation + * C - indicates activation for claimed block zio * idx - index for the highest bucket in the histogram * count - number of segments in the specified bucket */ -#define WEIGHT_GET_ACTIVE(weight) BF64_GET((weight), 62, 2) -#define WEIGHT_SET_ACTIVE(weight, x) BF64_SET((weight), 62, 2, x) +#define WEIGHT_GET_ACTIVE(weight) BF64_GET((weight), 61, 3) +#define WEIGHT_SET_ACTIVE(weight, x) BF64_SET((weight), 61, 3, x) #define WEIGHT_IS_SPACEBASED(weight) \ - ((weight) == 0 || BF64_GET((weight), 61, 1)) -#define WEIGHT_SET_SPACEBASED(weight) BF64_SET((weight), 61, 1, 1) + ((weight) == 0 || BF64_GET((weight), 60, 1)) +#define WEIGHT_SET_SPACEBASED(weight) BF64_SET((weight), 60, 1, 1) /* * These macros are only applicable to segment-based weighting. */ -#define WEIGHT_GET_INDEX(weight) BF64_GET((weight), 55, 6) -#define WEIGHT_SET_INDEX(weight, x) BF64_SET((weight), 55, 6, x) -#define WEIGHT_GET_COUNT(weight) BF64_GET((weight), 0, 55) -#define WEIGHT_SET_COUNT(weight, x) BF64_SET((weight), 0, 55, x) +#define WEIGHT_GET_INDEX(weight) BF64_GET((weight), 54, 6) +#define WEIGHT_SET_INDEX(weight, x) BF64_SET((weight), 54, 6, x) +#define WEIGHT_GET_COUNT(weight) BF64_GET((weight), 0, 54) +#define WEIGHT_SET_COUNT(weight, x) BF64_SET((weight), 0, 54, x) /* * A metaslab class encompasses a category of allocatable top-level vdevs. @@ -178,8 +183,8 @@ struct metaslab_class { * allowed to reserve slots even if we've reached the maximum * number of allocations allowed. */ - uint64_t mc_alloc_max_slots; - refcount_t mc_alloc_slots; + uint64_t *mc_alloc_max_slots; + refcount_t *mc_alloc_slots; uint64_t mc_alloc_groups; /* # of allocatable groups */ @@ -201,9 +206,12 @@ struct metaslab_class { */ struct metaslab_group { kmutex_t mg_lock; + metaslab_t **mg_primaries; + metaslab_t **mg_secondaries; avl_tree_t mg_metaslab_tree; uint64_t mg_aliquot; boolean_t mg_allocatable; /* can we allocate? */ + uint64_t mg_ms_ready; /* * A metaslab group is considered to be initialized only after @@ -223,15 +231,33 @@ struct metaslab_group { metaslab_group_t *mg_next; /* - * Each metaslab group can handle mg_max_alloc_queue_depth allocations - * which are tracked by mg_alloc_queue_depth. It's possible for a - * metaslab group to handle more allocations than its max. This - * can occur when gang blocks are required or when other groups - * are unable to handle their share of allocations. + * In order for the allocation throttle to function properly, we cannot + * have too many IOs going to each disk by default; the throttle + * operates by allocating more work to disks that finish quickly, so + * allocating larger chunks to each disk reduces its effectiveness. + * However, if the number of IOs going to each allocator is too small, + * we will not perform proper aggregation at the vdev_queue layer, + * also resulting in decreased performance. Therefore, we will use a + * ramp-up strategy. + * + * Each allocator in each metaslab group has a current queue depth + * (mg_alloc_queue_depth[allocator]) and a current max queue depth + * (mg_cur_max_alloc_queue_depth[allocator]), and each metaslab group + * has an absolute max queue depth (mg_max_alloc_queue_depth). We + * add IOs to an allocator until the mg_alloc_queue_depth for that + * allocator hits the cur_max. Every time an IO completes for a given + * allocator on a given metaslab group, we increment its cur_max until + * it reaches mg_max_alloc_queue_depth. The cur_max resets every txg to + * help protect against disks that decrease in performance over time. + * + * It's possible for an allocator to handle more allocations than + * its max. This can occur when gang blocks are required or when other + * groups are unable to handle their share of allocations. */ uint64_t mg_max_alloc_queue_depth; - refcount_t mg_alloc_queue_depth; - + uint64_t *mg_cur_max_alloc_queue_depth; + refcount_t *mg_alloc_queue_depth; + int mg_allocators; /* * A metalab group that can no longer allocate the minimum block * size will set mg_no_free_space. Once a metaslab group is out @@ -356,6 +382,13 @@ struct metaslab { uint64_t ms_max_size; /* maximum allocatable size */ /* + * -1 if it's not active in an allocator, otherwise set to the allocator + * this metaslab is active for. + */ + int ms_allocator; + boolean_t ms_primary; /* Only valid if ms_allocator is not -1 */ + + /* * The metaslab block allocators can optionally use a size-ordered * range tree and/or an array of LBAs. Not all allocators use * this functionality. The ms_allocatable_by_size should always @@ -369,6 +402,8 @@ struct metaslab { metaslab_group_t *ms_group; /* metaslab group */ avl_node_t ms_group_node; /* node in metaslab group tree */ txg_node_t ms_txg_node; /* per-txg dirty metaslab links */ + + boolean_t ms_new; }; #ifdef __cplusplus diff --git a/usr/src/uts/common/fs/zfs/sys/spa_impl.h b/usr/src/uts/common/fs/zfs/sys/spa_impl.h index a23f9b8c4f..a6da04b67b 100644 --- a/usr/src/uts/common/fs/zfs/sys/spa_impl.h +++ b/usr/src/uts/common/fs/zfs/sys/spa_impl.h @@ -237,8 +237,16 @@ struct spa { uint64_t spa_last_synced_guid; /* last synced guid */ list_t spa_config_dirty_list; /* vdevs with dirty config */ list_t spa_state_dirty_list; /* vdevs with dirty state */ - kmutex_t spa_alloc_lock; - avl_tree_t spa_alloc_tree; + /* + * spa_alloc_locks and spa_alloc_trees are arrays, whose lengths are + * stored in spa_alloc_count. There is one tree and one lock for each + * allocator, to help improve allocation performance in write-heavy + * workloads. + */ + kmutex_t *spa_alloc_locks; + avl_tree_t *spa_alloc_trees; + int spa_alloc_count; + spa_aux_vdev_t spa_spares; /* hot spares */ spa_aux_vdev_t spa_l2cache; /* L2ARC cache devices */ nvlist_t *spa_label_features; /* Features for reading MOS */ diff --git a/usr/src/uts/common/fs/zfs/sys/vdev_impl.h b/usr/src/uts/common/fs/zfs/sys/vdev_impl.h index 4327f61af9..252069c5a4 100644 --- a/usr/src/uts/common/fs/zfs/sys/vdev_impl.h +++ b/usr/src/uts/common/fs/zfs/sys/vdev_impl.h @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2017 by Delphix. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. */ #ifndef _SYS_VDEV_IMPL_H @@ -59,6 +59,7 @@ typedef struct vdev_cache_entry vdev_cache_entry_t; struct abd; extern int zfs_vdev_queue_depth_pct; +extern int zfs_vdev_def_queue_depth; extern uint32_t zfs_vdev_async_write_max_active; /* diff --git a/usr/src/uts/common/fs/zfs/sys/zio.h b/usr/src/uts/common/fs/zfs/sys/zio.h index 1520216c8f..273e5fcb0b 100644 --- a/usr/src/uts/common/fs/zfs/sys/zio.h +++ b/usr/src/uts/common/fs/zfs/sys/zio.h @@ -22,7 +22,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2012, 2017 by Delphix. All rights reserved. + * Copyright (c) 2012, 2018 by Delphix. All rights reserved. * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. * Copyright (c) 2013, Joyent, Inc. All rights reserved. * Copyright 2016 Toomas Soome <tsoome@me.com> @@ -459,6 +459,7 @@ struct zio { void *io_waiter; kmutex_t io_lock; kcondvar_t io_cv; + int io_allocator; /* FMA state */ zio_cksum_report_t *io_cksum_report; @@ -517,8 +518,8 @@ extern zio_t *zio_write_phys(zio_t *pio, vdev_t *vd, uint64_t offset, extern zio_t *zio_free_sync(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp, enum zio_flag flags); -extern int zio_alloc_zil(spa_t *spa, uint64_t txg, blkptr_t *new_bp, - blkptr_t *old_bp, uint64_t size, boolean_t *slog); +extern int zio_alloc_zil(spa_t *spa, uint64_t objset, uint64_t txg, + blkptr_t *new_bp, blkptr_t *old_bp, uint64_t size, boolean_t *slog); extern void zio_flush(zio_t *zio, vdev_t *vd); extern void zio_shrink(zio_t *zio, uint64_t size); diff --git a/usr/src/uts/common/fs/zfs/vdev.c b/usr/src/uts/common/fs/zfs/vdev.c index ae7f4b501c..e761ee4b39 100644 --- a/usr/src/uts/common/fs/zfs/vdev.c +++ b/usr/src/uts/common/fs/zfs/vdev.c @@ -644,7 +644,8 @@ vdev_alloc(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vdev_t *parent, uint_t id, alloctype == VDEV_ALLOC_SPLIT || alloctype == VDEV_ALLOC_ROOTPOOL); vd->vdev_mg = metaslab_group_create(islog ? - spa_log_class(spa) : spa_normal_class(spa), vd); + spa_log_class(spa) : spa_normal_class(spa), vd, + spa->spa_alloc_count); } if (vd->vdev_ops->vdev_op_leaf && @@ -1013,7 +1014,6 @@ vdev_metaslab_init(vdev_t *vd, uint64_t txg) vd->vdev_ms = mspp; vd->vdev_ms_count = newc; - for (m = oldc; m < newc; m++) { uint64_t object = 0; diff --git a/usr/src/uts/common/fs/zfs/vdev_queue.c b/usr/src/uts/common/fs/zfs/vdev_queue.c index 3a6644a51f..9f962350db 100644 --- a/usr/src/uts/common/fs/zfs/vdev_queue.c +++ b/usr/src/uts/common/fs/zfs/vdev_queue.c @@ -25,7 +25,7 @@ */ /* - * Copyright (c) 2012, 2017 by Delphix. All rights reserved. + * Copyright (c) 2012, 2018 by Delphix. All rights reserved. * Copyright (c) 2014 Integros [integros.com] */ @@ -189,6 +189,15 @@ int zfs_vdev_queue_depth_pct = 1000; int zfs_vdev_queue_depth_pct = 300; #endif +/* + * When performing allocations for a given metaslab, we want to make sure that + * there are enough IOs to aggregate together to improve throughput. We want to + * ensure that there are at least 128k worth of IOs that can be aggregated, and + * we assume that the average allocation size is 4k, so we need the queue depth + * to be 32 per allocator to get good aggregation of sequential writes. + */ +int zfs_vdev_def_queue_depth = 32; + int vdev_queue_offset_compare(const void *x1, const void *x2) diff --git a/usr/src/uts/common/fs/zfs/vdev_removal.c b/usr/src/uts/common/fs/zfs/vdev_removal.c index f8d149fc11..d00b5b35f7 100644 --- a/usr/src/uts/common/fs/zfs/vdev_removal.c +++ b/usr/src/uts/common/fs/zfs/vdev_removal.c @@ -806,8 +806,15 @@ spa_vdev_copy_segment(vdev_t *vd, uint64_t start, uint64_t size, uint64_t txg, ASSERT3U(size, <=, SPA_MAXBLOCKSIZE); + /* + * We use allocator 0 for this I/O because we don't expect device remap + * to be the steady state of the system, so parallelizing is not as + * critical as it is for other allocation types. We also want to ensure + * that the IOs are allocated together as much as possible, to reduce + * mapping sizes. + */ int error = metaslab_alloc_dva(spa, mg->mg_class, size, - &dst, 0, NULL, txg, 0, zal); + &dst, 0, NULL, txg, 0, zal, 0); if (error != 0) return (error); diff --git a/usr/src/uts/common/fs/zfs/zil.c b/usr/src/uts/common/fs/zfs/zil.c index 4711c7150f..0e02377de5 100644 --- a/usr/src/uts/common/fs/zfs/zil.c +++ b/usr/src/uts/common/fs/zfs/zil.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Joyent, Inc. All rights reserved. - * Copyright (c) 2011, 2017 by Delphix. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. * Copyright (c) 2014 Integros [integros.com] */ @@ -657,7 +657,8 @@ zil_create(zilog_t *zilog) BP_ZERO(&blk); } - error = zio_alloc_zil(zilog->zl_spa, txg, &blk, NULL, + error = zio_alloc_zil(zilog->zl_spa, + zilog->zl_os->os_dsl_dataset->ds_object, txg, &blk, NULL, ZIL_MIN_BLKSZ, &slog); if (error == 0) @@ -1334,7 +1335,8 @@ zil_lwb_write_issue(zilog_t *zilog, lwb_t *lwb) BP_ZERO(bp); /* pass the old blkptr in order to spread log blocks across devs */ - error = zio_alloc_zil(spa, txg, bp, &lwb->lwb_blk, zil_blksz, &slog); + error = zio_alloc_zil(spa, zilog->zl_os->os_dsl_dataset->ds_object, + txg, bp, &lwb->lwb_blk, zil_blksz, &slog); if (error == 0) { ASSERT3U(bp->blk_birth, ==, txg); bp->blk_cksum = lwb->lwb_blk.blk_cksum; diff --git a/usr/src/uts/common/fs/zfs/zio.c b/usr/src/uts/common/fs/zfs/zio.c index d43adabb5b..f2c511ef77 100644 --- a/usr/src/uts/common/fs/zfs/zio.c +++ b/usr/src/uts/common/fs/zfs/zio.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2017 by Delphix. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. * Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. * Copyright (c) 2014 Integros [integros.com] @@ -44,6 +44,7 @@ #include <sys/zfs_zone.h> #include <sys/metaslab_impl.h> #include <sys/abd.h> +#include <sys/cityhash.h> /* * ========================================================================== @@ -2235,7 +2236,8 @@ zio_write_gang_block(zio_t *pio) ASSERT(!(pio->io_flags & ZIO_FLAG_NODATA)); flags |= METASLAB_ASYNC_ALLOC; - VERIFY(refcount_held(&mc->mc_alloc_slots, pio)); + VERIFY(refcount_held(&mc->mc_alloc_slots[pio->io_allocator], + pio)); /* * The logical zio has already placed a reservation for @@ -2246,12 +2248,12 @@ zio_write_gang_block(zio_t *pio) * additional reservations for gang blocks. */ VERIFY(metaslab_class_throttle_reserve(mc, gbh_copies - copies, - pio, flags)); + pio->io_allocator, pio, flags)); } error = metaslab_alloc(spa, mc, SPA_GANGBLOCKSIZE, bp, gbh_copies, txg, pio == gio ? NULL : gio->io_bp, flags, - &pio->io_alloc_list, pio); + &pio->io_alloc_list, pio, pio->io_allocator); if (error) { if (pio->io_flags & ZIO_FLAG_IO_ALLOCATING) { ASSERT(pio->io_priority == ZIO_PRIORITY_ASYNC_WRITE); @@ -2265,7 +2267,7 @@ zio_write_gang_block(zio_t *pio) * stage. */ metaslab_class_throttle_unreserve(mc, - gbh_copies - copies, pio); + gbh_copies - copies, pio->io_allocator, pio); } pio->io_error = error; return (ZIO_PIPELINE_CONTINUE); @@ -2323,7 +2325,7 @@ zio_write_gang_block(zio_t *pio) * slot for them here. */ VERIFY(metaslab_class_throttle_reserve(mc, - zp.zp_copies, cio, flags)); + zp.zp_copies, cio->io_allocator, cio, flags)); } zio_nowait(cio); } @@ -2813,13 +2815,13 @@ zio_ddt_free(zio_t *zio) */ static zio_t * -zio_io_to_allocate(spa_t *spa) +zio_io_to_allocate(spa_t *spa, int allocator) { zio_t *zio; - ASSERT(MUTEX_HELD(&spa->spa_alloc_lock)); + ASSERT(MUTEX_HELD(&spa->spa_alloc_locks[allocator])); - zio = avl_first(&spa->spa_alloc_tree); + zio = avl_first(&spa->spa_alloc_trees[allocator]); if (zio == NULL) return (NULL); @@ -2829,12 +2831,13 @@ zio_io_to_allocate(spa_t *spa) * Try to place a reservation for this zio. If we're unable to * reserve then we throttle. */ + ASSERT3U(zio->io_allocator, ==, allocator); if (!metaslab_class_throttle_reserve(spa_normal_class(spa), - zio->io_prop.zp_copies, zio, 0)) { + zio->io_prop.zp_copies, zio->io_allocator, zio, 0)) { return (NULL); } - avl_remove(&spa->spa_alloc_tree, zio); + avl_remove(&spa->spa_alloc_trees[allocator], zio); ASSERT3U(zio->io_stage, <, ZIO_STAGE_DVA_ALLOCATE); return (zio); @@ -2858,13 +2861,23 @@ zio_dva_throttle(zio_t *zio) ASSERT3U(zio->io_queued_timestamp, >, 0); ASSERT(zio->io_stage == ZIO_STAGE_DVA_THROTTLE); - mutex_enter(&spa->spa_alloc_lock); + zbookmark_phys_t *bm = &zio->io_bookmark; + /* + * We want to try to use as many allocators as possible to help improve + * performance, but we also want logically adjacent IOs to be physically + * adjacent to improve sequential read performance. We chunk each object + * into 2^20 block regions, and then hash based on the objset, object, + * level, and region to accomplish both of these goals. + */ + zio->io_allocator = cityhash4(bm->zb_objset, bm->zb_object, + bm->zb_level, bm->zb_blkid >> 20) % spa->spa_alloc_count; + mutex_enter(&spa->spa_alloc_locks[zio->io_allocator]); ASSERT(zio->io_type == ZIO_TYPE_WRITE); - avl_add(&spa->spa_alloc_tree, zio); + avl_add(&spa->spa_alloc_trees[zio->io_allocator], zio); - nio = zio_io_to_allocate(zio->io_spa); - mutex_exit(&spa->spa_alloc_lock); + nio = zio_io_to_allocate(zio->io_spa, zio->io_allocator); + mutex_exit(&spa->spa_alloc_locks[zio->io_allocator]); if (nio == zio) return (ZIO_PIPELINE_CONTINUE); @@ -2885,13 +2898,13 @@ zio_dva_throttle(zio_t *zio) } void -zio_allocate_dispatch(spa_t *spa) +zio_allocate_dispatch(spa_t *spa, int allocator) { zio_t *zio; - mutex_enter(&spa->spa_alloc_lock); - zio = zio_io_to_allocate(spa); - mutex_exit(&spa->spa_alloc_lock); + mutex_enter(&spa->spa_alloc_locks[allocator]); + zio = zio_io_to_allocate(spa, allocator); + mutex_exit(&spa->spa_alloc_locks[allocator]); if (zio == NULL) return; @@ -2932,7 +2945,7 @@ zio_dva_allocate(zio_t *zio) error = metaslab_alloc(spa, mc, zio->io_size, bp, zio->io_prop.zp_copies, zio->io_txg, NULL, flags, - &zio->io_alloc_list, zio); + &zio->io_alloc_list, zio, zio->io_allocator); if (error != 0) { spa_dbgmsg(spa, "%s: metaslab allocation failure: zio %p, " @@ -2992,8 +3005,8 @@ zio_dva_unallocate(zio_t *zio, zio_gang_node_t *gn, blkptr_t *bp) * Try to allocate an intent log block. Return 0 on success, errno on failure. */ int -zio_alloc_zil(spa_t *spa, uint64_t txg, blkptr_t *new_bp, blkptr_t *old_bp, - uint64_t size, boolean_t *slog) +zio_alloc_zil(spa_t *spa, uint64_t objset, uint64_t txg, blkptr_t *new_bp, + blkptr_t *old_bp, uint64_t size, boolean_t *slog) { int error = 1; zio_alloc_list_t io_alloc_list; @@ -3001,14 +3014,22 @@ zio_alloc_zil(spa_t *spa, uint64_t txg, blkptr_t *new_bp, blkptr_t *old_bp, ASSERT(txg > spa_syncing_txg(spa)); metaslab_trace_init(&io_alloc_list); + /* + * When allocating a zil block, we don't have information about + * the final destination of the block except the objset it's part + * of, so we just hash the objset ID to pick the allocator to get + * some parallelism. + */ error = metaslab_alloc(spa, spa_log_class(spa), size, new_bp, 1, - txg, old_bp, METASLAB_HINTBP_AVOID, &io_alloc_list, NULL); + txg, old_bp, METASLAB_HINTBP_AVOID, &io_alloc_list, NULL, + cityhash4(0, 0, 0, objset) % spa->spa_alloc_count); if (error == 0) { *slog = TRUE; } else { error = metaslab_alloc(spa, spa_normal_class(spa), size, new_bp, 1, txg, old_bp, METASLAB_HINTBP_AVOID, - &io_alloc_list, NULL); + &io_alloc_list, NULL, cityhash4(0, 0, 0, objset) % + spa->spa_alloc_count); if (error == 0) *slog = FALSE; } @@ -3498,8 +3519,8 @@ zio_ready(zio_t *zio) */ metaslab_class_throttle_unreserve( spa_normal_class(zio->io_spa), - zio->io_prop.zp_copies, zio); - zio_allocate_dispatch(zio->io_spa); + zio->io_prop.zp_copies, zio->io_allocator, zio); + zio_allocate_dispatch(zio->io_spa, zio->io_allocator); } } @@ -3582,18 +3603,19 @@ zio_dva_throttle_done(zio_t *zio) ASSERT0(zio->io_flags & ZIO_FLAG_NOPWRITE); mutex_enter(&pio->io_lock); - metaslab_group_alloc_decrement(zio->io_spa, vd->vdev_id, pio, flags); + metaslab_group_alloc_decrement(zio->io_spa, vd->vdev_id, pio, flags, + pio->io_allocator, B_TRUE); mutex_exit(&pio->io_lock); metaslab_class_throttle_unreserve(spa_normal_class(zio->io_spa), - 1, pio); + 1, pio->io_allocator, pio); /* * Call into the pipeline to see if there is more work that * needs to be done. If there is work to be done it will be * dispatched to another taskq thread. */ - zio_allocate_dispatch(zio->io_spa); + zio_allocate_dispatch(zio->io_spa, pio->io_allocator); } static int @@ -3636,8 +3658,10 @@ zio_done(zio_t *zio) ASSERT(zio->io_type == ZIO_TYPE_WRITE); ASSERT(zio->io_priority == ZIO_PRIORITY_ASYNC_WRITE); ASSERT(bp != NULL); - metaslab_group_alloc_verify(spa, zio->io_bp, zio); - VERIFY(refcount_not_held(&mc->mc_alloc_slots, zio)); + metaslab_group_alloc_verify(spa, zio->io_bp, zio, + zio->io_allocator); + VERIFY(refcount_not_held(&mc->mc_alloc_slots[zio->io_allocator], + zio)); } for (int c = 0; c < ZIO_CHILD_TYPES; c++) diff --git a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c index 370c39ccc1..34014a5768 100644 --- a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c +++ b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c @@ -2143,7 +2143,7 @@ mptsas_get_sas_io_unit_page_hndshk(mptsas_t *mpt) "manufacturing information (%u). Driver " "will not attach. Please contact the " "firmware vendor about this.", num_phys, - mpt->m_num_phys, mpt->m_num_phys); + mpt->m_num_phys); rval = DDI_FAILURE; goto cleanup; } @@ -2243,7 +2243,7 @@ mptsas_get_sas_io_unit_page_hndshk(mptsas_t *mpt) "manufacturing information (%u). Driver " "will not attach. Please contact the " "firmware vendor about this.", num_phys, - mpt->m_num_phys, mpt->m_num_phys); + mpt->m_num_phys); rval = DDI_FAILURE; goto cleanup; } diff --git a/usr/src/uts/common/smb/Makefile b/usr/src/uts/common/smb/Makefile index 2efb11c19c..74ac618565 100644 --- a/usr/src/uts/common/smb/Makefile +++ b/usr/src/uts/common/smb/Makefile @@ -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 @@ HDRS= \ doserror.h \ lmerr.h \ nterror.h \ - ntstatus.h + ntstatus.h \ + wintypes.h ROOTDIR= $(ROOT)/usr/include/smb diff --git a/usr/src/uts/common/smbsrv/wintypes.h b/usr/src/uts/common/smb/wintypes.h index 1dc3e1515a..61e48016b4 100644 --- a/usr/src/uts/common/smbsrv/wintypes.h +++ b/usr/src/uts/common/smb/wintypes.h @@ -18,13 +18,16 @@ * * 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_WINTYPES_H -#define _SMBSRV_WINTYPES_H +#ifndef _SMB_WINTYPES_H +#define _SMB_WINTYPES_H #include <sys/types.h> @@ -42,36 +45,26 @@ extern "C" { typedef uint8_t BYTE; typedef uint16_t WORD; typedef uint32_t DWORD; -typedef uint32_t ntstatus_t; +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; -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 */ - +/* CONTEXT_HANDLE now in ndrtypes.ndl */ #ifdef __cplusplus } #endif -#endif /* _SMBSRV_WINTYPES_H */ +#endif /* _SMB_WINTYPES_H */ diff --git a/usr/src/uts/common/smbsrv/Makefile b/usr/src/uts/common/smbsrv/Makefile index f48dc89acb..4664c09cfb 100644 --- a/usr/src/uts/common/smbsrv/Makefile +++ b/usr/src/uts/common/smbsrv/Makefile @@ -33,7 +33,6 @@ HDRS= alloc.h \ mailslot.h \ mbuf.h \ msgbuf.h \ - ndr.h \ netbios.h \ netrauth.h \ nmpipes.h \ @@ -63,18 +62,15 @@ HDRS= alloc.h \ string.h \ svrapi.h \ winioctl.h \ - winsvc.h \ - wintypes.h + winsvc.h NDLHDRS= dssetup.ndl \ eventlog.ndl \ llsrpc.ndl \ lsarpc.ndl \ msgsvc.ndl \ - ndrtypes.ndl \ netdfs.ndl \ netlogon.ndl \ - rpcpdu.ndl \ samrpc.ndl \ security.ndl \ spoolss.ndl \ diff --git a/usr/src/uts/common/smbsrv/ndl/dssetup.ndl b/usr/src/uts/common/smbsrv/ndl/dssetup.ndl index b70a81bb5e..8f1d718e94 100644 --- a/usr/src/uts/common/smbsrv/ndl/dssetup.ndl +++ b/usr/src/uts/common/smbsrv/ndl/dssetup.ndl @@ -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 diff --git a/usr/src/uts/common/smbsrv/ndl/eventlog.ndl b/usr/src/uts/common/smbsrv/ndl/eventlog.ndl index df56f8837a..c0e579c4d6 100644 --- a/usr/src/uts/common/smbsrv/ndl/eventlog.ndl +++ b/usr/src/uts/common/smbsrv/ndl/eventlog.ndl @@ -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 diff --git a/usr/src/uts/common/smbsrv/ndl/llsrpc.ndl b/usr/src/uts/common/smbsrv/ndl/llsrpc.ndl index 3710b32e47..62c276873e 100644 --- a/usr/src/uts/common/smbsrv/ndl/llsrpc.ndl +++ b/usr/src/uts/common/smbsrv/ndl/llsrpc.ndl @@ -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 diff --git a/usr/src/uts/common/smbsrv/ndl/lsarpc.ndl b/usr/src/uts/common/smbsrv/ndl/lsarpc.ndl index 2d89687a6a..e93324b419 100644 --- a/usr/src/uts/common/smbsrv/ndl/lsarpc.ndl +++ b/usr/src/uts/common/smbsrv/ndl/lsarpc.ndl @@ -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 diff --git a/usr/src/uts/common/smbsrv/ndl/msgsvc.ndl b/usr/src/uts/common/smbsrv/ndl/msgsvc.ndl index 28ab3b6437..f804f32685 100644 --- a/usr/src/uts/common/smbsrv/ndl/msgsvc.ndl +++ b/usr/src/uts/common/smbsrv/ndl/msgsvc.ndl @@ -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 diff --git a/usr/src/uts/common/smbsrv/ndl/netdfs.ndl b/usr/src/uts/common/smbsrv/ndl/netdfs.ndl index afc4c88385..7e9a0a42d1 100644 --- a/usr/src/uts/common/smbsrv/ndl/netdfs.ndl +++ b/usr/src/uts/common/smbsrv/ndl/netdfs.ndl @@ -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" diff --git a/usr/src/uts/common/smbsrv/ndl/netlogon.ndl b/usr/src/uts/common/smbsrv/ndl/netlogon.ndl index 26df6a902a..907d52ec72 100644 --- a/usr/src/uts/common/smbsrv/ndl/netlogon.ndl +++ b/usr/src/uts/common/smbsrv/ndl/netlogon.ndl @@ -36,7 +36,7 @@ *********************************************************************** */ -#include "ndrtypes.ndl" +#include <libmlrpc/ndrtypes.ndl> #define NETR_OPNUM_UasLogon 0x00 diff --git a/usr/src/uts/common/smbsrv/ndl/samrpc.ndl b/usr/src/uts/common/smbsrv/ndl/samrpc.ndl index f5ccfd75b8..ef47fff452 100644 --- a/usr/src/uts/common/smbsrv/ndl/samrpc.ndl +++ b/usr/src/uts/common/smbsrv/ndl/samrpc.ndl @@ -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 @@ struct samr_logon_hours_all { #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 */ diff --git a/usr/src/uts/common/smbsrv/ndl/spoolss.ndl b/usr/src/uts/common/smbsrv/ndl/spoolss.ndl index a467b5638c..ef923797d4 100644 --- a/usr/src/uts/common/smbsrv/ndl/spoolss.ndl +++ b/usr/src/uts/common/smbsrv/ndl/spoolss.ndl @@ -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 diff --git a/usr/src/uts/common/smbsrv/ndl/srvsvc.ndl b/usr/src/uts/common/smbsrv/ndl/srvsvc.ndl index dbc42578d1..5e345a9585 100644 --- a/usr/src/uts/common/smbsrv/ndl/srvsvc.ndl +++ b/usr/src/uts/common/smbsrv/ndl/srvsvc.ndl @@ -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 diff --git a/usr/src/uts/common/smbsrv/ndl/svcctl.ndl b/usr/src/uts/common/smbsrv/ndl/svcctl.ndl index 5a6a9d034e..2509f62b52 100644 --- a/usr/src/uts/common/smbsrv/ndl/svcctl.ndl +++ b/usr/src/uts/common/smbsrv/ndl/svcctl.ndl @@ -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 diff --git a/usr/src/uts/common/smbsrv/ndl/winreg.ndl b/usr/src/uts/common/smbsrv/ndl/winreg.ndl index d09cc32ed2..5789a63e91 100644 --- a/usr/src/uts/common/smbsrv/ndl/winreg.ndl +++ b/usr/src/uts/common/smbsrv/ndl/winreg.ndl @@ -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 diff --git a/usr/src/uts/common/smbsrv/netrauth.h b/usr/src/uts/common/smbsrv/netrauth.h index bc11d81e8c..b621e2da1a 100644 --- a/usr/src/uts/common/smbsrv/netrauth.h +++ b/usr/src/uts/common/smbsrv/netrauth.h @@ -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> diff --git a/usr/src/uts/common/smbsrv/smb_door.h b/usr/src/uts/common/smbsrv/smb_door.h index 31d32794eb..a59040ecdf 100644 --- a/usr/src/uts/common/smbsrv/smb_door.h +++ b/usr/src/uts/common/smbsrv/smb_door.h @@ -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> diff --git a/usr/src/uts/common/smbsrv/smb_privilege.h b/usr/src/uts/common/smbsrv/smb_privilege.h index 1a1ee196c1..cbca27107f 100644 --- a/usr/src/uts/common/smbsrv/smb_privilege.h +++ b/usr/src/uts/common/smbsrv/smb_privilege.h @@ -28,7 +28,7 @@ #ifndef _SMB_PRIVILEGE_H #define _SMB_PRIVILEGE_H -#include <smbsrv/wintypes.h> +#include <smb/wintypes.h> #ifdef __cplusplus extern "C" { diff --git a/usr/src/uts/common/smbsrv/smb_share.h b/usr/src/uts/common/smbsrv/smb_share.h index cfb7551dec..b8cfba779a 100644 --- a/usr/src/uts/common/smbsrv/smb_share.h +++ b/usr/src/uts/common/smbsrv/smb_share.h @@ -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> diff --git a/usr/src/uts/common/smbsrv/smb_sid.h b/usr/src/uts/common/smbsrv/smb_sid.h index 5091f419a4..d6c749e8c1 100644 --- a/usr/src/uts/common/smbsrv/smb_sid.h +++ b/usr/src/uts/common/smbsrv/smb_sid.h @@ -29,7 +29,7 @@ /* * Security Identifier (SID) interface definition. */ -#include <smbsrv/wintypes.h> +#include <smb/wintypes.h> #ifdef __cplusplus extern "C" { diff --git a/usr/src/uts/common/smbsrv/smb_xdr.h b/usr/src/uts/common/smbsrv/smb_xdr.h index 51bf3b57e2..aaf0ff070f 100644 --- a/usr/src/uts/common/smbsrv/smb_xdr.h +++ b/usr/src/uts/common/smbsrv/smb_xdr.h @@ -34,14 +34,13 @@ extern "C" { #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> #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> diff --git a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE index f8cd22f7df..7741eb3a6b 100644 --- a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE +++ b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE @@ -1,6 +1,7 @@ -Copyright (c) 2013 LSI Corp. +Copyright (c) 2012-2015 LSI Corp. +Copyright (c) 2013-2016 Avago Technologies All rights reserved. - + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -12,7 +13,7 @@ are met: 3. 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 diff --git a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE.descrip b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE.descrip index 88aaf438dc..3d80aca794 100644 --- a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE.descrip +++ b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE.descrip @@ -1 +1 @@ -LSI Fusion-MPT MPI 2.0 / 2.5 Header Files +LSI Fusion-MPT MPI 2.0 / 2.5 / 2.6 Header Files |