b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * CDDL HEADER START
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * The contents of this file are subject to the terms of the
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Common Development and Distribution License (the "License").
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * You may not use this file except in compliance with the License.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * or http://www.opensolaris.org/os/licensing.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * See the License for the specific language governing permissions
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * and limitations under the License.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * When distributing Covered Code, include this CDDL HEADER in each
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * If applicable, add the following below this CDDL HEADER, with the
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * CDDL HEADER END
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/list.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <assert.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <alloca.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <door.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <errno.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <syslog.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <unistd.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <stdio.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <synch.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <string.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <stdlib.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/stat.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <fcntl.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <pthread.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <strings.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <umem.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <smbsrv/smb_door.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <smbsrv/smb_xdr.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <smbsrv/smb_token.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <smbsrv/libmlsvc.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <smbsrv/libsmbns.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include "smbd.h"
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Special version of smb_door_dispatch() for the
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * "fake" smbsrv (running in user space).
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * This is called via function pointer from
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * smbsrv: smb_kdoor_upcall()
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * The args and response go RPC encoded, just so we can
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * borrow some of the common doorsvc code, even though
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * there's no need for RPC encoding in this scenario.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossfksmbd_door_dispatch(smb_doorarg_t *da)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross smbd_arg_t dop_arg;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross smb_doorhdr_t *hdr;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross char *rbuf = NULL;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross char *argp = da->da_arg.data_ptr;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross size_t arg_size = da->da_arg.data_size;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross size_t hdr_size, rsize;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Decode
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * da->da_arg.data_ptr = (arg data, xdr encoded)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * da->da_arg.data_size = (arg data len)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross bzero(&dop_arg, sizeof (smbd_arg_t));
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross hdr = &dop_arg.hdr;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross hdr_size = xdr_sizeof(smb_doorhdr_xdr, hdr);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if ((argp == NULL) || (arg_size < hdr_size)) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross syslog(LOG_DEBUG, "fksmbd_door_dispatch: bad args");
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (-1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (smb_doorhdr_decode(hdr, (uint8_t *)argp, hdr_size) == -1) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross syslog(LOG_DEBUG, "smbd_door_dispatch: header decode failed");
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (-1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if ((hdr->dh_magic != SMB_DOOR_HDR_MAGIC) ||
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross (hdr->dh_flags != SMB_DF_FAKE_KERNEL)) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross syslog(LOG_DEBUG, "fksmbd_door_dispatch: invalid header");
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (-1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross dop_arg.opname = smb_doorhdr_opname(hdr->dh_op);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross dop_arg.data = argp + hdr_size;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross dop_arg.datalen = hdr->dh_datalen;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (hdr->dh_op == SMB_DR_ASYNC_RESPONSE) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * ASYNC_RESPONSE is not used here.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross syslog(LOG_DEBUG, "fksmbd_door_dispatch: ASYNC?");
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (-1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Dispatch
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Call the common smbd_doorsvc.c code.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross (void) smbd_door_dispatch_op(&dop_arg);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Encode
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * da->da_arg.rbuf = (return data buf)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * da->da_arg.rsize = (return data size)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Note that the return data buffer initially
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * points to the same buffer as the args.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * If that's not large enough, umem_alloc.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross rsize = dop_arg.rsize + hdr_size;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross rbuf = umem_alloc(rsize, UMEM_DEFAULT);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (rbuf == NULL) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross syslog(LOG_DEBUG, "fksmbd_door_dispatch[%s]: alloc %m",
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross dop_arg.opname);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (-1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* Copy caller's return data after the header. */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (dop_arg.rbuf != NULL) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross (void) memcpy(rbuf + hdr_size, dop_arg.rbuf, dop_arg.rsize);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross free(dop_arg.rbuf);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross hdr->dh_datalen = dop_arg.rsize;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross (void) smb_doorhdr_encode(hdr, (uint8_t *)rbuf, hdr_size);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* Let's update da->da_hdr too. */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross da->da_hdr = *hdr;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Was door_return()
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * NB: The "fake kernel" smbsrv code will umem_free rbuf.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross da->da_arg.rbuf = rbuf;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross da->da_arg.rsize = rsize;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (0);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}