smb_share_doorclnt.c revision 7f667e74610492ddbce8ce60f52ece95d2401949
849N/A/*
849N/A * CDDL HEADER START
849N/A *
849N/A * The contents of this file are subject to the terms of the
849N/A * Common Development and Distribution License (the "License").
849N/A * You may not use this file except in compliance with the License.
849N/A *
849N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
849N/A * or http://www.opensolaris.org/os/licensing.
849N/A * See the License for the specific language governing permissions
849N/A * and limitations under the License.
849N/A *
849N/A * When distributing Covered Code, include this CDDL HEADER in each
849N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
849N/A * If applicable, add the following below this CDDL HEADER, with the
849N/A * fields enclosed by brackets "[]" replaced with your own identifying
849N/A * information: Portions Copyright [yyyy] [name of copyright owner]
849N/A *
873N/A * CDDL HEADER END
849N/A */
849N/A
849N/A/*
849N/A * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
849N/A * Use is subject to license terms.
3232N/A */
5827N/A
849N/A/*
849N/A * User-space door client for LanMan share management.
849N/A */
849N/A
849N/A#include <syslog.h>
3853N/A#include <door.h>
3853N/A#include <fcntl.h>
849N/A#include <stdarg.h>
849N/A#include <errno.h>
849N/A#include <string.h>
849N/A#include <strings.h>
849N/A#include <unistd.h>
1008N/A#include <thread.h>
3853N/A#include <synch.h>
3853N/A
849N/A#include <smbsrv/libsmb.h>
849N/A#include <smbsrv/smb_share.h>
849N/A#include <smbsrv/lmerr.h>
849N/A#include <smbsrv/cifs.h>
849N/A
849N/A#define SMB_SHARE_DOOR_CALL_RETRIES 3
3853N/A
849N/Astatic int smb_share_dfd = -1;
3853N/Astatic uint64_t smb_share_dncall = 0;
849N/Astatic mutex_t smb_share_dmtx;
849N/Astatic cond_t smb_share_dcv;
849N/A
849N/Astatic int smb_share_door_clnt_open(void);
849N/Astatic void smb_share_door_clnt_close(void);
849N/A
3853N/Avoid
3853N/Asmb_share_door_clnt_init(void)
3853N/A{
849N/A (void) mutex_lock(&smb_share_dmtx);
849N/A (void) smb_share_door_clnt_open();
849N/A (void) mutex_unlock(&smb_share_dmtx);
849N/A}
849N/A
849N/Avoid
849N/Asmb_share_door_clnt_fini(void)
849N/A{
849N/A (void) mutex_lock(&smb_share_dmtx);
849N/A smb_share_door_clnt_close();
849N/A (void) mutex_unlock(&smb_share_dmtx);
849N/A}
849N/A
849N/A/*
849N/A * Open smb_share_door. This is a private call for use by
849N/A * smb_share_door_clnt_enter() and must be called with smb_share_dmtx held.
849N/A *
849N/A * Returns the door fd on success. Otherwise, -1.
849N/A */
849N/Astatic int
849N/Asmb_share_door_clnt_open(void)
849N/A{
849N/A if (smb_share_dfd == -1) {
849N/A if ((smb_share_dfd = open(SMB_SHARE_DNAME, O_RDONLY)) < 0)
849N/A smb_share_dfd = -1;
849N/A else
849N/A smb_share_dncall = 0;
849N/A }
849N/A
849N/A return (smb_share_dfd);
849N/A}
849N/A
849N/A/*
849N/A * Close smb_share_door.
849N/A * Private call that must be called with smb_share_dmtx held.
849N/A */
849N/Astatic void
849N/Asmb_share_door_clnt_close(void)
849N/A{
849N/A if (smb_share_dfd != -1) {
849N/A while (smb_share_dncall > 0)
2624N/A (void) cond_wait(&smb_share_dcv, &smb_share_dmtx);
849N/A
2624N/A if (smb_share_dfd != -1) {
849N/A (void) close(smb_share_dfd);
849N/A smb_share_dfd = -1;
849N/A }
849N/A }
849N/A}
849N/A
849N/A/*
2624N/A * Entry handler for smb_share_door calls.
849N/A */
2624N/Astatic door_arg_t *
2624N/Asmb_share_door_clnt_enter(void)
849N/A{
849N/A door_arg_t *arg;
849N/A char *buf;
849N/A
849N/A (void) mutex_lock(&smb_share_dmtx);
849N/A
849N/A if (smb_share_door_clnt_open() == -1) {
2624N/A (void) mutex_unlock(&smb_share_dmtx);
849N/A return (NULL);
2624N/A }
2624N/A
849N/A if ((arg = malloc(sizeof (door_arg_t) + SMB_SHARE_DSIZE)) != NULL) {
849N/A buf = ((char *)arg) + sizeof (door_arg_t);
849N/A bzero(arg, sizeof (door_arg_t));
849N/A arg->data_ptr = buf;
849N/A arg->rbuf = buf;
849N/A arg->rsize = SMB_SHARE_DSIZE;
849N/A
2624N/A ++smb_share_dncall;
849N/A }
2624N/A
2624N/A (void) mutex_unlock(&smb_share_dmtx);
849N/A return (arg);
849N/A}
849N/A
849N/A/*
849N/A * Exit handler for smb_share_door calls.
849N/A */
849N/Astatic void
2624N/Asmb_share_door_clnt_exit(door_arg_t *arg, boolean_t must_close, char *errmsg)
849N/A{
2624N/A if (errmsg)
2624N/A syslog(LOG_DEBUG, "smb_share_door: %s failed", errmsg);
849N/A
849N/A (void) mutex_lock(&smb_share_dmtx);
849N/A free(arg);
849N/A --smb_share_dncall;
849N/A (void) cond_signal(&smb_share_dcv);
849N/A
849N/A if (must_close)
2624N/A smb_share_door_clnt_close();
849N/A
2624N/A (void) mutex_unlock(&smb_share_dmtx);
2624N/A}
2624N/A
849N/Astatic int
849N/Asmb_share_door_call(int fd, door_arg_t *arg)
849N/A{
849N/A int rc;
849N/A int i;
849N/A
849N/A for (i = 0; i < SMB_SHARE_DOOR_CALL_RETRIES; ++i) {
2624N/A errno = 0;
849N/A
2624N/A if ((rc = door_call(fd, arg)) == 0)
2624N/A break;
2624N/A
849N/A if (errno != EAGAIN && errno != EINTR)
849N/A break;
849N/A }
849N/A
849N/A return (rc);
849N/A}
849N/A
2624N/Astatic int
849N/Asmb_share_dchk(smb_dr_ctx_t *dec_ctx)
2624N/A{
2624N/A int status = smb_dr_get_int32(dec_ctx);
2624N/A
849N/A if (status != SMB_SHARE_DSUCCESS) {
849N/A if (status == SMB_SHARE_DERROR)
849N/A (void) smb_dr_get_uint32(dec_ctx);
849N/A return (-1);
849N/A }
849N/A
849N/A return (0);
849N/A}
849N/A
849N/Auint32_t
849N/Asmb_share_list(int offset, smb_shrlist_t *list)
849N/A{
849N/A door_arg_t *arg;
849N/A smb_dr_ctx_t *dec_ctx;
849N/A smb_dr_ctx_t *enc_ctx;
849N/A uint32_t rc;
849N/A
849N/A bzero(list, sizeof (smb_shrlist_t));
849N/A
849N/A if ((arg = smb_share_door_clnt_enter()) == NULL)
849N/A return (NERR_InternalError);
849N/A
849N/A enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
849N/A smb_dr_put_uint32(enc_ctx, SMB_SHROP_LIST);
849N/A smb_dr_put_int32(enc_ctx, offset);
849N/A
849N/A rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
1008N/A if (rc != 0) {
1008N/A smb_share_door_clnt_exit(arg, B_FALSE, "encode");
1008N/A return (NERR_InternalError);
1008N/A }
849N/A
849N/A if (smb_share_door_call(smb_share_dfd, arg) < 0) {
849N/A smb_share_door_clnt_exit(arg, B_TRUE, "door call");
1008N/A return (NERR_InternalError);
849N/A }
849N/A
849N/A dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
849N/A if (smb_share_dchk(dec_ctx) != 0) {
849N/A (void) smb_dr_decode_finish(dec_ctx);
849N/A smb_share_door_clnt_exit(arg, B_FALSE, "decode");
849N/A return (NERR_InternalError);
849N/A }
849N/A
849N/A (void) smb_dr_get_buf(dec_ctx, (unsigned char *)list,
849N/A sizeof (smb_shrlist_t));
849N/A if (smb_dr_decode_finish(dec_ctx) != 0) {
849N/A smb_share_door_clnt_exit(arg, B_FALSE, "decode");
849N/A return (NERR_InternalError);
849N/A }
849N/A
849N/A smb_share_door_clnt_exit(arg, B_FALSE, NULL);
849N/A return (NERR_Success);
849N/A}
849N/A
849N/Aint
849N/Asmb_share_count(void)
849N/A{
849N/A door_arg_t *arg;
849N/A smb_dr_ctx_t *dec_ctx;
849N/A smb_dr_ctx_t *enc_ctx;
849N/A uint32_t num_shares;
849N/A int rc;
849N/A
849N/A if ((arg = smb_share_door_clnt_enter()) == NULL)
849N/A return (-1);
849N/A
3824N/A enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
849N/A smb_dr_put_uint32(enc_ctx, SMB_SHROP_NUM_SHARES);
3824N/A
849N/A rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
849N/A if (rc != 0) {
849N/A smb_share_door_clnt_exit(arg, B_FALSE, "encode");
849N/A return (-1);
3634N/A }
849N/A
849N/A if (smb_share_door_call(smb_share_dfd, arg) < 0) {
849N/A smb_share_door_clnt_exit(arg, B_TRUE, "door call");
849N/A return (-1);
849N/A }
849N/A
849N/A dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
849N/A if (smb_share_dchk(dec_ctx) != 0) {
849N/A (void) smb_dr_decode_finish(dec_ctx);
849N/A smb_share_door_clnt_exit(arg, B_FALSE, "decode");
849N/A return (-1);
849N/A }
849N/A
849N/A num_shares = smb_dr_get_uint32(dec_ctx);
849N/A if (smb_dr_decode_finish(dec_ctx) != 0) {
849N/A smb_share_door_clnt_exit(arg, B_FALSE, "decode");
849N/A return (-1);
849N/A }
849N/A
849N/A smb_share_door_clnt_exit(arg, B_FALSE, NULL);
849N/A return (num_shares);
849N/A}
849N/A
849N/Auint32_t
849N/Asmb_share_delete(char *share_name)
849N/A{
849N/A door_arg_t *arg;
849N/A smb_dr_ctx_t *dec_ctx;
849N/A smb_dr_ctx_t *enc_ctx;
849N/A uint32_t rc;
849N/A
849N/A if ((arg = smb_share_door_clnt_enter()) == NULL)
849N/A return (NERR_InternalError);
849N/A
849N/A enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
849N/A smb_dr_put_uint32(enc_ctx, SMB_SHROP_DELETE);
849N/A smb_dr_put_string(enc_ctx, share_name);
849N/A
849N/A rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
849N/A if (rc != 0) {
849N/A smb_share_door_clnt_exit(arg, B_FALSE, "encode");
849N/A return (NERR_InternalError);
849N/A }
849N/A
849N/A if (smb_share_door_call(smb_share_dfd, arg) < 0) {
849N/A smb_share_door_clnt_exit(arg, B_TRUE, "door call");
849N/A return (NERR_InternalError);
849N/A }
849N/A
849N/A dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
849N/A if (smb_share_dchk(dec_ctx) != 0) {
849N/A (void) smb_dr_decode_finish(dec_ctx);
849N/A smb_share_door_clnt_exit(arg, B_FALSE, "decode");
3824N/A return (NERR_InternalError);
849N/A }
3824N/A
849N/A rc = smb_dr_get_uint32(dec_ctx);
849N/A if (smb_dr_decode_finish(dec_ctx) != 0) {
849N/A smb_share_door_clnt_exit(arg, B_FALSE, "decode");
849N/A return (NERR_InternalError);
3634N/A }
849N/A
849N/A smb_share_door_clnt_exit(arg, B_FALSE, NULL);
849N/A return (rc);
849N/A
849N/A}
849N/A
849N/Auint32_t
849N/Asmb_share_rename(char *from, char *to)
849N/A{
849N/A door_arg_t *arg;
849N/A smb_dr_ctx_t *dec_ctx;
849N/A smb_dr_ctx_t *enc_ctx;
849N/A uint32_t rc;
849N/A
849N/A if ((arg = smb_share_door_clnt_enter()) == NULL)
849N/A return (NERR_InternalError);
849N/A
849N/A enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
849N/A smb_dr_put_uint32(enc_ctx, SMB_SHROP_RENAME);
849N/A smb_dr_put_string(enc_ctx, from);
849N/A smb_dr_put_string(enc_ctx, to);
849N/A
849N/A rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
849N/A if (rc != 0) {
849N/A smb_share_door_clnt_exit(arg, B_FALSE, "encode");
849N/A return (NERR_InternalError);
849N/A }
849N/A
849N/A if (smb_share_door_call(smb_share_dfd, arg) < 0) {
849N/A smb_share_door_clnt_exit(arg, B_TRUE, "door call");
849N/A return (NERR_InternalError);
849N/A }
849N/A
849N/A dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
849N/A if (smb_share_dchk(dec_ctx) != 0) {
849N/A (void) smb_dr_decode_finish(dec_ctx);
849N/A smb_share_door_clnt_exit(arg, B_FALSE, "decode");
849N/A return (NERR_InternalError);
849N/A }
849N/A
849N/A rc = smb_dr_get_uint32(dec_ctx);
849N/A if (smb_dr_decode_finish(dec_ctx) != 0) {
849N/A smb_share_door_clnt_exit(arg, B_FALSE, "decode");
849N/A return (NERR_InternalError);
849N/A }
849N/A
849N/A smb_share_door_clnt_exit(arg, B_FALSE, NULL);
849N/A return (rc);
849N/A}
849N/A
849N/Auint32_t
849N/Asmb_share_create(smb_share_t *si)
849N/A{
849N/A door_arg_t *arg;
3824N/A smb_dr_ctx_t *dec_ctx;
849N/A smb_dr_ctx_t *enc_ctx;
3824N/A uint32_t rc;
849N/A
849N/A if ((arg = smb_share_door_clnt_enter()) == NULL)
849N/A return (NERR_InternalError);
849N/A
3634N/A enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
849N/A smb_dr_put_uint32(enc_ctx, SMB_SHROP_ADD);
849N/A smb_dr_put_share(enc_ctx, si);
849N/A
849N/A rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
849N/A if (rc != 0) {
849N/A smb_share_door_clnt_exit(arg, B_FALSE, "encode");
849N/A return (NERR_InternalError);
849N/A }
849N/A
849N/A if (smb_share_door_call(smb_share_dfd, arg) < 0) {
849N/A smb_share_door_clnt_exit(arg, B_TRUE, "door call");
849N/A return (NERR_InternalError);
849N/A }
849N/A
849N/A dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
849N/A if (smb_share_dchk(dec_ctx) != 0) {
849N/A (void) smb_dr_decode_finish(dec_ctx);
849N/A smb_share_door_clnt_exit(arg, B_FALSE, "decode");
849N/A return (NERR_InternalError);
849N/A }
849N/A
849N/A rc = smb_dr_get_uint32(dec_ctx);
849N/A smb_dr_get_share(dec_ctx, si);
849N/A if (smb_dr_decode_finish(dec_ctx) != 0) {
849N/A smb_share_door_clnt_exit(arg, B_FALSE, "decode");
849N/A return (NERR_InternalError);
849N/A }
849N/A
849N/A smb_share_door_clnt_exit(arg, B_FALSE, NULL);
849N/A return (rc);
849N/A}
849N/A
849N/Auint32_t
849N/Asmb_share_modify(smb_share_t *si)
849N/A{
849N/A door_arg_t *arg;
849N/A smb_dr_ctx_t *dec_ctx;
849N/A smb_dr_ctx_t *enc_ctx;
849N/A uint32_t rc;
849N/A
849N/A if ((arg = smb_share_door_clnt_enter()) == NULL)
849N/A return (NERR_InternalError);
849N/A
849N/A enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
849N/A smb_dr_put_uint32(enc_ctx, SMB_SHROP_MODIFY);
849N/A smb_dr_put_share(enc_ctx, si);
849N/A
849N/A rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
849N/A if (rc != 0) {
849N/A smb_share_door_clnt_exit(arg, B_FALSE, "encode");
849N/A return (NERR_InternalError);
3824N/A }
849N/A
3824N/A if (smb_share_door_call(smb_share_dfd, arg) < 0) {
849N/A smb_share_door_clnt_exit(arg, B_TRUE, "door call");
849N/A return (NERR_InternalError);
849N/A }
849N/A
3634N/A dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
849N/A if (smb_share_dchk(dec_ctx) != 0) {
849N/A (void) smb_dr_decode_finish(dec_ctx);
849N/A smb_share_door_clnt_exit(arg, B_FALSE, "decode");
849N/A return (NERR_InternalError);
849N/A }
849N/A
849N/A rc = smb_dr_get_uint32(dec_ctx);
849N/A if (smb_dr_decode_finish(dec_ctx) != 0) {
849N/A smb_share_door_clnt_exit(arg, B_FALSE, "decode");
849N/A return (NERR_InternalError);
849N/A }
849N/A
849N/A smb_share_door_clnt_exit(arg, B_FALSE, NULL);
849N/A return (rc);
849N/A}
849N/A