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