xref: /onnv-gate/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c (revision 5331:3047ad28a67b)
1*5331Samw /*
2*5331Samw  * CDDL HEADER START
3*5331Samw  *
4*5331Samw  * The contents of this file are subject to the terms of the
5*5331Samw  * Common Development and Distribution License (the "License").
6*5331Samw  * You may not use this file except in compliance with the License.
7*5331Samw  *
8*5331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5331Samw  * or http://www.opensolaris.org/os/licensing.
10*5331Samw  * See the License for the specific language governing permissions
11*5331Samw  * and limitations under the License.
12*5331Samw  *
13*5331Samw  * When distributing Covered Code, include this CDDL HEADER in each
14*5331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5331Samw  * If applicable, add the following below this CDDL HEADER, with the
16*5331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
17*5331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5331Samw  *
19*5331Samw  * CDDL HEADER END
20*5331Samw  */
21*5331Samw /*
22*5331Samw  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*5331Samw  * Use is subject to license terms.
24*5331Samw  */
25*5331Samw 
26*5331Samw #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*5331Samw 
28*5331Samw /*
29*5331Samw  * SMBd door server
30*5331Samw  */
31*5331Samw 
32*5331Samw #include <alloca.h>
33*5331Samw #include <door.h>
34*5331Samw #include <errno.h>
35*5331Samw #include <syslog.h>
36*5331Samw #include <unistd.h>
37*5331Samw #include <varargs.h>
38*5331Samw #include <stdio.h>
39*5331Samw #include <synch.h>
40*5331Samw #include <string.h>
41*5331Samw #include <stdlib.h>
42*5331Samw #include <sys/stat.h>
43*5331Samw #include <fcntl.h>
44*5331Samw #include <pthread.h>
45*5331Samw #include <strings.h>
46*5331Samw #include <smbsrv/smb_door_svc.h>
47*5331Samw #include <smbsrv/smb_common_door.h>
48*5331Samw 
49*5331Samw 
50*5331Samw static int smb_doorsrv_fildes = -1;
51*5331Samw static mutex_t smb_doorsrv_mutex;
52*5331Samw 
53*5331Samw static void smb_door_srv_func(void *cookie, char *ptr, size_t size,
54*5331Samw     door_desc_t *dp, uint_t n_odesc);
55*5331Samw 
56*5331Samw /*
57*5331Samw  * smb_door_srv_start
58*5331Samw  *
59*5331Samw  * Start the smbd door service.  Create and bind to a door.
60*5331Samw  * Returns 0 on success. Otherwise, -1.
61*5331Samw  */
62*5331Samw int
63*5331Samw smb_door_srv_start()
64*5331Samw {
65*5331Samw 	int newfd;
66*5331Samw 
67*5331Samw 	(void) mutex_lock(&smb_doorsrv_mutex);
68*5331Samw 
69*5331Samw 	if (smb_doorsrv_fildes != -1) {
70*5331Samw 		(void) fprintf(stderr, "smb_doorsrv_start: already started");
71*5331Samw 		(void) mutex_unlock(&smb_doorsrv_mutex);
72*5331Samw 		return (-1);
73*5331Samw 	}
74*5331Samw 
75*5331Samw 	if ((smb_doorsrv_fildes = door_create(smb_door_srv_func,
76*5331Samw 	    SMB_DR_SVC_COOKIE, DOOR_UNREF)) < 0) {
77*5331Samw 		(void) fprintf(stderr, "smb_doorsrv_start: door_create: %s",
78*5331Samw 		    strerror(errno));
79*5331Samw 		smb_doorsrv_fildes = -1;
80*5331Samw 		(void) mutex_unlock(&smb_doorsrv_mutex);
81*5331Samw 		return (-1);
82*5331Samw 	}
83*5331Samw 
84*5331Samw 	(void) unlink(SMB_DR_SVC_NAME);
85*5331Samw 
86*5331Samw 	if ((newfd = creat(SMB_DR_SVC_NAME, 0644)) < 0) {
87*5331Samw 		(void) fprintf(stderr, "smb_doorsrv_start: open: %s",
88*5331Samw 		    strerror(errno));
89*5331Samw 		(void) door_revoke(smb_doorsrv_fildes);
90*5331Samw 		smb_doorsrv_fildes = -1;
91*5331Samw 		(void) mutex_unlock(&smb_doorsrv_mutex);
92*5331Samw 		return (-1);
93*5331Samw 	}
94*5331Samw 
95*5331Samw 	(void) close(newfd);
96*5331Samw 	(void) fdetach(SMB_DR_SVC_NAME);
97*5331Samw 
98*5331Samw 	if (fattach(smb_doorsrv_fildes, SMB_DR_SVC_NAME) < 0) {
99*5331Samw 		(void) fprintf(stderr, "smb_doorsrv_start: fattach: %s",
100*5331Samw 		    strerror(errno));
101*5331Samw 		(void) door_revoke(smb_doorsrv_fildes);
102*5331Samw 		smb_doorsrv_fildes = -1;
103*5331Samw 		(void) mutex_unlock(&smb_doorsrv_mutex);
104*5331Samw 		return (-1);
105*5331Samw 	}
106*5331Samw 
107*5331Samw 	(void) mutex_unlock(&smb_doorsrv_mutex);
108*5331Samw 	return (0);
109*5331Samw }
110*5331Samw 
111*5331Samw 
112*5331Samw /*
113*5331Samw  * smb_door_srv_stop
114*5331Samw  *
115*5331Samw  * Stop the smbd door service.
116*5331Samw  */
117*5331Samw void
118*5331Samw smb_door_srv_stop(void)
119*5331Samw {
120*5331Samw 	(void) mutex_lock(&smb_doorsrv_mutex);
121*5331Samw 
122*5331Samw 	if (smb_doorsrv_fildes != -1) {
123*5331Samw 		(void) fdetach(SMB_DR_SVC_NAME);
124*5331Samw 		(void) door_revoke(smb_doorsrv_fildes);
125*5331Samw 		smb_doorsrv_fildes = -1;
126*5331Samw 	}
127*5331Samw 
128*5331Samw 	(void) mutex_unlock(&smb_doorsrv_mutex);
129*5331Samw }
130*5331Samw 
131*5331Samw /*
132*5331Samw  * smb_door_err_hdlr
133*5331Samw  *
134*5331Samw  * Encode the appropriate error code to the first 4-byte of the result
135*5331Samw  * buffer upon any door operation failure.
136*5331Samw  */
137*5331Samw static char *
138*5331Samw smb_door_srv_err_hdlr(int stat, size_t *rbufsize)
139*5331Samw {
140*5331Samw 	char *rbuf;
141*5331Samw 
142*5331Samw 	if ((rbuf = smb_dr_set_res_stat(stat, rbufsize)) == NULL) {
143*5331Samw 		*rbufsize = 0;
144*5331Samw 		return (NULL);
145*5331Samw 	}
146*5331Samw 
147*5331Samw 	return (rbuf);
148*5331Samw }
149*5331Samw 
150*5331Samw /*
151*5331Samw  * smb_door_srv_func
152*5331Samw  *
153*5331Samw  * This function will determine the opcode by decoding the first 4-byte of
154*5331Samw  * the argument buffer passed by a door client.  The corresponding door
155*5331Samw  * operation will be looked up from the optab and get invoked.
156*5331Samw  * Basically, any door operation will takes the argument buffer as its
157*5331Samw  * parameter, and generates the result buffer.
158*5331Samw  */
159*5331Samw /*ARGSUSED*/
160*5331Samw void
161*5331Samw smb_door_srv_func(void *cookie, char *argp, size_t arg_size, door_desc_t *dp,
162*5331Samw     uint_t n_desc)
163*5331Samw {
164*5331Samw 	char *resbuf = NULL, *tmpbuf = NULL;
165*5331Samw 	size_t rbufsize = 0;
166*5331Samw 	int opcode;
167*5331Samw 	int err;
168*5331Samw 	smb_dr_op_t smbop;
169*5331Samw 
170*5331Samw 	if ((opcode = smb_dr_get_opcode(argp, arg_size)) < 0) {
171*5331Samw 		tmpbuf = smb_door_srv_err_hdlr(SMB_DR_OP_ERR_DECODE,
172*5331Samw 		    &rbufsize);
173*5331Samw 		goto door_return;
174*5331Samw 	}
175*5331Samw 
176*5331Samw 	syslog(LOG_DEBUG, "smb_door_srv_func: execute server routine"
177*5331Samw 	    "(opcode=%d)", opcode);
178*5331Samw 	if (smb_dr_is_valid_opcode(opcode) != 0) {
179*5331Samw 		tmpbuf = smb_door_srv_err_hdlr(SMB_DR_OP_ERR_INVALID_OPCODE,
180*5331Samw 		    &rbufsize);
181*5331Samw 	} else {
182*5331Samw 		smbop = smb_doorsrv_optab[opcode];
183*5331Samw 		if ((tmpbuf = smbop(argp + sizeof (opcode),
184*5331Samw 		    arg_size - sizeof (opcode), dp, n_desc,
185*5331Samw 		    &rbufsize, &err)) == NULL)
186*5331Samw 			tmpbuf = smb_door_srv_err_hdlr(err, &rbufsize);
187*5331Samw 	}
188*5331Samw 
189*5331Samw door_return:
190*5331Samw 	if (tmpbuf) {
191*5331Samw 		if ((resbuf = (char *)alloca(rbufsize)) == NULL)
192*5331Samw 			rbufsize = 0;
193*5331Samw 		else
194*5331Samw 			(void) memcpy(resbuf, tmpbuf, rbufsize);
195*5331Samw 		free(tmpbuf);
196*5331Samw 	}
197*5331Samw 
198*5331Samw 	(void) door_return(resbuf, rbufsize, NULL, 0);
199*5331Samw 	/*NOTREACHED*/
200*5331Samw }
201