18360efbdSAlfred Perlstein /* $NetBSD: svc.c,v 1.21 2000/07/06 03:10:35 christos Exp $ */ 28360efbdSAlfred Perlstein 399064799SGarrett Wollman /* 499064799SGarrett Wollman * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 599064799SGarrett Wollman * unrestricted use provided that this legend is included on all tape 699064799SGarrett Wollman * media and as a part of the software program in whole or part. Users 799064799SGarrett Wollman * may copy or modify Sun RPC without charge, but are not authorized 899064799SGarrett Wollman * to license or distribute it to anyone else except as part of a product or 999064799SGarrett Wollman * program developed by the user. 1099064799SGarrett Wollman * 1199064799SGarrett Wollman * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 1299064799SGarrett Wollman * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 1399064799SGarrett Wollman * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 1499064799SGarrett Wollman * 1599064799SGarrett Wollman * Sun RPC is provided with no support and without any obligation on the 1699064799SGarrett Wollman * part of Sun Microsystems, Inc. to assist in its use, correction, 1799064799SGarrett Wollman * modification or enhancement. 1899064799SGarrett Wollman * 1999064799SGarrett Wollman * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 2099064799SGarrett Wollman * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 2199064799SGarrett Wollman * OR ANY PART THEREOF. 2299064799SGarrett Wollman * 2399064799SGarrett Wollman * In no event will Sun Microsystems, Inc. be liable for any lost revenue 2499064799SGarrett Wollman * or profits or other special, indirect and consequential damages, even if 2599064799SGarrett Wollman * Sun has been advised of the possibility of such damages. 2699064799SGarrett Wollman * 2799064799SGarrett Wollman * Sun Microsystems, Inc. 2899064799SGarrett Wollman * 2550 Garcia Avenue 2999064799SGarrett Wollman * Mountain View, California 94043 3099064799SGarrett Wollman */ 3199064799SGarrett Wollman 3299064799SGarrett Wollman #if defined(LIBC_SCCS) && !defined(lint) 33a986ef57SDavid E. O'Brien static char *sccsid2 = "@(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro"; 34d3d20c82SDavid E. O'Brien static char *sccsid = "@(#)svc.c 2.4 88/08/11 4.0 RPCSRC"; 3599064799SGarrett Wollman #endif 36d3d20c82SDavid E. O'Brien #include <sys/cdefs.h> 37d3d20c82SDavid E. O'Brien __FBSDID("$FreeBSD$"); 3899064799SGarrett Wollman 3999064799SGarrett Wollman /* 4099064799SGarrett Wollman * svc.c, Server-side remote procedure call interface. 4199064799SGarrett Wollman * 4299064799SGarrett Wollman * There are two sets of procedures here. The xprt routines are 4399064799SGarrett Wollman * for handling transport handles. The svc routines handle the 4499064799SGarrett Wollman * list of service routines. 4599064799SGarrett Wollman * 4699064799SGarrett Wollman * Copyright (C) 1984, Sun Microsystems, Inc. 4799064799SGarrett Wollman */ 4899064799SGarrett Wollman 498360efbdSAlfred Perlstein #include "namespace.h" 509f5afc13SIan Dowse #include "reentrant.h" 518360efbdSAlfred Perlstein #include <sys/types.h> 528360efbdSAlfred Perlstein #include <sys/poll.h> 538360efbdSAlfred Perlstein #include <assert.h> 548360efbdSAlfred Perlstein #include <errno.h> 554c3af266SPoul-Henning Kamp #include <stdlib.h> 568360efbdSAlfred Perlstein #include <string.h> 578360efbdSAlfred Perlstein 5899064799SGarrett Wollman #include <rpc/rpc.h> 598360efbdSAlfred Perlstein #ifdef PORTMAP 6099064799SGarrett Wollman #include <rpc/pmap_clnt.h> 618360efbdSAlfred Perlstein #endif /* PORTMAP */ 628360efbdSAlfred Perlstein #include "un-namespace.h" 638360efbdSAlfred Perlstein 648360efbdSAlfred Perlstein #include "rpc_com.h" 65235baf26SDaniel Eischen #include "mt_misc.h" 6699064799SGarrett Wollman 6799064799SGarrett Wollman #define RQCRED_SIZE 400 /* this size is excessive */ 6899064799SGarrett Wollman 698360efbdSAlfred Perlstein #define SVC_VERSQUIET 0x0001 /* keep quiet about vers mismatch */ 708f55a568SDoug Rabson #define version_keepquiet(xp) (SVC_EXT(xp)->xp_flags & SVC_VERSQUIET) 718360efbdSAlfred Perlstein 72ae1e6afdSPeter Wemm #define max(a, b) (a > b ? a : b) 737d6a21b4SJames Raynard 7499064799SGarrett Wollman /* 7599064799SGarrett Wollman * The services list 7699064799SGarrett Wollman * Each entry represents a set of procedures (an rpc program). 7799064799SGarrett Wollman * The dispatch routine takes request structs and runs the 7899064799SGarrett Wollman * apropriate procedure. 7999064799SGarrett Wollman */ 8099064799SGarrett Wollman static struct svc_callout { 8199064799SGarrett Wollman struct svc_callout *sc_next; 828360efbdSAlfred Perlstein rpcprog_t sc_prog; 838360efbdSAlfred Perlstein rpcvers_t sc_vers; 848360efbdSAlfred Perlstein char *sc_netid; 85c05ac53bSDavid E. O'Brien void (*sc_dispatch)(struct svc_req *, SVCXPRT *); 8699064799SGarrett Wollman } *svc_head; 8799064799SGarrett Wollman 881372519bSDavid E. O'Brien static struct svc_callout *svc_find(rpcprog_t, rpcvers_t, 891372519bSDavid E. O'Brien struct svc_callout **, char *); 9008497c02SMartin Blapp static void __xprt_do_unregister (SVCXPRT *xprt, bool_t dolock); 91ae1e6afdSPeter Wemm 9299064799SGarrett Wollman /* *************** SVCXPRT related stuff **************** */ 9399064799SGarrett Wollman 9499064799SGarrett Wollman /* 9599064799SGarrett Wollman * Activate a transport handle. 9699064799SGarrett Wollman */ 9799064799SGarrett Wollman void 9899064799SGarrett Wollman xprt_register(xprt) 9999064799SGarrett Wollman SVCXPRT *xprt; 10099064799SGarrett Wollman { 1018360efbdSAlfred Perlstein int sock; 10299064799SGarrett Wollman 1038360efbdSAlfred Perlstein assert(xprt != NULL); 10499064799SGarrett Wollman 1058360efbdSAlfred Perlstein sock = xprt->xp_fd; 1068360efbdSAlfred Perlstein 1078360efbdSAlfred Perlstein rwlock_wrlock(&svc_fd_lock); 10808497c02SMartin Blapp if (__svc_xports == NULL) { 10908497c02SMartin Blapp __svc_xports = (SVCXPRT **) 1108360efbdSAlfred Perlstein mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *)); 111*ed8ddc6eSKonstantin Belousov if (__svc_xports == NULL) { 112*ed8ddc6eSKonstantin Belousov rwlock_unlock(&svc_fd_lock); 1138360efbdSAlfred Perlstein return; 114*ed8ddc6eSKonstantin Belousov } 11508497c02SMartin Blapp memset(__svc_xports, '\0', FD_SETSIZE * sizeof(SVCXPRT *)); 116ae1e6afdSPeter Wemm } 1178360efbdSAlfred Perlstein if (sock < FD_SETSIZE) { 11808497c02SMartin Blapp __svc_xports[sock] = xprt; 1198360efbdSAlfred Perlstein FD_SET(sock, &svc_fdset); 120ae1e6afdSPeter Wemm svc_maxfd = max(svc_maxfd, sock); 12199064799SGarrett Wollman } 1228360efbdSAlfred Perlstein rwlock_unlock(&svc_fd_lock); 1238360efbdSAlfred Perlstein } 12499064799SGarrett Wollman 12508497c02SMartin Blapp void 12608497c02SMartin Blapp xprt_unregister(SVCXPRT *xprt) 12708497c02SMartin Blapp { 12808497c02SMartin Blapp __xprt_do_unregister(xprt, TRUE); 12908497c02SMartin Blapp } 13008497c02SMartin Blapp 13108497c02SMartin Blapp void 13208497c02SMartin Blapp __xprt_unregister_unlocked(SVCXPRT *xprt) 13308497c02SMartin Blapp { 13408497c02SMartin Blapp __xprt_do_unregister(xprt, FALSE); 13508497c02SMartin Blapp } 13608497c02SMartin Blapp 13799064799SGarrett Wollman /* 13899064799SGarrett Wollman * De-activate a transport handle. 13999064799SGarrett Wollman */ 14008497c02SMartin Blapp static void 14108497c02SMartin Blapp __xprt_do_unregister(xprt, dolock) 14299064799SGarrett Wollman SVCXPRT *xprt; 14308497c02SMartin Blapp bool_t dolock; 14499064799SGarrett Wollman { 1458360efbdSAlfred Perlstein int sock; 14699064799SGarrett Wollman 1478360efbdSAlfred Perlstein assert(xprt != NULL); 1488360efbdSAlfred Perlstein 1498360efbdSAlfred Perlstein sock = xprt->xp_fd; 1508360efbdSAlfred Perlstein 15108497c02SMartin Blapp if (dolock) 1528360efbdSAlfred Perlstein rwlock_wrlock(&svc_fd_lock); 15308497c02SMartin Blapp if ((sock < FD_SETSIZE) && (__svc_xports[sock] == xprt)) { 15408497c02SMartin Blapp __svc_xports[sock] = NULL; 15599064799SGarrett Wollman FD_CLR(sock, &svc_fdset); 1568360efbdSAlfred Perlstein if (sock >= svc_maxfd) { 157ae1e6afdSPeter Wemm for (svc_maxfd--; svc_maxfd>=0; svc_maxfd--) 15808497c02SMartin Blapp if (__svc_xports[svc_maxfd]) 159ae1e6afdSPeter Wemm break; 16099064799SGarrett Wollman } 16199064799SGarrett Wollman } 16208497c02SMartin Blapp if (dolock) 1638360efbdSAlfred Perlstein rwlock_unlock(&svc_fd_lock); 16499064799SGarrett Wollman } 16599064799SGarrett Wollman 1668360efbdSAlfred Perlstein /* 1678360efbdSAlfred Perlstein * Add a service program to the callout list. 1688360efbdSAlfred Perlstein * The dispatch routine will be called when a rpc request for this 1698360efbdSAlfred Perlstein * program number comes in. 1708360efbdSAlfred Perlstein */ 1718360efbdSAlfred Perlstein bool_t 1728360efbdSAlfred Perlstein svc_reg(xprt, prog, vers, dispatch, nconf) 1738360efbdSAlfred Perlstein SVCXPRT *xprt; 1748360efbdSAlfred Perlstein const rpcprog_t prog; 1758360efbdSAlfred Perlstein const rpcvers_t vers; 176c05ac53bSDavid E. O'Brien void (*dispatch)(struct svc_req *, SVCXPRT *); 1778360efbdSAlfred Perlstein const struct netconfig *nconf; 1788360efbdSAlfred Perlstein { 1798360efbdSAlfred Perlstein bool_t dummy; 1808360efbdSAlfred Perlstein struct svc_callout *prev; 1818360efbdSAlfred Perlstein struct svc_callout *s; 1828360efbdSAlfred Perlstein struct netconfig *tnconf; 1838360efbdSAlfred Perlstein char *netid = NULL; 1848360efbdSAlfred Perlstein int flag = 0; 1858360efbdSAlfred Perlstein 1868360efbdSAlfred Perlstein /* VARIABLES PROTECTED BY svc_lock: s, prev, svc_head */ 1878360efbdSAlfred Perlstein 1888360efbdSAlfred Perlstein if (xprt->xp_netid) { 1898360efbdSAlfred Perlstein netid = strdup(xprt->xp_netid); 1908360efbdSAlfred Perlstein flag = 1; 1918360efbdSAlfred Perlstein } else if (nconf && nconf->nc_netid) { 1928360efbdSAlfred Perlstein netid = strdup(nconf->nc_netid); 1938360efbdSAlfred Perlstein flag = 1; 1948360efbdSAlfred Perlstein } else if ((tnconf = __rpcgettp(xprt->xp_fd)) != NULL) { 1958360efbdSAlfred Perlstein netid = strdup(tnconf->nc_netid); 1968360efbdSAlfred Perlstein flag = 1; 1978360efbdSAlfred Perlstein freenetconfigent(tnconf); 1988360efbdSAlfred Perlstein } /* must have been created with svc_raw_create */ 1998360efbdSAlfred Perlstein if ((netid == NULL) && (flag == 1)) { 2008360efbdSAlfred Perlstein return (FALSE); 2018360efbdSAlfred Perlstein } 2028360efbdSAlfred Perlstein 2038360efbdSAlfred Perlstein rwlock_wrlock(&svc_lock); 2048360efbdSAlfred Perlstein if ((s = svc_find(prog, vers, &prev, netid)) != NULL) { 2058360efbdSAlfred Perlstein if (netid) 2068360efbdSAlfred Perlstein free(netid); 2078360efbdSAlfred Perlstein if (s->sc_dispatch == dispatch) 2088360efbdSAlfred Perlstein goto rpcb_it; /* he is registering another xptr */ 2098360efbdSAlfred Perlstein rwlock_unlock(&svc_lock); 2108360efbdSAlfred Perlstein return (FALSE); 2118360efbdSAlfred Perlstein } 2128360efbdSAlfred Perlstein s = mem_alloc(sizeof (struct svc_callout)); 2138360efbdSAlfred Perlstein if (s == NULL) { 2148360efbdSAlfred Perlstein if (netid) 2158360efbdSAlfred Perlstein free(netid); 2168360efbdSAlfred Perlstein rwlock_unlock(&svc_lock); 2178360efbdSAlfred Perlstein return (FALSE); 2188360efbdSAlfred Perlstein } 2198360efbdSAlfred Perlstein 2208360efbdSAlfred Perlstein s->sc_prog = prog; 2218360efbdSAlfred Perlstein s->sc_vers = vers; 2228360efbdSAlfred Perlstein s->sc_dispatch = dispatch; 2238360efbdSAlfred Perlstein s->sc_netid = netid; 2248360efbdSAlfred Perlstein s->sc_next = svc_head; 2258360efbdSAlfred Perlstein svc_head = s; 2268360efbdSAlfred Perlstein 2278360efbdSAlfred Perlstein if ((xprt->xp_netid == NULL) && (flag == 1) && netid) 2288360efbdSAlfred Perlstein ((SVCXPRT *) xprt)->xp_netid = strdup(netid); 2298360efbdSAlfred Perlstein 2308360efbdSAlfred Perlstein rpcb_it: 2318360efbdSAlfred Perlstein rwlock_unlock(&svc_lock); 2328360efbdSAlfred Perlstein /* now register the information with the local binder service */ 2338360efbdSAlfred Perlstein if (nconf) { 2348360efbdSAlfred Perlstein /*LINTED const castaway*/ 2358360efbdSAlfred Perlstein dummy = rpcb_set(prog, vers, (struct netconfig *) nconf, 2368360efbdSAlfred Perlstein &((SVCXPRT *) xprt)->xp_ltaddr); 2378360efbdSAlfred Perlstein return (dummy); 2388360efbdSAlfred Perlstein } 2398360efbdSAlfred Perlstein return (TRUE); 2408360efbdSAlfred Perlstein } 2418360efbdSAlfred Perlstein 2428360efbdSAlfred Perlstein /* 2438360efbdSAlfred Perlstein * Remove a service program from the callout list. 2448360efbdSAlfred Perlstein */ 2458360efbdSAlfred Perlstein void 2468360efbdSAlfred Perlstein svc_unreg(prog, vers) 2478360efbdSAlfred Perlstein const rpcprog_t prog; 2488360efbdSAlfred Perlstein const rpcvers_t vers; 2498360efbdSAlfred Perlstein { 2508360efbdSAlfred Perlstein struct svc_callout *prev; 2518360efbdSAlfred Perlstein struct svc_callout *s; 2528360efbdSAlfred Perlstein 2538360efbdSAlfred Perlstein /* unregister the information anyway */ 2548360efbdSAlfred Perlstein (void) rpcb_unset(prog, vers, NULL); 2558360efbdSAlfred Perlstein rwlock_wrlock(&svc_lock); 2568360efbdSAlfred Perlstein while ((s = svc_find(prog, vers, &prev, NULL)) != NULL) { 2578360efbdSAlfred Perlstein if (prev == NULL) { 2588360efbdSAlfred Perlstein svc_head = s->sc_next; 2598360efbdSAlfred Perlstein } else { 2608360efbdSAlfred Perlstein prev->sc_next = s->sc_next; 2618360efbdSAlfred Perlstein } 2628360efbdSAlfred Perlstein s->sc_next = NULL; 2638360efbdSAlfred Perlstein if (s->sc_netid) 2648360efbdSAlfred Perlstein mem_free(s->sc_netid, sizeof (s->sc_netid) + 1); 2658360efbdSAlfred Perlstein mem_free(s, sizeof (struct svc_callout)); 2668360efbdSAlfred Perlstein } 2678360efbdSAlfred Perlstein rwlock_unlock(&svc_lock); 2688360efbdSAlfred Perlstein } 26999064799SGarrett Wollman 27099064799SGarrett Wollman /* ********************** CALLOUT list related stuff ************* */ 27199064799SGarrett Wollman 2728360efbdSAlfred Perlstein #ifdef PORTMAP 27399064799SGarrett Wollman /* 27499064799SGarrett Wollman * Add a service program to the callout list. 27599064799SGarrett Wollman * The dispatch routine will be called when a rpc request for this 27699064799SGarrett Wollman * program number comes in. 27799064799SGarrett Wollman */ 27899064799SGarrett Wollman bool_t 27999064799SGarrett Wollman svc_register(xprt, prog, vers, dispatch, protocol) 28099064799SGarrett Wollman SVCXPRT *xprt; 28199064799SGarrett Wollman u_long prog; 28299064799SGarrett Wollman u_long vers; 283c05ac53bSDavid E. O'Brien void (*dispatch)(struct svc_req *, SVCXPRT *); 28499064799SGarrett Wollman int protocol; 28599064799SGarrett Wollman { 28699064799SGarrett Wollman struct svc_callout *prev; 2878360efbdSAlfred Perlstein struct svc_callout *s; 28899064799SGarrett Wollman 2898360efbdSAlfred Perlstein assert(xprt != NULL); 2908360efbdSAlfred Perlstein assert(dispatch != NULL); 2918360efbdSAlfred Perlstein 2928360efbdSAlfred Perlstein if ((s = svc_find((rpcprog_t)prog, (rpcvers_t)vers, &prev, NULL)) != 2938360efbdSAlfred Perlstein NULL) { 29499064799SGarrett Wollman if (s->sc_dispatch == dispatch) 29599064799SGarrett Wollman goto pmap_it; /* he is registering another xptr */ 29699064799SGarrett Wollman return (FALSE); 29799064799SGarrett Wollman } 2988360efbdSAlfred Perlstein s = mem_alloc(sizeof(struct svc_callout)); 2998360efbdSAlfred Perlstein if (s == NULL) { 30099064799SGarrett Wollman return (FALSE); 30199064799SGarrett Wollman } 3028360efbdSAlfred Perlstein s->sc_prog = (rpcprog_t)prog; 3038360efbdSAlfred Perlstein s->sc_vers = (rpcvers_t)vers; 30499064799SGarrett Wollman s->sc_dispatch = dispatch; 30599064799SGarrett Wollman s->sc_next = svc_head; 30699064799SGarrett Wollman svc_head = s; 30799064799SGarrett Wollman pmap_it: 30899064799SGarrett Wollman /* now register the information with the local binder service */ 30999064799SGarrett Wollman if (protocol) { 31099064799SGarrett Wollman return (pmap_set(prog, vers, protocol, xprt->xp_port)); 31199064799SGarrett Wollman } 31299064799SGarrett Wollman return (TRUE); 31399064799SGarrett Wollman } 31499064799SGarrett Wollman 31599064799SGarrett Wollman /* 31699064799SGarrett Wollman * Remove a service program from the callout list. 31799064799SGarrett Wollman */ 31899064799SGarrett Wollman void 31999064799SGarrett Wollman svc_unregister(prog, vers) 32099064799SGarrett Wollman u_long prog; 32199064799SGarrett Wollman u_long vers; 32299064799SGarrett Wollman { 32399064799SGarrett Wollman struct svc_callout *prev; 3248360efbdSAlfred Perlstein struct svc_callout *s; 32599064799SGarrett Wollman 3268360efbdSAlfred Perlstein if ((s = svc_find((rpcprog_t)prog, (rpcvers_t)vers, &prev, NULL)) == 3278360efbdSAlfred Perlstein NULL) 32899064799SGarrett Wollman return; 3298360efbdSAlfred Perlstein if (prev == NULL) { 33099064799SGarrett Wollman svc_head = s->sc_next; 33199064799SGarrett Wollman } else { 33299064799SGarrett Wollman prev->sc_next = s->sc_next; 33399064799SGarrett Wollman } 3348360efbdSAlfred Perlstein s->sc_next = NULL; 3358360efbdSAlfred Perlstein mem_free(s, sizeof(struct svc_callout)); 33699064799SGarrett Wollman /* now unregister the information with the local binder service */ 33799064799SGarrett Wollman (void)pmap_unset(prog, vers); 33899064799SGarrett Wollman } 3398360efbdSAlfred Perlstein #endif /* PORTMAP */ 34099064799SGarrett Wollman 34199064799SGarrett Wollman /* 34299064799SGarrett Wollman * Search the callout list for a program number, return the callout 34399064799SGarrett Wollman * struct. 34499064799SGarrett Wollman */ 34599064799SGarrett Wollman static struct svc_callout * 3468360efbdSAlfred Perlstein svc_find(prog, vers, prev, netid) 3478360efbdSAlfred Perlstein rpcprog_t prog; 3488360efbdSAlfred Perlstein rpcvers_t vers; 34999064799SGarrett Wollman struct svc_callout **prev; 3508360efbdSAlfred Perlstein char *netid; 35199064799SGarrett Wollman { 3528360efbdSAlfred Perlstein struct svc_callout *s, *p; 35399064799SGarrett Wollman 3548360efbdSAlfred Perlstein assert(prev != NULL); 3558360efbdSAlfred Perlstein 3568360efbdSAlfred Perlstein p = NULL; 3578360efbdSAlfred Perlstein for (s = svc_head; s != NULL; s = s->sc_next) { 3588360efbdSAlfred Perlstein if (((s->sc_prog == prog) && (s->sc_vers == vers)) && 3598360efbdSAlfred Perlstein ((netid == NULL) || (s->sc_netid == NULL) || 3608360efbdSAlfred Perlstein (strcmp(netid, s->sc_netid) == 0))) 3618360efbdSAlfred Perlstein break; 36299064799SGarrett Wollman p = s; 36399064799SGarrett Wollman } 36499064799SGarrett Wollman *prev = p; 36599064799SGarrett Wollman return (s); 36699064799SGarrett Wollman } 36799064799SGarrett Wollman 36899064799SGarrett Wollman /* ******************* REPLY GENERATION ROUTINES ************ */ 36999064799SGarrett Wollman 37099064799SGarrett Wollman /* 37199064799SGarrett Wollman * Send a reply to an rpc request 37299064799SGarrett Wollman */ 37399064799SGarrett Wollman bool_t 37499064799SGarrett Wollman svc_sendreply(xprt, xdr_results, xdr_location) 3758360efbdSAlfred Perlstein SVCXPRT *xprt; 37699064799SGarrett Wollman xdrproc_t xdr_results; 377f249dbccSDag-Erling Smørgrav void * xdr_location; 37899064799SGarrett Wollman { 37999064799SGarrett Wollman struct rpc_msg rply; 38099064799SGarrett Wollman 3818360efbdSAlfred Perlstein assert(xprt != NULL); 3828360efbdSAlfred Perlstein 38399064799SGarrett Wollman rply.rm_direction = REPLY; 38499064799SGarrett Wollman rply.rm_reply.rp_stat = MSG_ACCEPTED; 38599064799SGarrett Wollman rply.acpted_rply.ar_verf = xprt->xp_verf; 38699064799SGarrett Wollman rply.acpted_rply.ar_stat = SUCCESS; 38799064799SGarrett Wollman rply.acpted_rply.ar_results.where = xdr_location; 38899064799SGarrett Wollman rply.acpted_rply.ar_results.proc = xdr_results; 38999064799SGarrett Wollman return (SVC_REPLY(xprt, &rply)); 39099064799SGarrett Wollman } 39199064799SGarrett Wollman 39299064799SGarrett Wollman /* 39399064799SGarrett Wollman * No procedure error reply 39499064799SGarrett Wollman */ 39599064799SGarrett Wollman void 39699064799SGarrett Wollman svcerr_noproc(xprt) 3978360efbdSAlfred Perlstein SVCXPRT *xprt; 39899064799SGarrett Wollman { 39999064799SGarrett Wollman struct rpc_msg rply; 40099064799SGarrett Wollman 4018360efbdSAlfred Perlstein assert(xprt != NULL); 4028360efbdSAlfred Perlstein 40399064799SGarrett Wollman rply.rm_direction = REPLY; 40499064799SGarrett Wollman rply.rm_reply.rp_stat = MSG_ACCEPTED; 40599064799SGarrett Wollman rply.acpted_rply.ar_verf = xprt->xp_verf; 40699064799SGarrett Wollman rply.acpted_rply.ar_stat = PROC_UNAVAIL; 40799064799SGarrett Wollman SVC_REPLY(xprt, &rply); 40899064799SGarrett Wollman } 40999064799SGarrett Wollman 41099064799SGarrett Wollman /* 41199064799SGarrett Wollman * Can't decode args error reply 41299064799SGarrett Wollman */ 41399064799SGarrett Wollman void 41499064799SGarrett Wollman svcerr_decode(xprt) 4158360efbdSAlfred Perlstein SVCXPRT *xprt; 41699064799SGarrett Wollman { 41799064799SGarrett Wollman struct rpc_msg rply; 41899064799SGarrett Wollman 4198360efbdSAlfred Perlstein assert(xprt != NULL); 4208360efbdSAlfred Perlstein 42199064799SGarrett Wollman rply.rm_direction = REPLY; 42299064799SGarrett Wollman rply.rm_reply.rp_stat = MSG_ACCEPTED; 42399064799SGarrett Wollman rply.acpted_rply.ar_verf = xprt->xp_verf; 42499064799SGarrett Wollman rply.acpted_rply.ar_stat = GARBAGE_ARGS; 42599064799SGarrett Wollman SVC_REPLY(xprt, &rply); 42699064799SGarrett Wollman } 42799064799SGarrett Wollman 42899064799SGarrett Wollman /* 42999064799SGarrett Wollman * Some system error 43099064799SGarrett Wollman */ 43199064799SGarrett Wollman void 43299064799SGarrett Wollman svcerr_systemerr(xprt) 4338360efbdSAlfred Perlstein SVCXPRT *xprt; 43499064799SGarrett Wollman { 43599064799SGarrett Wollman struct rpc_msg rply; 43699064799SGarrett Wollman 4378360efbdSAlfred Perlstein assert(xprt != NULL); 4388360efbdSAlfred Perlstein 43999064799SGarrett Wollman rply.rm_direction = REPLY; 44099064799SGarrett Wollman rply.rm_reply.rp_stat = MSG_ACCEPTED; 44199064799SGarrett Wollman rply.acpted_rply.ar_verf = xprt->xp_verf; 44299064799SGarrett Wollman rply.acpted_rply.ar_stat = SYSTEM_ERR; 44399064799SGarrett Wollman SVC_REPLY(xprt, &rply); 44499064799SGarrett Wollman } 44599064799SGarrett Wollman 4468360efbdSAlfred Perlstein #if 0 4478360efbdSAlfred Perlstein /* 4488360efbdSAlfred Perlstein * Tell RPC package to not complain about version errors to the client. This 4498360efbdSAlfred Perlstein * is useful when revving broadcast protocols that sit on a fixed address. 4508360efbdSAlfred Perlstein * There is really one (or should be only one) example of this kind of 4518360efbdSAlfred Perlstein * protocol: the portmapper (or rpc binder). 4528360efbdSAlfred Perlstein */ 4538360efbdSAlfred Perlstein void 4548360efbdSAlfred Perlstein __svc_versquiet_on(xprt) 4558360efbdSAlfred Perlstein SVCXPRT *xprt; 4568360efbdSAlfred Perlstein { 4578360efbdSAlfred Perlstein 4588f55a568SDoug Rabson SVC_EXT(xprt)->xp_flags |= SVC_VERSQUIET; 4598360efbdSAlfred Perlstein } 4608360efbdSAlfred Perlstein 4618360efbdSAlfred Perlstein void 4628360efbdSAlfred Perlstein __svc_versquiet_off(xprt) 4638360efbdSAlfred Perlstein SVCXPRT *xprt; 4648360efbdSAlfred Perlstein { 4658360efbdSAlfred Perlstein 4668f55a568SDoug Rabson SVC_EXT(xprt)->xp_flags &= ~SVC_VERSQUIET; 4678360efbdSAlfred Perlstein } 4688360efbdSAlfred Perlstein 4698360efbdSAlfred Perlstein void 4708360efbdSAlfred Perlstein svc_versquiet(xprt) 4718360efbdSAlfred Perlstein SVCXPRT *xprt; 4728360efbdSAlfred Perlstein { 4738360efbdSAlfred Perlstein __svc_versquiet_on(xprt); 4748360efbdSAlfred Perlstein } 4758360efbdSAlfred Perlstein 4768360efbdSAlfred Perlstein int 4778360efbdSAlfred Perlstein __svc_versquiet_get(xprt) 4788360efbdSAlfred Perlstein SVCXPRT *xprt; 4798360efbdSAlfred Perlstein { 4808f55a568SDoug Rabson 4818f55a568SDoug Rabson return (SVC_EXT(xprt)->xp_flags & SVC_VERSQUIET); 4828360efbdSAlfred Perlstein } 4838360efbdSAlfred Perlstein #endif 4848360efbdSAlfred Perlstein 48599064799SGarrett Wollman /* 48699064799SGarrett Wollman * Authentication error reply 48799064799SGarrett Wollman */ 48899064799SGarrett Wollman void 48999064799SGarrett Wollman svcerr_auth(xprt, why) 49099064799SGarrett Wollman SVCXPRT *xprt; 49199064799SGarrett Wollman enum auth_stat why; 49299064799SGarrett Wollman { 49399064799SGarrett Wollman struct rpc_msg rply; 49499064799SGarrett Wollman 4958360efbdSAlfred Perlstein assert(xprt != NULL); 4968360efbdSAlfred Perlstein 49799064799SGarrett Wollman rply.rm_direction = REPLY; 49899064799SGarrett Wollman rply.rm_reply.rp_stat = MSG_DENIED; 49999064799SGarrett Wollman rply.rjcted_rply.rj_stat = AUTH_ERROR; 50099064799SGarrett Wollman rply.rjcted_rply.rj_why = why; 50199064799SGarrett Wollman SVC_REPLY(xprt, &rply); 50299064799SGarrett Wollman } 50399064799SGarrett Wollman 50499064799SGarrett Wollman /* 50599064799SGarrett Wollman * Auth too weak error reply 50699064799SGarrett Wollman */ 50799064799SGarrett Wollman void 50899064799SGarrett Wollman svcerr_weakauth(xprt) 50999064799SGarrett Wollman SVCXPRT *xprt; 51099064799SGarrett Wollman { 51199064799SGarrett Wollman 5128360efbdSAlfred Perlstein assert(xprt != NULL); 5138360efbdSAlfred Perlstein 51499064799SGarrett Wollman svcerr_auth(xprt, AUTH_TOOWEAK); 51599064799SGarrett Wollman } 51699064799SGarrett Wollman 51799064799SGarrett Wollman /* 51899064799SGarrett Wollman * Program unavailable error reply 51999064799SGarrett Wollman */ 52099064799SGarrett Wollman void 52199064799SGarrett Wollman svcerr_noprog(xprt) 5228360efbdSAlfred Perlstein SVCXPRT *xprt; 52399064799SGarrett Wollman { 52499064799SGarrett Wollman struct rpc_msg rply; 52599064799SGarrett Wollman 5268360efbdSAlfred Perlstein assert(xprt != NULL); 5278360efbdSAlfred Perlstein 52899064799SGarrett Wollman rply.rm_direction = REPLY; 52999064799SGarrett Wollman rply.rm_reply.rp_stat = MSG_ACCEPTED; 53099064799SGarrett Wollman rply.acpted_rply.ar_verf = xprt->xp_verf; 53199064799SGarrett Wollman rply.acpted_rply.ar_stat = PROG_UNAVAIL; 53299064799SGarrett Wollman SVC_REPLY(xprt, &rply); 53399064799SGarrett Wollman } 53499064799SGarrett Wollman 53599064799SGarrett Wollman /* 53699064799SGarrett Wollman * Program version mismatch error reply 53799064799SGarrett Wollman */ 53899064799SGarrett Wollman void 53999064799SGarrett Wollman svcerr_progvers(xprt, low_vers, high_vers) 5408360efbdSAlfred Perlstein SVCXPRT *xprt; 5418360efbdSAlfred Perlstein rpcvers_t low_vers; 5428360efbdSAlfred Perlstein rpcvers_t high_vers; 54399064799SGarrett Wollman { 54499064799SGarrett Wollman struct rpc_msg rply; 54599064799SGarrett Wollman 5468360efbdSAlfred Perlstein assert(xprt != NULL); 5478360efbdSAlfred Perlstein 54899064799SGarrett Wollman rply.rm_direction = REPLY; 54999064799SGarrett Wollman rply.rm_reply.rp_stat = MSG_ACCEPTED; 55099064799SGarrett Wollman rply.acpted_rply.ar_verf = xprt->xp_verf; 55199064799SGarrett Wollman rply.acpted_rply.ar_stat = PROG_MISMATCH; 5528360efbdSAlfred Perlstein rply.acpted_rply.ar_vers.low = (u_int32_t)low_vers; 5538360efbdSAlfred Perlstein rply.acpted_rply.ar_vers.high = (u_int32_t)high_vers; 55499064799SGarrett Wollman SVC_REPLY(xprt, &rply); 55599064799SGarrett Wollman } 55699064799SGarrett Wollman 5578f55a568SDoug Rabson /* 5588f55a568SDoug Rabson * Allocate a new server transport structure. All fields are 5598f55a568SDoug Rabson * initialized to zero and xp_p3 is initialized to point at an 5608f55a568SDoug Rabson * extension structure to hold various flags and authentication 5618f55a568SDoug Rabson * parameters. 5628f55a568SDoug Rabson */ 5638f55a568SDoug Rabson SVCXPRT * 5648f55a568SDoug Rabson svc_xprt_alloc() 5658f55a568SDoug Rabson { 5668f55a568SDoug Rabson SVCXPRT *xprt; 5678f55a568SDoug Rabson SVCXPRT_EXT *ext; 5688f55a568SDoug Rabson 5698f55a568SDoug Rabson xprt = mem_alloc(sizeof(SVCXPRT)); 570*ed8ddc6eSKonstantin Belousov if (xprt == NULL) 571*ed8ddc6eSKonstantin Belousov return (NULL); 5728f55a568SDoug Rabson memset(xprt, 0, sizeof(SVCXPRT)); 5738f55a568SDoug Rabson ext = mem_alloc(sizeof(SVCXPRT_EXT)); 574*ed8ddc6eSKonstantin Belousov if (ext == NULL) { 575*ed8ddc6eSKonstantin Belousov mem_free(xprt, sizeof(SVCXPRT)); 576*ed8ddc6eSKonstantin Belousov return (NULL); 577*ed8ddc6eSKonstantin Belousov } 5788f55a568SDoug Rabson memset(ext, 0, sizeof(SVCXPRT_EXT)); 5798f55a568SDoug Rabson xprt->xp_p3 = ext; 5804efa8f3eSDoug Rabson ext->xp_auth.svc_ah_ops = &svc_auth_null_ops; 5818f55a568SDoug Rabson 5828f55a568SDoug Rabson return (xprt); 5838f55a568SDoug Rabson } 5848f55a568SDoug Rabson 5858f55a568SDoug Rabson /* 5868f55a568SDoug Rabson * Free a server transport structure. 5878f55a568SDoug Rabson */ 5888f55a568SDoug Rabson void 5898f55a568SDoug Rabson svc_xprt_free(xprt) 5908f55a568SDoug Rabson SVCXPRT *xprt; 5918f55a568SDoug Rabson { 5928f55a568SDoug Rabson 5938f55a568SDoug Rabson mem_free(xprt->xp_p3, sizeof(SVCXPRT_EXT)); 5948f55a568SDoug Rabson mem_free(xprt, sizeof(SVCXPRT)); 5958f55a568SDoug Rabson } 5968f55a568SDoug Rabson 59799064799SGarrett Wollman /* ******************* SERVER INPUT STUFF ******************* */ 59899064799SGarrett Wollman 59999064799SGarrett Wollman /* 60099064799SGarrett Wollman * Get server side input from some transport. 60199064799SGarrett Wollman * 60299064799SGarrett Wollman * Statement of authentication parameters management: 60399064799SGarrett Wollman * This function owns and manages all authentication parameters, specifically 60499064799SGarrett Wollman * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and 60599064799SGarrett Wollman * the "cooked" credentials (rqst->rq_clntcred). 60699064799SGarrett Wollman * However, this function does not know the structure of the cooked 60799064799SGarrett Wollman * credentials, so it make the following assumptions: 60899064799SGarrett Wollman * a) the structure is contiguous (no pointers), and 60999064799SGarrett Wollman * b) the cred structure size does not exceed RQCRED_SIZE bytes. 61099064799SGarrett Wollman * In all events, all three parameters are freed upon exit from this routine. 61199064799SGarrett Wollman * The storage is trivially management on the call stack in user land, but 61299064799SGarrett Wollman * is mallocated in kernel land. 61399064799SGarrett Wollman */ 61499064799SGarrett Wollman 61599064799SGarrett Wollman void 61699064799SGarrett Wollman svc_getreq(rdfds) 61799064799SGarrett Wollman int rdfds; 61899064799SGarrett Wollman { 61999064799SGarrett Wollman fd_set readfds; 62099064799SGarrett Wollman 62199064799SGarrett Wollman FD_ZERO(&readfds); 62299064799SGarrett Wollman readfds.fds_bits[0] = rdfds; 62399064799SGarrett Wollman svc_getreqset(&readfds); 62499064799SGarrett Wollman } 62599064799SGarrett Wollman 62699064799SGarrett Wollman void 62799064799SGarrett Wollman svc_getreqset(readfds) 62899064799SGarrett Wollman fd_set *readfds; 62999064799SGarrett Wollman { 6308360efbdSAlfred Perlstein int bit, fd; 6318360efbdSAlfred Perlstein fd_mask mask, *maskp; 6328360efbdSAlfred Perlstein int sock; 6338360efbdSAlfred Perlstein 6348360efbdSAlfred Perlstein assert(readfds != NULL); 6358360efbdSAlfred Perlstein 6368360efbdSAlfred Perlstein maskp = readfds->fds_bits; 6378360efbdSAlfred Perlstein for (sock = 0; sock < FD_SETSIZE; sock += NFDBITS) { 63855fdae4cSJohn Baldwin for (mask = *maskp++; (bit = ffsl(mask)) != 0; 63955fdae4cSJohn Baldwin mask ^= (1ul << (bit - 1))) { 6408360efbdSAlfred Perlstein /* sock has input waiting */ 6418360efbdSAlfred Perlstein fd = sock + bit - 1; 6428360efbdSAlfred Perlstein svc_getreq_common(fd); 6438360efbdSAlfred Perlstein } 6448360efbdSAlfred Perlstein } 645ae1e6afdSPeter Wemm } 646ae1e6afdSPeter Wemm 647ae1e6afdSPeter Wemm void 6488360efbdSAlfred Perlstein svc_getreq_common(fd) 6498360efbdSAlfred Perlstein int fd; 65099064799SGarrett Wollman { 6518360efbdSAlfred Perlstein SVCXPRT *xprt; 6528360efbdSAlfred Perlstein struct svc_req r; 65399064799SGarrett Wollman struct rpc_msg msg; 65499064799SGarrett Wollman int prog_found; 6558360efbdSAlfred Perlstein rpcvers_t low_vers; 6568360efbdSAlfred Perlstein rpcvers_t high_vers; 6578360efbdSAlfred Perlstein enum xprt_stat stat; 65899064799SGarrett Wollman char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE]; 6598360efbdSAlfred Perlstein 66099064799SGarrett Wollman msg.rm_call.cb_cred.oa_base = cred_area; 66199064799SGarrett Wollman msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); 66299064799SGarrett Wollman r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]); 66399064799SGarrett Wollman 6648360efbdSAlfred Perlstein rwlock_rdlock(&svc_fd_lock); 66508497c02SMartin Blapp xprt = __svc_xports[fd]; 6668360efbdSAlfred Perlstein rwlock_unlock(&svc_fd_lock); 667ae1e6afdSPeter Wemm if (xprt == NULL) 668ae1e6afdSPeter Wemm /* But do we control sock? */ 6698360efbdSAlfred Perlstein return; 67099064799SGarrett Wollman /* now receive msgs from xprtprt (support batch calls) */ 67199064799SGarrett Wollman do { 67299064799SGarrett Wollman if (SVC_RECV(xprt, &msg)) { 67399064799SGarrett Wollman 67499064799SGarrett Wollman /* now find the exported program and call it */ 6758360efbdSAlfred Perlstein struct svc_callout *s; 67699064799SGarrett Wollman enum auth_stat why; 67799064799SGarrett Wollman 67899064799SGarrett Wollman r.rq_xprt = xprt; 67999064799SGarrett Wollman r.rq_prog = msg.rm_call.cb_prog; 68099064799SGarrett Wollman r.rq_vers = msg.rm_call.cb_vers; 68199064799SGarrett Wollman r.rq_proc = msg.rm_call.cb_proc; 68299064799SGarrett Wollman r.rq_cred = msg.rm_call.cb_cred; 68399064799SGarrett Wollman /* first authenticate the message */ 68499064799SGarrett Wollman if ((why = _authenticate(&r, &msg)) != AUTH_OK) { 6858f55a568SDoug Rabson /* 6868f55a568SDoug Rabson * RPCSEC_GSS uses this return code 6878f55a568SDoug Rabson * for requests that form part of its 6888f55a568SDoug Rabson * context establishment protocol and 6898f55a568SDoug Rabson * should not be dispatched to the 6908f55a568SDoug Rabson * application. 6918f55a568SDoug Rabson */ 6928f55a568SDoug Rabson if (why != RPCSEC_GSS_NODISPATCH) 69399064799SGarrett Wollman svcerr_auth(xprt, why); 69499064799SGarrett Wollman goto call_done; 69599064799SGarrett Wollman } 69699064799SGarrett Wollman /* now match message with a registered service*/ 69799064799SGarrett Wollman prog_found = FALSE; 6988360efbdSAlfred Perlstein low_vers = (rpcvers_t) -1L; 6998360efbdSAlfred Perlstein high_vers = (rpcvers_t) 0L; 7008360efbdSAlfred Perlstein for (s = svc_head; s != NULL; s = s->sc_next) { 70199064799SGarrett Wollman if (s->sc_prog == r.rq_prog) { 70299064799SGarrett Wollman if (s->sc_vers == r.rq_vers) { 70399064799SGarrett Wollman (*s->sc_dispatch)(&r, xprt); 70499064799SGarrett Wollman goto call_done; 70599064799SGarrett Wollman } /* found correct version */ 70699064799SGarrett Wollman prog_found = TRUE; 70799064799SGarrett Wollman if (s->sc_vers < low_vers) 70899064799SGarrett Wollman low_vers = s->sc_vers; 70999064799SGarrett Wollman if (s->sc_vers > high_vers) 71099064799SGarrett Wollman high_vers = s->sc_vers; 71199064799SGarrett Wollman } /* found correct program */ 71299064799SGarrett Wollman } 71399064799SGarrett Wollman /* 71499064799SGarrett Wollman * if we got here, the program or version 71599064799SGarrett Wollman * is not served ... 71699064799SGarrett Wollman */ 71799064799SGarrett Wollman if (prog_found) 7188360efbdSAlfred Perlstein svcerr_progvers(xprt, low_vers, high_vers); 71999064799SGarrett Wollman else 72099064799SGarrett Wollman svcerr_noprog(xprt); 72199064799SGarrett Wollman /* Fall through to ... */ 72299064799SGarrett Wollman } 7238360efbdSAlfred Perlstein /* 7248360efbdSAlfred Perlstein * Check if the xprt has been disconnected in a 7258360efbdSAlfred Perlstein * recursive call in the service dispatch routine. 7268360efbdSAlfred Perlstein * If so, then break. 7278360efbdSAlfred Perlstein */ 7288360efbdSAlfred Perlstein rwlock_rdlock(&svc_fd_lock); 72908497c02SMartin Blapp if (xprt != __svc_xports[fd]) { 7308360efbdSAlfred Perlstein rwlock_unlock(&svc_fd_lock); 7318360efbdSAlfred Perlstein break; 7328360efbdSAlfred Perlstein } 7338360efbdSAlfred Perlstein rwlock_unlock(&svc_fd_lock); 73499064799SGarrett Wollman call_done: 73599064799SGarrett Wollman if ((stat = SVC_STAT(xprt)) == XPRT_DIED){ 73699064799SGarrett Wollman SVC_DESTROY(xprt); 73799064799SGarrett Wollman break; 73899064799SGarrett Wollman } 73999064799SGarrett Wollman } while (stat == XPRT_MOREREQS); 74099064799SGarrett Wollman } 7418360efbdSAlfred Perlstein 7428360efbdSAlfred Perlstein 7438360efbdSAlfred Perlstein void 7448360efbdSAlfred Perlstein svc_getreq_poll(pfdp, pollretval) 7458360efbdSAlfred Perlstein struct pollfd *pfdp; 7468360efbdSAlfred Perlstein int pollretval; 7478360efbdSAlfred Perlstein { 7488360efbdSAlfred Perlstein int i; 7498360efbdSAlfred Perlstein int fds_found; 7508360efbdSAlfred Perlstein 7518360efbdSAlfred Perlstein for (i = fds_found = 0; fds_found < pollretval; i++) { 7528360efbdSAlfred Perlstein struct pollfd *p = &pfdp[i]; 7538360efbdSAlfred Perlstein 7548360efbdSAlfred Perlstein if (p->revents) { 7558360efbdSAlfred Perlstein /* fd has input waiting */ 7568360efbdSAlfred Perlstein fds_found++; 7578360efbdSAlfred Perlstein /* 7588360efbdSAlfred Perlstein * We assume that this function is only called 7598360efbdSAlfred Perlstein * via someone _select()ing from svc_fdset or 7608360efbdSAlfred Perlstein * _poll()ing from svc_pollset[]. Thus it's safe 7618360efbdSAlfred Perlstein * to handle the POLLNVAL event by simply turning 7628360efbdSAlfred Perlstein * the corresponding bit off in svc_fdset. The 7638360efbdSAlfred Perlstein * svc_pollset[] array is derived from svc_fdset 7648360efbdSAlfred Perlstein * and so will also be updated eventually. 7658360efbdSAlfred Perlstein * 7668360efbdSAlfred Perlstein * XXX Should we do an xprt_unregister() instead? 7678360efbdSAlfred Perlstein */ 7688360efbdSAlfred Perlstein if (p->revents & POLLNVAL) { 7698360efbdSAlfred Perlstein rwlock_wrlock(&svc_fd_lock); 7708360efbdSAlfred Perlstein FD_CLR(p->fd, &svc_fdset); 7718360efbdSAlfred Perlstein rwlock_unlock(&svc_fd_lock); 7728360efbdSAlfred Perlstein } else 7738360efbdSAlfred Perlstein svc_getreq_common(p->fd); 7748360efbdSAlfred Perlstein } 77599064799SGarrett Wollman } 77699064799SGarrett Wollman } 77708497c02SMartin Blapp 77808497c02SMartin Blapp bool_t 77908497c02SMartin Blapp rpc_control(int what, void *arg) 78008497c02SMartin Blapp { 78108497c02SMartin Blapp int val; 78208497c02SMartin Blapp 78308497c02SMartin Blapp switch (what) { 78408497c02SMartin Blapp case RPC_SVC_CONNMAXREC_SET: 78508497c02SMartin Blapp val = *(int *)arg; 78608497c02SMartin Blapp if (val <= 0) 78708497c02SMartin Blapp return FALSE; 78808497c02SMartin Blapp __svc_maxrec = val; 78908497c02SMartin Blapp return TRUE; 79008497c02SMartin Blapp case RPC_SVC_CONNMAXREC_GET: 79108497c02SMartin Blapp *(int *)arg = __svc_maxrec; 79208497c02SMartin Blapp return TRUE; 79308497c02SMartin Blapp default: 79408497c02SMartin Blapp break; 79508497c02SMartin Blapp } 79608497c02SMartin Blapp return FALSE; 79708497c02SMartin Blapp } 798