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