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
);
555 smbd_user_nonauth_logon(sid
);
556 return (SMB_DOP_SUCCESS
);
560 smbd_dop_user_auth_logoff(smbd_arg_t
*arg
)
564 if (smb_common_decode(arg
->data
, arg
->datalen
,
565 xdr_uint32_t
, &sid
) != 0)
566 return (SMB_DOP_DECODE_ERROR
);
568 smbd_user_auth_logoff(sid
);
569 return (SMB_DOP_SUCCESS
);
573 * Obtains an access token on successful user authentication.
576 smbd_dop_user_auth_logon(smbd_arg_t
*arg
)
578 _NOTE(ARGUNUSED(arg
))
581 return (SMB_DOP_EMPTYBUF
);
585 smbd_dop_lookup_name(smbd_arg_t
*arg
)
590 char buf
[MAXNAMELEN
];
592 bzero(&acct
, sizeof (lsa_account_t
));
594 if (smb_common_decode(arg
->data
, arg
->datalen
,
595 lsa_account_xdr
, &acct
) != 0)
596 return (SMB_DOP_DECODE_ERROR
);
598 if (*acct
.a_domain
== '\0')
599 (void) snprintf(buf
, MAXNAMELEN
, "%s", acct
.a_name
);
600 else if (strchr(acct
.a_domain
, '.') != NULL
)
601 (void) snprintf(buf
, MAXNAMELEN
, "%s@%s", acct
.a_name
,
604 (void) snprintf(buf
, MAXNAMELEN
, "%s\\%s", acct
.a_domain
,
607 acct
.a_status
= lsa_lookup_name(buf
, acct
.a_sidtype
, &ainfo
);
608 if (acct
.a_status
== NT_STATUS_SUCCESS
) {
609 acct
.a_sidtype
= ainfo
.a_type
;
610 smb_sid_tostr(ainfo
.a_sid
, acct
.a_sid
);
611 (void) strlcpy(acct
.a_name
, ainfo
.a_name
, MAXNAMELEN
);
613 if (smb_domain_lookup_name(ainfo
.a_domain
, &dinfo
))
614 (void) strlcpy(acct
.a_domain
, dinfo
.di_fqname
,
617 (void) strlcpy(acct
.a_domain
, ainfo
.a_domain
,
619 smb_account_free(&ainfo
);
622 arg
->rbuf
= smb_common_encode(&acct
, lsa_account_xdr
, &arg
->rsize
);
624 if (arg
->rbuf
== NULL
)
625 return (SMB_DOP_ENCODE_ERROR
);
626 return (SMB_DOP_SUCCESS
);
630 smbd_dop_lookup_sid(smbd_arg_t
*arg
)
637 bzero(&acct
, sizeof (lsa_account_t
));
639 if (smb_common_decode(arg
->data
, arg
->datalen
,
640 lsa_account_xdr
, &acct
) != 0)
641 return (SMB_DOP_DECODE_ERROR
);
643 sid
= smb_sid_fromstr(acct
.a_sid
);
644 acct
.a_status
= lsa_lookup_sid(sid
, &ainfo
);
647 if (acct
.a_status
== NT_STATUS_SUCCESS
) {
648 acct
.a_sidtype
= ainfo
.a_type
;
649 smb_sid_tostr(ainfo
.a_sid
, acct
.a_sid
);
650 (void) strlcpy(acct
.a_name
, ainfo
.a_name
, MAXNAMELEN
);
652 if (smb_domain_lookup_name(ainfo
.a_domain
, &dinfo
))
653 (void) strlcpy(acct
.a_domain
, dinfo
.di_fqname
,
656 (void) strlcpy(acct
.a_domain
, ainfo
.a_domain
,
659 smb_account_free(&ainfo
);
662 arg
->rbuf
= smb_common_encode(&acct
, lsa_account_xdr
, &arg
->rsize
);
664 if (arg
->rbuf
== NULL
)
665 return (SMB_DOP_ENCODE_ERROR
);
666 return (SMB_DOP_SUCCESS
);
670 smbd_dop_join(smbd_arg_t
*arg
)
675 bzero(&jdi
, sizeof (smb_joininfo_t
));
676 bzero(&jdres
, sizeof (smb_joinres_t
));
678 if (smb_common_decode(arg
->data
, arg
->datalen
,
679 smb_joininfo_xdr
, &jdi
) != 0)
680 return (SMB_DOP_DECODE_ERROR
);
682 smbd_join(&jdi
, &jdres
);
684 arg
->rbuf
= smb_common_encode(&jdres
, smb_joinres_xdr
, &arg
->rsize
);
686 if (arg
->rbuf
== NULL
)
687 return (SMB_DOP_ENCODE_ERROR
);
688 return (SMB_DOP_SUCCESS
);
692 smbd_dop_get_dcinfo(smbd_arg_t
*arg
)
696 if (!smb_domain_getinfo(&dxi
))
697 return (SMB_DOP_EMPTYBUF
);
699 arg
->rbuf
= smb_string_encode(dxi
.d_dci
.dc_name
, &arg
->rsize
);
701 if (arg
->rbuf
== NULL
)
702 return (SMB_DOP_ENCODE_ERROR
);
703 return (SMB_DOP_SUCCESS
);
707 * Return the number of snapshots for a dataset
710 smbd_dop_vss_get_count(smbd_arg_t
*arg
)
715 bzero(&path
, sizeof (smb_string_t
));
718 if (smb_string_decode(&path
, arg
->data
, arg
->datalen
) != 0)
719 return (SMB_DOP_DECODE_ERROR
);
721 if (smbd_vss_get_count(path
.buf
, &count
) == 0)
722 arg
->rbuf
= smb_common_encode(&count
, xdr_uint32_t
,
725 xdr_free(smb_string_xdr
, (char *)&path
);
727 if (arg
->rbuf
== NULL
)
728 return (SMB_DOP_ENCODE_ERROR
);
729 return (SMB_DOP_SUCCESS
);
733 * Return the count and list of snapshots.
734 * The list is in @GMT token format.
737 smbd_dop_vss_get_snapshots(smbd_arg_t
*arg
)
740 smb_gmttoken_query_t request
;
741 smb_gmttoken_response_t reply
;
744 bzero(&request
, sizeof (smb_gmttoken_query_t
));
745 bzero(&reply
, sizeof (smb_gmttoken_response_t
));
747 if (smb_common_decode(arg
->data
, arg
->datalen
,
748 smb_gmttoken_query_xdr
, &request
) != 0)
749 return (SMB_DOP_DECODE_ERROR
);
751 reply
.gtr_gmttokens
.gtr_gmttokens_val
= malloc(request
.gtq_count
*
753 bzero(reply
.gtr_gmttokens
.gtr_gmttokens_val
, request
.gtq_count
*
756 if (reply
.gtr_gmttokens
.gtr_gmttokens_val
== NULL
) {
757 xdr_free(smb_gmttoken_query_xdr
, (char *)&request
);
758 return (SMB_DOP_EMPTYBUF
);
761 smbd_vss_get_snapshots(request
.gtq_path
, request
.gtq_count
,
763 &reply
.gtr_gmttokens
.gtr_gmttokens_len
,
764 reply
.gtr_gmttokens
.gtr_gmttokens_val
);
766 arg
->rbuf
= smb_common_encode(&reply
, smb_gmttoken_response_xdr
,
768 if (arg
->rbuf
== NULL
) {
769 xdr_free(smb_gmttoken_query_xdr
, (char *)&request
);
770 return (SMB_DOP_ENCODE_ERROR
);
773 for (i
= 0, gmtp
= reply
.gtr_gmttokens
.gtr_gmttokens_val
;
774 (i
< request
.gtq_count
); i
++) {
779 free(reply
.gtr_gmttokens
.gtr_gmttokens_val
);
780 xdr_free(smb_gmttoken_query_xdr
, (char *)&request
);
781 return (SMB_DOP_SUCCESS
);
785 * Return the name of the snapshot that matches the dataset path
789 smbd_dop_vss_map_gmttoken(smbd_arg_t
*arg
)
792 smb_gmttoken_snapname_t request
;
794 bzero(&request
, sizeof (smb_gmttoken_snapname_t
));
796 if (smb_common_decode(arg
->data
, arg
->datalen
,
797 smb_gmttoken_snapname_xdr
, &request
) != 0) {
798 xdr_free(smb_gmttoken_snapname_xdr
, (char *)&request
);
799 return (SMB_DOP_DECODE_ERROR
);
802 if ((snapname
= malloc(MAXPATHLEN
)) == NULL
) {
803 xdr_free(smb_gmttoken_snapname_xdr
, (char *)&request
);
807 if ((smbd_vss_map_gmttoken(request
.gts_path
, request
.gts_gmttoken
,
808 request
.gts_toktime
, snapname
) != 0)) {
812 arg
->rbuf
= smb_string_encode(snapname
, &arg
->rsize
);
813 xdr_free(smb_gmttoken_snapname_xdr
, (char *)&request
);
816 if (arg
->rbuf
== NULL
)
817 return (SMB_DOP_ENCODE_ERROR
);
818 return (SMB_DOP_SUCCESS
);
822 smbd_dop_ads_find_host(smbd_arg_t
*arg
)
824 smb_ads_host_info_t
*hinfo
= NULL
;
828 bzero(&fqdn
, sizeof (smb_string_t
));
830 if (smb_string_decode(&fqdn
, arg
->data
, arg
->datalen
) != 0)
831 return (SMB_DOP_DECODE_ERROR
);
833 if ((hinfo
= smb_ads_find_host(fqdn
.buf
)) != NULL
)
834 hostname
= hinfo
->name
;
836 xdr_free(smb_string_xdr
, (char *)&fqdn
);
838 arg
->rbuf
= smb_string_encode(hostname
, &arg
->rsize
);
841 if (arg
->rbuf
== NULL
)
842 return (SMB_DOP_ENCODE_ERROR
);
843 return (SMB_DOP_SUCCESS
);
847 * Query the list of user/group quota entries for a given filesystem.
850 smbd_dop_quota_query(smbd_arg_t
*arg
)
852 smb_quota_query_t request
;
853 smb_quota_response_t reply
;
856 bzero(&request
, sizeof (smb_quota_query_t
));
857 bzero(&reply
, sizeof (smb_quota_response_t
));
859 if (smb_common_decode(arg
->data
, arg
->datalen
,
860 smb_quota_query_xdr
, &request
) != 0)
861 return (SMB_DOP_DECODE_ERROR
);
863 status
= smb_quota_query(&request
, &reply
);
864 reply
.qr_status
= status
;
866 arg
->rbuf
= smb_common_encode(&reply
, smb_quota_response_xdr
,
869 xdr_free(smb_quota_query_xdr
, (char *)&request
);
870 smb_quota_free(&reply
);
872 if (arg
->rbuf
== NULL
)
873 return (SMB_DOP_ENCODE_ERROR
);
874 return (SMB_DOP_SUCCESS
);
878 * Set a list of user/group quota entries for a given filesystem.
881 smbd_dop_quota_set(smbd_arg_t
*arg
)
883 smb_quota_set_t request
;
886 bzero(&request
, sizeof (smb_quota_set_t
));
888 if (smb_common_decode(arg
->data
, arg
->datalen
,
889 smb_quota_set_xdr
, &request
) != 0)
890 return (SMB_DOP_DECODE_ERROR
);
892 status
= smb_quota_set(&request
);
894 arg
->rbuf
= smb_common_encode(&status
, xdr_uint32_t
, &arg
->rsize
);
895 xdr_free(smb_quota_set_xdr
, (char *)&request
);
897 if (arg
->rbuf
== NULL
)
898 return (SMB_DOP_ENCODE_ERROR
);
899 return (SMB_DOP_SUCCESS
);
903 smbd_dop_dfs_get_referrals(smbd_arg_t
*arg
)
905 dfs_referral_query_t request
;
906 dfs_referral_response_t reply
;
908 bzero(&request
, sizeof (request
));
909 bzero(&reply
, sizeof (reply
));
911 if (smb_common_decode(arg
->data
, arg
->datalen
,
912 dfs_referral_query_xdr
, &request
) != 0)
913 return (SMB_DOP_DECODE_ERROR
);
915 reply
.rp_status
= dfs_get_referrals((const char *)request
.rq_path
,
916 request
.rq_type
, &reply
.rp_referrals
);
918 if (reply
.rp_status
!= ERROR_SUCCESS
)
919 bzero(&reply
.rp_referrals
, sizeof (dfs_info_t
));
921 arg
->rbuf
= smb_common_encode(&reply
, dfs_referral_response_xdr
,
924 if (reply
.rp_status
== ERROR_SUCCESS
)
925 dfs_info_free(&reply
.rp_referrals
);
927 xdr_free(dfs_referral_query_xdr
, (char *)&request
);
929 if (arg
->rbuf
== NULL
)
930 return (SMB_DOP_ENCODE_ERROR
);
931 return (SMB_DOP_SUCCESS
);
935 smbd_dop_shr_hostaccess(smbd_arg_t
*arg
)
937 smb_shr_hostaccess_query_t request
;
940 bzero(&request
, sizeof (request
));
941 bzero(&reply
, sizeof (reply
));
943 if (smb_common_decode(arg
->data
, arg
->datalen
,
944 smb_shr_hostaccess_query_xdr
, &request
) != 0)
945 return (SMB_DOP_DECODE_ERROR
);
947 reply
= smb_shr_hostaccess(&request
.shq_ipaddr
, request
.shq_none
,
948 request
.shq_ro
, request
.shq_rw
, request
.shq_flag
);
950 arg
->rbuf
= smb_common_encode(&reply
, xdr_uint32_t
, &arg
->rsize
);
952 xdr_free(smb_shr_hostaccess_query_xdr
, (char *)&request
);
954 if (arg
->rbuf
== NULL
)
955 return (SMB_DOP_ENCODE_ERROR
);
956 return (SMB_DOP_SUCCESS
);
960 smbd_dop_shr_exec(smbd_arg_t
*arg
)
962 smb_shr_execinfo_t request
;
965 bzero(&request
, sizeof (request
));
966 bzero(&reply
, sizeof (reply
));
968 if (smb_common_decode(arg
->data
, arg
->datalen
,
969 smb_shr_execinfo_xdr
, &request
) != 0)
970 return (SMB_DOP_DECODE_ERROR
);
972 reply
= smb_shr_exec(&request
);
975 syslog(LOG_NOTICE
, "Failed to execute %s command",
976 (request
.e_type
== SMB_EXEC_MAP
) ? "map" : "unmap");
978 arg
->rbuf
= smb_common_encode(&reply
, xdr_int
, &arg
->rsize
);
980 xdr_free(smb_shr_execinfo_xdr
, (char *)&request
);
982 if (arg
->rbuf
== NULL
)
983 return (SMB_DOP_ENCODE_ERROR
);
984 return (SMB_DOP_SUCCESS
);
989 smbd_dop_notify_dc_changed(smbd_arg_t
*arg
)
992 smbd_dc_monitor_refresh();
994 return (SMB_DOP_SUCCESS
);