smb_opipe.c revision 8b2cc8ac894f2d58f38cf2fb7c3ac778f4c57c09
3db3f65c6274eb042354801a308c8e9bc4994553amw/*
3db3f65c6274eb042354801a308c8e9bc4994553amw * CDDL HEADER START
3db3f65c6274eb042354801a308c8e9bc4994553amw *
3db3f65c6274eb042354801a308c8e9bc4994553amw * The contents of this file are subject to the terms of the
3db3f65c6274eb042354801a308c8e9bc4994553amw * Common Development and Distribution License (the "License").
3db3f65c6274eb042354801a308c8e9bc4994553amw * You may not use this file except in compliance with the License.
3db3f65c6274eb042354801a308c8e9bc4994553amw *
3db3f65c6274eb042354801a308c8e9bc4994553amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
3db3f65c6274eb042354801a308c8e9bc4994553amw * or http://www.opensolaris.org/os/licensing.
3db3f65c6274eb042354801a308c8e9bc4994553amw * See the License for the specific language governing permissions
3db3f65c6274eb042354801a308c8e9bc4994553amw * and limitations under the License.
3db3f65c6274eb042354801a308c8e9bc4994553amw *
3db3f65c6274eb042354801a308c8e9bc4994553amw * When distributing Covered Code, include this CDDL HEADER in each
3db3f65c6274eb042354801a308c8e9bc4994553amw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
3db3f65c6274eb042354801a308c8e9bc4994553amw * If applicable, add the following below this CDDL HEADER, with the
3db3f65c6274eb042354801a308c8e9bc4994553amw * fields enclosed by brackets "[]" replaced with your own identifying
3db3f65c6274eb042354801a308c8e9bc4994553amw * information: Portions Copyright [yyyy] [name of copyright owner]
3db3f65c6274eb042354801a308c8e9bc4994553amw *
3db3f65c6274eb042354801a308c8e9bc4994553amw * CDDL HEADER END
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amw/*
8b2cc8ac894f2d58f38cf2fb7c3ac778f4c57c09afshin salek ardakani - Sun Microsystems - Irvine United States * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3db3f65c6274eb042354801a308c8e9bc4994553amw * Use is subject to license terms.
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw/*
3db3f65c6274eb042354801a308c8e9bc4994553amw * This module provides the interface to NDR RPC.
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw#include <sys/stat.h>
3db3f65c6274eb042354801a308c8e9bc4994553amw#include <sys/door.h>
3db3f65c6274eb042354801a308c8e9bc4994553amw#include <sys/door_data.h>
3db3f65c6274eb042354801a308c8e9bc4994553amw#include <sys/uio.h>
3db3f65c6274eb042354801a308c8e9bc4994553amw#include <sys/ksynch.h>
3db3f65c6274eb042354801a308c8e9bc4994553amw#include <smbsrv/smb_incl.h>
3db3f65c6274eb042354801a308c8e9bc4994553amw#include <smbsrv/smb_xdr.h>
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw#define SMB_OPIPE_ISOPEN(OPIPE) \
3db3f65c6274eb042354801a308c8e9bc4994553amw (((OPIPE)->p_hdr.oh_magic == SMB_OPIPE_HDR_MAGIC) && \
3db3f65c6274eb042354801a308c8e9bc4994553amw ((OPIPE)->p_hdr.oh_fid))
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amwextern volatile uint32_t smb_fids;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic int smb_opipe_do_open(smb_request_t *, smb_opipe_t *);
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic char *smb_opipe_lookup(const char *path);
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic uint32_t smb_opipe_fid(void);
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic int smb_opipe_set_hdr(smb_opipe_t *opipe, uint32_t, uint32_t);
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic void smb_opipe_enter(smb_opipe_t *);
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic void smb_opipe_exit(smb_opipe_t *);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic door_handle_t smb_opipe_door_hd = NULL;
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic int smb_opipe_door_id = -1;
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic uint64_t smb_opipe_door_ncall = 0;
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic kmutex_t smb_opipe_door_mutex;
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic kcondvar_t smb_opipe_door_cv;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic int smb_opipe_door_call(smb_opipe_t *);
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic int smb_opipe_door_upcall(smb_opipe_t *);
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic void smb_user_context_fini(smb_opipe_context_t *);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw/*
3db3f65c6274eb042354801a308c8e9bc4994553amw * smb_opipe_open
3db3f65c6274eb042354801a308c8e9bc4994553amw *
3db3f65c6274eb042354801a308c8e9bc4994553amw * Open a well-known RPC named pipe. This routine should be called if
3db3f65c6274eb042354801a308c8e9bc4994553amw * a file open is requested on a share of type STYPE_IPC.
3db3f65c6274eb042354801a308c8e9bc4994553amw * If we recognize the pipe, we setup a new ofile.
3db3f65c6274eb042354801a308c8e9bc4994553amw *
3db3f65c6274eb042354801a308c8e9bc4994553amw * Returns 0 on success, Otherwise an NT status is returned to indicate
3db3f65c6274eb042354801a308c8e9bc4994553amw * an error.
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amwint
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_opipe_open(smb_request_t *sr)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
8b2cc8ac894f2d58f38cf2fb7c3ac778f4c57c09afshin salek ardakani - Sun Microsystems - Irvine United States open_param_t *op = &sr->arg.open;
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_ofile_t *of;
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_t *opipe;
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_hdr_t hdr;
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_error_t err;
3db3f65c6274eb042354801a308c8e9bc4994553amw char *pipe_name;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if ((pipe_name = smb_opipe_lookup(op->fqi.path)) == NULL)
3db3f65c6274eb042354801a308c8e9bc4994553amw return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
3db3f65c6274eb042354801a308c8e9bc4994553amw
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego op->create_options = 0;
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego of = smb_ofile_open(sr->tid_tree, NULL, sr->smb_pid, op,
3db3f65c6274eb042354801a308c8e9bc4994553amw SMB_FTYPE_MESG_PIPE, SMB_UNIQ_FID(), &err);
8b2cc8ac894f2d58f38cf2fb7c3ac778f4c57c09afshin salek ardakani - Sun Microsystems - Irvine United States
3db3f65c6274eb042354801a308c8e9bc4994553amw if (of == NULL)
3db3f65c6274eb042354801a308c8e9bc4994553amw return (err.status);
3db3f65c6274eb042354801a308c8e9bc4994553amw
8b2cc8ac894f2d58f38cf2fb7c3ac778f4c57c09afshin salek ardakani - Sun Microsystems - Irvine United States if (!smb_tree_is_connected(sr->tid_tree)) {
8b2cc8ac894f2d58f38cf2fb7c3ac778f4c57c09afshin salek ardakani - Sun Microsystems - Irvine United States smb_ofile_close(of, 0);
8b2cc8ac894f2d58f38cf2fb7c3ac778f4c57c09afshin salek ardakani - Sun Microsystems - Irvine United States smb_ofile_release(of);
8b2cc8ac894f2d58f38cf2fb7c3ac778f4c57c09afshin salek ardakani - Sun Microsystems - Irvine United States return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
8b2cc8ac894f2d58f38cf2fb7c3ac778f4c57c09afshin salek ardakani - Sun Microsystems - Irvine United States }
8b2cc8ac894f2d58f38cf2fb7c3ac778f4c57c09afshin salek ardakani - Sun Microsystems - Irvine United States
3db3f65c6274eb042354801a308c8e9bc4994553amw op->dsize = 0x01000;
3db3f65c6274eb042354801a308c8e9bc4994553amw op->dattr = FILE_ATTRIBUTE_NORMAL;
3db3f65c6274eb042354801a308c8e9bc4994553amw op->ftype = SMB_FTYPE_MESG_PIPE;
3db3f65c6274eb042354801a308c8e9bc4994553amw op->action_taken = SMB_OACT_LOCK | SMB_OACT_OPENED; /* 0x8001 */
3db3f65c6274eb042354801a308c8e9bc4994553amw op->devstate = SMB_PIPE_READMODE_MESSAGE
3db3f65c6274eb042354801a308c8e9bc4994553amw | SMB_PIPE_TYPE_MESSAGE
3db3f65c6274eb042354801a308c8e9bc4994553amw | SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */
3db3f65c6274eb042354801a308c8e9bc4994553amw op->fileid = of->f_fid;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw sr->smb_fid = of->f_fid;
3db3f65c6274eb042354801a308c8e9bc4994553amw sr->fid_ofile = of;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw opipe = of->f_pipe;
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_init(&opipe->p_mutex, NULL, MUTEX_DEFAULT, NULL);
3db3f65c6274eb042354801a308c8e9bc4994553amw cv_init(&opipe->p_cv, NULL, CV_DEFAULT, NULL);
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_enter(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw opipe->p_name = pipe_name;
3db3f65c6274eb042354801a308c8e9bc4994553amw opipe->p_doorbuf = kmem_zalloc(SMB_OPIPE_DOOR_BUFSIZE, KM_SLEEP);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw /*
3db3f65c6274eb042354801a308c8e9bc4994553amw * p_data points to the offset within p_doorbuf at which
3db3f65c6274eb042354801a308c8e9bc4994553amw * data will be written or read.
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amw opipe->p_data = opipe->p_doorbuf + xdr_sizeof(smb_opipe_hdr_xdr, &hdr);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (smb_opipe_do_open(sr, opipe) != 0) {
3db3f65c6274eb042354801a308c8e9bc4994553amw /*
3db3f65c6274eb042354801a308c8e9bc4994553amw * On error, reset the header to clear the fid,
3db3f65c6274eb042354801a308c8e9bc4994553amw * which avoids confusion when smb_opipe_close() is
3db3f65c6274eb042354801a308c8e9bc4994553amw * called by smb_ofile_close().
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amw bzero(&opipe->p_hdr, sizeof (smb_opipe_hdr_t));
3db3f65c6274eb042354801a308c8e9bc4994553amw kmem_free(opipe->p_doorbuf, SMB_OPIPE_DOOR_BUFSIZE);
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_exit(opipe);
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego smb_ofile_close(of, 0);
3db3f65c6274eb042354801a308c8e9bc4994553amw return (NT_STATUS_NO_MEMORY);
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_exit(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw return (NT_STATUS_SUCCESS);
3db3f65c6274eb042354801a308c8e9bc4994553amw}
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw/*
3db3f65c6274eb042354801a308c8e9bc4994553amw * smb_opipe_lookup
3db3f65c6274eb042354801a308c8e9bc4994553amw *
3db3f65c6274eb042354801a308c8e9bc4994553amw * Lookup a path to see if it's a well-known RPC named pipe that we support.
3db3f65c6274eb042354801a308c8e9bc4994553amw * The full pipe path will be in the form \\PIPE\\SERVICE. The first part
3db3f65c6274eb042354801a308c8e9bc4994553amw * can be assumed, so all we need here are the service names.
3db3f65c6274eb042354801a308c8e9bc4994553amw *
3db3f65c6274eb042354801a308c8e9bc4994553amw * Returns a pointer to the pipe name (without any leading \'s) on sucess.
3db3f65c6274eb042354801a308c8e9bc4994553amw * Otherwise returns a null pointer.
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic char *
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_opipe_lookup(const char *path)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
3db3f65c6274eb042354801a308c8e9bc4994553amw static char *named_pipes[] = {
3db3f65c6274eb042354801a308c8e9bc4994553amw "LSARPC",
3db3f65c6274eb042354801a308c8e9bc4994553amw "NETLOGON",
3db3f65c6274eb042354801a308c8e9bc4994553amw "SAMR",
3db3f65c6274eb042354801a308c8e9bc4994553amw "SPOOLSS",
3db3f65c6274eb042354801a308c8e9bc4994553amw "SRVSVC",
3db3f65c6274eb042354801a308c8e9bc4994553amw "SVCCTL",
3db3f65c6274eb042354801a308c8e9bc4994553amw "WINREG",
3db3f65c6274eb042354801a308c8e9bc4994553amw "WKSSVC",
3db3f65c6274eb042354801a308c8e9bc4994553amw "EVENTLOG"
3db3f65c6274eb042354801a308c8e9bc4994553amw };
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw const char *name;
3db3f65c6274eb042354801a308c8e9bc4994553amw int i;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (path == NULL)
3db3f65c6274eb042354801a308c8e9bc4994553amw return (NULL);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw name = path;
3db3f65c6274eb042354801a308c8e9bc4994553amw name += strspn(name, "\\");
3db3f65c6274eb042354801a308c8e9bc4994553amw if (utf8_strncasecmp(name, "PIPE", 4) == 0) {
3db3f65c6274eb042354801a308c8e9bc4994553amw path += 4;
3db3f65c6274eb042354801a308c8e9bc4994553amw name += strspn(name, "\\");
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw for (i = 0; i < sizeof (named_pipes) / sizeof (named_pipes[0]); ++i) {
3db3f65c6274eb042354801a308c8e9bc4994553amw if (utf8_strcasecmp(name, named_pipes[i]) == 0)
3db3f65c6274eb042354801a308c8e9bc4994553amw return (named_pipes[i]);
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw return (NULL);
3db3f65c6274eb042354801a308c8e9bc4994553amw}
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw/*
3db3f65c6274eb042354801a308c8e9bc4994553amw * Initialize the opipe header and context, and make the door call.
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic int
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_opipe_do_open(smb_request_t *sr, smb_opipe_t *opipe)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_context_t *ctx = &opipe->p_context;
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_user_t *user = sr->uid_user;
3db3f65c6274eb042354801a308c8e9bc4994553amw uint8_t *buf = opipe->p_doorbuf;
3db3f65c6274eb042354801a308c8e9bc4994553amw uint32_t buflen = SMB_OPIPE_DOOR_BUFSIZE;
3db3f65c6274eb042354801a308c8e9bc4994553amw uint32_t len;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_user_context_init(user, ctx);
3db3f65c6274eb042354801a308c8e9bc4994553amw len = xdr_sizeof(smb_opipe_context_xdr, ctx);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw bzero(&opipe->p_hdr, sizeof (smb_opipe_hdr_t));
3db3f65c6274eb042354801a308c8e9bc4994553amw opipe->p_hdr.oh_magic = SMB_OPIPE_HDR_MAGIC;
3db3f65c6274eb042354801a308c8e9bc4994553amw opipe->p_hdr.oh_fid = smb_opipe_fid();
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (smb_opipe_set_hdr(opipe, SMB_OPIPE_OPEN, len) == -1)
3db3f65c6274eb042354801a308c8e9bc4994553amw return (-1);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw len = xdr_sizeof(smb_opipe_hdr_xdr, &opipe->p_hdr);
3db3f65c6274eb042354801a308c8e9bc4994553amw buf += len;
3db3f65c6274eb042354801a308c8e9bc4994553amw buflen -= len;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (smb_opipe_context_encode(ctx, buf, buflen) == -1)
3db3f65c6274eb042354801a308c8e9bc4994553amw return (-1);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw return (smb_opipe_door_call(opipe));
3db3f65c6274eb042354801a308c8e9bc4994553amw}
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw/*
3db3f65c6274eb042354801a308c8e9bc4994553amw * smb_opipe_fid
3db3f65c6274eb042354801a308c8e9bc4994553amw *
3db3f65c6274eb042354801a308c8e9bc4994553amw * The opipe_fid is an arbitrary id used to associate RPC requests
3db3f65c6274eb042354801a308c8e9bc4994553amw * with a binding handle. A new fid is returned on each call.
3db3f65c6274eb042354801a308c8e9bc4994553amw * 0 or -1 are not assigned: 0 is used to indicate an invalid fid
3db3f65c6274eb042354801a308c8e9bc4994553amw * and SMB sometimes uses -1 to indicate all open fid's.
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic uint32_t
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_opipe_fid(void)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
3db3f65c6274eb042354801a308c8e9bc4994553amw static uint32_t opipe_fid;
3db3f65c6274eb042354801a308c8e9bc4994553amw static kmutex_t smb_opipe_fid_mutex;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_enter(&smb_opipe_fid_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (opipe_fid == 0)
3db3f65c6274eb042354801a308c8e9bc4994553amw opipe_fid = lbolt << 11;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw do {
3db3f65c6274eb042354801a308c8e9bc4994553amw ++opipe_fid;
3db3f65c6274eb042354801a308c8e9bc4994553amw } while (opipe_fid == 0 || opipe_fid == (uint32_t)-1);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_exit(&smb_opipe_fid_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw return (opipe_fid);
3db3f65c6274eb042354801a308c8e9bc4994553amw}
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw/*
3db3f65c6274eb042354801a308c8e9bc4994553amw * smb_opipe_close
3db3f65c6274eb042354801a308c8e9bc4994553amw *
3db3f65c6274eb042354801a308c8e9bc4994553amw * Called whenever an IPC file/pipe is closed.
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amwvoid
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_opipe_close(smb_ofile_t *of)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_t *opipe;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw ASSERT(of);
3db3f65c6274eb042354801a308c8e9bc4994553amw ASSERT(of->f_ftype == SMB_FTYPE_MESG_PIPE);
3db3f65c6274eb042354801a308c8e9bc4994553amw ASSERT(of->f_pipe != NULL);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw opipe = of->f_pipe;
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_enter(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (SMB_OPIPE_ISOPEN(opipe)) {
3db3f65c6274eb042354801a308c8e9bc4994553amw (void) smb_opipe_set_hdr(opipe, SMB_OPIPE_CLOSE, 0);
3db3f65c6274eb042354801a308c8e9bc4994553amw (void) smb_opipe_door_call(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw bzero(&opipe->p_hdr, sizeof (smb_opipe_hdr_t));
3db3f65c6274eb042354801a308c8e9bc4994553amw kmem_free(opipe->p_doorbuf, SMB_OPIPE_DOOR_BUFSIZE);
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_user_context_fini(&opipe->p_context);
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_exit(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw cv_destroy(&opipe->p_cv);
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_destroy(&opipe->p_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw}
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic int
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_opipe_set_hdr(smb_opipe_t *opipe, uint32_t cmd, uint32_t datalen)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
3db3f65c6274eb042354801a308c8e9bc4994553amw opipe->p_hdr.oh_op = cmd;
3db3f65c6274eb042354801a308c8e9bc4994553amw opipe->p_hdr.oh_datalen = datalen;
3db3f65c6274eb042354801a308c8e9bc4994553amw opipe->p_hdr.oh_resid = 0;
3db3f65c6274eb042354801a308c8e9bc4994553amw opipe->p_hdr.oh_status = 0;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw return (smb_opipe_hdr_encode(&opipe->p_hdr, opipe->p_doorbuf,
3db3f65c6274eb042354801a308c8e9bc4994553amw SMB_OPIPE_DOOR_BUFSIZE));
3db3f65c6274eb042354801a308c8e9bc4994553amw}
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw/*
3db3f65c6274eb042354801a308c8e9bc4994553amw * smb_opipe_transact
3db3f65c6274eb042354801a308c8e9bc4994553amw *
3db3f65c6274eb042354801a308c8e9bc4994553amw * This is the entry point for RPC bind and request transactions.
3db3f65c6274eb042354801a308c8e9bc4994553amw * The fid is an arbitrary id used to associate RPC requests with a
3db3f65c6274eb042354801a308c8e9bc4994553amw * particular binding handle.
3db3f65c6274eb042354801a308c8e9bc4994553amw *
3db3f65c6274eb042354801a308c8e9bc4994553amw * If the data to be returned is larger than the client expects, we
3db3f65c6274eb042354801a308c8e9bc4994553amw * return as much as the client can handle and report a buffer overflow
3db3f65c6274eb042354801a308c8e9bc4994553amw * warning, which informs the client that we have more data to return.
3db3f65c6274eb042354801a308c8e9bc4994553amw * The residual data remains in the pipe until the client claims it or
3db3f65c6274eb042354801a308c8e9bc4994553amw * closes the pipe.
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_sdrc_t
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_opipe_transact(smb_request_t *sr, struct uio *uio)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_xa_t *xa;
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_t *opipe;
3db3f65c6274eb042354801a308c8e9bc4994553amw struct mbuf *mhead;
3db3f65c6274eb042354801a308c8e9bc4994553amw int mdrcnt;
3db3f65c6274eb042354801a308c8e9bc4994553amw int nbytes;
3db3f65c6274eb042354801a308c8e9bc4994553amw int rc;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if ((rc = smb_opipe_write(sr, uio)) != 0) {
3db3f65c6274eb042354801a308c8e9bc4994553amw if (rc == EBADF)
3db3f65c6274eb042354801a308c8e9bc4994553amw smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
3db3f65c6274eb042354801a308c8e9bc4994553amw ERRDOS, ERROR_INVALID_HANDLE);
3db3f65c6274eb042354801a308c8e9bc4994553amw else
3db3f65c6274eb042354801a308c8e9bc4994553amw smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
3db3f65c6274eb042354801a308c8e9bc4994553amw ERRDOS, ERROR_INTERNAL_ERROR);
3db3f65c6274eb042354801a308c8e9bc4994553amw return (SDRC_ERROR);
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw xa = sr->r_xa;
3db3f65c6274eb042354801a308c8e9bc4994553amw mdrcnt = xa->smb_mdrcnt;
3db3f65c6274eb042354801a308c8e9bc4994553amw opipe = sr->fid_ofile->f_pipe;
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_enter(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (smb_opipe_set_hdr(opipe, SMB_OPIPE_READ, mdrcnt) == -1) {
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_exit(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
3db3f65c6274eb042354801a308c8e9bc4994553amw ERRDOS, ERROR_INTERNAL_ERROR);
3db3f65c6274eb042354801a308c8e9bc4994553amw return (SDRC_ERROR);
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw rc = smb_opipe_door_call(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw nbytes = opipe->p_hdr.oh_datalen;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (rc != 0) {
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_exit(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
3db3f65c6274eb042354801a308c8e9bc4994553amw ERRDOS, ERROR_INTERNAL_ERROR);
3db3f65c6274eb042354801a308c8e9bc4994553amw return (SDRC_ERROR);
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (nbytes) {
3db3f65c6274eb042354801a308c8e9bc4994553amw mhead = smb_mbuf_get(opipe->p_data, nbytes);
3db3f65c6274eb042354801a308c8e9bc4994553amw xa->rep_data_mb.max_bytes = nbytes;
3db3f65c6274eb042354801a308c8e9bc4994553amw MBC_ATTACH_MBUF(&xa->rep_data_mb, mhead);
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (opipe->p_hdr.oh_resid) {
3db3f65c6274eb042354801a308c8e9bc4994553amw /*
3db3f65c6274eb042354801a308c8e9bc4994553amw * The pipe contains more data than mdrcnt, warn the
3db3f65c6274eb042354801a308c8e9bc4994553amw * client that there is more data in the pipe.
3db3f65c6274eb042354801a308c8e9bc4994553amw * Typically, the client will call SmbReadX, which
3db3f65c6274eb042354801a308c8e9bc4994553amw * will call smb_opipe_read, to get the data.
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amw smbsr_warn(sr, NT_STATUS_BUFFER_OVERFLOW,
3db3f65c6274eb042354801a308c8e9bc4994553amw ERRDOS, ERROR_MORE_DATA);
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_exit(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw return (SDRC_SUCCESS);
3db3f65c6274eb042354801a308c8e9bc4994553amw}
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw/*
3db3f65c6274eb042354801a308c8e9bc4994553amw * smb_opipe_write
3db3f65c6274eb042354801a308c8e9bc4994553amw *
3db3f65c6274eb042354801a308c8e9bc4994553amw * Write RPC request data to the pipe. The client should call smb_opipe_read
3db3f65c6274eb042354801a308c8e9bc4994553amw * to complete the exchange and obtain the RPC response.
3db3f65c6274eb042354801a308c8e9bc4994553amw *
3db3f65c6274eb042354801a308c8e9bc4994553amw * Returns 0 on success or an errno on failure.
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amwint
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_opipe_write(smb_request_t *sr, struct uio *uio)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_t *opipe;
3db3f65c6274eb042354801a308c8e9bc4994553amw uint32_t buflen;
3db3f65c6274eb042354801a308c8e9bc4994553amw uint32_t len;
3db3f65c6274eb042354801a308c8e9bc4994553amw int rc;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw ASSERT(sr->fid_ofile);
3db3f65c6274eb042354801a308c8e9bc4994553amw ASSERT(sr->fid_ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
3db3f65c6274eb042354801a308c8e9bc4994553amw ASSERT(sr->fid_ofile->f_pipe != NULL);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw opipe = sr->fid_ofile->f_pipe;
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_enter(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (!SMB_OPIPE_ISOPEN(opipe)) {
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_exit(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw return (EBADF);
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw rc = smb_opipe_set_hdr(opipe, SMB_OPIPE_WRITE, uio->uio_resid);
3db3f65c6274eb042354801a308c8e9bc4994553amw len = xdr_sizeof(smb_opipe_hdr_xdr, &opipe->p_hdr);
3db3f65c6274eb042354801a308c8e9bc4994553amw if (rc == -1 || len == 0) {
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_exit(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw return (ENOMEM);
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw buflen = SMB_OPIPE_DOOR_BUFSIZE - len;
3db3f65c6274eb042354801a308c8e9bc4994553amw (void) uiomove((caddr_t)opipe->p_data, buflen, UIO_WRITE, uio);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw rc = smb_opipe_door_call(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_exit(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw return ((rc == 0) ? 0 : EIO);
3db3f65c6274eb042354801a308c8e9bc4994553amw}
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw/*
3db3f65c6274eb042354801a308c8e9bc4994553amw * smb_opipe_read
3db3f65c6274eb042354801a308c8e9bc4994553amw *
3db3f65c6274eb042354801a308c8e9bc4994553amw * This interface may be called because smb_opipe_transact could not return
3db3f65c6274eb042354801a308c8e9bc4994553amw * all of the data in the original transaction or to form the second half
3db3f65c6274eb042354801a308c8e9bc4994553amw * of a transaction set up using smb_opipe_write. Either way, we just need
3db3f65c6274eb042354801a308c8e9bc4994553amw * to read data from the pipe and return it.
3db3f65c6274eb042354801a308c8e9bc4994553amw *
3db3f65c6274eb042354801a308c8e9bc4994553amw * The response data is encoded into raw_data as required by the smb_read
3db3f65c6274eb042354801a308c8e9bc4994553amw * functions. The uio_resid value indicates the number of bytes read.
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amwint
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_opipe_read(smb_request_t *sr, struct uio *uio)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_t *opipe;
3db3f65c6274eb042354801a308c8e9bc4994553amw struct mbuf *mhead;
3db3f65c6274eb042354801a308c8e9bc4994553amw uint32_t nbytes;
3db3f65c6274eb042354801a308c8e9bc4994553amw int rc;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw ASSERT(sr->fid_ofile);
3db3f65c6274eb042354801a308c8e9bc4994553amw ASSERT(sr->fid_ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
3db3f65c6274eb042354801a308c8e9bc4994553amw ASSERT(sr->fid_ofile->f_pipe != NULL);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw opipe = sr->fid_ofile->f_pipe;
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_enter(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (!SMB_OPIPE_ISOPEN(opipe)) {
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_exit(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw return (EBADF);
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (smb_opipe_set_hdr(opipe, SMB_OPIPE_READ, uio->uio_resid) == -1) {
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_exit(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw return (ENOMEM);
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw rc = smb_opipe_door_call(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw nbytes = opipe->p_hdr.oh_datalen;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (rc != 0 || nbytes > uio->uio_resid) {
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_exit(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw return (EIO);
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (nbytes) {
3db3f65c6274eb042354801a308c8e9bc4994553amw mhead = smb_mbuf_get(opipe->p_data, nbytes);
3db3f65c6274eb042354801a308c8e9bc4994553amw MBC_SETUP(&sr->raw_data, nbytes);
3db3f65c6274eb042354801a308c8e9bc4994553amw MBC_ATTACH_MBUF(&sr->raw_data, mhead);
3db3f65c6274eb042354801a308c8e9bc4994553amw uio->uio_resid -= nbytes;
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_exit(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw return (rc);
3db3f65c6274eb042354801a308c8e9bc4994553amw}
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw/*
3db3f65c6274eb042354801a308c8e9bc4994553amw * Named pipe I/O is serialized per fid to ensure that each request
3db3f65c6274eb042354801a308c8e9bc4994553amw * has exclusive opipe access for the duration of the request.
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic void
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_opipe_enter(smb_opipe_t *opipe)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_enter(&opipe->p_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw while (opipe->p_busy)
3db3f65c6274eb042354801a308c8e9bc4994553amw cv_wait(&opipe->p_cv, &opipe->p_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw opipe->p_busy = 1;
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_exit(&opipe->p_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw}
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic void
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_opipe_exit(smb_opipe_t *opipe)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_enter(&opipe->p_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw opipe->p_busy = 0;
3db3f65c6274eb042354801a308c8e9bc4994553amw cv_signal(&opipe->p_cv);
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_exit(&opipe->p_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw}
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw/*
3db3f65c6274eb042354801a308c8e9bc4994553amw * opipe door client (to user space door server).
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amwvoid
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_opipe_door_init(void)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_init(&smb_opipe_door_mutex, NULL, MUTEX_DEFAULT, NULL);
3db3f65c6274eb042354801a308c8e9bc4994553amw cv_init(&smb_opipe_door_cv, NULL, CV_DEFAULT, NULL);
3db3f65c6274eb042354801a308c8e9bc4994553amw}
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amwvoid
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_opipe_door_fini(void)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_door_close();
3db3f65c6274eb042354801a308c8e9bc4994553amw cv_destroy(&smb_opipe_door_cv);
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_destroy(&smb_opipe_door_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw}
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw/*
3db3f65c6274eb042354801a308c8e9bc4994553amw * Open the (user space) door. If the door is already open,
3db3f65c6274eb042354801a308c8e9bc4994553amw * close it first because the door-id has probably changed.
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amwint
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_opipe_door_open(int door_id)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_door_close();
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_enter(&smb_opipe_door_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_door_ncall = 0;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (smb_opipe_door_hd == NULL) {
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_door_id = door_id;
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_door_hd = door_ki_lookup(door_id);
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_exit(&smb_opipe_door_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw return ((smb_opipe_door_hd == NULL) ? -1 : 0);
3db3f65c6274eb042354801a308c8e9bc4994553amw}
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw/*
3db3f65c6274eb042354801a308c8e9bc4994553amw * Close the (user space) door.
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amwvoid
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_opipe_door_close(void)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_enter(&smb_opipe_door_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (smb_opipe_door_hd != NULL) {
3db3f65c6274eb042354801a308c8e9bc4994553amw while (smb_opipe_door_ncall > 0)
3db3f65c6274eb042354801a308c8e9bc4994553amw cv_wait(&smb_opipe_door_cv, &smb_opipe_door_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw door_ki_rele(smb_opipe_door_hd);
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_door_hd = NULL;
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_exit(&smb_opipe_door_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw}
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw/*
3db3f65c6274eb042354801a308c8e9bc4994553amw * opipe door call interface.
3db3f65c6274eb042354801a308c8e9bc4994553amw * Door serialization and call reference accounting is handled here.
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic int
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_opipe_door_call(smb_opipe_t *opipe)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
3db3f65c6274eb042354801a308c8e9bc4994553amw int rc;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_enter(&smb_opipe_door_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (smb_opipe_door_hd == NULL) {
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_exit(&smb_opipe_door_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (smb_opipe_door_open(smb_opipe_door_id) != 0)
3db3f65c6274eb042354801a308c8e9bc4994553amw return (-1);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_enter(&smb_opipe_door_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw ++smb_opipe_door_ncall;
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_exit(&smb_opipe_door_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw rc = smb_opipe_door_upcall(opipe);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_enter(&smb_opipe_door_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw --smb_opipe_door_ncall;
3db3f65c6274eb042354801a308c8e9bc4994553amw cv_signal(&smb_opipe_door_cv);
3db3f65c6274eb042354801a308c8e9bc4994553amw mutex_exit(&smb_opipe_door_mutex);
3db3f65c6274eb042354801a308c8e9bc4994553amw return (rc);
3db3f65c6274eb042354801a308c8e9bc4994553amw}
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw/*
3db3f65c6274eb042354801a308c8e9bc4994553amw * Door upcall wrapper - handles data marshalling.
3db3f65c6274eb042354801a308c8e9bc4994553amw * This function should only be called by smb_opipe_door_call.
3db3f65c6274eb042354801a308c8e9bc4994553amw */
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic int
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_opipe_door_upcall(smb_opipe_t *opipe)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
3db3f65c6274eb042354801a308c8e9bc4994553amw door_arg_t da;
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_opipe_hdr_t hdr;
3db3f65c6274eb042354801a308c8e9bc4994553amw int i;
3db3f65c6274eb042354801a308c8e9bc4994553amw int rc;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw da.data_ptr = (char *)opipe->p_doorbuf;
3db3f65c6274eb042354801a308c8e9bc4994553amw da.data_size = SMB_OPIPE_DOOR_BUFSIZE;
3db3f65c6274eb042354801a308c8e9bc4994553amw da.desc_ptr = NULL;
3db3f65c6274eb042354801a308c8e9bc4994553amw da.desc_num = 0;
3db3f65c6274eb042354801a308c8e9bc4994553amw da.rbuf = (char *)opipe->p_doorbuf;
3db3f65c6274eb042354801a308c8e9bc4994553amw da.rsize = SMB_OPIPE_DOOR_BUFSIZE;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw for (i = 0; i < 3; ++i) {
3db3f65c6274eb042354801a308c8e9bc4994553amw if ((rc = door_ki_upcall_limited(smb_opipe_door_hd, &da,
3db3f65c6274eb042354801a308c8e9bc4994553amw NULL, SIZE_MAX, 0)) == 0)
3db3f65c6274eb042354801a308c8e9bc4994553amw break;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (rc != EAGAIN && rc != EINTR)
3db3f65c6274eb042354801a308c8e9bc4994553amw return (-1);
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (rc != 0)
3db3f65c6274eb042354801a308c8e9bc4994553amw return (-1);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (smb_opipe_hdr_decode(&hdr, (uint8_t *)da.rbuf, da.rsize) == -1)
3db3f65c6274eb042354801a308c8e9bc4994553amw return (-1);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if ((hdr.oh_magic != SMB_OPIPE_HDR_MAGIC) ||
3db3f65c6274eb042354801a308c8e9bc4994553amw (hdr.oh_fid != opipe->p_hdr.oh_fid) ||
3db3f65c6274eb042354801a308c8e9bc4994553amw (hdr.oh_op != opipe->p_hdr.oh_op) ||
3db3f65c6274eb042354801a308c8e9bc4994553amw (hdr.oh_status != 0) ||
3db3f65c6274eb042354801a308c8e9bc4994553amw (hdr.oh_datalen > SMB_OPIPE_DOOR_BUFSIZE)) {
3db3f65c6274eb042354801a308c8e9bc4994553amw return (-1);
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw opipe->p_hdr.oh_datalen = hdr.oh_datalen;
3db3f65c6274eb042354801a308c8e9bc4994553amw opipe->p_hdr.oh_resid = hdr.oh_resid;
3db3f65c6274eb042354801a308c8e9bc4994553amw return (0);
3db3f65c6274eb042354801a308c8e9bc4994553amw}
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amwvoid
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_user_context_init(smb_user_t *user, smb_opipe_context_t *ctx)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_session_t *session;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw ASSERT(user);
3db3f65c6274eb042354801a308c8e9bc4994553amw ASSERT(user->u_domain);
3db3f65c6274eb042354801a308c8e9bc4994553amw ASSERT(user->u_name);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw session = user->u_session;
3db3f65c6274eb042354801a308c8e9bc4994553amw ASSERT(session);
3db3f65c6274eb042354801a308c8e9bc4994553amw ASSERT(session->workstation);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw ctx->oc_session_id = session->s_kid;
3db3f65c6274eb042354801a308c8e9bc4994553amw ctx->oc_native_os = session->native_os;
3db3f65c6274eb042354801a308c8e9bc4994553amw ctx->oc_ipaddr = session->ipaddr;
3db3f65c6274eb042354801a308c8e9bc4994553amw ctx->oc_uid = user->u_uid;
3db3f65c6274eb042354801a308c8e9bc4994553amw ctx->oc_logon_time = user->u_logon_time;
3db3f65c6274eb042354801a308c8e9bc4994553amw ctx->oc_flags = user->u_flags;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw ctx->oc_domain_len = user->u_domain_len;
3db3f65c6274eb042354801a308c8e9bc4994553amw ctx->oc_domain = smb_kstrdup(user->u_domain, ctx->oc_domain_len);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw ctx->oc_account_len = user->u_name_len;
3db3f65c6274eb042354801a308c8e9bc4994553amw ctx->oc_account = smb_kstrdup(user->u_name, ctx->oc_account_len);
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw ctx->oc_workstation_len = strlen(session->workstation) + 1;
3db3f65c6274eb042354801a308c8e9bc4994553amw ctx->oc_workstation = smb_kstrdup(session->workstation,
3db3f65c6274eb042354801a308c8e9bc4994553amw ctx->oc_workstation_len);
3db3f65c6274eb042354801a308c8e9bc4994553amw}
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic void
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_user_context_fini(smb_opipe_context_t *ctx)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
3db3f65c6274eb042354801a308c8e9bc4994553amw if (ctx) {
3db3f65c6274eb042354801a308c8e9bc4994553amw if (ctx->oc_domain)
3db3f65c6274eb042354801a308c8e9bc4994553amw kmem_free(ctx->oc_domain, ctx->oc_domain_len);
3db3f65c6274eb042354801a308c8e9bc4994553amw if (ctx->oc_account)
3db3f65c6274eb042354801a308c8e9bc4994553amw kmem_free(ctx->oc_account, ctx->oc_account_len);
3db3f65c6274eb042354801a308c8e9bc4994553amw if (ctx->oc_workstation)
3db3f65c6274eb042354801a308c8e9bc4994553amw kmem_free(ctx->oc_workstation, ctx->oc_workstation_len);
3db3f65c6274eb042354801a308c8e9bc4994553amw bzero(ctx, sizeof (smb_opipe_context_t));
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw}
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amwvoid
3db3f65c6274eb042354801a308c8e9bc4994553amwsmb_user_list_free(smb_dr_ulist_t *userlist)
3db3f65c6274eb042354801a308c8e9bc4994553amw{
3db3f65c6274eb042354801a308c8e9bc4994553amw int i;
3db3f65c6274eb042354801a308c8e9bc4994553amw
3db3f65c6274eb042354801a308c8e9bc4994553amw if (userlist) {
3db3f65c6274eb042354801a308c8e9bc4994553amw for (i = 0; i < userlist->dul_cnt; i++)
3db3f65c6274eb042354801a308c8e9bc4994553amw smb_user_context_fini(&userlist->dul_users[i]);
3db3f65c6274eb042354801a308c8e9bc4994553amw }
3db3f65c6274eb042354801a308c8e9bc4994553amw}