xref: /onnv-gate/usr/src/cmd/smbsrv/smbd/smbd_opipe_doorsvc.c (revision 11963:061945695ce1)
17052Samw /*
27052Samw  * CDDL HEADER START
37052Samw  *
47052Samw  * The contents of this file are subject to the terms of the
57052Samw  * Common Development and Distribution License (the "License").
67052Samw  * You may not use this file except in compliance with the License.
77052Samw  *
87052Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97052Samw  * or http://www.opensolaris.org/os/licensing.
107052Samw  * See the License for the specific language governing permissions
117052Samw  * and limitations under the License.
127052Samw  *
137052Samw  * When distributing Covered Code, include this CDDL HEADER in each
147052Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157052Samw  * If applicable, add the following below this CDDL HEADER, with the
167052Samw  * fields enclosed by brackets "[]" replaced with your own identifying
177052Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
187052Samw  *
197052Samw  * CDDL HEADER END
207052Samw  */
217052Samw /*
22*11963SAfshin.Ardakani@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
237052Samw  * Use is subject to license terms.
247052Samw  */
257052Samw 
267052Samw #include <stdio.h>
277052Samw #include <strings.h>
287052Samw #include <stdlib.h>
297052Samw #include <unistd.h>
307052Samw #include <fcntl.h>
317052Samw #include <sys/types.h>
327052Samw #include <sys/stat.h>
337052Samw #include <door.h>
347052Samw #include <errno.h>
357052Samw #include <pthread.h>
367052Samw 
377052Samw #include <smbsrv/libsmb.h>
387052Samw #include <smbsrv/libmlrpc.h>
39*11963SAfshin.Ardakani@Sun.COM #include "smbd.h"
407052Samw 
417052Samw static int smbd_opipe_fd = -1;
427052Samw static int smbd_opipe_cookie = 0x50495045;	/* PIPE */
437052Samw static pthread_mutex_t smbd_opipe_mutex = PTHREAD_MUTEX_INITIALIZER;
44*11963SAfshin.Ardakani@Sun.COM static smbd_door_t smbd_opipe_sdh;
457052Samw 
467052Samw static void smbd_opipe_dispatch(void *, char *, size_t, door_desc_t *, uint_t);
47*11963SAfshin.Ardakani@Sun.COM static int smbd_opipe_exec_async(uint32_t);
487052Samw 
497052Samw /*
507052Samw  * Create the smbd opipe door service.
517052Samw  * Returns the door descriptor on success.  Otherwise returns -1.
527052Samw  */
537052Samw int
smbd_opipe_start(void)54*11963SAfshin.Ardakani@Sun.COM smbd_opipe_start(void)
557052Samw {
567052Samw 	(void) pthread_mutex_lock(&smbd_opipe_mutex);
577052Samw 
587052Samw 	if (smbd_opipe_fd != -1) {
597052Samw 		(void) pthread_mutex_unlock(&smbd_opipe_mutex);
607052Samw 		errno = EEXIST;
617052Samw 		return (-1);
627052Samw 	}
637052Samw 
64*11963SAfshin.Ardakani@Sun.COM 	smbd_door_init(&smbd_opipe_sdh, "opipe");
65*11963SAfshin.Ardakani@Sun.COM 
667052Samw 	errno = 0;
677052Samw 	if ((smbd_opipe_fd = door_create(smbd_opipe_dispatch,
687052Samw 	    &smbd_opipe_cookie, (DOOR_UNREF | DOOR_REFUSE_DESC))) < 0) {
697052Samw 		smbd_opipe_fd = -1;
707052Samw 	}
717052Samw 
727052Samw 	(void) pthread_mutex_unlock(&smbd_opipe_mutex);
737052Samw 	return (smbd_opipe_fd);
747052Samw }
757052Samw 
767052Samw /*
777052Samw  * Stop the smbd opipe door service.
787052Samw  */
797052Samw void
smbd_opipe_stop(void)80*11963SAfshin.Ardakani@Sun.COM smbd_opipe_stop(void)
817052Samw {
827052Samw 	(void) pthread_mutex_lock(&smbd_opipe_mutex);
837052Samw 
84*11963SAfshin.Ardakani@Sun.COM 	smbd_door_fini(&smbd_opipe_sdh);
85*11963SAfshin.Ardakani@Sun.COM 
867052Samw 	if (smbd_opipe_fd != -1) {
877052Samw 		(void) door_revoke(smbd_opipe_fd);
887052Samw 		smbd_opipe_fd = -1;
897052Samw 	}
907052Samw 
917052Samw 	(void) pthread_mutex_unlock(&smbd_opipe_mutex);
927052Samw }
937052Samw 
947052Samw /*
957052Samw  * Process smbd opipe requests.
967052Samw  */
977052Samw /*ARGSUSED*/
987052Samw static void
smbd_opipe_dispatch(void * cookie,char * argp,size_t arg_size,door_desc_t * dd,uint_t n_desc)997052Samw smbd_opipe_dispatch(void *cookie, char *argp, size_t arg_size,
1007052Samw     door_desc_t *dd, uint_t n_desc)
1017052Samw {
1027052Samw 	char buf[SMB_OPIPE_DOOR_BUFSIZE];
103*11963SAfshin.Ardakani@Sun.COM 	smb_doorhdr_t hdr;
1047052Samw 	size_t hdr_size;
1057052Samw 	uint8_t *data;
1067052Samw 	uint32_t datalen;
1077052Samw 
108*11963SAfshin.Ardakani@Sun.COM 	smbd_door_enter(&smbd_opipe_sdh);
109*11963SAfshin.Ardakani@Sun.COM 
110*11963SAfshin.Ardakani@Sun.COM 	if (!smbd_online())
111*11963SAfshin.Ardakani@Sun.COM 		smbd_door_return(&smbd_opipe_sdh, NULL, 0, NULL, 0);
112*11963SAfshin.Ardakani@Sun.COM 
113*11963SAfshin.Ardakani@Sun.COM 	bzero(&hdr, sizeof (smb_doorhdr_t));
114*11963SAfshin.Ardakani@Sun.COM 	hdr_size = xdr_sizeof(smb_doorhdr_xdr, &hdr);
1157052Samw 
1167052Samw 	if ((cookie != &smbd_opipe_cookie) || (argp == NULL) ||
1177052Samw 	    (arg_size < hdr_size)) {
118*11963SAfshin.Ardakani@Sun.COM 		smbd_door_return(&smbd_opipe_sdh, NULL, 0, NULL, 0);
1197052Samw 	}
1207052Samw 
121*11963SAfshin.Ardakani@Sun.COM 	if (smb_doorhdr_decode(&hdr, (uint8_t *)argp, hdr_size) == -1)
122*11963SAfshin.Ardakani@Sun.COM 		smbd_door_return(&smbd_opipe_sdh, NULL, 0, NULL, 0);
1237052Samw 
124*11963SAfshin.Ardakani@Sun.COM 	if ((hdr.dh_magic != SMB_OPIPE_HDR_MAGIC) || (hdr.dh_fid == 0))
125*11963SAfshin.Ardakani@Sun.COM 		smbd_door_return(&smbd_opipe_sdh, NULL, 0, NULL, 0);
1267052Samw 
127*11963SAfshin.Ardakani@Sun.COM 	if (hdr.dh_datalen > SMB_OPIPE_DOOR_BUFSIZE)
128*11963SAfshin.Ardakani@Sun.COM 		hdr.dh_datalen = SMB_OPIPE_DOOR_BUFSIZE;
1297052Samw 
1307052Samw 	data = (uint8_t *)argp + hdr_size;
131*11963SAfshin.Ardakani@Sun.COM 	datalen = hdr.dh_datalen;
1327052Samw 
133*11963SAfshin.Ardakani@Sun.COM 	switch (hdr.dh_op) {
1347052Samw 	case SMB_OPIPE_OPEN:
135*11963SAfshin.Ardakani@Sun.COM 		hdr.dh_door_rc = ndr_pipe_open(hdr.dh_fid, data, datalen);
1367052Samw 
137*11963SAfshin.Ardakani@Sun.COM 		hdr.dh_datalen = 0;
138*11963SAfshin.Ardakani@Sun.COM 		hdr.dh_resid = 0;
1397052Samw 		datalen = hdr_size;
1407052Samw 		break;
1417052Samw 
1427052Samw 	case SMB_OPIPE_CLOSE:
143*11963SAfshin.Ardakani@Sun.COM 		hdr.dh_door_rc = ndr_pipe_close(hdr.dh_fid);
1447052Samw 
145*11963SAfshin.Ardakani@Sun.COM 		hdr.dh_datalen = 0;
146*11963SAfshin.Ardakani@Sun.COM 		hdr.dh_resid = 0;
1477052Samw 		datalen = hdr_size;
1487052Samw 		break;
1497052Samw 
1507052Samw 	case SMB_OPIPE_READ:
1517052Samw 		data = (uint8_t *)buf + hdr_size;
152*11963SAfshin.Ardakani@Sun.COM 		datalen = hdr.dh_datalen;
1537052Samw 
154*11963SAfshin.Ardakani@Sun.COM 		hdr.dh_door_rc = ndr_pipe_read(hdr.dh_fid, data, &datalen,
155*11963SAfshin.Ardakani@Sun.COM 		    &hdr.dh_resid);
1567052Samw 
157*11963SAfshin.Ardakani@Sun.COM 		hdr.dh_datalen = datalen;
1587052Samw 		datalen += hdr_size;
1597052Samw 		break;
1607052Samw 
1617052Samw 	case SMB_OPIPE_WRITE:
162*11963SAfshin.Ardakani@Sun.COM 		hdr.dh_door_rc = ndr_pipe_write(hdr.dh_fid, data, datalen);
1637052Samw 
164*11963SAfshin.Ardakani@Sun.COM 		hdr.dh_datalen = 0;
165*11963SAfshin.Ardakani@Sun.COM 		hdr.dh_resid = 0;
166*11963SAfshin.Ardakani@Sun.COM 		datalen = hdr_size;
167*11963SAfshin.Ardakani@Sun.COM 		break;
168*11963SAfshin.Ardakani@Sun.COM 
169*11963SAfshin.Ardakani@Sun.COM 	case SMB_OPIPE_EXEC:
170*11963SAfshin.Ardakani@Sun.COM 		hdr.dh_door_rc = smbd_opipe_exec_async(hdr.dh_fid);
171*11963SAfshin.Ardakani@Sun.COM 
172*11963SAfshin.Ardakani@Sun.COM 		hdr.dh_datalen = 0;
173*11963SAfshin.Ardakani@Sun.COM 		hdr.dh_resid = 0;
1747052Samw 		datalen = hdr_size;
1757052Samw 		break;
1767052Samw 
1777052Samw 	default:
178*11963SAfshin.Ardakani@Sun.COM 		smbd_door_return(&smbd_opipe_sdh, NULL, 0, NULL, 0);
1797052Samw 		break;
1807052Samw 	}
1817052Samw 
182*11963SAfshin.Ardakani@Sun.COM 	(void) smb_doorhdr_encode(&hdr, (uint8_t *)buf, hdr_size);
183*11963SAfshin.Ardakani@Sun.COM 	smbd_door_return(&smbd_opipe_sdh, buf, datalen, NULL, 0);
1847052Samw }
185*11963SAfshin.Ardakani@Sun.COM 
186*11963SAfshin.Ardakani@Sun.COM /*
187*11963SAfshin.Ardakani@Sun.COM  * On success, arg will be freed by the thread.
188*11963SAfshin.Ardakani@Sun.COM  */
189*11963SAfshin.Ardakani@Sun.COM static int
smbd_opipe_exec_async(uint32_t fid)190*11963SAfshin.Ardakani@Sun.COM smbd_opipe_exec_async(uint32_t fid)
191*11963SAfshin.Ardakani@Sun.COM {
192*11963SAfshin.Ardakani@Sun.COM 	pthread_attr_t	attr;
193*11963SAfshin.Ardakani@Sun.COM 	pthread_t	tid;
194*11963SAfshin.Ardakani@Sun.COM 	uint32_t	*arg;
195*11963SAfshin.Ardakani@Sun.COM 	int		rc;
196*11963SAfshin.Ardakani@Sun.COM 
197*11963SAfshin.Ardakani@Sun.COM 	if ((arg = malloc(sizeof (uint32_t))) == NULL)
198*11963SAfshin.Ardakani@Sun.COM 		return (ENOMEM);
199*11963SAfshin.Ardakani@Sun.COM 
200*11963SAfshin.Ardakani@Sun.COM 	*arg = fid;
201*11963SAfshin.Ardakani@Sun.COM 
202*11963SAfshin.Ardakani@Sun.COM 	(void) pthread_attr_init(&attr);
203*11963SAfshin.Ardakani@Sun.COM 	(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
204*11963SAfshin.Ardakani@Sun.COM 	rc = pthread_create(&tid, &attr, ndr_pipe_transact, arg);
205*11963SAfshin.Ardakani@Sun.COM 	(void) pthread_attr_destroy(&attr);
206*11963SAfshin.Ardakani@Sun.COM 
207*11963SAfshin.Ardakani@Sun.COM 	if (rc != 0)
208*11963SAfshin.Ardakani@Sun.COM 		free(arg);
209*11963SAfshin.Ardakani@Sun.COM 	return (rc);
210*11963SAfshin.Ardakani@Sun.COM }
211