xref: /onnv-gate/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c (revision 12508:edb7861a1533)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw /*
2212065SKeyur.Desai@Sun.COM  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
235331Samw  */
245331Samw 
2511963SAfshin.Ardakani@Sun.COM #include <sys/list.h>
2611963SAfshin.Ardakani@Sun.COM #include <assert.h>
275331Samw #include <alloca.h>
285331Samw #include <door.h>
295331Samw #include <errno.h>
305331Samw #include <syslog.h>
315331Samw #include <unistd.h>
325331Samw #include <stdio.h>
335331Samw #include <synch.h>
345331Samw #include <string.h>
355331Samw #include <stdlib.h>
365331Samw #include <sys/stat.h>
375331Samw #include <fcntl.h>
385331Samw #include <pthread.h>
395331Samw #include <strings.h>
4011963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_door.h>
4111963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_xdr.h>
4211963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_token.h>
4311963SAfshin.Ardakani@Sun.COM #include <smbsrv/libmlsvc.h>
4411963SAfshin.Ardakani@Sun.COM #include <smbsrv/libsmbns.h>
4511963SAfshin.Ardakani@Sun.COM #include "smbd.h"
465331Samw 
4712065SKeyur.Desai@Sun.COM #define	SMBD_ARG_MAGIC		0x53415247	/* 'SARG' */
4812065SKeyur.Desai@Sun.COM 
4911963SAfshin.Ardakani@Sun.COM /*
5011963SAfshin.Ardakani@Sun.COM  * Parameter for door operations.
5111963SAfshin.Ardakani@Sun.COM  */
5211963SAfshin.Ardakani@Sun.COM typedef struct smbd_arg {
5312065SKeyur.Desai@Sun.COM 	uint32_t	magic;
5411963SAfshin.Ardakani@Sun.COM 	list_node_t	lnd;
5511963SAfshin.Ardakani@Sun.COM 	smb_doorhdr_t	hdr;
5611963SAfshin.Ardakani@Sun.COM 	const char	*opname;
5711963SAfshin.Ardakani@Sun.COM 	char		*data;
5811963SAfshin.Ardakani@Sun.COM 	size_t		datalen;
5911963SAfshin.Ardakani@Sun.COM 	char		*rbuf;
6011963SAfshin.Ardakani@Sun.COM 	size_t		rsize;
6112065SKeyur.Desai@Sun.COM 	boolean_t	response_ready;
6212065SKeyur.Desai@Sun.COM 	boolean_t	response_abort;
6311963SAfshin.Ardakani@Sun.COM 	uint32_t	status;
6411963SAfshin.Ardakani@Sun.COM } smbd_arg_t;
655331Samw 
665331Samw /*
6711963SAfshin.Ardakani@Sun.COM  * The list contains asynchronous requests that have been initiated
6811963SAfshin.Ardakani@Sun.COM  * but have not yet been collected (via smbd_dop_async_response).
6911963SAfshin.Ardakani@Sun.COM  */
7011963SAfshin.Ardakani@Sun.COM typedef struct smbd_doorsvc {
7111963SAfshin.Ardakani@Sun.COM 	mutex_t		sd_mutex;
7211963SAfshin.Ardakani@Sun.COM 	cond_t		sd_cv;
7311963SAfshin.Ardakani@Sun.COM 	list_t		sd_async_list;
7411963SAfshin.Ardakani@Sun.COM 	uint32_t	sd_async_count;
7511963SAfshin.Ardakani@Sun.COM } smbd_doorsvc_t;
7611963SAfshin.Ardakani@Sun.COM 
7711963SAfshin.Ardakani@Sun.COM static int smbd_dop_null(smbd_arg_t *);
7811963SAfshin.Ardakani@Sun.COM static int smbd_dop_async_response(smbd_arg_t *);
7911963SAfshin.Ardakani@Sun.COM static int smbd_dop_user_auth_logon(smbd_arg_t *);
8011963SAfshin.Ardakani@Sun.COM static int smbd_dop_user_nonauth_logon(smbd_arg_t *);
8111963SAfshin.Ardakani@Sun.COM static int smbd_dop_user_auth_logoff(smbd_arg_t *);
8211963SAfshin.Ardakani@Sun.COM static int smbd_dop_lookup_sid(smbd_arg_t *);
8311963SAfshin.Ardakani@Sun.COM static int smbd_dop_lookup_name(smbd_arg_t *);
8411963SAfshin.Ardakani@Sun.COM static int smbd_dop_join(smbd_arg_t *);
8511963SAfshin.Ardakani@Sun.COM static int smbd_dop_get_dcinfo(smbd_arg_t *);
8611963SAfshin.Ardakani@Sun.COM static int smbd_dop_vss_get_count(smbd_arg_t *);
8711963SAfshin.Ardakani@Sun.COM static int smbd_dop_vss_get_snapshots(smbd_arg_t *);
8811963SAfshin.Ardakani@Sun.COM static int smbd_dop_vss_map_gmttoken(smbd_arg_t *);
8911963SAfshin.Ardakani@Sun.COM static int smbd_dop_ads_find_host(smbd_arg_t *);
9011963SAfshin.Ardakani@Sun.COM static int smbd_dop_quota_query(smbd_arg_t *);
9111963SAfshin.Ardakani@Sun.COM static int smbd_dop_quota_set(smbd_arg_t *);
9211963SAfshin.Ardakani@Sun.COM static int smbd_dop_dfs_get_referrals(smbd_arg_t *);
93*12508Samw@Sun.COM static int smbd_dop_shr_hostaccess(smbd_arg_t *);
94*12508Samw@Sun.COM static int smbd_dop_shr_exec(smbd_arg_t *);
9511963SAfshin.Ardakani@Sun.COM 
9611963SAfshin.Ardakani@Sun.COM typedef int (*smbd_dop_t)(smbd_arg_t *);
9711963SAfshin.Ardakani@Sun.COM 
9811963SAfshin.Ardakani@Sun.COM typedef struct smbd_doorop {
9911963SAfshin.Ardakani@Sun.COM 	smb_dopcode_t	opcode;
10011963SAfshin.Ardakani@Sun.COM 	smbd_dop_t	op;
10111963SAfshin.Ardakani@Sun.COM } smbd_doorop_t;
10211963SAfshin.Ardakani@Sun.COM 
10311963SAfshin.Ardakani@Sun.COM smbd_doorop_t smbd_doorops[] = {
10411963SAfshin.Ardakani@Sun.COM 	{ SMB_DR_NULL,			smbd_dop_null },
10511963SAfshin.Ardakani@Sun.COM 	{ SMB_DR_ASYNC_RESPONSE,	smbd_dop_async_response },
10611963SAfshin.Ardakani@Sun.COM 	{ SMB_DR_USER_AUTH_LOGON,	smbd_dop_user_auth_logon },
10711963SAfshin.Ardakani@Sun.COM 	{ SMB_DR_USER_NONAUTH_LOGON,	smbd_dop_user_nonauth_logon },
10811963SAfshin.Ardakani@Sun.COM 	{ SMB_DR_USER_AUTH_LOGOFF,	smbd_dop_user_auth_logoff },
10911963SAfshin.Ardakani@Sun.COM 	{ SMB_DR_LOOKUP_SID,		smbd_dop_lookup_sid },
11011963SAfshin.Ardakani@Sun.COM 	{ SMB_DR_LOOKUP_NAME,		smbd_dop_lookup_name },
11111963SAfshin.Ardakani@Sun.COM 	{ SMB_DR_JOIN,			smbd_dop_join },
11211963SAfshin.Ardakani@Sun.COM 	{ SMB_DR_GET_DCINFO,		smbd_dop_get_dcinfo },
11311963SAfshin.Ardakani@Sun.COM 	{ SMB_DR_VSS_GET_COUNT,		smbd_dop_vss_get_count },
11411963SAfshin.Ardakani@Sun.COM 	{ SMB_DR_VSS_GET_SNAPSHOTS,	smbd_dop_vss_get_snapshots },
11511963SAfshin.Ardakani@Sun.COM 	{ SMB_DR_VSS_MAP_GMTTOKEN,	smbd_dop_vss_map_gmttoken },
11611963SAfshin.Ardakani@Sun.COM 	{ SMB_DR_ADS_FIND_HOST,		smbd_dop_ads_find_host },
11711963SAfshin.Ardakani@Sun.COM 	{ SMB_DR_QUOTA_QUERY,		smbd_dop_quota_query },
11811963SAfshin.Ardakani@Sun.COM 	{ SMB_DR_QUOTA_SET,		smbd_dop_quota_set },
119*12508Samw@Sun.COM 	{ SMB_DR_DFS_GET_REFERRALS,	smbd_dop_dfs_get_referrals },
120*12508Samw@Sun.COM 	{ SMB_DR_SHR_HOSTACCESS,	smbd_dop_shr_hostaccess },
121*12508Samw@Sun.COM 	{ SMB_DR_SHR_EXEC,		smbd_dop_shr_exec }
12211963SAfshin.Ardakani@Sun.COM };
12311963SAfshin.Ardakani@Sun.COM 
12411963SAfshin.Ardakani@Sun.COM static int smbd_ndoorop = (sizeof (smbd_doorops) / sizeof (smbd_doorops[0]));
12511963SAfshin.Ardakani@Sun.COM 
12611963SAfshin.Ardakani@Sun.COM static smbd_doorsvc_t smbd_doorsvc;
12711963SAfshin.Ardakani@Sun.COM static int smbd_door_fd = -1;
12811963SAfshin.Ardakani@Sun.COM static int smbd_door_cookie = 0x534D4244;	/* SMBD */
12911963SAfshin.Ardakani@Sun.COM static smbd_door_t smbd_door_sdh;
13011963SAfshin.Ardakani@Sun.COM 
13111963SAfshin.Ardakani@Sun.COM static void smbd_door_dispatch(void *, char *, size_t, door_desc_t *, uint_t);
13211963SAfshin.Ardakani@Sun.COM static int smbd_door_dispatch_async(smbd_arg_t *);
13311963SAfshin.Ardakani@Sun.COM static void smbd_door_release_async(smbd_arg_t *);
13411963SAfshin.Ardakani@Sun.COM static void *smbd_door_dispatch_op(void *);
13511963SAfshin.Ardakani@Sun.COM 
13611963SAfshin.Ardakani@Sun.COM /*
1375331Samw  * Start the smbd door service.  Create and bind to a door.
1385331Samw  * Returns 0 on success. Otherwise, -1.
1395331Samw  */
1405331Samw int
smbd_door_start(void)14111963SAfshin.Ardakani@Sun.COM smbd_door_start(void)
1425331Samw {
1436139Sjb150015 	int	newfd;
1445331Samw 
14511963SAfshin.Ardakani@Sun.COM 	(void) mutex_lock(&smbd_doorsvc.sd_mutex);
1465331Samw 
14711963SAfshin.Ardakani@Sun.COM 	if (smbd_door_fd != -1) {
1485331Samw 		(void) fprintf(stderr, "smb_doorsrv_start: already started");
14911963SAfshin.Ardakani@Sun.COM 		(void) mutex_unlock(&smbd_doorsvc.sd_mutex);
1505331Samw 		return (-1);
1515331Samw 	}
1525331Samw 
15311963SAfshin.Ardakani@Sun.COM 	smbd_door_init(&smbd_door_sdh, "doorsrv");
15411963SAfshin.Ardakani@Sun.COM 
15511963SAfshin.Ardakani@Sun.COM 	list_create(&smbd_doorsvc.sd_async_list, sizeof (smbd_arg_t),
15611963SAfshin.Ardakani@Sun.COM 	    offsetof(smbd_arg_t, lnd));
15711963SAfshin.Ardakani@Sun.COM 	smbd_doorsvc.sd_async_count = 0;
15811963SAfshin.Ardakani@Sun.COM 
15911963SAfshin.Ardakani@Sun.COM 	if ((smbd_door_fd = door_create(smbd_door_dispatch,
16011963SAfshin.Ardakani@Sun.COM 	    &smbd_door_cookie, DOOR_UNREF)) < 0) {
1615331Samw 		(void) fprintf(stderr, "smb_doorsrv_start: door_create: %s",
1625331Samw 		    strerror(errno));
16311963SAfshin.Ardakani@Sun.COM 		smbd_door_fd = -1;
16411963SAfshin.Ardakani@Sun.COM 		(void) mutex_unlock(&smbd_doorsvc.sd_mutex);
1655331Samw 		return (-1);
1665331Samw 	}
1675331Samw 
16811963SAfshin.Ardakani@Sun.COM 	(void) unlink(SMBD_DOOR_NAME);
1695331Samw 
17011963SAfshin.Ardakani@Sun.COM 	if ((newfd = creat(SMBD_DOOR_NAME, 0644)) < 0) {
1715331Samw 		(void) fprintf(stderr, "smb_doorsrv_start: open: %s",
1725331Samw 		    strerror(errno));
17311963SAfshin.Ardakani@Sun.COM 		(void) door_revoke(smbd_door_fd);
17411963SAfshin.Ardakani@Sun.COM 		smbd_door_fd = -1;
17511963SAfshin.Ardakani@Sun.COM 		(void) mutex_unlock(&smbd_doorsvc.sd_mutex);
1765331Samw 		return (-1);
1775331Samw 	}
1785331Samw 
1795331Samw 	(void) close(newfd);
18011963SAfshin.Ardakani@Sun.COM 	(void) fdetach(SMBD_DOOR_NAME);
1815331Samw 
18211963SAfshin.Ardakani@Sun.COM 	if (fattach(smbd_door_fd, SMBD_DOOR_NAME) < 0) {
1835331Samw 		(void) fprintf(stderr, "smb_doorsrv_start: fattach: %s",
1845331Samw 		    strerror(errno));
18511963SAfshin.Ardakani@Sun.COM 		(void) door_revoke(smbd_door_fd);
18611963SAfshin.Ardakani@Sun.COM 		smbd_door_fd = -1;
18711963SAfshin.Ardakani@Sun.COM 		(void) mutex_unlock(&smbd_doorsvc.sd_mutex);
1885331Samw 		return (-1);
1895331Samw 	}
1905331Samw 
19111963SAfshin.Ardakani@Sun.COM 	(void) mutex_unlock(&smbd_doorsvc.sd_mutex);
19211963SAfshin.Ardakani@Sun.COM 	return (smbd_door_fd);
1935331Samw }
1945331Samw 
1955331Samw /*
1965331Samw  * Stop the smbd door service.
1975331Samw  */
1985331Samw void
smbd_door_stop(void)19911963SAfshin.Ardakani@Sun.COM smbd_door_stop(void)
20011963SAfshin.Ardakani@Sun.COM {
20111963SAfshin.Ardakani@Sun.COM 	(void) mutex_lock(&smbd_doorsvc.sd_mutex);
20211963SAfshin.Ardakani@Sun.COM 
20311963SAfshin.Ardakani@Sun.COM 	smbd_door_fini(&smbd_door_sdh);
20411963SAfshin.Ardakani@Sun.COM 
20511963SAfshin.Ardakani@Sun.COM 	if (smbd_door_fd != -1) {
20611963SAfshin.Ardakani@Sun.COM 		(void) fdetach(SMBD_DOOR_NAME);
20711963SAfshin.Ardakani@Sun.COM 		(void) door_revoke(smbd_door_fd);
20811963SAfshin.Ardakani@Sun.COM 		smbd_door_fd = -1;
20911963SAfshin.Ardakani@Sun.COM 	}
21011963SAfshin.Ardakani@Sun.COM 
21111963SAfshin.Ardakani@Sun.COM 	(void) mutex_unlock(&smbd_doorsvc.sd_mutex);
21211963SAfshin.Ardakani@Sun.COM }
21311963SAfshin.Ardakani@Sun.COM 
21411963SAfshin.Ardakani@Sun.COM /*ARGSUSED*/
21511963SAfshin.Ardakani@Sun.COM static void
smbd_door_dispatch(void * cookie,char * argp,size_t arg_size,door_desc_t * dp,uint_t n_desc)21611963SAfshin.Ardakani@Sun.COM smbd_door_dispatch(void *cookie, char *argp, size_t arg_size, door_desc_t *dp,
21711963SAfshin.Ardakani@Sun.COM     uint_t n_desc)
2185331Samw {
21911963SAfshin.Ardakani@Sun.COM 	smbd_arg_t	dop_arg;
22011963SAfshin.Ardakani@Sun.COM 	smb_doorhdr_t	*hdr;
22111963SAfshin.Ardakani@Sun.COM 	size_t		hdr_size;
22211963SAfshin.Ardakani@Sun.COM 	char		*rbuf = NULL;
22311963SAfshin.Ardakani@Sun.COM 
22411963SAfshin.Ardakani@Sun.COM 	smbd_door_enter(&smbd_door_sdh);
22511963SAfshin.Ardakani@Sun.COM 
22611963SAfshin.Ardakani@Sun.COM 	if (!smbd_online())
22711963SAfshin.Ardakani@Sun.COM 		smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0);
22811963SAfshin.Ardakani@Sun.COM 
22911963SAfshin.Ardakani@Sun.COM 	bzero(&dop_arg, sizeof (smbd_arg_t));
23011963SAfshin.Ardakani@Sun.COM 	hdr = &dop_arg.hdr;
23111963SAfshin.Ardakani@Sun.COM 	hdr_size = xdr_sizeof(smb_doorhdr_xdr, hdr);
23211963SAfshin.Ardakani@Sun.COM 
23311963SAfshin.Ardakani@Sun.COM 	if ((cookie != &smbd_door_cookie) || (argp == NULL) ||
23411963SAfshin.Ardakani@Sun.COM 	    (arg_size < hdr_size)) {
23511963SAfshin.Ardakani@Sun.COM 		smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0);
23611963SAfshin.Ardakani@Sun.COM 	}
23711963SAfshin.Ardakani@Sun.COM 
23811963SAfshin.Ardakani@Sun.COM 	if (smb_doorhdr_decode(hdr, (uint8_t *)argp, hdr_size) == -1) {
23911963SAfshin.Ardakani@Sun.COM 		syslog(LOG_DEBUG, "smbd_door_dispatch: header decode failed");
24011963SAfshin.Ardakani@Sun.COM 		smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0);
24111963SAfshin.Ardakani@Sun.COM 	}
24211963SAfshin.Ardakani@Sun.COM 
24311963SAfshin.Ardakani@Sun.COM 	if ((hdr->dh_magic != SMB_DOOR_HDR_MAGIC) || (hdr->dh_txid == 0)) {
24411963SAfshin.Ardakani@Sun.COM 		syslog(LOG_DEBUG, "smbd_door_dispatch: invalid header");
24511963SAfshin.Ardakani@Sun.COM 		smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0);
24611963SAfshin.Ardakani@Sun.COM 	}
24711963SAfshin.Ardakani@Sun.COM 
24811963SAfshin.Ardakani@Sun.COM 	dop_arg.opname = smb_doorhdr_opname(hdr->dh_op);
24911963SAfshin.Ardakani@Sun.COM 	dop_arg.data = argp + hdr_size;
25011963SAfshin.Ardakani@Sun.COM 	dop_arg.datalen = hdr->dh_datalen;
25111963SAfshin.Ardakani@Sun.COM 
25211963SAfshin.Ardakani@Sun.COM 	if (hdr->dh_op == SMB_DR_ASYNC_RESPONSE) {
25311963SAfshin.Ardakani@Sun.COM 		/*
25411963SAfshin.Ardakani@Sun.COM 		 * ASYNC_RESPONSE is used to collect the response
25511963SAfshin.Ardakani@Sun.COM 		 * to an async call; it cannot be an async call.
25611963SAfshin.Ardakani@Sun.COM 		 */
25711963SAfshin.Ardakani@Sun.COM 		hdr->dh_flags &= ~SMB_DF_ASYNC;
25811963SAfshin.Ardakani@Sun.COM 	}
25911963SAfshin.Ardakani@Sun.COM 
26011963SAfshin.Ardakani@Sun.COM 	if (hdr->dh_flags & SMB_DF_ASYNC) {
26111963SAfshin.Ardakani@Sun.COM 		if (smbd_door_dispatch_async(&dop_arg) == 0)
26211963SAfshin.Ardakani@Sun.COM 			hdr->dh_door_rc = SMB_DOP_SUCCESS;
26311963SAfshin.Ardakani@Sun.COM 		else
26411963SAfshin.Ardakani@Sun.COM 			hdr->dh_door_rc = SMB_DOP_NOT_CALLED;
26511963SAfshin.Ardakani@Sun.COM 	} else {
26611963SAfshin.Ardakani@Sun.COM 		(void) smbd_door_dispatch_op(&dop_arg);
26711963SAfshin.Ardakani@Sun.COM 	}
2685331Samw 
26911963SAfshin.Ardakani@Sun.COM 	if ((rbuf = (char *)alloca(dop_arg.rsize + hdr_size)) == NULL) {
27011963SAfshin.Ardakani@Sun.COM 		errno = ENOMEM;
27111963SAfshin.Ardakani@Sun.COM 		syslog(LOG_DEBUG, "smbd_door_dispatch[%s]: alloca %m",
27211963SAfshin.Ardakani@Sun.COM 		    dop_arg.opname);
27311963SAfshin.Ardakani@Sun.COM 		smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0);
27411963SAfshin.Ardakani@Sun.COM 	}
27511963SAfshin.Ardakani@Sun.COM 
27611963SAfshin.Ardakani@Sun.COM 	if (dop_arg.rbuf != NULL) {
27711963SAfshin.Ardakani@Sun.COM 		(void) memcpy(rbuf + hdr_size, dop_arg.rbuf, dop_arg.rsize);
27811963SAfshin.Ardakani@Sun.COM 		free(dop_arg.rbuf);
27911963SAfshin.Ardakani@Sun.COM 	}
28011963SAfshin.Ardakani@Sun.COM 
28111963SAfshin.Ardakani@Sun.COM 	hdr->dh_datalen = dop_arg.rsize;
28211963SAfshin.Ardakani@Sun.COM 	(void) smb_doorhdr_encode(hdr, (uint8_t *)rbuf, hdr_size);
28311963SAfshin.Ardakani@Sun.COM 	dop_arg.rsize += hdr_size;
28411963SAfshin.Ardakani@Sun.COM 
28511963SAfshin.Ardakani@Sun.COM 	smbd_door_return(&smbd_door_sdh, rbuf, dop_arg.rsize, NULL, 0);
28611963SAfshin.Ardakani@Sun.COM 	/*NOTREACHED*/
28711963SAfshin.Ardakani@Sun.COM }
28811963SAfshin.Ardakani@Sun.COM 
28911963SAfshin.Ardakani@Sun.COM /*
29011963SAfshin.Ardakani@Sun.COM  * Launch a thread to process an asynchronous door call.
29111963SAfshin.Ardakani@Sun.COM  */
29211963SAfshin.Ardakani@Sun.COM static int
smbd_door_dispatch_async(smbd_arg_t * req_arg)29311963SAfshin.Ardakani@Sun.COM smbd_door_dispatch_async(smbd_arg_t *req_arg)
29411963SAfshin.Ardakani@Sun.COM {
29511963SAfshin.Ardakani@Sun.COM 	smbd_arg_t	*arg = NULL;
29611963SAfshin.Ardakani@Sun.COM 	char		*data = NULL;
29711963SAfshin.Ardakani@Sun.COM 	pthread_attr_t	attr;
29811963SAfshin.Ardakani@Sun.COM 	pthread_t	tid;
29911963SAfshin.Ardakani@Sun.COM 	int		rc;
30011963SAfshin.Ardakani@Sun.COM 
30111963SAfshin.Ardakani@Sun.COM 	if ((req_arg->hdr.dh_flags & SMB_DF_ASYNC) == 0) {
30211963SAfshin.Ardakani@Sun.COM 		errno = EINVAL;
30311963SAfshin.Ardakani@Sun.COM 		return (-1);
30411963SAfshin.Ardakani@Sun.COM 	}
30511963SAfshin.Ardakani@Sun.COM 
30611963SAfshin.Ardakani@Sun.COM 	if ((arg = malloc(sizeof (smbd_arg_t))) == NULL) {
30711963SAfshin.Ardakani@Sun.COM 		syslog(LOG_DEBUG, "smbd_door_dispatch_async[%s]: %m",
30811963SAfshin.Ardakani@Sun.COM 		    req_arg->opname);
30911963SAfshin.Ardakani@Sun.COM 		return (-1);
31011963SAfshin.Ardakani@Sun.COM 	}
31111963SAfshin.Ardakani@Sun.COM 
31211963SAfshin.Ardakani@Sun.COM 	(void) memcpy(arg, req_arg, sizeof (smbd_arg_t));
31311963SAfshin.Ardakani@Sun.COM 	arg->data = NULL;
31411963SAfshin.Ardakani@Sun.COM 
31511963SAfshin.Ardakani@Sun.COM 	if (req_arg->datalen != 0) {
31611963SAfshin.Ardakani@Sun.COM 		if ((data = malloc(req_arg->datalen)) == NULL) {
31711963SAfshin.Ardakani@Sun.COM 			free(arg);
31811963SAfshin.Ardakani@Sun.COM 			syslog(LOG_DEBUG, "smbd_door_dispatch_async[%s]: %m",
31911963SAfshin.Ardakani@Sun.COM 			    req_arg->opname);
32011963SAfshin.Ardakani@Sun.COM 			return (-1);
32111963SAfshin.Ardakani@Sun.COM 		}
32211963SAfshin.Ardakani@Sun.COM 
32311963SAfshin.Ardakani@Sun.COM 		(void) memcpy(data, req_arg->data, req_arg->datalen);
32411963SAfshin.Ardakani@Sun.COM 		arg->data = data;
32511963SAfshin.Ardakani@Sun.COM 	}
32611963SAfshin.Ardakani@Sun.COM 
32711963SAfshin.Ardakani@Sun.COM 	(void) mutex_lock(&smbd_doorsvc.sd_mutex);
32812065SKeyur.Desai@Sun.COM 	arg->magic = SMBD_ARG_MAGIC;
32911963SAfshin.Ardakani@Sun.COM 	list_insert_tail(&smbd_doorsvc.sd_async_list, arg);
33011963SAfshin.Ardakani@Sun.COM 	++smbd_doorsvc.sd_async_count;
33111963SAfshin.Ardakani@Sun.COM 	(void) mutex_unlock(&smbd_doorsvc.sd_mutex);
33211963SAfshin.Ardakani@Sun.COM 
33311963SAfshin.Ardakani@Sun.COM 	(void) pthread_attr_init(&attr);
33411963SAfshin.Ardakani@Sun.COM 	(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
33511963SAfshin.Ardakani@Sun.COM 	rc = pthread_create(&tid, &attr, smbd_door_dispatch_op, arg);
33611963SAfshin.Ardakani@Sun.COM 	(void) pthread_attr_destroy(&attr);
33711963SAfshin.Ardakani@Sun.COM 
33811963SAfshin.Ardakani@Sun.COM 	if (rc != 0) {
33911963SAfshin.Ardakani@Sun.COM 		(void) mutex_lock(&smbd_doorsvc.sd_mutex);
34011963SAfshin.Ardakani@Sun.COM 		smbd_door_release_async(arg);
34111963SAfshin.Ardakani@Sun.COM 		(void) mutex_unlock(&smbd_doorsvc.sd_mutex);
3425331Samw 	}
3435331Samw 
34411963SAfshin.Ardakani@Sun.COM 	return (rc);
34511963SAfshin.Ardakani@Sun.COM }
34611963SAfshin.Ardakani@Sun.COM 
34711963SAfshin.Ardakani@Sun.COM /*
34811963SAfshin.Ardakani@Sun.COM  * Remove an entry from the async response pending list and free
34911963SAfshin.Ardakani@Sun.COM  * the arg and associated data.
35011963SAfshin.Ardakani@Sun.COM  *
35111963SAfshin.Ardakani@Sun.COM  * Must only be called while holding the smbd_doorsvc mutex.
35211963SAfshin.Ardakani@Sun.COM  */
35311963SAfshin.Ardakani@Sun.COM static void
smbd_door_release_async(smbd_arg_t * arg)35411963SAfshin.Ardakani@Sun.COM smbd_door_release_async(smbd_arg_t *arg)
35511963SAfshin.Ardakani@Sun.COM {
35611963SAfshin.Ardakani@Sun.COM 	if (arg != NULL) {
35712065SKeyur.Desai@Sun.COM 		assert(arg->magic == SMBD_ARG_MAGIC);
35812065SKeyur.Desai@Sun.COM 		arg->magic = (uint32_t)~SMBD_ARG_MAGIC;
35912065SKeyur.Desai@Sun.COM 
36011963SAfshin.Ardakani@Sun.COM 		list_remove(&smbd_doorsvc.sd_async_list, arg);
36111963SAfshin.Ardakani@Sun.COM 		--smbd_doorsvc.sd_async_count;
36211963SAfshin.Ardakani@Sun.COM 		free(arg->data);
36312065SKeyur.Desai@Sun.COM 		arg->data = NULL;
36411963SAfshin.Ardakani@Sun.COM 		free(arg);
36511963SAfshin.Ardakani@Sun.COM 	}
36611963SAfshin.Ardakani@Sun.COM }
36711963SAfshin.Ardakani@Sun.COM 
36811963SAfshin.Ardakani@Sun.COM /*
36911963SAfshin.Ardakani@Sun.COM  * All door calls are processed here: synchronous or asynchronous:
37011963SAfshin.Ardakani@Sun.COM  * - synchronous calls are invoked by direct function call
37111963SAfshin.Ardakani@Sun.COM  * - asynchronous calls are invoked from a launched thread
37211963SAfshin.Ardakani@Sun.COM  *
37312065SKeyur.Desai@Sun.COM  * If the kernel has attempted to collect a response before the op
37412065SKeyur.Desai@Sun.COM  * has completed, the arg will have been marked as response_abort
37512065SKeyur.Desai@Sun.COM  * and we can discard the response data and release the arg.
37612065SKeyur.Desai@Sun.COM  *
37711963SAfshin.Ardakani@Sun.COM  * We send a notification when asynchronous (ASYNC) door calls
37811963SAfshin.Ardakani@Sun.COM  * from the kernel (SYSSPACE) have completed.
37911963SAfshin.Ardakani@Sun.COM  */
38011963SAfshin.Ardakani@Sun.COM static void *
smbd_door_dispatch_op(void * thread_arg)38111963SAfshin.Ardakani@Sun.COM smbd_door_dispatch_op(void *thread_arg)
38211963SAfshin.Ardakani@Sun.COM {
38311963SAfshin.Ardakani@Sun.COM 	smbd_arg_t	*arg = (smbd_arg_t *)thread_arg;
38411963SAfshin.Ardakani@Sun.COM 	smbd_doorop_t	*doorop;
38511963SAfshin.Ardakani@Sun.COM 	smb_doorhdr_t	*hdr;
38611963SAfshin.Ardakani@Sun.COM 	int		i;
38711963SAfshin.Ardakani@Sun.COM 
38811963SAfshin.Ardakani@Sun.COM 	if ((!smbd_online()) || arg == NULL)
38911963SAfshin.Ardakani@Sun.COM 		return (NULL);
39011963SAfshin.Ardakani@Sun.COM 
39111963SAfshin.Ardakani@Sun.COM 	hdr = &arg->hdr;
39211963SAfshin.Ardakani@Sun.COM 	arg->opname = smb_doorhdr_opname(hdr->dh_op);
39311963SAfshin.Ardakani@Sun.COM 
39411963SAfshin.Ardakani@Sun.COM 	for (i = 0; i < smbd_ndoorop; ++i) {
39511963SAfshin.Ardakani@Sun.COM 		doorop = &smbd_doorops[i];
39611963SAfshin.Ardakani@Sun.COM 
39711963SAfshin.Ardakani@Sun.COM 		if (hdr->dh_op == doorop->opcode) {
39811963SAfshin.Ardakani@Sun.COM 			hdr->dh_door_rc = doorop->op(arg);
39911963SAfshin.Ardakani@Sun.COM 			hdr->dh_status = arg->status;
40011963SAfshin.Ardakani@Sun.COM 
40111963SAfshin.Ardakani@Sun.COM 			if ((hdr->dh_flags & SMB_DF_SYSSPACE) &&
40211963SAfshin.Ardakani@Sun.COM 			    (hdr->dh_flags & SMB_DF_ASYNC)) {
40311963SAfshin.Ardakani@Sun.COM 				assert(hdr->dh_op != SMB_DR_ASYNC_RESPONSE);
40412065SKeyur.Desai@Sun.COM 
40512065SKeyur.Desai@Sun.COM 				(void) mutex_lock(&smbd_doorsvc.sd_mutex);
40612065SKeyur.Desai@Sun.COM 				if (arg->response_abort) {
40712065SKeyur.Desai@Sun.COM 					free(arg->rbuf);
40812065SKeyur.Desai@Sun.COM 					arg->rbuf = NULL;
40912065SKeyur.Desai@Sun.COM 					smbd_door_release_async(arg);
41012065SKeyur.Desai@Sun.COM 				} else {
41112065SKeyur.Desai@Sun.COM 					arg->response_ready = B_TRUE;
41212065SKeyur.Desai@Sun.COM 				}
41312065SKeyur.Desai@Sun.COM 				(void) mutex_unlock(&smbd_doorsvc.sd_mutex);
41412065SKeyur.Desai@Sun.COM 
41511963SAfshin.Ardakani@Sun.COM 				(void) smb_kmod_event_notify(hdr->dh_txid);
41611963SAfshin.Ardakani@Sun.COM 			}
41711963SAfshin.Ardakani@Sun.COM 
41811963SAfshin.Ardakani@Sun.COM 			return (NULL);
41911963SAfshin.Ardakani@Sun.COM 		}
42011963SAfshin.Ardakani@Sun.COM 	}
42111963SAfshin.Ardakani@Sun.COM 
42211963SAfshin.Ardakani@Sun.COM 	syslog(LOG_ERR, "smbd_door_dispatch_op[%s]: invalid op %u",
42311963SAfshin.Ardakani@Sun.COM 	    arg->opname, hdr->dh_op);
42411963SAfshin.Ardakani@Sun.COM 	return (NULL);
42511963SAfshin.Ardakani@Sun.COM }
42611963SAfshin.Ardakani@Sun.COM 
42711963SAfshin.Ardakani@Sun.COM /*
42811963SAfshin.Ardakani@Sun.COM  * Wrapper for door_return.  smbd_door_enter() increments a reference count
42911963SAfshin.Ardakani@Sun.COM  * when a door call is dispatched and smbd_door_return() decrements the
43011963SAfshin.Ardakani@Sun.COM  * reference count when it completes.
43111963SAfshin.Ardakani@Sun.COM  *
43211963SAfshin.Ardakani@Sun.COM  * The reference counting is used in smbd_door_fini() to wait for active
43311963SAfshin.Ardakani@Sun.COM  * calls to complete before closing the door.
43411963SAfshin.Ardakani@Sun.COM  */
43511963SAfshin.Ardakani@Sun.COM void
smbd_door_init(smbd_door_t * sdh,const char * name)43611963SAfshin.Ardakani@Sun.COM smbd_door_init(smbd_door_t *sdh, const char *name)
43711963SAfshin.Ardakani@Sun.COM {
43811963SAfshin.Ardakani@Sun.COM 	(void) strlcpy(sdh->sd_name, name, SMBD_DOOR_NAMESZ);
43911963SAfshin.Ardakani@Sun.COM }
44011963SAfshin.Ardakani@Sun.COM 
44111963SAfshin.Ardakani@Sun.COM void
smbd_door_enter(smbd_door_t * sdh)44211963SAfshin.Ardakani@Sun.COM smbd_door_enter(smbd_door_t *sdh)
44311963SAfshin.Ardakani@Sun.COM {
44411963SAfshin.Ardakani@Sun.COM 	(void) mutex_lock(&sdh->sd_mutex);
44511963SAfshin.Ardakani@Sun.COM 	++sdh->sd_ncalls;
44611963SAfshin.Ardakani@Sun.COM 	(void) mutex_unlock(&sdh->sd_mutex);
44711963SAfshin.Ardakani@Sun.COM }
44811963SAfshin.Ardakani@Sun.COM 
44911963SAfshin.Ardakani@Sun.COM /*
45011963SAfshin.Ardakani@Sun.COM  * We have two calls to door_return because the first call (with data)
45111963SAfshin.Ardakani@Sun.COM  * can fail, which can leave the door call blocked here.  The second
45211963SAfshin.Ardakani@Sun.COM  * call (with NULL) is guaranteed to unblock and return to the caller.
45311963SAfshin.Ardakani@Sun.COM  */
45411963SAfshin.Ardakani@Sun.COM void
smbd_door_return(smbd_door_t * sdh,char * data_ptr,size_t data_size,door_desc_t * desc_ptr,uint_t num_desc)45511963SAfshin.Ardakani@Sun.COM smbd_door_return(smbd_door_t *sdh, char *data_ptr, size_t data_size,
45611963SAfshin.Ardakani@Sun.COM     door_desc_t *desc_ptr, uint_t num_desc)
45711963SAfshin.Ardakani@Sun.COM {
45811963SAfshin.Ardakani@Sun.COM 	(void) mutex_lock(&sdh->sd_mutex);
45911963SAfshin.Ardakani@Sun.COM 
46011963SAfshin.Ardakani@Sun.COM 	if (sdh->sd_ncalls == 0)
46111963SAfshin.Ardakani@Sun.COM 		syslog(LOG_ERR, "smbd_door_return[%s]: unexpected count=0",
46211963SAfshin.Ardakani@Sun.COM 		    sdh->sd_name);
46311963SAfshin.Ardakani@Sun.COM 	else
46411963SAfshin.Ardakani@Sun.COM 		--sdh->sd_ncalls;
46511963SAfshin.Ardakani@Sun.COM 
46611963SAfshin.Ardakani@Sun.COM 	(void) cond_broadcast(&sdh->sd_cv);
46711963SAfshin.Ardakani@Sun.COM 	(void) mutex_unlock(&sdh->sd_mutex);
46811963SAfshin.Ardakani@Sun.COM 
46911963SAfshin.Ardakani@Sun.COM 	(void) door_return(data_ptr, data_size, desc_ptr, num_desc);
47011963SAfshin.Ardakani@Sun.COM 	(void) door_return(NULL, 0, NULL, 0);
47111963SAfshin.Ardakani@Sun.COM 	/* NOTREACHED */
47211963SAfshin.Ardakani@Sun.COM }
47311963SAfshin.Ardakani@Sun.COM 
47411963SAfshin.Ardakani@Sun.COM /*
47511963SAfshin.Ardakani@Sun.COM  * A door service is about to terminate.
47611963SAfshin.Ardakani@Sun.COM  * Give active requests a small grace period to complete.
47711963SAfshin.Ardakani@Sun.COM  */
47811963SAfshin.Ardakani@Sun.COM void
smbd_door_fini(smbd_door_t * sdh)47911963SAfshin.Ardakani@Sun.COM smbd_door_fini(smbd_door_t *sdh)
48011963SAfshin.Ardakani@Sun.COM {
48111963SAfshin.Ardakani@Sun.COM 	timestruc_t	delay;
48211963SAfshin.Ardakani@Sun.COM 	int		rc = 0;
48311963SAfshin.Ardakani@Sun.COM 
48411963SAfshin.Ardakani@Sun.COM 	(void) mutex_lock(&sdh->sd_mutex);
48511963SAfshin.Ardakani@Sun.COM 
48611963SAfshin.Ardakani@Sun.COM 	while (rc != ETIME && sdh->sd_ncalls != 0) {
48711963SAfshin.Ardakani@Sun.COM 		delay.tv_sec = 1;
48811963SAfshin.Ardakani@Sun.COM 		delay.tv_nsec = 0;
48911963SAfshin.Ardakani@Sun.COM 		rc = cond_reltimedwait(&sdh->sd_cv, &sdh->sd_mutex, &delay);
49011963SAfshin.Ardakani@Sun.COM 	}
49111963SAfshin.Ardakani@Sun.COM 
49211963SAfshin.Ardakani@Sun.COM 	if (sdh->sd_ncalls != 0)
49311963SAfshin.Ardakani@Sun.COM 		syslog(LOG_NOTICE, "smbd_door_fini[%s]: %d remaining",
49411963SAfshin.Ardakani@Sun.COM 		    sdh->sd_name, sdh->sd_ncalls);
49511963SAfshin.Ardakani@Sun.COM 
49611963SAfshin.Ardakani@Sun.COM 	(void) mutex_unlock(&sdh->sd_mutex);
49711963SAfshin.Ardakani@Sun.COM }
49811963SAfshin.Ardakani@Sun.COM 
49911963SAfshin.Ardakani@Sun.COM /*
50011963SAfshin.Ardakani@Sun.COM  * Null door operation: always returns success.
50111963SAfshin.Ardakani@Sun.COM  * Assumes no request or response data.
50211963SAfshin.Ardakani@Sun.COM  */
50311963SAfshin.Ardakani@Sun.COM /*ARGSUSED*/
50411963SAfshin.Ardakani@Sun.COM static int
smbd_dop_null(smbd_arg_t * arg)50511963SAfshin.Ardakani@Sun.COM smbd_dop_null(smbd_arg_t *arg)
50611963SAfshin.Ardakani@Sun.COM {
50711963SAfshin.Ardakani@Sun.COM 	return (SMB_DOP_SUCCESS);
5085331Samw }
5095331Samw 
5105331Samw /*
51111963SAfshin.Ardakani@Sun.COM  * Async response handler: setup the rbuf and rsize for the specified
51211963SAfshin.Ardakani@Sun.COM  * transaction.  This function is used by the kernel to collect the
51311963SAfshin.Ardakani@Sun.COM  * response half of an asynchronous door call.
51412065SKeyur.Desai@Sun.COM  *
51512065SKeyur.Desai@Sun.COM  * If a door client attempts to collect a response before the op has
51612065SKeyur.Desai@Sun.COM  * completed (!response_ready), mark the arg as response_abort and
51712065SKeyur.Desai@Sun.COM  * set an error.  The response will be discarded when the op completes.
51811963SAfshin.Ardakani@Sun.COM  */
51911963SAfshin.Ardakani@Sun.COM static int
smbd_dop_async_response(smbd_arg_t * rsp_arg)52011963SAfshin.Ardakani@Sun.COM smbd_dop_async_response(smbd_arg_t *rsp_arg)
52111963SAfshin.Ardakani@Sun.COM {
52211963SAfshin.Ardakani@Sun.COM 	list_t		*arg_list = &smbd_doorsvc.sd_async_list;
52311963SAfshin.Ardakani@Sun.COM 	smbd_arg_t	*arg;
52411963SAfshin.Ardakani@Sun.COM 
52511963SAfshin.Ardakani@Sun.COM 	(void) mutex_lock(&smbd_doorsvc.sd_mutex);
52611963SAfshin.Ardakani@Sun.COM 	arg = list_head(arg_list);
52711963SAfshin.Ardakani@Sun.COM 
52811963SAfshin.Ardakani@Sun.COM 	while (arg != NULL) {
52912065SKeyur.Desai@Sun.COM 		assert(arg->magic == SMBD_ARG_MAGIC);
53012065SKeyur.Desai@Sun.COM 
53111963SAfshin.Ardakani@Sun.COM 		if (arg->hdr.dh_txid == rsp_arg->hdr.dh_txid) {
53212065SKeyur.Desai@Sun.COM 			if (!arg->response_ready) {
53312065SKeyur.Desai@Sun.COM 				arg->response_abort = B_TRUE;
53412065SKeyur.Desai@Sun.COM 				rsp_arg->hdr.dh_door_rc = SMB_DOP_NOT_CALLED;
53512065SKeyur.Desai@Sun.COM 				syslog(LOG_NOTICE, "doorsvc[%s]: %u not ready",
53612065SKeyur.Desai@Sun.COM 				    arg->opname, arg->hdr.dh_txid);
53712065SKeyur.Desai@Sun.COM 				break;
53812065SKeyur.Desai@Sun.COM 			}
53912065SKeyur.Desai@Sun.COM 
54011963SAfshin.Ardakani@Sun.COM 			rsp_arg->rbuf = arg->rbuf;
54111963SAfshin.Ardakani@Sun.COM 			rsp_arg->rsize = arg->rsize;
54211963SAfshin.Ardakani@Sun.COM 			arg->rbuf = NULL;
54311963SAfshin.Ardakani@Sun.COM 			arg->rsize = 0;
54411963SAfshin.Ardakani@Sun.COM 			smbd_door_release_async(arg);
54511963SAfshin.Ardakani@Sun.COM 			break;
54611963SAfshin.Ardakani@Sun.COM 		}
54711963SAfshin.Ardakani@Sun.COM 
54811963SAfshin.Ardakani@Sun.COM 		arg = list_next(arg_list, arg);
54911963SAfshin.Ardakani@Sun.COM 	}
55011963SAfshin.Ardakani@Sun.COM 
55111963SAfshin.Ardakani@Sun.COM 	(void) mutex_unlock(&smbd_doorsvc.sd_mutex);
55211963SAfshin.Ardakani@Sun.COM 	return (SMB_DOP_SUCCESS);
55311963SAfshin.Ardakani@Sun.COM }
55411963SAfshin.Ardakani@Sun.COM 
55511963SAfshin.Ardakani@Sun.COM static int
smbd_dop_user_nonauth_logon(smbd_arg_t * arg)55611963SAfshin.Ardakani@Sun.COM smbd_dop_user_nonauth_logon(smbd_arg_t *arg)
55711963SAfshin.Ardakani@Sun.COM {
55812065SKeyur.Desai@Sun.COM 	uint32_t	sid = 0;
55911963SAfshin.Ardakani@Sun.COM 
56011963SAfshin.Ardakani@Sun.COM 	if (smb_common_decode(arg->data, arg->datalen,
56111963SAfshin.Ardakani@Sun.COM 	    xdr_uint32_t, &sid) != 0)
56211963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_DECODE_ERROR);
56311963SAfshin.Ardakani@Sun.COM 
56411963SAfshin.Ardakani@Sun.COM 	smbd_user_nonauth_logon(sid);
56511963SAfshin.Ardakani@Sun.COM 	return (SMB_DOP_SUCCESS);
56611963SAfshin.Ardakani@Sun.COM }
56711963SAfshin.Ardakani@Sun.COM 
56811963SAfshin.Ardakani@Sun.COM static int
smbd_dop_user_auth_logoff(smbd_arg_t * arg)56911963SAfshin.Ardakani@Sun.COM smbd_dop_user_auth_logoff(smbd_arg_t *arg)
57011963SAfshin.Ardakani@Sun.COM {
57112065SKeyur.Desai@Sun.COM 	uint32_t	sid = 0;
57211963SAfshin.Ardakani@Sun.COM 
57311963SAfshin.Ardakani@Sun.COM 	if (smb_common_decode(arg->data, arg->datalen,
57411963SAfshin.Ardakani@Sun.COM 	    xdr_uint32_t, &sid) != 0)
57511963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_DECODE_ERROR);
57611963SAfshin.Ardakani@Sun.COM 
57711963SAfshin.Ardakani@Sun.COM 	smbd_user_auth_logoff(sid);
57811963SAfshin.Ardakani@Sun.COM 	return (SMB_DOP_SUCCESS);
57911963SAfshin.Ardakani@Sun.COM }
58011963SAfshin.Ardakani@Sun.COM 
58111963SAfshin.Ardakani@Sun.COM /*
58211963SAfshin.Ardakani@Sun.COM  * Obtains an access token on successful user authentication.
5835331Samw  */
58411963SAfshin.Ardakani@Sun.COM static int
smbd_dop_user_auth_logon(smbd_arg_t * arg)58511963SAfshin.Ardakani@Sun.COM smbd_dop_user_auth_logon(smbd_arg_t *arg)
58611963SAfshin.Ardakani@Sun.COM {
58711963SAfshin.Ardakani@Sun.COM 	smb_logon_t	*user_info;
58811963SAfshin.Ardakani@Sun.COM 	smb_token_t	*token;
58911963SAfshin.Ardakani@Sun.COM 
59011963SAfshin.Ardakani@Sun.COM 	user_info = smb_logon_decode((uint8_t *)arg->data,
59111963SAfshin.Ardakani@Sun.COM 	    arg->datalen);
59211963SAfshin.Ardakani@Sun.COM 	if (user_info == NULL)
59311963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_DECODE_ERROR);
59411963SAfshin.Ardakani@Sun.COM 
59511963SAfshin.Ardakani@Sun.COM 	token = smbd_user_auth_logon(user_info);
59611963SAfshin.Ardakani@Sun.COM 
59711963SAfshin.Ardakani@Sun.COM 	smb_logon_free(user_info);
59811963SAfshin.Ardakani@Sun.COM 
59911963SAfshin.Ardakani@Sun.COM 	if (token == NULL)
60011963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_EMPTYBUF);
60111963SAfshin.Ardakani@Sun.COM 
60211963SAfshin.Ardakani@Sun.COM 	arg->rbuf = (char *)smb_token_encode(token, &arg->rsize);
60311963SAfshin.Ardakani@Sun.COM 	smb_token_destroy(token);
60411963SAfshin.Ardakani@Sun.COM 
60511963SAfshin.Ardakani@Sun.COM 	if (arg->rbuf == NULL)
60611963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_ENCODE_ERROR);
60711963SAfshin.Ardakani@Sun.COM 	return (SMB_DOP_SUCCESS);
60811963SAfshin.Ardakani@Sun.COM }
60911963SAfshin.Ardakani@Sun.COM 
61011963SAfshin.Ardakani@Sun.COM static int
smbd_dop_lookup_name(smbd_arg_t * arg)61111963SAfshin.Ardakani@Sun.COM smbd_dop_lookup_name(smbd_arg_t *arg)
61211963SAfshin.Ardakani@Sun.COM {
61311963SAfshin.Ardakani@Sun.COM 	smb_domain_t	dinfo;
61411963SAfshin.Ardakani@Sun.COM 	smb_account_t	ainfo;
61511963SAfshin.Ardakani@Sun.COM 	lsa_account_t	acct;
61611963SAfshin.Ardakani@Sun.COM 	char		buf[MAXNAMELEN];
61711963SAfshin.Ardakani@Sun.COM 
61812065SKeyur.Desai@Sun.COM 	bzero(&acct, sizeof (lsa_account_t));
61912065SKeyur.Desai@Sun.COM 
62011963SAfshin.Ardakani@Sun.COM 	if (smb_common_decode(arg->data, arg->datalen,
62111963SAfshin.Ardakani@Sun.COM 	    lsa_account_xdr, &acct) != 0)
62211963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_DECODE_ERROR);
62311963SAfshin.Ardakani@Sun.COM 
62411963SAfshin.Ardakani@Sun.COM 	if (*acct.a_domain == '\0')
62511963SAfshin.Ardakani@Sun.COM 		(void) snprintf(buf, MAXNAMELEN, "%s", acct.a_name);
62611963SAfshin.Ardakani@Sun.COM 	else if (strchr(acct.a_domain, '.') != NULL)
62711963SAfshin.Ardakani@Sun.COM 		(void) snprintf(buf, MAXNAMELEN, "%s@%s", acct.a_name,
62811963SAfshin.Ardakani@Sun.COM 		    acct.a_domain);
62911963SAfshin.Ardakani@Sun.COM 	else
63011963SAfshin.Ardakani@Sun.COM 		(void) snprintf(buf, MAXNAMELEN, "%s\\%s", acct.a_domain,
63111963SAfshin.Ardakani@Sun.COM 		    acct.a_name);
63211963SAfshin.Ardakani@Sun.COM 
63311963SAfshin.Ardakani@Sun.COM 	acct.a_status = lsa_lookup_name(buf, acct.a_sidtype, &ainfo);
63411963SAfshin.Ardakani@Sun.COM 	if (acct.a_status == NT_STATUS_SUCCESS) {
63511963SAfshin.Ardakani@Sun.COM 		acct.a_sidtype = ainfo.a_type;
63611963SAfshin.Ardakani@Sun.COM 		smb_sid_tostr(ainfo.a_sid, acct.a_sid);
63711963SAfshin.Ardakani@Sun.COM 		(void) strlcpy(acct.a_name, ainfo.a_name, MAXNAMELEN);
63811963SAfshin.Ardakani@Sun.COM 
63911963SAfshin.Ardakani@Sun.COM 		if (smb_domain_lookup_name(ainfo.a_domain, &dinfo))
64011963SAfshin.Ardakani@Sun.COM 			(void) strlcpy(acct.a_domain, dinfo.di_fqname,
64111963SAfshin.Ardakani@Sun.COM 			    MAXNAMELEN);
64211963SAfshin.Ardakani@Sun.COM 		else
64311963SAfshin.Ardakani@Sun.COM 			(void) strlcpy(acct.a_domain, ainfo.a_domain,
64411963SAfshin.Ardakani@Sun.COM 			    MAXNAMELEN);
64511963SAfshin.Ardakani@Sun.COM 		smb_account_free(&ainfo);
64611963SAfshin.Ardakani@Sun.COM 	}
64711963SAfshin.Ardakani@Sun.COM 
64811963SAfshin.Ardakani@Sun.COM 	arg->rbuf = smb_common_encode(&acct, lsa_account_xdr, &arg->rsize);
64911963SAfshin.Ardakani@Sun.COM 
65011963SAfshin.Ardakani@Sun.COM 	if (arg->rbuf == NULL)
65111963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_ENCODE_ERROR);
65211963SAfshin.Ardakani@Sun.COM 	return (SMB_DOP_SUCCESS);
65311963SAfshin.Ardakani@Sun.COM }
65411963SAfshin.Ardakani@Sun.COM 
65511963SAfshin.Ardakani@Sun.COM static int
smbd_dop_lookup_sid(smbd_arg_t * arg)65611963SAfshin.Ardakani@Sun.COM smbd_dop_lookup_sid(smbd_arg_t *arg)
65711963SAfshin.Ardakani@Sun.COM {
65811963SAfshin.Ardakani@Sun.COM 	smb_domain_t	dinfo;
65911963SAfshin.Ardakani@Sun.COM 	smb_account_t	ainfo;
66011963SAfshin.Ardakani@Sun.COM 	lsa_account_t	acct;
66111963SAfshin.Ardakani@Sun.COM 	smb_sid_t	*sid;
66211963SAfshin.Ardakani@Sun.COM 
66312065SKeyur.Desai@Sun.COM 	bzero(&acct, sizeof (lsa_account_t));
66412065SKeyur.Desai@Sun.COM 
66511963SAfshin.Ardakani@Sun.COM 	if (smb_common_decode(arg->data, arg->datalen,
66611963SAfshin.Ardakani@Sun.COM 	    lsa_account_xdr, &acct) != 0)
66711963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_DECODE_ERROR);
66811963SAfshin.Ardakani@Sun.COM 
66911963SAfshin.Ardakani@Sun.COM 	sid = smb_sid_fromstr(acct.a_sid);
67011963SAfshin.Ardakani@Sun.COM 	acct.a_status = lsa_lookup_sid(sid, &ainfo);
67111963SAfshin.Ardakani@Sun.COM 	smb_sid_free(sid);
67211963SAfshin.Ardakani@Sun.COM 
67311963SAfshin.Ardakani@Sun.COM 	if (acct.a_status == NT_STATUS_SUCCESS) {
67411963SAfshin.Ardakani@Sun.COM 		acct.a_sidtype = ainfo.a_type;
67511963SAfshin.Ardakani@Sun.COM 		smb_sid_tostr(ainfo.a_sid, acct.a_sid);
67611963SAfshin.Ardakani@Sun.COM 		(void) strlcpy(acct.a_name, ainfo.a_name, MAXNAMELEN);
67711963SAfshin.Ardakani@Sun.COM 
67811963SAfshin.Ardakani@Sun.COM 		if (smb_domain_lookup_name(ainfo.a_domain, &dinfo))
67911963SAfshin.Ardakani@Sun.COM 			(void) strlcpy(acct.a_domain, dinfo.di_fqname,
68011963SAfshin.Ardakani@Sun.COM 			    MAXNAMELEN);
68111963SAfshin.Ardakani@Sun.COM 		else
68211963SAfshin.Ardakani@Sun.COM 			(void) strlcpy(acct.a_domain, ainfo.a_domain,
68311963SAfshin.Ardakani@Sun.COM 			    MAXNAMELEN);
68411963SAfshin.Ardakani@Sun.COM 
68511963SAfshin.Ardakani@Sun.COM 		smb_account_free(&ainfo);
68611963SAfshin.Ardakani@Sun.COM 	}
68711963SAfshin.Ardakani@Sun.COM 
68811963SAfshin.Ardakani@Sun.COM 	arg->rbuf = smb_common_encode(&acct, lsa_account_xdr, &arg->rsize);
68911963SAfshin.Ardakani@Sun.COM 
69011963SAfshin.Ardakani@Sun.COM 	if (arg->rbuf == NULL)
69111963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_ENCODE_ERROR);
69211963SAfshin.Ardakani@Sun.COM 	return (SMB_DOP_SUCCESS);
69311963SAfshin.Ardakani@Sun.COM }
69411963SAfshin.Ardakani@Sun.COM 
69511963SAfshin.Ardakani@Sun.COM static int
smbd_dop_join(smbd_arg_t * arg)69611963SAfshin.Ardakani@Sun.COM smbd_dop_join(smbd_arg_t *arg)
6975331Samw {
69811963SAfshin.Ardakani@Sun.COM 	smb_joininfo_t	jdi;
69911963SAfshin.Ardakani@Sun.COM 	uint32_t	status;
70011963SAfshin.Ardakani@Sun.COM 
70112065SKeyur.Desai@Sun.COM 	bzero(&jdi, sizeof (smb_joininfo_t));
70212065SKeyur.Desai@Sun.COM 
70311963SAfshin.Ardakani@Sun.COM 	if (smb_common_decode(arg->data, arg->datalen,
70411963SAfshin.Ardakani@Sun.COM 	    smb_joininfo_xdr, &jdi) != 0)
70511963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_DECODE_ERROR);
70611963SAfshin.Ardakani@Sun.COM 
70711963SAfshin.Ardakani@Sun.COM 	status = smbd_join(&jdi);
70811963SAfshin.Ardakani@Sun.COM 
70911963SAfshin.Ardakani@Sun.COM 	arg->rbuf = smb_common_encode(&status, xdr_uint32_t, &arg->rsize);
71011963SAfshin.Ardakani@Sun.COM 
71111963SAfshin.Ardakani@Sun.COM 	if (arg->rbuf == NULL)
71211963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_ENCODE_ERROR);
71311963SAfshin.Ardakani@Sun.COM 	return (SMB_DOP_SUCCESS);
71411963SAfshin.Ardakani@Sun.COM }
71511963SAfshin.Ardakani@Sun.COM 
71611963SAfshin.Ardakani@Sun.COM static int
smbd_dop_get_dcinfo(smbd_arg_t * arg)71711963SAfshin.Ardakani@Sun.COM smbd_dop_get_dcinfo(smbd_arg_t *arg)
71811963SAfshin.Ardakani@Sun.COM {
71911963SAfshin.Ardakani@Sun.COM 	smb_domainex_t	dxi;
72011963SAfshin.Ardakani@Sun.COM 
72111963SAfshin.Ardakani@Sun.COM 	if (!smb_domain_getinfo(&dxi))
72211963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_EMPTYBUF);
72311963SAfshin.Ardakani@Sun.COM 
72411963SAfshin.Ardakani@Sun.COM 	arg->rbuf = smb_string_encode(dxi.d_dc, &arg->rsize);
72511963SAfshin.Ardakani@Sun.COM 
72611963SAfshin.Ardakani@Sun.COM 	if (arg->rbuf == NULL)
72711963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_ENCODE_ERROR);
72811963SAfshin.Ardakani@Sun.COM 	return (SMB_DOP_SUCCESS);
72911963SAfshin.Ardakani@Sun.COM }
73011963SAfshin.Ardakani@Sun.COM 
73111963SAfshin.Ardakani@Sun.COM /*
73211963SAfshin.Ardakani@Sun.COM  * Return the number of snapshots for a dataset
73311963SAfshin.Ardakani@Sun.COM  */
73411963SAfshin.Ardakani@Sun.COM static int
smbd_dop_vss_get_count(smbd_arg_t * arg)73511963SAfshin.Ardakani@Sun.COM smbd_dop_vss_get_count(smbd_arg_t *arg)
73611963SAfshin.Ardakani@Sun.COM {
73711963SAfshin.Ardakani@Sun.COM 	smb_string_t	path;
73811963SAfshin.Ardakani@Sun.COM 	uint32_t	count;
73911963SAfshin.Ardakani@Sun.COM 
74011963SAfshin.Ardakani@Sun.COM 	bzero(&path, sizeof (smb_string_t));
74111963SAfshin.Ardakani@Sun.COM 	arg->rbuf = NULL;
74211963SAfshin.Ardakani@Sun.COM 
74311963SAfshin.Ardakani@Sun.COM 	if (smb_string_decode(&path, arg->data, arg->datalen) != 0)
74411963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_DECODE_ERROR);
74511963SAfshin.Ardakani@Sun.COM 
74611963SAfshin.Ardakani@Sun.COM 	if (smbd_vss_get_count(path.buf, &count) == 0)
74711963SAfshin.Ardakani@Sun.COM 		arg->rbuf = smb_common_encode(&count, xdr_uint32_t,
74811963SAfshin.Ardakani@Sun.COM 		    &arg->rsize);
74911963SAfshin.Ardakani@Sun.COM 
75011963SAfshin.Ardakani@Sun.COM 	xdr_free(smb_string_xdr, (char *)&path);
75111963SAfshin.Ardakani@Sun.COM 
75211963SAfshin.Ardakani@Sun.COM 	if (arg->rbuf == NULL)
75311963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_ENCODE_ERROR);
75411963SAfshin.Ardakani@Sun.COM 	return (SMB_DOP_SUCCESS);
75511963SAfshin.Ardakani@Sun.COM }
7565331Samw 
75711963SAfshin.Ardakani@Sun.COM /*
75811963SAfshin.Ardakani@Sun.COM  * Return the count and list of snapshots.
75911963SAfshin.Ardakani@Sun.COM  * The list is in @GMT token format.
76011963SAfshin.Ardakani@Sun.COM  */
76111963SAfshin.Ardakani@Sun.COM static int
smbd_dop_vss_get_snapshots(smbd_arg_t * arg)76211963SAfshin.Ardakani@Sun.COM smbd_dop_vss_get_snapshots(smbd_arg_t *arg)
76311963SAfshin.Ardakani@Sun.COM {
76411963SAfshin.Ardakani@Sun.COM 	char				**gmtp;
76511963SAfshin.Ardakani@Sun.COM 	smb_gmttoken_query_t		request;
76611963SAfshin.Ardakani@Sun.COM 	smb_gmttoken_response_t		reply;
76711963SAfshin.Ardakani@Sun.COM 	uint_t				i;
76811963SAfshin.Ardakani@Sun.COM 
76911963SAfshin.Ardakani@Sun.COM 	bzero(&request, sizeof (smb_gmttoken_query_t));
77011963SAfshin.Ardakani@Sun.COM 	bzero(&reply, sizeof (smb_gmttoken_response_t));
77111963SAfshin.Ardakani@Sun.COM 
77211963SAfshin.Ardakani@Sun.COM 	if (smb_common_decode(arg->data, arg->datalen,
77311963SAfshin.Ardakani@Sun.COM 	    smb_gmttoken_query_xdr, &request) != 0)
77411963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_DECODE_ERROR);
77511963SAfshin.Ardakani@Sun.COM 
77611963SAfshin.Ardakani@Sun.COM 	reply.gtr_gmttokens.gtr_gmttokens_val = malloc(request.gtq_count *
77711963SAfshin.Ardakani@Sun.COM 	    sizeof (char *));
77811963SAfshin.Ardakani@Sun.COM 	bzero(reply.gtr_gmttokens.gtr_gmttokens_val, request.gtq_count *
77911963SAfshin.Ardakani@Sun.COM 	    sizeof (char *));
78011963SAfshin.Ardakani@Sun.COM 
78111963SAfshin.Ardakani@Sun.COM 	if (reply.gtr_gmttokens.gtr_gmttokens_val == NULL) {
78211963SAfshin.Ardakani@Sun.COM 		xdr_free(smb_gmttoken_query_xdr, (char *)&request);
78311963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_EMPTYBUF);
78411963SAfshin.Ardakani@Sun.COM 	}
78511963SAfshin.Ardakani@Sun.COM 
78611963SAfshin.Ardakani@Sun.COM 	smbd_vss_get_snapshots(request.gtq_path, request.gtq_count,
78711963SAfshin.Ardakani@Sun.COM 	    &reply.gtr_count,
78811963SAfshin.Ardakani@Sun.COM 	    &reply.gtr_gmttokens.gtr_gmttokens_len,
78911963SAfshin.Ardakani@Sun.COM 	    reply.gtr_gmttokens.gtr_gmttokens_val);
79011963SAfshin.Ardakani@Sun.COM 
79111963SAfshin.Ardakani@Sun.COM 	arg->rbuf = smb_common_encode(&reply, smb_gmttoken_response_xdr,
79211963SAfshin.Ardakani@Sun.COM 	    &arg->rsize);
79311963SAfshin.Ardakani@Sun.COM 	if (arg->rbuf == NULL) {
79411963SAfshin.Ardakani@Sun.COM 		xdr_free(smb_gmttoken_query_xdr, (char *)&request);
79511963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_ENCODE_ERROR);
79611963SAfshin.Ardakani@Sun.COM 	}
79711963SAfshin.Ardakani@Sun.COM 
79811963SAfshin.Ardakani@Sun.COM 	for (i = 0, gmtp = reply.gtr_gmttokens.gtr_gmttokens_val;
79911963SAfshin.Ardakani@Sun.COM 	    (i < request.gtq_count); i++) {
80011963SAfshin.Ardakani@Sun.COM 		if (*gmtp)
80111963SAfshin.Ardakani@Sun.COM 			free(*gmtp);
80211963SAfshin.Ardakani@Sun.COM 		gmtp++;
80311963SAfshin.Ardakani@Sun.COM 	}
80411963SAfshin.Ardakani@Sun.COM 
80511963SAfshin.Ardakani@Sun.COM 	free(reply.gtr_gmttokens.gtr_gmttokens_val);
80611963SAfshin.Ardakani@Sun.COM 	xdr_free(smb_gmttoken_query_xdr, (char *)&request);
80711963SAfshin.Ardakani@Sun.COM 	return (SMB_DOP_SUCCESS);
80811963SAfshin.Ardakani@Sun.COM }
80911963SAfshin.Ardakani@Sun.COM 
81011963SAfshin.Ardakani@Sun.COM /*
81111963SAfshin.Ardakani@Sun.COM  * Return the name of the snapshot that matches the dataset path
81211963SAfshin.Ardakani@Sun.COM  * and @GMT token.
81311963SAfshin.Ardakani@Sun.COM  */
81411963SAfshin.Ardakani@Sun.COM static int
smbd_dop_vss_map_gmttoken(smbd_arg_t * arg)81511963SAfshin.Ardakani@Sun.COM smbd_dop_vss_map_gmttoken(smbd_arg_t *arg)
81611963SAfshin.Ardakani@Sun.COM {
81711963SAfshin.Ardakani@Sun.COM 	char			*snapname;
81811963SAfshin.Ardakani@Sun.COM 	smb_gmttoken_snapname_t	request;
81911963SAfshin.Ardakani@Sun.COM 
82011963SAfshin.Ardakani@Sun.COM 	bzero(&request, sizeof (smb_gmttoken_snapname_t));
82111963SAfshin.Ardakani@Sun.COM 
82211963SAfshin.Ardakani@Sun.COM 	if (smb_common_decode(arg->data, arg->datalen,
82311963SAfshin.Ardakani@Sun.COM 	    smb_gmttoken_snapname_xdr, &request) != 0) {
82411963SAfshin.Ardakani@Sun.COM 		xdr_free(smb_gmttoken_snapname_xdr, (char *)&request);
82511963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_DECODE_ERROR);
82611963SAfshin.Ardakani@Sun.COM 	}
82711963SAfshin.Ardakani@Sun.COM 
82811963SAfshin.Ardakani@Sun.COM 	if ((snapname = malloc(MAXPATHLEN)) == NULL) {
82911963SAfshin.Ardakani@Sun.COM 		xdr_free(smb_gmttoken_snapname_xdr, (char *)&request);
8305331Samw 		return (NULL);
8315331Samw 	}
8325331Samw 
83311963SAfshin.Ardakani@Sun.COM 	if ((smbd_vss_map_gmttoken(request.gts_path, request.gts_gmttoken,
83411963SAfshin.Ardakani@Sun.COM 	    snapname) != 0)) {
83511963SAfshin.Ardakani@Sun.COM 		*snapname = '\0';
83611963SAfshin.Ardakani@Sun.COM 	}
83711963SAfshin.Ardakani@Sun.COM 
83811963SAfshin.Ardakani@Sun.COM 	arg->rbuf = smb_string_encode(snapname, &arg->rsize);
83911963SAfshin.Ardakani@Sun.COM 	xdr_free(smb_gmttoken_snapname_xdr, (char *)&request);
84011963SAfshin.Ardakani@Sun.COM 	free(snapname);
84111963SAfshin.Ardakani@Sun.COM 
84211963SAfshin.Ardakani@Sun.COM 	if (arg->rbuf == NULL)
84311963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_ENCODE_ERROR);
84411963SAfshin.Ardakani@Sun.COM 	return (SMB_DOP_SUCCESS);
84511963SAfshin.Ardakani@Sun.COM }
84611963SAfshin.Ardakani@Sun.COM 
84711963SAfshin.Ardakani@Sun.COM static int
smbd_dop_ads_find_host(smbd_arg_t * arg)84811963SAfshin.Ardakani@Sun.COM smbd_dop_ads_find_host(smbd_arg_t *arg)
84911963SAfshin.Ardakani@Sun.COM {
85011963SAfshin.Ardakani@Sun.COM 	smb_ads_host_info_t	*hinfo = NULL;
85111963SAfshin.Ardakani@Sun.COM 	char			*hostname = "";
85211963SAfshin.Ardakani@Sun.COM 	smb_string_t		fqdn;
85311963SAfshin.Ardakani@Sun.COM 
85411963SAfshin.Ardakani@Sun.COM 	bzero(&fqdn, sizeof (smb_string_t));
85511963SAfshin.Ardakani@Sun.COM 
85611963SAfshin.Ardakani@Sun.COM 	if (smb_string_decode(&fqdn, arg->data, arg->datalen) != 0)
85711963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_DECODE_ERROR);
85811963SAfshin.Ardakani@Sun.COM 
85911963SAfshin.Ardakani@Sun.COM 	if ((hinfo = smb_ads_find_host(fqdn.buf, NULL)) != NULL)
86011963SAfshin.Ardakani@Sun.COM 		hostname = hinfo->name;
86111963SAfshin.Ardakani@Sun.COM 
86211963SAfshin.Ardakani@Sun.COM 	xdr_free(smb_string_xdr, (char *)&fqdn);
86311963SAfshin.Ardakani@Sun.COM 
86411963SAfshin.Ardakani@Sun.COM 	arg->rbuf = smb_string_encode(hostname, &arg->rsize);
86511963SAfshin.Ardakani@Sun.COM 	free(hinfo);
86611963SAfshin.Ardakani@Sun.COM 
86711963SAfshin.Ardakani@Sun.COM 	if (arg->rbuf == NULL)
86811963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_ENCODE_ERROR);
86911963SAfshin.Ardakani@Sun.COM 	return (SMB_DOP_SUCCESS);
8705331Samw }
8715331Samw 
8725331Samw /*
87311963SAfshin.Ardakani@Sun.COM  * Query the list of user/group quota entries for a given filesystem.
8745331Samw  */
87511963SAfshin.Ardakani@Sun.COM static int
smbd_dop_quota_query(smbd_arg_t * arg)87611963SAfshin.Ardakani@Sun.COM smbd_dop_quota_query(smbd_arg_t *arg)
8775331Samw {
87811963SAfshin.Ardakani@Sun.COM 	smb_quota_query_t	request;
87911963SAfshin.Ardakani@Sun.COM 	smb_quota_response_t	reply;
88011963SAfshin.Ardakani@Sun.COM 	uint32_t		status;
88111963SAfshin.Ardakani@Sun.COM 
88211963SAfshin.Ardakani@Sun.COM 	bzero(&request, sizeof (smb_quota_query_t));
88311963SAfshin.Ardakani@Sun.COM 	bzero(&reply, sizeof (smb_quota_response_t));
88411963SAfshin.Ardakani@Sun.COM 
88511963SAfshin.Ardakani@Sun.COM 	if (smb_common_decode(arg->data, arg->datalen,
88611963SAfshin.Ardakani@Sun.COM 	    smb_quota_query_xdr, &request) != 0)
88711963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_DECODE_ERROR);
88811963SAfshin.Ardakani@Sun.COM 
88911963SAfshin.Ardakani@Sun.COM 	status = smb_quota_query(&request, &reply);
89011963SAfshin.Ardakani@Sun.COM 	reply.qr_status = status;
89111963SAfshin.Ardakani@Sun.COM 
89211963SAfshin.Ardakani@Sun.COM 	arg->rbuf = smb_common_encode(&reply, smb_quota_response_xdr,
89311963SAfshin.Ardakani@Sun.COM 	    &arg->rsize);
8945331Samw 
89511963SAfshin.Ardakani@Sun.COM 	xdr_free(smb_quota_query_xdr, (char *)&request);
89611963SAfshin.Ardakani@Sun.COM 	smb_quota_free(&reply);
89711963SAfshin.Ardakani@Sun.COM 
89811963SAfshin.Ardakani@Sun.COM 	if (arg->rbuf == NULL)
89911963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_ENCODE_ERROR);
90011963SAfshin.Ardakani@Sun.COM 	return (SMB_DOP_SUCCESS);
90111963SAfshin.Ardakani@Sun.COM }
90211963SAfshin.Ardakani@Sun.COM 
90311963SAfshin.Ardakani@Sun.COM /*
90411963SAfshin.Ardakani@Sun.COM  * Set a list of user/group quota entries for a given filesystem.
90511963SAfshin.Ardakani@Sun.COM  */
90611963SAfshin.Ardakani@Sun.COM static int
smbd_dop_quota_set(smbd_arg_t * arg)90711963SAfshin.Ardakani@Sun.COM smbd_dop_quota_set(smbd_arg_t *arg)
90811963SAfshin.Ardakani@Sun.COM {
90911963SAfshin.Ardakani@Sun.COM 	smb_quota_set_t	request;
91011963SAfshin.Ardakani@Sun.COM 	uint32_t	status = 0;
91111963SAfshin.Ardakani@Sun.COM 
91211963SAfshin.Ardakani@Sun.COM 	bzero(&request, sizeof (smb_quota_set_t));
9136771Sjb150015 
91411963SAfshin.Ardakani@Sun.COM 	if (smb_common_decode(arg->data, arg->datalen,
91511963SAfshin.Ardakani@Sun.COM 	    smb_quota_set_xdr, &request) != 0)
91611963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_DECODE_ERROR);
91711963SAfshin.Ardakani@Sun.COM 
91811963SAfshin.Ardakani@Sun.COM 	status = smb_quota_set(&request);
91911963SAfshin.Ardakani@Sun.COM 
92011963SAfshin.Ardakani@Sun.COM 	arg->rbuf = smb_common_encode(&status, xdr_uint32_t, &arg->rsize);
92111963SAfshin.Ardakani@Sun.COM 	xdr_free(smb_quota_set_xdr, (char *)&request);
92211963SAfshin.Ardakani@Sun.COM 
92311963SAfshin.Ardakani@Sun.COM 	if (arg->rbuf == NULL)
92411963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_ENCODE_ERROR);
92511963SAfshin.Ardakani@Sun.COM 	return (SMB_DOP_SUCCESS);
92611963SAfshin.Ardakani@Sun.COM }
92711963SAfshin.Ardakani@Sun.COM 
92811963SAfshin.Ardakani@Sun.COM static int
smbd_dop_dfs_get_referrals(smbd_arg_t * arg)92911963SAfshin.Ardakani@Sun.COM smbd_dop_dfs_get_referrals(smbd_arg_t *arg)
93011963SAfshin.Ardakani@Sun.COM {
93111963SAfshin.Ardakani@Sun.COM 	dfs_referral_query_t	request;
93211963SAfshin.Ardakani@Sun.COM 	dfs_referral_response_t	reply;
93311963SAfshin.Ardakani@Sun.COM 
93411963SAfshin.Ardakani@Sun.COM 	bzero(&request, sizeof (request));
93511963SAfshin.Ardakani@Sun.COM 	bzero(&reply, sizeof (reply));
9365331Samw 
93711963SAfshin.Ardakani@Sun.COM 	if (smb_common_decode(arg->data, arg->datalen,
93811963SAfshin.Ardakani@Sun.COM 	    dfs_referral_query_xdr, &request) != 0)
93911963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_DECODE_ERROR);
94011963SAfshin.Ardakani@Sun.COM 
94111963SAfshin.Ardakani@Sun.COM 	reply.rp_status = dfs_get_referrals((const char *)request.rq_path,
94211963SAfshin.Ardakani@Sun.COM 	    request.rq_type, &reply.rp_referrals);
94311963SAfshin.Ardakani@Sun.COM 
94411963SAfshin.Ardakani@Sun.COM 	if (reply.rp_status != ERROR_SUCCESS)
94511963SAfshin.Ardakani@Sun.COM 		bzero(&reply.rp_referrals, sizeof (dfs_info_t));
9465331Samw 
94711963SAfshin.Ardakani@Sun.COM 	arg->rbuf = smb_common_encode(&reply, dfs_referral_response_xdr,
94811963SAfshin.Ardakani@Sun.COM 	    &arg->rsize);
94911963SAfshin.Ardakani@Sun.COM 
95011963SAfshin.Ardakani@Sun.COM 	if (reply.rp_status == ERROR_SUCCESS)
95111963SAfshin.Ardakani@Sun.COM 		dfs_info_free(&reply.rp_referrals);
9525331Samw 
95311963SAfshin.Ardakani@Sun.COM 	xdr_free(dfs_referral_query_xdr, (char *)&request);
95411963SAfshin.Ardakani@Sun.COM 
95511963SAfshin.Ardakani@Sun.COM 	if (arg->rbuf == NULL)
95611963SAfshin.Ardakani@Sun.COM 		return (SMB_DOP_ENCODE_ERROR);
95711963SAfshin.Ardakani@Sun.COM 	return (SMB_DOP_SUCCESS);
9585331Samw }
959*12508Samw@Sun.COM 
960*12508Samw@Sun.COM static int
smbd_dop_shr_hostaccess(smbd_arg_t * arg)961*12508Samw@Sun.COM smbd_dop_shr_hostaccess(smbd_arg_t *arg)
962*12508Samw@Sun.COM {
963*12508Samw@Sun.COM 	smb_shr_hostaccess_query_t request;
964*12508Samw@Sun.COM 	uint32_t reply;
965*12508Samw@Sun.COM 
966*12508Samw@Sun.COM 	bzero(&request, sizeof (request));
967*12508Samw@Sun.COM 	bzero(&reply, sizeof (reply));
968*12508Samw@Sun.COM 
969*12508Samw@Sun.COM 	if (smb_common_decode(arg->data, arg->datalen,
970*12508Samw@Sun.COM 	    smb_shr_hostaccess_query_xdr, &request) != 0)
971*12508Samw@Sun.COM 		return (SMB_DOP_DECODE_ERROR);
972*12508Samw@Sun.COM 
973*12508Samw@Sun.COM 	reply = smb_shr_hostaccess(&request.shq_ipaddr, request.shq_none,
974*12508Samw@Sun.COM 	    request.shq_ro, request.shq_rw, request.shq_flag);
975*12508Samw@Sun.COM 
976*12508Samw@Sun.COM 	arg->rbuf = smb_common_encode(&reply, xdr_uint32_t, &arg->rsize);
977*12508Samw@Sun.COM 
978*12508Samw@Sun.COM 	xdr_free(smb_shr_hostaccess_query_xdr, (char *)&request);
979*12508Samw@Sun.COM 
980*12508Samw@Sun.COM 	if (arg->rbuf == NULL)
981*12508Samw@Sun.COM 		return (SMB_DOP_ENCODE_ERROR);
982*12508Samw@Sun.COM 	return (SMB_DOP_SUCCESS);
983*12508Samw@Sun.COM }
984*12508Samw@Sun.COM 
985*12508Samw@Sun.COM static int
smbd_dop_shr_exec(smbd_arg_t * arg)986*12508Samw@Sun.COM smbd_dop_shr_exec(smbd_arg_t *arg)
987*12508Samw@Sun.COM {
988*12508Samw@Sun.COM 	smb_shr_execinfo_t request;
989*12508Samw@Sun.COM 	int reply;
990*12508Samw@Sun.COM 
991*12508Samw@Sun.COM 	bzero(&request, sizeof (request));
992*12508Samw@Sun.COM 	bzero(&reply, sizeof (reply));
993*12508Samw@Sun.COM 
994*12508Samw@Sun.COM 	if (smb_common_decode(arg->data, arg->datalen,
995*12508Samw@Sun.COM 	    smb_shr_execinfo_xdr, &request) != 0)
996*12508Samw@Sun.COM 		return (SMB_DOP_DECODE_ERROR);
997*12508Samw@Sun.COM 
998*12508Samw@Sun.COM 	reply = smb_shr_exec(&request);
999*12508Samw@Sun.COM 
1000*12508Samw@Sun.COM 	if (reply != 0)
1001*12508Samw@Sun.COM 		syslog(LOG_NOTICE, "Failed to execute %s command",
1002*12508Samw@Sun.COM 		    (request.e_type == SMB_EXEC_MAP) ? "map" : "unmap");
1003*12508Samw@Sun.COM 
1004*12508Samw@Sun.COM 	arg->rbuf = smb_common_encode(&reply, xdr_int, &arg->rsize);
1005*12508Samw@Sun.COM 
1006*12508Samw@Sun.COM 	xdr_free(smb_shr_execinfo_xdr, (char *)&request);
1007*12508Samw@Sun.COM 
1008*12508Samw@Sun.COM 	if (arg->rbuf == NULL)
1009*12508Samw@Sun.COM 		return (SMB_DOP_ENCODE_ERROR);
1010*12508Samw@Sun.COM 	return (SMB_DOP_SUCCESS);
1011*12508Samw@Sun.COM }
1012