168b2bbf2SGordon Ross /* 268b2bbf2SGordon Ross * This file and its contents are supplied under the terms of the 368b2bbf2SGordon Ross * Common Development and Distribution License ("CDDL"), version 1.0. 468b2bbf2SGordon Ross * You may only use this file in accordance with the terms of version 568b2bbf2SGordon Ross * 1.0 of the CDDL. 668b2bbf2SGordon Ross * 768b2bbf2SGordon Ross * A full copy of the text of the CDDL should have accompanied this 868b2bbf2SGordon Ross * source. A copy of the CDDL is also available via the Internet at 968b2bbf2SGordon Ross * http://www.illumos.org/license/CDDL. 1068b2bbf2SGordon Ross */ 1168b2bbf2SGordon Ross 1268b2bbf2SGordon Ross /* 1368b2bbf2SGordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 14b6b7639aSGordon Ross * Copyright 2022 RackTop Systems, Inc. 1568b2bbf2SGordon Ross */ 1668b2bbf2SGordon Ross 1768b2bbf2SGordon Ross /* 1868b2bbf2SGordon Ross * This is the named pipe service for smbd. 1968b2bbf2SGordon Ross */ 2068b2bbf2SGordon Ross 2168b2bbf2SGordon Ross #include <sys/types.h> 2268b2bbf2SGordon Ross #include <sys/stat.h> 2368b2bbf2SGordon Ross 2468b2bbf2SGordon Ross #include <stdio.h> 2568b2bbf2SGordon Ross #include <strings.h> 2668b2bbf2SGordon Ross #include <stdlib.h> 2768b2bbf2SGordon Ross #include <synch.h> 2868b2bbf2SGordon Ross #include <unistd.h> 2968b2bbf2SGordon Ross #include <fcntl.h> 3068b2bbf2SGordon Ross #include <door.h> 3168b2bbf2SGordon Ross #include <errno.h> 3268b2bbf2SGordon Ross #include <pthread.h> 3368b2bbf2SGordon Ross #include <signal.h> 34b6b7639aSGordon Ross #include <ucred.h> 35b6b7639aSGordon Ross #include <priv.h> 3668b2bbf2SGordon Ross 3768b2bbf2SGordon Ross #include <smbsrv/libsmb.h> 3868b2bbf2SGordon Ross #include <smbsrv/libmlsvc.h> 3968b2bbf2SGordon Ross #include <smbsrv/smb_xdr.h> 4068b2bbf2SGordon Ross #include "smbd.h" 4168b2bbf2SGordon Ross 4268b2bbf2SGordon Ross struct pipe_listener { 4368b2bbf2SGordon Ross const char *name; 4468b2bbf2SGordon Ross int max_allowed; 4568b2bbf2SGordon Ross int max_seen; 4668b2bbf2SGordon Ross int current; 4768b2bbf2SGordon Ross pthread_t tid; 4868b2bbf2SGordon Ross }; 4968b2bbf2SGordon Ross 5068b2bbf2SGordon Ross static void *pipesvc_listener(void *); 5168b2bbf2SGordon Ross static void *pipesvc_worker(void *); 5268b2bbf2SGordon Ross static int pipe_send(ndr_pipe_t *, void *, size_t); 5368b2bbf2SGordon Ross static int pipe_recv(ndr_pipe_t *, void *, size_t); 5468b2bbf2SGordon Ross 5568b2bbf2SGordon Ross mutex_t pipesvc_mutex = DEFAULTMUTEX; 5668b2bbf2SGordon Ross int pipesvc_workers_max = 500; 5768b2bbf2SGordon Ross int pipesvc_workers_cur = 0; 5868b2bbf2SGordon Ross 5968b2bbf2SGordon Ross uint16_t pipe_max_msgsize = SMB_PIPE_MAX_MSGSIZE; 6068b2bbf2SGordon Ross 6168b2bbf2SGordon Ross /* 6268b2bbf2SGordon Ross * Allow more opens on SRVSVC because that's used by many clients 6368b2bbf2SGordon Ross * to get the share list, etc. 6468b2bbf2SGordon Ross */ 6568b2bbf2SGordon Ross #define SRVSVC_MAX_OPENS 200 6668b2bbf2SGordon Ross #define DEF_MAX_OPENS 50 6768b2bbf2SGordon Ross 6868b2bbf2SGordon Ross #define NLISTENERS 11 6968b2bbf2SGordon Ross static struct pipe_listener 7068b2bbf2SGordon Ross pipe_listeners[NLISTENERS] = { 7168b2bbf2SGordon Ross { "eventlog", DEF_MAX_OPENS, 0, 0 }, 7268b2bbf2SGordon Ross { "lsarpc", DEF_MAX_OPENS, 0, 0 }, 7368b2bbf2SGordon Ross { "lsass", DEF_MAX_OPENS, 0, 0 }, 7468b2bbf2SGordon Ross { "netdfs", DEF_MAX_OPENS, 0, 0 }, 7568b2bbf2SGordon Ross { "netlogon", DEF_MAX_OPENS, 0, 0 }, 7668b2bbf2SGordon Ross { "samr", DEF_MAX_OPENS, 0, 0 }, 7768b2bbf2SGordon Ross { "spoolss", DEF_MAX_OPENS, 0, 0 }, 7868b2bbf2SGordon Ross { "srvsvc", SRVSVC_MAX_OPENS, 0, 0 }, 7968b2bbf2SGordon Ross { "svcctl", DEF_MAX_OPENS, 0, 0 }, 8068b2bbf2SGordon Ross { "winreg", DEF_MAX_OPENS, 0, 0 }, 8168b2bbf2SGordon Ross { "wkssvc", DEF_MAX_OPENS, 0, 0 }, 8268b2bbf2SGordon Ross }; 8368b2bbf2SGordon Ross 8468b2bbf2SGordon Ross static ndr_pipe_t * 8568b2bbf2SGordon Ross np_new(struct pipe_listener *pl, int fid) 8668b2bbf2SGordon Ross { 8768b2bbf2SGordon Ross ndr_pipe_t *np; 8868b2bbf2SGordon Ross size_t len; 8968b2bbf2SGordon Ross 9068b2bbf2SGordon Ross /* 9168b2bbf2SGordon Ross * Allocating ndr_pipe_t + smb_netuserinfo_t as one. 9268b2bbf2SGordon Ross * We could just make that part of ndr_pipe_t, but 9368b2bbf2SGordon Ross * that struct is opaque to libmlrpc. 9468b2bbf2SGordon Ross */ 9568b2bbf2SGordon Ross len = sizeof (*np) + sizeof (smb_netuserinfo_t); 9668b2bbf2SGordon Ross np = malloc(len); 9768b2bbf2SGordon Ross if (np == NULL) 9868b2bbf2SGordon Ross return (NULL); 9968b2bbf2SGordon Ross 10068b2bbf2SGordon Ross bzero(np, len); 10168b2bbf2SGordon Ross np->np_listener = pl; 10268b2bbf2SGordon Ross np->np_endpoint = pl->name; 10368b2bbf2SGordon Ross np->np_user = (void*)(np + 1); 10468b2bbf2SGordon Ross np->np_send = pipe_send; 10568b2bbf2SGordon Ross np->np_recv = pipe_recv; 10668b2bbf2SGordon Ross np->np_fid = fid; 10768b2bbf2SGordon Ross np->np_max_xmit_frag = pipe_max_msgsize; 10868b2bbf2SGordon Ross np->np_max_recv_frag = pipe_max_msgsize; 10968b2bbf2SGordon Ross 11068b2bbf2SGordon Ross return (np); 11168b2bbf2SGordon Ross } 11268b2bbf2SGordon Ross 11368b2bbf2SGordon Ross static void 11468b2bbf2SGordon Ross np_free(ndr_pipe_t *np) 11568b2bbf2SGordon Ross { 11668b2bbf2SGordon Ross (void) close(np->np_fid); 11768b2bbf2SGordon Ross free(np); 11868b2bbf2SGordon Ross } 11968b2bbf2SGordon Ross 12068b2bbf2SGordon Ross /* 12168b2bbf2SGordon Ross * Create the smbd opipe door service. 12268b2bbf2SGordon Ross * Returns the door descriptor on success. Otherwise returns -1. 12368b2bbf2SGordon Ross */ 12468b2bbf2SGordon Ross int 12568b2bbf2SGordon Ross smbd_pipesvc_start(void) 12668b2bbf2SGordon Ross { 12768b2bbf2SGordon Ross pthread_t tid; 12868b2bbf2SGordon Ross pthread_attr_t tattr; 12968b2bbf2SGordon Ross struct pipe_listener *pl; 13068b2bbf2SGordon Ross int i, rc; 13168b2bbf2SGordon Ross 13268b2bbf2SGordon Ross if (mlsvc_init() != 0) { 13368b2bbf2SGordon Ross smbd_report("msrpc initialization failed"); 13468b2bbf2SGordon Ross return (-1); 13568b2bbf2SGordon Ross } 13668b2bbf2SGordon Ross 13768b2bbf2SGordon Ross (void) pthread_attr_init(&tattr); 13868b2bbf2SGordon Ross (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 13968b2bbf2SGordon Ross 14068b2bbf2SGordon Ross for (i = 0; i < NLISTENERS; i++) { 14168b2bbf2SGordon Ross pl = &pipe_listeners[i]; 14268b2bbf2SGordon Ross pl->max_seen = 0; 14368b2bbf2SGordon Ross 14468b2bbf2SGordon Ross if (strcasecmp(pl->name, "spoolss") == 0 && 14568b2bbf2SGordon Ross smb_config_getbool(SMB_CI_PRINT_ENABLE) == B_FALSE) 14668b2bbf2SGordon Ross continue; 14768b2bbf2SGordon Ross 14868b2bbf2SGordon Ross rc = pthread_create(&tid, &tattr, pipesvc_listener, pl); 14968b2bbf2SGordon Ross if (rc != 0) 15068b2bbf2SGordon Ross break; 15168b2bbf2SGordon Ross pipe_listeners[i].tid = tid; 15268b2bbf2SGordon Ross } 15368b2bbf2SGordon Ross 15468b2bbf2SGordon Ross if (rc != 0) { 15568b2bbf2SGordon Ross smbd_report("pipesvc pthread_create, %d", rc); 15668b2bbf2SGordon Ross } 15768b2bbf2SGordon Ross 15868b2bbf2SGordon Ross (void) pthread_attr_destroy(&tattr); 15968b2bbf2SGordon Ross 16068b2bbf2SGordon Ross return (rc); 16168b2bbf2SGordon Ross } 16268b2bbf2SGordon Ross 16368b2bbf2SGordon Ross void 16468b2bbf2SGordon Ross smbd_pipesvc_stop(void) 16568b2bbf2SGordon Ross { 16668b2bbf2SGordon Ross int i; 16768b2bbf2SGordon Ross 16868b2bbf2SGordon Ross (void) mutex_lock(&pipesvc_mutex); 16968b2bbf2SGordon Ross for (i = 0; i < NLISTENERS; i++) { 17068b2bbf2SGordon Ross if (pipe_listeners[i].tid == 0) 17168b2bbf2SGordon Ross continue; 17268b2bbf2SGordon Ross (void) pthread_kill(pipe_listeners[i].tid, SIGTERM); 17368b2bbf2SGordon Ross pipe_listeners[i].tid = 0; 17468b2bbf2SGordon Ross } 17568b2bbf2SGordon Ross (void) mutex_unlock(&pipesvc_mutex); 17668b2bbf2SGordon Ross } 17768b2bbf2SGordon Ross 17868b2bbf2SGordon Ross static void * 17968b2bbf2SGordon Ross pipesvc_listener(void *varg) 18068b2bbf2SGordon Ross { 18168b2bbf2SGordon Ross struct sockaddr_un sa; 18268b2bbf2SGordon Ross int err, listen_fd, newfd, snlen; 18368b2bbf2SGordon Ross struct pipe_listener *pl = varg; 18468b2bbf2SGordon Ross ndr_pipe_t *np; 18568b2bbf2SGordon Ross pthread_t tid; 18668b2bbf2SGordon Ross int rc; 18768b2bbf2SGordon Ross 18868b2bbf2SGordon Ross listen_fd = socket(AF_UNIX, SOCK_STREAM, 0); 18968b2bbf2SGordon Ross if (listen_fd < 0) { 19068b2bbf2SGordon Ross smbd_report("pipesvc_listener, so_create: %d", errno); 19168b2bbf2SGordon Ross return (NULL); 19268b2bbf2SGordon Ross } 19368b2bbf2SGordon Ross 19468b2bbf2SGordon Ross bzero(&sa, sizeof (sa)); 19568b2bbf2SGordon Ross sa.sun_family = AF_UNIX; 19668b2bbf2SGordon Ross (void) snprintf(sa.sun_path, sizeof (sa.sun_path), 19768b2bbf2SGordon Ross "%s/%s", SMB_PIPE_DIR, pl->name); 19868b2bbf2SGordon Ross 19968b2bbf2SGordon Ross /* Bind it to a listening name. */ 20068b2bbf2SGordon Ross (void) unlink(sa.sun_path); 20168b2bbf2SGordon Ross if (bind(listen_fd, (struct sockaddr *)&sa, sizeof (sa)) < 0) { 20268b2bbf2SGordon Ross smbd_report("pipesvc_listener, so_bind: %d", errno); 20368b2bbf2SGordon Ross (void) close(listen_fd); 20468b2bbf2SGordon Ross return (NULL); 20568b2bbf2SGordon Ross } 20668b2bbf2SGordon Ross 20768b2bbf2SGordon Ross if (listen(listen_fd, SOMAXCONN) < 0) { 20868b2bbf2SGordon Ross smbd_report("pipesvc_listener, listen: %d", errno); 20968b2bbf2SGordon Ross (void) close(listen_fd); 21068b2bbf2SGordon Ross return (NULL); 21168b2bbf2SGordon Ross } 21268b2bbf2SGordon Ross 21368b2bbf2SGordon Ross for (;;) { 21468b2bbf2SGordon Ross 21568b2bbf2SGordon Ross snlen = sizeof (sa); 21668b2bbf2SGordon Ross newfd = accept(listen_fd, (struct sockaddr *)&sa, &snlen); 21768b2bbf2SGordon Ross if (newfd < 0) { 21868b2bbf2SGordon Ross err = errno; 21968b2bbf2SGordon Ross switch (err) { 22068b2bbf2SGordon Ross case ECONNABORTED: 22168b2bbf2SGordon Ross continue; 22268b2bbf2SGordon Ross case EINTR: 22368b2bbf2SGordon Ross /* normal termination */ 22468b2bbf2SGordon Ross goto out; 22568b2bbf2SGordon Ross default: 22668b2bbf2SGordon Ross smbd_report("pipesvc_listener, " 22768b2bbf2SGordon Ross "accept failed: %d", errno); 22868b2bbf2SGordon Ross } 22968b2bbf2SGordon Ross smbd_report("pipesvc_listener, accept: %d", err); 23068b2bbf2SGordon Ross break; 23168b2bbf2SGordon Ross } 23268b2bbf2SGordon Ross 23368b2bbf2SGordon Ross np = np_new(pl, newfd); 23468b2bbf2SGordon Ross if (np == NULL) { 23568b2bbf2SGordon Ross smbd_report("pipesvc_listener, alloc1 failed"); 23668b2bbf2SGordon Ross (void) close(newfd); 237*6926de2eSGordon Ross smbd_nomem(); 23868b2bbf2SGordon Ross } 23968b2bbf2SGordon Ross 24068b2bbf2SGordon Ross rc = pthread_create(&tid, NULL, pipesvc_worker, np); 24168b2bbf2SGordon Ross if (rc != 0) { 24268b2bbf2SGordon Ross smbd_report("pipesvc_listener, pthread_create: %d", 24368b2bbf2SGordon Ross errno); 24468b2bbf2SGordon Ross np_free(np); 245*6926de2eSGordon Ross smbd_nomem(); 24668b2bbf2SGordon Ross } 24768b2bbf2SGordon Ross (void) pthread_detach(tid); 24868b2bbf2SGordon Ross 24968b2bbf2SGordon Ross /* Note: np_free in pipesvc_worker */ 25068b2bbf2SGordon Ross np = NULL; 25168b2bbf2SGordon Ross } 25268b2bbf2SGordon Ross 25368b2bbf2SGordon Ross out: 25468b2bbf2SGordon Ross (void) close(listen_fd); 25568b2bbf2SGordon Ross pl->tid = 0; 25668b2bbf2SGordon Ross return (NULL); 25768b2bbf2SGordon Ross } 25868b2bbf2SGordon Ross 259b6b7639aSGordon Ross #ifndef FKSMBD 260b6b7639aSGordon Ross static boolean_t 261b6b7639aSGordon Ross pipe_has_priv(ndr_pipe_t *np) 262b6b7639aSGordon Ross { 263b6b7639aSGordon Ross ucred_t *uc = NULL; 264b6b7639aSGordon Ross const priv_set_t *ps = NULL; 265b6b7639aSGordon Ross boolean_t ret = B_FALSE; 266b6b7639aSGordon Ross pid_t clpid; 267b6b7639aSGordon Ross 268b6b7639aSGordon Ross if (getpeerucred(np->np_fid, &uc) != 0) { 269b6b7639aSGordon Ross smbd_report("pipesvc: getpeerucred err %d", errno); 270b6b7639aSGordon Ross return (B_FALSE); 271b6b7639aSGordon Ross } 272b6b7639aSGordon Ross clpid = ucred_getpid(uc); 273b6b7639aSGordon Ross if (clpid == 0) { 274b6b7639aSGordon Ross /* in-kernel caller: OK */ 275b6b7639aSGordon Ross ret = B_TRUE; 276b6b7639aSGordon Ross goto out; 277b6b7639aSGordon Ross } 278b6b7639aSGordon Ross 279b6b7639aSGordon Ross ps = ucred_getprivset(uc, PRIV_EFFECTIVE); 280b6b7639aSGordon Ross if (ps == NULL) { 281b6b7639aSGordon Ross smbd_report("pipesvc: ucred_getprivset failed"); 282b6b7639aSGordon Ross goto out; 283b6b7639aSGordon Ross } 284b6b7639aSGordon Ross 285b6b7639aSGordon Ross /* 286b6b7639aSGordon Ross * Otherwise require sys_smb priv. 287b6b7639aSGordon Ross */ 288b6b7639aSGordon Ross if (priv_ismember(ps, PRIV_SYS_SMB)) { 289b6b7639aSGordon Ross ret = B_TRUE; 290b6b7639aSGordon Ross goto out; 291b6b7639aSGordon Ross } 292b6b7639aSGordon Ross 293b6b7639aSGordon Ross if (smbd.s_debug) { 294b6b7639aSGordon Ross smbd_report("pipesvc: non-privileged client " 295b6b7639aSGordon Ross "PID = %d UID = %d", 296b6b7639aSGordon Ross (int)clpid, ucred_getruid(uc)); 297b6b7639aSGordon Ross } 298b6b7639aSGordon Ross 299b6b7639aSGordon Ross out: 300b6b7639aSGordon Ross /* ps is free'd with the ucred */ 301b6b7639aSGordon Ross if (uc != NULL) 302b6b7639aSGordon Ross ucred_free(uc); 303b6b7639aSGordon Ross 304b6b7639aSGordon Ross return (ret); 305b6b7639aSGordon Ross } 306b6b7639aSGordon Ross #endif 307b6b7639aSGordon Ross 30868b2bbf2SGordon Ross static void * 30968b2bbf2SGordon Ross pipesvc_worker(void *varg) 31068b2bbf2SGordon Ross { 31168b2bbf2SGordon Ross XDR xdrs; 31268b2bbf2SGordon Ross smb_pipehdr_t phdr; 31368b2bbf2SGordon Ross ndr_pipe_t *np = varg; 31468b2bbf2SGordon Ross struct pipe_listener *pl = np->np_listener; 31568b2bbf2SGordon Ross void *buf = NULL; 31668b2bbf2SGordon Ross uint32_t status; 31768b2bbf2SGordon Ross ssize_t rc; 31868b2bbf2SGordon Ross 31968b2bbf2SGordon Ross (void) mutex_lock(&pipesvc_mutex); 32068b2bbf2SGordon Ross if (pipesvc_workers_cur >= pipesvc_workers_max || 32168b2bbf2SGordon Ross pl->current >= pl->max_allowed) { 32268b2bbf2SGordon Ross (void) mutex_unlock(&pipesvc_mutex); 32368b2bbf2SGordon Ross status = NT_STATUS_PIPE_NOT_AVAILABLE; 32468b2bbf2SGordon Ross (void) send(np->np_fid, &status, sizeof (status), 0); 32568b2bbf2SGordon Ross goto out_free_np; 32668b2bbf2SGordon Ross } 32768b2bbf2SGordon Ross pipesvc_workers_cur++; 32868b2bbf2SGordon Ross pl->current++; 32968b2bbf2SGordon Ross if (pl->max_seen < pl->current) 33068b2bbf2SGordon Ross pl->max_seen = pl->current; 33168b2bbf2SGordon Ross (void) mutex_unlock(&pipesvc_mutex); 33268b2bbf2SGordon Ross 33368b2bbf2SGordon Ross /* 33468b2bbf2SGordon Ross * The smbsrv kmod sends us one initial message containing an 33568b2bbf2SGordon Ross * XDR encoded smb_netuserinfo_t that we read and decode here, 33668b2bbf2SGordon Ross * all unbeknownst to libmlrpc. 33768b2bbf2SGordon Ross * 33868b2bbf2SGordon Ross * Might be nice to enhance getpeerucred() so it can give us 33968b2bbf2SGordon Ross * all the info smb_netuserinfo_t carries, and then use that, 34068b2bbf2SGordon Ross * which would allow using a more generic RPC service. 34168b2bbf2SGordon Ross */ 34268b2bbf2SGordon Ross rc = pipe_recv(np, &phdr, sizeof (phdr)); 34368b2bbf2SGordon Ross if (rc != 0) { 34468b2bbf2SGordon Ross smbd_report("pipesvc_worker, recv1: %d", rc); 34568b2bbf2SGordon Ross goto out_decr; 34668b2bbf2SGordon Ross } 34768b2bbf2SGordon Ross if (phdr.ph_magic != SMB_PIPE_HDR_MAGIC || 34868b2bbf2SGordon Ross phdr.ph_uilen > 8192) { 34968b2bbf2SGordon Ross smbd_report("pipesvc_worker, bad hdr"); 35068b2bbf2SGordon Ross goto out_decr; 35168b2bbf2SGordon Ross } 35268b2bbf2SGordon Ross buf = malloc(phdr.ph_uilen); 35368b2bbf2SGordon Ross if (buf == NULL) { 35468b2bbf2SGordon Ross smbd_report("pipesvc_worker, alloc1 failed"); 35568b2bbf2SGordon Ross goto out_decr; 35668b2bbf2SGordon Ross } 35768b2bbf2SGordon Ross rc = pipe_recv(np, buf, phdr.ph_uilen); 35868b2bbf2SGordon Ross if (rc != 0) { 35968b2bbf2SGordon Ross smbd_report("pipesvc_worker, recv2: %d", rc); 36068b2bbf2SGordon Ross goto out_decr; 36168b2bbf2SGordon Ross } 36268b2bbf2SGordon Ross 36368b2bbf2SGordon Ross xdrmem_create(&xdrs, buf, phdr.ph_uilen, XDR_DECODE); 36468b2bbf2SGordon Ross if (!smb_netuserinfo_xdr(&xdrs, np->np_user)) { 36568b2bbf2SGordon Ross smbd_report("pipesvc_worker, bad uinfo"); 36668b2bbf2SGordon Ross goto out_free_buf; 36768b2bbf2SGordon Ross } 36868b2bbf2SGordon Ross 36968b2bbf2SGordon Ross /* 370b6b7639aSGordon Ross * Don't trust the netuserinfo unless the client side 371b6b7639aSGordon Ross * has the necessary privileges 372b6b7639aSGordon Ross */ 373b6b7639aSGordon Ross #ifndef FKSMBD 374b6b7639aSGordon Ross if (!pipe_has_priv(np)) { 375b6b7639aSGordon Ross np->np_user->ui_flags = SMB_ATF_ANON; 376b6b7639aSGordon Ross } 377b6b7639aSGordon Ross #endif 378b6b7639aSGordon Ross 379b6b7639aSGordon Ross /* 38068b2bbf2SGordon Ross * Later, could disallow opens of some pipes by 38168b2bbf2SGordon Ross * anonymous users, etc. For now, reply "OK". 38268b2bbf2SGordon Ross */ 38368b2bbf2SGordon Ross status = 0; 38468b2bbf2SGordon Ross rc = pipe_send(np, &status, sizeof (status)); 38568b2bbf2SGordon Ross if (rc != 0) { 38668b2bbf2SGordon Ross smbd_report("pipesvc_worker, send1: %d", rc); 38768b2bbf2SGordon Ross goto out_free_buf; 38868b2bbf2SGordon Ross } 38968b2bbf2SGordon Ross 39068b2bbf2SGordon Ross /* 39168b2bbf2SGordon Ross * Run the RPC service loop worker, which 39268b2bbf2SGordon Ross * returns when it sees the pipe close. 39368b2bbf2SGordon Ross */ 39468b2bbf2SGordon Ross ndr_pipe_worker(np); 39568b2bbf2SGordon Ross 39668b2bbf2SGordon Ross xdrs.x_op = XDR_FREE; 39768b2bbf2SGordon Ross (void) smb_netuserinfo_xdr(&xdrs, np->np_user); 39868b2bbf2SGordon Ross 39968b2bbf2SGordon Ross out_free_buf: 40068b2bbf2SGordon Ross free(buf); 40168b2bbf2SGordon Ross xdr_destroy(&xdrs); 40268b2bbf2SGordon Ross 40368b2bbf2SGordon Ross out_decr: 40468b2bbf2SGordon Ross (void) mutex_lock(&pipesvc_mutex); 40568b2bbf2SGordon Ross pipesvc_workers_cur--; 40668b2bbf2SGordon Ross pl->current--; 40768b2bbf2SGordon Ross (void) mutex_unlock(&pipesvc_mutex); 40868b2bbf2SGordon Ross 40968b2bbf2SGordon Ross out_free_np: 41068b2bbf2SGordon Ross /* Cleanup what came in by varg. */ 41168b2bbf2SGordon Ross (void) shutdown(np->np_fid, SHUT_RDWR); 41268b2bbf2SGordon Ross np_free(np); 41368b2bbf2SGordon Ross return (NULL); 41468b2bbf2SGordon Ross } 41568b2bbf2SGordon Ross 41668b2bbf2SGordon Ross /* 41768b2bbf2SGordon Ross * These are the transport get/put callback functions provided 41868b2bbf2SGordon Ross * via the ndr_pipe_t object to the libmlrpc`ndr_pipe_worker. 41968b2bbf2SGordon Ross * These are called only with known PDU sizes and should 42068b2bbf2SGordon Ross * loop as needed to transfer the entire message. 42168b2bbf2SGordon Ross */ 42268b2bbf2SGordon Ross static int 42368b2bbf2SGordon Ross pipe_recv(ndr_pipe_t *np, void *buf, size_t len) 42468b2bbf2SGordon Ross { 42568b2bbf2SGordon Ross int x; 42668b2bbf2SGordon Ross 42768b2bbf2SGordon Ross while (len > 0) { 42868b2bbf2SGordon Ross x = recv(np->np_fid, buf, len, 0); 42968b2bbf2SGordon Ross if (x < 0) 43068b2bbf2SGordon Ross return (errno); 43168b2bbf2SGordon Ross if (x == 0) 43268b2bbf2SGordon Ross return (EIO); 43368b2bbf2SGordon Ross buf = (char *)buf + x; 43468b2bbf2SGordon Ross len -= x; 43568b2bbf2SGordon Ross } 43668b2bbf2SGordon Ross 43768b2bbf2SGordon Ross return (0); 43868b2bbf2SGordon Ross } 43968b2bbf2SGordon Ross 44068b2bbf2SGordon Ross static int 44168b2bbf2SGordon Ross pipe_send(ndr_pipe_t *np, void *buf, size_t len) 44268b2bbf2SGordon Ross { 44368b2bbf2SGordon Ross int x; 44468b2bbf2SGordon Ross 44568b2bbf2SGordon Ross while (len > 0) { 44668b2bbf2SGordon Ross x = send(np->np_fid, buf, len, 0); 44768b2bbf2SGordon Ross if (x < 0) 44868b2bbf2SGordon Ross return (errno); 44968b2bbf2SGordon Ross if (x == 0) 45068b2bbf2SGordon Ross return (EIO); 45168b2bbf2SGordon Ross buf = (char *)buf + x; 45268b2bbf2SGordon Ross len -= x; 45368b2bbf2SGordon Ross } 45468b2bbf2SGordon Ross 45568b2bbf2SGordon Ross return (0); 45668b2bbf2SGordon Ross } 457