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