1*b819cea2SGordon Ross /*
2*b819cea2SGordon Ross  * CDDL HEADER START
3*b819cea2SGordon Ross  *
4*b819cea2SGordon Ross  * The contents of this file are subject to the terms of the
5*b819cea2SGordon Ross  * Common Development and Distribution License (the "License").
6*b819cea2SGordon Ross  * You may not use this file except in compliance with the License.
7*b819cea2SGordon Ross  *
8*b819cea2SGordon Ross  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*b819cea2SGordon Ross  * or http://www.opensolaris.org/os/licensing.
10*b819cea2SGordon Ross  * See the License for the specific language governing permissions
11*b819cea2SGordon Ross  * and limitations under the License.
12*b819cea2SGordon Ross  *
13*b819cea2SGordon Ross  * When distributing Covered Code, include this CDDL HEADER in each
14*b819cea2SGordon Ross  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*b819cea2SGordon Ross  * If applicable, add the following below this CDDL HEADER, with the
16*b819cea2SGordon Ross  * fields enclosed by brackets "[]" replaced with your own identifying
17*b819cea2SGordon Ross  * information: Portions Copyright [yyyy] [name of copyright owner]
18*b819cea2SGordon Ross  *
19*b819cea2SGordon Ross  * CDDL HEADER END
20*b819cea2SGordon Ross  */
21*b819cea2SGordon Ross /*
22*b819cea2SGordon Ross  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23*b819cea2SGordon Ross  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
24*b819cea2SGordon Ross  */
25*b819cea2SGordon Ross 
26*b819cea2SGordon Ross #include <sys/list.h>
27*b819cea2SGordon Ross #include <assert.h>
28*b819cea2SGordon Ross #include <alloca.h>
29*b819cea2SGordon Ross #include <door.h>
30*b819cea2SGordon Ross #include <errno.h>
31*b819cea2SGordon Ross #include <syslog.h>
32*b819cea2SGordon Ross #include <unistd.h>
33*b819cea2SGordon Ross #include <stdio.h>
34*b819cea2SGordon Ross #include <synch.h>
35*b819cea2SGordon Ross #include <string.h>
36*b819cea2SGordon Ross #include <stdlib.h>
37*b819cea2SGordon Ross #include <sys/stat.h>
38*b819cea2SGordon Ross #include <fcntl.h>
39*b819cea2SGordon Ross #include <pthread.h>
40*b819cea2SGordon Ross #include <strings.h>
41*b819cea2SGordon Ross #include <umem.h>
42*b819cea2SGordon Ross 
43*b819cea2SGordon Ross #include <smbsrv/smb_door.h>
44*b819cea2SGordon Ross #include <smbsrv/smb_xdr.h>
45*b819cea2SGordon Ross #include <smbsrv/smb_token.h>
46*b819cea2SGordon Ross #include <smbsrv/libmlsvc.h>
47*b819cea2SGordon Ross #include <smbsrv/libsmbns.h>
48*b819cea2SGordon Ross #include "smbd.h"
49*b819cea2SGordon Ross 
50*b819cea2SGordon Ross 
51*b819cea2SGordon Ross /*
52*b819cea2SGordon Ross  * Special version of smb_door_dispatch() for the
53*b819cea2SGordon Ross  * "fake" smbsrv (running in user space).
54*b819cea2SGordon Ross  *
55*b819cea2SGordon Ross  * This is called via function pointer from
56*b819cea2SGordon Ross  * smbsrv: smb_kdoor_upcall()
57*b819cea2SGordon Ross  *
58*b819cea2SGordon Ross  * The args and response go RPC encoded, just so we can
59*b819cea2SGordon Ross  * borrow some of the common doorsvc code, even though
60*b819cea2SGordon Ross  * there's no need for RPC encoding in this scenario.
61*b819cea2SGordon Ross  */
62*b819cea2SGordon Ross int
fksmbd_door_dispatch(smb_doorarg_t * da)63*b819cea2SGordon Ross fksmbd_door_dispatch(smb_doorarg_t *da)
64*b819cea2SGordon Ross {
65*b819cea2SGordon Ross 
66*b819cea2SGordon Ross 	smbd_arg_t	dop_arg;
67*b819cea2SGordon Ross 	smb_doorhdr_t	*hdr;
68*b819cea2SGordon Ross 	char		*rbuf = NULL;
69*b819cea2SGordon Ross 	char		*argp = da->da_arg.data_ptr;
70*b819cea2SGordon Ross 	size_t		arg_size = da->da_arg.data_size;
71*b819cea2SGordon Ross 	size_t		hdr_size, rsize;
72*b819cea2SGordon Ross 
73*b819cea2SGordon Ross 	/*
74*b819cea2SGordon Ross 	 * Decode
75*b819cea2SGordon Ross 	 *
76*b819cea2SGordon Ross 	 * da->da_arg.data_ptr  = (arg data, xdr encoded)
77*b819cea2SGordon Ross 	 * da->da_arg.data_size = (arg data len)
78*b819cea2SGordon Ross 	 */
79*b819cea2SGordon Ross 
80*b819cea2SGordon Ross 	bzero(&dop_arg, sizeof (smbd_arg_t));
81*b819cea2SGordon Ross 	hdr = &dop_arg.hdr;
82*b819cea2SGordon Ross 	hdr_size = xdr_sizeof(smb_doorhdr_xdr, hdr);
83*b819cea2SGordon Ross 
84*b819cea2SGordon Ross 	if ((argp == NULL) || (arg_size < hdr_size)) {
85*b819cea2SGordon Ross 		syslog(LOG_DEBUG, "fksmbd_door_dispatch: bad args");
86*b819cea2SGordon Ross 		return (-1);
87*b819cea2SGordon Ross 	}
88*b819cea2SGordon Ross 
89*b819cea2SGordon Ross 	if (smb_doorhdr_decode(hdr, (uint8_t *)argp, hdr_size) == -1) {
90*b819cea2SGordon Ross 		syslog(LOG_DEBUG, "smbd_door_dispatch: header decode failed");
91*b819cea2SGordon Ross 		return (-1);
92*b819cea2SGordon Ross 	}
93*b819cea2SGordon Ross 
94*b819cea2SGordon Ross 	if ((hdr->dh_magic != SMB_DOOR_HDR_MAGIC) ||
95*b819cea2SGordon Ross 	    (hdr->dh_flags != SMB_DF_FAKE_KERNEL)) {
96*b819cea2SGordon Ross 		syslog(LOG_DEBUG, "fksmbd_door_dispatch: invalid header");
97*b819cea2SGordon Ross 		return (-1);
98*b819cea2SGordon Ross 	}
99*b819cea2SGordon Ross 
100*b819cea2SGordon Ross 	dop_arg.opname = smb_doorhdr_opname(hdr->dh_op);
101*b819cea2SGordon Ross 	dop_arg.data = argp + hdr_size;
102*b819cea2SGordon Ross 	dop_arg.datalen = hdr->dh_datalen;
103*b819cea2SGordon Ross 
104*b819cea2SGordon Ross 	if (hdr->dh_op == SMB_DR_ASYNC_RESPONSE) {
105*b819cea2SGordon Ross 		/*
106*b819cea2SGordon Ross 		 * ASYNC_RESPONSE is not used here.
107*b819cea2SGordon Ross 		 */
108*b819cea2SGordon Ross 		syslog(LOG_DEBUG, "fksmbd_door_dispatch: ASYNC?");
109*b819cea2SGordon Ross 		return (-1);
110*b819cea2SGordon Ross 	}
111*b819cea2SGordon Ross 
112*b819cea2SGordon Ross 	/*
113*b819cea2SGordon Ross 	 * Dispatch
114*b819cea2SGordon Ross 	 *
115*b819cea2SGordon Ross 	 * Call the common smbd_doorsvc.c code.
116*b819cea2SGordon Ross 	 */
117*b819cea2SGordon Ross 	(void) smbd_door_dispatch_op(&dop_arg);
118*b819cea2SGordon Ross 
119*b819cea2SGordon Ross 	/*
120*b819cea2SGordon Ross 	 * Encode
121*b819cea2SGordon Ross 	 *
122*b819cea2SGordon Ross 	 * da->da_arg.rbuf  = (return data buf)
123*b819cea2SGordon Ross 	 * da->da_arg.rsize = (return data size)
124*b819cea2SGordon Ross 	 *
125*b819cea2SGordon Ross 	 * Note that the return data buffer initially
126*b819cea2SGordon Ross 	 * points to the same buffer as the args.
127*b819cea2SGordon Ross 	 * If that's not large enough, umem_alloc.
128*b819cea2SGordon Ross 	 */
129*b819cea2SGordon Ross 
130*b819cea2SGordon Ross 	rsize = dop_arg.rsize + hdr_size;
131*b819cea2SGordon Ross 	rbuf = umem_alloc(rsize, UMEM_DEFAULT);
132*b819cea2SGordon Ross 	if (rbuf == NULL) {
133*b819cea2SGordon Ross 		syslog(LOG_DEBUG, "fksmbd_door_dispatch[%s]: alloc %m",
134*b819cea2SGordon Ross 		    dop_arg.opname);
135*b819cea2SGordon Ross 		return (-1);
136*b819cea2SGordon Ross 	}
137*b819cea2SGordon Ross 
138*b819cea2SGordon Ross 	/* Copy caller's return data after the header. */
139*b819cea2SGordon Ross 	if (dop_arg.rbuf != NULL) {
140*b819cea2SGordon Ross 		(void) memcpy(rbuf + hdr_size, dop_arg.rbuf, dop_arg.rsize);
141*b819cea2SGordon Ross 		free(dop_arg.rbuf);
142*b819cea2SGordon Ross 	}
143*b819cea2SGordon Ross 
144*b819cea2SGordon Ross 	hdr->dh_datalen = dop_arg.rsize;
145*b819cea2SGordon Ross 	(void) smb_doorhdr_encode(hdr, (uint8_t *)rbuf, hdr_size);
146*b819cea2SGordon Ross 
147*b819cea2SGordon Ross 	/* Let's update da->da_hdr too. */
148*b819cea2SGordon Ross 	da->da_hdr = *hdr;
149*b819cea2SGordon Ross 
150*b819cea2SGordon Ross 	/*
151*b819cea2SGordon Ross 	 * Was door_return()
152*b819cea2SGordon Ross 	 * NB: The "fake kernel" smbsrv code will umem_free rbuf.
153*b819cea2SGordon Ross 	 */
154*b819cea2SGordon Ross 	da->da_arg.rbuf = rbuf;
155*b819cea2SGordon Ross 	da->da_arg.rsize = rsize;
156*b819cea2SGordon Ross 
157*b819cea2SGordon Ross 	return (0);
158*b819cea2SGordon Ross }