xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_svc.c (revision 8670:6da349c3f817)
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 /*
228474SJose.Borrego@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
238474SJose.Borrego@Sun.COM  * Use is subject to license terms.
248474SJose.Borrego@Sun.COM  */
258474SJose.Borrego@Sun.COM 
268474SJose.Borrego@Sun.COM /*
278474SJose.Borrego@Sun.COM  * Server Service RPC (SRVSVC) server-side interface definition.
288474SJose.Borrego@Sun.COM  * The server service provides a remote administration interface.
298474SJose.Borrego@Sun.COM  *
308474SJose.Borrego@Sun.COM  * This service uses NERR/Win32 error codes rather than NT status
318474SJose.Borrego@Sun.COM  * values.
328474SJose.Borrego@Sun.COM  */
338474SJose.Borrego@Sun.COM 
348474SJose.Borrego@Sun.COM #include <sys/errno.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>
488474SJose.Borrego@Sun.COM 
498474SJose.Borrego@Sun.COM #include <smbsrv/libsmb.h>
508474SJose.Borrego@Sun.COM #include <smbsrv/libmlsvc.h>
518474SJose.Borrego@Sun.COM #include <smbsrv/lmerr.h>
528474SJose.Borrego@Sun.COM #include <smbsrv/nterror.h>
538474SJose.Borrego@Sun.COM #include <smbsrv/nmpipes.h>
548474SJose.Borrego@Sun.COM #include <smbsrv/cifs.h>
558474SJose.Borrego@Sun.COM #include <smbsrv/netrauth.h>
568474SJose.Borrego@Sun.COM #include <smbsrv/ndl/srvsvc.ndl>
578474SJose.Borrego@Sun.COM #include <smbsrv/smb_common_door.h>
588474SJose.Borrego@Sun.COM 
598474SJose.Borrego@Sun.COM #define	SV_TYPE_SENT_BY_ME (SV_TYPE_WORKSTATION | SV_TYPE_SERVER | SV_TYPE_NT)
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 
688474SJose.Borrego@Sun.COM #define	SMB_SRVSVC_MAXBUFLEN	(8 * 1024 * 1024)
698474SJose.Borrego@Sun.COM #define	SMB_SRVSVC_MAXPREFLEN	((uint32_t)(-1))
708474SJose.Borrego@Sun.COM 
718474SJose.Borrego@Sun.COM /*
728474SJose.Borrego@Sun.COM  * prefmaxlen:    Client specified response buffer limit.
738474SJose.Borrego@Sun.COM  * resume_handle: Cookie used to track enumeration across multiple calls.
748474SJose.Borrego@Sun.COM  * n_total:       Total number of entries.
758474SJose.Borrego@Sun.COM  * n_enum:        Number of entries to enumerate (derived from prefmaxlen).
768474SJose.Borrego@Sun.COM  * n_skip:        Number of entries to skip (from incoming resume handle).
778474SJose.Borrego@Sun.COM  * n_read:        Number of objects returned for current enumeration request.
788474SJose.Borrego@Sun.COM  */
798474SJose.Borrego@Sun.COM typedef struct srvsvc_enum {
808474SJose.Borrego@Sun.COM 	uint32_t se_level;
818474SJose.Borrego@Sun.COM 	uint32_t se_prefmaxlen;
828474SJose.Borrego@Sun.COM 	uint32_t se_resume_handle;
838474SJose.Borrego@Sun.COM 	uint32_t se_n_total;
848474SJose.Borrego@Sun.COM 	uint32_t se_n_enum;
858474SJose.Borrego@Sun.COM 	uint32_t se_n_skip;
868474SJose.Borrego@Sun.COM 	uint32_t se_n_read;
878474SJose.Borrego@Sun.COM } srvsvc_enum_t;
888474SJose.Borrego@Sun.COM 
898474SJose.Borrego@Sun.COM static DWORD srvsvc_s_NetConnectEnumLevel0(ndr_xa_t *,
908474SJose.Borrego@Sun.COM     srvsvc_NetConnectInfo0_t *);
918474SJose.Borrego@Sun.COM static DWORD srvsvc_s_NetConnectEnumLevel1(ndr_xa_t *,
928474SJose.Borrego@Sun.COM     srvsvc_NetConnectInfo1_t *);
938474SJose.Borrego@Sun.COM 
948474SJose.Borrego@Sun.COM static DWORD srvsvc_NetFileEnum2(ndr_xa_t *,
958474SJose.Borrego@Sun.COM     struct mslm_NetFileEnum *);
968474SJose.Borrego@Sun.COM static DWORD srvsvc_NetFileEnum3(ndr_xa_t *,
978474SJose.Borrego@Sun.COM     struct mslm_NetFileEnum *);
988474SJose.Borrego@Sun.COM 
998474SJose.Borrego@Sun.COM static DWORD mlsvc_NetSessionEnumLevel0(struct mslm_infonres *, DWORD,
1008474SJose.Borrego@Sun.COM     ndr_xa_t *);
1018474SJose.Borrego@Sun.COM static DWORD mlsvc_NetSessionEnumLevel1(struct mslm_infonres *, DWORD,
1028474SJose.Borrego@Sun.COM     ndr_xa_t *);
1038474SJose.Borrego@Sun.COM 
1048474SJose.Borrego@Sun.COM static DWORD mlsvc_NetShareEnumLevel0(ndr_xa_t *,
1058474SJose.Borrego@Sun.COM     struct mslm_infonres *, srvsvc_enum_t *, int);
1068474SJose.Borrego@Sun.COM static DWORD mlsvc_NetShareEnumLevel1(ndr_xa_t *,
1078474SJose.Borrego@Sun.COM     struct mslm_infonres *, srvsvc_enum_t *, int);
1088474SJose.Borrego@Sun.COM static DWORD mlsvc_NetShareEnumLevel2(ndr_xa_t *,
1098474SJose.Borrego@Sun.COM     struct mslm_infonres *, srvsvc_enum_t *, int);
1108474SJose.Borrego@Sun.COM static DWORD mlsvc_NetShareEnumLevel501(ndr_xa_t *,
1118474SJose.Borrego@Sun.COM     struct mslm_infonres *, srvsvc_enum_t *, int);
1128474SJose.Borrego@Sun.COM static DWORD mlsvc_NetShareEnumLevel502(ndr_xa_t *,
1138474SJose.Borrego@Sun.COM     struct mslm_infonres *, srvsvc_enum_t *, int);
1148474SJose.Borrego@Sun.COM static DWORD mlsvc_NetShareEnumCommon(ndr_xa_t *,
1158474SJose.Borrego@Sun.COM     srvsvc_enum_t *, smb_share_t *, void *);
1168474SJose.Borrego@Sun.COM static boolean_t srvsvc_add_autohome(ndr_xa_t *, srvsvc_enum_t *,
1178474SJose.Borrego@Sun.COM     void *);
1188474SJose.Borrego@Sun.COM static char *srvsvc_share_mkpath(ndr_xa_t *, char *);
1198474SJose.Borrego@Sun.COM 
1208474SJose.Borrego@Sun.COM static int srvsvc_netconnect_qualifier(const char *);
1218474SJose.Borrego@Sun.COM static uint32_t srvsvc_estimate_objcnt(uint32_t, uint32_t, uint32_t);
1228474SJose.Borrego@Sun.COM 
1238474SJose.Borrego@Sun.COM static uint32_t srvsvc_sa_add(char *, char *, char *);
1248474SJose.Borrego@Sun.COM static uint32_t srvsvc_sa_delete(char *);
1258474SJose.Borrego@Sun.COM 
1268474SJose.Borrego@Sun.COM static char empty_string[1];
1278474SJose.Borrego@Sun.COM 
1288474SJose.Borrego@Sun.COM static ndr_stub_table_t srvsvc_stub_table[];
1298474SJose.Borrego@Sun.COM 
1308474SJose.Borrego@Sun.COM static ndr_service_t srvsvc_service = {
1318474SJose.Borrego@Sun.COM 	"SRVSVC",			/* name */
1328474SJose.Borrego@Sun.COM 	"Server services",		/* desc */
1338474SJose.Borrego@Sun.COM 	"\\srvsvc",			/* endpoint */
1348474SJose.Borrego@Sun.COM 	PIPE_NTSVCS,			/* sec_addr_port */
1358474SJose.Borrego@Sun.COM 	"4b324fc8-1670-01d3-1278-5a47bf6ee188", 3,	/* abstract */
1368474SJose.Borrego@Sun.COM 	NDR_TRANSFER_SYNTAX_UUID,		2,	/* transfer */
1378474SJose.Borrego@Sun.COM 	0,				/* no bind_instance_size */
1388474SJose.Borrego@Sun.COM 	0,				/* no bind_req() */
1398474SJose.Borrego@Sun.COM 	0,				/* no unbind_and_close() */
1408474SJose.Borrego@Sun.COM 	0,				/* use generic_call_stub() */
1418474SJose.Borrego@Sun.COM 	&TYPEINFO(srvsvc_interface),	/* interface ti */
1428474SJose.Borrego@Sun.COM 	srvsvc_stub_table		/* stub_table */
1438474SJose.Borrego@Sun.COM };
1448474SJose.Borrego@Sun.COM 
1458474SJose.Borrego@Sun.COM /*
1468474SJose.Borrego@Sun.COM  * srvsvc_initialize
1478474SJose.Borrego@Sun.COM  *
1488474SJose.Borrego@Sun.COM  * This function registers the SRVSVC RPC interface with the RPC runtime
1498474SJose.Borrego@Sun.COM  * library. It must be called in order to use either the client side
1508474SJose.Borrego@Sun.COM  * or the server side functions.
1518474SJose.Borrego@Sun.COM  */
1528474SJose.Borrego@Sun.COM void
1538474SJose.Borrego@Sun.COM srvsvc_initialize(void)
1548474SJose.Borrego@Sun.COM {
1558474SJose.Borrego@Sun.COM 	(void) ndr_svc_register(&srvsvc_service);
1568474SJose.Borrego@Sun.COM }
1578474SJose.Borrego@Sun.COM 
1588474SJose.Borrego@Sun.COM /*
1598474SJose.Borrego@Sun.COM  * srvsvc_s_NetConnectEnum
1608474SJose.Borrego@Sun.COM  *
1618474SJose.Borrego@Sun.COM  * List tree connections made to a share on this server or all tree
1628474SJose.Borrego@Sun.COM  * connections established from a specific client.  Administrator,
1638474SJose.Borrego@Sun.COM  * Server Operator, Print Operator or Power User group membership
1648474SJose.Borrego@Sun.COM  * is required to use this interface.
1658474SJose.Borrego@Sun.COM  *
1668474SJose.Borrego@Sun.COM  * There are three information levels:  0, 1, and 50.  We don't support
1678474SJose.Borrego@Sun.COM  * level 50, which is only used by Windows 9x clients.
1688474SJose.Borrego@Sun.COM  *
1698474SJose.Borrego@Sun.COM  * It seems Server Manger (srvmgr) only sends workstation as the qualifier
1708474SJose.Borrego@Sun.COM  * and the Computer Management Interface on Windows 2000 doesn't request
1718474SJose.Borrego@Sun.COM  * a list of connections.
1728474SJose.Borrego@Sun.COM  *
1738474SJose.Borrego@Sun.COM  * Return Values:
1748474SJose.Borrego@Sun.COM  * ERROR_SUCCESS            Success
1758474SJose.Borrego@Sun.COM  * ERROR_ACCESS_DENIED      Caller does not have access to this call.
1768474SJose.Borrego@Sun.COM  * ERROR_INVALID_PARAMETER  One of the parameters is invalid.
1778474SJose.Borrego@Sun.COM  * ERROR_INVALID_LEVEL      Unknown information level specified.
1788474SJose.Borrego@Sun.COM  * ERROR_MORE_DATA          Partial date returned, more entries available.
1798474SJose.Borrego@Sun.COM  * ERROR_NOT_ENOUGH_MEMORY  Insufficient memory is available.
1808474SJose.Borrego@Sun.COM  * NERR_NetNameNotFound     The share qualifier cannot be found.
1818474SJose.Borrego@Sun.COM  * NERR_BufTooSmall         The supplied buffer is too small.
1828474SJose.Borrego@Sun.COM  */
1838474SJose.Borrego@Sun.COM static int
1848474SJose.Borrego@Sun.COM srvsvc_s_NetConnectEnum(void *arg, ndr_xa_t *mxa)
1858474SJose.Borrego@Sun.COM {
1868474SJose.Borrego@Sun.COM 	struct mslm_NetConnectEnum *param = arg;
1878474SJose.Borrego@Sun.COM 	srvsvc_NetConnectInfo0_t *info0;
1888474SJose.Borrego@Sun.COM 	srvsvc_NetConnectInfo1_t *info1;
1898474SJose.Borrego@Sun.COM 	char *qualifier;
1908474SJose.Borrego@Sun.COM 	int qualtype;
1918474SJose.Borrego@Sun.COM 	DWORD status = ERROR_SUCCESS;
1928474SJose.Borrego@Sun.COM 
1938474SJose.Borrego@Sun.COM 	if (!ndr_is_poweruser(mxa)) {
1948474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetConnectEnum));
1958474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
1968474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
1978474SJose.Borrego@Sun.COM 	}
1988474SJose.Borrego@Sun.COM 
1998474SJose.Borrego@Sun.COM 	qualifier = (char *)param->qualifier;
2008474SJose.Borrego@Sun.COM 	qualtype = srvsvc_netconnect_qualifier(qualifier);
2018474SJose.Borrego@Sun.COM 
2028474SJose.Borrego@Sun.COM 	if (qualtype == SRVSVC_CONNECT_ENUM_NULL) {
2038474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetConnectEnum));
2048474SJose.Borrego@Sun.COM 		param->status = NERR_NetNameNotFound;
2058474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
2068474SJose.Borrego@Sun.COM 	}
2078474SJose.Borrego@Sun.COM 
2088474SJose.Borrego@Sun.COM 	switch (param->info.level) {
2098474SJose.Borrego@Sun.COM 	case 0:
2108474SJose.Borrego@Sun.COM 		info0 = NDR_NEW(mxa, srvsvc_NetConnectInfo0_t);
2118474SJose.Borrego@Sun.COM 		if (info0 == NULL) {
2128474SJose.Borrego@Sun.COM 			status = ERROR_NOT_ENOUGH_MEMORY;
2138474SJose.Borrego@Sun.COM 			break;
2148474SJose.Borrego@Sun.COM 		}
2158474SJose.Borrego@Sun.COM 
2168474SJose.Borrego@Sun.COM 		bzero(info0, sizeof (srvsvc_NetConnectInfo0_t));
2178474SJose.Borrego@Sun.COM 		param->info.ru.info0 = info0;
2188474SJose.Borrego@Sun.COM 
2198474SJose.Borrego@Sun.COM 		status = srvsvc_s_NetConnectEnumLevel0(mxa, info0);
2208474SJose.Borrego@Sun.COM 
2218474SJose.Borrego@Sun.COM 		param->total_entries = info0->entries_read;
2228474SJose.Borrego@Sun.COM 		param->resume_handle = NULL;
2238474SJose.Borrego@Sun.COM 		break;
2248474SJose.Borrego@Sun.COM 
2258474SJose.Borrego@Sun.COM 	case 1:
2268474SJose.Borrego@Sun.COM 		info1 = NDR_NEW(mxa, srvsvc_NetConnectInfo1_t);
2278474SJose.Borrego@Sun.COM 		if (info1 == NULL) {
2288474SJose.Borrego@Sun.COM 			status = ERROR_NOT_ENOUGH_MEMORY;
2298474SJose.Borrego@Sun.COM 			break;
2308474SJose.Borrego@Sun.COM 		}
2318474SJose.Borrego@Sun.COM 
2328474SJose.Borrego@Sun.COM 		bzero(info1, sizeof (srvsvc_NetConnectInfo1_t));
2338474SJose.Borrego@Sun.COM 		param->info.ru.info1 = info1;
2348474SJose.Borrego@Sun.COM 
2358474SJose.Borrego@Sun.COM 		status = srvsvc_s_NetConnectEnumLevel1(mxa, info1);
2368474SJose.Borrego@Sun.COM 
2378474SJose.Borrego@Sun.COM 		param->total_entries = info1->entries_read;
2388474SJose.Borrego@Sun.COM 		param->resume_handle = NULL;
2398474SJose.Borrego@Sun.COM 		break;
2408474SJose.Borrego@Sun.COM 
2418474SJose.Borrego@Sun.COM 	case 50:
2428474SJose.Borrego@Sun.COM 		status = ERROR_NOT_SUPPORTED;
2438474SJose.Borrego@Sun.COM 		break;
2448474SJose.Borrego@Sun.COM 
2458474SJose.Borrego@Sun.COM 	default:
2468474SJose.Borrego@Sun.COM 		status = ERROR_INVALID_LEVEL;
2478474SJose.Borrego@Sun.COM 		break;
2488474SJose.Borrego@Sun.COM 	}
2498474SJose.Borrego@Sun.COM 
2508474SJose.Borrego@Sun.COM 	if (status != ERROR_SUCCESS)
2518474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetConnectEnum));
2528474SJose.Borrego@Sun.COM 
2538474SJose.Borrego@Sun.COM 	param->status = status;
2548474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
2558474SJose.Borrego@Sun.COM }
2568474SJose.Borrego@Sun.COM 
2578474SJose.Borrego@Sun.COM static DWORD
2588474SJose.Borrego@Sun.COM srvsvc_s_NetConnectEnumLevel0(ndr_xa_t *mxa, srvsvc_NetConnectInfo0_t *info0)
2598474SJose.Borrego@Sun.COM {
2608474SJose.Borrego@Sun.COM 	srvsvc_NetConnectInfoBuf0_t *ci0;
2618474SJose.Borrego@Sun.COM 
2628474SJose.Borrego@Sun.COM 	ci0 = NDR_NEW(mxa, srvsvc_NetConnectInfoBuf0_t);
2638474SJose.Borrego@Sun.COM 	if (ci0 == NULL)
2648474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
2658474SJose.Borrego@Sun.COM 
2668474SJose.Borrego@Sun.COM 	ci0->coni0_id = 0x17;
2678474SJose.Borrego@Sun.COM 
2688474SJose.Borrego@Sun.COM 	info0->ci0 = ci0;
2698474SJose.Borrego@Sun.COM 	info0->entries_read = 1;
2708474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
2718474SJose.Borrego@Sun.COM }
2728474SJose.Borrego@Sun.COM 
2738474SJose.Borrego@Sun.COM static DWORD
2748474SJose.Borrego@Sun.COM srvsvc_s_NetConnectEnumLevel1(ndr_xa_t *mxa, srvsvc_NetConnectInfo1_t *info1)
2758474SJose.Borrego@Sun.COM {
2768474SJose.Borrego@Sun.COM 	srvsvc_NetConnectInfoBuf1_t *ci1;
2778474SJose.Borrego@Sun.COM 
2788474SJose.Borrego@Sun.COM 	ci1 = NDR_NEW(mxa, srvsvc_NetConnectInfoBuf1_t);
2798474SJose.Borrego@Sun.COM 	if (ci1 == NULL)
2808474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
2818474SJose.Borrego@Sun.COM 
2828474SJose.Borrego@Sun.COM 	ci1->coni1_id = 0x17;
2838474SJose.Borrego@Sun.COM 	ci1->coni1_type = STYPE_IPC;
2848474SJose.Borrego@Sun.COM 	ci1->coni1_num_opens = 1;
2858474SJose.Borrego@Sun.COM 	ci1->coni1_num_users = 1;
2868474SJose.Borrego@Sun.COM 	ci1->coni1_time = 16;
2878474SJose.Borrego@Sun.COM 	ci1->coni1_username = (uint8_t *)NDR_STRDUP(mxa, "Administrator");
2888474SJose.Borrego@Sun.COM 	ci1->coni1_netname = (uint8_t *)NDR_STRDUP(mxa, "IPC$");
2898474SJose.Borrego@Sun.COM 
2908474SJose.Borrego@Sun.COM 	info1->ci1 = ci1;
2918474SJose.Borrego@Sun.COM 	info1->entries_read = 1;
2928474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
2938474SJose.Borrego@Sun.COM }
2948474SJose.Borrego@Sun.COM 
2958474SJose.Borrego@Sun.COM /*
2968474SJose.Borrego@Sun.COM  * srvsvc_netconnect_qualifier
2978474SJose.Borrego@Sun.COM  *
2988474SJose.Borrego@Sun.COM  * The qualifier is a string that specifies a share name or computer name
2998474SJose.Borrego@Sun.COM  * for the connections of interest.  If it is a share name then all the
3008474SJose.Borrego@Sun.COM  * connections made to that share name are listed.  If it is a computer
3018474SJose.Borrego@Sun.COM  * name (it starts with two backslash characters), then NetConnectEnum
3028474SJose.Borrego@Sun.COM  * lists all connections made from that computer to the specified server.
3038474SJose.Borrego@Sun.COM  */
3048474SJose.Borrego@Sun.COM static int
3058474SJose.Borrego@Sun.COM srvsvc_netconnect_qualifier(const char *qualifier)
3068474SJose.Borrego@Sun.COM {
3078474SJose.Borrego@Sun.COM 	if (qualifier == NULL || *qualifier == '\0')
3088474SJose.Borrego@Sun.COM 		return (SRVSVC_CONNECT_ENUM_NULL);
3098474SJose.Borrego@Sun.COM 
3108474SJose.Borrego@Sun.COM 	if (strlen(qualifier) > MAXHOSTNAMELEN)
3118474SJose.Borrego@Sun.COM 		return (SRVSVC_CONNECT_ENUM_NULL);
3128474SJose.Borrego@Sun.COM 
3138474SJose.Borrego@Sun.COM 	if (qualifier[0] == '\\' && qualifier[1] == '\\') {
3148474SJose.Borrego@Sun.COM 		return (SRVSVC_CONNECT_ENUM_WKSTN);
3158474SJose.Borrego@Sun.COM 	} else {
3168474SJose.Borrego@Sun.COM 		if (!smb_shr_exists((char *)qualifier))
3178474SJose.Borrego@Sun.COM 			return (SRVSVC_CONNECT_ENUM_NULL);
3188474SJose.Borrego@Sun.COM 
3198474SJose.Borrego@Sun.COM 		return (SRVSVC_CONNECT_ENUM_SHARE);
3208474SJose.Borrego@Sun.COM 	}
3218474SJose.Borrego@Sun.COM }
3228474SJose.Borrego@Sun.COM 
3238474SJose.Borrego@Sun.COM /*
3248474SJose.Borrego@Sun.COM  * srvsvc_s_NetFileEnum
3258474SJose.Borrego@Sun.COM  *
3268474SJose.Borrego@Sun.COM  * Return information on open files or named pipes. Only members of the
3278474SJose.Borrego@Sun.COM  * Administrators or Server Operators local groups are allowed to make
3288474SJose.Borrego@Sun.COM  * this call. Currently, we only support Administrators.
3298474SJose.Borrego@Sun.COM  *
3308474SJose.Borrego@Sun.COM  * If basepath is null, all open resources are enumerated. If basepath
3318474SJose.Borrego@Sun.COM  * is non-null, only resources that have basepath as a prefix should
3328474SJose.Borrego@Sun.COM  * be returned.
3338474SJose.Borrego@Sun.COM  *
3348474SJose.Borrego@Sun.COM  * If username is specified (non-null), only files opened by username
3358474SJose.Borrego@Sun.COM  * should be returned.
3368474SJose.Borrego@Sun.COM  *
3378474SJose.Borrego@Sun.COM  * Notes:
3388474SJose.Borrego@Sun.COM  * 1. We don't validate the servername because we would have to check
3398474SJose.Borrego@Sun.COM  * all primary IPs and the ROI seems unlikely to be worth it.
3408474SJose.Borrego@Sun.COM  * 2. Both basepath and username are currently ignored because both
3418474SJose.Borrego@Sun.COM  * Server Manger (NT 4.0) and CMI (Windows 2000) always set them to null.
3428474SJose.Borrego@Sun.COM  *
3438474SJose.Borrego@Sun.COM  * The level of information requested may be one of:
3448474SJose.Borrego@Sun.COM  *
3458474SJose.Borrego@Sun.COM  *  2   Return the file identification number.
3468474SJose.Borrego@Sun.COM  *      This level is not supported on Windows Me/98/95.
3478474SJose.Borrego@Sun.COM  *
3488474SJose.Borrego@Sun.COM  *  3   Return information about the file.
3498474SJose.Borrego@Sun.COM  *      This level is not supported on Windows Me/98/95.
3508474SJose.Borrego@Sun.COM  *
3518474SJose.Borrego@Sun.COM  *  50  Windows Me/98/95:  Return information about the file.
3528474SJose.Borrego@Sun.COM  *
3538474SJose.Borrego@Sun.COM  * Note:
3548474SJose.Borrego@Sun.COM  * If pref_max_len is unlimited and resume_handle is null, the client
3558474SJose.Borrego@Sun.COM  * expects to receive all data in a single call.
3568474SJose.Borrego@Sun.COM  * If we are unable to do fit all data in a single response, we would
3578474SJose.Borrego@Sun.COM  * normally return ERROR_MORE_DATA with a partial list.
3588474SJose.Borrego@Sun.COM  *
3598474SJose.Borrego@Sun.COM  * Unfortunately, when both of these conditions occur, Server Manager
3608474SJose.Borrego@Sun.COM  * pops up an error box with the message "more data available" and
3618474SJose.Borrego@Sun.COM  * doesn't display any of the returned data. In this case, it is
3628474SJose.Borrego@Sun.COM  * probably better to return ERROR_SUCCESS with the partial list.
3638474SJose.Borrego@Sun.COM  * Windows 2000 doesn't have this problem because it always sends a
3648474SJose.Borrego@Sun.COM  * non-null resume_handle.
3658474SJose.Borrego@Sun.COM  *
3668474SJose.Borrego@Sun.COM  * Return Values:
3678474SJose.Borrego@Sun.COM  * ERROR_SUCCESS            Success
3688474SJose.Borrego@Sun.COM  * ERROR_ACCESS_DENIED      Caller does not have access to this call.
3698474SJose.Borrego@Sun.COM  * ERROR_INVALID_PARAMETER  One of the parameters is invalid.
3708474SJose.Borrego@Sun.COM  * ERROR_INVALID_LEVEL      Unknown information level specified.
3718474SJose.Borrego@Sun.COM  * ERROR_MORE_DATA          Partial date returned, more entries available.
3728474SJose.Borrego@Sun.COM  * ERROR_NOT_ENOUGH_MEMORY  Insufficient memory is available.
3738474SJose.Borrego@Sun.COM  * NERR_BufTooSmall         The supplied buffer is too small.
3748474SJose.Borrego@Sun.COM  */
3758474SJose.Borrego@Sun.COM static int
3768474SJose.Borrego@Sun.COM srvsvc_s_NetFileEnum(void *arg, ndr_xa_t *mxa)
3778474SJose.Borrego@Sun.COM {
3788474SJose.Borrego@Sun.COM 	struct mslm_NetFileEnum *param = arg;
3798474SJose.Borrego@Sun.COM 	DWORD status;
3808474SJose.Borrego@Sun.COM 
3818474SJose.Borrego@Sun.COM 	if (!ndr_is_admin(mxa)) {
3828474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetFileEnum));
3838474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
3848474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
3858474SJose.Borrego@Sun.COM 	}
3868474SJose.Borrego@Sun.COM 
3878474SJose.Borrego@Sun.COM 	switch (param->info.switch_value) {
3888474SJose.Borrego@Sun.COM 	case 2:
3898474SJose.Borrego@Sun.COM 		status = srvsvc_NetFileEnum2(mxa, param);
3908474SJose.Borrego@Sun.COM 		break;
3918474SJose.Borrego@Sun.COM 
3928474SJose.Borrego@Sun.COM 	case 3:
3938474SJose.Borrego@Sun.COM 		status = srvsvc_NetFileEnum3(mxa, param);
3948474SJose.Borrego@Sun.COM 		break;
3958474SJose.Borrego@Sun.COM 
3968474SJose.Borrego@Sun.COM 	case 50:
3978474SJose.Borrego@Sun.COM 		status = ERROR_NOT_SUPPORTED;
3988474SJose.Borrego@Sun.COM 		break;
3998474SJose.Borrego@Sun.COM 
4008474SJose.Borrego@Sun.COM 	default:
4018474SJose.Borrego@Sun.COM 		status = ERROR_INVALID_LEVEL;
4028474SJose.Borrego@Sun.COM 		break;
4038474SJose.Borrego@Sun.COM 	}
4048474SJose.Borrego@Sun.COM 
4058474SJose.Borrego@Sun.COM 	if (status != ERROR_SUCCESS) {
4068474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetFileEnum));
4078474SJose.Borrego@Sun.COM 		param->status = status;
4088474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
4098474SJose.Borrego@Sun.COM 	}
4108474SJose.Borrego@Sun.COM 
4118474SJose.Borrego@Sun.COM 	if (param->resume_handle)
4128474SJose.Borrego@Sun.COM 		*param->resume_handle = 0;
4138474SJose.Borrego@Sun.COM 
4148474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
4158474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
4168474SJose.Borrego@Sun.COM }
4178474SJose.Borrego@Sun.COM 
4188474SJose.Borrego@Sun.COM /*
4198474SJose.Borrego@Sun.COM  * Build level 2 file information.
4208474SJose.Borrego@Sun.COM  *
4218474SJose.Borrego@Sun.COM  * On success, the caller expects that the info2, fi2 and entries_read
4228474SJose.Borrego@Sun.COM  * fields have been set up.
4238474SJose.Borrego@Sun.COM  */
4248474SJose.Borrego@Sun.COM static DWORD
4258474SJose.Borrego@Sun.COM srvsvc_NetFileEnum2(ndr_xa_t *mxa, struct mslm_NetFileEnum *param)
4268474SJose.Borrego@Sun.COM {
4278474SJose.Borrego@Sun.COM 	struct mslm_NetFileInfoBuf2 *fi2;
4288474SJose.Borrego@Sun.COM 	ndr_pipe_info_t pi;
4298474SJose.Borrego@Sun.COM 	uint32_t entries_read = 0;
4308474SJose.Borrego@Sun.COM 	int i;
4318474SJose.Borrego@Sun.COM 
4328474SJose.Borrego@Sun.COM 	param->info.ru.info2 = NDR_NEW(mxa, struct mslm_NetFileInfo2);
4338474SJose.Borrego@Sun.COM 	if (param->info.ru.info3 == NULL)
4348474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
4358474SJose.Borrego@Sun.COM 
4368474SJose.Borrego@Sun.COM 	fi2 = NDR_NEWN(mxa, struct mslm_NetFileInfoBuf2, 128);
4378474SJose.Borrego@Sun.COM 	if (fi2 == NULL)
4388474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
4398474SJose.Borrego@Sun.COM 
4408474SJose.Borrego@Sun.COM 	param->info.ru.info2->fi2 = fi2;
4418474SJose.Borrego@Sun.COM 
4428474SJose.Borrego@Sun.COM 	for (i = 0; i < 128; ++i) {
4438474SJose.Borrego@Sun.COM 		if (ndr_pipe_getinfo(i, &pi) == -1)
4448474SJose.Borrego@Sun.COM 			continue;
4458474SJose.Borrego@Sun.COM 
4468474SJose.Borrego@Sun.COM 		fi2->fi2_id = pi.npi_fid;
4478474SJose.Borrego@Sun.COM 
4488474SJose.Borrego@Sun.COM 		++entries_read;
4498474SJose.Borrego@Sun.COM 		++fi2;
4508474SJose.Borrego@Sun.COM 	}
4518474SJose.Borrego@Sun.COM 
4528474SJose.Borrego@Sun.COM 	param->info.ru.info2->entries_read = entries_read;
4538474SJose.Borrego@Sun.COM 	param->total_entries = entries_read;
4548474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
4558474SJose.Borrego@Sun.COM }
4568474SJose.Borrego@Sun.COM 
4578474SJose.Borrego@Sun.COM /*
4588474SJose.Borrego@Sun.COM  * Build level 3 file information.
4598474SJose.Borrego@Sun.COM  *
4608474SJose.Borrego@Sun.COM  * On success, the caller expects that the info3, fi3 and entries_read
4618474SJose.Borrego@Sun.COM  * fields have been set up.
4628474SJose.Borrego@Sun.COM  */
4638474SJose.Borrego@Sun.COM static DWORD
4648474SJose.Borrego@Sun.COM srvsvc_NetFileEnum3(ndr_xa_t *mxa, struct mslm_NetFileEnum *param)
4658474SJose.Borrego@Sun.COM {
4668474SJose.Borrego@Sun.COM 	struct mslm_NetFileInfoBuf3 *fi3;
4678474SJose.Borrego@Sun.COM 	ndr_pipe_info_t pi;
4688474SJose.Borrego@Sun.COM 	uint32_t entries_read = 0;
4698474SJose.Borrego@Sun.COM 	int i;
4708474SJose.Borrego@Sun.COM 
4718474SJose.Borrego@Sun.COM 	param->info.ru.info3 = NDR_NEW(mxa, struct mslm_NetFileInfo3);
4728474SJose.Borrego@Sun.COM 	if (param->info.ru.info3 == NULL)
4738474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
4748474SJose.Borrego@Sun.COM 
4758474SJose.Borrego@Sun.COM 	fi3 = NDR_NEWN(mxa, struct mslm_NetFileInfoBuf3, 128);
4768474SJose.Borrego@Sun.COM 	if (fi3 == NULL)
4778474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
4788474SJose.Borrego@Sun.COM 
4798474SJose.Borrego@Sun.COM 	param->info.ru.info3->fi3 = fi3;
4808474SJose.Borrego@Sun.COM 
4818474SJose.Borrego@Sun.COM 	for (i = 0; i < 128; ++i) {
4828474SJose.Borrego@Sun.COM 		if (ndr_pipe_getinfo(i, &pi) == -1)
4838474SJose.Borrego@Sun.COM 			continue;
4848474SJose.Borrego@Sun.COM 
4858474SJose.Borrego@Sun.COM 		fi3->fi3_id = pi.npi_fid;
4868474SJose.Borrego@Sun.COM 		fi3->fi3_permissions = pi.npi_permissions;
4878474SJose.Borrego@Sun.COM 		fi3->fi3_num_locks = pi.npi_num_locks;
4888474SJose.Borrego@Sun.COM 		fi3->fi3_pathname = (uint8_t *)
4898474SJose.Borrego@Sun.COM 		    NDR_STRDUP(mxa, pi.npi_pathname);
4908474SJose.Borrego@Sun.COM 		fi3->fi3_username = (uint8_t *)
4918474SJose.Borrego@Sun.COM 		    NDR_STRDUP(mxa, pi.npi_username);
4928474SJose.Borrego@Sun.COM 
4938474SJose.Borrego@Sun.COM 		++entries_read;
4948474SJose.Borrego@Sun.COM 		++fi3;
4958474SJose.Borrego@Sun.COM 	}
4968474SJose.Borrego@Sun.COM 
4978474SJose.Borrego@Sun.COM 	param->info.ru.info3->entries_read = entries_read;
4988474SJose.Borrego@Sun.COM 	param->total_entries = entries_read;
4998474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
5008474SJose.Borrego@Sun.COM }
5018474SJose.Borrego@Sun.COM 
5028474SJose.Borrego@Sun.COM /*
5038474SJose.Borrego@Sun.COM  * srvsvc_s_NetFileClose
5048474SJose.Borrego@Sun.COM  *
5058474SJose.Borrego@Sun.COM  * NetFileClose forces a file to close. This function can be used when
5068474SJose.Borrego@Sun.COM  * an error prevents closure by any other means.  Use NetFileClose with
5078474SJose.Borrego@Sun.COM  * caution because it does not flush data, cached on a client, to the
5088474SJose.Borrego@Sun.COM  * file before closing the file.
5098474SJose.Borrego@Sun.COM  *
5108474SJose.Borrego@Sun.COM  * Return Values
5118474SJose.Borrego@Sun.COM  * ERROR_SUCCESS            Operation succeeded.
5128474SJose.Borrego@Sun.COM  * ERROR_ACCESS_DENIED      Operation denied.
5138474SJose.Borrego@Sun.COM  * NERR_FileIdNotFound      No open file with the specified id.
5148474SJose.Borrego@Sun.COM  *
5158474SJose.Borrego@Sun.COM  * Note: MSDN suggests that the error code should be ERROR_FILE_NOT_FOUND
5168474SJose.Borrego@Sun.COM  * but network captures using NT show NERR_FileIdNotFound.
5178474SJose.Borrego@Sun.COM  * The NetFileClose2 MSDN page has the right error code.
5188474SJose.Borrego@Sun.COM  */
5198474SJose.Borrego@Sun.COM static int
5208474SJose.Borrego@Sun.COM srvsvc_s_NetFileClose(void *arg, ndr_xa_t *mxa)
5218474SJose.Borrego@Sun.COM {
5228474SJose.Borrego@Sun.COM 	struct mslm_NetFileClose *param = arg;
5238474SJose.Borrego@Sun.COM 
5248474SJose.Borrego@Sun.COM 	if (!ndr_is_admin(mxa)) {
5258474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetFileClose));
5268474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
5278474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
5288474SJose.Borrego@Sun.COM 	}
5298474SJose.Borrego@Sun.COM 
5308474SJose.Borrego@Sun.COM 	bzero(param, sizeof (struct mslm_NetFileClose));
5318474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
5328474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
5338474SJose.Borrego@Sun.COM }
5348474SJose.Borrego@Sun.COM 
5358474SJose.Borrego@Sun.COM 
5368474SJose.Borrego@Sun.COM /*
5378474SJose.Borrego@Sun.COM  * srvsvc_s_NetShareGetInfo
5388474SJose.Borrego@Sun.COM  *
5398474SJose.Borrego@Sun.COM  * Returns Win32 error codes.
5408474SJose.Borrego@Sun.COM  */
5418474SJose.Borrego@Sun.COM static int
5428474SJose.Borrego@Sun.COM srvsvc_s_NetShareGetInfo(void *arg, ndr_xa_t *mxa)
5438474SJose.Borrego@Sun.COM {
5448474SJose.Borrego@Sun.COM 	struct mlsm_NetShareGetInfo *param = arg;
5458474SJose.Borrego@Sun.COM 	struct mslm_NetShareGetInfo0 *info0;
5468474SJose.Borrego@Sun.COM 	struct mslm_NetShareGetInfo1 *info1;
5478474SJose.Borrego@Sun.COM 	struct mslm_NetShareGetInfo2 *info2;
5488474SJose.Borrego@Sun.COM 	struct mslm_NetShareGetInfo501 *info501;
5498474SJose.Borrego@Sun.COM 	struct mslm_NetShareGetInfo502 *info502;
5508474SJose.Borrego@Sun.COM 	struct mslm_NetShareGetInfo1004 *info1004;
5518474SJose.Borrego@Sun.COM 	struct mslm_NetShareGetInfo1005 *info1005;
5528474SJose.Borrego@Sun.COM 	struct mslm_NetShareGetInfo1006 *info1006;
5538474SJose.Borrego@Sun.COM 	smb_share_t si;
5548474SJose.Borrego@Sun.COM 	DWORD status;
5558474SJose.Borrego@Sun.COM 
5568474SJose.Borrego@Sun.COM 	status = smb_shr_get((char *)param->netname, &si);
5578474SJose.Borrego@Sun.COM 	if (status != NERR_Success) {
5588474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mlsm_NetShareGetInfo));
5598474SJose.Borrego@Sun.COM 		param->status = status;
5608474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
5618474SJose.Borrego@Sun.COM 	}
5628474SJose.Borrego@Sun.COM 
5638474SJose.Borrego@Sun.COM 	switch (param->level) {
5648474SJose.Borrego@Sun.COM 	case 0:
5658474SJose.Borrego@Sun.COM 		info0 = NDR_NEW(mxa, struct mslm_NetShareGetInfo0);
5668474SJose.Borrego@Sun.COM 		if (info0 == NULL) {
5678474SJose.Borrego@Sun.COM 			status = ERROR_NOT_ENOUGH_MEMORY;
5688474SJose.Borrego@Sun.COM 			break;
5698474SJose.Borrego@Sun.COM 		}
5708474SJose.Borrego@Sun.COM 
5718474SJose.Borrego@Sun.COM 		info0->shi0_netname
5728474SJose.Borrego@Sun.COM 		    = (uint8_t *)NDR_STRDUP(mxa, si.shr_name);
5738474SJose.Borrego@Sun.COM 		if (info0->shi0_netname == NULL) {
5748474SJose.Borrego@Sun.COM 			status = ERROR_NOT_ENOUGH_MEMORY;
5758474SJose.Borrego@Sun.COM 			break;
5768474SJose.Borrego@Sun.COM 		}
5778474SJose.Borrego@Sun.COM 
5788474SJose.Borrego@Sun.COM 		param->result.ru.info0 = info0;
5798474SJose.Borrego@Sun.COM 		break;
5808474SJose.Borrego@Sun.COM 
5818474SJose.Borrego@Sun.COM 	case 1:
5828474SJose.Borrego@Sun.COM 		info1 = NDR_NEW(mxa, struct mslm_NetShareGetInfo1);
5838474SJose.Borrego@Sun.COM 		if (info1 == NULL) {
5848474SJose.Borrego@Sun.COM 			status = ERROR_NOT_ENOUGH_MEMORY;
5858474SJose.Borrego@Sun.COM 			break;
5868474SJose.Borrego@Sun.COM 		}
5878474SJose.Borrego@Sun.COM 
5888474SJose.Borrego@Sun.COM 		info1->shi1_netname = (uint8_t *)NDR_STRDUP(mxa, si.shr_name);
5898474SJose.Borrego@Sun.COM 		info1->shi1_comment = (uint8_t *)NDR_STRDUP(mxa, si.shr_cmnt);
5908474SJose.Borrego@Sun.COM 		if (info1->shi1_netname == NULL ||
5918474SJose.Borrego@Sun.COM 		    info1->shi1_comment == NULL) {
5928474SJose.Borrego@Sun.COM 			status = ERROR_NOT_ENOUGH_MEMORY;
5938474SJose.Borrego@Sun.COM 			break;
5948474SJose.Borrego@Sun.COM 		}
5958474SJose.Borrego@Sun.COM 
5968474SJose.Borrego@Sun.COM 		info1->shi1_type = si.shr_type;
5978474SJose.Borrego@Sun.COM 		param->result.ru.info1 = info1;
5988474SJose.Borrego@Sun.COM 		break;
5998474SJose.Borrego@Sun.COM 
6008474SJose.Borrego@Sun.COM 	case 2:
6018474SJose.Borrego@Sun.COM 		info2 = NDR_NEW(mxa, struct mslm_NetShareGetInfo2);
6028474SJose.Borrego@Sun.COM 		if (info2 == NULL) {
6038474SJose.Borrego@Sun.COM 			status = ERROR_NOT_ENOUGH_MEMORY;
6048474SJose.Borrego@Sun.COM 			break;
6058474SJose.Borrego@Sun.COM 		}
6068474SJose.Borrego@Sun.COM 
6078474SJose.Borrego@Sun.COM 		info2->shi2_netname = (uint8_t *)NDR_STRDUP(mxa, si.shr_name);
6088474SJose.Borrego@Sun.COM 		info2->shi2_comment = (uint8_t *)NDR_STRDUP(mxa, si.shr_cmnt);
6098474SJose.Borrego@Sun.COM 		if (info2->shi2_netname == NULL ||
6108474SJose.Borrego@Sun.COM 		    info2->shi2_comment == NULL) {
6118474SJose.Borrego@Sun.COM 			status = ERROR_NOT_ENOUGH_MEMORY;
6128474SJose.Borrego@Sun.COM 			break;
6138474SJose.Borrego@Sun.COM 		}
6148474SJose.Borrego@Sun.COM 
6158474SJose.Borrego@Sun.COM 		info2->shi2_path =
6168474SJose.Borrego@Sun.COM 		    (uint8_t *)srvsvc_share_mkpath(mxa, si.shr_path);
6178474SJose.Borrego@Sun.COM 		info2->shi2_passwd = 0;
6188474SJose.Borrego@Sun.COM 		info2->shi2_type = si.shr_type;
6198474SJose.Borrego@Sun.COM 		info2->shi2_permissions = 0;
6208474SJose.Borrego@Sun.COM 		info2->shi2_max_uses = SHI_USES_UNLIMITED;
6218474SJose.Borrego@Sun.COM 		info2->shi2_current_uses = 0;
6228474SJose.Borrego@Sun.COM 		param->result.ru.info2 = info2;
6238474SJose.Borrego@Sun.COM 		break;
6248474SJose.Borrego@Sun.COM 
6258474SJose.Borrego@Sun.COM 	case 1004:
6268474SJose.Borrego@Sun.COM 		info1004 = NDR_NEW(mxa, struct mslm_NetShareGetInfo1004);
6278474SJose.Borrego@Sun.COM 		if (info1004 == NULL) {
6288474SJose.Borrego@Sun.COM 			status = ERROR_NOT_ENOUGH_MEMORY;
6298474SJose.Borrego@Sun.COM 			break;
6308474SJose.Borrego@Sun.COM 		}
6318474SJose.Borrego@Sun.COM 
6328474SJose.Borrego@Sun.COM 		info1004->shi1004_comment =
6338474SJose.Borrego@Sun.COM 		    (uint8_t *)NDR_STRDUP(mxa, si.shr_cmnt);
6348474SJose.Borrego@Sun.COM 		if (info1004->shi1004_comment == NULL)
6358474SJose.Borrego@Sun.COM 			status = ERROR_NOT_ENOUGH_MEMORY;
6368474SJose.Borrego@Sun.COM 		break;
6378474SJose.Borrego@Sun.COM 
6388474SJose.Borrego@Sun.COM 	case 1005:
6398474SJose.Borrego@Sun.COM 		info1005 = NDR_NEW(mxa, struct mslm_NetShareGetInfo1005);
6408474SJose.Borrego@Sun.COM 		if (info1005 == NULL) {
6418474SJose.Borrego@Sun.COM 			status = ERROR_NOT_ENOUGH_MEMORY;
6428474SJose.Borrego@Sun.COM 			break;
6438474SJose.Borrego@Sun.COM 		}
6448474SJose.Borrego@Sun.COM 
6458474SJose.Borrego@Sun.COM 		info1005->shi1005_flags = 0;
6468474SJose.Borrego@Sun.COM 
6478474SJose.Borrego@Sun.COM 		switch (si.shr_flags & SMB_SHRF_CSC_MASK) {
6488474SJose.Borrego@Sun.COM 		case SMB_SHRF_CSC_DISABLED:
6498474SJose.Borrego@Sun.COM 			info1005->shi1005_flags |= CSC_CACHE_NONE;
6508474SJose.Borrego@Sun.COM 			break;
6518474SJose.Borrego@Sun.COM 		case SMB_SHRF_CSC_AUTO:
6528474SJose.Borrego@Sun.COM 			info1005->shi1005_flags |= CSC_CACHE_AUTO_REINT;
6538474SJose.Borrego@Sun.COM 			break;
6548474SJose.Borrego@Sun.COM 		case SMB_SHRF_CSC_VDO:
6558474SJose.Borrego@Sun.COM 			info1005->shi1005_flags |= CSC_CACHE_VDO;
6568474SJose.Borrego@Sun.COM 			break;
6578474SJose.Borrego@Sun.COM 		case SMB_SHRF_CSC_MANUAL:
6588474SJose.Borrego@Sun.COM 		default:
6598474SJose.Borrego@Sun.COM 			/*
6608474SJose.Borrego@Sun.COM 			 * Default to CSC_CACHE_MANUAL_REINT.
6618474SJose.Borrego@Sun.COM 			 */
6628474SJose.Borrego@Sun.COM 			break;
6638474SJose.Borrego@Sun.COM 		}
6648474SJose.Borrego@Sun.COM 
6658474SJose.Borrego@Sun.COM 		param->result.ru.info1005 = info1005;
6668474SJose.Borrego@Sun.COM 		break;
6678474SJose.Borrego@Sun.COM 
6688474SJose.Borrego@Sun.COM 	case 1006:
6698474SJose.Borrego@Sun.COM 		info1006 = NDR_NEW(mxa, struct mslm_NetShareGetInfo1006);
6708474SJose.Borrego@Sun.COM 		if (info1006 == NULL) {
6718474SJose.Borrego@Sun.COM 			status = ERROR_NOT_ENOUGH_MEMORY;
6728474SJose.Borrego@Sun.COM 			break;
6738474SJose.Borrego@Sun.COM 		}
6748474SJose.Borrego@Sun.COM 		info1006->shi1006_max_uses = SHI_USES_UNLIMITED;
6758474SJose.Borrego@Sun.COM 		param->result.ru.info1006 = info1006;
6768474SJose.Borrego@Sun.COM 		break;
6778474SJose.Borrego@Sun.COM 
6788474SJose.Borrego@Sun.COM 	case 501:
6798474SJose.Borrego@Sun.COM 		/*
6808474SJose.Borrego@Sun.COM 		 * Level 501 provides level 1 information.
6818474SJose.Borrego@Sun.COM 		 */
6828474SJose.Borrego@Sun.COM 		info501 = NDR_NEW(mxa, struct mslm_NetShareGetInfo501);
6838474SJose.Borrego@Sun.COM 		if (info501 == NULL) {
6848474SJose.Borrego@Sun.COM 			status = ERROR_NOT_ENOUGH_MEMORY;
6858474SJose.Borrego@Sun.COM 			break;
6868474SJose.Borrego@Sun.COM 		}
6878474SJose.Borrego@Sun.COM 
6888474SJose.Borrego@Sun.COM 		info501->shi501_netname =
6898474SJose.Borrego@Sun.COM 		    (uint8_t *)NDR_STRDUP(mxa, si.shr_name);
6908474SJose.Borrego@Sun.COM 		info501->shi501_comment =
6918474SJose.Borrego@Sun.COM 		    (uint8_t *)NDR_STRDUP(mxa, si.shr_cmnt);
6928474SJose.Borrego@Sun.COM 		if (info501->shi501_netname == NULL ||
6938474SJose.Borrego@Sun.COM 		    info501->shi501_comment == NULL) {
6948474SJose.Borrego@Sun.COM 			status = ERROR_NOT_ENOUGH_MEMORY;
6958474SJose.Borrego@Sun.COM 			break;
6968474SJose.Borrego@Sun.COM 		}
6978474SJose.Borrego@Sun.COM 
6988474SJose.Borrego@Sun.COM 		info501->shi501_type = si.shr_type;
6998474SJose.Borrego@Sun.COM 		info501->shi501_reserved = 0;
7008474SJose.Borrego@Sun.COM 		param->result.ru.info501 = info501;
7018474SJose.Borrego@Sun.COM 		break;
7028474SJose.Borrego@Sun.COM 
7038474SJose.Borrego@Sun.COM 	case 502:
7048474SJose.Borrego@Sun.COM 		/*
7058474SJose.Borrego@Sun.COM 		 * Level 502 provides level 2 information plus a
7068474SJose.Borrego@Sun.COM 		 * security descriptor. We don't support security
7078474SJose.Borrego@Sun.COM 		 * descriptors on shares yet.
7088474SJose.Borrego@Sun.COM 		 */
7098474SJose.Borrego@Sun.COM 		info502 = NDR_NEW(mxa, struct mslm_NetShareGetInfo502);
7108474SJose.Borrego@Sun.COM 		if (info502 == NULL) {
7118474SJose.Borrego@Sun.COM 			status = ERROR_NOT_ENOUGH_MEMORY;
7128474SJose.Borrego@Sun.COM 			break;
7138474SJose.Borrego@Sun.COM 		}
7148474SJose.Borrego@Sun.COM 
7158474SJose.Borrego@Sun.COM 		info502->shi502_netname =
7168474SJose.Borrego@Sun.COM 		    (uint8_t *)NDR_STRDUP(mxa, si.shr_name);
7178474SJose.Borrego@Sun.COM 		info502->shi502_comment =
7188474SJose.Borrego@Sun.COM 		    (uint8_t *)NDR_STRDUP(mxa, si.shr_cmnt);
7198474SJose.Borrego@Sun.COM 		if (info502->shi502_netname == NULL ||
7208474SJose.Borrego@Sun.COM 		    info502->shi502_comment == NULL) {
7218474SJose.Borrego@Sun.COM 			status = ERROR_NOT_ENOUGH_MEMORY;
7228474SJose.Borrego@Sun.COM 			break;
7238474SJose.Borrego@Sun.COM 		}
7248474SJose.Borrego@Sun.COM 
7258474SJose.Borrego@Sun.COM 		info502->shi502_path =
7268474SJose.Borrego@Sun.COM 		    (uint8_t *)srvsvc_share_mkpath(mxa, si.shr_path);
7278474SJose.Borrego@Sun.COM 		info502->shi502_passwd = 0;
7288474SJose.Borrego@Sun.COM 		info502->shi502_type = si.shr_type;
7298474SJose.Borrego@Sun.COM 		info502->shi502_permissions = 0;
7308474SJose.Borrego@Sun.COM 		info502->shi502_max_uses = SHI_USES_UNLIMITED;
7318474SJose.Borrego@Sun.COM 		info502->shi502_current_uses = 0;
7328474SJose.Borrego@Sun.COM 		info502->shi502_reserved = 0;
7338474SJose.Borrego@Sun.COM 		info502->shi502_security_descriptor = 0;
7348474SJose.Borrego@Sun.COM 		param->result.ru.info502 = info502;
7358474SJose.Borrego@Sun.COM 		break;
7368474SJose.Borrego@Sun.COM 
7378474SJose.Borrego@Sun.COM 	default:
7388474SJose.Borrego@Sun.COM 		status = ERROR_ACCESS_DENIED;
7398474SJose.Borrego@Sun.COM 		break;
7408474SJose.Borrego@Sun.COM 	}
7418474SJose.Borrego@Sun.COM 
7428474SJose.Borrego@Sun.COM 	if (status != ERROR_SUCCESS)
7438474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mlsm_NetShareGetInfo));
7448474SJose.Borrego@Sun.COM 	else
7458474SJose.Borrego@Sun.COM 		param->result.switch_value = param->level;
7468474SJose.Borrego@Sun.COM 
7478474SJose.Borrego@Sun.COM 	param->status = status;
7488474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
7498474SJose.Borrego@Sun.COM }
7508474SJose.Borrego@Sun.COM 
7518474SJose.Borrego@Sun.COM 
7528474SJose.Borrego@Sun.COM /*
7538474SJose.Borrego@Sun.COM  * srvsvc_s_NetShareSetInfo
7548474SJose.Borrego@Sun.COM  *
7558474SJose.Borrego@Sun.COM  * This call is made by SrvMgr to set share information.
7568474SJose.Borrego@Sun.COM  * Always returns ERROR_ACCESS_DENIED for now.
7578474SJose.Borrego@Sun.COM  *
7588474SJose.Borrego@Sun.COM  * Returns Win32 error codes.
7598474SJose.Borrego@Sun.COM  */
7608474SJose.Borrego@Sun.COM static int
7618474SJose.Borrego@Sun.COM srvsvc_s_NetShareSetInfo(void *arg, ndr_xa_t *mxa)
7628474SJose.Borrego@Sun.COM {
7638474SJose.Borrego@Sun.COM 	struct mlsm_NetShareSetInfo *param = arg;
7648474SJose.Borrego@Sun.COM 
7658474SJose.Borrego@Sun.COM 	(void) memset(param, 0, sizeof (struct mlsm_NetShareSetInfo));
7668474SJose.Borrego@Sun.COM 	param->parm_err_ptr = (DWORD)(uintptr_t)NDR_MALLOC(mxa,
7678474SJose.Borrego@Sun.COM 	    sizeof (DWORD));
7688474SJose.Borrego@Sun.COM 	param->parm_err = 0;
7698474SJose.Borrego@Sun.COM 
7708474SJose.Borrego@Sun.COM 	if (!smb_config_getbool(SMB_CI_SRVSVC_SHRSET_ENABLE))
7718474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
7728474SJose.Borrego@Sun.COM 	else
7738474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
7748474SJose.Borrego@Sun.COM 
7758474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
7768474SJose.Borrego@Sun.COM }
7778474SJose.Borrego@Sun.COM 
7788474SJose.Borrego@Sun.COM /*
7798474SJose.Borrego@Sun.COM  * srvsvc_s_NetSessionEnum
7808474SJose.Borrego@Sun.COM  *
7818474SJose.Borrego@Sun.COM  * Level 1 request is made by (Server Manager (srvmgr) on NT Server when
7828474SJose.Borrego@Sun.COM  * the user info icon is selected.
7838474SJose.Borrego@Sun.COM  *
7848474SJose.Borrego@Sun.COM  * On success, the return value is NERR_Success.
7858474SJose.Borrego@Sun.COM  * On error, the return value can be one of the following error codes:
7868474SJose.Borrego@Sun.COM  *
7878474SJose.Borrego@Sun.COM  * ERROR_ACCESS_DENIED      The user does not have access to the requested
7888474SJose.Borrego@Sun.COM  *                          information.
7898474SJose.Borrego@Sun.COM  * ERROR_INVALID_LEVEL      The value specified for the level is invalid.
7908474SJose.Borrego@Sun.COM  * ERROR_INVALID_PARAMETER  The specified parameter is invalid.
7918474SJose.Borrego@Sun.COM  * ERROR_MORE_DATA          More entries are available. Specify a large
7928474SJose.Borrego@Sun.COM  *                          enough buffer to receive all entries.
7938474SJose.Borrego@Sun.COM  * ERROR_NOT_ENOUGH_MEMORY  Insufficient memory is available.
7948474SJose.Borrego@Sun.COM  * NERR_ClientNameNotFound  A session does not exist with the computer name.
7958474SJose.Borrego@Sun.COM  * NERR_InvalidComputer     The computer name is invalid.
7968474SJose.Borrego@Sun.COM  * NERR_UserNotFound        The user name could not be found.
7978474SJose.Borrego@Sun.COM  */
7988474SJose.Borrego@Sun.COM static int
7998474SJose.Borrego@Sun.COM srvsvc_s_NetSessionEnum(void *arg, ndr_xa_t *mxa)
8008474SJose.Borrego@Sun.COM {
8018474SJose.Borrego@Sun.COM 	struct mslm_NetSessionEnum *param = arg;
8028474SJose.Borrego@Sun.COM 	struct mslm_infonres *infonres;
8038474SJose.Borrego@Sun.COM 	DWORD status;
8048474SJose.Borrego@Sun.COM 	DWORD n_sessions;
8058474SJose.Borrego@Sun.COM 
8068474SJose.Borrego@Sun.COM 	infonres = NDR_NEW(mxa, struct mslm_infonres);
8078474SJose.Borrego@Sun.COM 	if (infonres == NULL) {
8088474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetSessionEnum));
8098474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
8108474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8118474SJose.Borrego@Sun.COM 	}
8128474SJose.Borrego@Sun.COM 
8138474SJose.Borrego@Sun.COM 	infonres->entriesread = 0;
8148474SJose.Borrego@Sun.COM 	infonres->entries = NULL;
8158474SJose.Borrego@Sun.COM 	param->result.level = param->level;
8168474SJose.Borrego@Sun.COM 	param->result.bufptr.p = infonres;
8178474SJose.Borrego@Sun.COM 	param->total_entries = 0;
8188474SJose.Borrego@Sun.COM 	param->resume_handle = NULL;
8198474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
8208474SJose.Borrego@Sun.COM 
8218474SJose.Borrego@Sun.COM 	if ((n_sessions = (DWORD) mlsvc_get_num_users()) == 0)
8228474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8238474SJose.Borrego@Sun.COM 
8248474SJose.Borrego@Sun.COM 	switch (param->level) {
8258474SJose.Borrego@Sun.COM 	case 0:
8268474SJose.Borrego@Sun.COM 		status = mlsvc_NetSessionEnumLevel0(infonres, n_sessions, mxa);
8278474SJose.Borrego@Sun.COM 		break;
8288474SJose.Borrego@Sun.COM 
8298474SJose.Borrego@Sun.COM 	case 1:
8308474SJose.Borrego@Sun.COM 		status = mlsvc_NetSessionEnumLevel1(infonres, n_sessions, mxa);
8318474SJose.Borrego@Sun.COM 		break;
8328474SJose.Borrego@Sun.COM 
8338474SJose.Borrego@Sun.COM 	default:
8348474SJose.Borrego@Sun.COM 		status = ERROR_INVALID_LEVEL;
8358474SJose.Borrego@Sun.COM 		break;
8368474SJose.Borrego@Sun.COM 	}
8378474SJose.Borrego@Sun.COM 
8388474SJose.Borrego@Sun.COM 	if (status != 0) {
8398474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetSessionEnum));
8408474SJose.Borrego@Sun.COM 		param->status = status;
8418474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8428474SJose.Borrego@Sun.COM 	}
8438474SJose.Borrego@Sun.COM 
8448474SJose.Borrego@Sun.COM 	param->total_entries = infonres->entriesread;
8458474SJose.Borrego@Sun.COM 	param->status = status;
8468474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
8478474SJose.Borrego@Sun.COM }
8488474SJose.Borrego@Sun.COM 
8498474SJose.Borrego@Sun.COM /*
8508474SJose.Borrego@Sun.COM  * mlsvc_NetSessionEnumLevel0
8518474SJose.Borrego@Sun.COM  *
8528474SJose.Borrego@Sun.COM  * Build the level 0 session information.
8538474SJose.Borrego@Sun.COM  */
8548474SJose.Borrego@Sun.COM static DWORD
8558474SJose.Borrego@Sun.COM mlsvc_NetSessionEnumLevel0(struct mslm_infonres *infonres, DWORD n_sessions,
8568474SJose.Borrego@Sun.COM     ndr_xa_t *mxa)
8578474SJose.Borrego@Sun.COM {
8588474SJose.Borrego@Sun.COM 	struct mslm_SESSION_INFO_0 *info0;
8598474SJose.Borrego@Sun.COM 	smb_dr_ulist_t *ulist;
8608474SJose.Borrego@Sun.COM 	smb_opipe_context_t *user;
8618474SJose.Borrego@Sun.COM 	char *workstation;
862*8670SJose.Borrego@Sun.COM 	char ipaddr_buf[INET6_ADDRSTRLEN];
8638474SJose.Borrego@Sun.COM 	int n_users;
8648474SJose.Borrego@Sun.COM 	int offset = 0;
8658474SJose.Borrego@Sun.COM 	int i;
8668474SJose.Borrego@Sun.COM 
8678474SJose.Borrego@Sun.COM 	if ((ulist = malloc(sizeof (smb_dr_ulist_t))) == NULL)
8688474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
8698474SJose.Borrego@Sun.COM 
8708474SJose.Borrego@Sun.COM 	if ((n_users = mlsvc_get_user_list(offset, ulist)) == 0) {
8718474SJose.Borrego@Sun.COM 		smb_dr_ulist_free(ulist);
8728474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
8738474SJose.Borrego@Sun.COM 	}
8748474SJose.Borrego@Sun.COM 
8758474SJose.Borrego@Sun.COM 	if (n_users < n_sessions)
8768474SJose.Borrego@Sun.COM 		n_sessions = n_users;
8778474SJose.Borrego@Sun.COM 
8788474SJose.Borrego@Sun.COM 	info0 = NDR_NEWN(mxa, struct mslm_SESSION_INFO_0, n_sessions);
8798474SJose.Borrego@Sun.COM 	if (info0 == NULL) {
8808474SJose.Borrego@Sun.COM 		smb_dr_ulist_free(ulist);
8818474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
8828474SJose.Borrego@Sun.COM 	}
8838474SJose.Borrego@Sun.COM 
8848474SJose.Borrego@Sun.COM 	for (i = 0; i < n_sessions; ++i) {
8858474SJose.Borrego@Sun.COM 		user = &ulist->dul_users[i];
8868474SJose.Borrego@Sun.COM 
8878474SJose.Borrego@Sun.COM 		workstation = user->oc_workstation;
8888474SJose.Borrego@Sun.COM 		if (workstation == NULL || *workstation == '\0') {
889*8670SJose.Borrego@Sun.COM 			(void) smb_inet_ntop(&user->oc_ipaddr,
890*8670SJose.Borrego@Sun.COM 			    ipaddr_buf, SMB_IPSTRLEN(user->oc_ipaddr.a_family));
8918474SJose.Borrego@Sun.COM 			workstation = ipaddr_buf;
8928474SJose.Borrego@Sun.COM 		}
8938474SJose.Borrego@Sun.COM 
8948474SJose.Borrego@Sun.COM 		info0[i].sesi0_cname = NDR_STRDUP(mxa, workstation);
8958474SJose.Borrego@Sun.COM 		if (info0[i].sesi0_cname == NULL) {
8968474SJose.Borrego@Sun.COM 			smb_dr_ulist_free(ulist);
8978474SJose.Borrego@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
8988474SJose.Borrego@Sun.COM 		}
8998474SJose.Borrego@Sun.COM 	}
9008474SJose.Borrego@Sun.COM 
9018474SJose.Borrego@Sun.COM 	smb_dr_ulist_free(ulist);
9028474SJose.Borrego@Sun.COM 	infonres->entriesread = n_sessions;
9038474SJose.Borrego@Sun.COM 	infonres->entries = info0;
9048474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
9058474SJose.Borrego@Sun.COM }
9068474SJose.Borrego@Sun.COM 
9078474SJose.Borrego@Sun.COM /*
9088474SJose.Borrego@Sun.COM  * mlsvc_NetSessionEnumLevel1
9098474SJose.Borrego@Sun.COM  *
9108474SJose.Borrego@Sun.COM  * Build the level 1 session information.
9118474SJose.Borrego@Sun.COM  */
9128474SJose.Borrego@Sun.COM static DWORD
9138474SJose.Borrego@Sun.COM mlsvc_NetSessionEnumLevel1(struct mslm_infonres *infonres, DWORD n_sessions,
9148474SJose.Borrego@Sun.COM     ndr_xa_t *mxa)
9158474SJose.Borrego@Sun.COM {
9168474SJose.Borrego@Sun.COM 	struct mslm_SESSION_INFO_1 *info1;
9178474SJose.Borrego@Sun.COM 	smb_dr_ulist_t *ulist;
9188474SJose.Borrego@Sun.COM 	smb_opipe_context_t *user;
9198474SJose.Borrego@Sun.COM 	char *workstation;
9208474SJose.Borrego@Sun.COM 	char account[MAXNAMELEN];
921*8670SJose.Borrego@Sun.COM 	char ipaddr_buf[INET6_ADDRSTRLEN];
9228474SJose.Borrego@Sun.COM 	int n_users;
9238474SJose.Borrego@Sun.COM 	int offset = 0;
9248474SJose.Borrego@Sun.COM 	int i;
9258474SJose.Borrego@Sun.COM 
9268474SJose.Borrego@Sun.COM 	if ((ulist = malloc(sizeof (smb_dr_ulist_t))) == NULL)
9278474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
9288474SJose.Borrego@Sun.COM 
9298474SJose.Borrego@Sun.COM 	if ((n_users = mlsvc_get_user_list(offset, ulist)) == 0) {
9308474SJose.Borrego@Sun.COM 		smb_dr_ulist_free(ulist);
9318474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
9328474SJose.Borrego@Sun.COM 	}
9338474SJose.Borrego@Sun.COM 
9348474SJose.Borrego@Sun.COM 	if (n_users < n_sessions)
9358474SJose.Borrego@Sun.COM 		n_sessions = n_users;
9368474SJose.Borrego@Sun.COM 
9378474SJose.Borrego@Sun.COM 	info1 = NDR_NEWN(mxa, struct mslm_SESSION_INFO_1, n_sessions);
9388474SJose.Borrego@Sun.COM 	if (info1 == NULL) {
9398474SJose.Borrego@Sun.COM 		smb_dr_ulist_free(ulist);
9408474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
9418474SJose.Borrego@Sun.COM 	}
9428474SJose.Borrego@Sun.COM 
9438474SJose.Borrego@Sun.COM 	for (i = 0; i < n_sessions; ++i) {
9448474SJose.Borrego@Sun.COM 		user = &ulist->dul_users[i];
9458474SJose.Borrego@Sun.COM 
9468474SJose.Borrego@Sun.COM 		workstation = user->oc_workstation;
9478474SJose.Borrego@Sun.COM 		if (workstation == NULL || *workstation == '\0') {
948*8670SJose.Borrego@Sun.COM 			(void) smb_inet_ntop(&user->oc_ipaddr,
949*8670SJose.Borrego@Sun.COM 			    ipaddr_buf, SMB_IPSTRLEN(user->oc_ipaddr.a_family));
9508474SJose.Borrego@Sun.COM 			workstation = ipaddr_buf;
9518474SJose.Borrego@Sun.COM 		}
9528474SJose.Borrego@Sun.COM 
9538474SJose.Borrego@Sun.COM 		(void) snprintf(account, MAXNAMELEN, "%s\\%s",
9548474SJose.Borrego@Sun.COM 		    user->oc_domain, user->oc_account);
9558474SJose.Borrego@Sun.COM 
9568474SJose.Borrego@Sun.COM 		info1[i].sesi1_cname = NDR_STRDUP(mxa, workstation);
9578474SJose.Borrego@Sun.COM 		info1[i].sesi1_uname = NDR_STRDUP(mxa, account);
9588474SJose.Borrego@Sun.COM 
9598474SJose.Borrego@Sun.COM 		if (info1[i].sesi1_cname == NULL ||
9608474SJose.Borrego@Sun.COM 		    info1[i].sesi1_uname == NULL) {
9618474SJose.Borrego@Sun.COM 			smb_dr_ulist_free(ulist);
9628474SJose.Borrego@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
9638474SJose.Borrego@Sun.COM 		}
9648474SJose.Borrego@Sun.COM 
9658474SJose.Borrego@Sun.COM 		info1[i].sesi1_nopens = 1;
9668474SJose.Borrego@Sun.COM 		info1[i].sesi1_time = time(0) - user->oc_logon_time;
9678474SJose.Borrego@Sun.COM 		info1[i].sesi1_itime = 0;
9688474SJose.Borrego@Sun.COM 		info1[i].sesi1_uflags =
9698474SJose.Borrego@Sun.COM 		    (user->oc_flags & SMB_ATF_GUEST) ? SESS_GUEST : 0;
9708474SJose.Borrego@Sun.COM 	}
9718474SJose.Borrego@Sun.COM 
9728474SJose.Borrego@Sun.COM 	smb_dr_ulist_free(ulist);
9738474SJose.Borrego@Sun.COM 	infonres->entriesread = n_sessions;
9748474SJose.Borrego@Sun.COM 	infonres->entries = info1;
9758474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
9768474SJose.Borrego@Sun.COM }
9778474SJose.Borrego@Sun.COM 
9788474SJose.Borrego@Sun.COM /*
9798474SJose.Borrego@Sun.COM  * srvsvc_s_NetSessionDel
9808474SJose.Borrego@Sun.COM  *
9818474SJose.Borrego@Sun.COM  * Ends a network session between a server and a workstation.
9828474SJose.Borrego@Sun.COM  * On NT only members of the Administrators or Account Operators
9838474SJose.Borrego@Sun.COM  * local groups are permitted to use NetSessionDel.
9848474SJose.Borrego@Sun.COM  *
9858474SJose.Borrego@Sun.COM  * Return Values
9868474SJose.Borrego@Sun.COM  * If the function succeeds, the return value is NERR_Success/
9878474SJose.Borrego@Sun.COM  * ERROR_SUCCESS. If the function fails, the return value can be
9888474SJose.Borrego@Sun.COM  * one of the following error codes:
9898474SJose.Borrego@Sun.COM  *
9908474SJose.Borrego@Sun.COM  * ERROR_ACCESS_DENIED 		The user does not have access to the
9918474SJose.Borrego@Sun.COM  * 							requested information.
9928474SJose.Borrego@Sun.COM  * ERROR_INVALID_PARAMETER	The specified parameter is invalid.
9938474SJose.Borrego@Sun.COM  * ERROR_NOT_ENOUGH_MEMORY	Insufficient memory is available.
9948474SJose.Borrego@Sun.COM  * NERR_ClientNameNotFound	A session does not exist with that
9958474SJose.Borrego@Sun.COM  *                          computer name.
9968474SJose.Borrego@Sun.COM  */
9978474SJose.Borrego@Sun.COM static int
9988474SJose.Borrego@Sun.COM srvsvc_s_NetSessionDel(void *arg, ndr_xa_t *mxa)
9998474SJose.Borrego@Sun.COM {
10008474SJose.Borrego@Sun.COM 	struct mslm_NetSessionDel *param = arg;
10018474SJose.Borrego@Sun.COM 
10028474SJose.Borrego@Sun.COM 	if (!ndr_is_poweruser(mxa)) {
10038474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
10048474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
10058474SJose.Borrego@Sun.COM 	}
10068474SJose.Borrego@Sun.COM 
10078474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
10088474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
10098474SJose.Borrego@Sun.COM }
10108474SJose.Borrego@Sun.COM 
10118474SJose.Borrego@Sun.COM /*
10128474SJose.Borrego@Sun.COM  * SRVSVC NetServerGetInfo
10138474SJose.Borrego@Sun.COM  *
10148474SJose.Borrego@Sun.COM  *	IN	LPTSTR servername,
10158474SJose.Borrego@Sun.COM  *	IN	DWORD level,
10168474SJose.Borrego@Sun.COM  *	OUT	union switch(level) {
10178474SJose.Borrego@Sun.COM  *		case 100:	mslm_SERVER_INFO_100 *p100;
10188474SJose.Borrego@Sun.COM  *		case 101:	mslm_SERVER_INFO_101 *p101;
10198474SJose.Borrego@Sun.COM  *		case 102:	mslm_SERVER_INFO_102 *p102;
10208474SJose.Borrego@Sun.COM  *		default:	char *nullptr;
10218474SJose.Borrego@Sun.COM  *		} bufptr,
10228474SJose.Borrego@Sun.COM  *	OUT	DWORD status
10238474SJose.Borrego@Sun.COM  */
10248474SJose.Borrego@Sun.COM static int
10258474SJose.Borrego@Sun.COM srvsvc_s_NetServerGetInfo(void *arg, ndr_xa_t *mxa)
10268474SJose.Borrego@Sun.COM {
10278474SJose.Borrego@Sun.COM 	struct mslm_NetServerGetInfo *param = arg;
10288474SJose.Borrego@Sun.COM 	struct mslm_SERVER_INFO_100 *info100;
10298474SJose.Borrego@Sun.COM 	struct mslm_SERVER_INFO_101 *info101;
10308474SJose.Borrego@Sun.COM 	struct mslm_SERVER_INFO_102 *info102;
10318474SJose.Borrego@Sun.COM 	char sys_comment[SMB_PI_MAX_COMMENT];
10328474SJose.Borrego@Sun.COM 	char hostname[NETBIOS_NAME_SZ];
10338474SJose.Borrego@Sun.COM 
10348474SJose.Borrego@Sun.COM 	if (smb_getnetbiosname(hostname, sizeof (hostname)) != 0) {
10358474SJose.Borrego@Sun.COM netservergetinfo_no_memory:
10368474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetServerGetInfo));
10378474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
10388474SJose.Borrego@Sun.COM 	}
10398474SJose.Borrego@Sun.COM 
10408474SJose.Borrego@Sun.COM 	(void) smb_config_getstr(SMB_CI_SYS_CMNT, sys_comment,
10418474SJose.Borrego@Sun.COM 	    sizeof (sys_comment));
10428474SJose.Borrego@Sun.COM 	if (*sys_comment == '\0')
10438474SJose.Borrego@Sun.COM 		(void) strcpy(sys_comment, " ");
10448474SJose.Borrego@Sun.COM 
10458474SJose.Borrego@Sun.COM 	switch (param->level) {
10468474SJose.Borrego@Sun.COM 	case 100:
10478474SJose.Borrego@Sun.COM 		info100 = NDR_NEW(mxa, struct mslm_SERVER_INFO_100);
10488474SJose.Borrego@Sun.COM 		if (info100 == NULL)
10498474SJose.Borrego@Sun.COM 			goto netservergetinfo_no_memory;
10508474SJose.Borrego@Sun.COM 
10518474SJose.Borrego@Sun.COM 		bzero(info100, sizeof (struct mslm_SERVER_INFO_100));
10528474SJose.Borrego@Sun.COM 		info100->sv100_platform_id = SV_PLATFORM_ID_NT;
10538474SJose.Borrego@Sun.COM 		info100->sv100_name = (uint8_t *)NDR_STRDUP(mxa, hostname);
10548474SJose.Borrego@Sun.COM 		if (info100->sv100_name == NULL)
10558474SJose.Borrego@Sun.COM 			goto netservergetinfo_no_memory;
10568474SJose.Borrego@Sun.COM 
10578474SJose.Borrego@Sun.COM 		param->result.bufptr.bufptr100 = info100;
10588474SJose.Borrego@Sun.COM 		break;
10598474SJose.Borrego@Sun.COM 
10608474SJose.Borrego@Sun.COM 	case 101:
10618474SJose.Borrego@Sun.COM 		info101 = NDR_NEW(mxa, struct mslm_SERVER_INFO_101);
10628474SJose.Borrego@Sun.COM 		if (info101 == NULL)
10638474SJose.Borrego@Sun.COM 			goto netservergetinfo_no_memory;
10648474SJose.Borrego@Sun.COM 
10658474SJose.Borrego@Sun.COM 		bzero(info101, sizeof (struct mslm_SERVER_INFO_101));
10668474SJose.Borrego@Sun.COM 		info101->sv101_platform_id = SV_PLATFORM_ID_NT;
10678474SJose.Borrego@Sun.COM 		info101->sv101_version_major = 4;
10688474SJose.Borrego@Sun.COM 		info101->sv101_version_minor = 0;
10698474SJose.Borrego@Sun.COM 		info101->sv101_type = SV_TYPE_SENT_BY_ME;
10708474SJose.Borrego@Sun.COM 		info101->sv101_name = (uint8_t *)NDR_STRDUP(mxa, hostname);
10718474SJose.Borrego@Sun.COM 		info101->sv101_comment
10728474SJose.Borrego@Sun.COM 		    = (uint8_t *)NDR_STRDUP(mxa, sys_comment);
10738474SJose.Borrego@Sun.COM 
10748474SJose.Borrego@Sun.COM 		if (info101->sv101_name == NULL ||
10758474SJose.Borrego@Sun.COM 		    info101->sv101_comment == NULL)
10768474SJose.Borrego@Sun.COM 			goto netservergetinfo_no_memory;
10778474SJose.Borrego@Sun.COM 
10788474SJose.Borrego@Sun.COM 		param->result.bufptr.bufptr101 = info101;
10798474SJose.Borrego@Sun.COM 		break;
10808474SJose.Borrego@Sun.COM 
10818474SJose.Borrego@Sun.COM 	case 102:
10828474SJose.Borrego@Sun.COM 		info102 = NDR_NEW(mxa, struct mslm_SERVER_INFO_102);
10838474SJose.Borrego@Sun.COM 		if (info102 == NULL)
10848474SJose.Borrego@Sun.COM 			goto netservergetinfo_no_memory;
10858474SJose.Borrego@Sun.COM 
10868474SJose.Borrego@Sun.COM 		bzero(info102, sizeof (struct mslm_SERVER_INFO_102));
10878474SJose.Borrego@Sun.COM 		info102->sv102_platform_id = SV_PLATFORM_ID_NT;
10888474SJose.Borrego@Sun.COM 		info102->sv102_version_major = 4;
10898474SJose.Borrego@Sun.COM 		info102->sv102_version_minor = 0;
10908474SJose.Borrego@Sun.COM 		info102->sv102_type = SV_TYPE_SENT_BY_ME;
10918474SJose.Borrego@Sun.COM 		info102->sv102_name = (uint8_t *)NDR_STRDUP(mxa, hostname);
10928474SJose.Borrego@Sun.COM 		info102->sv102_comment
10938474SJose.Borrego@Sun.COM 		    = (uint8_t *)NDR_STRDUP(mxa, sys_comment);
10948474SJose.Borrego@Sun.COM 
10958474SJose.Borrego@Sun.COM 		/*
10968474SJose.Borrego@Sun.COM 		 * The following level 102 fields are defaulted to zero
10978474SJose.Borrego@Sun.COM 		 * by virtue of the call to bzero above.
10988474SJose.Borrego@Sun.COM 		 *
10998474SJose.Borrego@Sun.COM 		 * sv102_users
11008474SJose.Borrego@Sun.COM 		 * sv102_disc
11018474SJose.Borrego@Sun.COM 		 * sv102_hidden
11028474SJose.Borrego@Sun.COM 		 * sv102_announce
11038474SJose.Borrego@Sun.COM 		 * sv102_anndelta
11048474SJose.Borrego@Sun.COM 		 * sv102_licenses
11058474SJose.Borrego@Sun.COM 		 * sv102_userpath
11068474SJose.Borrego@Sun.COM 		 */
11078474SJose.Borrego@Sun.COM 		if (info102->sv102_name == NULL ||
11088474SJose.Borrego@Sun.COM 		    info102->sv102_comment == NULL)
11098474SJose.Borrego@Sun.COM 			goto netservergetinfo_no_memory;
11108474SJose.Borrego@Sun.COM 
11118474SJose.Borrego@Sun.COM 		param->result.bufptr.bufptr102 = info102;
11128474SJose.Borrego@Sun.COM 		break;
11138474SJose.Borrego@Sun.COM 
11148474SJose.Borrego@Sun.COM 	default:
11158474SJose.Borrego@Sun.COM 		bzero(&param->result,
11168474SJose.Borrego@Sun.COM 		    sizeof (struct mslm_NetServerGetInfo_result));
11178474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
11188474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
11198474SJose.Borrego@Sun.COM 	}
11208474SJose.Borrego@Sun.COM 
11218474SJose.Borrego@Sun.COM 	param->result.level = param->level;
11228474SJose.Borrego@Sun.COM 	param->status = (ERROR_SUCCESS);
11238474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
11248474SJose.Borrego@Sun.COM }
11258474SJose.Borrego@Sun.COM 
11268474SJose.Borrego@Sun.COM /*
11278474SJose.Borrego@Sun.COM  * NetRemoteTOD
11288474SJose.Borrego@Sun.COM  *
11298474SJose.Borrego@Sun.COM  * Returns information about the time of day on this server.
11308474SJose.Borrego@Sun.COM  *
11318474SJose.Borrego@Sun.COM  * typedef struct _TIME_OF_DAY_INFO {
11328474SJose.Borrego@Sun.COM  *	DWORD tod_elapsedt;  // seconds since 00:00:00 January 1 1970 GMT
11338474SJose.Borrego@Sun.COM  *	DWORD tod_msecs;     // arbitrary milliseconds (since reset)
11348474SJose.Borrego@Sun.COM  *	DWORD tod_hours;     // current hour [0-23]
11358474SJose.Borrego@Sun.COM  *	DWORD tod_mins;      // current minute [0-59]
11368474SJose.Borrego@Sun.COM  *	DWORD tod_secs;      // current second [0-59]
11378474SJose.Borrego@Sun.COM  *	DWORD tod_hunds;     // current hundredth (0.01) second [0-99]
11388474SJose.Borrego@Sun.COM  *	LONG tod_timezone;   // time zone of the server
11398474SJose.Borrego@Sun.COM  *	DWORD tod_tinterval; // clock tick time interval
11408474SJose.Borrego@Sun.COM  *	DWORD tod_day;       // day of the month [1-31]
11418474SJose.Borrego@Sun.COM  *	DWORD tod_month;     // month of the year [1-12]
11428474SJose.Borrego@Sun.COM  *	DWORD tod_year;      // current year
11438474SJose.Borrego@Sun.COM  *	DWORD tod_weekday;   // day of the week since Sunday [0-6]
11448474SJose.Borrego@Sun.COM  * } TIME_OF_DAY_INFO;
11458474SJose.Borrego@Sun.COM  *
11468474SJose.Borrego@Sun.COM  * The time zone of the server is calculated in minutes from Greenwich
11478474SJose.Borrego@Sun.COM  * Mean Time (GMT). For time zones west of Greenwich, the value is
11488474SJose.Borrego@Sun.COM  * positive; for time zones east of Greenwich, the value is negative.
11498474SJose.Borrego@Sun.COM  * A value of -1 indicates that the time zone is undefined.
11508474SJose.Borrego@Sun.COM  *
11518474SJose.Borrego@Sun.COM  * The clock tick value represents a resolution of one ten-thousandth
11528474SJose.Borrego@Sun.COM  * (0.0001) second.
11538474SJose.Borrego@Sun.COM  */
11548474SJose.Borrego@Sun.COM static int
11558474SJose.Borrego@Sun.COM srvsvc_s_NetRemoteTOD(void *arg, ndr_xa_t *mxa)
11568474SJose.Borrego@Sun.COM {
11578474SJose.Borrego@Sun.COM 	struct mslm_NetRemoteTOD *param = arg;
11588474SJose.Borrego@Sun.COM 	struct mslm_TIME_OF_DAY_INFO *tod;
11598474SJose.Borrego@Sun.COM 	struct timeval		time_val;
11608474SJose.Borrego@Sun.COM 	struct tm		tm;
11618474SJose.Borrego@Sun.COM 
11628474SJose.Borrego@Sun.COM 	(void) gettimeofday(&time_val, 0);
11638474SJose.Borrego@Sun.COM 	(void) gmtime_r(&time_val.tv_sec, &tm);
11648474SJose.Borrego@Sun.COM 
11658474SJose.Borrego@Sun.COM 	tod = NDR_NEW(mxa, struct mslm_TIME_OF_DAY_INFO);
11668474SJose.Borrego@Sun.COM 	if (tod == NULL) {
11678474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetRemoteTOD));
11688474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
11698474SJose.Borrego@Sun.COM 	}
11708474SJose.Borrego@Sun.COM 
11718474SJose.Borrego@Sun.COM 	tod->tod_elapsedt = time_val.tv_sec;
11728474SJose.Borrego@Sun.COM 	tod->tod_msecs = time_val.tv_usec;
11738474SJose.Borrego@Sun.COM 	tod->tod_hours = tm.tm_hour;
11748474SJose.Borrego@Sun.COM 	tod->tod_mins = tm.tm_min;
11758474SJose.Borrego@Sun.COM 	tod->tod_secs = tm.tm_sec;
11768474SJose.Borrego@Sun.COM 	tod->tod_hunds = 0;
11778474SJose.Borrego@Sun.COM 	tod->tod_tinterval = 1000;
11788474SJose.Borrego@Sun.COM 	tod->tod_day = tm.tm_mday;
11798474SJose.Borrego@Sun.COM 	tod->tod_month = tm.tm_mon+1;
11808474SJose.Borrego@Sun.COM 	tod->tod_year = tm.tm_year+1900;
11818474SJose.Borrego@Sun.COM 	tod->tod_weekday = tm.tm_wday;
11828474SJose.Borrego@Sun.COM 
11838474SJose.Borrego@Sun.COM 	(void) localtime_r(&time_val.tv_sec, &tm);
11848474SJose.Borrego@Sun.COM 
11858474SJose.Borrego@Sun.COM 	param->bufptr = tod;
11868474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
11878474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
11888474SJose.Borrego@Sun.COM }
11898474SJose.Borrego@Sun.COM 
11908474SJose.Borrego@Sun.COM /*
11918474SJose.Borrego@Sun.COM  * srvsvc_s_NetNameValidate
11928474SJose.Borrego@Sun.COM  *
11938474SJose.Borrego@Sun.COM  * Perform name validation.
11948474SJose.Borrego@Sun.COM  *
11958474SJose.Borrego@Sun.COM  * The share name is considered invalid if it contains any of the
11968474SJose.Borrego@Sun.COM  * following character (MSDN 236388).
11978474SJose.Borrego@Sun.COM  *
11988474SJose.Borrego@Sun.COM  * " / \ [ ] : | < > + ; , ? * =
11998474SJose.Borrego@Sun.COM  *
12008474SJose.Borrego@Sun.COM  * Returns Win32 error codes.
12018474SJose.Borrego@Sun.COM  */
12028474SJose.Borrego@Sun.COM /*ARGSUSED*/
12038474SJose.Borrego@Sun.COM static int
12048474SJose.Borrego@Sun.COM srvsvc_s_NetNameValidate(void *arg, ndr_xa_t *mxa)
12058474SJose.Borrego@Sun.COM {
12068474SJose.Borrego@Sun.COM 	struct mslm_NetNameValidate *param = arg;
12078474SJose.Borrego@Sun.COM 	char *name;
12088474SJose.Borrego@Sun.COM 	int len;
12098474SJose.Borrego@Sun.COM 
12108474SJose.Borrego@Sun.COM 	if ((name = (char *)param->pathname) == NULL) {
12118474SJose.Borrego@Sun.COM 		param->status = ERROR_INVALID_PARAMETER;
12128474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
12138474SJose.Borrego@Sun.COM 	}
12148474SJose.Borrego@Sun.COM 
12158474SJose.Borrego@Sun.COM 	len = strlen(name);
12168474SJose.Borrego@Sun.COM 
12178474SJose.Borrego@Sun.COM 	if ((param->flags == 0 && len > 81) ||
12188474SJose.Borrego@Sun.COM 	    (param->flags == 0x80000000 && len > 13)) {
12198474SJose.Borrego@Sun.COM 		param->status = ERROR_INVALID_NAME;
12208474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
12218474SJose.Borrego@Sun.COM 	}
12228474SJose.Borrego@Sun.COM 
12238474SJose.Borrego@Sun.COM 	switch (param->type) {
12248474SJose.Borrego@Sun.COM 	case NAMETYPE_SHARE:
12258474SJose.Borrego@Sun.COM 		if (smb_shr_chkname(name))
12268474SJose.Borrego@Sun.COM 			param->status = ERROR_SUCCESS;
12278474SJose.Borrego@Sun.COM 		else
12288474SJose.Borrego@Sun.COM 			param->status = ERROR_INVALID_NAME;
12298474SJose.Borrego@Sun.COM 		break;
12308474SJose.Borrego@Sun.COM 
12318474SJose.Borrego@Sun.COM 	case NAMETYPE_USER:
12328474SJose.Borrego@Sun.COM 	case NAMETYPE_PASSWORD:
12338474SJose.Borrego@Sun.COM 	case NAMETYPE_GROUP:
12348474SJose.Borrego@Sun.COM 	case NAMETYPE_COMPUTER:
12358474SJose.Borrego@Sun.COM 	case NAMETYPE_EVENT:
12368474SJose.Borrego@Sun.COM 	case NAMETYPE_DOMAIN:
12378474SJose.Borrego@Sun.COM 	case NAMETYPE_SERVICE:
12388474SJose.Borrego@Sun.COM 	case NAMETYPE_NET:
12398474SJose.Borrego@Sun.COM 	case NAMETYPE_MESSAGE:
12408474SJose.Borrego@Sun.COM 	case NAMETYPE_MESSAGEDEST:
12418474SJose.Borrego@Sun.COM 	case NAMETYPE_SHAREPASSWORD:
12428474SJose.Borrego@Sun.COM 	case NAMETYPE_WORKGROUP:
12438474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_SUPPORTED;
12448474SJose.Borrego@Sun.COM 		break;
12458474SJose.Borrego@Sun.COM 
12468474SJose.Borrego@Sun.COM 	default:
12478474SJose.Borrego@Sun.COM 		param->status = ERROR_INVALID_PARAMETER;
12488474SJose.Borrego@Sun.COM 		break;
12498474SJose.Borrego@Sun.COM 	}
12508474SJose.Borrego@Sun.COM 
12518474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
12528474SJose.Borrego@Sun.COM }
12538474SJose.Borrego@Sun.COM 
12548474SJose.Borrego@Sun.COM /*
12558474SJose.Borrego@Sun.COM  * srvsvc_s_NetShareAdd
12568474SJose.Borrego@Sun.COM  *
12578474SJose.Borrego@Sun.COM  * Add a new share. We support info levels 2 and 502 but ignore the
12588474SJose.Borrego@Sun.COM  * security descriptor in level 502 requests. Only the administrator,
12598474SJose.Borrego@Sun.COM  * or a member of the domain administrators group, is allowed to add
12608474SJose.Borrego@Sun.COM  * shares.
12618474SJose.Borrego@Sun.COM  *
12628474SJose.Borrego@Sun.COM  * This interface is used by the rmtshare command from the NT resource
12638474SJose.Borrego@Sun.COM  * kit. Rmtshare allows a client to add or remove shares on a server
12648474SJose.Borrego@Sun.COM  * from the client's command line.
12658474SJose.Borrego@Sun.COM  *
12668474SJose.Borrego@Sun.COM  * Note that we don't support security descriptors on a share. If the
12678474SJose.Borrego@Sun.COM  * /grant is used, the share will be created but the subsequent attempt
12688474SJose.Borrego@Sun.COM  * to manipulate the security descriptor (NetShareGetInfo) will fail.
12698474SJose.Borrego@Sun.COM  * Similarly for the /remove option.
12708474SJose.Borrego@Sun.COM  *
12718474SJose.Borrego@Sun.COM  * Returns Win32 error codes.
12728474SJose.Borrego@Sun.COM  */
12738474SJose.Borrego@Sun.COM static int
12748474SJose.Borrego@Sun.COM srvsvc_s_NetShareAdd(void *arg, ndr_xa_t *mxa)
12758474SJose.Borrego@Sun.COM {
12768474SJose.Borrego@Sun.COM 	static DWORD parm_err = 0;
12778474SJose.Borrego@Sun.COM 	DWORD parm_stat;
12788474SJose.Borrego@Sun.COM 	struct mslm_NetShareAdd *param = arg;
12798474SJose.Borrego@Sun.COM 	struct mslm_SHARE_INFO_2 *info2;
12808474SJose.Borrego@Sun.COM 	char realpath[MAXPATHLEN];
12818474SJose.Borrego@Sun.COM 	int32_t native_os;
12828474SJose.Borrego@Sun.COM 
12838474SJose.Borrego@Sun.COM 	native_os = ndr_native_os(mxa);
12848474SJose.Borrego@Sun.COM 
12858474SJose.Borrego@Sun.COM 	if (!ndr_is_poweruser(mxa)) {
12868474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareAdd));
12878474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
12888474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
12898474SJose.Borrego@Sun.COM 	}
12908474SJose.Borrego@Sun.COM 
12918474SJose.Borrego@Sun.COM 	switch (param->level) {
12928474SJose.Borrego@Sun.COM 	case 2:
12938474SJose.Borrego@Sun.COM 		info2 = param->info.un.info2;
12948474SJose.Borrego@Sun.COM 		break;
12958474SJose.Borrego@Sun.COM 
12968474SJose.Borrego@Sun.COM 	case 502:
12978474SJose.Borrego@Sun.COM 		info2 = (struct mslm_SHARE_INFO_2 *)param->info.un.info502;
12988474SJose.Borrego@Sun.COM 		break;
12998474SJose.Borrego@Sun.COM 
13008474SJose.Borrego@Sun.COM 	default:
13018474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareAdd));
13028474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
13038474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
13048474SJose.Borrego@Sun.COM 	}
13058474SJose.Borrego@Sun.COM 
13068474SJose.Borrego@Sun.COM 	if (info2->shi2_netname == NULL || info2->shi2_path == NULL) {
13078474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareAdd));
13088474SJose.Borrego@Sun.COM 		param->status = NERR_NetNameNotFound;
13098474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
13108474SJose.Borrego@Sun.COM 	}
13118474SJose.Borrego@Sun.COM 
13128474SJose.Borrego@Sun.COM 	if (smb_shr_is_restricted((char *)info2->shi2_netname)) {
13138474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareAdd));
13148474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
13158474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
13168474SJose.Borrego@Sun.COM 	}
13178474SJose.Borrego@Sun.COM 
13188474SJose.Borrego@Sun.COM 	if (info2->shi2_remark == NULL)
13198474SJose.Borrego@Sun.COM 		info2->shi2_remark = (uint8_t *)"";
13208474SJose.Borrego@Sun.COM 
13218474SJose.Borrego@Sun.COM 	/*
13228474SJose.Borrego@Sun.COM 	 * Derive the real path which will be stored in the
13238474SJose.Borrego@Sun.COM 	 * directory field of the smb_share_t structure
13248474SJose.Borrego@Sun.COM 	 * from the path field in this RPC request.
13258474SJose.Borrego@Sun.COM 	 */
13268474SJose.Borrego@Sun.COM 	parm_stat = smb_shr_get_realpath((const char *)info2->shi2_path,
13278474SJose.Borrego@Sun.COM 	    realpath, MAXPATHLEN);
13288474SJose.Borrego@Sun.COM 
13298474SJose.Borrego@Sun.COM 	if (parm_stat != NERR_Success) {
13308474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareAdd));
13318474SJose.Borrego@Sun.COM 		param->status = parm_stat;
13328474SJose.Borrego@Sun.COM 		param->parm_err
13338474SJose.Borrego@Sun.COM 		    = (native_os == NATIVE_OS_WIN95) ? 0 : &parm_err;
13348474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
13358474SJose.Borrego@Sun.COM 	}
13368474SJose.Borrego@Sun.COM 
13378474SJose.Borrego@Sun.COM 	param->status = srvsvc_sa_add((char *)info2->shi2_netname, realpath,
13388474SJose.Borrego@Sun.COM 	    (char *)info2->shi2_remark);
13398474SJose.Borrego@Sun.COM 	if (param->status == NERR_Success) {
13408474SJose.Borrego@Sun.COM 		smb_share_t si;
13418474SJose.Borrego@Sun.COM 		/*
13428474SJose.Borrego@Sun.COM 		 * Lookup the share, which will bring it into the cache.
13438474SJose.Borrego@Sun.COM 		 */
13448474SJose.Borrego@Sun.COM 		(void) smb_shr_get((char *)info2->shi2_netname, &si);
13458474SJose.Borrego@Sun.COM 	}
13468474SJose.Borrego@Sun.COM 	param->parm_err = (native_os == NATIVE_OS_WIN95) ? 0 : &parm_err;
13478474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
13488474SJose.Borrego@Sun.COM }
13498474SJose.Borrego@Sun.COM 
13508474SJose.Borrego@Sun.COM /*
13518474SJose.Borrego@Sun.COM  * srvsvc_estimate_objcnt
13528474SJose.Borrego@Sun.COM  *
13538474SJose.Borrego@Sun.COM  * Estimate the number of objects that will fit in prefmaxlen.
13548474SJose.Borrego@Sun.COM  */
13558474SJose.Borrego@Sun.COM static uint32_t
13568474SJose.Borrego@Sun.COM srvsvc_estimate_objcnt(uint32_t prefmaxlen, uint32_t n_obj, uint32_t obj_size)
13578474SJose.Borrego@Sun.COM {
13588474SJose.Borrego@Sun.COM 	DWORD max_cnt;
13598474SJose.Borrego@Sun.COM 
13608474SJose.Borrego@Sun.COM 	if (obj_size == 0)
13618474SJose.Borrego@Sun.COM 		return (0);
13628474SJose.Borrego@Sun.COM 
13638474SJose.Borrego@Sun.COM 	if ((max_cnt = (prefmaxlen / obj_size)) == 0)
13648474SJose.Borrego@Sun.COM 		return (0);
13658474SJose.Borrego@Sun.COM 
13668474SJose.Borrego@Sun.COM 	if (n_obj > max_cnt)
13678474SJose.Borrego@Sun.COM 		n_obj = max_cnt;
13688474SJose.Borrego@Sun.COM 
13698474SJose.Borrego@Sun.COM 	return (n_obj);
13708474SJose.Borrego@Sun.COM }
13718474SJose.Borrego@Sun.COM 
13728474SJose.Borrego@Sun.COM /*
13738474SJose.Borrego@Sun.COM  * srvsvc_s_NetShareEnum
13748474SJose.Borrego@Sun.COM  *
13758474SJose.Borrego@Sun.COM  * Enumerate all shares (see also NetShareEnumSticky).
13768474SJose.Borrego@Sun.COM  *
13778474SJose.Borrego@Sun.COM  * Request for various levels of information about our shares.
13788474SJose.Borrego@Sun.COM  * Level 0: share names.
13798474SJose.Borrego@Sun.COM  * Level 1: share name, share type and comment field.
13808474SJose.Borrego@Sun.COM  * Level 2: everything that we know about the shares.
13818474SJose.Borrego@Sun.COM  * Level 501: level 1 + flags (flags must be zero).
13828474SJose.Borrego@Sun.COM  * Level 502: level 2 + security descriptor.
13838474SJose.Borrego@Sun.COM  */
13848474SJose.Borrego@Sun.COM static int
13858474SJose.Borrego@Sun.COM srvsvc_s_NetShareEnum(void *arg, ndr_xa_t *mxa)
13868474SJose.Borrego@Sun.COM {
13878474SJose.Borrego@Sun.COM 	struct mslm_NetShareEnum *param = arg;
13888474SJose.Borrego@Sun.COM 	struct mslm_infonres *infonres;
13898474SJose.Borrego@Sun.COM 	srvsvc_enum_t se;
13908474SJose.Borrego@Sun.COM 	DWORD status;
13918474SJose.Borrego@Sun.COM 
13928474SJose.Borrego@Sun.COM 	infonres = NDR_NEW(mxa, struct mslm_infonres);
13938474SJose.Borrego@Sun.COM 	if (infonres == NULL) {
13948474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareEnum));
13958474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
13968474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
13978474SJose.Borrego@Sun.COM 	}
13988474SJose.Borrego@Sun.COM 
13998474SJose.Borrego@Sun.COM 	infonres->entriesread = 0;
14008474SJose.Borrego@Sun.COM 	infonres->entries = NULL;
14018474SJose.Borrego@Sun.COM 	param->result.level = param->level;
14028474SJose.Borrego@Sun.COM 	param->result.bufptr.p = infonres;
14038474SJose.Borrego@Sun.COM 
14048474SJose.Borrego@Sun.COM 	bzero(&se, sizeof (srvsvc_enum_t));
14058474SJose.Borrego@Sun.COM 	se.se_level = param->level;
14068474SJose.Borrego@Sun.COM 	se.se_n_total = smb_shr_count();
14078474SJose.Borrego@Sun.COM 
14088474SJose.Borrego@Sun.COM 	if (param->prefmaxlen == SMB_SRVSVC_MAXPREFLEN ||
14098474SJose.Borrego@Sun.COM 	    param->prefmaxlen > SMB_SRVSVC_MAXBUFLEN)
14108474SJose.Borrego@Sun.COM 		se.se_prefmaxlen = SMB_SRVSVC_MAXBUFLEN;
14118474SJose.Borrego@Sun.COM 	else
14128474SJose.Borrego@Sun.COM 		se.se_prefmaxlen = param->prefmaxlen;
14138474SJose.Borrego@Sun.COM 
14148474SJose.Borrego@Sun.COM 	if (param->resume_handle) {
14158474SJose.Borrego@Sun.COM 		se.se_resume_handle = *param->resume_handle;
14168474SJose.Borrego@Sun.COM 		se.se_n_skip = se.se_resume_handle;
14178474SJose.Borrego@Sun.COM 	}
14188474SJose.Borrego@Sun.COM 
14198474SJose.Borrego@Sun.COM 	switch (param->level) {
14208474SJose.Borrego@Sun.COM 	case 0:
14218474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel0(mxa, infonres, &se, 0);
14228474SJose.Borrego@Sun.COM 		break;
14238474SJose.Borrego@Sun.COM 
14248474SJose.Borrego@Sun.COM 	case 1:
14258474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel1(mxa, infonres, &se, 0);
14268474SJose.Borrego@Sun.COM 		break;
14278474SJose.Borrego@Sun.COM 
14288474SJose.Borrego@Sun.COM 	case 2:
14298474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel2(mxa, infonres, &se, 0);
14308474SJose.Borrego@Sun.COM 		break;
14318474SJose.Borrego@Sun.COM 
14328474SJose.Borrego@Sun.COM 	case 501:
14338474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel501(mxa, infonres, &se, 0);
14348474SJose.Borrego@Sun.COM 		break;
14358474SJose.Borrego@Sun.COM 
14368474SJose.Borrego@Sun.COM 	case 502:
14378474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel502(mxa, infonres, &se, 0);
14388474SJose.Borrego@Sun.COM 		break;
14398474SJose.Borrego@Sun.COM 
14408474SJose.Borrego@Sun.COM 	default:
14418474SJose.Borrego@Sun.COM 		status = ERROR_INVALID_PARAMETER;
14428474SJose.Borrego@Sun.COM 		break;
14438474SJose.Borrego@Sun.COM 	}
14448474SJose.Borrego@Sun.COM 
14458474SJose.Borrego@Sun.COM 	if (status != 0) {
14468474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareEnum));
14478474SJose.Borrego@Sun.COM 		param->status = status;
14488474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
14498474SJose.Borrego@Sun.COM 	}
14508474SJose.Borrego@Sun.COM 
14518474SJose.Borrego@Sun.COM 	if (se.se_n_enum == 0) {
14528474SJose.Borrego@Sun.COM 		if (param->resume_handle)
14538474SJose.Borrego@Sun.COM 			*param->resume_handle = 0;
14548474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
14558474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
14568474SJose.Borrego@Sun.COM 	}
14578474SJose.Borrego@Sun.COM 
14588474SJose.Borrego@Sun.COM 	if (param->resume_handle &&
14598474SJose.Borrego@Sun.COM 	    param->prefmaxlen != SMB_SRVSVC_MAXPREFLEN) {
14608474SJose.Borrego@Sun.COM 		if (se.se_resume_handle < se.se_n_total) {
14618474SJose.Borrego@Sun.COM 			*param->resume_handle = se.se_resume_handle;
14628474SJose.Borrego@Sun.COM 			status = ERROR_MORE_DATA;
14638474SJose.Borrego@Sun.COM 		} else {
14648474SJose.Borrego@Sun.COM 			*param->resume_handle = 0;
14658474SJose.Borrego@Sun.COM 		}
14668474SJose.Borrego@Sun.COM 	}
14678474SJose.Borrego@Sun.COM 
14688474SJose.Borrego@Sun.COM 	param->totalentries = se.se_n_total;
14698474SJose.Borrego@Sun.COM 	param->status = status;
14708474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
14718474SJose.Borrego@Sun.COM }
14728474SJose.Borrego@Sun.COM 
14738474SJose.Borrego@Sun.COM /*
14748474SJose.Borrego@Sun.COM  * srvsvc_s_NetShareEnumSticky
14758474SJose.Borrego@Sun.COM  *
14768474SJose.Borrego@Sun.COM  * Enumerate sticky shares: all shares except those marked STYPE_SPECIAL.
14778474SJose.Borrego@Sun.COM  * Except for excluding STYPE_SPECIAL shares, NetShareEnumSticky is the
14788474SJose.Borrego@Sun.COM  * same as NetShareEnum.
14798474SJose.Borrego@Sun.COM  *
14808474SJose.Borrego@Sun.COM  * Request for various levels of information about our shares.
14818474SJose.Borrego@Sun.COM  * Level 0: share names.
14828474SJose.Borrego@Sun.COM  * Level 1: share name, share type and comment field.
14838474SJose.Borrego@Sun.COM  * Level 2: everything that we know about the shares.
14848474SJose.Borrego@Sun.COM  * Level 501: not valid for this request.
14858474SJose.Borrego@Sun.COM  * Level 502: level 2 + security descriptor.
14868474SJose.Borrego@Sun.COM  *
14878474SJose.Borrego@Sun.COM  * We set n_skip to resume_handle, which is used to find the appropriate
14888474SJose.Borrego@Sun.COM  * place to resume.  The resume_handle is similar to the readdir cookie.
14898474SJose.Borrego@Sun.COM  */
14908474SJose.Borrego@Sun.COM static int
14918474SJose.Borrego@Sun.COM srvsvc_s_NetShareEnumSticky(void *arg, ndr_xa_t *mxa)
14928474SJose.Borrego@Sun.COM {
14938474SJose.Borrego@Sun.COM 	struct mslm_NetShareEnum *param = arg;
14948474SJose.Borrego@Sun.COM 	struct mslm_infonres *infonres;
14958474SJose.Borrego@Sun.COM 	srvsvc_enum_t se;
14968474SJose.Borrego@Sun.COM 	DWORD status;
14978474SJose.Borrego@Sun.COM 
14988474SJose.Borrego@Sun.COM 	infonres = NDR_NEW(mxa, struct mslm_infonres);
14998474SJose.Borrego@Sun.COM 	if (infonres == NULL) {
15008474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareEnum));
15018474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
15028474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
15038474SJose.Borrego@Sun.COM 	}
15048474SJose.Borrego@Sun.COM 
15058474SJose.Borrego@Sun.COM 	infonres->entriesread = 0;
15068474SJose.Borrego@Sun.COM 	infonres->entries = NULL;
15078474SJose.Borrego@Sun.COM 	param->result.level = param->level;
15088474SJose.Borrego@Sun.COM 	param->result.bufptr.p = infonres;
15098474SJose.Borrego@Sun.COM 
15108474SJose.Borrego@Sun.COM 	bzero(&se, sizeof (srvsvc_enum_t));
15118474SJose.Borrego@Sun.COM 	se.se_level = param->level;
15128474SJose.Borrego@Sun.COM 	se.se_n_total = smb_shr_count();
15138474SJose.Borrego@Sun.COM 
15148474SJose.Borrego@Sun.COM 	if (param->prefmaxlen == SMB_SRVSVC_MAXPREFLEN ||
15158474SJose.Borrego@Sun.COM 	    param->prefmaxlen > SMB_SRVSVC_MAXBUFLEN)
15168474SJose.Borrego@Sun.COM 		se.se_prefmaxlen = SMB_SRVSVC_MAXBUFLEN;
15178474SJose.Borrego@Sun.COM 	else
15188474SJose.Borrego@Sun.COM 		se.se_prefmaxlen = param->prefmaxlen;
15198474SJose.Borrego@Sun.COM 
15208474SJose.Borrego@Sun.COM 	if (param->resume_handle) {
15218474SJose.Borrego@Sun.COM 		se.se_resume_handle = *param->resume_handle;
15228474SJose.Borrego@Sun.COM 		se.se_n_skip = se.se_resume_handle;
15238474SJose.Borrego@Sun.COM 	}
15248474SJose.Borrego@Sun.COM 
15258474SJose.Borrego@Sun.COM 	switch (param->level) {
15268474SJose.Borrego@Sun.COM 	case 0:
15278474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel0(mxa, infonres, &se, 1);
15288474SJose.Borrego@Sun.COM 		break;
15298474SJose.Borrego@Sun.COM 
15308474SJose.Borrego@Sun.COM 	case 1:
15318474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel1(mxa, infonres, &se, 1);
15328474SJose.Borrego@Sun.COM 		break;
15338474SJose.Borrego@Sun.COM 
15348474SJose.Borrego@Sun.COM 	case 2:
15358474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel2(mxa, infonres, &se, 1);
15368474SJose.Borrego@Sun.COM 		break;
15378474SJose.Borrego@Sun.COM 
15388474SJose.Borrego@Sun.COM 	case 502:
15398474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel502(mxa, infonres, &se, 1);
15408474SJose.Borrego@Sun.COM 		break;
15418474SJose.Borrego@Sun.COM 
15428474SJose.Borrego@Sun.COM 	default:
15438474SJose.Borrego@Sun.COM 		status = ERROR_INVALID_LEVEL;
15448474SJose.Borrego@Sun.COM 		break;
15458474SJose.Borrego@Sun.COM 	}
15468474SJose.Borrego@Sun.COM 
15478474SJose.Borrego@Sun.COM 	if (status != ERROR_SUCCESS) {
15488474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareEnum));
15498474SJose.Borrego@Sun.COM 		param->status = status;
15508474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
15518474SJose.Borrego@Sun.COM 	}
15528474SJose.Borrego@Sun.COM 
15538474SJose.Borrego@Sun.COM 	if (se.se_n_enum == 0) {
15548474SJose.Borrego@Sun.COM 		if (param->resume_handle)
15558474SJose.Borrego@Sun.COM 			*param->resume_handle = 0;
15568474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
15578474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
15588474SJose.Borrego@Sun.COM 	}
15598474SJose.Borrego@Sun.COM 
15608474SJose.Borrego@Sun.COM 	if (param->resume_handle &&
15618474SJose.Borrego@Sun.COM 	    param->prefmaxlen != SMB_SRVSVC_MAXPREFLEN) {
15628474SJose.Borrego@Sun.COM 		if (se.se_resume_handle < se.se_n_total) {
15638474SJose.Borrego@Sun.COM 			*param->resume_handle = se.se_resume_handle;
15648474SJose.Borrego@Sun.COM 			status = ERROR_MORE_DATA;
15658474SJose.Borrego@Sun.COM 		} else {
15668474SJose.Borrego@Sun.COM 			*param->resume_handle = 0;
15678474SJose.Borrego@Sun.COM 		}
15688474SJose.Borrego@Sun.COM 	}
15698474SJose.Borrego@Sun.COM 
15708474SJose.Borrego@Sun.COM 	param->totalentries = se.se_n_total;
15718474SJose.Borrego@Sun.COM 	param->status = status;
15728474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
15738474SJose.Borrego@Sun.COM }
15748474SJose.Borrego@Sun.COM 
15758474SJose.Borrego@Sun.COM /*
15768474SJose.Borrego@Sun.COM  * NetShareEnum Level 0
15778474SJose.Borrego@Sun.COM  */
15788474SJose.Borrego@Sun.COM static DWORD
15798474SJose.Borrego@Sun.COM mlsvc_NetShareEnumLevel0(ndr_xa_t *mxa,
15808474SJose.Borrego@Sun.COM     struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky)
15818474SJose.Borrego@Sun.COM {
15828474SJose.Borrego@Sun.COM 	struct mslm_SHARE_INFO_0 *info0;
15838474SJose.Borrego@Sun.COM 	smb_shriter_t iterator;
15848474SJose.Borrego@Sun.COM 	smb_share_t *si;
15858474SJose.Borrego@Sun.COM 	DWORD status;
15868474SJose.Borrego@Sun.COM 
15878474SJose.Borrego@Sun.COM 	se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen,
15888474SJose.Borrego@Sun.COM 	    se->se_n_total, sizeof (struct mslm_SHARE_INFO_0) + MAXNAMELEN);
15898474SJose.Borrego@Sun.COM 	if (se->se_n_enum == 0)
15908474SJose.Borrego@Sun.COM 		return (ERROR_SUCCESS);
15918474SJose.Borrego@Sun.COM 
15928474SJose.Borrego@Sun.COM 	info0 = NDR_NEWN(mxa, struct mslm_SHARE_INFO_0, se->se_n_enum);
15938474SJose.Borrego@Sun.COM 	if (info0 == NULL)
15948474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
15958474SJose.Borrego@Sun.COM 
15968474SJose.Borrego@Sun.COM 	smb_shr_iterinit(&iterator);
15978474SJose.Borrego@Sun.COM 
15988474SJose.Borrego@Sun.COM 	se->se_n_read = 0;
15998474SJose.Borrego@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != NULL) {
16008474SJose.Borrego@Sun.COM 		if (se->se_n_skip > 0) {
16018474SJose.Borrego@Sun.COM 			--se->se_n_skip;
16028474SJose.Borrego@Sun.COM 			continue;
16038474SJose.Borrego@Sun.COM 		}
16048474SJose.Borrego@Sun.COM 
16058474SJose.Borrego@Sun.COM 		++se->se_resume_handle;
16068474SJose.Borrego@Sun.COM 
16078474SJose.Borrego@Sun.COM 		if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
16088474SJose.Borrego@Sun.COM 			continue;
16098474SJose.Borrego@Sun.COM 
16108474SJose.Borrego@Sun.COM 		if (si->shr_flags & SMB_SHRF_AUTOHOME)
16118474SJose.Borrego@Sun.COM 			continue;
16128474SJose.Borrego@Sun.COM 
16138474SJose.Borrego@Sun.COM 		if (se->se_n_read >= se->se_n_enum) {
16148474SJose.Borrego@Sun.COM 			se->se_n_read = se->se_n_enum;
16158474SJose.Borrego@Sun.COM 			break;
16168474SJose.Borrego@Sun.COM 		}
16178474SJose.Borrego@Sun.COM 
16188474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info0);
16198474SJose.Borrego@Sun.COM 		if (status != ERROR_SUCCESS)
16208474SJose.Borrego@Sun.COM 			break;
16218474SJose.Borrego@Sun.COM 
16228474SJose.Borrego@Sun.COM 		++se->se_n_read;
16238474SJose.Borrego@Sun.COM 	}
16248474SJose.Borrego@Sun.COM 
16258474SJose.Borrego@Sun.COM 	if (se->se_n_read < se->se_n_enum) {
16268474SJose.Borrego@Sun.COM 		if (srvsvc_add_autohome(mxa, se, (void *)info0))
16278474SJose.Borrego@Sun.COM 			++se->se_n_read;
16288474SJose.Borrego@Sun.COM 	}
16298474SJose.Borrego@Sun.COM 
16308474SJose.Borrego@Sun.COM 	infonres->entriesread = se->se_n_read;
16318474SJose.Borrego@Sun.COM 	infonres->entries = info0;
16328474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
16338474SJose.Borrego@Sun.COM }
16348474SJose.Borrego@Sun.COM 
16358474SJose.Borrego@Sun.COM /*
16368474SJose.Borrego@Sun.COM  * NetShareEnum Level 1
16378474SJose.Borrego@Sun.COM  */
16388474SJose.Borrego@Sun.COM static DWORD
16398474SJose.Borrego@Sun.COM mlsvc_NetShareEnumLevel1(ndr_xa_t *mxa,
16408474SJose.Borrego@Sun.COM     struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky)
16418474SJose.Borrego@Sun.COM {
16428474SJose.Borrego@Sun.COM 	struct mslm_SHARE_INFO_1 *info1;
16438474SJose.Borrego@Sun.COM 	smb_shriter_t iterator;
16448474SJose.Borrego@Sun.COM 	smb_share_t *si;
16458474SJose.Borrego@Sun.COM 	DWORD status;
16468474SJose.Borrego@Sun.COM 
16478474SJose.Borrego@Sun.COM 	se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen,
16488474SJose.Borrego@Sun.COM 	    se->se_n_total, sizeof (struct mslm_SHARE_INFO_1) + MAXNAMELEN);
16498474SJose.Borrego@Sun.COM 	if (se->se_n_enum == 0)
16508474SJose.Borrego@Sun.COM 		return (ERROR_SUCCESS);
16518474SJose.Borrego@Sun.COM 
16528474SJose.Borrego@Sun.COM 	info1 = NDR_NEWN(mxa, struct mslm_SHARE_INFO_1, se->se_n_enum);
16538474SJose.Borrego@Sun.COM 	if (info1 == NULL)
16548474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
16558474SJose.Borrego@Sun.COM 
16568474SJose.Borrego@Sun.COM 	smb_shr_iterinit(&iterator);
16578474SJose.Borrego@Sun.COM 
16588474SJose.Borrego@Sun.COM 	se->se_n_read = 0;
16598474SJose.Borrego@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != 0) {
16608474SJose.Borrego@Sun.COM 		if (se->se_n_skip > 0) {
16618474SJose.Borrego@Sun.COM 			--se->se_n_skip;
16628474SJose.Borrego@Sun.COM 			continue;
16638474SJose.Borrego@Sun.COM 		}
16648474SJose.Borrego@Sun.COM 
16658474SJose.Borrego@Sun.COM 		++se->se_resume_handle;
16668474SJose.Borrego@Sun.COM 
16678474SJose.Borrego@Sun.COM 		if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
16688474SJose.Borrego@Sun.COM 			continue;
16698474SJose.Borrego@Sun.COM 
16708474SJose.Borrego@Sun.COM 		if (si->shr_flags & SMB_SHRF_AUTOHOME)
16718474SJose.Borrego@Sun.COM 			continue;
16728474SJose.Borrego@Sun.COM 
16738474SJose.Borrego@Sun.COM 		if (se->se_n_read >= se->se_n_enum) {
16748474SJose.Borrego@Sun.COM 			se->se_n_read = se->se_n_enum;
16758474SJose.Borrego@Sun.COM 			break;
16768474SJose.Borrego@Sun.COM 		}
16778474SJose.Borrego@Sun.COM 
16788474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info1);
16798474SJose.Borrego@Sun.COM 		if (status != ERROR_SUCCESS)
16808474SJose.Borrego@Sun.COM 			break;
16818474SJose.Borrego@Sun.COM 
16828474SJose.Borrego@Sun.COM 		++se->se_n_read;
16838474SJose.Borrego@Sun.COM 	}
16848474SJose.Borrego@Sun.COM 
16858474SJose.Borrego@Sun.COM 	if (se->se_n_read < se->se_n_enum) {
16868474SJose.Borrego@Sun.COM 		if (srvsvc_add_autohome(mxa, se, (void *)info1))
16878474SJose.Borrego@Sun.COM 			++se->se_n_read;
16888474SJose.Borrego@Sun.COM 	}
16898474SJose.Borrego@Sun.COM 
16908474SJose.Borrego@Sun.COM 	infonres->entriesread = se->se_n_read;
16918474SJose.Borrego@Sun.COM 	infonres->entries = info1;
16928474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
16938474SJose.Borrego@Sun.COM }
16948474SJose.Borrego@Sun.COM 
16958474SJose.Borrego@Sun.COM /*
16968474SJose.Borrego@Sun.COM  * NetShareEnum Level 2
16978474SJose.Borrego@Sun.COM  */
16988474SJose.Borrego@Sun.COM static DWORD
16998474SJose.Borrego@Sun.COM mlsvc_NetShareEnumLevel2(ndr_xa_t *mxa,
17008474SJose.Borrego@Sun.COM     struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky)
17018474SJose.Borrego@Sun.COM {
17028474SJose.Borrego@Sun.COM 	struct mslm_SHARE_INFO_2 *info2;
17038474SJose.Borrego@Sun.COM 	smb_shriter_t iterator;
17048474SJose.Borrego@Sun.COM 	smb_share_t *si;
17058474SJose.Borrego@Sun.COM 	DWORD status;
17068474SJose.Borrego@Sun.COM 
17078474SJose.Borrego@Sun.COM 	se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen,
17088474SJose.Borrego@Sun.COM 	    se->se_n_total, sizeof (struct mslm_SHARE_INFO_2) + MAXNAMELEN);
17098474SJose.Borrego@Sun.COM 	if (se->se_n_enum == 0)
17108474SJose.Borrego@Sun.COM 		return (ERROR_SUCCESS);
17118474SJose.Borrego@Sun.COM 
17128474SJose.Borrego@Sun.COM 	info2 = NDR_NEWN(mxa, struct mslm_SHARE_INFO_2, se->se_n_enum);
17138474SJose.Borrego@Sun.COM 	if (info2 == NULL)
17148474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
17158474SJose.Borrego@Sun.COM 
17168474SJose.Borrego@Sun.COM 	smb_shr_iterinit(&iterator);
17178474SJose.Borrego@Sun.COM 
17188474SJose.Borrego@Sun.COM 	se->se_n_read = 0;
17198474SJose.Borrego@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != 0) {
17208474SJose.Borrego@Sun.COM 		if (se->se_n_skip > 0) {
17218474SJose.Borrego@Sun.COM 			--se->se_n_skip;
17228474SJose.Borrego@Sun.COM 			continue;
17238474SJose.Borrego@Sun.COM 		}
17248474SJose.Borrego@Sun.COM 
17258474SJose.Borrego@Sun.COM 		++se->se_resume_handle;
17268474SJose.Borrego@Sun.COM 
17278474SJose.Borrego@Sun.COM 		if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
17288474SJose.Borrego@Sun.COM 			continue;
17298474SJose.Borrego@Sun.COM 
17308474SJose.Borrego@Sun.COM 		if (si->shr_flags & SMB_SHRF_AUTOHOME)
17318474SJose.Borrego@Sun.COM 			continue;
17328474SJose.Borrego@Sun.COM 
17338474SJose.Borrego@Sun.COM 		if (se->se_n_read >= se->se_n_enum) {
17348474SJose.Borrego@Sun.COM 			se->se_n_read = se->se_n_enum;
17358474SJose.Borrego@Sun.COM 			break;
17368474SJose.Borrego@Sun.COM 		}
17378474SJose.Borrego@Sun.COM 
17388474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info2);
17398474SJose.Borrego@Sun.COM 		if (status != ERROR_SUCCESS)
17408474SJose.Borrego@Sun.COM 			break;
17418474SJose.Borrego@Sun.COM 
17428474SJose.Borrego@Sun.COM 		++se->se_n_read;
17438474SJose.Borrego@Sun.COM 	}
17448474SJose.Borrego@Sun.COM 
17458474SJose.Borrego@Sun.COM 	if (se->se_n_read < se->se_n_enum) {
17468474SJose.Borrego@Sun.COM 		if (srvsvc_add_autohome(mxa, se, (void *)info2))
17478474SJose.Borrego@Sun.COM 			++se->se_n_read;
17488474SJose.Borrego@Sun.COM 	}
17498474SJose.Borrego@Sun.COM 
17508474SJose.Borrego@Sun.COM 	infonres->entriesread = se->se_n_read;
17518474SJose.Borrego@Sun.COM 	infonres->entries = info2;
17528474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
17538474SJose.Borrego@Sun.COM }
17548474SJose.Borrego@Sun.COM 
17558474SJose.Borrego@Sun.COM /*
17568474SJose.Borrego@Sun.COM  * NetShareEnum Level 501
17578474SJose.Borrego@Sun.COM  */
17588474SJose.Borrego@Sun.COM static DWORD
17598474SJose.Borrego@Sun.COM mlsvc_NetShareEnumLevel501(ndr_xa_t *mxa,
17608474SJose.Borrego@Sun.COM     struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky)
17618474SJose.Borrego@Sun.COM {
17628474SJose.Borrego@Sun.COM 	struct mslm_SHARE_INFO_501 *info501;
17638474SJose.Borrego@Sun.COM 	smb_shriter_t iterator;
17648474SJose.Borrego@Sun.COM 	smb_share_t *si;
17658474SJose.Borrego@Sun.COM 	DWORD status;
17668474SJose.Borrego@Sun.COM 
17678474SJose.Borrego@Sun.COM 	se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen,
17688474SJose.Borrego@Sun.COM 	    se->se_n_total, sizeof (struct mslm_SHARE_INFO_501) + MAXNAMELEN);
17698474SJose.Borrego@Sun.COM 	if (se->se_n_enum == 0)
17708474SJose.Borrego@Sun.COM 		return (ERROR_SUCCESS);
17718474SJose.Borrego@Sun.COM 
17728474SJose.Borrego@Sun.COM 	info501 = NDR_NEWN(mxa, struct mslm_SHARE_INFO_501,
17738474SJose.Borrego@Sun.COM 	    se->se_n_enum);
17748474SJose.Borrego@Sun.COM 	if (info501 == NULL)
17758474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
17768474SJose.Borrego@Sun.COM 
17778474SJose.Borrego@Sun.COM 	smb_shr_iterinit(&iterator);
17788474SJose.Borrego@Sun.COM 
17798474SJose.Borrego@Sun.COM 	se->se_n_read = 0;
17808474SJose.Borrego@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != 0) {
17818474SJose.Borrego@Sun.COM 		if (se->se_n_skip > 0) {
17828474SJose.Borrego@Sun.COM 			--se->se_n_skip;
17838474SJose.Borrego@Sun.COM 			continue;
17848474SJose.Borrego@Sun.COM 		}
17858474SJose.Borrego@Sun.COM 
17868474SJose.Borrego@Sun.COM 		++se->se_resume_handle;
17878474SJose.Borrego@Sun.COM 
17888474SJose.Borrego@Sun.COM 		if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
17898474SJose.Borrego@Sun.COM 			continue;
17908474SJose.Borrego@Sun.COM 
17918474SJose.Borrego@Sun.COM 		if (si->shr_flags & SMB_SHRF_AUTOHOME)
17928474SJose.Borrego@Sun.COM 			continue;
17938474SJose.Borrego@Sun.COM 
17948474SJose.Borrego@Sun.COM 		if (se->se_n_read >= se->se_n_enum) {
17958474SJose.Borrego@Sun.COM 			se->se_n_read = se->se_n_enum;
17968474SJose.Borrego@Sun.COM 			break;
17978474SJose.Borrego@Sun.COM 		}
17988474SJose.Borrego@Sun.COM 
17998474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info501);
18008474SJose.Borrego@Sun.COM 		if (status != ERROR_SUCCESS)
18018474SJose.Borrego@Sun.COM 			break;
18028474SJose.Borrego@Sun.COM 
18038474SJose.Borrego@Sun.COM 		++se->se_n_read;
18048474SJose.Borrego@Sun.COM 	}
18058474SJose.Borrego@Sun.COM 
18068474SJose.Borrego@Sun.COM 	if (se->se_n_read < se->se_n_enum) {
18078474SJose.Borrego@Sun.COM 		if (srvsvc_add_autohome(mxa, se, (void *)info501))
18088474SJose.Borrego@Sun.COM 			++se->se_n_read;
18098474SJose.Borrego@Sun.COM 	}
18108474SJose.Borrego@Sun.COM 
18118474SJose.Borrego@Sun.COM 	infonres->entriesread = se->se_n_read;
18128474SJose.Borrego@Sun.COM 	infonres->entries = info501;
18138474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
18148474SJose.Borrego@Sun.COM }
18158474SJose.Borrego@Sun.COM 
18168474SJose.Borrego@Sun.COM /*
18178474SJose.Borrego@Sun.COM  * NetShareEnum Level 502
18188474SJose.Borrego@Sun.COM  */
18198474SJose.Borrego@Sun.COM static DWORD
18208474SJose.Borrego@Sun.COM mlsvc_NetShareEnumLevel502(ndr_xa_t *mxa,
18218474SJose.Borrego@Sun.COM     struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky)
18228474SJose.Borrego@Sun.COM {
18238474SJose.Borrego@Sun.COM 	struct mslm_SHARE_INFO_502 *info502;
18248474SJose.Borrego@Sun.COM 	smb_shriter_t iterator;
18258474SJose.Borrego@Sun.COM 	smb_share_t *si;
18268474SJose.Borrego@Sun.COM 	DWORD status;
18278474SJose.Borrego@Sun.COM 
18288474SJose.Borrego@Sun.COM 	se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen,
18298474SJose.Borrego@Sun.COM 	    se->se_n_total, sizeof (struct mslm_SHARE_INFO_502) + MAXNAMELEN);
18308474SJose.Borrego@Sun.COM 	if (se->se_n_enum == 0)
18318474SJose.Borrego@Sun.COM 		return (ERROR_SUCCESS);
18328474SJose.Borrego@Sun.COM 
18338474SJose.Borrego@Sun.COM 	info502 = NDR_NEWN(mxa, struct mslm_SHARE_INFO_502,
18348474SJose.Borrego@Sun.COM 	    se->se_n_enum);
18358474SJose.Borrego@Sun.COM 	if (info502 == NULL)
18368474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
18378474SJose.Borrego@Sun.COM 
18388474SJose.Borrego@Sun.COM 	smb_shr_iterinit(&iterator);
18398474SJose.Borrego@Sun.COM 
18408474SJose.Borrego@Sun.COM 	se->se_n_read = 0;
18418474SJose.Borrego@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != NULL) {
18428474SJose.Borrego@Sun.COM 		if (se->se_n_skip > 0) {
18438474SJose.Borrego@Sun.COM 			--se->se_n_skip;
18448474SJose.Borrego@Sun.COM 			continue;
18458474SJose.Borrego@Sun.COM 		}
18468474SJose.Borrego@Sun.COM 
18478474SJose.Borrego@Sun.COM 		++se->se_resume_handle;
18488474SJose.Borrego@Sun.COM 
18498474SJose.Borrego@Sun.COM 		if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
18508474SJose.Borrego@Sun.COM 			continue;
18518474SJose.Borrego@Sun.COM 
18528474SJose.Borrego@Sun.COM 		if (si->shr_flags & SMB_SHRF_AUTOHOME)
18538474SJose.Borrego@Sun.COM 			continue;
18548474SJose.Borrego@Sun.COM 
18558474SJose.Borrego@Sun.COM 		if (se->se_n_read >= se->se_n_enum) {
18568474SJose.Borrego@Sun.COM 			se->se_n_read = se->se_n_enum;
18578474SJose.Borrego@Sun.COM 			break;
18588474SJose.Borrego@Sun.COM 		}
18598474SJose.Borrego@Sun.COM 
18608474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info502);
18618474SJose.Borrego@Sun.COM 		if (status != ERROR_SUCCESS)
18628474SJose.Borrego@Sun.COM 			break;
18638474SJose.Borrego@Sun.COM 
18648474SJose.Borrego@Sun.COM 		++se->se_n_read;
18658474SJose.Borrego@Sun.COM 	}
18668474SJose.Borrego@Sun.COM 
18678474SJose.Borrego@Sun.COM 	if (se->se_n_read < se->se_n_enum) {
18688474SJose.Borrego@Sun.COM 		if (srvsvc_add_autohome(mxa, se, (void *)info502))
18698474SJose.Borrego@Sun.COM 			++se->se_n_read;
18708474SJose.Borrego@Sun.COM 	}
18718474SJose.Borrego@Sun.COM 
18728474SJose.Borrego@Sun.COM 	infonres->entriesread = se->se_n_read;
18738474SJose.Borrego@Sun.COM 	infonres->entries = info502;
18748474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
18758474SJose.Borrego@Sun.COM }
18768474SJose.Borrego@Sun.COM 
18778474SJose.Borrego@Sun.COM /*
18788474SJose.Borrego@Sun.COM  * mlsvc_NetShareEnumCommon
18798474SJose.Borrego@Sun.COM  *
18808474SJose.Borrego@Sun.COM  * Build the levels 0, 1, 2, 501 and 502 share information. This function
18818474SJose.Borrego@Sun.COM  * is called by the various NetShareEnum levels for each share. If
18828474SJose.Borrego@Sun.COM  * we cannot build the share data for some reason, we return an error
18838474SJose.Borrego@Sun.COM  * but the actual value of the error is not important to the caller.
18848474SJose.Borrego@Sun.COM  * The caller just needs to know not to include this info in the RPC
18858474SJose.Borrego@Sun.COM  * response.
18868474SJose.Borrego@Sun.COM  *
18878474SJose.Borrego@Sun.COM  * Returns:
18888474SJose.Borrego@Sun.COM  *	ERROR_SUCCESS
18898474SJose.Borrego@Sun.COM  *	ERROR_NOT_ENOUGH_MEMORY
18908474SJose.Borrego@Sun.COM  *	ERROR_INVALID_LEVEL
18918474SJose.Borrego@Sun.COM  */
18928474SJose.Borrego@Sun.COM static DWORD
18938474SJose.Borrego@Sun.COM mlsvc_NetShareEnumCommon(ndr_xa_t *mxa, srvsvc_enum_t *se,
18948474SJose.Borrego@Sun.COM     smb_share_t *si, void *infop)
18958474SJose.Borrego@Sun.COM {
18968474SJose.Borrego@Sun.COM 	struct mslm_SHARE_INFO_0 *info0;
18978474SJose.Borrego@Sun.COM 	struct mslm_SHARE_INFO_1 *info1;
18988474SJose.Borrego@Sun.COM 	struct mslm_SHARE_INFO_2 *info2;
18998474SJose.Borrego@Sun.COM 	struct mslm_SHARE_INFO_501 *info501;
19008474SJose.Borrego@Sun.COM 	struct mslm_SHARE_INFO_502 *info502;
19018474SJose.Borrego@Sun.COM 	int i = se->se_n_read;
19028474SJose.Borrego@Sun.COM 
19038474SJose.Borrego@Sun.COM 	switch (se->se_level) {
19048474SJose.Borrego@Sun.COM 	case 0:
19058474SJose.Borrego@Sun.COM 		info0 = (struct mslm_SHARE_INFO_0 *)infop;
19068474SJose.Borrego@Sun.COM 		info0[i].shi0_netname
19078474SJose.Borrego@Sun.COM 		    = (uint8_t *)NDR_STRDUP(mxa, si->shr_name);
19088474SJose.Borrego@Sun.COM 
19098474SJose.Borrego@Sun.COM 		if (info0[i].shi0_netname == NULL)
19108474SJose.Borrego@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
19118474SJose.Borrego@Sun.COM 		break;
19128474SJose.Borrego@Sun.COM 
19138474SJose.Borrego@Sun.COM 	case 1:
19148474SJose.Borrego@Sun.COM 		info1 = (struct mslm_SHARE_INFO_1 *)infop;
19158474SJose.Borrego@Sun.COM 		info1[i].shi1_netname
19168474SJose.Borrego@Sun.COM 		    = (uint8_t *)NDR_STRDUP(mxa, si->shr_name);
19178474SJose.Borrego@Sun.COM 		info1[i].shi1_remark
19188474SJose.Borrego@Sun.COM 		    = (uint8_t *)NDR_STRDUP(mxa, si->shr_cmnt);
19198474SJose.Borrego@Sun.COM 
19208474SJose.Borrego@Sun.COM 		info1[i].shi1_type = si->shr_type;
19218474SJose.Borrego@Sun.COM 
19228474SJose.Borrego@Sun.COM 		if (!info1[i].shi1_netname || !info1[i].shi1_remark)
19238474SJose.Borrego@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
19248474SJose.Borrego@Sun.COM 		break;
19258474SJose.Borrego@Sun.COM 
19268474SJose.Borrego@Sun.COM 	case 2:
19278474SJose.Borrego@Sun.COM 		info2 = (struct mslm_SHARE_INFO_2 *)infop;
19288474SJose.Borrego@Sun.COM 		info2[i].shi2_netname
19298474SJose.Borrego@Sun.COM 		    = (uint8_t *)NDR_STRDUP(mxa, si->shr_name);
19308474SJose.Borrego@Sun.COM 		info2[i].shi2_remark
19318474SJose.Borrego@Sun.COM 		    = (uint8_t *)NDR_STRDUP(mxa, si->shr_cmnt);
19328474SJose.Borrego@Sun.COM 
19338474SJose.Borrego@Sun.COM 		info2[i].shi2_path
19348474SJose.Borrego@Sun.COM 		    = (uint8_t *)srvsvc_share_mkpath(mxa, si->shr_path);
19358474SJose.Borrego@Sun.COM 
19368474SJose.Borrego@Sun.COM 		info2[i].shi2_type = si->shr_type;
19378474SJose.Borrego@Sun.COM 		info2[i].shi2_permissions = 0;
19388474SJose.Borrego@Sun.COM 		info2[i].shi2_max_uses = SHI_USES_UNLIMITED;
19398474SJose.Borrego@Sun.COM 		info2[i].shi2_current_uses = 0;
19408474SJose.Borrego@Sun.COM 		info2[i].shi2_passwd
19418474SJose.Borrego@Sun.COM 		    = (uint8_t *)NDR_STRDUP(mxa, empty_string);
19428474SJose.Borrego@Sun.COM 
19438474SJose.Borrego@Sun.COM 		if (!info2[i].shi2_netname || !info2[i].shi2_remark ||
19448474SJose.Borrego@Sun.COM 		    !info2[i].shi2_passwd || !info2[i].shi2_path)
19458474SJose.Borrego@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
19468474SJose.Borrego@Sun.COM 
19478474SJose.Borrego@Sun.COM 		break;
19488474SJose.Borrego@Sun.COM 
19498474SJose.Borrego@Sun.COM 	case 501:
19508474SJose.Borrego@Sun.COM 		info501 = (struct mslm_SHARE_INFO_501 *)infop;
19518474SJose.Borrego@Sun.COM 		info501[i].shi501_netname
19528474SJose.Borrego@Sun.COM 		    = (uint8_t *)NDR_STRDUP(mxa, si->shr_name);
19538474SJose.Borrego@Sun.COM 		info501[i].shi501_remark
19548474SJose.Borrego@Sun.COM 		    = (uint8_t *)NDR_STRDUP(mxa, si->shr_cmnt);
19558474SJose.Borrego@Sun.COM 
19568474SJose.Borrego@Sun.COM 		info501[i].shi501_type = si->shr_type;
19578474SJose.Borrego@Sun.COM 		info501[i].shi501_flags = 0;
19588474SJose.Borrego@Sun.COM 
19598474SJose.Borrego@Sun.COM 		if (!info501[i].shi501_netname || !info501[i].shi501_remark)
19608474SJose.Borrego@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
19618474SJose.Borrego@Sun.COM 		break;
19628474SJose.Borrego@Sun.COM 
19638474SJose.Borrego@Sun.COM 	case 502:
19648474SJose.Borrego@Sun.COM 		info502 = (struct mslm_SHARE_INFO_502 *)infop;
19658474SJose.Borrego@Sun.COM 		info502[i].shi502_netname
19668474SJose.Borrego@Sun.COM 		    = (uint8_t *)NDR_STRDUP(mxa, si->shr_name);
19678474SJose.Borrego@Sun.COM 		info502[i].shi502_remark
19688474SJose.Borrego@Sun.COM 		    = (uint8_t *)NDR_STRDUP(mxa, si->shr_cmnt);
19698474SJose.Borrego@Sun.COM 
19708474SJose.Borrego@Sun.COM 		info502[i].shi502_path
19718474SJose.Borrego@Sun.COM 		    = (uint8_t *)srvsvc_share_mkpath(mxa, si->shr_path);
19728474SJose.Borrego@Sun.COM 
19738474SJose.Borrego@Sun.COM 		info502[i].shi502_type = si->shr_type;
19748474SJose.Borrego@Sun.COM 		info502[i].shi502_permissions = 0;
19758474SJose.Borrego@Sun.COM 		info502[i].shi502_max_uses = SHI_USES_UNLIMITED;
19768474SJose.Borrego@Sun.COM 		info502[i].shi502_current_uses = 0;
19778474SJose.Borrego@Sun.COM 		info502[i].shi502_passwd
19788474SJose.Borrego@Sun.COM 		    = (uint8_t *)NDR_STRDUP(mxa, empty_string);
19798474SJose.Borrego@Sun.COM 
19808474SJose.Borrego@Sun.COM 		info502[i].shi502_reserved = 0;
19818474SJose.Borrego@Sun.COM 		info502[i].shi502_security_descriptor = 0;
19828474SJose.Borrego@Sun.COM 
19838474SJose.Borrego@Sun.COM 		if (!info502[i].shi502_netname || !info502[i].shi502_remark ||
19848474SJose.Borrego@Sun.COM 		    !info502[i].shi502_passwd || !info502[i].shi502_path)
19858474SJose.Borrego@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
19868474SJose.Borrego@Sun.COM 		break;
19878474SJose.Borrego@Sun.COM 
19888474SJose.Borrego@Sun.COM 	default:
19898474SJose.Borrego@Sun.COM 		return (ERROR_INVALID_LEVEL);
19908474SJose.Borrego@Sun.COM 	}
19918474SJose.Borrego@Sun.COM 
19928474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
19938474SJose.Borrego@Sun.COM }
19948474SJose.Borrego@Sun.COM 
19958474SJose.Borrego@Sun.COM /*
19968474SJose.Borrego@Sun.COM  * srvsvc_add_autohome
19978474SJose.Borrego@Sun.COM  *
19988474SJose.Borrego@Sun.COM  * Add the autohome share for the user. The share must not be a permanent
19998474SJose.Borrego@Sun.COM  * share to avoid duplicates.
20008474SJose.Borrego@Sun.COM  */
20018474SJose.Borrego@Sun.COM static boolean_t
20028474SJose.Borrego@Sun.COM srvsvc_add_autohome(ndr_xa_t *mxa, srvsvc_enum_t *se, void *infop)
20038474SJose.Borrego@Sun.COM {
20048474SJose.Borrego@Sun.COM 	smb_opipe_context_t *ctx = &mxa->pipe->np_ctx;
20058474SJose.Borrego@Sun.COM 	char *username = ctx->oc_account;
20068474SJose.Borrego@Sun.COM 	smb_share_t si;
20078474SJose.Borrego@Sun.COM 	DWORD status;
20088474SJose.Borrego@Sun.COM 
20098474SJose.Borrego@Sun.COM 	if (smb_shr_get(username, &si) != NERR_Success)
20108474SJose.Borrego@Sun.COM 		return (B_FALSE);
20118474SJose.Borrego@Sun.COM 
20128474SJose.Borrego@Sun.COM 	if ((si.shr_flags & SMB_SHRF_AUTOHOME) == 0)
20138474SJose.Borrego@Sun.COM 		return (B_FALSE);
20148474SJose.Borrego@Sun.COM 
20158474SJose.Borrego@Sun.COM 	status = mlsvc_NetShareEnumCommon(mxa, se, &si, infop);
20168474SJose.Borrego@Sun.COM 	return (status == ERROR_SUCCESS);
20178474SJose.Borrego@Sun.COM }
20188474SJose.Borrego@Sun.COM 
20198474SJose.Borrego@Sun.COM /*
20208474SJose.Borrego@Sun.COM  * srvsvc_share_mkpath
20218474SJose.Borrego@Sun.COM  *
20228474SJose.Borrego@Sun.COM  * Create the share path required by the share enum calls. The path
20238474SJose.Borrego@Sun.COM  * is created in a heap buffer ready for use by the caller.
20248474SJose.Borrego@Sun.COM  *
20258474SJose.Borrego@Sun.COM  * Some Windows over-the-wire backup applications do not work unless a
20268474SJose.Borrego@Sun.COM  * drive letter is present in the share path.  We don't care about the
20278474SJose.Borrego@Sun.COM  * drive letter since the path is fully qualified with the volume name.
20288474SJose.Borrego@Sun.COM  *
20298474SJose.Borrego@Sun.COM  * Windows clients seem to be mostly okay with forward slashes in
20308474SJose.Borrego@Sun.COM  * share paths but they cannot handle one immediately after the drive
20318474SJose.Borrego@Sun.COM  * letter, i.e. B:/.  For consistency we convert all the slashes in
20328474SJose.Borrego@Sun.COM  * the path.
20338474SJose.Borrego@Sun.COM  *
20348474SJose.Borrego@Sun.COM  * Returns a pointer to a heap buffer containing the share path, which
20358474SJose.Borrego@Sun.COM  * could be a null pointer if the heap allocation fails.
20368474SJose.Borrego@Sun.COM  */
20378474SJose.Borrego@Sun.COM static char *
20388474SJose.Borrego@Sun.COM srvsvc_share_mkpath(ndr_xa_t *mxa, char *path)
20398474SJose.Borrego@Sun.COM {
20408474SJose.Borrego@Sun.COM 	char tmpbuf[MAXPATHLEN];
20418474SJose.Borrego@Sun.COM 	char *p;
20428474SJose.Borrego@Sun.COM 
20438474SJose.Borrego@Sun.COM 	if (strlen(path) == 0)
20448474SJose.Borrego@Sun.COM 		return (NDR_STRDUP(mxa, path));
20458474SJose.Borrego@Sun.COM 
20468474SJose.Borrego@Sun.COM 	/*
20478474SJose.Borrego@Sun.COM 	 * Strip the volume name from the path (/vol1/home -> /home).
20488474SJose.Borrego@Sun.COM 	 */
20498474SJose.Borrego@Sun.COM 	p = path;
20508474SJose.Borrego@Sun.COM 	p += strspn(p, "/");
20518474SJose.Borrego@Sun.COM 	p += strcspn(p, "/");
20528474SJose.Borrego@Sun.COM 	p += strspn(p, "/");
20538474SJose.Borrego@Sun.COM 	(void) snprintf(tmpbuf, MAXPATHLEN, "%c:/%s", 'B', p);
20548474SJose.Borrego@Sun.COM 	(void) strsubst(tmpbuf, '/', '\\');
20558474SJose.Borrego@Sun.COM 
20568474SJose.Borrego@Sun.COM 	return (NDR_STRDUP(mxa, tmpbuf));
20578474SJose.Borrego@Sun.COM }
20588474SJose.Borrego@Sun.COM 
20598474SJose.Borrego@Sun.COM /*
20608474SJose.Borrego@Sun.COM  * srvsvc_s_NetShareDel
20618474SJose.Borrego@Sun.COM  *
20628474SJose.Borrego@Sun.COM  * Delete a share. Only the administrator, or a member of the domain
20638474SJose.Borrego@Sun.COM  * administrators group, is allowed to delete shares.
20648474SJose.Borrego@Sun.COM  *
20658474SJose.Borrego@Sun.COM  * This interface is used by the rmtshare command from the NT resource
20668474SJose.Borrego@Sun.COM  * kit. Rmtshare allows a client to add or remove shares on a server
20678474SJose.Borrego@Sun.COM  * from the client's command line.
20688474SJose.Borrego@Sun.COM  *
20698474SJose.Borrego@Sun.COM  * Returns Win32 error codes.
20708474SJose.Borrego@Sun.COM  */
20718474SJose.Borrego@Sun.COM static int
20728474SJose.Borrego@Sun.COM srvsvc_s_NetShareDel(void *arg, ndr_xa_t *mxa)
20738474SJose.Borrego@Sun.COM {
20748474SJose.Borrego@Sun.COM 	struct mslm_NetShareDel *param = arg;
20758474SJose.Borrego@Sun.COM 
20768474SJose.Borrego@Sun.COM 	if (!ndr_is_poweruser(mxa) ||
20778474SJose.Borrego@Sun.COM 	    smb_shr_is_restricted((char *)param->netname)) {
20788474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
20798474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
20808474SJose.Borrego@Sun.COM 	}
20818474SJose.Borrego@Sun.COM 
20828474SJose.Borrego@Sun.COM 	param->status = srvsvc_sa_delete((char *)param->netname);
20838474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
20848474SJose.Borrego@Sun.COM }
20858474SJose.Borrego@Sun.COM 
20868474SJose.Borrego@Sun.COM /*
20878474SJose.Borrego@Sun.COM  * srvsvc_s_NetGetFileSecurity
20888474SJose.Borrego@Sun.COM  *
20898474SJose.Borrego@Sun.COM  * Get security descriptor of the requested file/folder
20908474SJose.Borrego@Sun.COM  *
20918474SJose.Borrego@Sun.COM  * Right now, just returns ERROR_ACCESS_DENIED, because we cannot
20928474SJose.Borrego@Sun.COM  * get the requested SD here in RPC code.
20938474SJose.Borrego@Sun.COM  */
20948474SJose.Borrego@Sun.COM /*ARGSUSED*/
20958474SJose.Borrego@Sun.COM static int
20968474SJose.Borrego@Sun.COM srvsvc_s_NetGetFileSecurity(void *arg, ndr_xa_t *mxa)
20978474SJose.Borrego@Sun.COM {
20988474SJose.Borrego@Sun.COM 	struct mslm_NetGetFileSecurity *param = arg;
20998474SJose.Borrego@Sun.COM 
21008474SJose.Borrego@Sun.COM 	param->length = 0;
21018474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
21028474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
21038474SJose.Borrego@Sun.COM }
21048474SJose.Borrego@Sun.COM 
21058474SJose.Borrego@Sun.COM /*
21068474SJose.Borrego@Sun.COM  * srvsvc_s_NetSetFileSecurity
21078474SJose.Borrego@Sun.COM  *
21088474SJose.Borrego@Sun.COM  * Set the given security descriptor for the requested file/folder
21098474SJose.Borrego@Sun.COM  *
21108474SJose.Borrego@Sun.COM  * Right now, just returns ERROR_ACCESS_DENIED, because we cannot
21118474SJose.Borrego@Sun.COM  * set the requested SD here in RPC code.
21128474SJose.Borrego@Sun.COM  */
21138474SJose.Borrego@Sun.COM /*ARGSUSED*/
21148474SJose.Borrego@Sun.COM static int
21158474SJose.Borrego@Sun.COM srvsvc_s_NetSetFileSecurity(void *arg, ndr_xa_t *mxa)
21168474SJose.Borrego@Sun.COM {
21178474SJose.Borrego@Sun.COM 	struct mslm_NetSetFileSecurity *param = arg;
21188474SJose.Borrego@Sun.COM 
21198474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
21208474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
21218474SJose.Borrego@Sun.COM }
21228474SJose.Borrego@Sun.COM 
21238474SJose.Borrego@Sun.COM /*
21248474SJose.Borrego@Sun.COM  * If the default "smb" share group exists then return the group
21258474SJose.Borrego@Sun.COM  * handle, otherwise create the group and return the handle.
21268474SJose.Borrego@Sun.COM  *
21278474SJose.Borrego@Sun.COM  * All shares created via the srvsvc will be added to the "smb"
21288474SJose.Borrego@Sun.COM  * group.
21298474SJose.Borrego@Sun.COM  */
21308474SJose.Borrego@Sun.COM static sa_group_t
21318474SJose.Borrego@Sun.COM srvsvc_sa_get_smbgrp(sa_handle_t handle)
21328474SJose.Borrego@Sun.COM {
21338474SJose.Borrego@Sun.COM 	sa_group_t group = NULL;
21348474SJose.Borrego@Sun.COM 	int err;
21358474SJose.Borrego@Sun.COM 
21368474SJose.Borrego@Sun.COM 	group = sa_get_group(handle, SMB_DEFAULT_SHARE_GROUP);
21378474SJose.Borrego@Sun.COM 	if (group != NULL)
21388474SJose.Borrego@Sun.COM 		return (group);
21398474SJose.Borrego@Sun.COM 
21408474SJose.Borrego@Sun.COM 	group = sa_create_group(handle, SMB_DEFAULT_SHARE_GROUP, &err);
21418474SJose.Borrego@Sun.COM 	if (group == NULL)
21428474SJose.Borrego@Sun.COM 		return (NULL);
21438474SJose.Borrego@Sun.COM 
21448474SJose.Borrego@Sun.COM 	if (sa_create_optionset(group, SMB_DEFAULT_SHARE_GROUP) == NULL) {
21458474SJose.Borrego@Sun.COM 		(void) sa_remove_group(group);
21468474SJose.Borrego@Sun.COM 		group = NULL;
21478474SJose.Borrego@Sun.COM 	}
21488474SJose.Borrego@Sun.COM 
21498474SJose.Borrego@Sun.COM 	return (group);
21508474SJose.Borrego@Sun.COM }
21518474SJose.Borrego@Sun.COM 
21528474SJose.Borrego@Sun.COM /*
21538474SJose.Borrego@Sun.COM  * Stores the given share in sharemgr
21548474SJose.Borrego@Sun.COM  */
21558474SJose.Borrego@Sun.COM static uint32_t
21568474SJose.Borrego@Sun.COM srvsvc_sa_add(char *sharename, char *path, char *cmnt)
21578474SJose.Borrego@Sun.COM {
21588474SJose.Borrego@Sun.COM 	sa_handle_t handle;
21598474SJose.Borrego@Sun.COM 	sa_share_t share;
21608474SJose.Borrego@Sun.COM 	sa_group_t group;
21618474SJose.Borrego@Sun.COM 	sa_resource_t resource;
21628474SJose.Borrego@Sun.COM 	boolean_t new_share = B_FALSE;
21638474SJose.Borrego@Sun.COM 	uint32_t status = NERR_Success;
21648474SJose.Borrego@Sun.COM 	int err;
21658474SJose.Borrego@Sun.COM 
21668474SJose.Borrego@Sun.COM 	if ((handle = smb_shr_sa_enter()) == NULL)
21678474SJose.Borrego@Sun.COM 		return (NERR_InternalError);
21688474SJose.Borrego@Sun.COM 
21698474SJose.Borrego@Sun.COM 	share = sa_find_share(handle, path);
21708474SJose.Borrego@Sun.COM 	if (share == NULL) {
21718474SJose.Borrego@Sun.COM 		group = srvsvc_sa_get_smbgrp(handle);
21728474SJose.Borrego@Sun.COM 		if (group == NULL) {
21738474SJose.Borrego@Sun.COM 			smb_shr_sa_exit();
21748474SJose.Borrego@Sun.COM 			return (NERR_InternalError);
21758474SJose.Borrego@Sun.COM 		}
21768474SJose.Borrego@Sun.COM 
21778474SJose.Borrego@Sun.COM 		share = sa_add_share(group, path, SA_SHARE_PERMANENT, &err);
21788474SJose.Borrego@Sun.COM 		if (share == NULL) {
21798474SJose.Borrego@Sun.COM 			smb_shr_sa_exit();
21808474SJose.Borrego@Sun.COM 			return (NERR_InternalError);
21818474SJose.Borrego@Sun.COM 		}
21828474SJose.Borrego@Sun.COM 		new_share = B_TRUE;
21838474SJose.Borrego@Sun.COM 	}
21848474SJose.Borrego@Sun.COM 
21858474SJose.Borrego@Sun.COM 	resource = sa_get_share_resource(share, sharename);
21868474SJose.Borrego@Sun.COM 	if (resource == NULL) {
21878474SJose.Borrego@Sun.COM 		resource = sa_add_resource(share, sharename,
21888474SJose.Borrego@Sun.COM 		    SA_SHARE_PERMANENT, &err);
21898474SJose.Borrego@Sun.COM 		if (resource == NULL) {
21908474SJose.Borrego@Sun.COM 			if (new_share)
21918474SJose.Borrego@Sun.COM 				(void) sa_remove_share(share);
21928474SJose.Borrego@Sun.COM 			smb_shr_sa_exit();
21938474SJose.Borrego@Sun.COM 			return (NERR_InternalError);
21948474SJose.Borrego@Sun.COM 		}
21958474SJose.Borrego@Sun.COM 	}
21968474SJose.Borrego@Sun.COM 
21978474SJose.Borrego@Sun.COM 	(void) sa_set_resource_description(resource, cmnt);
21988474SJose.Borrego@Sun.COM 
21998474SJose.Borrego@Sun.COM 	smb_shr_sa_exit();
22008474SJose.Borrego@Sun.COM 	return (status);
22018474SJose.Borrego@Sun.COM }
22028474SJose.Borrego@Sun.COM 
22038474SJose.Borrego@Sun.COM /*
22048474SJose.Borrego@Sun.COM  * Removes the share from sharemgr
22058474SJose.Borrego@Sun.COM  */
22068474SJose.Borrego@Sun.COM static uint32_t
22078474SJose.Borrego@Sun.COM srvsvc_sa_delete(char *sharename)
22088474SJose.Borrego@Sun.COM {
22098474SJose.Borrego@Sun.COM 	sa_handle_t handle;
22108474SJose.Borrego@Sun.COM 	sa_resource_t resource;
22118474SJose.Borrego@Sun.COM 	uint32_t status;
22128474SJose.Borrego@Sun.COM 
22138474SJose.Borrego@Sun.COM 	if ((handle = smb_shr_sa_enter()) == NULL)
22148474SJose.Borrego@Sun.COM 		return (NERR_InternalError);
22158474SJose.Borrego@Sun.COM 
22168474SJose.Borrego@Sun.COM 	status = NERR_InternalError;
22178474SJose.Borrego@Sun.COM 	if ((resource = sa_find_resource(handle, sharename)) != NULL) {
22188474SJose.Borrego@Sun.COM 		if (sa_remove_resource(resource) == SA_OK)
22198474SJose.Borrego@Sun.COM 			status = NERR_Success;
22208474SJose.Borrego@Sun.COM 	}
22218474SJose.Borrego@Sun.COM 
22228474SJose.Borrego@Sun.COM 	smb_shr_sa_exit();
22238474SJose.Borrego@Sun.COM 	return (status);
22248474SJose.Borrego@Sun.COM }
22258474SJose.Borrego@Sun.COM 
22268474SJose.Borrego@Sun.COM static ndr_stub_table_t srvsvc_stub_table[] = {
22278474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetConnectEnum,	SRVSVC_OPNUM_NetConnectEnum },
22288474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetFileEnum,		SRVSVC_OPNUM_NetFileEnum },
22298474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetFileClose,	SRVSVC_OPNUM_NetFileClose },
22308474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetShareGetInfo,	SRVSVC_OPNUM_NetShareGetInfo },
22318474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetShareSetInfo,	SRVSVC_OPNUM_NetShareSetInfo },
22328474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetSessionEnum,	SRVSVC_OPNUM_NetSessionEnum },
22338474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetSessionDel,	SRVSVC_OPNUM_NetSessionDel },
22348474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetServerGetInfo,	SRVSVC_OPNUM_NetServerGetInfo },
22358474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetRemoteTOD,	SRVSVC_OPNUM_NetRemoteTOD },
22368474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetNameValidate,	SRVSVC_OPNUM_NetNameValidate },
22378474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetShareAdd,		SRVSVC_OPNUM_NetShareAdd },
22388474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetShareDel,		SRVSVC_OPNUM_NetShareDel },
22398474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetShareEnum,	SRVSVC_OPNUM_NetShareEnum },
22408474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetShareEnumSticky,	SRVSVC_OPNUM_NetShareEnumSticky },
22418474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetGetFileSecurity,	SRVSVC_OPNUM_NetGetFileSecurity },
22428474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetSetFileSecurity,	SRVSVC_OPNUM_NetSetFileSecurity },
22438474SJose.Borrego@Sun.COM 	{0}
22448474SJose.Borrego@Sun.COM };
2245