xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_kshare.c (revision 3ad684d66b78e06edd37e2c4fd3b3949f095194b)
1*3ad684d6Sjb150015 /*
2*3ad684d6Sjb150015  * CDDL HEADER START
3*3ad684d6Sjb150015  *
4*3ad684d6Sjb150015  * The contents of this file are subject to the terms of the
5*3ad684d6Sjb150015  * Common Development and Distribution License (the "License").
6*3ad684d6Sjb150015  * You may not use this file except in compliance with the License.
7*3ad684d6Sjb150015  *
8*3ad684d6Sjb150015  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*3ad684d6Sjb150015  * or http://www.opensolaris.org/os/licensing.
10*3ad684d6Sjb150015  * See the License for the specific language governing permissions
11*3ad684d6Sjb150015  * and limitations under the License.
12*3ad684d6Sjb150015  *
13*3ad684d6Sjb150015  * When distributing Covered Code, include this CDDL HEADER in each
14*3ad684d6Sjb150015  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*3ad684d6Sjb150015  * If applicable, add the following below this CDDL HEADER, with the
16*3ad684d6Sjb150015  * fields enclosed by brackets "[]" replaced with your own identifying
17*3ad684d6Sjb150015  * information: Portions Copyright [yyyy] [name of copyright owner]
18*3ad684d6Sjb150015  *
19*3ad684d6Sjb150015  * CDDL HEADER END
20*3ad684d6Sjb150015  */
21*3ad684d6Sjb150015 /*
22*3ad684d6Sjb150015  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*3ad684d6Sjb150015  * Use is subject to license terms.
24*3ad684d6Sjb150015  */
25*3ad684d6Sjb150015 
26*3ad684d6Sjb150015 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*3ad684d6Sjb150015 
28*3ad684d6Sjb150015 /*
29*3ad684d6Sjb150015  * Kernel door client for LanMan share management.
30*3ad684d6Sjb150015  */
31*3ad684d6Sjb150015 
32*3ad684d6Sjb150015 #include <sys/ddi.h>
33*3ad684d6Sjb150015 #include <sys/sunddi.h>
34*3ad684d6Sjb150015 #include <sys/cmn_err.h>
35*3ad684d6Sjb150015 #include <sys/door.h>
36*3ad684d6Sjb150015 #include <smbsrv/lmshare.h>
37*3ad684d6Sjb150015 #include <smbsrv/lmerr.h>
38*3ad684d6Sjb150015 #include <smbsrv/smb_common_door.h>
39*3ad684d6Sjb150015 #include <smbsrv/lmshare_door.h>
40*3ad684d6Sjb150015 #include <smbsrv/smbinfo.h>
41*3ad684d6Sjb150015 
42*3ad684d6Sjb150015 static int smb_kshare_chk_dsrv_status(int, smb_dr_ctx_t *);
43*3ad684d6Sjb150015 
44*3ad684d6Sjb150015 /*
45*3ad684d6Sjb150015  * smb_kshare_init
46*3ad684d6Sjb150015  *
47*3ad684d6Sjb150015  * This function is not MultiThread safe. The caller has to make sure only one
48*3ad684d6Sjb150015  * thread calls this function.
49*3ad684d6Sjb150015  */
50*3ad684d6Sjb150015 door_handle_t
51*3ad684d6Sjb150015 smb_kshare_init(int door_id)
52*3ad684d6Sjb150015 {
53*3ad684d6Sjb150015 	return (door_ki_lookup(door_id));
54*3ad684d6Sjb150015 }
55*3ad684d6Sjb150015 
56*3ad684d6Sjb150015 /*
57*3ad684d6Sjb150015  * smb_kshare_fini
58*3ad684d6Sjb150015  *
59*3ad684d6Sjb150015  * This function is not MultiThread safe. The caller has to make sure only one
60*3ad684d6Sjb150015  * thread calls this function.
61*3ad684d6Sjb150015  */
62*3ad684d6Sjb150015 void
63*3ad684d6Sjb150015 smb_kshare_fini(door_handle_t dhdl)
64*3ad684d6Sjb150015 {
65*3ad684d6Sjb150015 	ASSERT(dhdl != NULL);
66*3ad684d6Sjb150015 	if (dhdl)
67*3ad684d6Sjb150015 		door_ki_rele(dhdl);
68*3ad684d6Sjb150015 }
69*3ad684d6Sjb150015 
70*3ad684d6Sjb150015 uint32_t
71*3ad684d6Sjb150015 smb_kshare_getinfo(door_handle_t dhdl, char *share_name, lmshare_info_t *si)
72*3ad684d6Sjb150015 {
73*3ad684d6Sjb150015 	door_arg_t arg;
74*3ad684d6Sjb150015 	char *buf;
75*3ad684d6Sjb150015 	unsigned int used;
76*3ad684d6Sjb150015 	smb_dr_ctx_t *dec_ctx;
77*3ad684d6Sjb150015 	smb_dr_ctx_t *enc_ctx;
78*3ad684d6Sjb150015 	int status;
79*3ad684d6Sjb150015 	uint32_t rc;
80*3ad684d6Sjb150015 	int opcode = LMSHR_DOOR_GETINFO;
81*3ad684d6Sjb150015 
82*3ad684d6Sjb150015 	buf = kmem_alloc(LMSHR_DOOR_SIZE, KM_SLEEP);
83*3ad684d6Sjb150015 
84*3ad684d6Sjb150015 	enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
85*3ad684d6Sjb150015 	smb_dr_put_uint32(enc_ctx, opcode);
86*3ad684d6Sjb150015 	smb_dr_put_string(enc_ctx, share_name);
87*3ad684d6Sjb150015 
88*3ad684d6Sjb150015 	if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
89*3ad684d6Sjb150015 		cmn_err(CE_WARN, "smb_kshare_getinfo: Encode error %d",
90*3ad684d6Sjb150015 		    status);
91*3ad684d6Sjb150015 		kmem_free(buf, LMSHR_DOOR_SIZE);
92*3ad684d6Sjb150015 		return (NERR_InternalError);
93*3ad684d6Sjb150015 	}
94*3ad684d6Sjb150015 
95*3ad684d6Sjb150015 	arg.data_ptr = buf;
96*3ad684d6Sjb150015 	arg.data_size = used;
97*3ad684d6Sjb150015 	arg.desc_ptr = NULL;
98*3ad684d6Sjb150015 	arg.desc_num = 0;
99*3ad684d6Sjb150015 	arg.rbuf = buf;
100*3ad684d6Sjb150015 	arg.rsize = LMSHR_DOOR_SIZE;
101*3ad684d6Sjb150015 
102*3ad684d6Sjb150015 	if (door_ki_upcall(dhdl, &arg) != 0) {
103*3ad684d6Sjb150015 		cmn_err(CE_WARN, "smb_kshare_getinfo: Door call failed");
104*3ad684d6Sjb150015 		kmem_free(buf, LMSHR_DOOR_SIZE);
105*3ad684d6Sjb150015 		return (NERR_InternalError);
106*3ad684d6Sjb150015 	}
107*3ad684d6Sjb150015 
108*3ad684d6Sjb150015 	dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
109*3ad684d6Sjb150015 	if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) {
110*3ad684d6Sjb150015 		kmem_free(buf, LMSHR_DOOR_SIZE);
111*3ad684d6Sjb150015 		return (NERR_InternalError);
112*3ad684d6Sjb150015 	}
113*3ad684d6Sjb150015 
114*3ad684d6Sjb150015 	rc = smb_dr_get_uint32(dec_ctx);
115*3ad684d6Sjb150015 	smb_dr_get_lmshare(dec_ctx, si);
116*3ad684d6Sjb150015 	if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
117*3ad684d6Sjb150015 		cmn_err(CE_WARN, "smb_kshare_getinfo: Decode error %d",
118*3ad684d6Sjb150015 		    status);
119*3ad684d6Sjb150015 		rc = NERR_InternalError;
120*3ad684d6Sjb150015 	}
121*3ad684d6Sjb150015 
122*3ad684d6Sjb150015 	kmem_free(buf, LMSHR_DOOR_SIZE);
123*3ad684d6Sjb150015 	return (rc);
124*3ad684d6Sjb150015 }
125*3ad684d6Sjb150015 
126*3ad684d6Sjb150015 uint32_t
127*3ad684d6Sjb150015 smb_kshare_enum(door_handle_t dhdl, smb_enumshare_info_t *enuminfo)
128*3ad684d6Sjb150015 {
129*3ad684d6Sjb150015 	door_arg_t arg;
130*3ad684d6Sjb150015 	char *door_buf;
131*3ad684d6Sjb150015 	int door_bufsz;
132*3ad684d6Sjb150015 	unsigned int used;
133*3ad684d6Sjb150015 	smb_dr_ctx_t *dec_ctx;
134*3ad684d6Sjb150015 	smb_dr_ctx_t *enc_ctx;
135*3ad684d6Sjb150015 	int status;
136*3ad684d6Sjb150015 	uint32_t rc;
137*3ad684d6Sjb150015 	int opcode = LMSHR_DOOR_ENUM;
138*3ad684d6Sjb150015 
139*3ad684d6Sjb150015 	enuminfo->es_ntotal = enuminfo->es_nsent = 0;
140*3ad684d6Sjb150015 
141*3ad684d6Sjb150015 	door_bufsz = enuminfo->es_bufsize + strlen(enuminfo->es_username)
142*3ad684d6Sjb150015 	    + sizeof (smb_enumshare_info_t);
143*3ad684d6Sjb150015 	door_buf = kmem_alloc(door_bufsz, KM_SLEEP);
144*3ad684d6Sjb150015 
145*3ad684d6Sjb150015 	enc_ctx = smb_dr_encode_start(door_buf, door_bufsz);
146*3ad684d6Sjb150015 	smb_dr_put_uint32(enc_ctx, opcode);
147*3ad684d6Sjb150015 	smb_dr_put_ushort(enc_ctx, enuminfo->es_bufsize);
148*3ad684d6Sjb150015 	smb_dr_put_string(enc_ctx, enuminfo->es_username);
149*3ad684d6Sjb150015 
150*3ad684d6Sjb150015 	if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
151*3ad684d6Sjb150015 		cmn_err(CE_WARN, "smb_kshare_enum: Encode error %d", status);
152*3ad684d6Sjb150015 		kmem_free(door_buf, door_bufsz);
153*3ad684d6Sjb150015 		return (NERR_InternalError);
154*3ad684d6Sjb150015 	}
155*3ad684d6Sjb150015 
156*3ad684d6Sjb150015 	arg.data_ptr = door_buf;
157*3ad684d6Sjb150015 	arg.data_size = used;
158*3ad684d6Sjb150015 	arg.desc_ptr = NULL;
159*3ad684d6Sjb150015 	arg.desc_num = 0;
160*3ad684d6Sjb150015 	arg.rbuf = door_buf;
161*3ad684d6Sjb150015 	arg.rsize = door_bufsz;
162*3ad684d6Sjb150015 
163*3ad684d6Sjb150015 	if (door_ki_upcall(dhdl, &arg) != 0) {
164*3ad684d6Sjb150015 		cmn_err(CE_WARN, "smb_kshare_enum: Door call failed");
165*3ad684d6Sjb150015 		kmem_free(door_buf, door_bufsz);
166*3ad684d6Sjb150015 		return (NERR_InternalError);
167*3ad684d6Sjb150015 	}
168*3ad684d6Sjb150015 
169*3ad684d6Sjb150015 	dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
170*3ad684d6Sjb150015 	if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) {
171*3ad684d6Sjb150015 		kmem_free(door_buf, door_bufsz);
172*3ad684d6Sjb150015 		return (NERR_InternalError);
173*3ad684d6Sjb150015 	}
174*3ad684d6Sjb150015 
175*3ad684d6Sjb150015 	rc = smb_dr_get_uint32(dec_ctx);
176*3ad684d6Sjb150015 	if (rc == NERR_Success) {
177*3ad684d6Sjb150015 		enuminfo->es_ntotal = smb_dr_get_ushort(dec_ctx);
178*3ad684d6Sjb150015 		enuminfo->es_nsent = smb_dr_get_ushort(dec_ctx);
179*3ad684d6Sjb150015 		enuminfo->es_datasize = smb_dr_get_ushort(dec_ctx);
180*3ad684d6Sjb150015 		(void) smb_dr_get_buf(dec_ctx,
181*3ad684d6Sjb150015 		    (unsigned char *)enuminfo->es_buf,
182*3ad684d6Sjb150015 		    enuminfo->es_bufsize);
183*3ad684d6Sjb150015 	}
184*3ad684d6Sjb150015 
185*3ad684d6Sjb150015 	if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
186*3ad684d6Sjb150015 		cmn_err(CE_WARN, "smb_kshare_enum: Decode error %d", status);
187*3ad684d6Sjb150015 		rc = NERR_InternalError;
188*3ad684d6Sjb150015 	}
189*3ad684d6Sjb150015 
190*3ad684d6Sjb150015 	kmem_free(door_buf, door_bufsz);
191*3ad684d6Sjb150015 	return (rc);
192*3ad684d6Sjb150015 }
193*3ad684d6Sjb150015 
194*3ad684d6Sjb150015 /*
195*3ad684d6Sjb150015  * This is a special interface that will be utilized by ZFS to cause
196*3ad684d6Sjb150015  * a share to be added/removed
197*3ad684d6Sjb150015  *
198*3ad684d6Sjb150015  * arg is either a lmshare_info_t or share_name from userspace.
199*3ad684d6Sjb150015  * It will need to be copied into the kernel.   It is lmshare_info_t
200*3ad684d6Sjb150015  * for add operations and share_name for delete operations.
201*3ad684d6Sjb150015  */
202*3ad684d6Sjb150015 int
203*3ad684d6Sjb150015 smb_kshare_upcall(door_handle_t dhdl, void *arg, boolean_t add_share)
204*3ad684d6Sjb150015 {
205*3ad684d6Sjb150015 	door_arg_t	doorarg = { 0 };
206*3ad684d6Sjb150015 	char		*buf = NULL;
207*3ad684d6Sjb150015 	char		*str = NULL;
208*3ad684d6Sjb150015 	int		error;
209*3ad684d6Sjb150015 	int		rc;
210*3ad684d6Sjb150015 	unsigned int	used;
211*3ad684d6Sjb150015 	smb_dr_ctx_t	*dec_ctx;
212*3ad684d6Sjb150015 	smb_dr_ctx_t	*enc_ctx;
213*3ad684d6Sjb150015 	lmshare_info_t	*lmshare = NULL;
214*3ad684d6Sjb150015 	int		opcode;
215*3ad684d6Sjb150015 
216*3ad684d6Sjb150015 	opcode = add_share == B_TRUE ? LMSHR_DOOR_ADD : LMSHR_DOOR_DELETE;
217*3ad684d6Sjb150015 
218*3ad684d6Sjb150015 	buf = kmem_alloc(LMSHR_DOOR_SIZE, KM_SLEEP);
219*3ad684d6Sjb150015 	enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
220*3ad684d6Sjb150015 	smb_dr_put_uint32(enc_ctx, opcode);
221*3ad684d6Sjb150015 
222*3ad684d6Sjb150015 	switch (opcode) {
223*3ad684d6Sjb150015 	case LMSHR_DOOR_ADD:
224*3ad684d6Sjb150015 		lmshare = kmem_alloc(sizeof (lmshare_info_t), KM_SLEEP);
225*3ad684d6Sjb150015 		if (error = xcopyin(arg, lmshare, sizeof (lmshare_info_t))) {
226*3ad684d6Sjb150015 			kmem_free(lmshare, sizeof (lmshare_info_t));
227*3ad684d6Sjb150015 			kmem_free(buf, LMSHR_DOOR_SIZE);
228*3ad684d6Sjb150015 			return (error);
229*3ad684d6Sjb150015 		}
230*3ad684d6Sjb150015 		smb_dr_put_lmshare(enc_ctx, lmshare);
231*3ad684d6Sjb150015 		break;
232*3ad684d6Sjb150015 
233*3ad684d6Sjb150015 	case LMSHR_DOOR_DELETE:
234*3ad684d6Sjb150015 		str = kmem_alloc(MAXPATHLEN, KM_SLEEP);
235*3ad684d6Sjb150015 		if (error = copyinstr(arg, str, MAXPATHLEN, NULL)) {
236*3ad684d6Sjb150015 			kmem_free(str, MAXPATHLEN);
237*3ad684d6Sjb150015 			kmem_free(buf, LMSHR_DOOR_SIZE);
238*3ad684d6Sjb150015 			return (error);
239*3ad684d6Sjb150015 		}
240*3ad684d6Sjb150015 		smb_dr_put_string(enc_ctx, str);
241*3ad684d6Sjb150015 		kmem_free(str, MAXPATHLEN);
242*3ad684d6Sjb150015 		break;
243*3ad684d6Sjb150015 	}
244*3ad684d6Sjb150015 
245*3ad684d6Sjb150015 	if ((error = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
246*3ad684d6Sjb150015 		kmem_free(buf, LMSHR_DOOR_SIZE);
247*3ad684d6Sjb150015 		if (lmshare)
248*3ad684d6Sjb150015 			kmem_free(lmshare, sizeof (lmshare_info_t));
249*3ad684d6Sjb150015 		return (NERR_InternalError);
250*3ad684d6Sjb150015 	}
251*3ad684d6Sjb150015 
252*3ad684d6Sjb150015 	doorarg.data_ptr = buf;
253*3ad684d6Sjb150015 	doorarg.data_size = used;
254*3ad684d6Sjb150015 	doorarg.rbuf = buf;
255*3ad684d6Sjb150015 	doorarg.rsize = LMSHR_DOOR_SIZE;
256*3ad684d6Sjb150015 
257*3ad684d6Sjb150015 	error = door_ki_upcall(dhdl, &doorarg);
258*3ad684d6Sjb150015 
259*3ad684d6Sjb150015 	if (error) {
260*3ad684d6Sjb150015 		kmem_free(buf, LMSHR_DOOR_SIZE);
261*3ad684d6Sjb150015 		if (lmshare)
262*3ad684d6Sjb150015 			kmem_free(lmshare, sizeof (lmshare_info_t));
263*3ad684d6Sjb150015 		return (error);
264*3ad684d6Sjb150015 	}
265*3ad684d6Sjb150015 
266*3ad684d6Sjb150015 	dec_ctx = smb_dr_decode_start(doorarg.data_ptr, doorarg.data_size);
267*3ad684d6Sjb150015 	if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) {
268*3ad684d6Sjb150015 		kmem_free(buf, LMSHR_DOOR_SIZE);
269*3ad684d6Sjb150015 		if (lmshare)
270*3ad684d6Sjb150015 			kmem_free(lmshare, sizeof (lmshare_info_t));
271*3ad684d6Sjb150015 		return (NERR_InternalError);
272*3ad684d6Sjb150015 	}
273*3ad684d6Sjb150015 
274*3ad684d6Sjb150015 	rc = smb_dr_get_uint32(dec_ctx);
275*3ad684d6Sjb150015 	if (opcode == LMSHR_DOOR_ADD)
276*3ad684d6Sjb150015 		smb_dr_get_lmshare(dec_ctx, lmshare);
277*3ad684d6Sjb150015 
278*3ad684d6Sjb150015 	if (smb_dr_decode_finish(dec_ctx))
279*3ad684d6Sjb150015 		rc = NERR_InternalError;
280*3ad684d6Sjb150015 
281*3ad684d6Sjb150015 	kmem_free(buf, LMSHR_DOOR_SIZE);
282*3ad684d6Sjb150015 	if (lmshare)
283*3ad684d6Sjb150015 		kmem_free(lmshare, sizeof (lmshare_info_t));
284*3ad684d6Sjb150015 
285*3ad684d6Sjb150015 	return ((rc == NERR_DuplicateShare && add_share) ? 0 : rc);
286*3ad684d6Sjb150015 }
287*3ad684d6Sjb150015 
288*3ad684d6Sjb150015 /*
289*3ad684d6Sjb150015  * Return 0 upon success. Otherwise > 0
290*3ad684d6Sjb150015  */
291*3ad684d6Sjb150015 static int
292*3ad684d6Sjb150015 smb_kshare_chk_dsrv_status(int opcode, smb_dr_ctx_t *dec_ctx)
293*3ad684d6Sjb150015 {
294*3ad684d6Sjb150015 	int status = smb_dr_get_int32(dec_ctx);
295*3ad684d6Sjb150015 	int err;
296*3ad684d6Sjb150015 
297*3ad684d6Sjb150015 	switch (status) {
298*3ad684d6Sjb150015 	case LMSHR_DOOR_SRV_SUCCESS:
299*3ad684d6Sjb150015 		return (0);
300*3ad684d6Sjb150015 
301*3ad684d6Sjb150015 	case LMSHR_DOOR_SRV_ERROR:
302*3ad684d6Sjb150015 		err = smb_dr_get_uint32(dec_ctx);
303*3ad684d6Sjb150015 		cmn_err(CE_WARN, "%d: Encountered door server error %d",
304*3ad684d6Sjb150015 		    opcode, err);
305*3ad684d6Sjb150015 		(void) smb_dr_decode_finish(dec_ctx);
306*3ad684d6Sjb150015 		return (err);
307*3ad684d6Sjb150015 	}
308*3ad684d6Sjb150015 
309*3ad684d6Sjb150015 	ASSERT(0);
310*3ad684d6Sjb150015 	return (EINVAL);
311*3ad684d6Sjb150015 }
312