/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#include <assert.h>
#include <alloca.h>
#include <door.h>
#include <errno.h>
#include <syslog.h>
#include <unistd.h>
#include <stdio.h>
#include <synch.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <pthread.h>
#include <strings.h>
#include <note.h>
#include <smbsrv/smb_door.h>
#include <smbsrv/smb_token.h>
#include <smbsrv/libmlsvc.h>
#include <smbsrv/libsmbns.h>
#include "smbd.h"
/*
* The list contains asynchronous requests that have been initiated
* but have not yet been collected (via smbd_dop_async_response).
*/
typedef struct smbd_doorsvc {
static int smbd_dop_null(smbd_arg_t *);
static int smbd_dop_async_response(smbd_arg_t *);
static int smbd_dop_user_auth_logon(smbd_arg_t *);
static int smbd_dop_user_nonauth_logon(smbd_arg_t *);
static int smbd_dop_user_auth_logoff(smbd_arg_t *);
static int smbd_dop_lookup_sid(smbd_arg_t *);
static int smbd_dop_lookup_name(smbd_arg_t *);
static int smbd_dop_join(smbd_arg_t *);
static int smbd_dop_get_dcinfo(smbd_arg_t *);
static int smbd_dop_vss_get_count(smbd_arg_t *);
static int smbd_dop_vss_get_snapshots(smbd_arg_t *);
static int smbd_dop_vss_map_gmttoken(smbd_arg_t *);
static int smbd_dop_ads_find_host(smbd_arg_t *);
static int smbd_dop_quota_query(smbd_arg_t *);
static int smbd_dop_quota_set(smbd_arg_t *);
static int smbd_dop_dfs_get_referrals(smbd_arg_t *);
static int smbd_dop_shr_hostaccess(smbd_arg_t *);
static int smbd_dop_shr_exec(smbd_arg_t *);
static int smbd_dop_notify_dc_changed(smbd_arg_t *);
typedef struct smbd_doorop {
{ SMB_DR_NULL, smbd_dop_null },
{ SMB_DR_JOIN, smbd_dop_join },
};
static int smbd_door_dispatch_async(smbd_arg_t *);
static void smbd_door_release_async(smbd_arg_t *);
/*
* Start the smbd door service. Create and bind to a door.
* Returns 0 on success. Otherwise, -1.
*/
int
smbd_door_start(void)
{
int newfd;
if (smbd_door_fd != -1) {
return (-1);
}
if (smbd_door_name == NULL)
&smbd_door_cookie, DOOR_UNREF)) < 0) {
smbd_door_fd = -1;
return (-1);
}
(void) unlink(smbd_door_name);
(void) door_revoke(smbd_door_fd);
smbd_door_fd = -1;
return (-1);
}
(void) fdetach(smbd_door_name);
(void) door_revoke(smbd_door_fd);
smbd_door_fd = -1;
return (-1);
}
return (smbd_door_fd);
}
/*
* Stop the smbd door service.
*/
void
smbd_door_stop(void)
{
if (smbd_door_name)
(void) fdetach(smbd_door_name);
if (smbd_door_fd != -1) {
(void) door_revoke(smbd_door_fd);
smbd_door_fd = -1;
}
}
/*ARGSUSED*/
static void
{
if (!smbd_online())
}
}
}
/*
* ASYNC_RESPONSE is used to collect the response
* to an async call; it cannot be an async call.
*/
}
if (smbd_door_dispatch_async(&dop_arg) == 0)
else
} else {
(void) smbd_door_dispatch_op(&dop_arg);
}
}
}
/*NOTREACHED*/
}
/*
* Launch a thread to process an asynchronous door call.
*/
static int
{
int rc;
return (-1);
}
return (-1);
}
return (-1);
}
}
(void) pthread_attr_init(&attr);
(void) pthread_attr_destroy(&attr);
if (rc != 0) {
}
return (rc);
}
/*
* Remove an entry from the async response pending list and free
* the arg and associated data.
*
* Must only be called while holding the smbd_doorsvc mutex.
*/
static void
{
}
}
/*
* All door calls are processed here: synchronous or asynchronous:
* - synchronous calls are invoked by direct function call
* - asynchronous calls are invoked from a launched thread
*
* If the kernel has attempted to collect a response before the op
* has completed, the arg will have been marked as response_abort
* and we can discard the response data and release the arg.
*
* We send a notification when asynchronous (ASYNC) door calls
* from the kernel (SYSSPACE) have completed.
*/
void *
{
int i;
return (NULL);
for (i = 0; i < smbd_ndoorop; ++i) {
doorop = &smbd_doorops[i];
if (arg->response_abort) {
} else {
}
}
return (NULL);
}
}
return (NULL);
}
/*
* Wrapper for door_return. smbd_door_enter() increments a reference count
* when a door call is dispatched and smbd_door_return() decrements the
* reference count when it completes.
*
* The reference counting is used in smbd_door_fini() to wait for active
* calls to complete before closing the door.
*/
void
{
}
void
{
}
/*
* We have two calls to door_return because the first call (with data)
* can fail, which can leave the door call blocked here. The second
* call (with NULL) is guaranteed to unblock and return to the caller.
*/
void
{
else
/* NOTREACHED */
}
/*
* A door service is about to terminate.
* Give active requests a small grace period to complete.
*/
void
{
int rc = 0;
}
}
/*
* Null door operation: always returns success.
* Assumes no request or response data.
*/
/*ARGSUSED*/
static int
{
return (SMB_DOP_SUCCESS);
}
/*
* Async response handler: setup the rbuf and rsize for the specified
* transaction. This function is used by the kernel to collect the
* response half of an asynchronous door call.
*
* If a door client attempts to collect a response before the op has
* completed (!response_ready), mark the arg as response_abort and
* set an error. The response will be discarded when the op completes.
*/
static int
{
if (!arg->response_ready) {
break;
}
break;
}
}
return (SMB_DOP_SUCCESS);
}
static int
{
xdr_uint32_t, &sid) != 0)
return (SMB_DOP_DECODE_ERROR);
return (SMB_DOP_SUCCESS);
}
static int
{
xdr_uint32_t, &sid) != 0)
return (SMB_DOP_DECODE_ERROR);
return (SMB_DOP_SUCCESS);
}
/*
* Obtains an access token on successful user authentication.
*/
static int
{
/* No longer used */
return (SMB_DOP_EMPTYBUF);
}
static int
{
lsa_account_xdr, &acct) != 0)
return (SMB_DOP_DECODE_ERROR);
else
else
}
return (SMB_DOP_ENCODE_ERROR);
return (SMB_DOP_SUCCESS);
}
static int
{
lsa_account_xdr, &acct) != 0)
return (SMB_DOP_DECODE_ERROR);
else
}
return (SMB_DOP_ENCODE_ERROR);
return (SMB_DOP_SUCCESS);
}
static int
{
smb_joininfo_xdr, &jdi) != 0)
return (SMB_DOP_DECODE_ERROR);
return (SMB_DOP_ENCODE_ERROR);
return (SMB_DOP_SUCCESS);
}
static int
{
if (!smb_domain_getinfo(&dxi))
return (SMB_DOP_EMPTYBUF);
return (SMB_DOP_ENCODE_ERROR);
return (SMB_DOP_SUCCESS);
}
/*
* Return the number of snapshots for a dataset
*/
static int
{
return (SMB_DOP_DECODE_ERROR);
return (SMB_DOP_ENCODE_ERROR);
return (SMB_DOP_SUCCESS);
}
/*
* Return the count and list of snapshots.
* The list is in @GMT token format.
*/
static int
{
char **gmtp;
uint_t i;
smb_gmttoken_query_xdr, &request) != 0)
return (SMB_DOP_DECODE_ERROR);
sizeof (char *));
sizeof (char *));
return (SMB_DOP_EMPTYBUF);
}
return (SMB_DOP_ENCODE_ERROR);
}
if (*gmtp)
gmtp++;
}
return (SMB_DOP_SUCCESS);
}
/*
* Return the name of the snapshot that matches the dataset path
* and @GMT token.
*/
static int
{
char *snapname;
smb_gmttoken_snapname_xdr, &request) != 0) {
return (SMB_DOP_DECODE_ERROR);
}
return (NULL);
}
*snapname = '\0';
}
return (SMB_DOP_ENCODE_ERROR);
return (SMB_DOP_SUCCESS);
}
static int
{
return (SMB_DOP_DECODE_ERROR);
return (SMB_DOP_ENCODE_ERROR);
return (SMB_DOP_SUCCESS);
}
/*
*/
static int
{
smb_quota_query_xdr, &request) != 0)
return (SMB_DOP_DECODE_ERROR);
return (SMB_DOP_ENCODE_ERROR);
return (SMB_DOP_SUCCESS);
}
/*
*/
static int
{
smb_quota_set_xdr, &request) != 0)
return (SMB_DOP_DECODE_ERROR);
return (SMB_DOP_ENCODE_ERROR);
return (SMB_DOP_SUCCESS);
}
static int
{
dfs_referral_query_xdr, &request) != 0)
return (SMB_DOP_DECODE_ERROR);
return (SMB_DOP_ENCODE_ERROR);
return (SMB_DOP_SUCCESS);
}
static int
{
smb_shr_hostaccess_query_xdr, &request) != 0)
return (SMB_DOP_DECODE_ERROR);
return (SMB_DOP_ENCODE_ERROR);
return (SMB_DOP_SUCCESS);
}
static int
{
int reply;
smb_shr_execinfo_xdr, &request) != 0)
return (SMB_DOP_DECODE_ERROR);
if (reply != 0)
return (SMB_DOP_ENCODE_ERROR);
return (SMB_DOP_SUCCESS);
}
/* ARGSUSED */
static int
{
return (SMB_DOP_SUCCESS);
}