xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_svc.c (revision 12065:0e89d02a32ea)
18474SJose.Borrego@Sun.COM /*
28474SJose.Borrego@Sun.COM  * CDDL HEADER START
38474SJose.Borrego@Sun.COM  *
48474SJose.Borrego@Sun.COM  * The contents of this file are subject to the terms of the
58474SJose.Borrego@Sun.COM  * Common Development and Distribution License (the "License").
68474SJose.Borrego@Sun.COM  * You may not use this file except in compliance with the License.
78474SJose.Borrego@Sun.COM  *
88474SJose.Borrego@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98474SJose.Borrego@Sun.COM  * or http://www.opensolaris.org/os/licensing.
108474SJose.Borrego@Sun.COM  * See the License for the specific language governing permissions
118474SJose.Borrego@Sun.COM  * and limitations under the License.
128474SJose.Borrego@Sun.COM  *
138474SJose.Borrego@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
148474SJose.Borrego@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158474SJose.Borrego@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
168474SJose.Borrego@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
178474SJose.Borrego@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
188474SJose.Borrego@Sun.COM  *
198474SJose.Borrego@Sun.COM  * CDDL HEADER END
208474SJose.Borrego@Sun.COM  */
218474SJose.Borrego@Sun.COM /*
22*12065SKeyur.Desai@Sun.COM  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
238474SJose.Borrego@Sun.COM  */
248474SJose.Borrego@Sun.COM 
258474SJose.Borrego@Sun.COM /*
268474SJose.Borrego@Sun.COM  * Server Service RPC (SRVSVC) server-side interface definition.
278474SJose.Borrego@Sun.COM  * The server service provides a remote administration interface.
288474SJose.Borrego@Sun.COM  *
298474SJose.Borrego@Sun.COM  * This service uses NERR/Win32 error codes rather than NT status
308474SJose.Borrego@Sun.COM  * values.
318474SJose.Borrego@Sun.COM  */
328474SJose.Borrego@Sun.COM 
338474SJose.Borrego@Sun.COM #include <sys/errno.h>
3410966SJordan.Brown@Sun.COM #include <sys/tzfile.h>
358474SJose.Borrego@Sun.COM #include <unistd.h>
368474SJose.Borrego@Sun.COM #include <netdb.h>
378474SJose.Borrego@Sun.COM #include <strings.h>
388474SJose.Borrego@Sun.COM #include <time.h>
398474SJose.Borrego@Sun.COM #include <thread.h>
408474SJose.Borrego@Sun.COM #include <ctype.h>
418474SJose.Borrego@Sun.COM #include <stdlib.h>
428474SJose.Borrego@Sun.COM #include <string.h>
438474SJose.Borrego@Sun.COM #include <sys/types.h>
448474SJose.Borrego@Sun.COM #include <sys/socket.h>
458474SJose.Borrego@Sun.COM #include <netinet/in.h>
468474SJose.Borrego@Sun.COM #include <arpa/inet.h>
478474SJose.Borrego@Sun.COM #include <libshare.h>
4810504SKeyur.Desai@Sun.COM #include <libnvpair.h>
49*12065SKeyur.Desai@Sun.COM #include <sys/idmap.h>
50*12065SKeyur.Desai@Sun.COM #include <pwd.h>
51*12065SKeyur.Desai@Sun.COM #include <nss_dbdefs.h>
528474SJose.Borrego@Sun.COM #include <smbsrv/libsmb.h>
538474SJose.Borrego@Sun.COM #include <smbsrv/libmlsvc.h>
548474SJose.Borrego@Sun.COM #include <smbsrv/lmerr.h>
558474SJose.Borrego@Sun.COM #include <smbsrv/nmpipes.h>
5610966SJordan.Brown@Sun.COM #include <smbsrv/smb.h>
578474SJose.Borrego@Sun.COM #include <smbsrv/netrauth.h>
588474SJose.Borrego@Sun.COM #include <smbsrv/ndl/srvsvc.ndl>
599832Samw@Sun.COM #include "mlsvc.h"
608474SJose.Borrego@Sun.COM 
618474SJose.Borrego@Sun.COM /*
628474SJose.Borrego@Sun.COM  * Qualifier types for NetConnectEnum.
638474SJose.Borrego@Sun.COM  */
648474SJose.Borrego@Sun.COM #define	SRVSVC_CONNECT_ENUM_NULL	0
658474SJose.Borrego@Sun.COM #define	SRVSVC_CONNECT_ENUM_SHARE	1
668474SJose.Borrego@Sun.COM #define	SRVSVC_CONNECT_ENUM_WKSTN	2
678474SJose.Borrego@Sun.COM 
6810122SJordan.Brown@Sun.COM #define	SMB_SRVSVC_MAXBUFLEN		(8 * 1024 * 1024)
6910122SJordan.Brown@Sun.COM #define	SMB_SRVSVC_MAXPREFLEN		((uint32_t)(-1))
708474SJose.Borrego@Sun.COM 
719832Samw@Sun.COM typedef struct srvsvc_sd {
729832Samw@Sun.COM 	uint8_t *sd_buf;
739832Samw@Sun.COM 	uint32_t sd_size;
749832Samw@Sun.COM } srvsvc_sd_t;
759832Samw@Sun.COM 
769832Samw@Sun.COM typedef struct srvsvc_netshare_setinfo {
779832Samw@Sun.COM 	char *nss_netname;
789832Samw@Sun.COM 	char *nss_comment;
799832Samw@Sun.COM 	char *nss_path;
809832Samw@Sun.COM 	uint32_t nss_type;
819832Samw@Sun.COM 	srvsvc_sd_t nss_sd;
829832Samw@Sun.COM } srvsvc_netshare_setinfo_t;
839832Samw@Sun.COM 
849832Samw@Sun.COM typedef union srvsvc_netshare_getinfo {
859832Samw@Sun.COM 	struct mslm_NetShareInfo_0 nsg_info0;
869832Samw@Sun.COM 	struct mslm_NetShareInfo_1 nsg_info1;
879832Samw@Sun.COM 	struct mslm_NetShareInfo_2 nsg_info2;
889832Samw@Sun.COM 	struct mslm_NetShareInfo_501 nsg_info501;
899832Samw@Sun.COM 	struct mslm_NetShareInfo_502 nsg_info502;
909832Samw@Sun.COM 	struct mslm_NetShareInfo_503 nsg_info503;
919832Samw@Sun.COM 	struct mslm_NetShareInfo_1004 nsg_info1004;
929832Samw@Sun.COM 	struct mslm_NetShareInfo_1005 nsg_info1005;
939832Samw@Sun.COM 	struct mslm_NetShareInfo_1006 nsg_info1006;
949832Samw@Sun.COM 	struct mslm_NetShareInfo_1501 nsg_info1501;
959832Samw@Sun.COM } srvsvc_netshare_getinfo_t;
969832Samw@Sun.COM 
9710122SJordan.Brown@Sun.COM typedef struct mslm_infonres srvsvc_infonres_t;
9810122SJordan.Brown@Sun.COM typedef struct mslm_NetConnectEnum srvsvc_NetConnectEnum_t;
9910122SJordan.Brown@Sun.COM 
10010122SJordan.Brown@Sun.COM static uint32_t srvsvc_netconnectenum_level0(ndr_xa_t *, smb_svcenum_t *,
10110122SJordan.Brown@Sun.COM     srvsvc_NetConnectEnum_t *);
10210122SJordan.Brown@Sun.COM static uint32_t srvsvc_netconnectenum_level1(ndr_xa_t *, smb_svcenum_t *,
10310122SJordan.Brown@Sun.COM     srvsvc_NetConnectEnum_t *);
10410122SJordan.Brown@Sun.COM static uint32_t srvsvc_netconnectenum_common(ndr_xa_t *,
10510122SJordan.Brown@Sun.COM     srvsvc_NetConnectInfo_t *, smb_netsvc_t *, smb_svcenum_t *);
10610122SJordan.Brown@Sun.COM 
10710122SJordan.Brown@Sun.COM static DWORD srvsvc_NetFileEnum2(ndr_xa_t *, struct mslm_NetFileEnum *,
10810122SJordan.Brown@Sun.COM     smb_svcenum_t *se);
10910122SJordan.Brown@Sun.COM static DWORD srvsvc_NetFileEnum3(ndr_xa_t *, struct mslm_NetFileEnum *,
11010122SJordan.Brown@Sun.COM     smb_svcenum_t *se);
11110122SJordan.Brown@Sun.COM 
11210122SJordan.Brown@Sun.COM static uint32_t srvsvc_NetSessionEnumCommon(ndr_xa_t *, srvsvc_infonres_t *,
11310122SJordan.Brown@Sun.COM     smb_netsvc_t *, smb_svcenum_t *);
11410122SJordan.Brown@Sun.COM 
11510122SJordan.Brown@Sun.COM static DWORD mlsvc_NetShareEnumLevel0(ndr_xa_t *, srvsvc_infonres_t *,
11610122SJordan.Brown@Sun.COM     smb_svcenum_t *, int);
11710122SJordan.Brown@Sun.COM static DWORD mlsvc_NetShareEnumLevel1(ndr_xa_t *, srvsvc_infonres_t *,
11810122SJordan.Brown@Sun.COM     smb_svcenum_t *, int);
11910122SJordan.Brown@Sun.COM static DWORD mlsvc_NetShareEnumLevel2(ndr_xa_t *, srvsvc_infonres_t *,
12010122SJordan.Brown@Sun.COM     smb_svcenum_t *, int);
12110122SJordan.Brown@Sun.COM static DWORD mlsvc_NetShareEnumLevel501(ndr_xa_t *, srvsvc_infonres_t *,
12210122SJordan.Brown@Sun.COM     smb_svcenum_t *, int);
12310122SJordan.Brown@Sun.COM static DWORD mlsvc_NetShareEnumLevel502(ndr_xa_t *, srvsvc_infonres_t *,
12410122SJordan.Brown@Sun.COM     smb_svcenum_t *, int);
12510122SJordan.Brown@Sun.COM static DWORD mlsvc_NetShareEnumCommon(ndr_xa_t *, smb_svcenum_t *,
12610122SJordan.Brown@Sun.COM     smb_share_t *, void *);
12710122SJordan.Brown@Sun.COM static boolean_t srvsvc_add_autohome(ndr_xa_t *, smb_svcenum_t *, void *);
1288474SJose.Borrego@Sun.COM static char *srvsvc_share_mkpath(ndr_xa_t *, char *);
1299832Samw@Sun.COM static uint32_t srvsvc_share_getsd(ndr_xa_t *, smb_share_t *, srvsvc_sd_t *);
1308474SJose.Borrego@Sun.COM 
1318474SJose.Borrego@Sun.COM static int srvsvc_netconnect_qualifier(const char *);
13210122SJordan.Brown@Sun.COM static void srvsvc_estimate_limit(smb_svcenum_t *, uint32_t);
13310122SJordan.Brown@Sun.COM static uint32_t srvsvc_open_sessions(void);
13410122SJordan.Brown@Sun.COM static uint32_t srvsvc_open_connections(uint32_t, const char *);
13510122SJordan.Brown@Sun.COM static uint32_t srvsvc_open_files(void);
1368474SJose.Borrego@Sun.COM 
1379832Samw@Sun.COM static uint32_t srvsvc_modify_share(smb_share_t *,
1389832Samw@Sun.COM     srvsvc_netshare_setinfo_t *);
1399832Samw@Sun.COM static uint32_t srvsvc_modify_transient_share(smb_share_t *,
1409832Samw@Sun.COM     srvsvc_netshare_setinfo_t *);
1419832Samw@Sun.COM static uint32_t srvsvc_update_share_flags(smb_share_t *, uint32_t);
14210504SKeyur.Desai@Sun.COM static uint32_t srvsvc_get_share_flags(smb_share_t *);
1439832Samw@Sun.COM 
1448474SJose.Borrego@Sun.COM static uint32_t srvsvc_sa_add(char *, char *, char *);
1458474SJose.Borrego@Sun.COM static uint32_t srvsvc_sa_delete(char *);
1469832Samw@Sun.COM static uint32_t srvsvc_sa_modify(smb_share_t *, srvsvc_netshare_setinfo_t *);
14710504SKeyur.Desai@Sun.COM static uint32_t srvsvc_sa_setprop(smb_share_t *, nvlist_t *);
1488474SJose.Borrego@Sun.COM 
1498474SJose.Borrego@Sun.COM static char empty_string[1];
1508474SJose.Borrego@Sun.COM 
1518474SJose.Borrego@Sun.COM static ndr_stub_table_t srvsvc_stub_table[];
1528474SJose.Borrego@Sun.COM 
1538474SJose.Borrego@Sun.COM static ndr_service_t srvsvc_service = {
1548474SJose.Borrego@Sun.COM 	"SRVSVC",			/* name */
1558474SJose.Borrego@Sun.COM 	"Server services",		/* desc */
1568474SJose.Borrego@Sun.COM 	"\\srvsvc",			/* endpoint */
1578474SJose.Borrego@Sun.COM 	PIPE_NTSVCS,			/* sec_addr_port */
1588474SJose.Borrego@Sun.COM 	"4b324fc8-1670-01d3-1278-5a47bf6ee188", 3,	/* abstract */
1598474SJose.Borrego@Sun.COM 	NDR_TRANSFER_SYNTAX_UUID,		2,	/* transfer */
1608474SJose.Borrego@Sun.COM 	0,				/* no bind_instance_size */
1618474SJose.Borrego@Sun.COM 	0,				/* no bind_req() */
1628474SJose.Borrego@Sun.COM 	0,				/* no unbind_and_close() */
1638474SJose.Borrego@Sun.COM 	0,				/* use generic_call_stub() */
1648474SJose.Borrego@Sun.COM 	&TYPEINFO(srvsvc_interface),	/* interface ti */
1658474SJose.Borrego@Sun.COM 	srvsvc_stub_table		/* stub_table */
1668474SJose.Borrego@Sun.COM };
1678474SJose.Borrego@Sun.COM 
1688474SJose.Borrego@Sun.COM /*
1698474SJose.Borrego@Sun.COM  * srvsvc_initialize
1708474SJose.Borrego@Sun.COM  *
1718474SJose.Borrego@Sun.COM  * This function registers the SRVSVC RPC interface with the RPC runtime
1728474SJose.Borrego@Sun.COM  * library. It must be called in order to use either the client side
1738474SJose.Borrego@Sun.COM  * or the server side functions.
1748474SJose.Borrego@Sun.COM  */
1758474SJose.Borrego@Sun.COM void
1768474SJose.Borrego@Sun.COM srvsvc_initialize(void)
1778474SJose.Borrego@Sun.COM {
1788474SJose.Borrego@Sun.COM 	(void) ndr_svc_register(&srvsvc_service);
1798474SJose.Borrego@Sun.COM }
1808474SJose.Borrego@Sun.COM 
1818474SJose.Borrego@Sun.COM /*
18211963SAfshin.Ardakani@Sun.COM  * Turn "dfsroot" property on/off for the specified
18311963SAfshin.Ardakani@Sun.COM  * share and save it.
18411963SAfshin.Ardakani@Sun.COM  *
18511963SAfshin.Ardakani@Sun.COM  * If the requested value is the same as what is already
18611963SAfshin.Ardakani@Sun.COM  * set then no change is required and the function returns.
18711963SAfshin.Ardakani@Sun.COM  */
18811963SAfshin.Ardakani@Sun.COM uint32_t
18911963SAfshin.Ardakani@Sun.COM srvsvc_shr_setdfsroot(smb_share_t *si, boolean_t on)
19011963SAfshin.Ardakani@Sun.COM {
19111963SAfshin.Ardakani@Sun.COM 	char *dfs = NULL;
19211963SAfshin.Ardakani@Sun.COM 	nvlist_t *nvl;
19311963SAfshin.Ardakani@Sun.COM 	uint32_t nerr;
19411963SAfshin.Ardakani@Sun.COM 
19511963SAfshin.Ardakani@Sun.COM 	if (on && ((si->shr_flags & SMB_SHRF_DFSROOT) == 0)) {
19611963SAfshin.Ardakani@Sun.COM 		si->shr_flags |= SMB_SHRF_DFSROOT;
19711963SAfshin.Ardakani@Sun.COM 		dfs = "true";
19811963SAfshin.Ardakani@Sun.COM 	} else if (!on && (si->shr_flags & SMB_SHRF_DFSROOT)) {
19911963SAfshin.Ardakani@Sun.COM 		si->shr_flags &= ~SMB_SHRF_DFSROOT;
20011963SAfshin.Ardakani@Sun.COM 		dfs = "false";
20111963SAfshin.Ardakani@Sun.COM 	}
20211963SAfshin.Ardakani@Sun.COM 
20311963SAfshin.Ardakani@Sun.COM 	if (dfs == NULL)
20411963SAfshin.Ardakani@Sun.COM 		return (ERROR_SUCCESS);
20511963SAfshin.Ardakani@Sun.COM 
20611963SAfshin.Ardakani@Sun.COM 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
20711963SAfshin.Ardakani@Sun.COM 		return (NERR_InternalError);
20811963SAfshin.Ardakani@Sun.COM 
20911963SAfshin.Ardakani@Sun.COM 	if (nvlist_add_string(nvl, SHOPT_DFSROOT, dfs) != 0) {
21011963SAfshin.Ardakani@Sun.COM 		nvlist_free(nvl);
21111963SAfshin.Ardakani@Sun.COM 		return (NERR_InternalError);
21211963SAfshin.Ardakani@Sun.COM 	}
21311963SAfshin.Ardakani@Sun.COM 
21411963SAfshin.Ardakani@Sun.COM 	nerr = srvsvc_sa_setprop(si, nvl);
21511963SAfshin.Ardakani@Sun.COM 	nvlist_free(nvl);
21611963SAfshin.Ardakani@Sun.COM 
21711963SAfshin.Ardakani@Sun.COM 	if (nerr != NERR_Success)
21811963SAfshin.Ardakani@Sun.COM 		return (nerr);
21911963SAfshin.Ardakani@Sun.COM 
22011963SAfshin.Ardakani@Sun.COM 	return (smb_shr_modify(si));
22111963SAfshin.Ardakani@Sun.COM }
22211963SAfshin.Ardakani@Sun.COM 
22311963SAfshin.Ardakani@Sun.COM /*
2248474SJose.Borrego@Sun.COM  * srvsvc_s_NetConnectEnum
2258474SJose.Borrego@Sun.COM  *
2268474SJose.Borrego@Sun.COM  * List tree connections made to a share on this server or all tree
2278474SJose.Borrego@Sun.COM  * connections established from a specific client.  Administrator,
2288474SJose.Borrego@Sun.COM  * Server Operator, Print Operator or Power User group membership
2298474SJose.Borrego@Sun.COM  * is required to use this interface.
2308474SJose.Borrego@Sun.COM  *
2318474SJose.Borrego@Sun.COM  * There are three information levels:  0, 1, and 50.  We don't support
2328474SJose.Borrego@Sun.COM  * level 50, which is only used by Windows 9x clients.
2338474SJose.Borrego@Sun.COM  *
2348474SJose.Borrego@Sun.COM  * It seems Server Manger (srvmgr) only sends workstation as the qualifier
2358474SJose.Borrego@Sun.COM  * and the Computer Management Interface on Windows 2000 doesn't request
2368474SJose.Borrego@Sun.COM  * a list of connections.
2378474SJose.Borrego@Sun.COM  *
2388474SJose.Borrego@Sun.COM  * Return Values:
2398474SJose.Borrego@Sun.COM  * ERROR_SUCCESS            Success
2408474SJose.Borrego@Sun.COM  * ERROR_ACCESS_DENIED      Caller does not have access to this call.
2418474SJose.Borrego@Sun.COM  * ERROR_INVALID_PARAMETER  One of the parameters is invalid.
2428474SJose.Borrego@Sun.COM  * ERROR_INVALID_LEVEL      Unknown information level specified.
2438474SJose.Borrego@Sun.COM  * ERROR_MORE_DATA          Partial date returned, more entries available.
2448474SJose.Borrego@Sun.COM  * ERROR_NOT_ENOUGH_MEMORY  Insufficient memory is available.
2458474SJose.Borrego@Sun.COM  * NERR_NetNameNotFound     The share qualifier cannot be found.
2468474SJose.Borrego@Sun.COM  * NERR_BufTooSmall         The supplied buffer is too small.
2478474SJose.Borrego@Sun.COM  */
2488474SJose.Borrego@Sun.COM static int
2498474SJose.Borrego@Sun.COM srvsvc_s_NetConnectEnum(void *arg, ndr_xa_t *mxa)
2508474SJose.Borrego@Sun.COM {
25110122SJordan.Brown@Sun.COM 	srvsvc_NetConnectEnum_t		*param = arg;
25210122SJordan.Brown@Sun.COM 	smb_netsvc_t			*ns;
25310122SJordan.Brown@Sun.COM 	smb_svcenum_t			se;
25410122SJordan.Brown@Sun.COM 	char				*qualifier;
25510122SJordan.Brown@Sun.COM 	int				qualtype;
25610122SJordan.Brown@Sun.COM 	DWORD				status = ERROR_SUCCESS;
2578474SJose.Borrego@Sun.COM 
2588474SJose.Borrego@Sun.COM 	if (!ndr_is_poweruser(mxa)) {
25910122SJordan.Brown@Sun.COM 		status = ERROR_ACCESS_DENIED;
26010122SJordan.Brown@Sun.COM 		goto srvsvc_netconnectenum_error;
2618474SJose.Borrego@Sun.COM 	}
2628474SJose.Borrego@Sun.COM 
2638474SJose.Borrego@Sun.COM 	qualifier = (char *)param->qualifier;
2648474SJose.Borrego@Sun.COM 	qualtype = srvsvc_netconnect_qualifier(qualifier);
2658474SJose.Borrego@Sun.COM 	if (qualtype == SRVSVC_CONNECT_ENUM_NULL) {
26610122SJordan.Brown@Sun.COM 		status = NERR_NetNameNotFound;
26710122SJordan.Brown@Sun.COM 		goto srvsvc_netconnectenum_error;
26810122SJordan.Brown@Sun.COM 	}
26910122SJordan.Brown@Sun.COM 
27010122SJordan.Brown@Sun.COM 	param->total_entries = srvsvc_open_connections(qualtype, qualifier);
27110122SJordan.Brown@Sun.COM 	if (param->total_entries == 0) {
27210122SJordan.Brown@Sun.COM 		bzero(param, sizeof (srvsvc_NetConnectEnum_t));
27310122SJordan.Brown@Sun.COM 		param->status = ERROR_SUCCESS;
2748474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
2758474SJose.Borrego@Sun.COM 	}
2768474SJose.Borrego@Sun.COM 
27710122SJordan.Brown@Sun.COM 	bzero(&se, sizeof (smb_svcenum_t));
27810122SJordan.Brown@Sun.COM 	se.se_type = SMB_SVCENUM_TYPE_TREE;
27910122SJordan.Brown@Sun.COM 	se.se_level = param->info.level;
28010122SJordan.Brown@Sun.COM 	se.se_ntotal = param->total_entries;
28110122SJordan.Brown@Sun.COM 	se.se_nlimit = se.se_ntotal;
28210122SJordan.Brown@Sun.COM 
28310122SJordan.Brown@Sun.COM 	if (param->pref_max_len == SMB_SRVSVC_MAXPREFLEN ||
28410122SJordan.Brown@Sun.COM 	    param->pref_max_len > SMB_SRVSVC_MAXBUFLEN)
28510122SJordan.Brown@Sun.COM 		se.se_prefmaxlen = SMB_SRVSVC_MAXBUFLEN;
28610122SJordan.Brown@Sun.COM 	else
28710122SJordan.Brown@Sun.COM 		se.se_prefmaxlen = param->pref_max_len;
28810122SJordan.Brown@Sun.COM 
28910122SJordan.Brown@Sun.COM 	if (param->resume_handle) {
29010122SJordan.Brown@Sun.COM 		se.se_resume = *param->resume_handle;
29110122SJordan.Brown@Sun.COM 		se.se_nskip = se.se_resume;
29210122SJordan.Brown@Sun.COM 		*param->resume_handle = 0;
29310122SJordan.Brown@Sun.COM 	}
29410122SJordan.Brown@Sun.COM 
2958474SJose.Borrego@Sun.COM 	switch (param->info.level) {
2968474SJose.Borrego@Sun.COM 	case 0:
29710122SJordan.Brown@Sun.COM 		status = srvsvc_netconnectenum_level0(mxa, &se, param);
2988474SJose.Borrego@Sun.COM 		break;
2998474SJose.Borrego@Sun.COM 	case 1:
30010122SJordan.Brown@Sun.COM 		status = srvsvc_netconnectenum_level1(mxa, &se, param);
3018474SJose.Borrego@Sun.COM 		break;
3028474SJose.Borrego@Sun.COM 	case 50:
3038474SJose.Borrego@Sun.COM 		status = ERROR_NOT_SUPPORTED;
3048474SJose.Borrego@Sun.COM 		break;
3058474SJose.Borrego@Sun.COM 	default:
3068474SJose.Borrego@Sun.COM 		status = ERROR_INVALID_LEVEL;
3078474SJose.Borrego@Sun.COM 		break;
3088474SJose.Borrego@Sun.COM 	}
3098474SJose.Borrego@Sun.COM 
3108474SJose.Borrego@Sun.COM 	if (status != ERROR_SUCCESS)
31110122SJordan.Brown@Sun.COM 		goto srvsvc_netconnectenum_error;
31210122SJordan.Brown@Sun.COM 
31310122SJordan.Brown@Sun.COM 	if ((ns = smb_kmod_enum_init(&se)) == NULL) {
31410122SJordan.Brown@Sun.COM 		status = ERROR_NOT_ENOUGH_MEMORY;
31510122SJordan.Brown@Sun.COM 		goto srvsvc_netconnectenum_error;
31610122SJordan.Brown@Sun.COM 	}
31710122SJordan.Brown@Sun.COM 
31810122SJordan.Brown@Sun.COM 	status = srvsvc_netconnectenum_common(mxa, &param->info, ns, &se);
31910122SJordan.Brown@Sun.COM 	smb_kmod_enum_fini(ns);
32010122SJordan.Brown@Sun.COM 
32110122SJordan.Brown@Sun.COM 	if (status != ERROR_SUCCESS)
32210122SJordan.Brown@Sun.COM 		goto srvsvc_netconnectenum_error;
32310122SJordan.Brown@Sun.COM 
32410122SJordan.Brown@Sun.COM 	if (param->resume_handle &&
32510122SJordan.Brown@Sun.COM 	    param->pref_max_len != SMB_SRVSVC_MAXPREFLEN) {
32610122SJordan.Brown@Sun.COM 		if (se.se_resume < param->total_entries) {
32710122SJordan.Brown@Sun.COM 			*param->resume_handle = se.se_resume;
32810122SJordan.Brown@Sun.COM 			status = ERROR_MORE_DATA;
32910122SJordan.Brown@Sun.COM 		}
33010122SJordan.Brown@Sun.COM 	}
33110122SJordan.Brown@Sun.COM 
33210122SJordan.Brown@Sun.COM 	param->status = status;
33310122SJordan.Brown@Sun.COM 	return (NDR_DRC_OK);
33410122SJordan.Brown@Sun.COM 
33510122SJordan.Brown@Sun.COM srvsvc_netconnectenum_error:
33610122SJordan.Brown@Sun.COM 	bzero(param, sizeof (srvsvc_NetConnectEnum_t));
3378474SJose.Borrego@Sun.COM 	param->status = status;
3388474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
3398474SJose.Borrego@Sun.COM }
3408474SJose.Borrego@Sun.COM 
34110122SJordan.Brown@Sun.COM /*
34210122SJordan.Brown@Sun.COM  * Allocate memory and estimate the number of objects that can
34310122SJordan.Brown@Sun.COM  * be returned for NetConnectEnum level 0.
34410122SJordan.Brown@Sun.COM  */
34510122SJordan.Brown@Sun.COM static uint32_t
34610122SJordan.Brown@Sun.COM srvsvc_netconnectenum_level0(ndr_xa_t *mxa, smb_svcenum_t *se,
34710122SJordan.Brown@Sun.COM     srvsvc_NetConnectEnum_t *param)
3488474SJose.Borrego@Sun.COM {
34910122SJordan.Brown@Sun.COM 	srvsvc_NetConnectInfo0_t	*info0;
35010122SJordan.Brown@Sun.COM 	srvsvc_NetConnectInfoBuf0_t	*ci0;
35110122SJordan.Brown@Sun.COM 
35210122SJordan.Brown@Sun.COM 	if ((info0 = NDR_NEW(mxa, srvsvc_NetConnectInfo0_t)) == NULL)
35310122SJordan.Brown@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
35410122SJordan.Brown@Sun.COM 
35510122SJordan.Brown@Sun.COM 	bzero(info0, sizeof (srvsvc_NetConnectInfo0_t));
35610122SJordan.Brown@Sun.COM 	param->info.ru.info0 = info0;
35710122SJordan.Brown@Sun.COM 
35810122SJordan.Brown@Sun.COM 	srvsvc_estimate_limit(se, sizeof (srvsvc_NetConnectInfoBuf0_t));
35910122SJordan.Brown@Sun.COM 	if (se->se_nlimit == 0)
36010122SJordan.Brown@Sun.COM 		return (NERR_BufTooSmall);
36110122SJordan.Brown@Sun.COM 
36210122SJordan.Brown@Sun.COM 	do {
36310122SJordan.Brown@Sun.COM 		ci0 = NDR_NEWN(mxa, srvsvc_NetConnectInfoBuf0_t, se->se_nlimit);
36410122SJordan.Brown@Sun.COM 		if (ci0 == NULL)
36510122SJordan.Brown@Sun.COM 			se->se_nlimit >>= 1;
36610122SJordan.Brown@Sun.COM 	} while ((se->se_nlimit > 0) && (ci0 == NULL));
36710122SJordan.Brown@Sun.COM 
3688474SJose.Borrego@Sun.COM 	if (ci0 == NULL)
3698474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
3708474SJose.Borrego@Sun.COM 
3718474SJose.Borrego@Sun.COM 	info0->ci0 = ci0;
37210122SJordan.Brown@Sun.COM 	info0->entries_read = 0;
3738474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
3748474SJose.Borrego@Sun.COM }
3758474SJose.Borrego@Sun.COM 
37610122SJordan.Brown@Sun.COM /*
37710122SJordan.Brown@Sun.COM  * Allocate memory and estimate the number of objects that can
37810122SJordan.Brown@Sun.COM  * be returned for NetConnectEnum level 1.
37910122SJordan.Brown@Sun.COM  */
38010122SJordan.Brown@Sun.COM static uint32_t
38110122SJordan.Brown@Sun.COM srvsvc_netconnectenum_level1(ndr_xa_t *mxa, smb_svcenum_t *se,
38210122SJordan.Brown@Sun.COM     srvsvc_NetConnectEnum_t *param)
3838474SJose.Borrego@Sun.COM {
38410122SJordan.Brown@Sun.COM 	srvsvc_NetConnectInfo1_t	*info1;
38510122SJordan.Brown@Sun.COM 	srvsvc_NetConnectInfoBuf1_t	*ci1;
38610122SJordan.Brown@Sun.COM 
38710122SJordan.Brown@Sun.COM 	if ((info1 = NDR_NEW(mxa, srvsvc_NetConnectInfo1_t)) == NULL)
38810122SJordan.Brown@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
38910122SJordan.Brown@Sun.COM 
39010122SJordan.Brown@Sun.COM 	bzero(info1, sizeof (srvsvc_NetConnectInfo1_t));
39110122SJordan.Brown@Sun.COM 	param->info.ru.info1 = info1;
39210122SJordan.Brown@Sun.COM 
39310122SJordan.Brown@Sun.COM 	srvsvc_estimate_limit(se,
39410122SJordan.Brown@Sun.COM 	    sizeof (srvsvc_NetConnectInfoBuf1_t) + MAXNAMELEN);
39510122SJordan.Brown@Sun.COM 	if (se->se_nlimit == 0)
39610122SJordan.Brown@Sun.COM 		return (NERR_BufTooSmall);
39710122SJordan.Brown@Sun.COM 
39810122SJordan.Brown@Sun.COM 	do {
39910122SJordan.Brown@Sun.COM 		ci1 = NDR_NEWN(mxa, srvsvc_NetConnectInfoBuf1_t, se->se_nlimit);
40010122SJordan.Brown@Sun.COM 		if (ci1 == NULL)
40110122SJordan.Brown@Sun.COM 			se->se_nlimit >>= 1;
40210122SJordan.Brown@Sun.COM 	} while ((se->se_nlimit > 0) && (ci1 == NULL));
40310122SJordan.Brown@Sun.COM 
4048474SJose.Borrego@Sun.COM 	if (ci1 == NULL)
4058474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
4068474SJose.Borrego@Sun.COM 
4078474SJose.Borrego@Sun.COM 	info1->ci1 = ci1;
40810122SJordan.Brown@Sun.COM 	info1->entries_read = 0;
40910122SJordan.Brown@Sun.COM 	return (ERROR_SUCCESS);
41010122SJordan.Brown@Sun.COM }
41110122SJordan.Brown@Sun.COM 
41210122SJordan.Brown@Sun.COM /*
41310122SJordan.Brown@Sun.COM  * Request a list of connections from the kernel and set up
41410122SJordan.Brown@Sun.COM  * the connection information to be returned to the client.
41510122SJordan.Brown@Sun.COM  */
41610122SJordan.Brown@Sun.COM static uint32_t
41710122SJordan.Brown@Sun.COM srvsvc_netconnectenum_common(ndr_xa_t *mxa, srvsvc_NetConnectInfo_t *info,
41810122SJordan.Brown@Sun.COM     smb_netsvc_t *ns, smb_svcenum_t *se)
41910122SJordan.Brown@Sun.COM {
42010122SJordan.Brown@Sun.COM 	srvsvc_NetConnectInfo0_t	*info0;
42110122SJordan.Brown@Sun.COM 	srvsvc_NetConnectInfo1_t	*info1;
42210122SJordan.Brown@Sun.COM 	srvsvc_NetConnectInfoBuf0_t	*ci0;
42310122SJordan.Brown@Sun.COM 	srvsvc_NetConnectInfoBuf1_t	*ci1;
42410122SJordan.Brown@Sun.COM 	smb_netsvcitem_t		*item;
42510122SJordan.Brown@Sun.COM 	smb_netconnectinfo_t		*tree;
42610122SJordan.Brown@Sun.COM 
42710122SJordan.Brown@Sun.COM 	if (smb_kmod_enum(ns) != 0)
42810122SJordan.Brown@Sun.COM 		return (ERROR_INTERNAL_ERROR);
42910122SJordan.Brown@Sun.COM 
43010122SJordan.Brown@Sun.COM 	info0 = info->ru.info0;
43110122SJordan.Brown@Sun.COM 	ci0 = info0->ci0;
43210122SJordan.Brown@Sun.COM 
43310122SJordan.Brown@Sun.COM 	info1 = info->ru.info1;
43410122SJordan.Brown@Sun.COM 	ci1 = info1->ci1;
43510122SJordan.Brown@Sun.COM 
43610122SJordan.Brown@Sun.COM 	item = list_head(&ns->ns_list);
43710122SJordan.Brown@Sun.COM 	while (item != NULL) {
43810122SJordan.Brown@Sun.COM 		tree = &item->nsi_un.nsi_tree;
43910122SJordan.Brown@Sun.COM 
44010122SJordan.Brown@Sun.COM 		switch (se->se_level) {
44110122SJordan.Brown@Sun.COM 		case 0:
44210122SJordan.Brown@Sun.COM 			ci0->coni0_id = tree->ci_id;
44310122SJordan.Brown@Sun.COM 			++ci0;
44410122SJordan.Brown@Sun.COM 			++info0->entries_read;
44510122SJordan.Brown@Sun.COM 			break;
44610122SJordan.Brown@Sun.COM 		case 1:
44710122SJordan.Brown@Sun.COM 			ci1->coni1_id = tree->ci_id;
44810122SJordan.Brown@Sun.COM 			ci1->coni1_type = tree->ci_type;
44910122SJordan.Brown@Sun.COM 			ci1->coni1_num_opens = tree->ci_numopens;
45010122SJordan.Brown@Sun.COM 			ci1->coni1_num_users = tree->ci_numusers;
45110122SJordan.Brown@Sun.COM 			ci1->coni1_time = tree->ci_time;
45210122SJordan.Brown@Sun.COM 			ci1->coni1_username = (uint8_t *)
45310122SJordan.Brown@Sun.COM 			    NDR_STRDUP(mxa, tree->ci_username);
45410122SJordan.Brown@Sun.COM 			ci1->coni1_netname = (uint8_t *)
45510122SJordan.Brown@Sun.COM 			    NDR_STRDUP(mxa, tree->ci_share);
45610122SJordan.Brown@Sun.COM 			++ci1;
45710122SJordan.Brown@Sun.COM 			++info1->entries_read;
45810122SJordan.Brown@Sun.COM 			break;
45910122SJordan.Brown@Sun.COM 		default:
46010122SJordan.Brown@Sun.COM 			return (ERROR_INVALID_LEVEL);
46110122SJordan.Brown@Sun.COM 		}
46210122SJordan.Brown@Sun.COM 
46310122SJordan.Brown@Sun.COM 		++se->se_resume;
46410122SJordan.Brown@Sun.COM 		item = list_next(&ns->ns_list, item);
46510122SJordan.Brown@Sun.COM 	}
46610122SJordan.Brown@Sun.COM 
4678474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
4688474SJose.Borrego@Sun.COM }
4698474SJose.Borrego@Sun.COM 
4708474SJose.Borrego@Sun.COM /*
4718474SJose.Borrego@Sun.COM  * srvsvc_netconnect_qualifier
4728474SJose.Borrego@Sun.COM  *
4738474SJose.Borrego@Sun.COM  * The qualifier is a string that specifies a share name or computer name
4748474SJose.Borrego@Sun.COM  * for the connections of interest.  If it is a share name then all the
4758474SJose.Borrego@Sun.COM  * connections made to that share name are listed.  If it is a computer
4768474SJose.Borrego@Sun.COM  * name (it starts with two backslash characters), then NetConnectEnum
4778474SJose.Borrego@Sun.COM  * lists all connections made from that computer to the specified server.
4788474SJose.Borrego@Sun.COM  */
4798474SJose.Borrego@Sun.COM static int
4808474SJose.Borrego@Sun.COM srvsvc_netconnect_qualifier(const char *qualifier)
4818474SJose.Borrego@Sun.COM {
4828474SJose.Borrego@Sun.COM 	if (qualifier == NULL || *qualifier == '\0')
4838474SJose.Borrego@Sun.COM 		return (SRVSVC_CONNECT_ENUM_NULL);
4848474SJose.Borrego@Sun.COM 
4858474SJose.Borrego@Sun.COM 	if (strlen(qualifier) > MAXHOSTNAMELEN)
4868474SJose.Borrego@Sun.COM 		return (SRVSVC_CONNECT_ENUM_NULL);
4878474SJose.Borrego@Sun.COM 
4888474SJose.Borrego@Sun.COM 	if (qualifier[0] == '\\' && qualifier[1] == '\\') {
4898474SJose.Borrego@Sun.COM 		return (SRVSVC_CONNECT_ENUM_WKSTN);
4908474SJose.Borrego@Sun.COM 	} else {
4918474SJose.Borrego@Sun.COM 		if (!smb_shr_exists((char *)qualifier))
4928474SJose.Borrego@Sun.COM 			return (SRVSVC_CONNECT_ENUM_NULL);
4938474SJose.Borrego@Sun.COM 
4948474SJose.Borrego@Sun.COM 		return (SRVSVC_CONNECT_ENUM_SHARE);
4958474SJose.Borrego@Sun.COM 	}
4968474SJose.Borrego@Sun.COM }
4978474SJose.Borrego@Sun.COM 
49810122SJordan.Brown@Sun.COM static uint32_t
49910122SJordan.Brown@Sun.COM srvsvc_open_sessions(void)
50010122SJordan.Brown@Sun.COM {
50110122SJordan.Brown@Sun.COM 	smb_opennum_t	opennum;
50210122SJordan.Brown@Sun.COM 
50310122SJordan.Brown@Sun.COM 	bzero(&opennum, sizeof (smb_opennum_t));
50410122SJordan.Brown@Sun.COM 	if (smb_kmod_get_open_num(&opennum) != 0)
50510122SJordan.Brown@Sun.COM 		return (0);
50610122SJordan.Brown@Sun.COM 
50710122SJordan.Brown@Sun.COM 	return (opennum.open_users);
50810122SJordan.Brown@Sun.COM }
50910122SJordan.Brown@Sun.COM 
51010122SJordan.Brown@Sun.COM static uint32_t
51110122SJordan.Brown@Sun.COM srvsvc_open_connections(uint32_t qualtype, const char *qualifier)
51210122SJordan.Brown@Sun.COM {
51310122SJordan.Brown@Sun.COM 	smb_opennum_t	opennum;
51410122SJordan.Brown@Sun.COM 
51510122SJordan.Brown@Sun.COM 	bzero(&opennum, sizeof (smb_opennum_t));
51610122SJordan.Brown@Sun.COM 	opennum.qualtype = qualtype;
51710122SJordan.Brown@Sun.COM 	(void) strlcpy(opennum.qualifier, qualifier, MAXNAMELEN);
51810122SJordan.Brown@Sun.COM 
51910122SJordan.Brown@Sun.COM 	if (smb_kmod_get_open_num(&opennum) != 0)
52010122SJordan.Brown@Sun.COM 		return (0);
52110122SJordan.Brown@Sun.COM 
52210122SJordan.Brown@Sun.COM 	return (opennum.open_trees);
52310122SJordan.Brown@Sun.COM }
52410122SJordan.Brown@Sun.COM 
52510122SJordan.Brown@Sun.COM static uint32_t
52610122SJordan.Brown@Sun.COM srvsvc_open_files(void)
52710122SJordan.Brown@Sun.COM {
52810122SJordan.Brown@Sun.COM 	smb_opennum_t	opennum;
52910122SJordan.Brown@Sun.COM 
53010122SJordan.Brown@Sun.COM 	bzero(&opennum, sizeof (smb_opennum_t));
53110122SJordan.Brown@Sun.COM 	if (smb_kmod_get_open_num(&opennum) != 0)
53210122SJordan.Brown@Sun.COM 		return (0);
53310122SJordan.Brown@Sun.COM 
53410122SJordan.Brown@Sun.COM 	return (opennum.open_files);
53510122SJordan.Brown@Sun.COM }
53610122SJordan.Brown@Sun.COM 
5378474SJose.Borrego@Sun.COM /*
5388474SJose.Borrego@Sun.COM  * srvsvc_s_NetFileEnum
5398474SJose.Borrego@Sun.COM  *
5408474SJose.Borrego@Sun.COM  * Return information on open files or named pipes. Only members of the
5418474SJose.Borrego@Sun.COM  * Administrators or Server Operators local groups are allowed to make
5428474SJose.Borrego@Sun.COM  * this call. Currently, we only support Administrators.
5438474SJose.Borrego@Sun.COM  *
5448474SJose.Borrego@Sun.COM  * If basepath is null, all open resources are enumerated. If basepath
5458474SJose.Borrego@Sun.COM  * is non-null, only resources that have basepath as a prefix should
5468474SJose.Borrego@Sun.COM  * be returned.
5478474SJose.Borrego@Sun.COM  *
5488474SJose.Borrego@Sun.COM  * If username is specified (non-null), only files opened by username
5498474SJose.Borrego@Sun.COM  * should be returned.
5508474SJose.Borrego@Sun.COM  *
5518474SJose.Borrego@Sun.COM  * Notes:
5528474SJose.Borrego@Sun.COM  * 1. We don't validate the servername because we would have to check
5538474SJose.Borrego@Sun.COM  * all primary IPs and the ROI seems unlikely to be worth it.
5548474SJose.Borrego@Sun.COM  * 2. Both basepath and username are currently ignored because both
5558474SJose.Borrego@Sun.COM  * Server Manger (NT 4.0) and CMI (Windows 2000) always set them to null.
5568474SJose.Borrego@Sun.COM  *
5578474SJose.Borrego@Sun.COM  * The level of information requested may be one of:
5588474SJose.Borrego@Sun.COM  *
5598474SJose.Borrego@Sun.COM  *  2   Return the file identification number.
5608474SJose.Borrego@Sun.COM  *      This level is not supported on Windows Me/98/95.
5618474SJose.Borrego@Sun.COM  *
5628474SJose.Borrego@Sun.COM  *  3   Return information about the file.
5638474SJose.Borrego@Sun.COM  *      This level is not supported on Windows Me/98/95.
5648474SJose.Borrego@Sun.COM  *
5658474SJose.Borrego@Sun.COM  *  50  Windows Me/98/95:  Return information about the file.
5668474SJose.Borrego@Sun.COM  *
5678474SJose.Borrego@Sun.COM  * Note:
5688474SJose.Borrego@Sun.COM  * If pref_max_len is unlimited and resume_handle is null, the client
5698474SJose.Borrego@Sun.COM  * expects to receive all data in a single call.
5708474SJose.Borrego@Sun.COM  * If we are unable to do fit all data in a single response, we would
5718474SJose.Borrego@Sun.COM  * normally return ERROR_MORE_DATA with a partial list.
5728474SJose.Borrego@Sun.COM  *
5738474SJose.Borrego@Sun.COM  * Unfortunately, when both of these conditions occur, Server Manager
5748474SJose.Borrego@Sun.COM  * pops up an error box with the message "more data available" and
5758474SJose.Borrego@Sun.COM  * doesn't display any of the returned data. In this case, it is
5768474SJose.Borrego@Sun.COM  * probably better to return ERROR_SUCCESS with the partial list.
5778474SJose.Borrego@Sun.COM  * Windows 2000 doesn't have this problem because it always sends a
5788474SJose.Borrego@Sun.COM  * non-null resume_handle.
5798474SJose.Borrego@Sun.COM  *
5808474SJose.Borrego@Sun.COM  * Return Values:
5818474SJose.Borrego@Sun.COM  * ERROR_SUCCESS            Success
5828474SJose.Borrego@Sun.COM  * ERROR_ACCESS_DENIED      Caller does not have access to this call.
5838474SJose.Borrego@Sun.COM  * ERROR_INVALID_PARAMETER  One of the parameters is invalid.
5848474SJose.Borrego@Sun.COM  * ERROR_INVALID_LEVEL      Unknown information level specified.
5858474SJose.Borrego@Sun.COM  * ERROR_MORE_DATA          Partial date returned, more entries available.
5868474SJose.Borrego@Sun.COM  * ERROR_NOT_ENOUGH_MEMORY  Insufficient memory is available.
5878474SJose.Borrego@Sun.COM  * NERR_BufTooSmall         The supplied buffer is too small.
5888474SJose.Borrego@Sun.COM  */
5898474SJose.Borrego@Sun.COM static int
5908474SJose.Borrego@Sun.COM srvsvc_s_NetFileEnum(void *arg, ndr_xa_t *mxa)
5918474SJose.Borrego@Sun.COM {
59210122SJordan.Brown@Sun.COM 	struct mslm_NetFileEnum	*param = arg;
59310122SJordan.Brown@Sun.COM 	smb_svcenum_t		se;
59410122SJordan.Brown@Sun.COM 	DWORD			status;
5958474SJose.Borrego@Sun.COM 
5968474SJose.Borrego@Sun.COM 	if (!ndr_is_admin(mxa)) {
5978474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetFileEnum));
5988474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
5998474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
6008474SJose.Borrego@Sun.COM 	}
6018474SJose.Borrego@Sun.COM 
60210122SJordan.Brown@Sun.COM 	if ((param->total_entries = srvsvc_open_files()) == 0) {
60310122SJordan.Brown@Sun.COM 		bzero(param, sizeof (struct mslm_NetFileEnum));
60410122SJordan.Brown@Sun.COM 		param->status = ERROR_SUCCESS;
60510122SJordan.Brown@Sun.COM 		return (NDR_DRC_OK);
60610122SJordan.Brown@Sun.COM 	}
60710122SJordan.Brown@Sun.COM 
60810122SJordan.Brown@Sun.COM 	bzero(&se, sizeof (smb_svcenum_t));
60910122SJordan.Brown@Sun.COM 	se.se_type = SMB_SVCENUM_TYPE_FILE;
61010122SJordan.Brown@Sun.COM 	se.se_level = param->info.switch_value;
61110122SJordan.Brown@Sun.COM 	se.se_ntotal = param->total_entries;
61210122SJordan.Brown@Sun.COM 	se.se_nlimit = se.se_ntotal;
61310122SJordan.Brown@Sun.COM 
61410122SJordan.Brown@Sun.COM 	if (param->pref_max_len == SMB_SRVSVC_MAXPREFLEN ||
61510122SJordan.Brown@Sun.COM 	    param->pref_max_len > SMB_SRVSVC_MAXBUFLEN)
61610122SJordan.Brown@Sun.COM 		se.se_prefmaxlen = SMB_SRVSVC_MAXBUFLEN;
61710122SJordan.Brown@Sun.COM 	else
61810122SJordan.Brown@Sun.COM 		se.se_prefmaxlen = param->pref_max_len;
61910122SJordan.Brown@Sun.COM 
62010122SJordan.Brown@Sun.COM 	if (param->resume_handle) {
62110122SJordan.Brown@Sun.COM 		se.se_resume = *param->resume_handle;
62210122SJordan.Brown@Sun.COM 		se.se_nskip = se.se_resume;
62310122SJordan.Brown@Sun.COM 		*param->resume_handle = 0;
62410122SJordan.Brown@Sun.COM 	}
62510122SJordan.Brown@Sun.COM 
6268474SJose.Borrego@Sun.COM 	switch (param->info.switch_value) {
6278474SJose.Borrego@Sun.COM 	case 2:
62810122SJordan.Brown@Sun.COM 		status = srvsvc_NetFileEnum2(mxa, param, &se);
6298474SJose.Borrego@Sun.COM 		break;
6308474SJose.Borrego@Sun.COM 
6318474SJose.Borrego@Sun.COM 	case 3:
63210122SJordan.Brown@Sun.COM 		status = srvsvc_NetFileEnum3(mxa, param, &se);
6338474SJose.Borrego@Sun.COM 		break;
6348474SJose.Borrego@Sun.COM 
6358474SJose.Borrego@Sun.COM 	case 50:
6368474SJose.Borrego@Sun.COM 		status = ERROR_NOT_SUPPORTED;
6378474SJose.Borrego@Sun.COM 		break;
6388474SJose.Borrego@Sun.COM 
6398474SJose.Borrego@Sun.COM 	default:
6408474SJose.Borrego@Sun.COM 		status = ERROR_INVALID_LEVEL;
6418474SJose.Borrego@Sun.COM 		break;
6428474SJose.Borrego@Sun.COM 	}
6438474SJose.Borrego@Sun.COM 
6448474SJose.Borrego@Sun.COM 	if (status != ERROR_SUCCESS) {
6458474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetFileEnum));
6468474SJose.Borrego@Sun.COM 		param->status = status;
6478474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
6488474SJose.Borrego@Sun.COM 	}
6498474SJose.Borrego@Sun.COM 
65010122SJordan.Brown@Sun.COM 	if (param->resume_handle &&
65110122SJordan.Brown@Sun.COM 	    param->pref_max_len != SMB_SRVSVC_MAXPREFLEN) {
65210122SJordan.Brown@Sun.COM 		if (se.se_resume < param->total_entries) {
65310122SJordan.Brown@Sun.COM 			*param->resume_handle = se.se_resume;
65410122SJordan.Brown@Sun.COM 			status = ERROR_MORE_DATA;
65510122SJordan.Brown@Sun.COM 		}
65610122SJordan.Brown@Sun.COM 	}
65710122SJordan.Brown@Sun.COM 
65810122SJordan.Brown@Sun.COM 	param->status = status;
6598474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
6608474SJose.Borrego@Sun.COM }
6618474SJose.Borrego@Sun.COM 
6628474SJose.Borrego@Sun.COM /*
6638474SJose.Borrego@Sun.COM  * Build level 2 file information.
6648474SJose.Borrego@Sun.COM  *
66510122SJordan.Brown@Sun.COM  * SMB fids are 16-bit values but this interface expects 32-bit file ids.
66610122SJordan.Brown@Sun.COM  * So we use the uniqid here.
66710122SJordan.Brown@Sun.COM  *
6688474SJose.Borrego@Sun.COM  * On success, the caller expects that the info2, fi2 and entries_read
6698474SJose.Borrego@Sun.COM  * fields have been set up.
6708474SJose.Borrego@Sun.COM  */
6718474SJose.Borrego@Sun.COM static DWORD
67210122SJordan.Brown@Sun.COM srvsvc_NetFileEnum2(ndr_xa_t *mxa, struct mslm_NetFileEnum *param,
67310122SJordan.Brown@Sun.COM     smb_svcenum_t *se)
6748474SJose.Borrego@Sun.COM {
67510122SJordan.Brown@Sun.COM 	struct mslm_NetFileInfoBuf2	*fi2;
67610122SJordan.Brown@Sun.COM 	smb_netsvc_t			*ns;
67710122SJordan.Brown@Sun.COM 	smb_netsvcitem_t		*item;
67810122SJordan.Brown@Sun.COM 	smb_netfileinfo_t		*ofile;
67910122SJordan.Brown@Sun.COM 	uint32_t			entries_read = 0;
6808474SJose.Borrego@Sun.COM 
6818474SJose.Borrego@Sun.COM 	param->info.ru.info2 = NDR_NEW(mxa, struct mslm_NetFileInfo2);
6829832Samw@Sun.COM 	if (param->info.ru.info2 == NULL)
6838474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
6848474SJose.Borrego@Sun.COM 
68510122SJordan.Brown@Sun.COM 	srvsvc_estimate_limit(se, sizeof (struct mslm_NetFileInfoBuf2));
68610122SJordan.Brown@Sun.COM 	if (se->se_nlimit == 0)
68710122SJordan.Brown@Sun.COM 		return (NERR_BufTooSmall);
68810122SJordan.Brown@Sun.COM 
68910122SJordan.Brown@Sun.COM 	do {
69010122SJordan.Brown@Sun.COM 		fi2 = NDR_NEWN(mxa, struct mslm_NetFileInfoBuf2, se->se_nlimit);
69110122SJordan.Brown@Sun.COM 		if (fi2 == NULL)
69210122SJordan.Brown@Sun.COM 			se->se_nlimit >>= 1;
69310122SJordan.Brown@Sun.COM 	} while ((se->se_nlimit > 0) && (fi2 == NULL));
69410122SJordan.Brown@Sun.COM 
6958474SJose.Borrego@Sun.COM 	if (fi2 == NULL)
6968474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
6978474SJose.Borrego@Sun.COM 
6988474SJose.Borrego@Sun.COM 	param->info.ru.info2->fi2 = fi2;
6998474SJose.Borrego@Sun.COM 
70010122SJordan.Brown@Sun.COM 	if ((ns = smb_kmod_enum_init(se)) == NULL)
70110122SJordan.Brown@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
70210122SJordan.Brown@Sun.COM 
70310122SJordan.Brown@Sun.COM 	if (smb_kmod_enum(ns) != 0) {
70410122SJordan.Brown@Sun.COM 		smb_kmod_enum_fini(ns);
70510122SJordan.Brown@Sun.COM 		return (ERROR_INTERNAL_ERROR);
70610122SJordan.Brown@Sun.COM 	}
70710122SJordan.Brown@Sun.COM 
70810122SJordan.Brown@Sun.COM 	item = list_head(&ns->ns_list);
70910122SJordan.Brown@Sun.COM 	while (item != NULL) {
71010122SJordan.Brown@Sun.COM 		ofile = &item->nsi_un.nsi_ofile;
71110122SJordan.Brown@Sun.COM 		fi2->fi2_id = ofile->fi_uniqid;
7128474SJose.Borrego@Sun.COM 
7138474SJose.Borrego@Sun.COM 		++entries_read;
7148474SJose.Borrego@Sun.COM 		++fi2;
71510122SJordan.Brown@Sun.COM 		item = list_next(&ns->ns_list, item);
7168474SJose.Borrego@Sun.COM 	}
7178474SJose.Borrego@Sun.COM 
71810122SJordan.Brown@Sun.COM 	se->se_resume += entries_read;
7198474SJose.Borrego@Sun.COM 	param->info.ru.info2->entries_read = entries_read;
72010122SJordan.Brown@Sun.COM 	smb_kmod_enum_fini(ns);
7218474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
7228474SJose.Borrego@Sun.COM }
7238474SJose.Borrego@Sun.COM 
7248474SJose.Borrego@Sun.COM /*
7258474SJose.Borrego@Sun.COM  * Build level 3 file information.
7268474SJose.Borrego@Sun.COM  *
72710122SJordan.Brown@Sun.COM  * SMB fids are 16-bit values but this interface expects 32-bit file ids.
72810122SJordan.Brown@Sun.COM  * So we use the uniqid here.
72910122SJordan.Brown@Sun.COM  *
7308474SJose.Borrego@Sun.COM  * On success, the caller expects that the info3, fi3 and entries_read
7318474SJose.Borrego@Sun.COM  * fields have been set up.
7328474SJose.Borrego@Sun.COM  */
7338474SJose.Borrego@Sun.COM static DWORD
73410122SJordan.Brown@Sun.COM srvsvc_NetFileEnum3(ndr_xa_t *mxa, struct mslm_NetFileEnum *param,
73510122SJordan.Brown@Sun.COM     smb_svcenum_t *se)
7368474SJose.Borrego@Sun.COM {
73710122SJordan.Brown@Sun.COM 	struct mslm_NetFileInfoBuf3	*fi3;
73810122SJordan.Brown@Sun.COM 	smb_netsvc_t			*ns;
73910122SJordan.Brown@Sun.COM 	smb_netsvcitem_t		*item;
74010122SJordan.Brown@Sun.COM 	smb_netfileinfo_t		*ofile;
74110122SJordan.Brown@Sun.COM 	uint32_t			entries_read = 0;
7428474SJose.Borrego@Sun.COM 
7438474SJose.Borrego@Sun.COM 	param->info.ru.info3 = NDR_NEW(mxa, struct mslm_NetFileInfo3);
7448474SJose.Borrego@Sun.COM 	if (param->info.ru.info3 == NULL)
7458474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
7468474SJose.Borrego@Sun.COM 
74710122SJordan.Brown@Sun.COM 	srvsvc_estimate_limit(se,
74810122SJordan.Brown@Sun.COM 	    sizeof (struct mslm_NetFileInfoBuf3) + MAXNAMELEN);
74910122SJordan.Brown@Sun.COM 	if (se->se_nlimit == 0)
75010122SJordan.Brown@Sun.COM 		return (NERR_BufTooSmall);
75110122SJordan.Brown@Sun.COM 
75210122SJordan.Brown@Sun.COM 	do {
75310122SJordan.Brown@Sun.COM 		fi3 = NDR_NEWN(mxa, struct mslm_NetFileInfoBuf3, se->se_nlimit);
75410122SJordan.Brown@Sun.COM 		if (fi3 == NULL)
75510122SJordan.Brown@Sun.COM 			se->se_nlimit >>= 1;
75610122SJordan.Brown@Sun.COM 	} while ((se->se_nlimit > 0) && (fi3 == NULL));
75710122SJordan.Brown@Sun.COM 
7588474SJose.Borrego@Sun.COM 	if (fi3 == NULL)
7598474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
7608474SJose.Borrego@Sun.COM 
7618474SJose.Borrego@Sun.COM 	param->info.ru.info3->fi3 = fi3;
7628474SJose.Borrego@Sun.COM 
76310122SJordan.Brown@Sun.COM 	if ((ns = smb_kmod_enum_init(se)) == NULL)
76410122SJordan.Brown@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
76510122SJordan.Brown@Sun.COM 
76610122SJordan.Brown@Sun.COM 	if (smb_kmod_enum(ns) != 0) {
76710122SJordan.Brown@Sun.COM 		smb_kmod_enum_fini(ns);
76810122SJordan.Brown@Sun.COM 		return (ERROR_INTERNAL_ERROR);
76910122SJordan.Brown@Sun.COM 	}
77010122SJordan.Brown@Sun.COM 
77110122SJordan.Brown@Sun.COM 	item = list_head(&ns->ns_list);
77210122SJordan.Brown@Sun.COM 	while (item != NULL) {
77310122SJordan.Brown@Sun.COM 		ofile = &item->nsi_un.nsi_ofile;
77410122SJordan.Brown@Sun.COM 		fi3->fi3_id = ofile->fi_uniqid;
77510122SJordan.Brown@Sun.COM 		fi3->fi3_permissions = ofile->fi_permissions;
77610122SJordan.Brown@Sun.COM 		fi3->fi3_num_locks = ofile->fi_numlocks;
7778474SJose.Borrego@Sun.COM 		fi3->fi3_pathname = (uint8_t *)
77810122SJordan.Brown@Sun.COM 		    NDR_STRDUP(mxa, ofile->fi_path);
7798474SJose.Borrego@Sun.COM 		fi3->fi3_username = (uint8_t *)
78010122SJordan.Brown@Sun.COM 		    NDR_STRDUP(mxa, ofile->fi_username);
7818474SJose.Borrego@Sun.COM 
7828474SJose.Borrego@Sun.COM 		++entries_read;
7838474SJose.Borrego@Sun.COM 		++fi3;
78410122SJordan.Brown@Sun.COM 		item = list_next(&ns->ns_list, item);
7858474SJose.Borrego@Sun.COM 	}
7868474SJose.Borrego@Sun.COM 
78710122SJordan.Brown@Sun.COM 	se->se_resume += entries_read;
7888474SJose.Borrego@Sun.COM 	param->info.ru.info3->entries_read = entries_read;
7898474SJose.Borrego@Sun.COM 	param->total_entries = entries_read;
79011963SAfshin.Ardakani@Sun.COM 	smb_kmod_enum_fini(ns);
7918474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
7928474SJose.Borrego@Sun.COM }
7938474SJose.Borrego@Sun.COM 
7948474SJose.Borrego@Sun.COM /*
7958474SJose.Borrego@Sun.COM  * srvsvc_s_NetFileClose
7968474SJose.Borrego@Sun.COM  *
7978474SJose.Borrego@Sun.COM  * NetFileClose forces a file to close. This function can be used when
79810122SJordan.Brown@Sun.COM  * an error prevents closure by other means.  Use NetFileClose with
7998474SJose.Borrego@Sun.COM  * caution because it does not flush data, cached on a client, to the
8008474SJose.Borrego@Sun.COM  * file before closing the file.
8018474SJose.Borrego@Sun.COM  *
80210122SJordan.Brown@Sun.COM  * SMB fids are 16-bit values but this interface expects 32-bit file ids.
80310122SJordan.Brown@Sun.COM  * So we use the uniqid here.
80410122SJordan.Brown@Sun.COM  *
8058474SJose.Borrego@Sun.COM  * Return Values
8068474SJose.Borrego@Sun.COM  * ERROR_SUCCESS            Operation succeeded.
8078474SJose.Borrego@Sun.COM  * ERROR_ACCESS_DENIED      Operation denied.
8088474SJose.Borrego@Sun.COM  * NERR_FileIdNotFound      No open file with the specified id.
8098474SJose.Borrego@Sun.COM  *
81010122SJordan.Brown@Sun.COM  * Note: MSDN suggests ERROR_FILE_NOT_FOUND for NetFileClose but network
81110122SJordan.Brown@Sun.COM  * captures using NT show NERR_FileIdNotFound, which is consistent with
81210122SJordan.Brown@Sun.COM  * the NetFileClose2 page on MSDN.
8138474SJose.Borrego@Sun.COM  */
8148474SJose.Borrego@Sun.COM static int
8158474SJose.Borrego@Sun.COM srvsvc_s_NetFileClose(void *arg, ndr_xa_t *mxa)
8168474SJose.Borrego@Sun.COM {
81710122SJordan.Brown@Sun.COM 	static struct {
81810122SJordan.Brown@Sun.COM 		int errnum;
81910122SJordan.Brown@Sun.COM 		int nerr;
82010122SJordan.Brown@Sun.COM 	} errmap[] = {
82110122SJordan.Brown@Sun.COM 		0,	ERROR_SUCCESS,
82210122SJordan.Brown@Sun.COM 		EACCES,	ERROR_ACCESS_DENIED,
82310122SJordan.Brown@Sun.COM 		EPERM,	ERROR_ACCESS_DENIED,
82410122SJordan.Brown@Sun.COM 		EINVAL,	ERROR_INVALID_PARAMETER,
82510122SJordan.Brown@Sun.COM 		ENOMEM,	ERROR_NOT_ENOUGH_MEMORY,
82610122SJordan.Brown@Sun.COM 		ENOENT,	NERR_FileIdNotFound
82710122SJordan.Brown@Sun.COM 	};
82810122SJordan.Brown@Sun.COM 
8298474SJose.Borrego@Sun.COM 	struct mslm_NetFileClose *param = arg;
83010122SJordan.Brown@Sun.COM 	int		i;
83110122SJordan.Brown@Sun.COM 	int		rc;
8328474SJose.Borrego@Sun.COM 
8338474SJose.Borrego@Sun.COM 	if (!ndr_is_admin(mxa)) {
8348474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
8358474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8368474SJose.Borrego@Sun.COM 	}
8378474SJose.Borrego@Sun.COM 
83810122SJordan.Brown@Sun.COM 	rc = smb_kmod_file_close(param->file_id);
83910122SJordan.Brown@Sun.COM 
84010122SJordan.Brown@Sun.COM 	for (i = 0; i < (sizeof (errmap) / sizeof (errmap[0])); ++i) {
84110122SJordan.Brown@Sun.COM 		if (rc == errmap[i].errnum) {
84210122SJordan.Brown@Sun.COM 			param->status = errmap[i].nerr;
84310122SJordan.Brown@Sun.COM 			return (NDR_DRC_OK);
84410122SJordan.Brown@Sun.COM 		}
84510122SJordan.Brown@Sun.COM 	}
84610122SJordan.Brown@Sun.COM 
84710122SJordan.Brown@Sun.COM 	param->status = ERROR_INTERNAL_ERROR;
8488474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
8498474SJose.Borrego@Sun.COM }
8508474SJose.Borrego@Sun.COM 
8518474SJose.Borrego@Sun.COM /*
8528474SJose.Borrego@Sun.COM  * srvsvc_s_NetShareGetInfo
8538474SJose.Borrego@Sun.COM  *
8548474SJose.Borrego@Sun.COM  * Returns Win32 error codes.
8558474SJose.Borrego@Sun.COM  */
8568474SJose.Borrego@Sun.COM static int
8578474SJose.Borrego@Sun.COM srvsvc_s_NetShareGetInfo(void *arg, ndr_xa_t *mxa)
8588474SJose.Borrego@Sun.COM {
8598474SJose.Borrego@Sun.COM 	struct mlsm_NetShareGetInfo *param = arg;
8609343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_0 *info0;
8619343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_1 *info1;
8629343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_2 *info2;
8639343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_501 *info501;
8649343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_502 *info502;
8659832Samw@Sun.COM 	struct mslm_NetShareInfo_503 *info503;
8669343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_1004 *info1004;
8679343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_1005 *info1005;
8689343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_1006 *info1006;
8699832Samw@Sun.COM 	struct mslm_NetShareInfo_1501 *info1501;
8709832Samw@Sun.COM 	srvsvc_netshare_getinfo_t *info;
8719832Samw@Sun.COM 	uint8_t *netname;
8729832Samw@Sun.COM 	uint8_t *comment;
8738474SJose.Borrego@Sun.COM 	smb_share_t si;
8749832Samw@Sun.COM 	srvsvc_sd_t sd;
8758474SJose.Borrego@Sun.COM 	DWORD status;
8768474SJose.Borrego@Sun.COM 
8778474SJose.Borrego@Sun.COM 	status = smb_shr_get((char *)param->netname, &si);
8788474SJose.Borrego@Sun.COM 	if (status != NERR_Success) {
8798474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mlsm_NetShareGetInfo));
8808474SJose.Borrego@Sun.COM 		param->status = status;
8818474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8828474SJose.Borrego@Sun.COM 	}
8838474SJose.Borrego@Sun.COM 
8849832Samw@Sun.COM 	netname = (uint8_t *)NDR_STRDUP(mxa, si.shr_name);
8859832Samw@Sun.COM 	comment = (uint8_t *)NDR_STRDUP(mxa, si.shr_cmnt);
8869832Samw@Sun.COM 	info = NDR_NEW(mxa, srvsvc_netshare_getinfo_t);
8879832Samw@Sun.COM 
8889832Samw@Sun.COM 	if (netname == NULL || comment == NULL || info == NULL) {
8899832Samw@Sun.COM 		bzero(param, sizeof (struct mlsm_NetShareGetInfo));
8909832Samw@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
8919832Samw@Sun.COM 		return (NDR_DRC_OK);
8929832Samw@Sun.COM 	}
8939832Samw@Sun.COM 
8948474SJose.Borrego@Sun.COM 	switch (param->level) {
8958474SJose.Borrego@Sun.COM 	case 0:
8969832Samw@Sun.COM 		info0 = &info->nsg_info0;
8979832Samw@Sun.COM 		info0->shi0_netname = netname;
8988474SJose.Borrego@Sun.COM 		param->result.ru.info0 = info0;
8998474SJose.Borrego@Sun.COM 		break;
9008474SJose.Borrego@Sun.COM 
9018474SJose.Borrego@Sun.COM 	case 1:
9029832Samw@Sun.COM 		info1 = &info->nsg_info1;
9039832Samw@Sun.COM 		info1->shi1_netname = netname;
9049832Samw@Sun.COM 		info1->shi1_comment = comment;
9058474SJose.Borrego@Sun.COM 		info1->shi1_type = si.shr_type;
9068474SJose.Borrego@Sun.COM 		param->result.ru.info1 = info1;
9078474SJose.Borrego@Sun.COM 		break;
9088474SJose.Borrego@Sun.COM 
9098474SJose.Borrego@Sun.COM 	case 2:
9109832Samw@Sun.COM 		info2 = &info->nsg_info2;
9119832Samw@Sun.COM 		info2->shi2_netname = netname;
9129832Samw@Sun.COM 		info2->shi2_comment = comment;
9138474SJose.Borrego@Sun.COM 		info2->shi2_path =
9148474SJose.Borrego@Sun.COM 		    (uint8_t *)srvsvc_share_mkpath(mxa, si.shr_path);
9158474SJose.Borrego@Sun.COM 		info2->shi2_passwd = 0;
9168474SJose.Borrego@Sun.COM 		info2->shi2_type = si.shr_type;
9178474SJose.Borrego@Sun.COM 		info2->shi2_permissions = 0;
9188474SJose.Borrego@Sun.COM 		info2->shi2_max_uses = SHI_USES_UNLIMITED;
9198474SJose.Borrego@Sun.COM 		info2->shi2_current_uses = 0;
9208474SJose.Borrego@Sun.COM 		param->result.ru.info2 = info2;
9218474SJose.Borrego@Sun.COM 		break;
9228474SJose.Borrego@Sun.COM 
9239832Samw@Sun.COM 	case 501:
9249832Samw@Sun.COM 		info501 = &info->nsg_info501;
9259832Samw@Sun.COM 		info501->shi501_netname = netname;
9269832Samw@Sun.COM 		info501->shi501_comment = comment;
9279832Samw@Sun.COM 		info501->shi501_type = si.shr_type;
92810504SKeyur.Desai@Sun.COM 		info501->shi501_flags = srvsvc_get_share_flags(&si);
9299832Samw@Sun.COM 		param->result.ru.info501 = info501;
9309832Samw@Sun.COM 		break;
9319832Samw@Sun.COM 
9329832Samw@Sun.COM 	case 502:
9339832Samw@Sun.COM 		info502 = &info->nsg_info502;
9349832Samw@Sun.COM 		info502->shi502_netname = netname;
9359832Samw@Sun.COM 		info502->shi502_comment = comment;
9369832Samw@Sun.COM 		info502->shi502_path =
9379832Samw@Sun.COM 		    (uint8_t *)srvsvc_share_mkpath(mxa, si.shr_path);
9389832Samw@Sun.COM 		info502->shi502_passwd = 0;
9399832Samw@Sun.COM 		info502->shi502_type = si.shr_type;
9409832Samw@Sun.COM 		info502->shi502_permissions = 0;
9419832Samw@Sun.COM 		info502->shi502_max_uses = SHI_USES_UNLIMITED;
9429832Samw@Sun.COM 		info502->shi502_current_uses = 0;
9439832Samw@Sun.COM 
9449832Samw@Sun.COM 		status = srvsvc_share_getsd(mxa, &si, &sd);
9459832Samw@Sun.COM 		if (status == ERROR_SUCCESS) {
9469832Samw@Sun.COM 			info502->shi502_reserved = sd.sd_size;
9479832Samw@Sun.COM 			info502->shi502_security_descriptor = sd.sd_buf;
9489832Samw@Sun.COM 		} else {
9499832Samw@Sun.COM 			info502->shi502_reserved = 0;
9509832Samw@Sun.COM 			info502->shi502_security_descriptor = NULL;
9518474SJose.Borrego@Sun.COM 		}
9528474SJose.Borrego@Sun.COM 
9539832Samw@Sun.COM 		param->result.ru.info502 = info502;
9549832Samw@Sun.COM 		break;
9559832Samw@Sun.COM 
9569832Samw@Sun.COM 	case 503:
9579832Samw@Sun.COM 		info503 = &info->nsg_info503;
9589832Samw@Sun.COM 		info503->shi503_netname = netname;
9599832Samw@Sun.COM 		info503->shi503_comment = comment;
9609832Samw@Sun.COM 		info503->shi503_path =
9619832Samw@Sun.COM 		    (uint8_t *)srvsvc_share_mkpath(mxa, si.shr_path);
9629832Samw@Sun.COM 		info503->shi503_passwd = NULL;
9639832Samw@Sun.COM 		info503->shi503_type = si.shr_type;
9649832Samw@Sun.COM 		info503->shi503_permissions = 0;
9659832Samw@Sun.COM 		info503->shi503_max_uses = SHI_USES_UNLIMITED;
9669832Samw@Sun.COM 		info503->shi503_current_uses = 0;
9679832Samw@Sun.COM 		info503->shi503_servername = NULL;
9689832Samw@Sun.COM 
9699832Samw@Sun.COM 		status = srvsvc_share_getsd(mxa, &si, &sd);
9709832Samw@Sun.COM 		if (status == ERROR_SUCCESS) {
9719832Samw@Sun.COM 			info503->shi503_reserved = sd.sd_size;
9729832Samw@Sun.COM 			info503->shi503_security_descriptor = sd.sd_buf;
9739832Samw@Sun.COM 		} else {
9749832Samw@Sun.COM 			info503->shi503_reserved = 0;
9759832Samw@Sun.COM 			info503->shi503_security_descriptor = NULL;
9769832Samw@Sun.COM 		}
9779832Samw@Sun.COM 
9789832Samw@Sun.COM 		param->result.ru.info503 = info503;
9799832Samw@Sun.COM 		break;
9809832Samw@Sun.COM 
9819832Samw@Sun.COM 	case 1004:
9829832Samw@Sun.COM 		info1004 = &info->nsg_info1004;
9839832Samw@Sun.COM 		info1004->shi1004_comment = comment;
9849832Samw@Sun.COM 		param->result.ru.info1004 = info1004;
9858474SJose.Borrego@Sun.COM 		break;
9868474SJose.Borrego@Sun.COM 
9878474SJose.Borrego@Sun.COM 	case 1005:
9889832Samw@Sun.COM 		info1005 = &info->nsg_info1005;
98910504SKeyur.Desai@Sun.COM 		info1005->shi1005_flags = srvsvc_get_share_flags(&si);
9908474SJose.Borrego@Sun.COM 		param->result.ru.info1005 = info1005;
9918474SJose.Borrego@Sun.COM 		break;
9928474SJose.Borrego@Sun.COM 
9938474SJose.Borrego@Sun.COM 	case 1006:
9949832Samw@Sun.COM 		info1006 = &info->nsg_info1006;
9958474SJose.Borrego@Sun.COM 		info1006->shi1006_max_uses = SHI_USES_UNLIMITED;
9968474SJose.Borrego@Sun.COM 		param->result.ru.info1006 = info1006;
9978474SJose.Borrego@Sun.COM 		break;
9988474SJose.Borrego@Sun.COM 
9999832Samw@Sun.COM 	case 1501:
10009832Samw@Sun.COM 		info1501 = &info->nsg_info1501;
10019832Samw@Sun.COM 
10029832Samw@Sun.COM 		status = srvsvc_share_getsd(mxa, &si, &sd);
10039832Samw@Sun.COM 		if (status == ERROR_SUCCESS) {
10049832Samw@Sun.COM 			info503->shi503_reserved = sd.sd_size;
10059832Samw@Sun.COM 			info503->shi503_security_descriptor = sd.sd_buf;
10069832Samw@Sun.COM 		} else {
10079832Samw@Sun.COM 			info503->shi503_reserved = 0;
10089832Samw@Sun.COM 			info503->shi503_security_descriptor = NULL;
10098474SJose.Borrego@Sun.COM 		}
10108474SJose.Borrego@Sun.COM 
10119832Samw@Sun.COM 		param->result.ru.info1501 = info1501;
10128474SJose.Borrego@Sun.COM 		break;
10138474SJose.Borrego@Sun.COM 
10148474SJose.Borrego@Sun.COM 	default:
10158474SJose.Borrego@Sun.COM 		status = ERROR_ACCESS_DENIED;
10168474SJose.Borrego@Sun.COM 		break;
10178474SJose.Borrego@Sun.COM 	}
10188474SJose.Borrego@Sun.COM 
10198474SJose.Borrego@Sun.COM 	if (status != ERROR_SUCCESS)
10208474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mlsm_NetShareGetInfo));
10218474SJose.Borrego@Sun.COM 	else
10228474SJose.Borrego@Sun.COM 		param->result.switch_value = param->level;
10238474SJose.Borrego@Sun.COM 
10248474SJose.Borrego@Sun.COM 	param->status = status;
10258474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
10268474SJose.Borrego@Sun.COM }
10278474SJose.Borrego@Sun.COM 
10289832Samw@Sun.COM static uint32_t
10299832Samw@Sun.COM srvsvc_share_getsd(ndr_xa_t *mxa, smb_share_t *si, srvsvc_sd_t *sd)
10309832Samw@Sun.COM {
10319832Samw@Sun.COM 	uint32_t status;
10329832Samw@Sun.COM 
10339832Samw@Sun.COM 	status = srvsvc_sd_get(si, NULL, &sd->sd_size);
10349832Samw@Sun.COM 	if (status != ERROR_SUCCESS) {
10359832Samw@Sun.COM 		if (status == ERROR_PATH_NOT_FOUND) {
10369832Samw@Sun.COM 			bzero(sd, sizeof (srvsvc_sd_t));
10379832Samw@Sun.COM 			status = ERROR_SUCCESS;
10389832Samw@Sun.COM 		}
10399832Samw@Sun.COM 
10409832Samw@Sun.COM 		return (status);
10419832Samw@Sun.COM 	}
10429832Samw@Sun.COM 
10439832Samw@Sun.COM 	if ((sd->sd_buf = NDR_MALLOC(mxa, sd->sd_size)) == NULL)
10449832Samw@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
10459832Samw@Sun.COM 
10469832Samw@Sun.COM 	status = srvsvc_sd_get(si, sd->sd_buf, NULL);
10479832Samw@Sun.COM 	if (status == ERROR_PATH_NOT_FOUND) {
10489832Samw@Sun.COM 		bzero(sd, sizeof (srvsvc_sd_t));
10499832Samw@Sun.COM 		status = ERROR_SUCCESS;
10509832Samw@Sun.COM 	}
10519832Samw@Sun.COM 
10529832Samw@Sun.COM 	return (status);
10539832Samw@Sun.COM }
10548474SJose.Borrego@Sun.COM 
10558474SJose.Borrego@Sun.COM /*
10568474SJose.Borrego@Sun.COM  * srvsvc_s_NetShareSetInfo
10578474SJose.Borrego@Sun.COM  *
10588474SJose.Borrego@Sun.COM  * This call is made by SrvMgr to set share information.
10599832Samw@Sun.COM  * Only power users groups can manage shares.
10609832Samw@Sun.COM  *
10619832Samw@Sun.COM  * To avoid misleading errors, we don't report an error
10629832Samw@Sun.COM  * when a FS doesn't support ACLs on shares.
10638474SJose.Borrego@Sun.COM  *
10648474SJose.Borrego@Sun.COM  * Returns Win32 error codes.
10658474SJose.Borrego@Sun.COM  */
10668474SJose.Borrego@Sun.COM static int
10678474SJose.Borrego@Sun.COM srvsvc_s_NetShareSetInfo(void *arg, ndr_xa_t *mxa)
10688474SJose.Borrego@Sun.COM {
10698474SJose.Borrego@Sun.COM 	struct mlsm_NetShareSetInfo *param = arg;
10709832Samw@Sun.COM 	struct mslm_NetShareInfo_0 *info0;
10719832Samw@Sun.COM 	struct mslm_NetShareInfo_1 *info1;
10729832Samw@Sun.COM 	struct mslm_NetShareInfo_2 *info2;
10739832Samw@Sun.COM 	struct mslm_NetShareInfo_501 *info501;
10749832Samw@Sun.COM 	struct mslm_NetShareInfo_502 *info502;
10759832Samw@Sun.COM 	struct mslm_NetShareInfo_503 *info503;
10769832Samw@Sun.COM 	struct mslm_NetShareInfo_1004 *info1004;
10779832Samw@Sun.COM 	struct mslm_NetShareInfo_1005 *info1005;
10789832Samw@Sun.COM 	struct mslm_NetShareInfo_1501 *info1501;
10799832Samw@Sun.COM 	static DWORD parm_err = 0;
10809832Samw@Sun.COM 	srvsvc_netshare_setinfo_t info;
10819832Samw@Sun.COM 	smb_share_t si;
10829832Samw@Sun.COM 	uint8_t *sdbuf;
10839832Samw@Sun.COM 	int32_t native_os;
10849832Samw@Sun.COM 	DWORD status;
10859832Samw@Sun.COM 
10869832Samw@Sun.COM 	native_os = ndr_native_os(mxa);
10879832Samw@Sun.COM 
10889832Samw@Sun.COM 	if (!ndr_is_poweruser(mxa)) {
10899832Samw@Sun.COM 		status = ERROR_ACCESS_DENIED;
10909832Samw@Sun.COM 		goto netsharesetinfo_exit;
10919832Samw@Sun.COM 	}
10929832Samw@Sun.COM 
10939832Samw@Sun.COM 	if (smb_shr_get((char *)param->netname, &si) != NERR_Success) {
10949832Samw@Sun.COM 		status = ERROR_INVALID_NETNAME;
10959832Samw@Sun.COM 		goto netsharesetinfo_exit;
10969832Samw@Sun.COM 	}
10979832Samw@Sun.COM 
10989832Samw@Sun.COM 	if (param->result.ru.nullptr == NULL) {
10999832Samw@Sun.COM 		status = ERROR_INVALID_PARAMETER;
11009832Samw@Sun.COM 		goto netsharesetinfo_exit;
11019832Samw@Sun.COM 	}
11029832Samw@Sun.COM 
11039832Samw@Sun.COM 	bzero(&info, sizeof (srvsvc_netshare_setinfo_t));
11049832Samw@Sun.COM 
11059832Samw@Sun.COM 	switch (param->level) {
11069832Samw@Sun.COM 	case 0:
11079832Samw@Sun.COM 		info0 = (struct mslm_NetShareInfo_0 *)param->result.ru.info0;
11089832Samw@Sun.COM 		info.nss_netname = (char *)info0->shi0_netname;
11099832Samw@Sun.COM 		status = srvsvc_modify_share(&si, &info);
11109832Samw@Sun.COM 		break;
11119832Samw@Sun.COM 
11129832Samw@Sun.COM 	case 1:
11139832Samw@Sun.COM 		info1 = (struct mslm_NetShareInfo_1 *)param->result.ru.info1;
11149832Samw@Sun.COM 		info.nss_netname = (char *)info1->shi1_netname;
11159832Samw@Sun.COM 		info.nss_comment = (char *)info1->shi1_comment;
11169832Samw@Sun.COM 		info.nss_type = info1->shi1_type;
11179832Samw@Sun.COM 		status = srvsvc_modify_share(&si, &info);
11189832Samw@Sun.COM 		break;
11199832Samw@Sun.COM 
11209832Samw@Sun.COM 	case 2:
11219832Samw@Sun.COM 		info2 = (struct mslm_NetShareInfo_2 *)param->result.ru.info2;
11229832Samw@Sun.COM 		info.nss_netname = (char *)info2->shi2_netname;
11239832Samw@Sun.COM 		info.nss_comment = (char *)info2->shi2_comment;
11249832Samw@Sun.COM 		info.nss_path = (char *)info2->shi2_path;
11259832Samw@Sun.COM 		info.nss_type = info2->shi2_type;
11269832Samw@Sun.COM 		status = srvsvc_modify_share(&si, &info);
11279832Samw@Sun.COM 		break;
11289832Samw@Sun.COM 
11299832Samw@Sun.COM 	case 501:
11309832Samw@Sun.COM 		info501 = (struct mslm_NetShareInfo_501 *)
11319832Samw@Sun.COM 		    param->result.ru.info501;
11329832Samw@Sun.COM 		info.nss_netname = (char *)info501->shi501_netname;
11339832Samw@Sun.COM 		info.nss_comment = (char *)info501->shi501_comment;
11349832Samw@Sun.COM 		info.nss_type = info501->shi501_type;
11359832Samw@Sun.COM 		status = srvsvc_modify_share(&si, &info);
113610504SKeyur.Desai@Sun.COM 		if (status == ERROR_SUCCESS)
113710504SKeyur.Desai@Sun.COM 			status = srvsvc_update_share_flags(&si,
113810504SKeyur.Desai@Sun.COM 			    info501->shi501_flags);
11399832Samw@Sun.COM 		break;
11409832Samw@Sun.COM 
11419832Samw@Sun.COM 	case 502:
11429832Samw@Sun.COM 		info502 = (struct mslm_NetShareInfo_502 *)
11439832Samw@Sun.COM 		    param->result.ru.info502;
11449832Samw@Sun.COM 		info.nss_netname = (char *)info502->shi502_netname;
11459832Samw@Sun.COM 		info.nss_comment = (char *)info502->shi502_comment;
11469832Samw@Sun.COM 		info.nss_path = (char *)info502->shi502_path;
11479832Samw@Sun.COM 		info.nss_type = info502->shi502_type;
11489832Samw@Sun.COM 		info.nss_sd.sd_buf = info502->shi502_security_descriptor;
11499832Samw@Sun.COM 		status = srvsvc_modify_share(&si, &info);
11509832Samw@Sun.COM 		break;
11519832Samw@Sun.COM 
11529832Samw@Sun.COM 	case 503:
11539832Samw@Sun.COM 		info503 = (struct mslm_NetShareInfo_503 *)
11549832Samw@Sun.COM 		    param->result.ru.info503;
11559832Samw@Sun.COM 		info.nss_netname = (char *)info503->shi503_netname;
11569832Samw@Sun.COM 		info.nss_comment = (char *)info503->shi503_comment;
11579832Samw@Sun.COM 		info.nss_path = (char *)info503->shi503_path;
11589832Samw@Sun.COM 		info.nss_type = info503->shi503_type;
11599832Samw@Sun.COM 		info.nss_sd.sd_buf = info503->shi503_security_descriptor;
11609832Samw@Sun.COM 		status = srvsvc_modify_share(&si, &info);
11619832Samw@Sun.COM 		break;
11629832Samw@Sun.COM 
11639832Samw@Sun.COM 	case 1004:
11649832Samw@Sun.COM 		info1004 = (struct mslm_NetShareInfo_1004 *)
11659832Samw@Sun.COM 		    param->result.ru.info1004;
11669832Samw@Sun.COM 		info.nss_comment = (char *)info1004->shi1004_comment;
11679832Samw@Sun.COM 		status = srvsvc_modify_share(&si, &info);
11689832Samw@Sun.COM 		break;
11699832Samw@Sun.COM 
11709832Samw@Sun.COM 	case 1005:
11719832Samw@Sun.COM 		info1005 = (struct mslm_NetShareInfo_1005 *)
11729832Samw@Sun.COM 		    param->result.ru.info1005;
11739832Samw@Sun.COM 		status = srvsvc_update_share_flags(&si,
11749832Samw@Sun.COM 		    info1005->shi1005_flags);
11759832Samw@Sun.COM 		break;
11769832Samw@Sun.COM 
11779832Samw@Sun.COM 	case 1006:
11789832Samw@Sun.COM 		/*
11799832Samw@Sun.COM 		 * We don't limit the maximum number of concurrent
11809832Samw@Sun.COM 		 * connections to a share.
11819832Samw@Sun.COM 		 */
11829832Samw@Sun.COM 		status = ERROR_SUCCESS;
11839832Samw@Sun.COM 		break;
11849832Samw@Sun.COM 
11859832Samw@Sun.COM 	case 1501:
11869832Samw@Sun.COM 		info1501 = (struct mslm_NetShareInfo_1501 *)
11879832Samw@Sun.COM 		    param->result.ru.info1501;
11889832Samw@Sun.COM 		sdbuf = info1501->shi1501_security_descriptor;
11899832Samw@Sun.COM 		status = ERROR_SUCCESS;
11909832Samw@Sun.COM 
11919832Samw@Sun.COM 		if (sdbuf != NULL) {
11929832Samw@Sun.COM 			status = srvsvc_sd_set(&si, sdbuf);
11939832Samw@Sun.COM 			if (status == ERROR_PATH_NOT_FOUND)
11949832Samw@Sun.COM 				status = ERROR_SUCCESS;
11959832Samw@Sun.COM 		}
11969832Samw@Sun.COM 		break;
11979832Samw@Sun.COM 
11989832Samw@Sun.COM 	default:
11999832Samw@Sun.COM 		status = ERROR_ACCESS_DENIED;
12009832Samw@Sun.COM 		break;
12019832Samw@Sun.COM 	}
12029832Samw@Sun.COM 
12039832Samw@Sun.COM netsharesetinfo_exit:
12049832Samw@Sun.COM 	if (status != ERROR_SUCCESS)
12059832Samw@Sun.COM 		bzero(param, sizeof (struct mlsm_NetShareSetInfo));
12069832Samw@Sun.COM 
12079832Samw@Sun.COM 	param->parm_err = (native_os == NATIVE_OS_WIN95) ? 0 : &parm_err;
12089832Samw@Sun.COM 	param->status = status;
12098474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
12108474SJose.Borrego@Sun.COM }
12118474SJose.Borrego@Sun.COM 
12129832Samw@Sun.COM static uint32_t
12139832Samw@Sun.COM srvsvc_modify_share(smb_share_t *si, srvsvc_netshare_setinfo_t *info)
12149832Samw@Sun.COM {
12159832Samw@Sun.COM 	uint32_t nerr = NERR_Success;
12169832Samw@Sun.COM 
12179832Samw@Sun.COM 	if (si->shr_flags & SMB_SHRF_TRANS)
12189832Samw@Sun.COM 		return (srvsvc_modify_transient_share(si, info));
12199832Samw@Sun.COM 
12209832Samw@Sun.COM 	if (info->nss_sd.sd_buf != NULL) {
12219832Samw@Sun.COM 		nerr = srvsvc_sd_set(si, info->nss_sd.sd_buf);
12229832Samw@Sun.COM 		if (nerr == ERROR_PATH_NOT_FOUND)
12239832Samw@Sun.COM 			nerr = NERR_Success;
12249832Samw@Sun.COM 	}
12259832Samw@Sun.COM 
12269832Samw@Sun.COM 	if ((nerr = srvsvc_sa_modify(si, info)) == NERR_Success)
12279832Samw@Sun.COM 		nerr = smb_shr_modify(si);
12289832Samw@Sun.COM 
12299832Samw@Sun.COM 	return (nerr);
12309832Samw@Sun.COM }
12319832Samw@Sun.COM 
12329832Samw@Sun.COM /*
12339832Samw@Sun.COM  * Update transient shares.  This includes autohome shares.
12349832Samw@Sun.COM  */
12359832Samw@Sun.COM static uint32_t
12369832Samw@Sun.COM srvsvc_modify_transient_share(smb_share_t *si, srvsvc_netshare_setinfo_t *info)
12379832Samw@Sun.COM {
12389832Samw@Sun.COM 	uint32_t nerr;
12399832Samw@Sun.COM 
12409832Samw@Sun.COM 	if (info->nss_netname != NULL && info->nss_netname[0] != '\0' &&
124110966SJordan.Brown@Sun.COM 	    smb_strcasecmp(info->nss_netname, si->shr_name, 0) != 0) {
12429832Samw@Sun.COM 		nerr = smb_shr_rename(si->shr_name, info->nss_netname);
12439832Samw@Sun.COM 		if (nerr != NERR_Success)
12449832Samw@Sun.COM 			return (nerr);
12459832Samw@Sun.COM 
12469832Samw@Sun.COM 		(void) strlcpy(si->shr_name, info->nss_netname, MAXNAMELEN);
12479832Samw@Sun.COM 	}
12489832Samw@Sun.COM 
12499832Samw@Sun.COM 	if ((info->nss_comment != NULL) &&
12509832Samw@Sun.COM 	    (strcmp(info->nss_comment, si->shr_cmnt) != 0)) {
12519832Samw@Sun.COM 		(void) strlcpy(si->shr_cmnt, info->nss_comment,
12529832Samw@Sun.COM 		    SMB_SHARE_CMNT_MAX);
12539832Samw@Sun.COM 
12549832Samw@Sun.COM 		if ((nerr = smb_shr_modify(si)) != NERR_Success)
12559832Samw@Sun.COM 			return (nerr);
12569832Samw@Sun.COM 	}
12579832Samw@Sun.COM 
12589832Samw@Sun.COM 	return (NERR_Success);
12599832Samw@Sun.COM }
12609832Samw@Sun.COM 
126110504SKeyur.Desai@Sun.COM /*
126210504SKeyur.Desai@Sun.COM  * srvsvc_update_share_flags
126310504SKeyur.Desai@Sun.COM  *
126410504SKeyur.Desai@Sun.COM  * This function updates flags for shares.
126510504SKeyur.Desai@Sun.COM  * Flags for Persistent shares are updated in both libshare and the local cache.
126610504SKeyur.Desai@Sun.COM  * Flags for Transient shares are updated only in the local cache.
126710504SKeyur.Desai@Sun.COM  */
12689832Samw@Sun.COM static uint32_t
12699832Samw@Sun.COM srvsvc_update_share_flags(smb_share_t *si, uint32_t shi_flags)
12709832Samw@Sun.COM {
12719832Samw@Sun.COM 	uint32_t nerr = NERR_Success;
127210504SKeyur.Desai@Sun.COM 	uint32_t flag = 0;
127310504SKeyur.Desai@Sun.COM 	char *csc_value;
127410504SKeyur.Desai@Sun.COM 	char *abe_value = "false";
127510504SKeyur.Desai@Sun.COM 	nvlist_t *nvl;
127610504SKeyur.Desai@Sun.COM 	int err = 0;
127710504SKeyur.Desai@Sun.COM 
127810504SKeyur.Desai@Sun.COM 	if (shi_flags & SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM) {
127910504SKeyur.Desai@Sun.COM 		flag = SMB_SHRF_ABE;
128010504SKeyur.Desai@Sun.COM 		abe_value = "true";
128110504SKeyur.Desai@Sun.COM 	}
128210504SKeyur.Desai@Sun.COM 
128310504SKeyur.Desai@Sun.COM 	si->shr_flags &= ~SMB_SHRF_ABE;
128410504SKeyur.Desai@Sun.COM 	si->shr_flags |= flag;
12859832Samw@Sun.COM 
12869832Samw@Sun.COM 	switch ((shi_flags & CSC_MASK)) {
12879832Samw@Sun.COM 	case CSC_CACHE_AUTO_REINT:
128810504SKeyur.Desai@Sun.COM 		flag = SMB_SHRF_CSC_AUTO;
12899832Samw@Sun.COM 		break;
12909832Samw@Sun.COM 	case CSC_CACHE_VDO:
129110504SKeyur.Desai@Sun.COM 		flag = SMB_SHRF_CSC_VDO;
12929832Samw@Sun.COM 		break;
12939832Samw@Sun.COM 	case CSC_CACHE_NONE:
129410504SKeyur.Desai@Sun.COM 		flag = SMB_SHRF_CSC_DISABLED;
12959832Samw@Sun.COM 		break;
12969832Samw@Sun.COM 	case CSC_CACHE_MANUAL_REINT:
129710504SKeyur.Desai@Sun.COM 		flag = SMB_SHRF_CSC_MANUAL;
12989832Samw@Sun.COM 		break;
12999832Samw@Sun.COM 	default:
130010504SKeyur.Desai@Sun.COM 		return (NERR_InternalError);
13019832Samw@Sun.COM 	}
13029832Samw@Sun.COM 
13039832Samw@Sun.COM 	si->shr_flags &= ~SMB_SHRF_CSC_MASK;
130410504SKeyur.Desai@Sun.COM 	si->shr_flags |= flag;
13059832Samw@Sun.COM 
13069832Samw@Sun.COM 	if ((si->shr_flags & SMB_SHRF_TRANS) == 0) {
130710504SKeyur.Desai@Sun.COM 		csc_value = smb_shr_sa_csc_name(si);
130810504SKeyur.Desai@Sun.COM 
130910504SKeyur.Desai@Sun.COM 		if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
131010504SKeyur.Desai@Sun.COM 			return (NERR_InternalError);
131110504SKeyur.Desai@Sun.COM 
131210504SKeyur.Desai@Sun.COM 		err |= nvlist_add_string(nvl, SHOPT_CSC, csc_value);
131310504SKeyur.Desai@Sun.COM 		err |= nvlist_add_string(nvl, SHOPT_ABE, abe_value);
131410504SKeyur.Desai@Sun.COM 		if (err) {
131510504SKeyur.Desai@Sun.COM 			nvlist_free(nvl);
131610504SKeyur.Desai@Sun.COM 			return (NERR_InternalError);
131710504SKeyur.Desai@Sun.COM 		}
131810504SKeyur.Desai@Sun.COM 
131910504SKeyur.Desai@Sun.COM 		nerr = srvsvc_sa_setprop(si, nvl);
132010504SKeyur.Desai@Sun.COM 		nvlist_free(nvl);
132110504SKeyur.Desai@Sun.COM 
132210504SKeyur.Desai@Sun.COM 		if (nerr != NERR_Success)
13239832Samw@Sun.COM 			return (nerr);
13249832Samw@Sun.COM 	}
13259832Samw@Sun.COM 
13269832Samw@Sun.COM 	return (smb_shr_modify(si));
13279832Samw@Sun.COM }
13289832Samw@Sun.COM 
132910504SKeyur.Desai@Sun.COM static uint32_t
133010504SKeyur.Desai@Sun.COM srvsvc_get_share_flags(smb_share_t *si)
133110504SKeyur.Desai@Sun.COM {
133210504SKeyur.Desai@Sun.COM 	uint32_t flags = 0;
133310504SKeyur.Desai@Sun.COM 
133410504SKeyur.Desai@Sun.COM 	switch (si->shr_flags & SMB_SHRF_CSC_MASK) {
133510504SKeyur.Desai@Sun.COM 	case SMB_SHRF_CSC_DISABLED:
133610504SKeyur.Desai@Sun.COM 		flags |= CSC_CACHE_NONE;
133710504SKeyur.Desai@Sun.COM 		break;
133810504SKeyur.Desai@Sun.COM 	case SMB_SHRF_CSC_AUTO:
133910504SKeyur.Desai@Sun.COM 		flags |= CSC_CACHE_AUTO_REINT;
134010504SKeyur.Desai@Sun.COM 		break;
134110504SKeyur.Desai@Sun.COM 	case SMB_SHRF_CSC_VDO:
134210504SKeyur.Desai@Sun.COM 		flags |= CSC_CACHE_VDO;
134310504SKeyur.Desai@Sun.COM 		break;
134410504SKeyur.Desai@Sun.COM 	case SMB_SHRF_CSC_MANUAL:
134510504SKeyur.Desai@Sun.COM 	default:
134610504SKeyur.Desai@Sun.COM 		/*
134710504SKeyur.Desai@Sun.COM 		 * Default to CSC_CACHE_MANUAL_REINT.
134810504SKeyur.Desai@Sun.COM 		 */
134910504SKeyur.Desai@Sun.COM 		break;
135010504SKeyur.Desai@Sun.COM 	}
135110504SKeyur.Desai@Sun.COM 
135210504SKeyur.Desai@Sun.COM 	if (si->shr_flags & SMB_SHRF_ABE)
135310504SKeyur.Desai@Sun.COM 		flags |= SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM;
135410504SKeyur.Desai@Sun.COM 
135510504SKeyur.Desai@Sun.COM 	return (flags);
135610504SKeyur.Desai@Sun.COM }
135710504SKeyur.Desai@Sun.COM 
13588474SJose.Borrego@Sun.COM /*
13598474SJose.Borrego@Sun.COM  * srvsvc_s_NetSessionEnum
13608474SJose.Borrego@Sun.COM  *
13618474SJose.Borrego@Sun.COM  * Level 1 request is made by (Server Manager (srvmgr) on NT Server when
13628474SJose.Borrego@Sun.COM  * the user info icon is selected.
13638474SJose.Borrego@Sun.COM  *
13648474SJose.Borrego@Sun.COM  * On success, the return value is NERR_Success.
13658474SJose.Borrego@Sun.COM  * On error, the return value can be one of the following error codes:
13668474SJose.Borrego@Sun.COM  *
13678474SJose.Borrego@Sun.COM  * ERROR_ACCESS_DENIED      The user does not have access to the requested
13688474SJose.Borrego@Sun.COM  *                          information.
13698474SJose.Borrego@Sun.COM  * ERROR_INVALID_LEVEL      The value specified for the level is invalid.
13708474SJose.Borrego@Sun.COM  * ERROR_INVALID_PARAMETER  The specified parameter is invalid.
13718474SJose.Borrego@Sun.COM  * ERROR_MORE_DATA          More entries are available. Specify a large
13728474SJose.Borrego@Sun.COM  *                          enough buffer to receive all entries.
13738474SJose.Borrego@Sun.COM  * ERROR_NOT_ENOUGH_MEMORY  Insufficient memory is available.
13748474SJose.Borrego@Sun.COM  * NERR_ClientNameNotFound  A session does not exist with the computer name.
13758474SJose.Borrego@Sun.COM  * NERR_InvalidComputer     The computer name is invalid.
13768474SJose.Borrego@Sun.COM  * NERR_UserNotFound        The user name could not be found.
13778474SJose.Borrego@Sun.COM  */
13788474SJose.Borrego@Sun.COM static int
13798474SJose.Borrego@Sun.COM srvsvc_s_NetSessionEnum(void *arg, ndr_xa_t *mxa)
13808474SJose.Borrego@Sun.COM {
138110122SJordan.Brown@Sun.COM 	struct mslm_NetSessionEnum	*param = arg;
138210122SJordan.Brown@Sun.COM 	srvsvc_infonres_t		*info;
138310122SJordan.Brown@Sun.COM 	smb_netsvc_t			*ns;
138410122SJordan.Brown@Sun.COM 	smb_svcenum_t			se;
138510122SJordan.Brown@Sun.COM 	DWORD				status = ERROR_SUCCESS;
138610122SJordan.Brown@Sun.COM 
138710122SJordan.Brown@Sun.COM 	if (!ndr_is_admin(mxa)) {
138810122SJordan.Brown@Sun.COM 		status = ERROR_ACCESS_DENIED;
138910122SJordan.Brown@Sun.COM 		goto srvsvc_netsessionenum_error;
139010122SJordan.Brown@Sun.COM 	}
139110122SJordan.Brown@Sun.COM 
139210122SJordan.Brown@Sun.COM 	if ((info = NDR_NEW(mxa, srvsvc_infonres_t)) == NULL) {
139310122SJordan.Brown@Sun.COM 		status = ERROR_NOT_ENOUGH_MEMORY;
139410122SJordan.Brown@Sun.COM 		goto srvsvc_netsessionenum_error;
139510122SJordan.Brown@Sun.COM 	}
139610122SJordan.Brown@Sun.COM 
139710122SJordan.Brown@Sun.COM 	info->entriesread = 0;
139810122SJordan.Brown@Sun.COM 	info->entries = NULL;
139910122SJordan.Brown@Sun.COM 	param->result.level = param->level;
140010122SJordan.Brown@Sun.COM 	param->result.bufptr.p = info;
140110122SJordan.Brown@Sun.COM 
140210122SJordan.Brown@Sun.COM 	if ((param->total_entries = srvsvc_open_sessions()) == 0) {
140310122SJordan.Brown@Sun.COM 		param->resume_handle = NULL;
140410122SJordan.Brown@Sun.COM 		param->status = ERROR_SUCCESS;
14058474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
14068474SJose.Borrego@Sun.COM 	}
14078474SJose.Borrego@Sun.COM 
140810122SJordan.Brown@Sun.COM 	bzero(&se, sizeof (smb_svcenum_t));
140910122SJordan.Brown@Sun.COM 	se.se_type = SMB_SVCENUM_TYPE_USER;
141010122SJordan.Brown@Sun.COM 	se.se_level = param->level;
141110122SJordan.Brown@Sun.COM 	se.se_ntotal = param->total_entries;
141210122SJordan.Brown@Sun.COM 	se.se_nlimit = se.se_ntotal;
141310122SJordan.Brown@Sun.COM 
141410122SJordan.Brown@Sun.COM 	if (param->resume_handle) {
141510122SJordan.Brown@Sun.COM 		se.se_resume = *param->resume_handle;
141610122SJordan.Brown@Sun.COM 		se.se_nskip = se.se_resume;
141710122SJordan.Brown@Sun.COM 		*param->resume_handle = 0;
141810122SJordan.Brown@Sun.COM 	}
14198474SJose.Borrego@Sun.COM 
14208474SJose.Borrego@Sun.COM 	switch (param->level) {
14218474SJose.Borrego@Sun.COM 	case 0:
142210122SJordan.Brown@Sun.COM 		info->entries = NDR_NEWN(mxa, struct mslm_SESSION_INFO_0,
142310122SJordan.Brown@Sun.COM 		    se.se_nlimit);
14248474SJose.Borrego@Sun.COM 		break;
142510122SJordan.Brown@Sun.COM 	case 1:
142610122SJordan.Brown@Sun.COM 		info->entries = NDR_NEWN(mxa, struct mslm_SESSION_INFO_1,
142710122SJordan.Brown@Sun.COM 		    se.se_nlimit);
14289832Samw@Sun.COM 		break;
142910122SJordan.Brown@Sun.COM 	case 2:
143010122SJordan.Brown@Sun.COM 		info->entries = NDR_NEWN(mxa, struct mslm_SESSION_INFO_2,
143110122SJordan.Brown@Sun.COM 		    se.se_nlimit);
14329832Samw@Sun.COM 		break;
143310122SJordan.Brown@Sun.COM 	case 10:
143410122SJordan.Brown@Sun.COM 		info->entries = NDR_NEWN(mxa, struct mslm_SESSION_INFO_10,
143510122SJordan.Brown@Sun.COM 		    se.se_nlimit);
143610122SJordan.Brown@Sun.COM 		break;
14379832Samw@Sun.COM 	case 502:
143810122SJordan.Brown@Sun.COM 		info->entries = NDR_NEWN(mxa, struct mslm_SESSION_INFO_502,
143910122SJordan.Brown@Sun.COM 		    se.se_nlimit);
14409832Samw@Sun.COM 		break;
14418474SJose.Borrego@Sun.COM 	default:
14428474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetSessionEnum));
144310122SJordan.Brown@Sun.COM 		param->status = ERROR_INVALID_LEVEL;
14448474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
14458474SJose.Borrego@Sun.COM 	}
14468474SJose.Borrego@Sun.COM 
144710122SJordan.Brown@Sun.COM 	if (info->entries == NULL) {
144810122SJordan.Brown@Sun.COM 		status = ERROR_NOT_ENOUGH_MEMORY;
144910122SJordan.Brown@Sun.COM 		goto srvsvc_netsessionenum_error;
145010122SJordan.Brown@Sun.COM 	}
145110122SJordan.Brown@Sun.COM 
145210122SJordan.Brown@Sun.COM 	if ((ns = smb_kmod_enum_init(&se)) == NULL) {
145310122SJordan.Brown@Sun.COM 		status = ERROR_NOT_ENOUGH_MEMORY;
145410122SJordan.Brown@Sun.COM 		goto srvsvc_netsessionenum_error;
145510122SJordan.Brown@Sun.COM 	}
145610122SJordan.Brown@Sun.COM 
145710122SJordan.Brown@Sun.COM 	status = srvsvc_NetSessionEnumCommon(mxa, info, ns, &se);
145810122SJordan.Brown@Sun.COM 	smb_kmod_enum_fini(ns);
145910122SJordan.Brown@Sun.COM 
146010122SJordan.Brown@Sun.COM 	if (status != ERROR_SUCCESS)
146110122SJordan.Brown@Sun.COM 		goto srvsvc_netsessionenum_error;
146210122SJordan.Brown@Sun.COM 
146310122SJordan.Brown@Sun.COM 	if (param->resume_handle &&
146410122SJordan.Brown@Sun.COM 	    param->pref_max_len != SMB_SRVSVC_MAXPREFLEN) {
146510122SJordan.Brown@Sun.COM 		if (se.se_resume < param->total_entries) {
146610122SJordan.Brown@Sun.COM 			*param->resume_handle = se.se_resume;
146710122SJordan.Brown@Sun.COM 			status = ERROR_MORE_DATA;
146810122SJordan.Brown@Sun.COM 		}
146910122SJordan.Brown@Sun.COM 	}
147010122SJordan.Brown@Sun.COM 
147110122SJordan.Brown@Sun.COM 	param->total_entries = info->entriesread;
147210122SJordan.Brown@Sun.COM 	param->status = status;
147310122SJordan.Brown@Sun.COM 	return (NDR_DRC_OK);
147410122SJordan.Brown@Sun.COM 
147510122SJordan.Brown@Sun.COM srvsvc_netsessionenum_error:
147610122SJordan.Brown@Sun.COM 	bzero(param, sizeof (struct mslm_NetSessionEnum));
14778474SJose.Borrego@Sun.COM 	param->status = status;
14788474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
14798474SJose.Borrego@Sun.COM }
14808474SJose.Borrego@Sun.COM 
148110122SJordan.Brown@Sun.COM static uint32_t
148210122SJordan.Brown@Sun.COM srvsvc_NetSessionEnumCommon(ndr_xa_t *mxa, srvsvc_infonres_t *info,
148310122SJordan.Brown@Sun.COM     smb_netsvc_t *ns, smb_svcenum_t *se)
14848474SJose.Borrego@Sun.COM {
148510122SJordan.Brown@Sun.COM 	struct mslm_SESSION_INFO_0	*info0 = info->entries;
148610122SJordan.Brown@Sun.COM 	struct mslm_SESSION_INFO_1	*info1 = info->entries;
148710122SJordan.Brown@Sun.COM 	struct mslm_SESSION_INFO_2	*info2 = info->entries;
148810122SJordan.Brown@Sun.COM 	struct mslm_SESSION_INFO_10	*info10 = info->entries;
148910122SJordan.Brown@Sun.COM 	struct mslm_SESSION_INFO_502	*info502 = info->entries;
149010122SJordan.Brown@Sun.COM 	smb_netsvcitem_t		*item;
149110122SJordan.Brown@Sun.COM 	smb_netuserinfo_t		*user;
149210122SJordan.Brown@Sun.COM 	char				*workstation;
149310122SJordan.Brown@Sun.COM 	char				account[MAXNAMELEN];
149410122SJordan.Brown@Sun.COM 	char				ipaddr_buf[INET6_ADDRSTRLEN];
149510122SJordan.Brown@Sun.COM 	uint32_t			logon_time;
149610122SJordan.Brown@Sun.COM 	uint32_t			flags;
149710122SJordan.Brown@Sun.COM 	uint32_t			entries_read = 0;
149810122SJordan.Brown@Sun.COM 
149910122SJordan.Brown@Sun.COM 	if (smb_kmod_enum(ns) != 0)
150010122SJordan.Brown@Sun.COM 		return (ERROR_INTERNAL_ERROR);
150110122SJordan.Brown@Sun.COM 
150210122SJordan.Brown@Sun.COM 	item = list_head(&ns->ns_list);
150310122SJordan.Brown@Sun.COM 	while (item != NULL) {
150410122SJordan.Brown@Sun.COM 		user = &item->nsi_un.nsi_user;
150510122SJordan.Brown@Sun.COM 
150610122SJordan.Brown@Sun.COM 		workstation = user->ui_workstation;
15078474SJose.Borrego@Sun.COM 		if (workstation == NULL || *workstation == '\0') {
150810122SJordan.Brown@Sun.COM 			(void) smb_inet_ntop(&user->ui_ipaddr, ipaddr_buf,
150910122SJordan.Brown@Sun.COM 			    SMB_IPSTRLEN(user->ui_ipaddr.a_family));
15108474SJose.Borrego@Sun.COM 			workstation = ipaddr_buf;
15118474SJose.Borrego@Sun.COM 		}
15128474SJose.Borrego@Sun.COM 
15138474SJose.Borrego@Sun.COM 		(void) snprintf(account, MAXNAMELEN, "%s\\%s",
151410122SJordan.Brown@Sun.COM 		    user->ui_domain, user->ui_account);
151510122SJordan.Brown@Sun.COM 
151610122SJordan.Brown@Sun.COM 		logon_time = time(0) - user->ui_logon_time;
151710122SJordan.Brown@Sun.COM 		flags = (user->ui_flags & SMB_ATF_GUEST) ? SESS_GUEST : 0;
151810122SJordan.Brown@Sun.COM 
151910122SJordan.Brown@Sun.COM 		switch (se->se_level) {
152010122SJordan.Brown@Sun.COM 		case 0:
152110122SJordan.Brown@Sun.COM 			info0->sesi0_cname = NDR_STRDUP(mxa, workstation);
152210122SJordan.Brown@Sun.COM 			if (info0->sesi0_cname == NULL)
152310122SJordan.Brown@Sun.COM 				return (ERROR_NOT_ENOUGH_MEMORY);
152410122SJordan.Brown@Sun.COM 			++info0;
152510122SJordan.Brown@Sun.COM 			break;
152610122SJordan.Brown@Sun.COM 
152710122SJordan.Brown@Sun.COM 		case 1:
152810122SJordan.Brown@Sun.COM 			info1->sesi1_cname = NDR_STRDUP(mxa, workstation);
152910122SJordan.Brown@Sun.COM 			info1->sesi1_uname = NDR_STRDUP(mxa, account);
153010122SJordan.Brown@Sun.COM 
153110122SJordan.Brown@Sun.COM 			if (info1->sesi1_cname == NULL ||
153210122SJordan.Brown@Sun.COM 			    info1->sesi1_uname == NULL)
153310122SJordan.Brown@Sun.COM 				return (ERROR_NOT_ENOUGH_MEMORY);
153410122SJordan.Brown@Sun.COM 
153510122SJordan.Brown@Sun.COM 			info1->sesi1_nopens = user->ui_numopens;
153610122SJordan.Brown@Sun.COM 			info1->sesi1_time = logon_time;
153710122SJordan.Brown@Sun.COM 			info1->sesi1_itime = 0;
153810122SJordan.Brown@Sun.COM 			info1->sesi1_uflags = flags;
153910122SJordan.Brown@Sun.COM 			++info1;
154010122SJordan.Brown@Sun.COM 			break;
154110122SJordan.Brown@Sun.COM 
154210122SJordan.Brown@Sun.COM 		case 2:
154310122SJordan.Brown@Sun.COM 			info2->sesi2_cname = NDR_STRDUP(mxa, workstation);
154410122SJordan.Brown@Sun.COM 			info2->sesi2_uname = NDR_STRDUP(mxa, account);
154510122SJordan.Brown@Sun.COM 
154610122SJordan.Brown@Sun.COM 			if (info2->sesi2_cname == NULL ||
154710122SJordan.Brown@Sun.COM 			    info2->sesi2_uname == NULL)
154810122SJordan.Brown@Sun.COM 				return (ERROR_NOT_ENOUGH_MEMORY);
154910122SJordan.Brown@Sun.COM 
155010122SJordan.Brown@Sun.COM 			info2->sesi2_nopens = user->ui_numopens;
155110122SJordan.Brown@Sun.COM 			info2->sesi2_time = logon_time;
155210122SJordan.Brown@Sun.COM 			info2->sesi2_itime = 0;
155310122SJordan.Brown@Sun.COM 			info2->sesi2_uflags = flags;
155410122SJordan.Brown@Sun.COM 			info2->sesi2_cltype_name = (uint8_t *)"";
155510122SJordan.Brown@Sun.COM 			++info2;
155610122SJordan.Brown@Sun.COM 			break;
155710122SJordan.Brown@Sun.COM 
155810122SJordan.Brown@Sun.COM 		case 10:
155910122SJordan.Brown@Sun.COM 			info10->sesi10_cname = NDR_STRDUP(mxa, workstation);
156010122SJordan.Brown@Sun.COM 			info10->sesi10_uname = NDR_STRDUP(mxa, account);
156110122SJordan.Brown@Sun.COM 
156210122SJordan.Brown@Sun.COM 			if (info10->sesi10_cname == NULL ||
156310122SJordan.Brown@Sun.COM 			    info10->sesi10_uname == NULL)
156410122SJordan.Brown@Sun.COM 				return (ERROR_NOT_ENOUGH_MEMORY);
156510122SJordan.Brown@Sun.COM 
156610122SJordan.Brown@Sun.COM 			info10->sesi10_time = logon_time;
156710122SJordan.Brown@Sun.COM 			info10->sesi10_itime = 0;
156810122SJordan.Brown@Sun.COM 			++info10;
156910122SJordan.Brown@Sun.COM 			break;
157010122SJordan.Brown@Sun.COM 
157110122SJordan.Brown@Sun.COM 		case 502:
157210122SJordan.Brown@Sun.COM 			info502->sesi502_cname = NDR_STRDUP(mxa, workstation);
157310122SJordan.Brown@Sun.COM 			info502->sesi502_uname = NDR_STRDUP(mxa, account);
157410122SJordan.Brown@Sun.COM 
157510122SJordan.Brown@Sun.COM 			if (info502->sesi502_cname == NULL ||
157610122SJordan.Brown@Sun.COM 			    info502->sesi502_uname == NULL)
157710122SJordan.Brown@Sun.COM 				return (ERROR_NOT_ENOUGH_MEMORY);
157810122SJordan.Brown@Sun.COM 
157910122SJordan.Brown@Sun.COM 			info502->sesi502_nopens = user->ui_numopens;
158010122SJordan.Brown@Sun.COM 			info502->sesi502_time = logon_time;
158110122SJordan.Brown@Sun.COM 			info502->sesi502_itime = 0;
158210122SJordan.Brown@Sun.COM 			info502->sesi502_uflags = flags;
158310122SJordan.Brown@Sun.COM 			info502->sesi502_cltype_name = (uint8_t *)"";
158410122SJordan.Brown@Sun.COM 			info502->sesi502_transport = (uint8_t *)"";
158510122SJordan.Brown@Sun.COM 			++info502;
158610122SJordan.Brown@Sun.COM 			break;
158710122SJordan.Brown@Sun.COM 
158810122SJordan.Brown@Sun.COM 		default:
158910122SJordan.Brown@Sun.COM 			return (ERROR_INVALID_LEVEL);
15908474SJose.Borrego@Sun.COM 		}
15918474SJose.Borrego@Sun.COM 
159210122SJordan.Brown@Sun.COM 		++entries_read;
159310122SJordan.Brown@Sun.COM 		item = list_next(&ns->ns_list, item);
15949832Samw@Sun.COM 	}
15959832Samw@Sun.COM 
159610122SJordan.Brown@Sun.COM 	info->entriesread = entries_read;
15979832Samw@Sun.COM 	return (ERROR_SUCCESS);
15989832Samw@Sun.COM }
15999832Samw@Sun.COM 
16009832Samw@Sun.COM /*
16018474SJose.Borrego@Sun.COM  * srvsvc_s_NetSessionDel
16028474SJose.Borrego@Sun.COM  *
16038474SJose.Borrego@Sun.COM  * Ends a network session between a server and a workstation.
16048474SJose.Borrego@Sun.COM  * On NT only members of the Administrators or Account Operators
16058474SJose.Borrego@Sun.COM  * local groups are permitted to use NetSessionDel.
16068474SJose.Borrego@Sun.COM  *
160710122SJordan.Brown@Sun.COM  * If unc_clientname is NULL, all sessions associated with the
160810122SJordan.Brown@Sun.COM  * specified user will be disconnected.
160910122SJordan.Brown@Sun.COM  *
161010122SJordan.Brown@Sun.COM  * If username is NULL, all sessions from the specified client
161110122SJordan.Brown@Sun.COM  * will be disconnected.
161210122SJordan.Brown@Sun.COM  *
16138474SJose.Borrego@Sun.COM  * Return Values
161410122SJordan.Brown@Sun.COM  * On success, the return value is NERR_Success/ERROR_SUCCESS.
161510122SJordan.Brown@Sun.COM  * On failure, the return value can be one of the following errors:
16168474SJose.Borrego@Sun.COM  *
16178474SJose.Borrego@Sun.COM  * ERROR_ACCESS_DENIED 		The user does not have access to the
161810122SJordan.Brown@Sun.COM  * 				requested information.
16198474SJose.Borrego@Sun.COM  * ERROR_INVALID_PARAMETER	The specified parameter is invalid.
16208474SJose.Borrego@Sun.COM  * ERROR_NOT_ENOUGH_MEMORY	Insufficient memory is available.
16218474SJose.Borrego@Sun.COM  * NERR_ClientNameNotFound	A session does not exist with that
162210122SJordan.Brown@Sun.COM  *				computer name.
16238474SJose.Borrego@Sun.COM  */
16248474SJose.Borrego@Sun.COM static int
16258474SJose.Borrego@Sun.COM srvsvc_s_NetSessionDel(void *arg, ndr_xa_t *mxa)
16268474SJose.Borrego@Sun.COM {
162710122SJordan.Brown@Sun.COM 	static struct {
162810122SJordan.Brown@Sun.COM 		int errnum;
162910122SJordan.Brown@Sun.COM 		int nerr;
163010122SJordan.Brown@Sun.COM 	} errmap[] = {
163110122SJordan.Brown@Sun.COM 		0,	ERROR_SUCCESS,
163210122SJordan.Brown@Sun.COM 		EACCES,	ERROR_ACCESS_DENIED,
163310122SJordan.Brown@Sun.COM 		EPERM,	ERROR_ACCESS_DENIED,
163410122SJordan.Brown@Sun.COM 		EINVAL,	ERROR_INVALID_PARAMETER,
163510122SJordan.Brown@Sun.COM 		ENOMEM,	ERROR_NOT_ENOUGH_MEMORY,
163610122SJordan.Brown@Sun.COM 		ENOENT,	NERR_ClientNameNotFound
163710122SJordan.Brown@Sun.COM 	};
163810122SJordan.Brown@Sun.COM 
16398474SJose.Borrego@Sun.COM 	struct mslm_NetSessionDel *param = arg;
164010122SJordan.Brown@Sun.COM 	int	i;
164110122SJordan.Brown@Sun.COM 	int	rc;
164210122SJordan.Brown@Sun.COM 
164310122SJordan.Brown@Sun.COM 	if (!ndr_is_admin(mxa)) {
16448474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
16458474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
16468474SJose.Borrego@Sun.COM 	}
16478474SJose.Borrego@Sun.COM 
164810122SJordan.Brown@Sun.COM 	rc = smb_kmod_session_close((char *)param->unc_clientname,
164910122SJordan.Brown@Sun.COM 	    (char *)param->username);
165010122SJordan.Brown@Sun.COM 
165110122SJordan.Brown@Sun.COM 	for (i = 0; i < (sizeof (errmap) / sizeof (errmap[0])); ++i) {
165210122SJordan.Brown@Sun.COM 		if (rc == errmap[i].errnum) {
165310122SJordan.Brown@Sun.COM 			param->status = errmap[i].nerr;
165410122SJordan.Brown@Sun.COM 			return (NDR_DRC_OK);
165510122SJordan.Brown@Sun.COM 		}
165610122SJordan.Brown@Sun.COM 	}
165710122SJordan.Brown@Sun.COM 
165810122SJordan.Brown@Sun.COM 	param->status = ERROR_INTERNAL_ERROR;
16598474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
16608474SJose.Borrego@Sun.COM }
16618474SJose.Borrego@Sun.COM 
16628474SJose.Borrego@Sun.COM static int
16638474SJose.Borrego@Sun.COM srvsvc_s_NetServerGetInfo(void *arg, ndr_xa_t *mxa)
16648474SJose.Borrego@Sun.COM {
16658474SJose.Borrego@Sun.COM 	struct mslm_NetServerGetInfo *param = arg;
16668474SJose.Borrego@Sun.COM 	struct mslm_SERVER_INFO_100 *info100;
16678474SJose.Borrego@Sun.COM 	struct mslm_SERVER_INFO_101 *info101;
16688474SJose.Borrego@Sun.COM 	struct mslm_SERVER_INFO_102 *info102;
16699832Samw@Sun.COM 	struct mslm_SERVER_INFO_502 *info502;
16709832Samw@Sun.COM 	struct mslm_SERVER_INFO_503 *info503;
16718474SJose.Borrego@Sun.COM 	char sys_comment[SMB_PI_MAX_COMMENT];
16728474SJose.Borrego@Sun.COM 	char hostname[NETBIOS_NAME_SZ];
167311963SAfshin.Ardakani@Sun.COM 	smb_version_t version;
16748474SJose.Borrego@Sun.COM 
16758474SJose.Borrego@Sun.COM 	if (smb_getnetbiosname(hostname, sizeof (hostname)) != 0) {
16768474SJose.Borrego@Sun.COM netservergetinfo_no_memory:
16778474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetServerGetInfo));
16788474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
16798474SJose.Borrego@Sun.COM 	}
16808474SJose.Borrego@Sun.COM 
16818474SJose.Borrego@Sun.COM 	(void) smb_config_getstr(SMB_CI_SYS_CMNT, sys_comment,
16828474SJose.Borrego@Sun.COM 	    sizeof (sys_comment));
16838474SJose.Borrego@Sun.COM 	if (*sys_comment == '\0')
16848474SJose.Borrego@Sun.COM 		(void) strcpy(sys_comment, " ");
16858474SJose.Borrego@Sun.COM 
168611963SAfshin.Ardakani@Sun.COM 	smb_config_get_version(&version);
168711963SAfshin.Ardakani@Sun.COM 
16888474SJose.Borrego@Sun.COM 	switch (param->level) {
16898474SJose.Borrego@Sun.COM 	case 100:
16908474SJose.Borrego@Sun.COM 		info100 = NDR_NEW(mxa, struct mslm_SERVER_INFO_100);
16918474SJose.Borrego@Sun.COM 		if (info100 == NULL)
16928474SJose.Borrego@Sun.COM 			goto netservergetinfo_no_memory;
16938474SJose.Borrego@Sun.COM 
16948474SJose.Borrego@Sun.COM 		bzero(info100, sizeof (struct mslm_SERVER_INFO_100));
16958474SJose.Borrego@Sun.COM 		info100->sv100_platform_id = SV_PLATFORM_ID_NT;
16968474SJose.Borrego@Sun.COM 		info100->sv100_name = (uint8_t *)NDR_STRDUP(mxa, hostname);
16978474SJose.Borrego@Sun.COM 		if (info100->sv100_name == NULL)
16988474SJose.Borrego@Sun.COM 			goto netservergetinfo_no_memory;
16998474SJose.Borrego@Sun.COM 
17008474SJose.Borrego@Sun.COM 		param->result.bufptr.bufptr100 = info100;
17018474SJose.Borrego@Sun.COM 		break;
17028474SJose.Borrego@Sun.COM 
17038474SJose.Borrego@Sun.COM 	case 101:
17048474SJose.Borrego@Sun.COM 		info101 = NDR_NEW(mxa, struct mslm_SERVER_INFO_101);
17058474SJose.Borrego@Sun.COM 		if (info101 == NULL)
17068474SJose.Borrego@Sun.COM 			goto netservergetinfo_no_memory;
17078474SJose.Borrego@Sun.COM 
17088474SJose.Borrego@Sun.COM 		bzero(info101, sizeof (struct mslm_SERVER_INFO_101));
17098474SJose.Borrego@Sun.COM 		info101->sv101_platform_id = SV_PLATFORM_ID_NT;
171011963SAfshin.Ardakani@Sun.COM 		info101->sv101_version_major = version.sv_major;
171111963SAfshin.Ardakani@Sun.COM 		info101->sv101_version_minor = version.sv_minor;
171211337SWilliam.Krier@Sun.COM 		info101->sv101_type = SV_TYPE_DEFAULT;
17138474SJose.Borrego@Sun.COM 		info101->sv101_name = (uint8_t *)NDR_STRDUP(mxa, hostname);
17148474SJose.Borrego@Sun.COM 		info101->sv101_comment
17158474SJose.Borrego@Sun.COM 		    = (uint8_t *)NDR_STRDUP(mxa, sys_comment);
17168474SJose.Borrego@Sun.COM 
17178474SJose.Borrego@Sun.COM 		if (info101->sv101_name == NULL ||
17188474SJose.Borrego@Sun.COM 		    info101->sv101_comment == NULL)
17198474SJose.Borrego@Sun.COM 			goto netservergetinfo_no_memory;
17208474SJose.Borrego@Sun.COM 
17218474SJose.Borrego@Sun.COM 		param->result.bufptr.bufptr101 = info101;
17228474SJose.Borrego@Sun.COM 		break;
17238474SJose.Borrego@Sun.COM 
17248474SJose.Borrego@Sun.COM 	case 102:
17258474SJose.Borrego@Sun.COM 		info102 = NDR_NEW(mxa, struct mslm_SERVER_INFO_102);
17268474SJose.Borrego@Sun.COM 		if (info102 == NULL)
17278474SJose.Borrego@Sun.COM 			goto netservergetinfo_no_memory;
17288474SJose.Borrego@Sun.COM 
17298474SJose.Borrego@Sun.COM 		bzero(info102, sizeof (struct mslm_SERVER_INFO_102));
17308474SJose.Borrego@Sun.COM 		info102->sv102_platform_id = SV_PLATFORM_ID_NT;
173111963SAfshin.Ardakani@Sun.COM 		info102->sv102_version_major = version.sv_major;
173211963SAfshin.Ardakani@Sun.COM 		info102->sv102_version_minor = version.sv_minor;
173311337SWilliam.Krier@Sun.COM 		info102->sv102_type = SV_TYPE_DEFAULT;
17348474SJose.Borrego@Sun.COM 		info102->sv102_name = (uint8_t *)NDR_STRDUP(mxa, hostname);
17358474SJose.Borrego@Sun.COM 		info102->sv102_comment
17368474SJose.Borrego@Sun.COM 		    = (uint8_t *)NDR_STRDUP(mxa, sys_comment);
17378474SJose.Borrego@Sun.COM 
17388474SJose.Borrego@Sun.COM 		/*
17398474SJose.Borrego@Sun.COM 		 * The following level 102 fields are defaulted to zero
17408474SJose.Borrego@Sun.COM 		 * by virtue of the call to bzero above.
17418474SJose.Borrego@Sun.COM 		 *
17428474SJose.Borrego@Sun.COM 		 * sv102_users
17438474SJose.Borrego@Sun.COM 		 * sv102_disc
17448474SJose.Borrego@Sun.COM 		 * sv102_hidden
17458474SJose.Borrego@Sun.COM 		 * sv102_announce
17468474SJose.Borrego@Sun.COM 		 * sv102_anndelta
17478474SJose.Borrego@Sun.COM 		 * sv102_licenses
17488474SJose.Borrego@Sun.COM 		 * sv102_userpath
17498474SJose.Borrego@Sun.COM 		 */
17508474SJose.Borrego@Sun.COM 		if (info102->sv102_name == NULL ||
17518474SJose.Borrego@Sun.COM 		    info102->sv102_comment == NULL)
17528474SJose.Borrego@Sun.COM 			goto netservergetinfo_no_memory;
17538474SJose.Borrego@Sun.COM 
17548474SJose.Borrego@Sun.COM 		param->result.bufptr.bufptr102 = info102;
17558474SJose.Borrego@Sun.COM 		break;
17568474SJose.Borrego@Sun.COM 
17579832Samw@Sun.COM 	case 502:
17589832Samw@Sun.COM 		info502 = NDR_NEW(mxa, struct mslm_SERVER_INFO_502);
17599832Samw@Sun.COM 		if (info502 == NULL)
17609832Samw@Sun.COM 			goto netservergetinfo_no_memory;
17619832Samw@Sun.COM 
17629832Samw@Sun.COM 		bzero(info502, sizeof (struct mslm_SERVER_INFO_502));
17639832Samw@Sun.COM 		param->result.bufptr.bufptr502 = info502;
17649832Samw@Sun.COM #ifdef SRVSVC_SATISFY_SMBTORTURE
17659832Samw@Sun.COM 		break;
17669832Samw@Sun.COM #else
17679832Samw@Sun.COM 		param->result.level = param->level;
17689832Samw@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
17699832Samw@Sun.COM 		return (NDR_DRC_OK);
17709832Samw@Sun.COM #endif /* SRVSVC_SATISFY_SMBTORTURE */
17719832Samw@Sun.COM 
17729832Samw@Sun.COM 	case 503:
17739832Samw@Sun.COM 		info503 = NDR_NEW(mxa, struct mslm_SERVER_INFO_503);
17749832Samw@Sun.COM 		if (info503 == NULL)
17759832Samw@Sun.COM 			goto netservergetinfo_no_memory;
17769832Samw@Sun.COM 
17779832Samw@Sun.COM 		bzero(info503, sizeof (struct mslm_SERVER_INFO_503));
17789832Samw@Sun.COM 		param->result.bufptr.bufptr503 = info503;
17799832Samw@Sun.COM #ifdef SRVSVC_SATISFY_SMBTORTURE
17809832Samw@Sun.COM 		break;
17819832Samw@Sun.COM #else
17829832Samw@Sun.COM 		param->result.level = param->level;
17839832Samw@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
17849832Samw@Sun.COM 		return (NDR_DRC_OK);
17859832Samw@Sun.COM #endif /* SRVSVC_SATISFY_SMBTORTURE */
17869832Samw@Sun.COM 
17878474SJose.Borrego@Sun.COM 	default:
17888474SJose.Borrego@Sun.COM 		bzero(&param->result,
17898474SJose.Borrego@Sun.COM 		    sizeof (struct mslm_NetServerGetInfo_result));
17908474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
17918474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
17928474SJose.Borrego@Sun.COM 	}
17938474SJose.Borrego@Sun.COM 
17948474SJose.Borrego@Sun.COM 	param->result.level = param->level;
17959832Samw@Sun.COM 	param->status = ERROR_SUCCESS;
17968474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
17978474SJose.Borrego@Sun.COM }
17988474SJose.Borrego@Sun.COM 
17998474SJose.Borrego@Sun.COM /*
18008474SJose.Borrego@Sun.COM  * NetRemoteTOD
18018474SJose.Borrego@Sun.COM  *
18028474SJose.Borrego@Sun.COM  * Returns information about the time of day on this server.
18038474SJose.Borrego@Sun.COM  *
18048474SJose.Borrego@Sun.COM  * typedef struct _TIME_OF_DAY_INFO {
18058474SJose.Borrego@Sun.COM  *	DWORD tod_elapsedt;  // seconds since 00:00:00 January 1 1970 GMT
18068474SJose.Borrego@Sun.COM  *	DWORD tod_msecs;     // arbitrary milliseconds (since reset)
18078474SJose.Borrego@Sun.COM  *	DWORD tod_hours;     // current hour [0-23]
18088474SJose.Borrego@Sun.COM  *	DWORD tod_mins;      // current minute [0-59]
18098474SJose.Borrego@Sun.COM  *	DWORD tod_secs;      // current second [0-59]
18108474SJose.Borrego@Sun.COM  *	DWORD tod_hunds;     // current hundredth (0.01) second [0-99]
18118474SJose.Borrego@Sun.COM  *	LONG tod_timezone;   // time zone of the server
18128474SJose.Borrego@Sun.COM  *	DWORD tod_tinterval; // clock tick time interval
18138474SJose.Borrego@Sun.COM  *	DWORD tod_day;       // day of the month [1-31]
18148474SJose.Borrego@Sun.COM  *	DWORD tod_month;     // month of the year [1-12]
18158474SJose.Borrego@Sun.COM  *	DWORD tod_year;      // current year
18168474SJose.Borrego@Sun.COM  *	DWORD tod_weekday;   // day of the week since Sunday [0-6]
18178474SJose.Borrego@Sun.COM  * } TIME_OF_DAY_INFO;
18188474SJose.Borrego@Sun.COM  *
18198474SJose.Borrego@Sun.COM  * The time zone of the server is calculated in minutes from Greenwich
18208474SJose.Borrego@Sun.COM  * Mean Time (GMT). For time zones west of Greenwich, the value is
18218474SJose.Borrego@Sun.COM  * positive; for time zones east of Greenwich, the value is negative.
18228474SJose.Borrego@Sun.COM  * A value of -1 indicates that the time zone is undefined.
18238474SJose.Borrego@Sun.COM  *
182410966SJordan.Brown@Sun.COM  * Determine offset from GMT. If daylight saving time use altzone,
182510966SJordan.Brown@Sun.COM  * otherwise use timezone.
182610966SJordan.Brown@Sun.COM  *
18278474SJose.Borrego@Sun.COM  * The clock tick value represents a resolution of one ten-thousandth
18288474SJose.Borrego@Sun.COM  * (0.0001) second.
18298474SJose.Borrego@Sun.COM  */
18308474SJose.Borrego@Sun.COM static int
18318474SJose.Borrego@Sun.COM srvsvc_s_NetRemoteTOD(void *arg, ndr_xa_t *mxa)
18328474SJose.Borrego@Sun.COM {
18338474SJose.Borrego@Sun.COM 	struct mslm_NetRemoteTOD *param = arg;
18348474SJose.Borrego@Sun.COM 	struct mslm_TIME_OF_DAY_INFO *tod;
18358474SJose.Borrego@Sun.COM 	struct timeval		time_val;
18368474SJose.Borrego@Sun.COM 	struct tm		tm;
183710966SJordan.Brown@Sun.COM 	time_t			gmtoff;
183810966SJordan.Brown@Sun.COM 
18398474SJose.Borrego@Sun.COM 
18408474SJose.Borrego@Sun.COM 	(void) gettimeofday(&time_val, 0);
18418474SJose.Borrego@Sun.COM 	(void) gmtime_r(&time_val.tv_sec, &tm);
18428474SJose.Borrego@Sun.COM 
18438474SJose.Borrego@Sun.COM 	tod = NDR_NEW(mxa, struct mslm_TIME_OF_DAY_INFO);
18448474SJose.Borrego@Sun.COM 	if (tod == NULL) {
18458474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetRemoteTOD));
18468474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
18478474SJose.Borrego@Sun.COM 	}
18488474SJose.Borrego@Sun.COM 
184910966SJordan.Brown@Sun.COM 	bzero(tod, sizeof (struct mslm_TIME_OF_DAY_INFO));
185010966SJordan.Brown@Sun.COM 
18518474SJose.Borrego@Sun.COM 	tod->tod_elapsedt = time_val.tv_sec;
18528474SJose.Borrego@Sun.COM 	tod->tod_msecs = time_val.tv_usec;
18538474SJose.Borrego@Sun.COM 	tod->tod_hours = tm.tm_hour;
18548474SJose.Borrego@Sun.COM 	tod->tod_mins = tm.tm_min;
18558474SJose.Borrego@Sun.COM 	tod->tod_secs = tm.tm_sec;
18568474SJose.Borrego@Sun.COM 	tod->tod_hunds = 0;
18578474SJose.Borrego@Sun.COM 	tod->tod_tinterval = 1000;
18588474SJose.Borrego@Sun.COM 	tod->tod_day = tm.tm_mday;
18598474SJose.Borrego@Sun.COM 	tod->tod_month = tm.tm_mon+1;
18608474SJose.Borrego@Sun.COM 	tod->tod_year = tm.tm_year+1900;
18618474SJose.Borrego@Sun.COM 	tod->tod_weekday = tm.tm_wday;
18628474SJose.Borrego@Sun.COM 
18638474SJose.Borrego@Sun.COM 	(void) localtime_r(&time_val.tv_sec, &tm);
186410966SJordan.Brown@Sun.COM 	gmtoff = (tm.tm_isdst) ? altzone : timezone;
186510966SJordan.Brown@Sun.COM 	tod->tod_timezone = gmtoff / SECSPERMIN;
18668474SJose.Borrego@Sun.COM 
18678474SJose.Borrego@Sun.COM 	param->bufptr = tod;
18688474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
18698474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
18708474SJose.Borrego@Sun.COM }
18718474SJose.Borrego@Sun.COM 
18728474SJose.Borrego@Sun.COM /*
18738474SJose.Borrego@Sun.COM  * srvsvc_s_NetNameValidate
18748474SJose.Borrego@Sun.COM  *
18758474SJose.Borrego@Sun.COM  * Perform name validation.
18768474SJose.Borrego@Sun.COM  *
18778474SJose.Borrego@Sun.COM  * Returns Win32 error codes.
18788474SJose.Borrego@Sun.COM  */
18798474SJose.Borrego@Sun.COM /*ARGSUSED*/
18808474SJose.Borrego@Sun.COM static int
18818474SJose.Borrego@Sun.COM srvsvc_s_NetNameValidate(void *arg, ndr_xa_t *mxa)
18828474SJose.Borrego@Sun.COM {
18838474SJose.Borrego@Sun.COM 	struct mslm_NetNameValidate *param = arg;
18848474SJose.Borrego@Sun.COM 	char *name;
188511337SWilliam.Krier@Sun.COM 	int maxlen;
18868474SJose.Borrego@Sun.COM 	int len;
18878474SJose.Borrego@Sun.COM 
18888474SJose.Borrego@Sun.COM 	if ((name = (char *)param->pathname) == NULL) {
18898474SJose.Borrego@Sun.COM 		param->status = ERROR_INVALID_PARAMETER;
18908474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
18918474SJose.Borrego@Sun.COM 	}
18928474SJose.Borrego@Sun.COM 
18938474SJose.Borrego@Sun.COM 	switch (param->type) {
18948474SJose.Borrego@Sun.COM 	case NAMETYPE_SHARE:
189511337SWilliam.Krier@Sun.COM 		len = strlen(name);
189611337SWilliam.Krier@Sun.COM 		maxlen = (param->flags & NAMEFLAG_LM2) ?
189711337SWilliam.Krier@Sun.COM 		    SMB_SHARE_OEMNAME_MAX : SMB_SHARE_NTNAME_MAX;
189811337SWilliam.Krier@Sun.COM 
189911337SWilliam.Krier@Sun.COM 		if (len > maxlen) {
19008474SJose.Borrego@Sun.COM 			param->status = ERROR_INVALID_NAME;
190111337SWilliam.Krier@Sun.COM 			return (NDR_DRC_OK);
190211337SWilliam.Krier@Sun.COM 		}
190311337SWilliam.Krier@Sun.COM 
190411337SWilliam.Krier@Sun.COM 		param->status = smb_name_validate_share(name);
19058474SJose.Borrego@Sun.COM 		break;
19068474SJose.Borrego@Sun.COM 
19078474SJose.Borrego@Sun.COM 	case NAMETYPE_USER:
190811337SWilliam.Krier@Sun.COM 	case NAMETYPE_GROUP:
190911337SWilliam.Krier@Sun.COM 		param->status = smb_name_validate_account(name);
191011337SWilliam.Krier@Sun.COM 		break;
191111337SWilliam.Krier@Sun.COM 
191211337SWilliam.Krier@Sun.COM 	case NAMETYPE_DOMAIN:	/* NetBIOS domain name */
191311337SWilliam.Krier@Sun.COM 		param->status = smb_name_validate_nbdomain(name);
191411337SWilliam.Krier@Sun.COM 		break;
191511337SWilliam.Krier@Sun.COM 
191611337SWilliam.Krier@Sun.COM 	case NAMETYPE_WORKGROUP:
191711337SWilliam.Krier@Sun.COM 		param->status = smb_name_validate_workgroup(name);
191811337SWilliam.Krier@Sun.COM 		break;
191911337SWilliam.Krier@Sun.COM 
19208474SJose.Borrego@Sun.COM 	case NAMETYPE_PASSWORD:
19218474SJose.Borrego@Sun.COM 	case NAMETYPE_COMPUTER:
19228474SJose.Borrego@Sun.COM 	case NAMETYPE_EVENT:
19238474SJose.Borrego@Sun.COM 	case NAMETYPE_SERVICE:
19248474SJose.Borrego@Sun.COM 	case NAMETYPE_NET:
19258474SJose.Borrego@Sun.COM 	case NAMETYPE_MESSAGE:
19268474SJose.Borrego@Sun.COM 	case NAMETYPE_MESSAGEDEST:
19278474SJose.Borrego@Sun.COM 	case NAMETYPE_SHAREPASSWORD:
19288474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_SUPPORTED;
19298474SJose.Borrego@Sun.COM 		break;
19308474SJose.Borrego@Sun.COM 
19318474SJose.Borrego@Sun.COM 	default:
19328474SJose.Borrego@Sun.COM 		param->status = ERROR_INVALID_PARAMETER;
19338474SJose.Borrego@Sun.COM 		break;
19348474SJose.Borrego@Sun.COM 	}
19358474SJose.Borrego@Sun.COM 
19368474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
19378474SJose.Borrego@Sun.COM }
19388474SJose.Borrego@Sun.COM 
19398474SJose.Borrego@Sun.COM /*
19408474SJose.Borrego@Sun.COM  * srvsvc_s_NetShareAdd
19418474SJose.Borrego@Sun.COM  *
19429832Samw@Sun.COM  * Add a new share. Only power users groups can manage shares.
19438474SJose.Borrego@Sun.COM  *
19448474SJose.Borrego@Sun.COM  * This interface is used by the rmtshare command from the NT resource
19458474SJose.Borrego@Sun.COM  * kit. Rmtshare allows a client to add or remove shares on a server
19468474SJose.Borrego@Sun.COM  * from the client's command line.
19478474SJose.Borrego@Sun.COM  *
19488474SJose.Borrego@Sun.COM  * Returns Win32 error codes.
19498474SJose.Borrego@Sun.COM  */
19508474SJose.Borrego@Sun.COM static int
19518474SJose.Borrego@Sun.COM srvsvc_s_NetShareAdd(void *arg, ndr_xa_t *mxa)
19528474SJose.Borrego@Sun.COM {
19538474SJose.Borrego@Sun.COM 	static DWORD parm_err = 0;
19548474SJose.Borrego@Sun.COM 	DWORD parm_stat;
19558474SJose.Borrego@Sun.COM 	struct mslm_NetShareAdd *param = arg;
19569343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_2 *info2;
19579832Samw@Sun.COM 	struct mslm_NetShareInfo_502 *info502;
19588474SJose.Borrego@Sun.COM 	char realpath[MAXPATHLEN];
19598474SJose.Borrego@Sun.COM 	int32_t native_os;
19609832Samw@Sun.COM 	uint8_t *sdbuf = NULL;
19619832Samw@Sun.COM 	uint32_t status;
19629832Samw@Sun.COM 	smb_share_t si;
19638474SJose.Borrego@Sun.COM 
19648474SJose.Borrego@Sun.COM 	native_os = ndr_native_os(mxa);
19658474SJose.Borrego@Sun.COM 
19668474SJose.Borrego@Sun.COM 	if (!ndr_is_poweruser(mxa)) {
19678474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareAdd));
19688474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
19698474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
19708474SJose.Borrego@Sun.COM 	}
19718474SJose.Borrego@Sun.COM 
19728474SJose.Borrego@Sun.COM 	switch (param->level) {
19738474SJose.Borrego@Sun.COM 	case 2:
19749832Samw@Sun.COM 		info2 = (struct mslm_NetShareInfo_2 *)param->info.un.info2;
19758474SJose.Borrego@Sun.COM 		break;
19768474SJose.Borrego@Sun.COM 
19778474SJose.Borrego@Sun.COM 	case 502:
19789832Samw@Sun.COM 		info502 = (struct mslm_NetShareInfo_502 *)
19799832Samw@Sun.COM 		    param->info.un.info502;
19809832Samw@Sun.COM 		sdbuf = info502->shi502_security_descriptor;
19819832Samw@Sun.COM 		info2 = (struct mslm_NetShareInfo_2 *)info502;
19828474SJose.Borrego@Sun.COM 		break;
19838474SJose.Borrego@Sun.COM 
19848474SJose.Borrego@Sun.COM 	default:
19858474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareAdd));
19868474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
19878474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
19888474SJose.Borrego@Sun.COM 	}
19898474SJose.Borrego@Sun.COM 
19908474SJose.Borrego@Sun.COM 	if (info2->shi2_netname == NULL || info2->shi2_path == NULL) {
19918474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareAdd));
19928474SJose.Borrego@Sun.COM 		param->status = NERR_NetNameNotFound;
19938474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
19948474SJose.Borrego@Sun.COM 	}
19958474SJose.Borrego@Sun.COM 
19968474SJose.Borrego@Sun.COM 	if (smb_shr_is_restricted((char *)info2->shi2_netname)) {
19978474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareAdd));
19988474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
19998474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
20008474SJose.Borrego@Sun.COM 	}
20018474SJose.Borrego@Sun.COM 
20029343SAfshin.Ardakani@Sun.COM 	if (info2->shi2_comment == NULL)
20039343SAfshin.Ardakani@Sun.COM 		info2->shi2_comment = (uint8_t *)"";
20048474SJose.Borrego@Sun.COM 
20058474SJose.Borrego@Sun.COM 	/*
20068474SJose.Borrego@Sun.COM 	 * Derive the real path which will be stored in the
20078474SJose.Borrego@Sun.COM 	 * directory field of the smb_share_t structure
20088474SJose.Borrego@Sun.COM 	 * from the path field in this RPC request.
20098474SJose.Borrego@Sun.COM 	 */
20108474SJose.Borrego@Sun.COM 	parm_stat = smb_shr_get_realpath((const char *)info2->shi2_path,
20118474SJose.Borrego@Sun.COM 	    realpath, MAXPATHLEN);
20128474SJose.Borrego@Sun.COM 
20138474SJose.Borrego@Sun.COM 	if (parm_stat != NERR_Success) {
20148474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareAdd));
20158474SJose.Borrego@Sun.COM 		param->status = parm_stat;
20168474SJose.Borrego@Sun.COM 		param->parm_err
20178474SJose.Borrego@Sun.COM 		    = (native_os == NATIVE_OS_WIN95) ? 0 : &parm_err;
20188474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
20198474SJose.Borrego@Sun.COM 	}
20208474SJose.Borrego@Sun.COM 
20218474SJose.Borrego@Sun.COM 	param->status = srvsvc_sa_add((char *)info2->shi2_netname, realpath,
20229343SAfshin.Ardakani@Sun.COM 	    (char *)info2->shi2_comment);
20238474SJose.Borrego@Sun.COM 	if (param->status == NERR_Success) {
20249832Samw@Sun.COM 		status = smb_shr_get((char *)info2->shi2_netname, &si);
20259832Samw@Sun.COM 
20269832Samw@Sun.COM 		if ((sdbuf != NULL) && (status == NERR_Success))
20279832Samw@Sun.COM 			(void) srvsvc_sd_set(&si, sdbuf);
20288474SJose.Borrego@Sun.COM 	}
20298474SJose.Borrego@Sun.COM 	param->parm_err = (native_os == NATIVE_OS_WIN95) ? 0 : &parm_err;
20308474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
20318474SJose.Borrego@Sun.COM }
20328474SJose.Borrego@Sun.COM 
20338474SJose.Borrego@Sun.COM /*
203410122SJordan.Brown@Sun.COM  * srvsvc_estimate_limit
20358474SJose.Borrego@Sun.COM  *
20368474SJose.Borrego@Sun.COM  * Estimate the number of objects that will fit in prefmaxlen.
203710122SJordan.Brown@Sun.COM  * nlimit is adjusted here.
20388474SJose.Borrego@Sun.COM  */
203910122SJordan.Brown@Sun.COM static void
204010122SJordan.Brown@Sun.COM srvsvc_estimate_limit(smb_svcenum_t *se, uint32_t obj_size)
20418474SJose.Borrego@Sun.COM {
20428474SJose.Borrego@Sun.COM 	DWORD max_cnt;
20438474SJose.Borrego@Sun.COM 
204410122SJordan.Brown@Sun.COM 	if (obj_size == 0) {
204510122SJordan.Brown@Sun.COM 		se->se_nlimit = 0;
204610122SJordan.Brown@Sun.COM 		return;
204710122SJordan.Brown@Sun.COM 	}
204810122SJordan.Brown@Sun.COM 
204910122SJordan.Brown@Sun.COM 	if ((max_cnt = (se->se_prefmaxlen / obj_size)) == 0) {
205010122SJordan.Brown@Sun.COM 		se->se_nlimit = 0;
205110122SJordan.Brown@Sun.COM 		return;
205210122SJordan.Brown@Sun.COM 	}
205310122SJordan.Brown@Sun.COM 
205410122SJordan.Brown@Sun.COM 	if (se->se_ntotal > max_cnt)
205510122SJordan.Brown@Sun.COM 		se->se_nlimit = max_cnt;
205610122SJordan.Brown@Sun.COM 	else
205710122SJordan.Brown@Sun.COM 		se->se_nlimit = se->se_ntotal;
20588474SJose.Borrego@Sun.COM }
20598474SJose.Borrego@Sun.COM 
20608474SJose.Borrego@Sun.COM /*
20618474SJose.Borrego@Sun.COM  * srvsvc_s_NetShareEnum
20628474SJose.Borrego@Sun.COM  *
20638474SJose.Borrego@Sun.COM  * Enumerate all shares (see also NetShareEnumSticky).
20648474SJose.Borrego@Sun.COM  *
20658474SJose.Borrego@Sun.COM  * Request for various levels of information about our shares.
20668474SJose.Borrego@Sun.COM  * Level 0: share names.
20678474SJose.Borrego@Sun.COM  * Level 1: share name, share type and comment field.
20688474SJose.Borrego@Sun.COM  * Level 2: everything that we know about the shares.
206910504SKeyur.Desai@Sun.COM  * Level 501: level 1 + flags.
20708474SJose.Borrego@Sun.COM  * Level 502: level 2 + security descriptor.
20718474SJose.Borrego@Sun.COM  */
20728474SJose.Borrego@Sun.COM static int
20738474SJose.Borrego@Sun.COM srvsvc_s_NetShareEnum(void *arg, ndr_xa_t *mxa)
20748474SJose.Borrego@Sun.COM {
20758474SJose.Borrego@Sun.COM 	struct mslm_NetShareEnum *param = arg;
207610122SJordan.Brown@Sun.COM 	srvsvc_infonres_t *infonres;
207710122SJordan.Brown@Sun.COM 	smb_svcenum_t se;
20788474SJose.Borrego@Sun.COM 	DWORD status;
20798474SJose.Borrego@Sun.COM 
208010122SJordan.Brown@Sun.COM 	infonres = NDR_NEW(mxa, srvsvc_infonres_t);
20818474SJose.Borrego@Sun.COM 	if (infonres == NULL) {
20828474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareEnum));
20838474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
20848474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
20858474SJose.Borrego@Sun.COM 	}
20868474SJose.Borrego@Sun.COM 
20878474SJose.Borrego@Sun.COM 	infonres->entriesread = 0;
20888474SJose.Borrego@Sun.COM 	infonres->entries = NULL;
20898474SJose.Borrego@Sun.COM 	param->result.level = param->level;
20908474SJose.Borrego@Sun.COM 	param->result.bufptr.p = infonres;
20918474SJose.Borrego@Sun.COM 
209210122SJordan.Brown@Sun.COM 	bzero(&se, sizeof (smb_svcenum_t));
209310122SJordan.Brown@Sun.COM 	se.se_type = SMB_SVCENUM_TYPE_SHARE;
20948474SJose.Borrego@Sun.COM 	se.se_level = param->level;
209510122SJordan.Brown@Sun.COM 	se.se_ntotal = smb_shr_count();
209610122SJordan.Brown@Sun.COM 	se.se_nlimit = se.se_ntotal;
20978474SJose.Borrego@Sun.COM 
20988474SJose.Borrego@Sun.COM 	if (param->prefmaxlen == SMB_SRVSVC_MAXPREFLEN ||
20998474SJose.Borrego@Sun.COM 	    param->prefmaxlen > SMB_SRVSVC_MAXBUFLEN)
21008474SJose.Borrego@Sun.COM 		se.se_prefmaxlen = SMB_SRVSVC_MAXBUFLEN;
21018474SJose.Borrego@Sun.COM 	else
21028474SJose.Borrego@Sun.COM 		se.se_prefmaxlen = param->prefmaxlen;
21038474SJose.Borrego@Sun.COM 
21048474SJose.Borrego@Sun.COM 	if (param->resume_handle) {
210510122SJordan.Brown@Sun.COM 		se.se_resume = *param->resume_handle;
210610122SJordan.Brown@Sun.COM 		se.se_nskip = se.se_resume;
210710122SJordan.Brown@Sun.COM 		*param->resume_handle = 0;
21088474SJose.Borrego@Sun.COM 	}
21098474SJose.Borrego@Sun.COM 
21108474SJose.Borrego@Sun.COM 	switch (param->level) {
21118474SJose.Borrego@Sun.COM 	case 0:
21128474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel0(mxa, infonres, &se, 0);
21138474SJose.Borrego@Sun.COM 		break;
21148474SJose.Borrego@Sun.COM 
21158474SJose.Borrego@Sun.COM 	case 1:
21168474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel1(mxa, infonres, &se, 0);
21178474SJose.Borrego@Sun.COM 		break;
21188474SJose.Borrego@Sun.COM 
21198474SJose.Borrego@Sun.COM 	case 2:
21208474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel2(mxa, infonres, &se, 0);
21218474SJose.Borrego@Sun.COM 		break;
21228474SJose.Borrego@Sun.COM 
21238474SJose.Borrego@Sun.COM 	case 501:
21248474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel501(mxa, infonres, &se, 0);
21258474SJose.Borrego@Sun.COM 		break;
21268474SJose.Borrego@Sun.COM 
21278474SJose.Borrego@Sun.COM 	case 502:
21288474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel502(mxa, infonres, &se, 0);
21298474SJose.Borrego@Sun.COM 		break;
21308474SJose.Borrego@Sun.COM 
21318474SJose.Borrego@Sun.COM 	default:
21329832Samw@Sun.COM 		status = ERROR_INVALID_LEVEL;
21338474SJose.Borrego@Sun.COM 		break;
21348474SJose.Borrego@Sun.COM 	}
21358474SJose.Borrego@Sun.COM 
21368474SJose.Borrego@Sun.COM 	if (status != 0) {
21378474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareEnum));
21388474SJose.Borrego@Sun.COM 		param->status = status;
21398474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
21408474SJose.Borrego@Sun.COM 	}
21418474SJose.Borrego@Sun.COM 
214210122SJordan.Brown@Sun.COM 	if (se.se_nlimit == 0) {
21438474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
21448474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
21458474SJose.Borrego@Sun.COM 	}
21468474SJose.Borrego@Sun.COM 
21478474SJose.Borrego@Sun.COM 	if (param->resume_handle &&
21488474SJose.Borrego@Sun.COM 	    param->prefmaxlen != SMB_SRVSVC_MAXPREFLEN) {
214910122SJordan.Brown@Sun.COM 		if (se.se_resume < se.se_ntotal) {
215010122SJordan.Brown@Sun.COM 			*param->resume_handle = se.se_resume;
21518474SJose.Borrego@Sun.COM 			status = ERROR_MORE_DATA;
21528474SJose.Borrego@Sun.COM 		}
21538474SJose.Borrego@Sun.COM 	}
21548474SJose.Borrego@Sun.COM 
215510122SJordan.Brown@Sun.COM 	param->totalentries = se.se_ntotal;
21568474SJose.Borrego@Sun.COM 	param->status = status;
21578474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
21588474SJose.Borrego@Sun.COM }
21598474SJose.Borrego@Sun.COM 
21608474SJose.Borrego@Sun.COM /*
21618474SJose.Borrego@Sun.COM  * srvsvc_s_NetShareEnumSticky
21628474SJose.Borrego@Sun.COM  *
21638474SJose.Borrego@Sun.COM  * Enumerate sticky shares: all shares except those marked STYPE_SPECIAL.
21648474SJose.Borrego@Sun.COM  * Except for excluding STYPE_SPECIAL shares, NetShareEnumSticky is the
21658474SJose.Borrego@Sun.COM  * same as NetShareEnum.
21668474SJose.Borrego@Sun.COM  *
21678474SJose.Borrego@Sun.COM  * Request for various levels of information about our shares.
21688474SJose.Borrego@Sun.COM  * Level 0: share names.
21698474SJose.Borrego@Sun.COM  * Level 1: share name, share type and comment field.
21708474SJose.Borrego@Sun.COM  * Level 2: everything that we know about the shares.
21718474SJose.Borrego@Sun.COM  * Level 501: not valid for this request.
21728474SJose.Borrego@Sun.COM  * Level 502: level 2 + security descriptor.
21738474SJose.Borrego@Sun.COM  *
21748474SJose.Borrego@Sun.COM  * We set n_skip to resume_handle, which is used to find the appropriate
21758474SJose.Borrego@Sun.COM  * place to resume.  The resume_handle is similar to the readdir cookie.
21768474SJose.Borrego@Sun.COM  */
21778474SJose.Borrego@Sun.COM static int
21788474SJose.Borrego@Sun.COM srvsvc_s_NetShareEnumSticky(void *arg, ndr_xa_t *mxa)
21798474SJose.Borrego@Sun.COM {
21808474SJose.Borrego@Sun.COM 	struct mslm_NetShareEnum *param = arg;
218110122SJordan.Brown@Sun.COM 	srvsvc_infonres_t *infonres;
218210122SJordan.Brown@Sun.COM 	smb_svcenum_t se;
21838474SJose.Borrego@Sun.COM 	DWORD status;
21848474SJose.Borrego@Sun.COM 
218510122SJordan.Brown@Sun.COM 	infonres = NDR_NEW(mxa, srvsvc_infonres_t);
21868474SJose.Borrego@Sun.COM 	if (infonres == NULL) {
21878474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareEnum));
21888474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
21898474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
21908474SJose.Borrego@Sun.COM 	}
21918474SJose.Borrego@Sun.COM 
21928474SJose.Borrego@Sun.COM 	infonres->entriesread = 0;
21938474SJose.Borrego@Sun.COM 	infonres->entries = NULL;
21948474SJose.Borrego@Sun.COM 	param->result.level = param->level;
21958474SJose.Borrego@Sun.COM 	param->result.bufptr.p = infonres;
21968474SJose.Borrego@Sun.COM 
219710122SJordan.Brown@Sun.COM 	bzero(&se, sizeof (smb_svcenum_t));
219810122SJordan.Brown@Sun.COM 	se.se_type = SMB_SVCENUM_TYPE_SHARE;
21998474SJose.Borrego@Sun.COM 	se.se_level = param->level;
220010122SJordan.Brown@Sun.COM 	se.se_ntotal = smb_shr_count();
220110122SJordan.Brown@Sun.COM 	se.se_nlimit = se.se_ntotal;
22028474SJose.Borrego@Sun.COM 
22038474SJose.Borrego@Sun.COM 	if (param->prefmaxlen == SMB_SRVSVC_MAXPREFLEN ||
22048474SJose.Borrego@Sun.COM 	    param->prefmaxlen > SMB_SRVSVC_MAXBUFLEN)
22058474SJose.Borrego@Sun.COM 		se.se_prefmaxlen = SMB_SRVSVC_MAXBUFLEN;
22068474SJose.Borrego@Sun.COM 	else
22078474SJose.Borrego@Sun.COM 		se.se_prefmaxlen = param->prefmaxlen;
22088474SJose.Borrego@Sun.COM 
22098474SJose.Borrego@Sun.COM 	if (param->resume_handle) {
221010122SJordan.Brown@Sun.COM 		se.se_resume = *param->resume_handle;
221110122SJordan.Brown@Sun.COM 		se.se_nskip = se.se_resume;
221210122SJordan.Brown@Sun.COM 		*param->resume_handle = 0;
22138474SJose.Borrego@Sun.COM 	}
22148474SJose.Borrego@Sun.COM 
22158474SJose.Borrego@Sun.COM 	switch (param->level) {
22168474SJose.Borrego@Sun.COM 	case 0:
22178474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel0(mxa, infonres, &se, 1);
22188474SJose.Borrego@Sun.COM 		break;
22198474SJose.Borrego@Sun.COM 
22208474SJose.Borrego@Sun.COM 	case 1:
22218474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel1(mxa, infonres, &se, 1);
22228474SJose.Borrego@Sun.COM 		break;
22238474SJose.Borrego@Sun.COM 
22248474SJose.Borrego@Sun.COM 	case 2:
22258474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel2(mxa, infonres, &se, 1);
22268474SJose.Borrego@Sun.COM 		break;
22278474SJose.Borrego@Sun.COM 
22288474SJose.Borrego@Sun.COM 	case 502:
22298474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel502(mxa, infonres, &se, 1);
22308474SJose.Borrego@Sun.COM 		break;
22318474SJose.Borrego@Sun.COM 
22329832Samw@Sun.COM 	case 501:
22338474SJose.Borrego@Sun.COM 	default:
22348474SJose.Borrego@Sun.COM 		status = ERROR_INVALID_LEVEL;
22358474SJose.Borrego@Sun.COM 		break;
22368474SJose.Borrego@Sun.COM 	}
22378474SJose.Borrego@Sun.COM 
22388474SJose.Borrego@Sun.COM 	if (status != ERROR_SUCCESS) {
22398474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareEnum));
22408474SJose.Borrego@Sun.COM 		param->status = status;
22418474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
22428474SJose.Borrego@Sun.COM 	}
22438474SJose.Borrego@Sun.COM 
224410122SJordan.Brown@Sun.COM 	if (se.se_nlimit == 0) {
22458474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
22468474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
22478474SJose.Borrego@Sun.COM 	}
22488474SJose.Borrego@Sun.COM 
22498474SJose.Borrego@Sun.COM 	if (param->resume_handle &&
22508474SJose.Borrego@Sun.COM 	    param->prefmaxlen != SMB_SRVSVC_MAXPREFLEN) {
225110122SJordan.Brown@Sun.COM 		if (se.se_resume < se.se_ntotal) {
225210122SJordan.Brown@Sun.COM 			*param->resume_handle = se.se_resume;
22538474SJose.Borrego@Sun.COM 			status = ERROR_MORE_DATA;
22548474SJose.Borrego@Sun.COM 		}
22558474SJose.Borrego@Sun.COM 	}
22568474SJose.Borrego@Sun.COM 
225710122SJordan.Brown@Sun.COM 	param->totalentries = se.se_ntotal;
22588474SJose.Borrego@Sun.COM 	param->status = status;
22598474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
22608474SJose.Borrego@Sun.COM }
22618474SJose.Borrego@Sun.COM 
22628474SJose.Borrego@Sun.COM /*
22638474SJose.Borrego@Sun.COM  * NetShareEnum Level 0
22648474SJose.Borrego@Sun.COM  */
22658474SJose.Borrego@Sun.COM static DWORD
226610122SJordan.Brown@Sun.COM mlsvc_NetShareEnumLevel0(ndr_xa_t *mxa, srvsvc_infonres_t *infonres,
226710122SJordan.Brown@Sun.COM     smb_svcenum_t *se, int sticky)
22688474SJose.Borrego@Sun.COM {
22699343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_0 *info0;
22708474SJose.Borrego@Sun.COM 	smb_shriter_t iterator;
22718474SJose.Borrego@Sun.COM 	smb_share_t *si;
22728474SJose.Borrego@Sun.COM 	DWORD status;
22738474SJose.Borrego@Sun.COM 
227410122SJordan.Brown@Sun.COM 	srvsvc_estimate_limit(se,
227510122SJordan.Brown@Sun.COM 	    sizeof (struct mslm_NetShareInfo_0) + MAXNAMELEN);
227610122SJordan.Brown@Sun.COM 	if (se->se_nlimit == 0)
22778474SJose.Borrego@Sun.COM 		return (ERROR_SUCCESS);
22788474SJose.Borrego@Sun.COM 
227910122SJordan.Brown@Sun.COM 	info0 = NDR_NEWN(mxa, struct mslm_NetShareInfo_0, se->se_nlimit);
22808474SJose.Borrego@Sun.COM 	if (info0 == NULL)
22818474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
22828474SJose.Borrego@Sun.COM 
22838474SJose.Borrego@Sun.COM 	smb_shr_iterinit(&iterator);
22848474SJose.Borrego@Sun.COM 
228510122SJordan.Brown@Sun.COM 	se->se_nitems = 0;
22868474SJose.Borrego@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != NULL) {
228710122SJordan.Brown@Sun.COM 		if (se->se_nskip > 0) {
228810122SJordan.Brown@Sun.COM 			--se->se_nskip;
22898474SJose.Borrego@Sun.COM 			continue;
22908474SJose.Borrego@Sun.COM 		}
22918474SJose.Borrego@Sun.COM 
229210122SJordan.Brown@Sun.COM 		++se->se_resume;
22938474SJose.Borrego@Sun.COM 
22948474SJose.Borrego@Sun.COM 		if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
22958474SJose.Borrego@Sun.COM 			continue;
22968474SJose.Borrego@Sun.COM 
22978474SJose.Borrego@Sun.COM 		if (si->shr_flags & SMB_SHRF_AUTOHOME)
22988474SJose.Borrego@Sun.COM 			continue;
22998474SJose.Borrego@Sun.COM 
230010122SJordan.Brown@Sun.COM 		if (se->se_nitems >= se->se_nlimit) {
230110122SJordan.Brown@Sun.COM 			se->se_nitems = se->se_nlimit;
23028474SJose.Borrego@Sun.COM 			break;
23038474SJose.Borrego@Sun.COM 		}
23048474SJose.Borrego@Sun.COM 
23058474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info0);
23068474SJose.Borrego@Sun.COM 		if (status != ERROR_SUCCESS)
23078474SJose.Borrego@Sun.COM 			break;
23088474SJose.Borrego@Sun.COM 
230910122SJordan.Brown@Sun.COM 		++se->se_nitems;
23108474SJose.Borrego@Sun.COM 	}
23118474SJose.Borrego@Sun.COM 
231210122SJordan.Brown@Sun.COM 	if (se->se_nitems < se->se_nlimit) {
23138474SJose.Borrego@Sun.COM 		if (srvsvc_add_autohome(mxa, se, (void *)info0))
231410122SJordan.Brown@Sun.COM 			++se->se_nitems;
23158474SJose.Borrego@Sun.COM 	}
23168474SJose.Borrego@Sun.COM 
231710122SJordan.Brown@Sun.COM 	infonres->entriesread = se->se_nitems;
23188474SJose.Borrego@Sun.COM 	infonres->entries = info0;
23198474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
23208474SJose.Borrego@Sun.COM }
23218474SJose.Borrego@Sun.COM 
23228474SJose.Borrego@Sun.COM /*
23238474SJose.Borrego@Sun.COM  * NetShareEnum Level 1
23248474SJose.Borrego@Sun.COM  */
23258474SJose.Borrego@Sun.COM static DWORD
232610122SJordan.Brown@Sun.COM mlsvc_NetShareEnumLevel1(ndr_xa_t *mxa, srvsvc_infonres_t *infonres,
232710122SJordan.Brown@Sun.COM     smb_svcenum_t *se, int sticky)
23288474SJose.Borrego@Sun.COM {
23299343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_1 *info1;
23308474SJose.Borrego@Sun.COM 	smb_shriter_t iterator;
23318474SJose.Borrego@Sun.COM 	smb_share_t *si;
23328474SJose.Borrego@Sun.COM 	DWORD status;
23338474SJose.Borrego@Sun.COM 
233410122SJordan.Brown@Sun.COM 	srvsvc_estimate_limit(se,
233510122SJordan.Brown@Sun.COM 	    sizeof (struct mslm_NetShareInfo_1) + MAXNAMELEN);
233610122SJordan.Brown@Sun.COM 	if (se->se_nlimit == 0)
23378474SJose.Borrego@Sun.COM 		return (ERROR_SUCCESS);
23388474SJose.Borrego@Sun.COM 
233910122SJordan.Brown@Sun.COM 	info1 = NDR_NEWN(mxa, struct mslm_NetShareInfo_1, se->se_nlimit);
23408474SJose.Borrego@Sun.COM 	if (info1 == NULL)
23418474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
23428474SJose.Borrego@Sun.COM 
23438474SJose.Borrego@Sun.COM 	smb_shr_iterinit(&iterator);
23448474SJose.Borrego@Sun.COM 
234510122SJordan.Brown@Sun.COM 	se->se_nitems = 0;
23468474SJose.Borrego@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != 0) {
234710122SJordan.Brown@Sun.COM 		if (se->se_nskip > 0) {
234810122SJordan.Brown@Sun.COM 			--se->se_nskip;
23498474SJose.Borrego@Sun.COM 			continue;
23508474SJose.Borrego@Sun.COM 		}
23518474SJose.Borrego@Sun.COM 
235210122SJordan.Brown@Sun.COM 		++se->se_resume;
23538474SJose.Borrego@Sun.COM 
23548474SJose.Borrego@Sun.COM 		if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
23558474SJose.Borrego@Sun.COM 			continue;
23568474SJose.Borrego@Sun.COM 
23578474SJose.Borrego@Sun.COM 		if (si->shr_flags & SMB_SHRF_AUTOHOME)
23588474SJose.Borrego@Sun.COM 			continue;
23598474SJose.Borrego@Sun.COM 
236010122SJordan.Brown@Sun.COM 		if (se->se_nitems >= se->se_nlimit) {
236110122SJordan.Brown@Sun.COM 			se->se_nitems = se->se_nlimit;
23628474SJose.Borrego@Sun.COM 			break;
23638474SJose.Borrego@Sun.COM 		}
23648474SJose.Borrego@Sun.COM 
23658474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info1);
23668474SJose.Borrego@Sun.COM 		if (status != ERROR_SUCCESS)
23678474SJose.Borrego@Sun.COM 			break;
23688474SJose.Borrego@Sun.COM 
236910122SJordan.Brown@Sun.COM 		++se->se_nitems;
23708474SJose.Borrego@Sun.COM 	}
23718474SJose.Borrego@Sun.COM 
237210122SJordan.Brown@Sun.COM 	if (se->se_nitems < se->se_nlimit) {
23738474SJose.Borrego@Sun.COM 		if (srvsvc_add_autohome(mxa, se, (void *)info1))
237410122SJordan.Brown@Sun.COM 			++se->se_nitems;
23758474SJose.Borrego@Sun.COM 	}
23768474SJose.Borrego@Sun.COM 
237710122SJordan.Brown@Sun.COM 	infonres->entriesread = se->se_nitems;
23788474SJose.Borrego@Sun.COM 	infonres->entries = info1;
23798474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
23808474SJose.Borrego@Sun.COM }
23818474SJose.Borrego@Sun.COM 
23828474SJose.Borrego@Sun.COM /*
23838474SJose.Borrego@Sun.COM  * NetShareEnum Level 2
23848474SJose.Borrego@Sun.COM  */
23858474SJose.Borrego@Sun.COM static DWORD
238610122SJordan.Brown@Sun.COM mlsvc_NetShareEnumLevel2(ndr_xa_t *mxa, srvsvc_infonres_t *infonres,
238710122SJordan.Brown@Sun.COM     smb_svcenum_t *se, int sticky)
23888474SJose.Borrego@Sun.COM {
23899343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_2 *info2;
23908474SJose.Borrego@Sun.COM 	smb_shriter_t iterator;
23918474SJose.Borrego@Sun.COM 	smb_share_t *si;
23928474SJose.Borrego@Sun.COM 	DWORD status;
23938474SJose.Borrego@Sun.COM 
239410122SJordan.Brown@Sun.COM 	srvsvc_estimate_limit(se,
239510122SJordan.Brown@Sun.COM 	    sizeof (struct mslm_NetShareInfo_2) + MAXNAMELEN);
239610122SJordan.Brown@Sun.COM 	if (se->se_nlimit == 0)
23978474SJose.Borrego@Sun.COM 		return (ERROR_SUCCESS);
23988474SJose.Borrego@Sun.COM 
239910122SJordan.Brown@Sun.COM 	info2 = NDR_NEWN(mxa, struct mslm_NetShareInfo_2, se->se_nlimit);
24008474SJose.Borrego@Sun.COM 	if (info2 == NULL)
24018474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
24028474SJose.Borrego@Sun.COM 
24038474SJose.Borrego@Sun.COM 	smb_shr_iterinit(&iterator);
24048474SJose.Borrego@Sun.COM 
240510122SJordan.Brown@Sun.COM 	se->se_nitems = 0;
24068474SJose.Borrego@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != 0) {
240710122SJordan.Brown@Sun.COM 		if (se->se_nskip > 0) {
240810122SJordan.Brown@Sun.COM 			--se->se_nskip;
24098474SJose.Borrego@Sun.COM 			continue;
24108474SJose.Borrego@Sun.COM 		}
24118474SJose.Borrego@Sun.COM 
241210122SJordan.Brown@Sun.COM 		++se->se_resume;
24138474SJose.Borrego@Sun.COM 
24148474SJose.Borrego@Sun.COM 		if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
24158474SJose.Borrego@Sun.COM 			continue;
24168474SJose.Borrego@Sun.COM 
24178474SJose.Borrego@Sun.COM 		if (si->shr_flags & SMB_SHRF_AUTOHOME)
24188474SJose.Borrego@Sun.COM 			continue;
24198474SJose.Borrego@Sun.COM 
242010122SJordan.Brown@Sun.COM 		if (se->se_nitems >= se->se_nlimit) {
242110122SJordan.Brown@Sun.COM 			se->se_nitems = se->se_nlimit;
24228474SJose.Borrego@Sun.COM 			break;
24238474SJose.Borrego@Sun.COM 		}
24248474SJose.Borrego@Sun.COM 
24258474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info2);
24268474SJose.Borrego@Sun.COM 		if (status != ERROR_SUCCESS)
24278474SJose.Borrego@Sun.COM 			break;
24288474SJose.Borrego@Sun.COM 
242910122SJordan.Brown@Sun.COM 		++se->se_nitems;
24308474SJose.Borrego@Sun.COM 	}
24318474SJose.Borrego@Sun.COM 
243210122SJordan.Brown@Sun.COM 	if (se->se_nitems < se->se_nlimit) {
24338474SJose.Borrego@Sun.COM 		if (srvsvc_add_autohome(mxa, se, (void *)info2))
243410122SJordan.Brown@Sun.COM 			++se->se_nitems;
24358474SJose.Borrego@Sun.COM 	}
24368474SJose.Borrego@Sun.COM 
243710122SJordan.Brown@Sun.COM 	infonres->entriesread = se->se_nitems;
24388474SJose.Borrego@Sun.COM 	infonres->entries = info2;
24398474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
24408474SJose.Borrego@Sun.COM }
24418474SJose.Borrego@Sun.COM 
24428474SJose.Borrego@Sun.COM /*
24438474SJose.Borrego@Sun.COM  * NetShareEnum Level 501
24448474SJose.Borrego@Sun.COM  */
24458474SJose.Borrego@Sun.COM static DWORD
244610122SJordan.Brown@Sun.COM mlsvc_NetShareEnumLevel501(ndr_xa_t *mxa, srvsvc_infonres_t *infonres,
244710122SJordan.Brown@Sun.COM     smb_svcenum_t *se, int sticky)
24488474SJose.Borrego@Sun.COM {
24499343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_501 *info501;
24508474SJose.Borrego@Sun.COM 	smb_shriter_t iterator;
24518474SJose.Borrego@Sun.COM 	smb_share_t *si;
24528474SJose.Borrego@Sun.COM 	DWORD status;
24538474SJose.Borrego@Sun.COM 
245410122SJordan.Brown@Sun.COM 	srvsvc_estimate_limit(se,
245510122SJordan.Brown@Sun.COM 	    sizeof (struct mslm_NetShareInfo_501) + MAXNAMELEN);
245610122SJordan.Brown@Sun.COM 	if (se->se_nlimit == 0)
24578474SJose.Borrego@Sun.COM 		return (ERROR_SUCCESS);
24588474SJose.Borrego@Sun.COM 
24599343SAfshin.Ardakani@Sun.COM 	info501 = NDR_NEWN(mxa, struct mslm_NetShareInfo_501,
246010122SJordan.Brown@Sun.COM 	    se->se_nlimit);
24618474SJose.Borrego@Sun.COM 	if (info501 == NULL)
24628474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
24638474SJose.Borrego@Sun.COM 
24648474SJose.Borrego@Sun.COM 	smb_shr_iterinit(&iterator);
24658474SJose.Borrego@Sun.COM 
246610122SJordan.Brown@Sun.COM 	se->se_nitems = 0;
24678474SJose.Borrego@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != 0) {
246810122SJordan.Brown@Sun.COM 		if (se->se_nskip > 0) {
246910122SJordan.Brown@Sun.COM 			--se->se_nskip;
24708474SJose.Borrego@Sun.COM 			continue;
24718474SJose.Borrego@Sun.COM 		}
24728474SJose.Borrego@Sun.COM 
247310122SJordan.Brown@Sun.COM 		++se->se_resume;
24748474SJose.Borrego@Sun.COM 
24758474SJose.Borrego@Sun.COM 		if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
24768474SJose.Borrego@Sun.COM 			continue;
24778474SJose.Borrego@Sun.COM 
24788474SJose.Borrego@Sun.COM 		if (si->shr_flags & SMB_SHRF_AUTOHOME)
24798474SJose.Borrego@Sun.COM 			continue;
24808474SJose.Borrego@Sun.COM 
248110122SJordan.Brown@Sun.COM 		if (se->se_nitems >= se->se_nlimit) {
248210122SJordan.Brown@Sun.COM 			se->se_nitems = se->se_nlimit;
24838474SJose.Borrego@Sun.COM 			break;
24848474SJose.Borrego@Sun.COM 		}
24858474SJose.Borrego@Sun.COM 
24868474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info501);
24878474SJose.Borrego@Sun.COM 		if (status != ERROR_SUCCESS)
24888474SJose.Borrego@Sun.COM 			break;
24898474SJose.Borrego@Sun.COM 
249010122SJordan.Brown@Sun.COM 		++se->se_nitems;
24918474SJose.Borrego@Sun.COM 	}
24928474SJose.Borrego@Sun.COM 
249310122SJordan.Brown@Sun.COM 	if (se->se_nitems < se->se_nlimit) {
24948474SJose.Borrego@Sun.COM 		if (srvsvc_add_autohome(mxa, se, (void *)info501))
249510122SJordan.Brown@Sun.COM 			++se->se_nitems;
24968474SJose.Borrego@Sun.COM 	}
24978474SJose.Borrego@Sun.COM 
249810122SJordan.Brown@Sun.COM 	infonres->entriesread = se->se_nitems;
24998474SJose.Borrego@Sun.COM 	infonres->entries = info501;
25008474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
25018474SJose.Borrego@Sun.COM }
25028474SJose.Borrego@Sun.COM 
25038474SJose.Borrego@Sun.COM /*
25048474SJose.Borrego@Sun.COM  * NetShareEnum Level 502
25058474SJose.Borrego@Sun.COM  */
25068474SJose.Borrego@Sun.COM static DWORD
250710122SJordan.Brown@Sun.COM mlsvc_NetShareEnumLevel502(ndr_xa_t *mxa, srvsvc_infonres_t *infonres,
250810122SJordan.Brown@Sun.COM     smb_svcenum_t *se, int sticky)
25098474SJose.Borrego@Sun.COM {
25109343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_502 *info502;
25118474SJose.Borrego@Sun.COM 	smb_shriter_t iterator;
25128474SJose.Borrego@Sun.COM 	smb_share_t *si;
25138474SJose.Borrego@Sun.COM 	DWORD status;
25148474SJose.Borrego@Sun.COM 
251510122SJordan.Brown@Sun.COM 	srvsvc_estimate_limit(se,
251610122SJordan.Brown@Sun.COM 	    sizeof (struct mslm_NetShareInfo_502) + MAXNAMELEN);
251710122SJordan.Brown@Sun.COM 	if (se->se_nlimit == 0)
25188474SJose.Borrego@Sun.COM 		return (ERROR_SUCCESS);
25198474SJose.Borrego@Sun.COM 
25209343SAfshin.Ardakani@Sun.COM 	info502 = NDR_NEWN(mxa, struct mslm_NetShareInfo_502,
252110122SJordan.Brown@Sun.COM 	    se->se_nlimit);
25228474SJose.Borrego@Sun.COM 	if (info502 == NULL)
25238474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
25248474SJose.Borrego@Sun.COM 
25258474SJose.Borrego@Sun.COM 	smb_shr_iterinit(&iterator);
25268474SJose.Borrego@Sun.COM 
252710122SJordan.Brown@Sun.COM 	se->se_nitems = 0;
25288474SJose.Borrego@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != NULL) {
252910122SJordan.Brown@Sun.COM 		if (se->se_nskip > 0) {
253010122SJordan.Brown@Sun.COM 			--se->se_nskip;
25318474SJose.Borrego@Sun.COM 			continue;
25328474SJose.Borrego@Sun.COM 		}
25338474SJose.Borrego@Sun.COM 
253410122SJordan.Brown@Sun.COM 		++se->se_resume;
25358474SJose.Borrego@Sun.COM 
25368474SJose.Borrego@Sun.COM 		if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
25378474SJose.Borrego@Sun.COM 			continue;
25388474SJose.Borrego@Sun.COM 
25398474SJose.Borrego@Sun.COM 		if (si->shr_flags & SMB_SHRF_AUTOHOME)
25408474SJose.Borrego@Sun.COM 			continue;
25418474SJose.Borrego@Sun.COM 
254210122SJordan.Brown@Sun.COM 		if (se->se_nitems >= se->se_nlimit) {
254310122SJordan.Brown@Sun.COM 			se->se_nitems = se->se_nlimit;
25448474SJose.Borrego@Sun.COM 			break;
25458474SJose.Borrego@Sun.COM 		}
25468474SJose.Borrego@Sun.COM 
25478474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info502);
25488474SJose.Borrego@Sun.COM 		if (status != ERROR_SUCCESS)
25498474SJose.Borrego@Sun.COM 			break;
25508474SJose.Borrego@Sun.COM 
255110122SJordan.Brown@Sun.COM 		++se->se_nitems;
25528474SJose.Borrego@Sun.COM 	}
25538474SJose.Borrego@Sun.COM 
255410122SJordan.Brown@Sun.COM 	if (se->se_nitems < se->se_nlimit) {
25558474SJose.Borrego@Sun.COM 		if (srvsvc_add_autohome(mxa, se, (void *)info502))
255610122SJordan.Brown@Sun.COM 			++se->se_nitems;
25578474SJose.Borrego@Sun.COM 	}
25588474SJose.Borrego@Sun.COM 
255910122SJordan.Brown@Sun.COM 	infonres->entriesread = se->se_nitems;
25608474SJose.Borrego@Sun.COM 	infonres->entries = info502;
25618474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
25628474SJose.Borrego@Sun.COM }
25638474SJose.Borrego@Sun.COM 
25648474SJose.Borrego@Sun.COM /*
25658474SJose.Borrego@Sun.COM  * mlsvc_NetShareEnumCommon
25668474SJose.Borrego@Sun.COM  *
25678474SJose.Borrego@Sun.COM  * Build the levels 0, 1, 2, 501 and 502 share information. This function
25688474SJose.Borrego@Sun.COM  * is called by the various NetShareEnum levels for each share. If
25698474SJose.Borrego@Sun.COM  * we cannot build the share data for some reason, we return an error
25708474SJose.Borrego@Sun.COM  * but the actual value of the error is not important to the caller.
25718474SJose.Borrego@Sun.COM  * The caller just needs to know not to include this info in the RPC
25728474SJose.Borrego@Sun.COM  * response.
25738474SJose.Borrego@Sun.COM  *
25748474SJose.Borrego@Sun.COM  * Returns:
25758474SJose.Borrego@Sun.COM  *	ERROR_SUCCESS
25768474SJose.Borrego@Sun.COM  *	ERROR_NOT_ENOUGH_MEMORY
25778474SJose.Borrego@Sun.COM  *	ERROR_INVALID_LEVEL
25788474SJose.Borrego@Sun.COM  */
25798474SJose.Borrego@Sun.COM static DWORD
258010122SJordan.Brown@Sun.COM mlsvc_NetShareEnumCommon(ndr_xa_t *mxa, smb_svcenum_t *se,
25818474SJose.Borrego@Sun.COM     smb_share_t *si, void *infop)
25828474SJose.Borrego@Sun.COM {
25839343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_0 *info0;
25849343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_1 *info1;
25859343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_2 *info2;
25869343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_501 *info501;
25879343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_502 *info502;
25889832Samw@Sun.COM 	srvsvc_sd_t sd;
25899832Samw@Sun.COM 	uint8_t *netname;
25909832Samw@Sun.COM 	uint8_t *comment;
25919832Samw@Sun.COM 	uint8_t *passwd;
25929832Samw@Sun.COM 	uint8_t *path;
259310122SJordan.Brown@Sun.COM 	int i = se->se_nitems;
25948474SJose.Borrego@Sun.COM 
25959832Samw@Sun.COM 	netname = (uint8_t *)NDR_STRDUP(mxa, si->shr_name);
25969832Samw@Sun.COM 	comment = (uint8_t *)NDR_STRDUP(mxa, si->shr_cmnt);
25979832Samw@Sun.COM 	passwd = (uint8_t *)NDR_STRDUP(mxa, empty_string);
25989832Samw@Sun.COM 	path = (uint8_t *)srvsvc_share_mkpath(mxa, si->shr_path);
25999832Samw@Sun.COM 
26009832Samw@Sun.COM 	if (!netname || !comment || !passwd || !path)
26019832Samw@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
26029832Samw@Sun.COM 
26038474SJose.Borrego@Sun.COM 	switch (se->se_level) {
26048474SJose.Borrego@Sun.COM 	case 0:
26059343SAfshin.Ardakani@Sun.COM 		info0 = (struct mslm_NetShareInfo_0 *)infop;
26069832Samw@Sun.COM 		info0[i].shi0_netname = netname;
26078474SJose.Borrego@Sun.COM 		break;
26088474SJose.Borrego@Sun.COM 
26098474SJose.Borrego@Sun.COM 	case 1:
26109343SAfshin.Ardakani@Sun.COM 		info1 = (struct mslm_NetShareInfo_1 *)infop;
26119832Samw@Sun.COM 		info1[i].shi1_netname = netname;
26129832Samw@Sun.COM 		info1[i].shi1_comment = comment;
26138474SJose.Borrego@Sun.COM 		info1[i].shi1_type = si->shr_type;
26148474SJose.Borrego@Sun.COM 		break;
26158474SJose.Borrego@Sun.COM 
26168474SJose.Borrego@Sun.COM 	case 2:
26179343SAfshin.Ardakani@Sun.COM 		info2 = (struct mslm_NetShareInfo_2 *)infop;
26189832Samw@Sun.COM 		info2[i].shi2_netname = netname;
26199832Samw@Sun.COM 		info2[i].shi2_comment = comment;
26209832Samw@Sun.COM 		info2[i].shi2_path = path;
26218474SJose.Borrego@Sun.COM 		info2[i].shi2_type = si->shr_type;
26228474SJose.Borrego@Sun.COM 		info2[i].shi2_permissions = 0;
26238474SJose.Borrego@Sun.COM 		info2[i].shi2_max_uses = SHI_USES_UNLIMITED;
26248474SJose.Borrego@Sun.COM 		info2[i].shi2_current_uses = 0;
26259832Samw@Sun.COM 		info2[i].shi2_passwd = passwd;
26268474SJose.Borrego@Sun.COM 		break;
26278474SJose.Borrego@Sun.COM 
26288474SJose.Borrego@Sun.COM 	case 501:
26299343SAfshin.Ardakani@Sun.COM 		info501 = (struct mslm_NetShareInfo_501 *)infop;
26309832Samw@Sun.COM 		info501[i].shi501_netname = netname;
26319832Samw@Sun.COM 		info501[i].shi501_comment = comment;
26328474SJose.Borrego@Sun.COM 		info501[i].shi501_type = si->shr_type;
263310504SKeyur.Desai@Sun.COM 		info501[i].shi501_flags = srvsvc_get_share_flags(si);
26348474SJose.Borrego@Sun.COM 		break;
26358474SJose.Borrego@Sun.COM 
26368474SJose.Borrego@Sun.COM 	case 502:
26379343SAfshin.Ardakani@Sun.COM 		info502 = (struct mslm_NetShareInfo_502 *)infop;
26389832Samw@Sun.COM 		info502[i].shi502_netname = netname;
26399832Samw@Sun.COM 		info502[i].shi502_comment = comment;
26409832Samw@Sun.COM 		info502[i].shi502_path = path;
26418474SJose.Borrego@Sun.COM 		info502[i].shi502_type = si->shr_type;
26428474SJose.Borrego@Sun.COM 		info502[i].shi502_permissions = 0;
26438474SJose.Borrego@Sun.COM 		info502[i].shi502_max_uses = SHI_USES_UNLIMITED;
26448474SJose.Borrego@Sun.COM 		info502[i].shi502_current_uses = 0;
26459832Samw@Sun.COM 		info502[i].shi502_passwd = passwd;
26469832Samw@Sun.COM 
26479832Samw@Sun.COM 		if (srvsvc_share_getsd(mxa, si, &sd) == ERROR_SUCCESS) {
26489832Samw@Sun.COM 			info502[i].shi502_reserved = sd.sd_size;
26499832Samw@Sun.COM 			info502[i].shi502_security_descriptor = sd.sd_buf;
26509832Samw@Sun.COM 		} else {
26519832Samw@Sun.COM 			info502[i].shi502_reserved = 0;
26529832Samw@Sun.COM 			info502[i].shi502_security_descriptor = NULL;
26539832Samw@Sun.COM 		}
26549832Samw@Sun.COM 
26558474SJose.Borrego@Sun.COM 		break;
26568474SJose.Borrego@Sun.COM 
26578474SJose.Borrego@Sun.COM 	default:
26588474SJose.Borrego@Sun.COM 		return (ERROR_INVALID_LEVEL);
26598474SJose.Borrego@Sun.COM 	}
26608474SJose.Borrego@Sun.COM 
26618474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
26628474SJose.Borrego@Sun.COM }
26638474SJose.Borrego@Sun.COM 
26648474SJose.Borrego@Sun.COM /*
26658474SJose.Borrego@Sun.COM  * srvsvc_add_autohome
26668474SJose.Borrego@Sun.COM  *
26678474SJose.Borrego@Sun.COM  * Add the autohome share for the user. The share must not be a permanent
26688474SJose.Borrego@Sun.COM  * share to avoid duplicates.
26698474SJose.Borrego@Sun.COM  */
26708474SJose.Borrego@Sun.COM static boolean_t
267110122SJordan.Brown@Sun.COM srvsvc_add_autohome(ndr_xa_t *mxa, smb_svcenum_t *se, void *infop)
26728474SJose.Borrego@Sun.COM {
267310122SJordan.Brown@Sun.COM 	smb_netuserinfo_t *user = &mxa->pipe->np_user;
2674*12065SKeyur.Desai@Sun.COM 	char *username;
26758474SJose.Borrego@Sun.COM 	smb_share_t si;
26768474SJose.Borrego@Sun.COM 	DWORD status;
2677*12065SKeyur.Desai@Sun.COM 	struct passwd pw;
2678*12065SKeyur.Desai@Sun.COM 	char buf[NSS_LINELEN_PASSWD];
2679*12065SKeyur.Desai@Sun.COM 
2680*12065SKeyur.Desai@Sun.COM 	if (IDMAP_ID_IS_EPHEMERAL(user->ui_posix_uid)) {
2681*12065SKeyur.Desai@Sun.COM 		username = user->ui_account;
2682*12065SKeyur.Desai@Sun.COM 	} else {
2683*12065SKeyur.Desai@Sun.COM 		if (getpwuid_r(user->ui_posix_uid, &pw, buf, sizeof (buf)) ==
2684*12065SKeyur.Desai@Sun.COM 		    NULL)
2685*12065SKeyur.Desai@Sun.COM 			return (B_FALSE);
2686*12065SKeyur.Desai@Sun.COM 
2687*12065SKeyur.Desai@Sun.COM 		username = pw.pw_name;
2688*12065SKeyur.Desai@Sun.COM 	}
26898474SJose.Borrego@Sun.COM 
26908474SJose.Borrego@Sun.COM 	if (smb_shr_get(username, &si) != NERR_Success)
26918474SJose.Borrego@Sun.COM 		return (B_FALSE);
26928474SJose.Borrego@Sun.COM 
26938474SJose.Borrego@Sun.COM 	if ((si.shr_flags & SMB_SHRF_AUTOHOME) == 0)
26948474SJose.Borrego@Sun.COM 		return (B_FALSE);
26958474SJose.Borrego@Sun.COM 
26968474SJose.Borrego@Sun.COM 	status = mlsvc_NetShareEnumCommon(mxa, se, &si, infop);
26978474SJose.Borrego@Sun.COM 	return (status == ERROR_SUCCESS);
26988474SJose.Borrego@Sun.COM }
26998474SJose.Borrego@Sun.COM 
27008474SJose.Borrego@Sun.COM /*
27018474SJose.Borrego@Sun.COM  * srvsvc_share_mkpath
27028474SJose.Borrego@Sun.COM  *
27038474SJose.Borrego@Sun.COM  * Create the share path required by the share enum calls. The path
27048474SJose.Borrego@Sun.COM  * is created in a heap buffer ready for use by the caller.
27058474SJose.Borrego@Sun.COM  *
27068474SJose.Borrego@Sun.COM  * Some Windows over-the-wire backup applications do not work unless a
27078474SJose.Borrego@Sun.COM  * drive letter is present in the share path.  We don't care about the
27088474SJose.Borrego@Sun.COM  * drive letter since the path is fully qualified with the volume name.
27098474SJose.Borrego@Sun.COM  *
27108474SJose.Borrego@Sun.COM  * Windows clients seem to be mostly okay with forward slashes in
27118474SJose.Borrego@Sun.COM  * share paths but they cannot handle one immediately after the drive
27128474SJose.Borrego@Sun.COM  * letter, i.e. B:/.  For consistency we convert all the slashes in
27138474SJose.Borrego@Sun.COM  * the path.
27148474SJose.Borrego@Sun.COM  *
27158474SJose.Borrego@Sun.COM  * Returns a pointer to a heap buffer containing the share path, which
27168474SJose.Borrego@Sun.COM  * could be a null pointer if the heap allocation fails.
27178474SJose.Borrego@Sun.COM  */
27188474SJose.Borrego@Sun.COM static char *
27198474SJose.Borrego@Sun.COM srvsvc_share_mkpath(ndr_xa_t *mxa, char *path)
27208474SJose.Borrego@Sun.COM {
27218474SJose.Borrego@Sun.COM 	char tmpbuf[MAXPATHLEN];
27228474SJose.Borrego@Sun.COM 	char *p;
2723*12065SKeyur.Desai@Sun.COM 	char drive_letter;
27248474SJose.Borrego@Sun.COM 
27258474SJose.Borrego@Sun.COM 	if (strlen(path) == 0)
27268474SJose.Borrego@Sun.COM 		return (NDR_STRDUP(mxa, path));
27278474SJose.Borrego@Sun.COM 
2728*12065SKeyur.Desai@Sun.COM 	drive_letter = smb_shr_drive_letter(path);
2729*12065SKeyur.Desai@Sun.COM 	if (drive_letter != '\0') {
2730*12065SKeyur.Desai@Sun.COM 		(void) snprintf(tmpbuf, MAXPATHLEN, "%c:\\", drive_letter);
2731*12065SKeyur.Desai@Sun.COM 		return (NDR_STRDUP(mxa, tmpbuf));
2732*12065SKeyur.Desai@Sun.COM 	}
2733*12065SKeyur.Desai@Sun.COM 
27348474SJose.Borrego@Sun.COM 	/*
27358474SJose.Borrego@Sun.COM 	 * Strip the volume name from the path (/vol1/home -> /home).
27368474SJose.Borrego@Sun.COM 	 */
27378474SJose.Borrego@Sun.COM 	p = path;
27388474SJose.Borrego@Sun.COM 	p += strspn(p, "/");
27398474SJose.Borrego@Sun.COM 	p += strcspn(p, "/");
27408474SJose.Borrego@Sun.COM 	p += strspn(p, "/");
27418474SJose.Borrego@Sun.COM 	(void) snprintf(tmpbuf, MAXPATHLEN, "%c:/%s", 'B', p);
27428474SJose.Borrego@Sun.COM 	(void) strsubst(tmpbuf, '/', '\\');
27438474SJose.Borrego@Sun.COM 
27448474SJose.Borrego@Sun.COM 	return (NDR_STRDUP(mxa, tmpbuf));
27458474SJose.Borrego@Sun.COM }
27468474SJose.Borrego@Sun.COM 
27479832Samw@Sun.COM static int
27489832Samw@Sun.COM srvsvc_s_NetShareCheck(void *arg, ndr_xa_t *mxa)
27499832Samw@Sun.COM {
27509832Samw@Sun.COM 	struct mslm_NetShareCheck *param = arg;
27519832Samw@Sun.COM 	smb_shriter_t iterator;
27529832Samw@Sun.COM 	smb_share_t *si;
27539832Samw@Sun.COM 	char *path;
27549832Samw@Sun.COM 
27559832Samw@Sun.COM 	if (param->path == NULL) {
27569832Samw@Sun.COM 		param->stype = STYPE_DISKTREE;
27579832Samw@Sun.COM 		param->status = NERR_NetNameNotFound;
27589832Samw@Sun.COM 		return (NDR_DRC_OK);
27599832Samw@Sun.COM 	}
27609832Samw@Sun.COM 
27619832Samw@Sun.COM 	(void) strsubst((char *)param->path, '/', '\\');
27629832Samw@Sun.COM 
27639832Samw@Sun.COM 	smb_shr_iterinit(&iterator);
27649832Samw@Sun.COM 
27659832Samw@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != NULL) {
27669832Samw@Sun.COM 		path = srvsvc_share_mkpath(mxa, si->shr_path);
27679832Samw@Sun.COM 
276810966SJordan.Brown@Sun.COM 		if (smb_strcasecmp(path, (char *)param->path, 0) == 0) {
27699832Samw@Sun.COM 			param->stype = (si->shr_type & STYPE_MASK);
27709832Samw@Sun.COM 			param->status = NERR_Success;
27719832Samw@Sun.COM 			return (NDR_DRC_OK);
27729832Samw@Sun.COM 		}
27739832Samw@Sun.COM 	}
27749832Samw@Sun.COM 
27759832Samw@Sun.COM 	param->stype = STYPE_DISKTREE;
27769832Samw@Sun.COM 	param->status = NERR_NetNameNotFound;
27779832Samw@Sun.COM 	return (NDR_DRC_OK);
27789832Samw@Sun.COM }
27799832Samw@Sun.COM 
27808474SJose.Borrego@Sun.COM /*
278110122SJordan.Brown@Sun.COM  * Delete a share.  Only members of the Administrators, Server Operators
278210122SJordan.Brown@Sun.COM  * or Power Users local groups are allowed to delete shares.
27838474SJose.Borrego@Sun.COM  *
27848474SJose.Borrego@Sun.COM  * This interface is used by the rmtshare command from the NT resource
27858474SJose.Borrego@Sun.COM  * kit. Rmtshare allows a client to add or remove shares on a server
27868474SJose.Borrego@Sun.COM  * from the client's command line.
27878474SJose.Borrego@Sun.COM  *
27888474SJose.Borrego@Sun.COM  * Returns Win32 error codes.
27898474SJose.Borrego@Sun.COM  */
27908474SJose.Borrego@Sun.COM static int
27918474SJose.Borrego@Sun.COM srvsvc_s_NetShareDel(void *arg, ndr_xa_t *mxa)
27928474SJose.Borrego@Sun.COM {
27938474SJose.Borrego@Sun.COM 	struct mslm_NetShareDel *param = arg;
279411963SAfshin.Ardakani@Sun.COM 	smb_share_t si;
27958474SJose.Borrego@Sun.COM 
27968474SJose.Borrego@Sun.COM 	if (!ndr_is_poweruser(mxa) ||
27978474SJose.Borrego@Sun.COM 	    smb_shr_is_restricted((char *)param->netname)) {
27988474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
27998474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
28008474SJose.Borrego@Sun.COM 	}
28018474SJose.Borrego@Sun.COM 
280211963SAfshin.Ardakani@Sun.COM 	if (smb_shr_get((char *)param->netname, &si) == NERR_Success) {
280311963SAfshin.Ardakani@Sun.COM 		if (si.shr_flags & SMB_SHRF_DFSROOT) {
280411963SAfshin.Ardakani@Sun.COM 			param->status = NERR_IsDfsShare;
280511963SAfshin.Ardakani@Sun.COM 			return (NDR_DRC_OK);
280611963SAfshin.Ardakani@Sun.COM 		}
280711963SAfshin.Ardakani@Sun.COM 	}
280811963SAfshin.Ardakani@Sun.COM 
28098474SJose.Borrego@Sun.COM 	param->status = srvsvc_sa_delete((char *)param->netname);
28108474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
28118474SJose.Borrego@Sun.COM }
28128474SJose.Borrego@Sun.COM 
28138474SJose.Borrego@Sun.COM /*
28148474SJose.Borrego@Sun.COM  * srvsvc_s_NetGetFileSecurity
28158474SJose.Borrego@Sun.COM  *
28168474SJose.Borrego@Sun.COM  * Get security descriptor of the requested file/folder
28178474SJose.Borrego@Sun.COM  *
28188474SJose.Borrego@Sun.COM  * Right now, just returns ERROR_ACCESS_DENIED, because we cannot
28198474SJose.Borrego@Sun.COM  * get the requested SD here in RPC code.
28208474SJose.Borrego@Sun.COM  */
28218474SJose.Borrego@Sun.COM /*ARGSUSED*/
28228474SJose.Borrego@Sun.COM static int
28238474SJose.Borrego@Sun.COM srvsvc_s_NetGetFileSecurity(void *arg, ndr_xa_t *mxa)
28248474SJose.Borrego@Sun.COM {
28258474SJose.Borrego@Sun.COM 	struct mslm_NetGetFileSecurity *param = arg;
28268474SJose.Borrego@Sun.COM 
28278474SJose.Borrego@Sun.COM 	param->length = 0;
28288474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
28298474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
28308474SJose.Borrego@Sun.COM }
28318474SJose.Borrego@Sun.COM 
28328474SJose.Borrego@Sun.COM /*
28338474SJose.Borrego@Sun.COM  * srvsvc_s_NetSetFileSecurity
28348474SJose.Borrego@Sun.COM  *
28358474SJose.Borrego@Sun.COM  * Set the given security descriptor for the requested file/folder
28368474SJose.Borrego@Sun.COM  *
28378474SJose.Borrego@Sun.COM  * Right now, just returns ERROR_ACCESS_DENIED, because we cannot
28388474SJose.Borrego@Sun.COM  * set the requested SD here in RPC code.
28398474SJose.Borrego@Sun.COM  */
28408474SJose.Borrego@Sun.COM /*ARGSUSED*/
28418474SJose.Borrego@Sun.COM static int
28428474SJose.Borrego@Sun.COM srvsvc_s_NetSetFileSecurity(void *arg, ndr_xa_t *mxa)
28438474SJose.Borrego@Sun.COM {
28448474SJose.Borrego@Sun.COM 	struct mslm_NetSetFileSecurity *param = arg;
28458474SJose.Borrego@Sun.COM 
28468474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
28478474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
28488474SJose.Borrego@Sun.COM }
28498474SJose.Borrego@Sun.COM 
28508474SJose.Borrego@Sun.COM /*
28518474SJose.Borrego@Sun.COM  * If the default "smb" share group exists then return the group
28528474SJose.Borrego@Sun.COM  * handle, otherwise create the group and return the handle.
28538474SJose.Borrego@Sun.COM  *
28548474SJose.Borrego@Sun.COM  * All shares created via the srvsvc will be added to the "smb"
28558474SJose.Borrego@Sun.COM  * group.
28568474SJose.Borrego@Sun.COM  */
28578474SJose.Borrego@Sun.COM static sa_group_t
28588474SJose.Borrego@Sun.COM srvsvc_sa_get_smbgrp(sa_handle_t handle)
28598474SJose.Borrego@Sun.COM {
28608474SJose.Borrego@Sun.COM 	sa_group_t group = NULL;
28618474SJose.Borrego@Sun.COM 	int err;
28628474SJose.Borrego@Sun.COM 
28638474SJose.Borrego@Sun.COM 	group = sa_get_group(handle, SMB_DEFAULT_SHARE_GROUP);
28648474SJose.Borrego@Sun.COM 	if (group != NULL)
28658474SJose.Borrego@Sun.COM 		return (group);
28668474SJose.Borrego@Sun.COM 
28678474SJose.Borrego@Sun.COM 	group = sa_create_group(handle, SMB_DEFAULT_SHARE_GROUP, &err);
28688474SJose.Borrego@Sun.COM 	if (group == NULL)
28698474SJose.Borrego@Sun.COM 		return (NULL);
28708474SJose.Borrego@Sun.COM 
28718474SJose.Borrego@Sun.COM 	if (sa_create_optionset(group, SMB_DEFAULT_SHARE_GROUP) == NULL) {
28728474SJose.Borrego@Sun.COM 		(void) sa_remove_group(group);
28738474SJose.Borrego@Sun.COM 		group = NULL;
28748474SJose.Borrego@Sun.COM 	}
28758474SJose.Borrego@Sun.COM 
28768474SJose.Borrego@Sun.COM 	return (group);
28778474SJose.Borrego@Sun.COM }
28788474SJose.Borrego@Sun.COM 
28798474SJose.Borrego@Sun.COM /*
28808474SJose.Borrego@Sun.COM  * Stores the given share in sharemgr
28818474SJose.Borrego@Sun.COM  */
28828474SJose.Borrego@Sun.COM static uint32_t
28838474SJose.Borrego@Sun.COM srvsvc_sa_add(char *sharename, char *path, char *cmnt)
28848474SJose.Borrego@Sun.COM {
28858474SJose.Borrego@Sun.COM 	sa_handle_t handle;
28868474SJose.Borrego@Sun.COM 	sa_share_t share;
28878474SJose.Borrego@Sun.COM 	sa_group_t group;
28888474SJose.Borrego@Sun.COM 	sa_resource_t resource;
28898474SJose.Borrego@Sun.COM 	boolean_t new_share = B_FALSE;
28908474SJose.Borrego@Sun.COM 	uint32_t status = NERR_Success;
28918474SJose.Borrego@Sun.COM 	int err;
28928474SJose.Borrego@Sun.COM 
28938474SJose.Borrego@Sun.COM 	if ((handle = smb_shr_sa_enter()) == NULL)
28948474SJose.Borrego@Sun.COM 		return (NERR_InternalError);
28958474SJose.Borrego@Sun.COM 
28968474SJose.Borrego@Sun.COM 	share = sa_find_share(handle, path);
28978474SJose.Borrego@Sun.COM 	if (share == NULL) {
28988474SJose.Borrego@Sun.COM 		group = srvsvc_sa_get_smbgrp(handle);
28998474SJose.Borrego@Sun.COM 		if (group == NULL) {
29008474SJose.Borrego@Sun.COM 			smb_shr_sa_exit();
29018474SJose.Borrego@Sun.COM 			return (NERR_InternalError);
29028474SJose.Borrego@Sun.COM 		}
29038474SJose.Borrego@Sun.COM 
29048474SJose.Borrego@Sun.COM 		share = sa_add_share(group, path, SA_SHARE_PERMANENT, &err);
29058474SJose.Borrego@Sun.COM 		if (share == NULL) {
29068474SJose.Borrego@Sun.COM 			smb_shr_sa_exit();
29078474SJose.Borrego@Sun.COM 			return (NERR_InternalError);
29088474SJose.Borrego@Sun.COM 		}
29098474SJose.Borrego@Sun.COM 		new_share = B_TRUE;
29108474SJose.Borrego@Sun.COM 	}
29118474SJose.Borrego@Sun.COM 
29128474SJose.Borrego@Sun.COM 	resource = sa_get_share_resource(share, sharename);
29138474SJose.Borrego@Sun.COM 	if (resource == NULL) {
29148474SJose.Borrego@Sun.COM 		resource = sa_add_resource(share, sharename,
29158474SJose.Borrego@Sun.COM 		    SA_SHARE_PERMANENT, &err);
29168474SJose.Borrego@Sun.COM 		if (resource == NULL) {
29178474SJose.Borrego@Sun.COM 			if (new_share)
29188474SJose.Borrego@Sun.COM 				(void) sa_remove_share(share);
29198474SJose.Borrego@Sun.COM 			smb_shr_sa_exit();
29208474SJose.Borrego@Sun.COM 			return (NERR_InternalError);
29218474SJose.Borrego@Sun.COM 		}
29228474SJose.Borrego@Sun.COM 	}
29238474SJose.Borrego@Sun.COM 
29248474SJose.Borrego@Sun.COM 	(void) sa_set_resource_description(resource, cmnt);
29258474SJose.Borrego@Sun.COM 
29268474SJose.Borrego@Sun.COM 	smb_shr_sa_exit();
29278474SJose.Borrego@Sun.COM 	return (status);
29288474SJose.Borrego@Sun.COM }
29298474SJose.Borrego@Sun.COM 
29308474SJose.Borrego@Sun.COM /*
29318474SJose.Borrego@Sun.COM  * Removes the share from sharemgr
29328474SJose.Borrego@Sun.COM  */
29338474SJose.Borrego@Sun.COM static uint32_t
29348474SJose.Borrego@Sun.COM srvsvc_sa_delete(char *sharename)
29358474SJose.Borrego@Sun.COM {
29368474SJose.Borrego@Sun.COM 	sa_handle_t handle;
29378474SJose.Borrego@Sun.COM 	sa_resource_t resource;
29388474SJose.Borrego@Sun.COM 	uint32_t status;
29398474SJose.Borrego@Sun.COM 
29408474SJose.Borrego@Sun.COM 	if ((handle = smb_shr_sa_enter()) == NULL)
29418474SJose.Borrego@Sun.COM 		return (NERR_InternalError);
29428474SJose.Borrego@Sun.COM 
29438474SJose.Borrego@Sun.COM 	status = NERR_InternalError;
29448474SJose.Borrego@Sun.COM 	if ((resource = sa_find_resource(handle, sharename)) != NULL) {
29458474SJose.Borrego@Sun.COM 		if (sa_remove_resource(resource) == SA_OK)
29468474SJose.Borrego@Sun.COM 			status = NERR_Success;
29478474SJose.Borrego@Sun.COM 	}
29488474SJose.Borrego@Sun.COM 
29498474SJose.Borrego@Sun.COM 	smb_shr_sa_exit();
29508474SJose.Borrego@Sun.COM 	return (status);
29518474SJose.Borrego@Sun.COM }
29528474SJose.Borrego@Sun.COM 
29539832Samw@Sun.COM /*
29549832Samw@Sun.COM  * Update the share information.
29559832Samw@Sun.COM  */
29569832Samw@Sun.COM static uint32_t
29579832Samw@Sun.COM srvsvc_sa_modify(smb_share_t *si, srvsvc_netshare_setinfo_t *info)
29589832Samw@Sun.COM {
29599832Samw@Sun.COM 	sa_handle_t handle;
29609832Samw@Sun.COM 	sa_share_t share;
29619832Samw@Sun.COM 	sa_resource_t resource;
29629832Samw@Sun.COM 	boolean_t renamed = B_FALSE;
29639832Samw@Sun.COM 	uint32_t nerr = NERR_Success;
29649832Samw@Sun.COM 
29659832Samw@Sun.COM 	if ((handle = smb_shr_sa_enter()) == NULL)
29669832Samw@Sun.COM 		return (NERR_InternalError);
29679832Samw@Sun.COM 
29689832Samw@Sun.COM 	if ((share = sa_find_share(handle, si->shr_path)) == NULL) {
29699832Samw@Sun.COM 		smb_shr_sa_exit();
29709832Samw@Sun.COM 		return (NERR_InternalError);
29719832Samw@Sun.COM 	}
29729832Samw@Sun.COM 
29739832Samw@Sun.COM 	if ((resource = sa_get_share_resource(share, si->shr_name)) == NULL) {
29749832Samw@Sun.COM 		smb_shr_sa_exit();
29759832Samw@Sun.COM 		return (NERR_InternalError);
29769832Samw@Sun.COM 	}
29779832Samw@Sun.COM 
29789832Samw@Sun.COM 	if (info->nss_netname != NULL && info->nss_netname[0] != '\0' &&
297910966SJordan.Brown@Sun.COM 	    smb_strcasecmp(info->nss_netname, si->shr_name, 0) != 0) {
29809832Samw@Sun.COM 		(void) sa_set_resource_attr(resource, SHOPT_NAME,
29819832Samw@Sun.COM 		    info->nss_netname);
29829832Samw@Sun.COM 		renamed = B_TRUE;
29839832Samw@Sun.COM 	}
29849832Samw@Sun.COM 
29859832Samw@Sun.COM 	if ((info->nss_comment != NULL) &&
29869832Samw@Sun.COM 	    (strcmp(info->nss_comment, si->shr_cmnt) != 0)) {
29879832Samw@Sun.COM 		(void) sa_set_resource_description(resource, info->nss_comment);
29889832Samw@Sun.COM 		(void) strlcpy(si->shr_cmnt, info->nss_comment,
29899832Samw@Sun.COM 		    SMB_SHARE_CMNT_MAX);
29909832Samw@Sun.COM 	}
29919832Samw@Sun.COM 
29929832Samw@Sun.COM 	smb_shr_sa_exit();
29939832Samw@Sun.COM 
29949832Samw@Sun.COM 	if (renamed) {
29959832Samw@Sun.COM 		nerr = smb_shr_rename(si->shr_name, info->nss_netname);
29969832Samw@Sun.COM 		if (nerr != NERR_Success)
29979832Samw@Sun.COM 			return (nerr);
29989832Samw@Sun.COM 
29999832Samw@Sun.COM 		(void) strlcpy(si->shr_name, info->nss_netname, MAXNAMELEN);
30009832Samw@Sun.COM 	}
30019832Samw@Sun.COM 
30029832Samw@Sun.COM 	return (nerr);
30039832Samw@Sun.COM }
30049832Samw@Sun.COM 
30059832Samw@Sun.COM /*
300610504SKeyur.Desai@Sun.COM  * Update the share properties.
300710504SKeyur.Desai@Sun.COM  *
300810504SKeyur.Desai@Sun.COM  * Updates the optionset properties of the share resource.
300910504SKeyur.Desai@Sun.COM  * The properties are given as a list of name-value pair.
301010504SKeyur.Desai@Sun.COM  * The name argument should be the optionset property name and the value
301110504SKeyur.Desai@Sun.COM  * should be a valid value for the specified property.
30129832Samw@Sun.COM  */
30139832Samw@Sun.COM static uint32_t
301410504SKeyur.Desai@Sun.COM srvsvc_sa_setprop(smb_share_t *si, nvlist_t *nvl)
30159832Samw@Sun.COM {
30169832Samw@Sun.COM 	sa_handle_t handle;
30179832Samw@Sun.COM 	sa_share_t share;
30189832Samw@Sun.COM 	sa_resource_t resource;
301910504SKeyur.Desai@Sun.COM 	sa_property_t prop;
302010504SKeyur.Desai@Sun.COM 	sa_optionset_t opts;
302110504SKeyur.Desai@Sun.COM 	uint32_t nerr = NERR_Success;
302210504SKeyur.Desai@Sun.COM 	nvpair_t *cur;
302310504SKeyur.Desai@Sun.COM 	int err = 0;
302410504SKeyur.Desai@Sun.COM 	char *name, *val;
30259832Samw@Sun.COM 
302611963SAfshin.Ardakani@Sun.COM 	if ((handle = sa_init(SA_INIT_SHARE_API)) == NULL)
30279832Samw@Sun.COM 		return (NERR_InternalError);
30289832Samw@Sun.COM 
30299832Samw@Sun.COM 	if ((share = sa_find_share(handle, si->shr_path)) == NULL) {
303011963SAfshin.Ardakani@Sun.COM 		sa_fini(handle);
30319832Samw@Sun.COM 		return (NERR_InternalError);
30329832Samw@Sun.COM 	}
30339832Samw@Sun.COM 
30349832Samw@Sun.COM 	if ((resource = sa_get_share_resource(share, si->shr_name)) == NULL) {
303511963SAfshin.Ardakani@Sun.COM 		sa_fini(handle);
30369832Samw@Sun.COM 		return (NERR_InternalError);
30379832Samw@Sun.COM 	}
30389832Samw@Sun.COM 
303910504SKeyur.Desai@Sun.COM 	if ((opts = sa_get_optionset(resource, SMB_PROTOCOL_NAME)) == NULL) {
304010504SKeyur.Desai@Sun.COM 		opts = sa_create_optionset(resource, SMB_PROTOCOL_NAME);
304110504SKeyur.Desai@Sun.COM 		if (opts == NULL) {
304211963SAfshin.Ardakani@Sun.COM 			sa_fini(handle);
304310504SKeyur.Desai@Sun.COM 			return (NERR_InternalError);
304410504SKeyur.Desai@Sun.COM 		}
30459832Samw@Sun.COM 	}
30469832Samw@Sun.COM 
304710504SKeyur.Desai@Sun.COM 	cur = nvlist_next_nvpair(nvl, NULL);
304810504SKeyur.Desai@Sun.COM 	while (cur != NULL) {
304910504SKeyur.Desai@Sun.COM 		name = nvpair_name(cur);
305010504SKeyur.Desai@Sun.COM 		err = nvpair_value_string(cur, &val);
305110504SKeyur.Desai@Sun.COM 		if ((err != 0) || (name == NULL) || (val == NULL)) {
305210504SKeyur.Desai@Sun.COM 			nerr = NERR_InternalError;
305310504SKeyur.Desai@Sun.COM 			break;
305410504SKeyur.Desai@Sun.COM 		}
305510504SKeyur.Desai@Sun.COM 
305610504SKeyur.Desai@Sun.COM 		prop = NULL;
305710504SKeyur.Desai@Sun.COM 		if ((prop = sa_get_property(opts, name)) == NULL) {
305810504SKeyur.Desai@Sun.COM 			prop = sa_create_property(name, val);
305910504SKeyur.Desai@Sun.COM 			if (prop != NULL) {
306010504SKeyur.Desai@Sun.COM 				nerr = sa_valid_property(handle, opts,
306110504SKeyur.Desai@Sun.COM 				    SMB_PROTOCOL_NAME, prop);
306210504SKeyur.Desai@Sun.COM 				if (nerr != NERR_Success) {
306310504SKeyur.Desai@Sun.COM 					(void) sa_remove_property(prop);
306410504SKeyur.Desai@Sun.COM 					break;
306510504SKeyur.Desai@Sun.COM 				}
306610504SKeyur.Desai@Sun.COM 			}
306710504SKeyur.Desai@Sun.COM 			nerr = sa_add_property(opts, prop);
306810504SKeyur.Desai@Sun.COM 			if (nerr != NERR_Success)
306910504SKeyur.Desai@Sun.COM 				break;
307010504SKeyur.Desai@Sun.COM 		} else {
307110504SKeyur.Desai@Sun.COM 			nerr = sa_update_property(prop, val);
307210504SKeyur.Desai@Sun.COM 			if (nerr != NERR_Success)
307310504SKeyur.Desai@Sun.COM 				break;
307410504SKeyur.Desai@Sun.COM 		}
307510504SKeyur.Desai@Sun.COM 
307610504SKeyur.Desai@Sun.COM 		cur = nvlist_next_nvpair(nvl, cur);
307710504SKeyur.Desai@Sun.COM 	}
307810504SKeyur.Desai@Sun.COM 
307910504SKeyur.Desai@Sun.COM 	if (nerr == NERR_Success)
308010504SKeyur.Desai@Sun.COM 		nerr = sa_commit_properties(opts, 0);
308110504SKeyur.Desai@Sun.COM 
308211963SAfshin.Ardakani@Sun.COM 	sa_fini(handle);
308310504SKeyur.Desai@Sun.COM 	return (nerr);
30849832Samw@Sun.COM }
30859832Samw@Sun.COM 
308610504SKeyur.Desai@Sun.COM 
30878474SJose.Borrego@Sun.COM static ndr_stub_table_t srvsvc_stub_table[] = {
30888474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetConnectEnum,	SRVSVC_OPNUM_NetConnectEnum },
30898474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetFileEnum,		SRVSVC_OPNUM_NetFileEnum },
30908474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetFileClose,	SRVSVC_OPNUM_NetFileClose },
30918474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetShareGetInfo,	SRVSVC_OPNUM_NetShareGetInfo },
30928474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetShareSetInfo,	SRVSVC_OPNUM_NetShareSetInfo },
30938474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetSessionEnum,	SRVSVC_OPNUM_NetSessionEnum },
30948474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetSessionDel,	SRVSVC_OPNUM_NetSessionDel },
30958474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetServerGetInfo,	SRVSVC_OPNUM_NetServerGetInfo },
30968474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetRemoteTOD,	SRVSVC_OPNUM_NetRemoteTOD },
30978474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetNameValidate,	SRVSVC_OPNUM_NetNameValidate },
30988474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetShareAdd,		SRVSVC_OPNUM_NetShareAdd },
30998474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetShareDel,		SRVSVC_OPNUM_NetShareDel },
31008474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetShareEnum,	SRVSVC_OPNUM_NetShareEnum },
31018474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetShareEnumSticky,	SRVSVC_OPNUM_NetShareEnumSticky },
31029832Samw@Sun.COM 	{ srvsvc_s_NetShareCheck,	SRVSVC_OPNUM_NetShareCheck },
31038474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetGetFileSecurity,	SRVSVC_OPNUM_NetGetFileSecurity },
31048474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetSetFileSecurity,	SRVSVC_OPNUM_NetSetFileSecurity },
31058474SJose.Borrego@Sun.COM 	{0}
31068474SJose.Borrego@Sun.COM };
3107