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.
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.
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]
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
28 * User-space door client for LanMan share management.
42 #include <smbsrv/libsmb.h>
43 #include <smbsrv/smb_share.h>
44 #include <smbsrv/smb.h>
46 #define SMB_SHARE_DOOR_CALL_RETRIES 3
48 static int smb_share_dfd
= -1;
49 static uint64_t smb_share_dncall
= 0;
50 static mutex_t smb_share_dmtx
;
51 static cond_t smb_share_dcv
;
53 static int smb_share_door_clnt_open(void);
54 static void smb_share_door_clnt_close(void);
57 smb_share_door_clnt_init(void)
59 (void) mutex_lock(&smb_share_dmtx
);
60 (void) smb_share_door_clnt_open();
61 (void) mutex_unlock(&smb_share_dmtx
);
65 smb_share_door_clnt_fini(void)
67 (void) mutex_lock(&smb_share_dmtx
);
68 smb_share_door_clnt_close();
69 (void) mutex_unlock(&smb_share_dmtx
);
73 * Open smb_share_door. This is a private call for use by
74 * smb_share_door_clnt_enter() and must be called with smb_share_dmtx held.
76 * Returns the door fd on success. Otherwise, -1.
79 smb_share_door_clnt_open(void)
81 const char *door_name
;
83 if (smb_share_dfd
== -1) {
84 door_name
= getenv("SMB_SHARE_DNAME");
85 if (door_name
== NULL
)
86 door_name
= SMB_SHARE_DNAME
;
88 if ((smb_share_dfd
= open(door_name
, O_RDONLY
)) < 0)
94 return (smb_share_dfd
);
98 * Close smb_share_door.
99 * Private call that must be called with smb_share_dmtx held.
102 smb_share_door_clnt_close(void)
104 if (smb_share_dfd
!= -1) {
105 while (smb_share_dncall
> 0)
106 (void) cond_wait(&smb_share_dcv
, &smb_share_dmtx
);
108 if (smb_share_dfd
!= -1) {
109 (void) close(smb_share_dfd
);
116 * Entry handler for smb_share_door calls.
119 smb_share_door_clnt_enter(void)
124 (void) mutex_lock(&smb_share_dmtx
);
126 if (smb_share_door_clnt_open() == -1) {
127 (void) mutex_unlock(&smb_share_dmtx
);
131 if ((arg
= malloc(sizeof (door_arg_t
) + SMB_SHARE_DSIZE
)) != NULL
) {
132 buf
= ((char *)arg
) + sizeof (door_arg_t
);
133 bzero(arg
, sizeof (door_arg_t
));
136 arg
->rsize
= SMB_SHARE_DSIZE
;
141 (void) mutex_unlock(&smb_share_dmtx
);
146 * Exit handler for smb_share_door calls.
149 smb_share_door_clnt_exit(door_arg_t
*arg
, boolean_t must_close
, char *errmsg
)
152 syslog(LOG_DEBUG
, "smb_share_door: %s failed", errmsg
);
154 (void) mutex_lock(&smb_share_dmtx
);
157 (void) cond_signal(&smb_share_dcv
);
160 smb_share_door_clnt_close();
162 (void) mutex_unlock(&smb_share_dmtx
);
166 smb_share_door_call(int fd
, door_arg_t
*arg
)
171 for (i
= 0; i
< SMB_SHARE_DOOR_CALL_RETRIES
; ++i
) {
174 if ((rc
= door_call(fd
, arg
)) == 0)
177 if (errno
!= EAGAIN
&& errno
!= EINTR
)
185 smb_share_dchk(smb_dr_ctx_t
*dec_ctx
)
187 int status
= smb_dr_get_int32(dec_ctx
);
189 if (status
!= SMB_SHARE_DSUCCESS
) {
190 if (status
== SMB_SHARE_DERROR
)
191 (void) smb_dr_get_uint32(dec_ctx
);
199 smb_share_list(int offset
, smb_shrlist_t
*list
)
202 smb_dr_ctx_t
*dec_ctx
;
203 smb_dr_ctx_t
*enc_ctx
;
206 bzero(list
, sizeof (smb_shrlist_t
));
208 if ((arg
= smb_share_door_clnt_enter()) == NULL
)
209 return (NERR_InternalError
);
211 enc_ctx
= smb_dr_encode_start(arg
->data_ptr
, SMB_SHARE_DSIZE
);
212 smb_dr_put_uint32(enc_ctx
, SMB_SHROP_LIST
);
213 smb_dr_put_int32(enc_ctx
, offset
);
215 rc
= smb_dr_encode_finish(enc_ctx
, (unsigned int *)&arg
->data_size
);
217 smb_share_door_clnt_exit(arg
, B_FALSE
, "encode");
218 return (NERR_InternalError
);
221 if (smb_share_door_call(smb_share_dfd
, arg
) < 0) {
222 smb_share_door_clnt_exit(arg
, B_TRUE
, "door call");
223 return (NERR_InternalError
);
226 dec_ctx
= smb_dr_decode_start(arg
->data_ptr
, arg
->data_size
);
227 if (smb_share_dchk(dec_ctx
) != 0) {
228 (void) smb_dr_decode_finish(dec_ctx
);
229 smb_share_door_clnt_exit(arg
, B_FALSE
, "decode");
230 return (NERR_InternalError
);
233 (void) smb_dr_get_buf(dec_ctx
, (unsigned char *)list
,
234 sizeof (smb_shrlist_t
));
235 if (smb_dr_decode_finish(dec_ctx
) != 0) {
236 smb_share_door_clnt_exit(arg
, B_FALSE
, "decode");
237 return (NERR_InternalError
);
240 smb_share_door_clnt_exit(arg
, B_FALSE
, NULL
);
241 return (NERR_Success
);
245 smb_share_count(void)
248 smb_dr_ctx_t
*dec_ctx
;
249 smb_dr_ctx_t
*enc_ctx
;
253 if ((arg
= smb_share_door_clnt_enter()) == NULL
)
256 enc_ctx
= smb_dr_encode_start(arg
->data_ptr
, SMB_SHARE_DSIZE
);
257 smb_dr_put_uint32(enc_ctx
, SMB_SHROP_NUM_SHARES
);
259 rc
= smb_dr_encode_finish(enc_ctx
, (unsigned int *)&arg
->data_size
);
261 smb_share_door_clnt_exit(arg
, B_FALSE
, "encode");
265 if (smb_share_door_call(smb_share_dfd
, arg
) < 0) {
266 smb_share_door_clnt_exit(arg
, B_TRUE
, "door call");
270 dec_ctx
= smb_dr_decode_start(arg
->data_ptr
, arg
->data_size
);
271 if (smb_share_dchk(dec_ctx
) != 0) {
272 (void) smb_dr_decode_finish(dec_ctx
);
273 smb_share_door_clnt_exit(arg
, B_FALSE
, "decode");
277 num_shares
= smb_dr_get_uint32(dec_ctx
);
278 if (smb_dr_decode_finish(dec_ctx
) != 0) {
279 smb_share_door_clnt_exit(arg
, B_FALSE
, "decode");
283 smb_share_door_clnt_exit(arg
, B_FALSE
, NULL
);
288 smb_share_delete(char *share_name
)
291 smb_dr_ctx_t
*dec_ctx
;
292 smb_dr_ctx_t
*enc_ctx
;
295 if ((arg
= smb_share_door_clnt_enter()) == NULL
)
296 return (NERR_InternalError
);
298 enc_ctx
= smb_dr_encode_start(arg
->data_ptr
, SMB_SHARE_DSIZE
);
299 smb_dr_put_uint32(enc_ctx
, SMB_SHROP_DELETE
);
300 smb_dr_put_string(enc_ctx
, share_name
);
302 rc
= smb_dr_encode_finish(enc_ctx
, (unsigned int *)&arg
->data_size
);
304 smb_share_door_clnt_exit(arg
, B_FALSE
, "encode");
305 return (NERR_InternalError
);
308 if (smb_share_door_call(smb_share_dfd
, arg
) < 0) {
309 smb_share_door_clnt_exit(arg
, B_TRUE
, "door call");
310 return (NERR_InternalError
);
313 dec_ctx
= smb_dr_decode_start(arg
->data_ptr
, arg
->data_size
);
314 if (smb_share_dchk(dec_ctx
) != 0) {
315 (void) smb_dr_decode_finish(dec_ctx
);
316 smb_share_door_clnt_exit(arg
, B_FALSE
, "decode");
317 return (NERR_InternalError
);
320 rc
= smb_dr_get_uint32(dec_ctx
);
321 if (smb_dr_decode_finish(dec_ctx
) != 0) {
322 smb_share_door_clnt_exit(arg
, B_FALSE
, "decode");
323 return (NERR_InternalError
);
326 smb_share_door_clnt_exit(arg
, B_FALSE
, NULL
);
332 smb_share_rename(char *from
, char *to
)
335 smb_dr_ctx_t
*dec_ctx
;
336 smb_dr_ctx_t
*enc_ctx
;
339 if ((arg
= smb_share_door_clnt_enter()) == NULL
)
340 return (NERR_InternalError
);
342 enc_ctx
= smb_dr_encode_start(arg
->data_ptr
, SMB_SHARE_DSIZE
);
343 smb_dr_put_uint32(enc_ctx
, SMB_SHROP_RENAME
);
344 smb_dr_put_string(enc_ctx
, from
);
345 smb_dr_put_string(enc_ctx
, to
);
347 rc
= smb_dr_encode_finish(enc_ctx
, (unsigned int *)&arg
->data_size
);
349 smb_share_door_clnt_exit(arg
, B_FALSE
, "encode");
350 return (NERR_InternalError
);
353 if (smb_share_door_call(smb_share_dfd
, arg
) < 0) {
354 smb_share_door_clnt_exit(arg
, B_TRUE
, "door call");
355 return (NERR_InternalError
);
358 dec_ctx
= smb_dr_decode_start(arg
->data_ptr
, arg
->data_size
);
359 if (smb_share_dchk(dec_ctx
) != 0) {
360 (void) smb_dr_decode_finish(dec_ctx
);
361 smb_share_door_clnt_exit(arg
, B_FALSE
, "decode");
362 return (NERR_InternalError
);
365 rc
= smb_dr_get_uint32(dec_ctx
);
366 if (smb_dr_decode_finish(dec_ctx
) != 0) {
367 smb_share_door_clnt_exit(arg
, B_FALSE
, "decode");
368 return (NERR_InternalError
);
371 smb_share_door_clnt_exit(arg
, B_FALSE
, NULL
);
376 smb_share_create(smb_share_t
*si
)
379 smb_dr_ctx_t
*dec_ctx
;
380 smb_dr_ctx_t
*enc_ctx
;
383 if ((arg
= smb_share_door_clnt_enter()) == NULL
)
384 return (NERR_InternalError
);
386 enc_ctx
= smb_dr_encode_start(arg
->data_ptr
, SMB_SHARE_DSIZE
);
387 smb_dr_put_uint32(enc_ctx
, SMB_SHROP_ADD
);
388 smb_dr_put_share(enc_ctx
, si
);
390 rc
= smb_dr_encode_finish(enc_ctx
, (unsigned int *)&arg
->data_size
);
392 smb_share_door_clnt_exit(arg
, B_FALSE
, "encode");
393 return (NERR_InternalError
);
396 if (smb_share_door_call(smb_share_dfd
, arg
) < 0) {
397 smb_share_door_clnt_exit(arg
, B_TRUE
, "door call");
398 return (NERR_InternalError
);
401 dec_ctx
= smb_dr_decode_start(arg
->data_ptr
, arg
->data_size
);
402 if (smb_share_dchk(dec_ctx
) != 0) {
403 (void) smb_dr_decode_finish(dec_ctx
);
404 smb_share_door_clnt_exit(arg
, B_FALSE
, "decode");
405 return (NERR_InternalError
);
408 rc
= smb_dr_get_uint32(dec_ctx
);
409 smb_dr_get_share(dec_ctx
, si
);
410 if (smb_dr_decode_finish(dec_ctx
) != 0) {
411 smb_share_door_clnt_exit(arg
, B_FALSE
, "decode");
412 return (NERR_InternalError
);
415 smb_share_door_clnt_exit(arg
, B_FALSE
, NULL
);
420 smb_share_modify(smb_share_t
*si
)
423 smb_dr_ctx_t
*dec_ctx
;
424 smb_dr_ctx_t
*enc_ctx
;
427 if ((arg
= smb_share_door_clnt_enter()) == NULL
)
428 return (NERR_InternalError
);
430 enc_ctx
= smb_dr_encode_start(arg
->data_ptr
, SMB_SHARE_DSIZE
);
431 smb_dr_put_uint32(enc_ctx
, SMB_SHROP_MODIFY
);
432 smb_dr_put_share(enc_ctx
, si
);
434 rc
= smb_dr_encode_finish(enc_ctx
, (unsigned int *)&arg
->data_size
);
436 smb_share_door_clnt_exit(arg
, B_FALSE
, "encode");
437 return (NERR_InternalError
);
440 if (smb_share_door_call(smb_share_dfd
, arg
) < 0) {
441 smb_share_door_clnt_exit(arg
, B_TRUE
, "door call");
442 return (NERR_InternalError
);
445 dec_ctx
= smb_dr_decode_start(arg
->data_ptr
, arg
->data_size
);
446 if (smb_share_dchk(dec_ctx
) != 0) {
447 (void) smb_dr_decode_finish(dec_ctx
);
448 smb_share_door_clnt_exit(arg
, B_FALSE
, "decode");
449 return (NERR_InternalError
);
452 rc
= smb_dr_get_uint32(dec_ctx
);
453 if (smb_dr_decode_finish(dec_ctx
) != 0) {
454 smb_share_door_clnt_exit(arg
, B_FALSE
, "decode");
455 return (NERR_InternalError
);
458 smb_share_door_clnt_exit(arg
, B_FALSE
, NULL
);