smbiod.c revision 613a2f6ba31e891e3d947a356daf5e563d43c1ce
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * CDDL HEADER START
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * The contents of this file are subject to the terms of the
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Common Development and Distribution License (the "License").
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * You may not use this file except in compliance with the License.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * or http://www.opensolaris.org/os/licensing.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * See the License for the specific language governing permissions
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * and limitations under the License.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * When distributing Covered Code, include this CDDL HEADER in each
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * If applicable, add the following below this CDDL HEADER, with the
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * CDDL HEADER END
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Use is subject to license terms.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * SMBFS I/O Deamon (smbiod)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <sys/types.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <sys/stat.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <sys/note.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <errno.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <fcntl.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <signal.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <stdarg.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <stdio.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <string.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <strings.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <stdlib.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <synch.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <time.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <unistd.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <ucred.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <err.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <door.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <thread.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <netsmb/smb_lib.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#define ALARM_TIME 30 /* sec. */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#define EXIT_FAIL 1
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#define EXIT_OK 0
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#if defined(DEBUG) || defined(__lint)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#define DPRINT(...) do \
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{ \
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (smb_debug) \
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross fprintf(stderr, __VA_ARGS__); \
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross _NOTE(CONSTCOND) \
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross} while (0)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#else
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#define DPRINT(...) ((void)0)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#endif
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossmutex_t iod_mutex = DEFAULTMUTEX;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint iod_thr_count; /* threads, excluding main */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint iod_terminating;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossvoid iod_dispatch(void *cookie, char *argp, size_t argsz,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross door_desc_t *dp, uint_t n_desc);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint iod_newvc(smb_iod_ssn_t *clnt_ssn);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossvoid * iod_work(void *arg);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossmain(int argc, char **argv)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross static const int door_attrs =
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DOOR_REFUSE_DESC | DOOR_NO_CANCEL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sigset_t oldmask, tmpmask;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross char *env, *door_path = NULL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int door_fd = -1, tmp_fd = -1;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int err, i, sig;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int rc = EXIT_FAIL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Debugging support. */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if ((env = getenv("SMBFS_DEBUG")) != NULL) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_debug = atoi(env);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (smb_debug < 1)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_debug = 1;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Find out if an IOD is already running.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * If so, we lost a harmless startup race.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * An IOD did start, so exit success.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = smb_iod_open_door(&door_fd);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (err == 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross close(door_fd);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross door_fd = -1;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("main: already running\n");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross exit(EXIT_OK);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Create a file for the door.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross door_path = smb_iod_door_path();
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross unlink(door_path);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross tmp_fd = open(door_path, O_RDWR|O_CREAT|O_EXCL, 0600);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (tmp_fd < 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross perror(door_path);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross exit(EXIT_FAIL);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross close(tmp_fd);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross tmp_fd = -1;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Close FDs 0,1,2 so we don't have a TTY, and
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * re-open them on /dev/null so they won't be
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * used for device handles (etc.) later, and
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * we don't have to worry about printf calls
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * or whatever going to these FDs.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross for (i = 0; i < 3; i++) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Exception: If smb_debug, keep stderr */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (smb_debug && i == 2)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross break;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross close(i);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross tmp_fd = open("/dev/null", O_RDWR);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (tmp_fd < 0)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross perror("/dev/null");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (tmp_fd != i)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("Open /dev/null - wrong fd?\n");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Become session leader.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross setsid();
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Create door service threads with signals blocked.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sigfillset(&tmpmask);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sigprocmask(SIG_BLOCK, &tmpmask, &oldmask);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Setup the door service. */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross door_fd = door_create(iod_dispatch, NULL, door_attrs);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (door_fd < 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross fprintf(stderr, "%s: door_create failed\n", argv[0]);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rc = EXIT_FAIL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto errout;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross fdetach(door_path);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (fattach(door_fd, door_path) < 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross fprintf(stderr, "%s: fattach failed\n", argv[0]);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rc = EXIT_FAIL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto errout;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Post the initial alarm, and then just
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * wait for signals.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross alarm(ALARM_TIME);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossagain:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sig = sigwait(&tmpmask);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("main: sig=%d\n", sig);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * If a door call races with the alarm, ignore the alarm.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * It will be rescheduled when the threads go away.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_lock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (sig == SIGALRM && iod_thr_count > 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_unlock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto again;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross iod_terminating = 1;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_unlock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rc = EXIT_OK;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosserrout:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross fdetach(door_path);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross door_revoke(door_fd);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross door_fd = -1;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross unlink(door_path);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (rc);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*ARGSUSED*/
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossvoid
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossiod_dispatch(void *cookie, char *argp, size_t argsz,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross door_desc_t *dp, uint_t n_desc)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_iod_ssn_t *ssn;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ucred_t *ucred;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross uid_t cl_uid;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int rc;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Verify that the calling process has the same UID.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Paranoia: The door we created has mode 0600, so
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * this check is probably redundant.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ucred = NULL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (door_ucred(&ucred) != 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rc = EACCES;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross cl_uid = ucred_getruid(ucred);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ucred_free(ucred);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ucred = NULL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (cl_uid != getuid()) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("iod_dispatch: wrong UID\n");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rc = EACCES;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * The library uses a NULL arg call to check if
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * the deamon is running. Just return zero.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (argp == NULL) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rc = 0;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Otherwise, the arg must be the (fixed size)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * smb_iod_ssn_t
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (argsz != sizeof (*ssn)) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rc = EINVAL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_lock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (iod_terminating) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_unlock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("iod_dispatch: terminating\n");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rc = EINTR;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (iod_thr_count++ == 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross alarm(0);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("iod_dispatch: cancelled alarm\n");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_unlock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ssn = (void *) argp;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rc = iod_newvc(ssn);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_lock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (--iod_thr_count == 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("iod_dispatch: schedule alarm\n");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross alarm(ALARM_TIME);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_unlock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossout:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross door_return((void *)&rc, sizeof (rc), NULL, 0);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Try making a connection with the server described by
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * the info in the smb_iod_ssn_t arg. If successful,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * start an IOD thread to service it, then return to
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * the client side of the door.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossiod_newvc(smb_iod_ssn_t *clnt_ssn)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_ctx_t *ctx;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross thread_t tid;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int err;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * This needs to essentially "clone" the smb_ctx_t
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * from the client side of the door, or at least
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * as much of it as we need while creating a VC.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = smb_ctx_alloc(&ctx);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (err)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross bcopy(clnt_ssn, &ctx->ct_iod_ssn, sizeof (ctx->ct_iod_ssn));
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Do the initial connection setup here, so we can
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * report the outcome to the door client.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = smb_iod_connect(ctx);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (err != 0)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Create the driver session now, so we don't
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * race with the door client findvc call.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if ((err = smb_ctx_gethandle(ctx)) != 0)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (ioctl(ctx->ct_dev_fd, SMBIOC_SSN_CREATE, &ctx->ct_ssn) < 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = errno;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* The rest happens in the iod_work thread. */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = thr_create(NULL, 0, iod_work, ctx, THR_DETACHED, &tid);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (err == 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Given to the new thread.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * free at end of iod_work
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctx = NULL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossout:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (ctx)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_ctx_free(ctx);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Be the reader thread for some VC.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * This is started by a door call thread, which means
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * this is always at least the 2nd thread, therefore
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * it should never see thr_count==0 or terminating.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossvoid *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossiod_work(void *arg)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_ctx_t *ctx = arg;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_lock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (iod_thr_count++ == 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross alarm(0);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("iod_work: cancelled alarm\n");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_unlock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross (void) smb_iod_work(ctx);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_lock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (--iod_thr_count == 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("iod_work: schedule alarm\n");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross alarm(ALARM_TIME);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_unlock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_ctx_free(ctx);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (NULL);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}