68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross/*
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * This file and its contents are supplied under the terms of the
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * Common Development and Distribution License ("CDDL"), version 1.0.
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * You may only use this file in accordance with the terms of version
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * 1.0 of the CDDL.
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross *
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * A full copy of the text of the CDDL should have accompanied this
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * source. A copy of the CDDL is also available via the Internet at
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * http://www.illumos.org/license/CDDL.
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross */
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross/*
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross */
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross/*
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * This is the named pipe service for smbd.
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross */
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross#include <sys/types.h>
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross#include <sys/stat.h>
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross#include <stdio.h>
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross#include <strings.h>
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross#include <stdlib.h>
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross#include <synch.h>
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross#include <unistd.h>
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross#include <fcntl.h>
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross#include <door.h>
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross#include <errno.h>
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross#include <pthread.h>
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross#include <signal.h>
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross#include <smbsrv/libsmb.h>
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross#include <smbsrv/libmlsvc.h>
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross#include <smbsrv/smb_xdr.h>
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross#include "smbd.h"
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossstruct pipe_listener {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross const char *name;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross int max_allowed;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross int max_seen;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross int current;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross pthread_t tid;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross};
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossstatic void *pipesvc_listener(void *);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossstatic void *pipesvc_worker(void *);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossstatic int pipe_send(ndr_pipe_t *, void *, size_t);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossstatic int pipe_recv(ndr_pipe_t *, void *, size_t);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossmutex_t pipesvc_mutex = DEFAULTMUTEX;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossint pipesvc_workers_max = 500;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossint pipesvc_workers_cur = 0;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossuint16_t pipe_max_msgsize = SMB_PIPE_MAX_MSGSIZE;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross/*
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * Allow more opens on SRVSVC because that's used by many clients
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * to get the share list, etc.
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross */
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross#define SRVSVC_MAX_OPENS 200
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross#define DEF_MAX_OPENS 50
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross#define NLISTENERS 11
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossstatic struct pipe_listener
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rosspipe_listeners[NLISTENERS] = {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross { "eventlog", DEF_MAX_OPENS, 0, 0 },
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross { "lsarpc", DEF_MAX_OPENS, 0, 0 },
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross { "lsass", DEF_MAX_OPENS, 0, 0 },
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross { "netdfs", DEF_MAX_OPENS, 0, 0 },
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross { "netlogon", DEF_MAX_OPENS, 0, 0 },
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross { "samr", DEF_MAX_OPENS, 0, 0 },
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross { "spoolss", DEF_MAX_OPENS, 0, 0 },
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross { "srvsvc", SRVSVC_MAX_OPENS, 0, 0 },
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross { "svcctl", DEF_MAX_OPENS, 0, 0 },
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross { "winreg", DEF_MAX_OPENS, 0, 0 },
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross { "wkssvc", DEF_MAX_OPENS, 0, 0 },
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross};
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossstatic ndr_pipe_t *
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossnp_new(struct pipe_listener *pl, int fid)
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross{
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross ndr_pipe_t *np;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross size_t len;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross /*
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * Allocating ndr_pipe_t + smb_netuserinfo_t as one.
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * We could just make that part of ndr_pipe_t, but
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * that struct is opaque to libmlrpc.
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross */
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross len = sizeof (*np) + sizeof (smb_netuserinfo_t);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross np = malloc(len);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (np == NULL)
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross return (NULL);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross bzero(np, len);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross np->np_listener = pl;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross np->np_endpoint = pl->name;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross np->np_user = (void*)(np + 1);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross np->np_send = pipe_send;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross np->np_recv = pipe_recv;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross np->np_fid = fid;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross np->np_max_xmit_frag = pipe_max_msgsize;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross np->np_max_recv_frag = pipe_max_msgsize;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross return (np);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross}
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossstatic void
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossnp_free(ndr_pipe_t *np)
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross{
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) close(np->np_fid);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross free(np);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross}
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross/*
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * Create the smbd opipe door service.
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * Returns the door descriptor on success. Otherwise returns -1.
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross */
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossint
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rosssmbd_pipesvc_start(void)
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross{
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross pthread_t tid;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross pthread_attr_t tattr;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross struct pipe_listener *pl;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross int i, rc;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (mlsvc_init() != 0) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross smbd_report("msrpc initialization failed");
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross return (-1);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) pthread_attr_init(&tattr);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross for (i = 0; i < NLISTENERS; i++) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross pl = &pipe_listeners[i];
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross pl->max_seen = 0;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (strcasecmp(pl->name, "spoolss") == 0 &&
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross smb_config_getbool(SMB_CI_PRINT_ENABLE) == B_FALSE)
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross continue;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross rc = pthread_create(&tid, &tattr, pipesvc_listener, pl);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (rc != 0)
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross break;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross pipe_listeners[i].tid = tid;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (rc != 0) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross smbd_report("pipesvc pthread_create, %d", rc);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) pthread_attr_destroy(&tattr);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross return (rc);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross}
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossvoid
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rosssmbd_pipesvc_stop(void)
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross{
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross int i;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) mutex_lock(&pipesvc_mutex);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross for (i = 0; i < NLISTENERS; i++) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (pipe_listeners[i].tid == 0)
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross continue;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) pthread_kill(pipe_listeners[i].tid, SIGTERM);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross pipe_listeners[i].tid = 0;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) mutex_unlock(&pipesvc_mutex);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross}
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossstatic void *
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rosspipesvc_listener(void *varg)
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross{
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross struct sockaddr_un sa;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross int err, listen_fd, newfd, snlen;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross struct pipe_listener *pl = varg;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross ndr_pipe_t *np;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross pthread_t tid;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross int rc;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross listen_fd = socket(AF_UNIX, SOCK_STREAM, 0);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (listen_fd < 0) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross smbd_report("pipesvc_listener, so_create: %d", errno);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross return (NULL);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross bzero(&sa, sizeof (sa));
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross sa.sun_family = AF_UNIX;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) snprintf(sa.sun_path, sizeof (sa.sun_path),
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross "%s/%s", SMB_PIPE_DIR, pl->name);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross /* Bind it to a listening name. */
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) unlink(sa.sun_path);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (bind(listen_fd, (struct sockaddr *)&sa, sizeof (sa)) < 0) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross smbd_report("pipesvc_listener, so_bind: %d", errno);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) close(listen_fd);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross return (NULL);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (listen(listen_fd, SOMAXCONN) < 0) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross smbd_report("pipesvc_listener, listen: %d", errno);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) close(listen_fd);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross return (NULL);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross for (;;) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross snlen = sizeof (sa);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross newfd = accept(listen_fd, (struct sockaddr *)&sa, &snlen);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (newfd < 0) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross err = errno;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross switch (err) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross case ECONNABORTED:
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross continue;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross case EINTR:
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross /* normal termination */
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross goto out;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross default:
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross smbd_report("pipesvc_listener, "
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross "accept failed: %d", errno);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross smbd_report("pipesvc_listener, accept: %d", err);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross break;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross np = np_new(pl, newfd);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (np == NULL) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross smbd_report("pipesvc_listener, alloc1 failed");
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) close(newfd);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross continue;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross rc = pthread_create(&tid, NULL, pipesvc_worker, np);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (rc != 0) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross smbd_report("pipesvc_listener, pthread_create: %d",
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross errno);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross np_free(np);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross continue;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) pthread_detach(tid);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross /* Note: np_free in pipesvc_worker */
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross np = NULL;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossout:
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) close(listen_fd);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross pl->tid = 0;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross return (NULL);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross}
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossstatic void *
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rosspipesvc_worker(void *varg)
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross{
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross XDR xdrs;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross smb_pipehdr_t phdr;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross ndr_pipe_t *np = varg;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross struct pipe_listener *pl = np->np_listener;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross void *buf = NULL;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross uint32_t status;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross ssize_t rc;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) mutex_lock(&pipesvc_mutex);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (pipesvc_workers_cur >= pipesvc_workers_max ||
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross pl->current >= pl->max_allowed) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) mutex_unlock(&pipesvc_mutex);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross status = NT_STATUS_PIPE_NOT_AVAILABLE;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) send(np->np_fid, &status, sizeof (status), 0);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross goto out_free_np;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross pipesvc_workers_cur++;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross pl->current++;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (pl->max_seen < pl->current)
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross pl->max_seen = pl->current;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) mutex_unlock(&pipesvc_mutex);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross /*
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * The smbsrv kmod sends us one initial message containing an
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * XDR encoded smb_netuserinfo_t that we read and decode here,
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * all unbeknownst to libmlrpc.
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross *
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * Might be nice to enhance getpeerucred() so it can give us
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * all the info smb_netuserinfo_t carries, and then use that,
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * which would allow using a more generic RPC service.
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross */
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross rc = pipe_recv(np, &phdr, sizeof (phdr));
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (rc != 0) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross smbd_report("pipesvc_worker, recv1: %d", rc);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross goto out_decr;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (phdr.ph_magic != SMB_PIPE_HDR_MAGIC ||
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross phdr.ph_uilen > 8192) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross smbd_report("pipesvc_worker, bad hdr");
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross goto out_decr;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross buf = malloc(phdr.ph_uilen);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (buf == NULL) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross smbd_report("pipesvc_worker, alloc1 failed");
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross goto out_decr;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross rc = pipe_recv(np, buf, phdr.ph_uilen);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (rc != 0) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross smbd_report("pipesvc_worker, recv2: %d", rc);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross goto out_decr;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross xdrmem_create(&xdrs, buf, phdr.ph_uilen, XDR_DECODE);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (!smb_netuserinfo_xdr(&xdrs, np->np_user)) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross smbd_report("pipesvc_worker, bad uinfo");
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross goto out_free_buf;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross /*
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * Later, could disallow opens of some pipes by
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * anonymous users, etc. For now, reply "OK".
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross */
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross status = 0;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross rc = pipe_send(np, &status, sizeof (status));
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (rc != 0) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross smbd_report("pipesvc_worker, send1: %d", rc);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross goto out_free_buf;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross /*
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * Run the RPC service loop worker, which
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * returns when it sees the pipe close.
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross */
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross ndr_pipe_worker(np);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross xdrs.x_op = XDR_FREE;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) smb_netuserinfo_xdr(&xdrs, np->np_user);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossout_free_buf:
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross free(buf);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross xdr_destroy(&xdrs);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossout_decr:
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) mutex_lock(&pipesvc_mutex);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross pipesvc_workers_cur--;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross pl->current--;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) mutex_unlock(&pipesvc_mutex);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossout_free_np:
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross /* Cleanup what came in by varg. */
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross (void) shutdown(np->np_fid, SHUT_RDWR);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross np_free(np);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross return (NULL);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross}
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross/*
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * These are the transport get/put callback functions provided
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * via the ndr_pipe_t object to the libmlrpc`ndr_pipe_worker.
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * These are called only with known PDU sizes and should
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross * loop as needed to transfer the entire message.
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross */
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossstatic int
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rosspipe_recv(ndr_pipe_t *np, void *buf, size_t len)
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross{
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross int x;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross while (len > 0) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross x = recv(np->np_fid, buf, len, 0);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (x < 0)
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross return (errno);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (x == 0)
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross return (EIO);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross buf = (char *)buf + x;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross len -= x;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross return (0);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross}
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rossstatic int
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Rosspipe_send(ndr_pipe_t *np, void *buf, size_t len)
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross{
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross int x;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross while (len > 0) {
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross x = send(np->np_fid, buf, len, 0);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (x < 0)
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross return (errno);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross if (x == 0)
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross return (EIO);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross buf = (char *)buf + x;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross len -= x;
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross }
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross return (0);
68b2bbf26c7040fea4281dcb58b81e7627e46f34Gordon Ross}