svc.c revision 92990
174462Salfred/* $NetBSD: svc.c,v 1.21 2000/07/06 03:10:35 christos Exp $ */ 274462Salfred 31901Swollman/* 41901Swollman * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 51901Swollman * unrestricted use provided that this legend is included on all tape 61901Swollman * media and as a part of the software program in whole or part. Users 71901Swollman * may copy or modify Sun RPC without charge, but are not authorized 81901Swollman * to license or distribute it to anyone else except as part of a product or 91901Swollman * program developed by the user. 108870Srgrimes * 111901Swollman * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 121901Swollman * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 131901Swollman * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 148870Srgrimes * 151901Swollman * Sun RPC is provided with no support and without any obligation on the 161901Swollman * part of Sun Microsystems, Inc. to assist in its use, correction, 171901Swollman * modification or enhancement. 188870Srgrimes * 191901Swollman * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 201901Swollman * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 211901Swollman * OR ANY PART THEREOF. 228870Srgrimes * 231901Swollman * In no event will Sun Microsystems, Inc. be liable for any lost revenue 241901Swollman * or profits or other special, indirect and consequential damages, even if 251901Swollman * Sun has been advised of the possibility of such damages. 268870Srgrimes * 271901Swollman * Sun Microsystems, Inc. 281901Swollman * 2550 Garcia Avenue 291901Swollman * Mountain View, California 94043 301901Swollman */ 311901Swollman 328870Srgrimes#if defined(LIBC_SCCS) && !defined(lint) 3392990Sobrienstatic char *sccsid = "@(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro"; 3492990Sobrienstatic char *sccsid = "@(#)svc.c 2.4 88/08/11 4.0 RPCSRC"; 351901Swollman#endif 3692990Sobrien#include <sys/cdefs.h> 3792990Sobrien__FBSDID("$FreeBSD: head/lib/libc/rpc/svc.c 92990 2002-03-22 23:18:37Z obrien $"); 381901Swollman 391901Swollman/* 401901Swollman * svc.c, Server-side remote procedure call interface. 411901Swollman * 421901Swollman * There are two sets of procedures here. The xprt routines are 431901Swollman * for handling transport handles. The svc routines handle the 441901Swollman * list of service routines. 451901Swollman * 461901Swollman * Copyright (C) 1984, Sun Microsystems, Inc. 471901Swollman */ 481901Swollman 4975094Siedowse#include "namespace.h" 5074462Salfred#include "reentrant.h" 5174462Salfred#include <sys/types.h> 5274462Salfred#include <sys/poll.h> 5374462Salfred#include <assert.h> 5474462Salfred#include <errno.h> 5574462Salfred#include <stdlib.h> 5611666Sphk#include <string.h> 5774462Salfred 581901Swollman#include <rpc/rpc.h> 5974462Salfred#ifdef PORTMAP 601901Swollman#include <rpc/pmap_clnt.h> 6174462Salfred#endif /* PORTMAP */ 6274462Salfred#include "un-namespace.h" 631901Swollman 6474462Salfred#include "rpc_com.h" 6574462Salfred 661901Swollmanstatic SVCXPRT **xports; 671901Swollman 681901Swollman#define RQCRED_SIZE 400 /* this size is excessive */ 691901Swollman 7074462Salfred#define SVC_VERSQUIET 0x0001 /* keep quiet about vers mismatch */ 7174462Salfred#define version_keepquiet(xp) ((u_long)(xp)->xp_p3 & SVC_VERSQUIET) 7274462Salfred 7321087Speter#define max(a, b) (a > b ? a : b) 7416270Sjraynard 751901Swollman/* 761901Swollman * The services list 771901Swollman * Each entry represents a set of procedures (an rpc program). 781901Swollman * The dispatch routine takes request structs and runs the 791901Swollman * apropriate procedure. 801901Swollman */ 811901Swollmanstatic struct svc_callout { 821901Swollman struct svc_callout *sc_next; 8374462Salfred rpcprog_t sc_prog; 8474462Salfred rpcvers_t sc_vers; 8574462Salfred char *sc_netid; 8692905Sobrien void (*sc_dispatch)(struct svc_req *, SVCXPRT *); 871901Swollman} *svc_head; 881901Swollman 8974462Salfredextern rwlock_t svc_lock; 9074462Salfredextern rwlock_t svc_fd_lock; 911901Swollman 9292941Sobrienstatic struct svc_callout *svc_find(rpcprog_t, rpcvers_t, 9392941Sobrien struct svc_callout **, char *); 9421087Speter 951901Swollman/* *************** SVCXPRT related stuff **************** */ 961901Swollman 971901Swollman/* 981901Swollman * Activate a transport handle. 991901Swollman */ 1001901Swollmanvoid 1011901Swollmanxprt_register(xprt) 1021901Swollman SVCXPRT *xprt; 1031901Swollman{ 10474462Salfred int sock; 1051901Swollman 10674462Salfred assert(xprt != NULL); 10721087Speter 10874462Salfred sock = xprt->xp_fd; 10974462Salfred 11074462Salfred rwlock_wrlock(&svc_fd_lock); 11174462Salfred if (xports == NULL) { 11274462Salfred xports = (SVCXPRT **) 11374462Salfred mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *)); 11474462Salfred if (xports == NULL) 11574462Salfred return; 11674462Salfred memset(xports, '\0', FD_SETSIZE * sizeof(SVCXPRT *)); 1171901Swollman } 11874462Salfred if (sock < FD_SETSIZE) { 11974462Salfred xports[sock] = xprt; 1201901Swollman FD_SET(sock, &svc_fdset); 12174462Salfred svc_maxfd = max(svc_maxfd, sock); 1221901Swollman } 12374462Salfred rwlock_unlock(&svc_fd_lock); 1241901Swollman} 1251901Swollman 1261901Swollman/* 1278870Srgrimes * De-activate a transport handle. 1281901Swollman */ 1291901Swollmanvoid 13074462Salfredxprt_unregister(xprt) 1311901Swollman SVCXPRT *xprt; 1328870Srgrimes{ 13374462Salfred int sock; 1341901Swollman 13574462Salfred assert(xprt != NULL); 13674462Salfred 13774462Salfred sock = xprt->xp_fd; 13874462Salfred 13974462Salfred rwlock_wrlock(&svc_fd_lock); 14074462Salfred if ((sock < FD_SETSIZE) && (xports[sock] == xprt)) { 14174462Salfred xports[sock] = NULL; 14274462Salfred FD_CLR(sock, &svc_fdset); 14374462Salfred if (sock >= svc_maxfd) { 14474462Salfred for (svc_maxfd--; svc_maxfd>=0; svc_maxfd--) 14521087Speter if (xports[svc_maxfd]) 14621087Speter break; 14721087Speter } 1481901Swollman } 14974462Salfred rwlock_unlock(&svc_fd_lock); 1501901Swollman} 1511901Swollman 15274462Salfred/* 15374462Salfred * Add a service program to the callout list. 15474462Salfred * The dispatch routine will be called when a rpc request for this 15574462Salfred * program number comes in. 15674462Salfred */ 15774462Salfredbool_t 15874462Salfredsvc_reg(xprt, prog, vers, dispatch, nconf) 15974462Salfred SVCXPRT *xprt; 16074462Salfred const rpcprog_t prog; 16174462Salfred const rpcvers_t vers; 16292905Sobrien void (*dispatch)(struct svc_req *, SVCXPRT *); 16374462Salfred const struct netconfig *nconf; 16474462Salfred{ 16574462Salfred bool_t dummy; 16674462Salfred struct svc_callout *prev; 16774462Salfred struct svc_callout *s; 16874462Salfred struct netconfig *tnconf; 16974462Salfred char *netid = NULL; 17074462Salfred int flag = 0; 1711901Swollman 17274462Salfred/* VARIABLES PROTECTED BY svc_lock: s, prev, svc_head */ 17374462Salfred 17474462Salfred if (xprt->xp_netid) { 17574462Salfred netid = strdup(xprt->xp_netid); 17674462Salfred flag = 1; 17774462Salfred } else if (nconf && nconf->nc_netid) { 17874462Salfred netid = strdup(nconf->nc_netid); 17974462Salfred flag = 1; 18074462Salfred } else if ((tnconf = __rpcgettp(xprt->xp_fd)) != NULL) { 18174462Salfred netid = strdup(tnconf->nc_netid); 18274462Salfred flag = 1; 18374462Salfred freenetconfigent(tnconf); 18474462Salfred } /* must have been created with svc_raw_create */ 18574462Salfred if ((netid == NULL) && (flag == 1)) { 18674462Salfred return (FALSE); 18774462Salfred } 18874462Salfred 18974462Salfred rwlock_wrlock(&svc_lock); 19074462Salfred if ((s = svc_find(prog, vers, &prev, netid)) != NULL) { 19174462Salfred if (netid) 19274462Salfred free(netid); 19374462Salfred if (s->sc_dispatch == dispatch) 19474462Salfred goto rpcb_it; /* he is registering another xptr */ 19574462Salfred rwlock_unlock(&svc_lock); 19674462Salfred return (FALSE); 19774462Salfred } 19874462Salfred s = mem_alloc(sizeof (struct svc_callout)); 19974462Salfred if (s == NULL) { 20074462Salfred if (netid) 20174462Salfred free(netid); 20274462Salfred rwlock_unlock(&svc_lock); 20374462Salfred return (FALSE); 20474462Salfred } 20574462Salfred 20674462Salfred s->sc_prog = prog; 20774462Salfred s->sc_vers = vers; 20874462Salfred s->sc_dispatch = dispatch; 20974462Salfred s->sc_netid = netid; 21074462Salfred s->sc_next = svc_head; 21174462Salfred svc_head = s; 21274462Salfred 21374462Salfred if ((xprt->xp_netid == NULL) && (flag == 1) && netid) 21474462Salfred ((SVCXPRT *) xprt)->xp_netid = strdup(netid); 21574462Salfred 21674462Salfredrpcb_it: 21774462Salfred rwlock_unlock(&svc_lock); 21874462Salfred /* now register the information with the local binder service */ 21974462Salfred if (nconf) { 22074462Salfred /*LINTED const castaway*/ 22174462Salfred dummy = rpcb_set(prog, vers, (struct netconfig *) nconf, 22274462Salfred &((SVCXPRT *) xprt)->xp_ltaddr); 22374462Salfred return (dummy); 22474462Salfred } 22574462Salfred return (TRUE); 22674462Salfred} 22774462Salfred 22874462Salfred/* 22974462Salfred * Remove a service program from the callout list. 23074462Salfred */ 23174462Salfredvoid 23274462Salfredsvc_unreg(prog, vers) 23374462Salfred const rpcprog_t prog; 23474462Salfred const rpcvers_t vers; 23574462Salfred{ 23674462Salfred struct svc_callout *prev; 23774462Salfred struct svc_callout *s; 23874462Salfred 23974462Salfred /* unregister the information anyway */ 24074462Salfred (void) rpcb_unset(prog, vers, NULL); 24174462Salfred rwlock_wrlock(&svc_lock); 24274462Salfred while ((s = svc_find(prog, vers, &prev, NULL)) != NULL) { 24374462Salfred if (prev == NULL) { 24474462Salfred svc_head = s->sc_next; 24574462Salfred } else { 24674462Salfred prev->sc_next = s->sc_next; 24774462Salfred } 24874462Salfred s->sc_next = NULL; 24974462Salfred if (s->sc_netid) 25074462Salfred mem_free(s->sc_netid, sizeof (s->sc_netid) + 1); 25174462Salfred mem_free(s, sizeof (struct svc_callout)); 25274462Salfred } 25374462Salfred rwlock_unlock(&svc_lock); 25474462Salfred} 25574462Salfred 2561901Swollman/* ********************** CALLOUT list related stuff ************* */ 2571901Swollman 25874462Salfred#ifdef PORTMAP 2591901Swollman/* 2601901Swollman * Add a service program to the callout list. 2611901Swollman * The dispatch routine will be called when a rpc request for this 2621901Swollman * program number comes in. 2631901Swollman */ 2641901Swollmanbool_t 2651901Swollmansvc_register(xprt, prog, vers, dispatch, protocol) 2661901Swollman SVCXPRT *xprt; 2671901Swollman u_long prog; 2681901Swollman u_long vers; 26992905Sobrien void (*dispatch)(struct svc_req *, SVCXPRT *); 2701901Swollman int protocol; 2711901Swollman{ 2721901Swollman struct svc_callout *prev; 27374462Salfred struct svc_callout *s; 2741901Swollman 27574462Salfred assert(xprt != NULL); 27674462Salfred assert(dispatch != NULL); 27774462Salfred 27874462Salfred if ((s = svc_find((rpcprog_t)prog, (rpcvers_t)vers, &prev, NULL)) != 27974462Salfred NULL) { 2801901Swollman if (s->sc_dispatch == dispatch) 2811901Swollman goto pmap_it; /* he is registering another xptr */ 2821901Swollman return (FALSE); 2831901Swollman } 28474462Salfred s = mem_alloc(sizeof(struct svc_callout)); 28574462Salfred if (s == NULL) { 2861901Swollman return (FALSE); 2871901Swollman } 28874462Salfred s->sc_prog = (rpcprog_t)prog; 28974462Salfred s->sc_vers = (rpcvers_t)vers; 2901901Swollman s->sc_dispatch = dispatch; 2911901Swollman s->sc_next = svc_head; 2921901Swollman svc_head = s; 2931901Swollmanpmap_it: 2941901Swollman /* now register the information with the local binder service */ 2951901Swollman if (protocol) { 2961901Swollman return (pmap_set(prog, vers, protocol, xprt->xp_port)); 2971901Swollman } 2981901Swollman return (TRUE); 2991901Swollman} 3001901Swollman 3011901Swollman/* 3021901Swollman * Remove a service program from the callout list. 3031901Swollman */ 3041901Swollmanvoid 3051901Swollmansvc_unregister(prog, vers) 3061901Swollman u_long prog; 3071901Swollman u_long vers; 3081901Swollman{ 3091901Swollman struct svc_callout *prev; 31074462Salfred struct svc_callout *s; 3111901Swollman 31274462Salfred if ((s = svc_find((rpcprog_t)prog, (rpcvers_t)vers, &prev, NULL)) == 31374462Salfred NULL) 3141901Swollman return; 31574462Salfred if (prev == NULL) { 3161901Swollman svc_head = s->sc_next; 3171901Swollman } else { 3181901Swollman prev->sc_next = s->sc_next; 3191901Swollman } 32074462Salfred s->sc_next = NULL; 32174462Salfred mem_free(s, sizeof(struct svc_callout)); 3221901Swollman /* now unregister the information with the local binder service */ 3231901Swollman (void)pmap_unset(prog, vers); 3241901Swollman} 32574462Salfred#endif /* PORTMAP */ 3261901Swollman 3271901Swollman/* 3281901Swollman * Search the callout list for a program number, return the callout 3291901Swollman * struct. 3301901Swollman */ 3311901Swollmanstatic struct svc_callout * 33274462Salfredsvc_find(prog, vers, prev, netid) 33374462Salfred rpcprog_t prog; 33474462Salfred rpcvers_t vers; 3351901Swollman struct svc_callout **prev; 33674462Salfred char *netid; 3371901Swollman{ 33874462Salfred struct svc_callout *s, *p; 3391901Swollman 34074462Salfred assert(prev != NULL); 34174462Salfred 34274462Salfred p = NULL; 34374462Salfred for (s = svc_head; s != NULL; s = s->sc_next) { 34474462Salfred if (((s->sc_prog == prog) && (s->sc_vers == vers)) && 34574462Salfred ((netid == NULL) || (s->sc_netid == NULL) || 34674462Salfred (strcmp(netid, s->sc_netid) == 0))) 34774462Salfred break; 3481901Swollman p = s; 3491901Swollman } 3501901Swollman *prev = p; 3511901Swollman return (s); 3521901Swollman} 3531901Swollman 3541901Swollman/* ******************* REPLY GENERATION ROUTINES ************ */ 3551901Swollman 3561901Swollman/* 3571901Swollman * Send a reply to an rpc request 3581901Swollman */ 3591901Swollmanbool_t 3601901Swollmansvc_sendreply(xprt, xdr_results, xdr_location) 36174462Salfred SVCXPRT *xprt; 3621901Swollman xdrproc_t xdr_results; 3631901Swollman caddr_t xdr_location; 3641901Swollman{ 36574462Salfred struct rpc_msg rply; 3661901Swollman 36774462Salfred assert(xprt != NULL); 36874462Salfred 36974462Salfred rply.rm_direction = REPLY; 37074462Salfred rply.rm_reply.rp_stat = MSG_ACCEPTED; 37174462Salfred rply.acpted_rply.ar_verf = xprt->xp_verf; 3721901Swollman rply.acpted_rply.ar_stat = SUCCESS; 3731901Swollman rply.acpted_rply.ar_results.where = xdr_location; 3741901Swollman rply.acpted_rply.ar_results.proc = xdr_results; 37574462Salfred return (SVC_REPLY(xprt, &rply)); 3761901Swollman} 3771901Swollman 3781901Swollman/* 3791901Swollman * No procedure error reply 3801901Swollman */ 3811901Swollmanvoid 3821901Swollmansvcerr_noproc(xprt) 38374462Salfred SVCXPRT *xprt; 3841901Swollman{ 3851901Swollman struct rpc_msg rply; 3861901Swollman 38774462Salfred assert(xprt != NULL); 38874462Salfred 3891901Swollman rply.rm_direction = REPLY; 3901901Swollman rply.rm_reply.rp_stat = MSG_ACCEPTED; 3911901Swollman rply.acpted_rply.ar_verf = xprt->xp_verf; 3921901Swollman rply.acpted_rply.ar_stat = PROC_UNAVAIL; 3931901Swollman SVC_REPLY(xprt, &rply); 3941901Swollman} 3951901Swollman 3961901Swollman/* 3971901Swollman * Can't decode args error reply 3981901Swollman */ 3991901Swollmanvoid 4001901Swollmansvcerr_decode(xprt) 40174462Salfred SVCXPRT *xprt; 4021901Swollman{ 40374462Salfred struct rpc_msg rply; 4041901Swollman 40574462Salfred assert(xprt != NULL); 40674462Salfred 40774462Salfred rply.rm_direction = REPLY; 40874462Salfred rply.rm_reply.rp_stat = MSG_ACCEPTED; 4091901Swollman rply.acpted_rply.ar_verf = xprt->xp_verf; 4101901Swollman rply.acpted_rply.ar_stat = GARBAGE_ARGS; 41174462Salfred SVC_REPLY(xprt, &rply); 4121901Swollman} 4131901Swollman 4141901Swollman/* 4151901Swollman * Some system error 4161901Swollman */ 4171901Swollmanvoid 4181901Swollmansvcerr_systemerr(xprt) 41974462Salfred SVCXPRT *xprt; 4201901Swollman{ 42174462Salfred struct rpc_msg rply; 4221901Swollman 42374462Salfred assert(xprt != NULL); 42474462Salfred 42574462Salfred rply.rm_direction = REPLY; 42674462Salfred rply.rm_reply.rp_stat = MSG_ACCEPTED; 4271901Swollman rply.acpted_rply.ar_verf = xprt->xp_verf; 4281901Swollman rply.acpted_rply.ar_stat = SYSTEM_ERR; 42974462Salfred SVC_REPLY(xprt, &rply); 4301901Swollman} 4311901Swollman 43274462Salfred#if 0 4331901Swollman/* 43474462Salfred * Tell RPC package to not complain about version errors to the client. This 43574462Salfred * is useful when revving broadcast protocols that sit on a fixed address. 43674462Salfred * There is really one (or should be only one) example of this kind of 43774462Salfred * protocol: the portmapper (or rpc binder). 43874462Salfred */ 43974462Salfredvoid 44074462Salfred__svc_versquiet_on(xprt) 44174462Salfred SVCXPRT *xprt; 44274462Salfred{ 44374462Salfred u_long tmp; 44474462Salfred 44574462Salfred tmp = ((u_long) xprt->xp_p3) | SVC_VERSQUIET; 44674462Salfred xprt->xp_p3 = (caddr_t) tmp; 44774462Salfred} 44874462Salfred 44974462Salfredvoid 45074462Salfred__svc_versquiet_off(xprt) 45174462Salfred SVCXPRT *xprt; 45274462Salfred{ 45374462Salfred u_long tmp; 45474462Salfred 45574462Salfred tmp = ((u_long) xprt->xp_p3) & ~SVC_VERSQUIET; 45674462Salfred xprt->xp_p3 = (caddr_t) tmp; 45774462Salfred} 45874462Salfred 45974462Salfredvoid 46074462Salfredsvc_versquiet(xprt) 46174462Salfred SVCXPRT *xprt; 46274462Salfred{ 46374462Salfred __svc_versquiet_on(xprt); 46474462Salfred} 46574462Salfred 46674462Salfredint 46774462Salfred__svc_versquiet_get(xprt) 46874462Salfred SVCXPRT *xprt; 46974462Salfred{ 47074462Salfred return ((int) xprt->xp_p3) & SVC_VERSQUIET; 47174462Salfred} 47274462Salfred#endif 47374462Salfred 47474462Salfred/* 4751901Swollman * Authentication error reply 4761901Swollman */ 4771901Swollmanvoid 4781901Swollmansvcerr_auth(xprt, why) 4791901Swollman SVCXPRT *xprt; 4801901Swollman enum auth_stat why; 4811901Swollman{ 4821901Swollman struct rpc_msg rply; 4831901Swollman 48474462Salfred assert(xprt != NULL); 48574462Salfred 4861901Swollman rply.rm_direction = REPLY; 4871901Swollman rply.rm_reply.rp_stat = MSG_DENIED; 4881901Swollman rply.rjcted_rply.rj_stat = AUTH_ERROR; 4891901Swollman rply.rjcted_rply.rj_why = why; 4901901Swollman SVC_REPLY(xprt, &rply); 4911901Swollman} 4921901Swollman 4931901Swollman/* 4941901Swollman * Auth too weak error reply 4951901Swollman */ 4961901Swollmanvoid 4971901Swollmansvcerr_weakauth(xprt) 4981901Swollman SVCXPRT *xprt; 4991901Swollman{ 5001901Swollman 50174462Salfred assert(xprt != NULL); 50274462Salfred 5031901Swollman svcerr_auth(xprt, AUTH_TOOWEAK); 5041901Swollman} 5051901Swollman 5061901Swollman/* 5071901Swollman * Program unavailable error reply 5081901Swollman */ 50974462Salfredvoid 5101901Swollmansvcerr_noprog(xprt) 51174462Salfred SVCXPRT *xprt; 5121901Swollman{ 51374462Salfred struct rpc_msg rply; 5141901Swollman 51574462Salfred assert(xprt != NULL); 51674462Salfred 51774462Salfred rply.rm_direction = REPLY; 51874462Salfred rply.rm_reply.rp_stat = MSG_ACCEPTED; 51974462Salfred rply.acpted_rply.ar_verf = xprt->xp_verf; 5201901Swollman rply.acpted_rply.ar_stat = PROG_UNAVAIL; 5211901Swollman SVC_REPLY(xprt, &rply); 5221901Swollman} 5231901Swollman 5241901Swollman/* 5251901Swollman * Program version mismatch error reply 5261901Swollman */ 52774462Salfredvoid 5281901Swollmansvcerr_progvers(xprt, low_vers, high_vers) 52974462Salfred SVCXPRT *xprt; 53074462Salfred rpcvers_t low_vers; 53174462Salfred rpcvers_t high_vers; 5321901Swollman{ 5331901Swollman struct rpc_msg rply; 5341901Swollman 53574462Salfred assert(xprt != NULL); 53674462Salfred 5371901Swollman rply.rm_direction = REPLY; 5381901Swollman rply.rm_reply.rp_stat = MSG_ACCEPTED; 5391901Swollman rply.acpted_rply.ar_verf = xprt->xp_verf; 5401901Swollman rply.acpted_rply.ar_stat = PROG_MISMATCH; 54174462Salfred rply.acpted_rply.ar_vers.low = (u_int32_t)low_vers; 54274462Salfred rply.acpted_rply.ar_vers.high = (u_int32_t)high_vers; 5431901Swollman SVC_REPLY(xprt, &rply); 5441901Swollman} 5451901Swollman 5461901Swollman/* ******************* SERVER INPUT STUFF ******************* */ 5471901Swollman 5481901Swollman/* 5491901Swollman * Get server side input from some transport. 5501901Swollman * 5511901Swollman * Statement of authentication parameters management: 5521901Swollman * This function owns and manages all authentication parameters, specifically 5531901Swollman * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and 5541901Swollman * the "cooked" credentials (rqst->rq_clntcred). 5551901Swollman * However, this function does not know the structure of the cooked 5568870Srgrimes * credentials, so it make the following assumptions: 5571901Swollman * a) the structure is contiguous (no pointers), and 5588870Srgrimes * b) the cred structure size does not exceed RQCRED_SIZE bytes. 5591901Swollman * In all events, all three parameters are freed upon exit from this routine. 5601901Swollman * The storage is trivially management on the call stack in user land, but 5611901Swollman * is mallocated in kernel land. 5621901Swollman */ 5631901Swollman 5641901Swollmanvoid 5651901Swollmansvc_getreq(rdfds) 5661901Swollman int rdfds; 5671901Swollman{ 5681901Swollman fd_set readfds; 5691901Swollman 5701901Swollman FD_ZERO(&readfds); 5711901Swollman readfds.fds_bits[0] = rdfds; 5721901Swollman svc_getreqset(&readfds); 5731901Swollman} 5741901Swollman 5751901Swollmanvoid 5761901Swollmansvc_getreqset(readfds) 5771901Swollman fd_set *readfds; 5781901Swollman{ 57974462Salfred int bit, fd; 58074462Salfred fd_mask mask, *maskp; 58174462Salfred int sock; 58274462Salfred 58374462Salfred assert(readfds != NULL); 58474462Salfred 58574462Salfred maskp = readfds->fds_bits; 58674462Salfred for (sock = 0; sock < FD_SETSIZE; sock += NFDBITS) { 58774462Salfred for (mask = *maskp++; (bit = ffs(mask)) != 0; 58874462Salfred mask ^= (1 << (bit - 1))) { 58974462Salfred /* sock has input waiting */ 59074462Salfred fd = sock + bit - 1; 59174462Salfred svc_getreq_common(fd); 59274462Salfred } 59374462Salfred } 59421087Speter} 59521087Speter 59621087Spetervoid 59774462Salfredsvc_getreq_common(fd) 59874462Salfred int fd; 5991901Swollman{ 60074462Salfred SVCXPRT *xprt; 60174462Salfred struct svc_req r; 6021901Swollman struct rpc_msg msg; 6031901Swollman int prog_found; 60474462Salfred rpcvers_t low_vers; 60574462Salfred rpcvers_t high_vers; 60674462Salfred enum xprt_stat stat; 6071901Swollman char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE]; 60874462Salfred 6091901Swollman msg.rm_call.cb_cred.oa_base = cred_area; 6101901Swollman msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); 6111901Swollman r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]); 6121901Swollman 61374462Salfred rwlock_rdlock(&svc_fd_lock); 61474462Salfred xprt = xports[fd]; 61574462Salfred rwlock_unlock(&svc_fd_lock); 61674462Salfred if (xprt == NULL) 61774462Salfred /* But do we control sock? */ 61874462Salfred return; 61974462Salfred /* now receive msgs from xprtprt (support batch calls) */ 62074462Salfred do { 62174462Salfred if (SVC_RECV(xprt, &msg)) { 6221901Swollman 62374462Salfred /* now find the exported program and call it */ 62474462Salfred struct svc_callout *s; 62574462Salfred enum auth_stat why; 6261901Swollman 62774462Salfred r.rq_xprt = xprt; 62874462Salfred r.rq_prog = msg.rm_call.cb_prog; 62974462Salfred r.rq_vers = msg.rm_call.cb_vers; 63074462Salfred r.rq_proc = msg.rm_call.cb_proc; 63174462Salfred r.rq_cred = msg.rm_call.cb_cred; 63274462Salfred /* first authenticate the message */ 63374462Salfred if ((why = _authenticate(&r, &msg)) != AUTH_OK) { 63474462Salfred svcerr_auth(xprt, why); 63574462Salfred goto call_done; 6361901Swollman } 63774462Salfred /* now match message with a registered service*/ 63874462Salfred prog_found = FALSE; 63974462Salfred low_vers = (rpcvers_t) -1L; 64074462Salfred high_vers = (rpcvers_t) 0L; 64174462Salfred for (s = svc_head; s != NULL; s = s->sc_next) { 64274462Salfred if (s->sc_prog == r.rq_prog) { 64374462Salfred if (s->sc_vers == r.rq_vers) { 64474462Salfred (*s->sc_dispatch)(&r, xprt); 64574462Salfred goto call_done; 64674462Salfred } /* found correct version */ 64774462Salfred prog_found = TRUE; 64874462Salfred if (s->sc_vers < low_vers) 64974462Salfred low_vers = s->sc_vers; 65074462Salfred if (s->sc_vers > high_vers) 65174462Salfred high_vers = s->sc_vers; 65274462Salfred } /* found correct program */ 6531901Swollman } 65474462Salfred /* 65574462Salfred * if we got here, the program or version 65674462Salfred * is not served ... 65774462Salfred */ 65874462Salfred if (prog_found) 65974462Salfred svcerr_progvers(xprt, low_vers, high_vers); 66074462Salfred else 66174462Salfred svcerr_noprog(xprt); 66274462Salfred /* Fall through to ... */ 66374462Salfred } 66474462Salfred /* 66574462Salfred * Check if the xprt has been disconnected in a 66674462Salfred * recursive call in the service dispatch routine. 66774462Salfred * If so, then break. 66874462Salfred */ 66974462Salfred rwlock_rdlock(&svc_fd_lock); 67074462Salfred if (xprt != xports[fd]) { 67174462Salfred rwlock_unlock(&svc_fd_lock); 67274462Salfred break; 67374462Salfred } 67474462Salfred rwlock_unlock(&svc_fd_lock); 67574462Salfredcall_done: 67674462Salfred if ((stat = SVC_STAT(xprt)) == XPRT_DIED){ 67774462Salfred SVC_DESTROY(xprt); 67874462Salfred break; 67974462Salfred } 68074462Salfred } while (stat == XPRT_MOREREQS); 68174462Salfred} 68274462Salfred 68374462Salfred 68474462Salfredvoid 68574462Salfredsvc_getreq_poll(pfdp, pollretval) 68674462Salfred struct pollfd *pfdp; 68774462Salfred int pollretval; 68874462Salfred{ 68974462Salfred int i; 69074462Salfred int fds_found; 69174462Salfred 69274462Salfred for (i = fds_found = 0; fds_found < pollretval; i++) { 69374462Salfred struct pollfd *p = &pfdp[i]; 69474462Salfred 69574462Salfred if (p->revents) { 69674462Salfred /* fd has input waiting */ 69774462Salfred fds_found++; 69874462Salfred /* 69974462Salfred * We assume that this function is only called 70074462Salfred * via someone _select()ing from svc_fdset or 70174462Salfred * _poll()ing from svc_pollset[]. Thus it's safe 70274462Salfred * to handle the POLLNVAL event by simply turning 70374462Salfred * the corresponding bit off in svc_fdset. The 70474462Salfred * svc_pollset[] array is derived from svc_fdset 70574462Salfred * and so will also be updated eventually. 70674462Salfred * 70774462Salfred * XXX Should we do an xprt_unregister() instead? 70874462Salfred */ 70974462Salfred if (p->revents & POLLNVAL) { 71074462Salfred rwlock_wrlock(&svc_fd_lock); 71174462Salfred FD_CLR(p->fd, &svc_fdset); 71274462Salfred rwlock_unlock(&svc_fd_lock); 71374462Salfred } else 71474462Salfred svc_getreq_common(p->fd); 71574462Salfred } 7161901Swollman } 7171901Swollman} 718