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]
22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
42 #include <smbsrv/smb_door.h>
43 #include <smbsrv/smb_xdr.h>
44 #include <smbsrv/smb_token.h>
45 #include <smbsrv/libmlsvc.h>
46 #include <smbsrv/libsmbns.h>
50 * The list contains asynchronous requests that have been initiated
51 * but have not yet been collected (via smbd_dop_async_response).
53 typedef struct smbd_doorsvc
{
57 uint32_t sd_async_count
;
60 static int smbd_dop_null(smbd_arg_t
*);
61 static int smbd_dop_async_response(smbd_arg_t
*);
62 static int smbd_dop_user_auth_logon(smbd_arg_t
*);
63 static int smbd_dop_user_nonauth_logon(smbd_arg_t
*);
64 static int smbd_dop_user_auth_logoff(smbd_arg_t
*);
65 static int smbd_dop_lookup_sid(smbd_arg_t
*);
66 static int smbd_dop_lookup_name(smbd_arg_t
*);
67 static int smbd_dop_join(smbd_arg_t
*);
68 static int smbd_dop_get_dcinfo(smbd_arg_t
*);
69 static int smbd_dop_vss_get_count(smbd_arg_t
*);
70 static int smbd_dop_vss_get_snapshots(smbd_arg_t
*);
71 static int smbd_dop_vss_map_gmttoken(smbd_arg_t
*);
72 static int smbd_dop_ads_find_host(smbd_arg_t
*);
73 static int smbd_dop_quota_query(smbd_arg_t
*);
74 static int smbd_dop_quota_set(smbd_arg_t
*);
75 static int smbd_dop_dfs_get_referrals(smbd_arg_t
*);
76 static int smbd_dop_shr_hostaccess(smbd_arg_t
*);
77 static int smbd_dop_shr_exec(smbd_arg_t
*);
78 static int smbd_dop_notify_dc_changed(smbd_arg_t
*);
80 typedef int (*smbd_dop_t
)(smbd_arg_t
*);
82 typedef struct smbd_doorop
{
87 smbd_doorop_t smbd_doorops
[] = {
88 { SMB_DR_NULL
, smbd_dop_null
},
89 { SMB_DR_ASYNC_RESPONSE
, smbd_dop_async_response
},
90 { SMB_DR_USER_AUTH_LOGON
, smbd_dop_user_auth_logon
},
91 { SMB_DR_USER_NONAUTH_LOGON
, smbd_dop_user_nonauth_logon
},
92 { SMB_DR_USER_AUTH_LOGOFF
, smbd_dop_user_auth_logoff
},
93 { SMB_DR_LOOKUP_SID
, smbd_dop_lookup_sid
},
94 { SMB_DR_LOOKUP_NAME
, smbd_dop_lookup_name
},
95 { SMB_DR_JOIN
, smbd_dop_join
},
96 { SMB_DR_GET_DCINFO
, smbd_dop_get_dcinfo
},
97 { SMB_DR_VSS_GET_COUNT
, smbd_dop_vss_get_count
},
98 { SMB_DR_VSS_GET_SNAPSHOTS
, smbd_dop_vss_get_snapshots
},
99 { SMB_DR_VSS_MAP_GMTTOKEN
, smbd_dop_vss_map_gmttoken
},
100 { SMB_DR_ADS_FIND_HOST
, smbd_dop_ads_find_host
},
101 { SMB_DR_QUOTA_QUERY
, smbd_dop_quota_query
},
102 { SMB_DR_QUOTA_SET
, smbd_dop_quota_set
},
103 { SMB_DR_DFS_GET_REFERRALS
, smbd_dop_dfs_get_referrals
},
104 { SMB_DR_SHR_HOSTACCESS
, smbd_dop_shr_hostaccess
},
105 { SMB_DR_SHR_EXEC
, smbd_dop_shr_exec
},
106 { SMB_DR_NOTIFY_DC_CHANGED
, smbd_dop_notify_dc_changed
}
109 static int smbd_ndoorop
= (sizeof (smbd_doorops
) / sizeof (smbd_doorops
[0]));
111 static smbd_doorsvc_t smbd_doorsvc
;
112 static int smbd_door_fd
= -1;
113 static int smbd_door_cookie
= 0x534D4244; /* SMBD */
114 static smbd_door_t smbd_door_sdh
;
115 static char *smbd_door_name
= NULL
;
117 static void smbd_door_dispatch(void *, char *, size_t, door_desc_t
*, uint_t
);
118 static int smbd_door_dispatch_async(smbd_arg_t
*);
119 static void smbd_door_release_async(smbd_arg_t
*);
122 * Start the smbd door service. Create and bind to a door.
123 * Returns 0 on success. Otherwise, -1.
126 smbd_door_start(void)
130 (void) mutex_lock(&smbd_doorsvc
.sd_mutex
);
132 if (smbd_door_fd
!= -1) {
133 (void) fprintf(stderr
, "smb_doorsrv_start: already started");
134 (void) mutex_unlock(&smbd_doorsvc
.sd_mutex
);
138 smbd_door_name
= getenv("SMBD_DOOR_NAME");
139 if (smbd_door_name
== NULL
)
140 smbd_door_name
= SMBD_DOOR_NAME
;
142 smbd_door_init(&smbd_door_sdh
, "doorsrv");
144 list_create(&smbd_doorsvc
.sd_async_list
, sizeof (smbd_arg_t
),
145 offsetof(smbd_arg_t
, lnd
));
146 smbd_doorsvc
.sd_async_count
= 0;
148 if ((smbd_door_fd
= door_create(smbd_door_dispatch
,
149 &smbd_door_cookie
, DOOR_UNREF
)) < 0) {
150 (void) fprintf(stderr
, "smb_doorsrv_start: door_create: %s",
153 (void) mutex_unlock(&smbd_doorsvc
.sd_mutex
);
157 (void) unlink(smbd_door_name
);
159 if ((newfd
= creat(smbd_door_name
, 0644)) < 0) {
160 (void) fprintf(stderr
, "smb_doorsrv_start: open: %s",
162 (void) door_revoke(smbd_door_fd
);
164 (void) mutex_unlock(&smbd_doorsvc
.sd_mutex
);
169 (void) fdetach(smbd_door_name
);
171 if (fattach(smbd_door_fd
, smbd_door_name
) < 0) {
172 (void) fprintf(stderr
, "smb_doorsrv_start: fattach: %s",
174 (void) door_revoke(smbd_door_fd
);
176 (void) mutex_unlock(&smbd_doorsvc
.sd_mutex
);
180 (void) mutex_unlock(&smbd_doorsvc
.sd_mutex
);
181 return (smbd_door_fd
);
185 * Stop the smbd door service.
190 (void) mutex_lock(&smbd_doorsvc
.sd_mutex
);
192 smbd_door_fini(&smbd_door_sdh
);
195 (void) fdetach(smbd_door_name
);
197 if (smbd_door_fd
!= -1) {
198 (void) door_revoke(smbd_door_fd
);
202 (void) mutex_unlock(&smbd_doorsvc
.sd_mutex
);
207 smbd_door_dispatch(void *cookie
, char *argp
, size_t arg_size
, door_desc_t
*dp
,
215 smbd_door_enter(&smbd_door_sdh
);
218 smbd_door_return(&smbd_door_sdh
, NULL
, 0, NULL
, 0);
220 bzero(&dop_arg
, sizeof (smbd_arg_t
));
222 hdr_size
= xdr_sizeof(smb_doorhdr_xdr
, hdr
);
224 if ((cookie
!= &smbd_door_cookie
) || (argp
== NULL
) ||
225 (arg_size
< hdr_size
)) {
226 smbd_door_return(&smbd_door_sdh
, NULL
, 0, NULL
, 0);
229 if (smb_doorhdr_decode(hdr
, (uint8_t *)argp
, hdr_size
) == -1) {
230 syslog(LOG_DEBUG
, "smbd_door_dispatch: header decode failed");
231 smbd_door_return(&smbd_door_sdh
, NULL
, 0, NULL
, 0);
234 if ((hdr
->dh_magic
!= SMB_DOOR_HDR_MAGIC
) || (hdr
->dh_txid
== 0)) {
235 syslog(LOG_DEBUG
, "smbd_door_dispatch: invalid header");
236 smbd_door_return(&smbd_door_sdh
, NULL
, 0, NULL
, 0);
239 dop_arg
.opname
= smb_doorhdr_opname(hdr
->dh_op
);
240 dop_arg
.data
= argp
+ hdr_size
;
241 dop_arg
.datalen
= hdr
->dh_datalen
;
243 if (hdr
->dh_op
== SMB_DR_ASYNC_RESPONSE
) {
245 * ASYNC_RESPONSE is used to collect the response
246 * to an async call; it cannot be an async call.
248 hdr
->dh_flags
&= ~SMB_DF_ASYNC
;
251 if (hdr
->dh_flags
& SMB_DF_ASYNC
) {
252 if (smbd_door_dispatch_async(&dop_arg
) == 0)
253 hdr
->dh_door_rc
= SMB_DOP_SUCCESS
;
255 hdr
->dh_door_rc
= SMB_DOP_NOT_CALLED
;
257 (void) smbd_door_dispatch_op(&dop_arg
);
260 if ((rbuf
= (char *)alloca(dop_arg
.rsize
+ hdr_size
)) == NULL
) {
262 syslog(LOG_DEBUG
, "smbd_door_dispatch[%s]: alloca %m",
264 smbd_door_return(&smbd_door_sdh
, NULL
, 0, NULL
, 0);
267 if (dop_arg
.rbuf
!= NULL
) {
268 (void) memcpy(rbuf
+ hdr_size
, dop_arg
.rbuf
, dop_arg
.rsize
);
272 hdr
->dh_datalen
= dop_arg
.rsize
;
273 (void) smb_doorhdr_encode(hdr
, (uint8_t *)rbuf
, hdr_size
);
274 dop_arg
.rsize
+= hdr_size
;
276 smbd_door_return(&smbd_door_sdh
, rbuf
, dop_arg
.rsize
, NULL
, 0);
281 * Launch a thread to process an asynchronous door call.
284 smbd_door_dispatch_async(smbd_arg_t
*req_arg
)
286 smbd_arg_t
*arg
= NULL
;
292 if ((req_arg
->hdr
.dh_flags
& SMB_DF_ASYNC
) == 0) {
297 if ((arg
= malloc(sizeof (smbd_arg_t
))) == NULL
) {
298 syslog(LOG_DEBUG
, "smbd_door_dispatch_async[%s]: %m",
303 (void) memcpy(arg
, req_arg
, sizeof (smbd_arg_t
));
306 if (req_arg
->datalen
!= 0) {
307 if ((data
= malloc(req_arg
->datalen
)) == NULL
) {
309 syslog(LOG_DEBUG
, "smbd_door_dispatch_async[%s]: %m",
314 (void) memcpy(data
, req_arg
->data
, req_arg
->datalen
);
318 (void) mutex_lock(&smbd_doorsvc
.sd_mutex
);
319 arg
->magic
= SMBD_ARG_MAGIC
;
320 list_insert_tail(&smbd_doorsvc
.sd_async_list
, arg
);
321 ++smbd_doorsvc
.sd_async_count
;
322 (void) mutex_unlock(&smbd_doorsvc
.sd_mutex
);
324 (void) pthread_attr_init(&attr
);
325 (void) pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
326 rc
= pthread_create(&tid
, &attr
, smbd_door_dispatch_op
, arg
);
327 (void) pthread_attr_destroy(&attr
);
330 (void) mutex_lock(&smbd_doorsvc
.sd_mutex
);
331 smbd_door_release_async(arg
);
332 (void) mutex_unlock(&smbd_doorsvc
.sd_mutex
);
339 * Remove an entry from the async response pending list and free
340 * the arg and associated data.
342 * Must only be called while holding the smbd_doorsvc mutex.
345 smbd_door_release_async(smbd_arg_t
*arg
)
348 assert(arg
->magic
== SMBD_ARG_MAGIC
);
349 arg
->magic
= (uint32_t)~SMBD_ARG_MAGIC
;
351 list_remove(&smbd_doorsvc
.sd_async_list
, arg
);
352 --smbd_doorsvc
.sd_async_count
;
360 * All door calls are processed here: synchronous or asynchronous:
361 * - synchronous calls are invoked by direct function call
362 * - asynchronous calls are invoked from a launched thread
364 * If the kernel has attempted to collect a response before the op
365 * has completed, the arg will have been marked as response_abort
366 * and we can discard the response data and release the arg.
368 * We send a notification when asynchronous (ASYNC) door calls
369 * from the kernel (SYSSPACE) have completed.
372 smbd_door_dispatch_op(void *thread_arg
)
374 smbd_arg_t
*arg
= (smbd_arg_t
*)thread_arg
;
375 smbd_doorop_t
*doorop
;
379 if ((!smbd_online()) || arg
== NULL
)
383 arg
->opname
= smb_doorhdr_opname(hdr
->dh_op
);
385 for (i
= 0; i
< smbd_ndoorop
; ++i
) {
386 doorop
= &smbd_doorops
[i
];
388 if (hdr
->dh_op
== doorop
->opcode
) {
389 hdr
->dh_door_rc
= doorop
->op(arg
);
390 hdr
->dh_status
= arg
->status
;
392 if ((hdr
->dh_flags
& SMB_DF_SYSSPACE
) &&
393 (hdr
->dh_flags
& SMB_DF_ASYNC
)) {
394 assert(hdr
->dh_op
!= SMB_DR_ASYNC_RESPONSE
);
396 (void) mutex_lock(&smbd_doorsvc
.sd_mutex
);
397 if (arg
->response_abort
) {
400 smbd_door_release_async(arg
);
402 arg
->response_ready
= B_TRUE
;
404 (void) mutex_unlock(&smbd_doorsvc
.sd_mutex
);
406 (void) smb_kmod_event_notify(hdr
->dh_txid
);
413 syslog(LOG_ERR
, "smbd_door_dispatch_op[%s]: invalid op %u",
414 arg
->opname
, hdr
->dh_op
);
419 * Wrapper for door_return. smbd_door_enter() increments a reference count
420 * when a door call is dispatched and smbd_door_return() decrements the
421 * reference count when it completes.
423 * The reference counting is used in smbd_door_fini() to wait for active
424 * calls to complete before closing the door.
427 smbd_door_init(smbd_door_t
*sdh
, const char *name
)
429 (void) strlcpy(sdh
->sd_name
, name
, sizeof (sdh
->sd_name
));
433 smbd_door_enter(smbd_door_t
*sdh
)
435 (void) mutex_lock(&sdh
->sd_mutex
);
437 (void) mutex_unlock(&sdh
->sd_mutex
);
441 * We have two calls to door_return because the first call (with data)
442 * can fail, which can leave the door call blocked here. The second
443 * call (with NULL) is guaranteed to unblock and return to the caller.
446 smbd_door_return(smbd_door_t
*sdh
, char *data_ptr
, size_t data_size
,
447 door_desc_t
*desc_ptr
, uint_t num_desc
)
449 (void) mutex_lock(&sdh
->sd_mutex
);
451 if (sdh
->sd_ncalls
== 0)
452 syslog(LOG_ERR
, "smbd_door_return[%s]: unexpected count=0",
457 (void) cond_broadcast(&sdh
->sd_cv
);
458 (void) mutex_unlock(&sdh
->sd_mutex
);
460 (void) door_return(data_ptr
, data_size
, desc_ptr
, num_desc
);
461 (void) door_return(NULL
, 0, NULL
, 0);
466 * A door service is about to terminate.
467 * Give active requests a small grace period to complete.
470 smbd_door_fini(smbd_door_t
*sdh
)
475 (void) mutex_lock(&sdh
->sd_mutex
);
477 while (rc
!= ETIME
&& sdh
->sd_ncalls
!= 0) {
480 rc
= cond_reltimedwait(&sdh
->sd_cv
, &sdh
->sd_mutex
, &delay
);
483 if (sdh
->sd_ncalls
!= 0)
484 syslog(LOG_NOTICE
, "smbd_door_fini[%s]: %d remaining",
485 sdh
->sd_name
, sdh
->sd_ncalls
);
487 (void) mutex_unlock(&sdh
->sd_mutex
);
491 * Null door operation: always returns success.
492 * Assumes no request or response data.
496 smbd_dop_null(smbd_arg_t
*arg
)
498 return (SMB_DOP_SUCCESS
);
502 * Async response handler: setup the rbuf and rsize for the specified
503 * transaction. This function is used by the kernel to collect the
504 * response half of an asynchronous door call.
506 * If a door client attempts to collect a response before the op has
507 * completed (!response_ready), mark the arg as response_abort and
508 * set an error. The response will be discarded when the op completes.
511 smbd_dop_async_response(smbd_arg_t
*rsp_arg
)
513 list_t
*arg_list
= &smbd_doorsvc
.sd_async_list
;
516 (void) mutex_lock(&smbd_doorsvc
.sd_mutex
);
517 arg
= list_head(arg_list
);
519 while (arg
!= NULL
) {
520 assert(arg
->magic
== SMBD_ARG_MAGIC
);
522 if (arg
->hdr
.dh_txid
== rsp_arg
->hdr
.dh_txid
) {
523 if (!arg
->response_ready
) {
524 arg
->response_abort
= B_TRUE
;
525 rsp_arg
->hdr
.dh_door_rc
= SMB_DOP_NOT_CALLED
;
526 syslog(LOG_NOTICE
, "doorsvc[%s]: %u not ready",
527 arg
->opname
, arg
->hdr
.dh_txid
);
531 rsp_arg
->rbuf
= arg
->rbuf
;
532 rsp_arg
->rsize
= arg
->rsize
;
535 smbd_door_release_async(arg
);
539 arg
= list_next(arg_list
, arg
);
542 (void) mutex_unlock(&smbd_doorsvc
.sd_mutex
);
543 return (SMB_DOP_SUCCESS
);
547 smbd_dop_user_nonauth_logon(smbd_arg_t
*arg
)
551 if (smb_common_decode(arg
->data
, arg
->datalen
,
552 xdr_uint32_t
, &sid
) != 0)
553 return (SMB_DOP_DECODE_ERROR
);
554 return (SMB_DOP_SUCCESS
);
558 smbd_dop_user_auth_logoff(smbd_arg_t
*arg
)
562 if (smb_common_decode(arg
->data
, arg
->datalen
,
563 xdr_uint32_t
, &sid
) != 0)
564 return (SMB_DOP_DECODE_ERROR
);
565 return (SMB_DOP_SUCCESS
);
569 * Obtains an access token on successful user authentication.
572 smbd_dop_user_auth_logon(smbd_arg_t
*arg
)
574 _NOTE(ARGUNUSED(arg
))
577 return (SMB_DOP_EMPTYBUF
);
581 smbd_dop_lookup_name(smbd_arg_t
*arg
)
586 char buf
[MAXNAMELEN
];
588 bzero(&acct
, sizeof (lsa_account_t
));
590 if (smb_common_decode(arg
->data
, arg
->datalen
,
591 lsa_account_xdr
, &acct
) != 0)
592 return (SMB_DOP_DECODE_ERROR
);
594 if (*acct
.a_domain
== '\0')
595 (void) snprintf(buf
, MAXNAMELEN
, "%s", acct
.a_name
);
596 else if (strchr(acct
.a_domain
, '.') != NULL
)
597 (void) snprintf(buf
, MAXNAMELEN
, "%s@%s", acct
.a_name
,
600 (void) snprintf(buf
, MAXNAMELEN
, "%s\\%s", acct
.a_domain
,
603 acct
.a_status
= lsa_lookup_name(buf
, acct
.a_sidtype
, &ainfo
);
604 if (acct
.a_status
== NT_STATUS_SUCCESS
) {
605 acct
.a_sidtype
= ainfo
.a_type
;
606 smb_sid_tostr(ainfo
.a_sid
, acct
.a_sid
);
607 (void) strlcpy(acct
.a_name
, ainfo
.a_name
, MAXNAMELEN
);
609 if (smb_domain_lookup_name(ainfo
.a_domain
, &dinfo
))
610 (void) strlcpy(acct
.a_domain
, dinfo
.di_fqname
,
613 (void) strlcpy(acct
.a_domain
, ainfo
.a_domain
,
615 smb_account_free(&ainfo
);
618 arg
->rbuf
= smb_common_encode(&acct
, lsa_account_xdr
, &arg
->rsize
);
620 if (arg
->rbuf
== NULL
)
621 return (SMB_DOP_ENCODE_ERROR
);
622 return (SMB_DOP_SUCCESS
);
626 smbd_dop_lookup_sid(smbd_arg_t
*arg
)
633 bzero(&acct
, sizeof (lsa_account_t
));
635 if (smb_common_decode(arg
->data
, arg
->datalen
,
636 lsa_account_xdr
, &acct
) != 0)
637 return (SMB_DOP_DECODE_ERROR
);
639 sid
= smb_sid_fromstr(acct
.a_sid
);
640 acct
.a_status
= lsa_lookup_sid(sid
, &ainfo
);
643 if (acct
.a_status
== NT_STATUS_SUCCESS
) {
644 acct
.a_sidtype
= ainfo
.a_type
;
645 smb_sid_tostr(ainfo
.a_sid
, acct
.a_sid
);
646 (void) strlcpy(acct
.a_name
, ainfo
.a_name
, MAXNAMELEN
);
648 if (smb_domain_lookup_name(ainfo
.a_domain
, &dinfo
))
649 (void) strlcpy(acct
.a_domain
, dinfo
.di_fqname
,
652 (void) strlcpy(acct
.a_domain
, ainfo
.a_domain
,
655 smb_account_free(&ainfo
);
658 arg
->rbuf
= smb_common_encode(&acct
, lsa_account_xdr
, &arg
->rsize
);
660 if (arg
->rbuf
== NULL
)
661 return (SMB_DOP_ENCODE_ERROR
);
662 return (SMB_DOP_SUCCESS
);
666 smbd_dop_join(smbd_arg_t
*arg
)
671 bzero(&jdi
, sizeof (smb_joininfo_t
));
672 bzero(&jdres
, sizeof (smb_joinres_t
));
674 if (smb_common_decode(arg
->data
, arg
->datalen
,
675 smb_joininfo_xdr
, &jdi
) != 0)
676 return (SMB_DOP_DECODE_ERROR
);
678 smbd_join(&jdi
, &jdres
);
680 arg
->rbuf
= smb_common_encode(&jdres
, smb_joinres_xdr
, &arg
->rsize
);
682 if (arg
->rbuf
== NULL
)
683 return (SMB_DOP_ENCODE_ERROR
);
684 return (SMB_DOP_SUCCESS
);
688 smbd_dop_get_dcinfo(smbd_arg_t
*arg
)
692 if (!smb_domain_getinfo(&dxi
))
693 return (SMB_DOP_EMPTYBUF
);
695 arg
->rbuf
= smb_string_encode(dxi
.d_dci
.dc_name
, &arg
->rsize
);
697 if (arg
->rbuf
== NULL
)
698 return (SMB_DOP_ENCODE_ERROR
);
699 return (SMB_DOP_SUCCESS
);
703 * Return the number of snapshots for a dataset
706 smbd_dop_vss_get_count(smbd_arg_t
*arg
)
711 bzero(&path
, sizeof (smb_string_t
));
714 if (smb_string_decode(&path
, arg
->data
, arg
->datalen
) != 0)
715 return (SMB_DOP_DECODE_ERROR
);
717 if (smbd_vss_get_count(path
.buf
, &count
) == 0)
718 arg
->rbuf
= smb_common_encode(&count
, xdr_uint32_t
,
721 xdr_free(smb_string_xdr
, (char *)&path
);
723 if (arg
->rbuf
== NULL
)
724 return (SMB_DOP_ENCODE_ERROR
);
725 return (SMB_DOP_SUCCESS
);
729 * Return the count and list of snapshots.
730 * The list is in @GMT token format.
733 smbd_dop_vss_get_snapshots(smbd_arg_t
*arg
)
736 smb_gmttoken_query_t request
;
737 smb_gmttoken_response_t reply
;
740 bzero(&request
, sizeof (smb_gmttoken_query_t
));
741 bzero(&reply
, sizeof (smb_gmttoken_response_t
));
743 if (smb_common_decode(arg
->data
, arg
->datalen
,
744 smb_gmttoken_query_xdr
, &request
) != 0)
745 return (SMB_DOP_DECODE_ERROR
);
747 reply
.gtr_gmttokens
.gtr_gmttokens_val
= malloc(request
.gtq_count
*
749 bzero(reply
.gtr_gmttokens
.gtr_gmttokens_val
, request
.gtq_count
*
752 if (reply
.gtr_gmttokens
.gtr_gmttokens_val
== NULL
) {
753 xdr_free(smb_gmttoken_query_xdr
, (char *)&request
);
754 return (SMB_DOP_EMPTYBUF
);
757 smbd_vss_get_snapshots(request
.gtq_path
, request
.gtq_count
,
759 &reply
.gtr_gmttokens
.gtr_gmttokens_len
,
760 reply
.gtr_gmttokens
.gtr_gmttokens_val
);
762 arg
->rbuf
= smb_common_encode(&reply
, smb_gmttoken_response_xdr
,
764 if (arg
->rbuf
== NULL
) {
765 xdr_free(smb_gmttoken_query_xdr
, (char *)&request
);
766 return (SMB_DOP_ENCODE_ERROR
);
769 for (i
= 0, gmtp
= reply
.gtr_gmttokens
.gtr_gmttokens_val
;
770 (i
< request
.gtq_count
); i
++) {
775 free(reply
.gtr_gmttokens
.gtr_gmttokens_val
);
776 xdr_free(smb_gmttoken_query_xdr
, (char *)&request
);
777 return (SMB_DOP_SUCCESS
);
781 * Return the name of the snapshot that matches the dataset path
785 smbd_dop_vss_map_gmttoken(smbd_arg_t
*arg
)
788 smb_gmttoken_snapname_t request
;
790 bzero(&request
, sizeof (smb_gmttoken_snapname_t
));
792 if (smb_common_decode(arg
->data
, arg
->datalen
,
793 smb_gmttoken_snapname_xdr
, &request
) != 0) {
794 xdr_free(smb_gmttoken_snapname_xdr
, (char *)&request
);
795 return (SMB_DOP_DECODE_ERROR
);
798 if ((snapname
= malloc(MAXPATHLEN
)) == NULL
) {
799 xdr_free(smb_gmttoken_snapname_xdr
, (char *)&request
);
803 if ((smbd_vss_map_gmttoken(request
.gts_path
, request
.gts_gmttoken
,
804 request
.gts_toktime
, snapname
) != 0)) {
808 arg
->rbuf
= smb_string_encode(snapname
, &arg
->rsize
);
809 xdr_free(smb_gmttoken_snapname_xdr
, (char *)&request
);
812 if (arg
->rbuf
== NULL
)
813 return (SMB_DOP_ENCODE_ERROR
);
814 return (SMB_DOP_SUCCESS
);
818 smbd_dop_ads_find_host(smbd_arg_t
*arg
)
820 smb_ads_host_info_t
*hinfo
= NULL
;
824 bzero(&fqdn
, sizeof (smb_string_t
));
826 if (smb_string_decode(&fqdn
, arg
->data
, arg
->datalen
) != 0)
827 return (SMB_DOP_DECODE_ERROR
);
829 if ((hinfo
= smb_ads_find_host(fqdn
.buf
)) != NULL
)
830 hostname
= hinfo
->name
;
832 xdr_free(smb_string_xdr
, (char *)&fqdn
);
834 arg
->rbuf
= smb_string_encode(hostname
, &arg
->rsize
);
837 if (arg
->rbuf
== NULL
)
838 return (SMB_DOP_ENCODE_ERROR
);
839 return (SMB_DOP_SUCCESS
);
843 * Query the list of user/group quota entries for a given filesystem.
846 smbd_dop_quota_query(smbd_arg_t
*arg
)
848 smb_quota_query_t request
;
849 smb_quota_response_t reply
;
852 bzero(&request
, sizeof (smb_quota_query_t
));
853 bzero(&reply
, sizeof (smb_quota_response_t
));
855 if (smb_common_decode(arg
->data
, arg
->datalen
,
856 smb_quota_query_xdr
, &request
) != 0)
857 return (SMB_DOP_DECODE_ERROR
);
859 status
= smb_quota_query(&request
, &reply
);
860 reply
.qr_status
= status
;
862 arg
->rbuf
= smb_common_encode(&reply
, smb_quota_response_xdr
,
865 xdr_free(smb_quota_query_xdr
, (char *)&request
);
866 smb_quota_free(&reply
);
868 if (arg
->rbuf
== NULL
)
869 return (SMB_DOP_ENCODE_ERROR
);
870 return (SMB_DOP_SUCCESS
);
874 * Set a list of user/group quota entries for a given filesystem.
877 smbd_dop_quota_set(smbd_arg_t
*arg
)
879 smb_quota_set_t request
;
882 bzero(&request
, sizeof (smb_quota_set_t
));
884 if (smb_common_decode(arg
->data
, arg
->datalen
,
885 smb_quota_set_xdr
, &request
) != 0)
886 return (SMB_DOP_DECODE_ERROR
);
888 status
= smb_quota_set(&request
);
890 arg
->rbuf
= smb_common_encode(&status
, xdr_uint32_t
, &arg
->rsize
);
891 xdr_free(smb_quota_set_xdr
, (char *)&request
);
893 if (arg
->rbuf
== NULL
)
894 return (SMB_DOP_ENCODE_ERROR
);
895 return (SMB_DOP_SUCCESS
);
899 smbd_dop_dfs_get_referrals(smbd_arg_t
*arg
)
901 dfs_referral_query_t request
;
902 dfs_referral_response_t reply
;
904 bzero(&request
, sizeof (request
));
905 bzero(&reply
, sizeof (reply
));
907 if (smb_common_decode(arg
->data
, arg
->datalen
,
908 dfs_referral_query_xdr
, &request
) != 0)
909 return (SMB_DOP_DECODE_ERROR
);
911 reply
.rp_status
= dfs_get_referrals((const char *)request
.rq_path
,
912 request
.rq_type
, &reply
.rp_referrals
);
914 if (reply
.rp_status
!= ERROR_SUCCESS
)
915 bzero(&reply
.rp_referrals
, sizeof (dfs_info_t
));
917 arg
->rbuf
= smb_common_encode(&reply
, dfs_referral_response_xdr
,
920 if (reply
.rp_status
== ERROR_SUCCESS
)
921 dfs_info_free(&reply
.rp_referrals
);
923 xdr_free(dfs_referral_query_xdr
, (char *)&request
);
925 if (arg
->rbuf
== NULL
)
926 return (SMB_DOP_ENCODE_ERROR
);
927 return (SMB_DOP_SUCCESS
);
931 smbd_dop_shr_hostaccess(smbd_arg_t
*arg
)
933 smb_shr_hostaccess_query_t request
;
936 bzero(&request
, sizeof (request
));
937 bzero(&reply
, sizeof (reply
));
939 if (smb_common_decode(arg
->data
, arg
->datalen
,
940 smb_shr_hostaccess_query_xdr
, &request
) != 0)
941 return (SMB_DOP_DECODE_ERROR
);
943 reply
= smb_shr_hostaccess(&request
.shq_ipaddr
, request
.shq_none
,
944 request
.shq_ro
, request
.shq_rw
, request
.shq_flag
);
946 arg
->rbuf
= smb_common_encode(&reply
, xdr_uint32_t
, &arg
->rsize
);
948 xdr_free(smb_shr_hostaccess_query_xdr
, (char *)&request
);
950 if (arg
->rbuf
== NULL
)
951 return (SMB_DOP_ENCODE_ERROR
);
952 return (SMB_DOP_SUCCESS
);
956 smbd_dop_shr_exec(smbd_arg_t
*arg
)
958 smb_shr_execinfo_t request
;
961 bzero(&request
, sizeof (request
));
962 bzero(&reply
, sizeof (reply
));
964 if (smb_common_decode(arg
->data
, arg
->datalen
,
965 smb_shr_execinfo_xdr
, &request
) != 0)
966 return (SMB_DOP_DECODE_ERROR
);
968 reply
= smb_shr_exec(&request
);
971 syslog(LOG_NOTICE
, "Failed to execute %s command",
972 (request
.e_type
== SMB_EXEC_MAP
) ? "map" : "unmap");
974 arg
->rbuf
= smb_common_encode(&reply
, xdr_int
, &arg
->rsize
);
976 xdr_free(smb_shr_execinfo_xdr
, (char *)&request
);
978 if (arg
->rbuf
== NULL
)
979 return (SMB_DOP_ENCODE_ERROR
);
980 return (SMB_DOP_SUCCESS
);
985 smbd_dop_notify_dc_changed(smbd_arg_t
*arg
)
988 smbd_dc_monitor_refresh();
990 return (SMB_DOP_SUCCESS
);