svc.c revision 74462
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) 331901Swollman/*static char *sccsid = "from: @(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro";*/ 341901Swollman/*static char *sccsid = "from: @(#)svc.c 2.4 88/08/11 4.0 RPCSRC";*/ 3550476Speterstatic char *rcsid = "$FreeBSD: head/lib/libc/rpc/svc.c 74462 2001-03-19 12:50:13Z alfred $"; 361901Swollman#endif 371901Swollman 381901Swollman/* 391901Swollman * svc.c, Server-side remote procedure call interface. 401901Swollman * 411901Swollman * There are two sets of procedures here. The xprt routines are 421901Swollman * for handling transport handles. The svc routines handle the 431901Swollman * list of service routines. 441901Swollman * 451901Swollman * Copyright (C) 1984, Sun Microsystems, Inc. 461901Swollman */ 471901Swollman 4874462Salfred#include "reentrant.h" 4974462Salfred#include "namespace.h" 5074462Salfred#include <sys/types.h> 5174462Salfred#include <sys/poll.h> 5274462Salfred#include <assert.h> 5374462Salfred#include <errno.h> 5474462Salfred#include <stdlib.h> 5511666Sphk#include <string.h> 5674462Salfred 571901Swollman#include <rpc/rpc.h> 5874462Salfred#ifdef PORTMAP 591901Swollman#include <rpc/pmap_clnt.h> 6074462Salfred#endif /* PORTMAP */ 6174462Salfred#include "un-namespace.h" 621901Swollman 6374462Salfred#include "rpc_com.h" 6474462Salfred 651901Swollmanstatic SVCXPRT **xports; 661901Swollman 671901Swollman#define RQCRED_SIZE 400 /* this size is excessive */ 681901Swollman 6974462Salfred#define SVC_VERSQUIET 0x0001 /* keep quiet about vers mismatch */ 7074462Salfred#define version_keepquiet(xp) ((u_long)(xp)->xp_p3 & SVC_VERSQUIET) 7174462Salfred 7221087Speter#define max(a, b) (a > b ? a : b) 7316270Sjraynard 741901Swollman/* 751901Swollman * The services list 761901Swollman * Each entry represents a set of procedures (an rpc program). 771901Swollman * The dispatch routine takes request structs and runs the 781901Swollman * apropriate procedure. 791901Swollman */ 801901Swollmanstatic struct svc_callout { 811901Swollman struct svc_callout *sc_next; 8274462Salfred rpcprog_t sc_prog; 8374462Salfred rpcvers_t sc_vers; 8474462Salfred char *sc_netid; 8574462Salfred void (*sc_dispatch) __P((struct svc_req *, SVCXPRT *)); 861901Swollman} *svc_head; 871901Swollman 8874462Salfredextern rwlock_t svc_lock; 8974462Salfredextern rwlock_t svc_fd_lock; 901901Swollman 9174462Salfredstatic struct svc_callout *svc_find __P((rpcprog_t, rpcvers_t, 9274462Salfred struct svc_callout **, char *)); 9321087Speter 941901Swollman/* *************** SVCXPRT related stuff **************** */ 951901Swollman 961901Swollman/* 971901Swollman * Activate a transport handle. 981901Swollman */ 991901Swollmanvoid 1001901Swollmanxprt_register(xprt) 1011901Swollman SVCXPRT *xprt; 1021901Swollman{ 10374462Salfred int sock; 1041901Swollman 10574462Salfred assert(xprt != NULL); 10621087Speter 10774462Salfred sock = xprt->xp_fd; 10874462Salfred 10974462Salfred rwlock_wrlock(&svc_fd_lock); 11074462Salfred if (xports == NULL) { 11174462Salfred xports = (SVCXPRT **) 11274462Salfred mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *)); 11374462Salfred if (xports == NULL) 11474462Salfred return; 11574462Salfred memset(xports, '\0', FD_SETSIZE * sizeof(SVCXPRT *)); 1161901Swollman } 11774462Salfred if (sock < FD_SETSIZE) { 11874462Salfred xports[sock] = xprt; 1191901Swollman FD_SET(sock, &svc_fdset); 12074462Salfred svc_maxfd = max(svc_maxfd, sock); 1211901Swollman } 12274462Salfred rwlock_unlock(&svc_fd_lock); 1231901Swollman} 1241901Swollman 1251901Swollman/* 1268870Srgrimes * De-activate a transport handle. 1271901Swollman */ 1281901Swollmanvoid 12974462Salfredxprt_unregister(xprt) 1301901Swollman SVCXPRT *xprt; 1318870Srgrimes{ 13274462Salfred int sock; 1331901Swollman 13474462Salfred assert(xprt != NULL); 13574462Salfred 13674462Salfred sock = xprt->xp_fd; 13774462Salfred 13874462Salfred rwlock_wrlock(&svc_fd_lock); 13974462Salfred if ((sock < FD_SETSIZE) && (xports[sock] == xprt)) { 14074462Salfred xports[sock] = NULL; 14174462Salfred FD_CLR(sock, &svc_fdset); 14274462Salfred if (sock >= svc_maxfd) { 14374462Salfred for (svc_maxfd--; svc_maxfd>=0; svc_maxfd--) 14421087Speter if (xports[svc_maxfd]) 14521087Speter break; 14621087Speter } 1471901Swollman } 14874462Salfred rwlock_unlock(&svc_fd_lock); 1491901Swollman} 1501901Swollman 15174462Salfred/* 15274462Salfred * Add a service program to the callout list. 15374462Salfred * The dispatch routine will be called when a rpc request for this 15474462Salfred * program number comes in. 15574462Salfred */ 15674462Salfredbool_t 15774462Salfredsvc_reg(xprt, prog, vers, dispatch, nconf) 15874462Salfred SVCXPRT *xprt; 15974462Salfred const rpcprog_t prog; 16074462Salfred const rpcvers_t vers; 16174462Salfred void (*dispatch) __P((struct svc_req *, SVCXPRT *)); 16274462Salfred const struct netconfig *nconf; 16374462Salfred{ 16474462Salfred bool_t dummy; 16574462Salfred struct svc_callout *prev; 16674462Salfred struct svc_callout *s; 16774462Salfred struct netconfig *tnconf; 16874462Salfred char *netid = NULL; 16974462Salfred int flag = 0; 1701901Swollman 17174462Salfred/* VARIABLES PROTECTED BY svc_lock: s, prev, svc_head */ 17274462Salfred 17374462Salfred if (xprt->xp_netid) { 17474462Salfred netid = strdup(xprt->xp_netid); 17574462Salfred flag = 1; 17674462Salfred } else if (nconf && nconf->nc_netid) { 17774462Salfred netid = strdup(nconf->nc_netid); 17874462Salfred flag = 1; 17974462Salfred } else if ((tnconf = __rpcgettp(xprt->xp_fd)) != NULL) { 18074462Salfred netid = strdup(tnconf->nc_netid); 18174462Salfred flag = 1; 18274462Salfred freenetconfigent(tnconf); 18374462Salfred } /* must have been created with svc_raw_create */ 18474462Salfred if ((netid == NULL) && (flag == 1)) { 18574462Salfred return (FALSE); 18674462Salfred } 18774462Salfred 18874462Salfred rwlock_wrlock(&svc_lock); 18974462Salfred if ((s = svc_find(prog, vers, &prev, netid)) != NULL) { 19074462Salfred if (netid) 19174462Salfred free(netid); 19274462Salfred if (s->sc_dispatch == dispatch) 19374462Salfred goto rpcb_it; /* he is registering another xptr */ 19474462Salfred rwlock_unlock(&svc_lock); 19574462Salfred return (FALSE); 19674462Salfred } 19774462Salfred s = mem_alloc(sizeof (struct svc_callout)); 19874462Salfred if (s == NULL) { 19974462Salfred if (netid) 20074462Salfred free(netid); 20174462Salfred rwlock_unlock(&svc_lock); 20274462Salfred return (FALSE); 20374462Salfred } 20474462Salfred 20574462Salfred s->sc_prog = prog; 20674462Salfred s->sc_vers = vers; 20774462Salfred s->sc_dispatch = dispatch; 20874462Salfred s->sc_netid = netid; 20974462Salfred s->sc_next = svc_head; 21074462Salfred svc_head = s; 21174462Salfred 21274462Salfred if ((xprt->xp_netid == NULL) && (flag == 1) && netid) 21374462Salfred ((SVCXPRT *) xprt)->xp_netid = strdup(netid); 21474462Salfred 21574462Salfredrpcb_it: 21674462Salfred rwlock_unlock(&svc_lock); 21774462Salfred /* now register the information with the local binder service */ 21874462Salfred if (nconf) { 21974462Salfred /*LINTED const castaway*/ 22074462Salfred dummy = rpcb_set(prog, vers, (struct netconfig *) nconf, 22174462Salfred &((SVCXPRT *) xprt)->xp_ltaddr); 22274462Salfred return (dummy); 22374462Salfred } 22474462Salfred return (TRUE); 22574462Salfred} 22674462Salfred 22774462Salfred/* 22874462Salfred * Remove a service program from the callout list. 22974462Salfred */ 23074462Salfredvoid 23174462Salfredsvc_unreg(prog, vers) 23274462Salfred const rpcprog_t prog; 23374462Salfred const rpcvers_t vers; 23474462Salfred{ 23574462Salfred struct svc_callout *prev; 23674462Salfred struct svc_callout *s; 23774462Salfred 23874462Salfred /* unregister the information anyway */ 23974462Salfred (void) rpcb_unset(prog, vers, NULL); 24074462Salfred rwlock_wrlock(&svc_lock); 24174462Salfred while ((s = svc_find(prog, vers, &prev, NULL)) != NULL) { 24274462Salfred if (prev == NULL) { 24374462Salfred svc_head = s->sc_next; 24474462Salfred } else { 24574462Salfred prev->sc_next = s->sc_next; 24674462Salfred } 24774462Salfred s->sc_next = NULL; 24874462Salfred if (s->sc_netid) 24974462Salfred mem_free(s->sc_netid, sizeof (s->sc_netid) + 1); 25074462Salfred mem_free(s, sizeof (struct svc_callout)); 25174462Salfred } 25274462Salfred rwlock_unlock(&svc_lock); 25374462Salfred} 25474462Salfred 2551901Swollman/* ********************** CALLOUT list related stuff ************* */ 2561901Swollman 25774462Salfred#ifdef PORTMAP 2581901Swollman/* 2591901Swollman * Add a service program to the callout list. 2601901Swollman * The dispatch routine will be called when a rpc request for this 2611901Swollman * program number comes in. 2621901Swollman */ 2631901Swollmanbool_t 2641901Swollmansvc_register(xprt, prog, vers, dispatch, protocol) 2651901Swollman SVCXPRT *xprt; 2661901Swollman u_long prog; 2671901Swollman u_long vers; 26874462Salfred void (*dispatch) __P((struct svc_req *, SVCXPRT *)); 2691901Swollman int protocol; 2701901Swollman{ 2711901Swollman struct svc_callout *prev; 27274462Salfred struct svc_callout *s; 2731901Swollman 27474462Salfred assert(xprt != NULL); 27574462Salfred assert(dispatch != NULL); 27674462Salfred 27774462Salfred if ((s = svc_find((rpcprog_t)prog, (rpcvers_t)vers, &prev, NULL)) != 27874462Salfred NULL) { 2791901Swollman if (s->sc_dispatch == dispatch) 2801901Swollman goto pmap_it; /* he is registering another xptr */ 2811901Swollman return (FALSE); 2821901Swollman } 28374462Salfred s = mem_alloc(sizeof(struct svc_callout)); 28474462Salfred if (s == NULL) { 2851901Swollman return (FALSE); 2861901Swollman } 28774462Salfred s->sc_prog = (rpcprog_t)prog; 28874462Salfred s->sc_vers = (rpcvers_t)vers; 2891901Swollman s->sc_dispatch = dispatch; 2901901Swollman s->sc_next = svc_head; 2911901Swollman svc_head = s; 2921901Swollmanpmap_it: 2931901Swollman /* now register the information with the local binder service */ 2941901Swollman if (protocol) { 2951901Swollman return (pmap_set(prog, vers, protocol, xprt->xp_port)); 2961901Swollman } 2971901Swollman return (TRUE); 2981901Swollman} 2991901Swollman 3001901Swollman/* 3011901Swollman * Remove a service program from the callout list. 3021901Swollman */ 3031901Swollmanvoid 3041901Swollmansvc_unregister(prog, vers) 3051901Swollman u_long prog; 3061901Swollman u_long vers; 3071901Swollman{ 3081901Swollman struct svc_callout *prev; 30974462Salfred struct svc_callout *s; 3101901Swollman 31174462Salfred if ((s = svc_find((rpcprog_t)prog, (rpcvers_t)vers, &prev, NULL)) == 31274462Salfred NULL) 3131901Swollman return; 31474462Salfred if (prev == NULL) { 3151901Swollman svc_head = s->sc_next; 3161901Swollman } else { 3171901Swollman prev->sc_next = s->sc_next; 3181901Swollman } 31974462Salfred s->sc_next = NULL; 32074462Salfred mem_free(s, sizeof(struct svc_callout)); 3211901Swollman /* now unregister the information with the local binder service */ 3221901Swollman (void)pmap_unset(prog, vers); 3231901Swollman} 32474462Salfred#endif /* PORTMAP */ 3251901Swollman 3261901Swollman/* 3271901Swollman * Search the callout list for a program number, return the callout 3281901Swollman * struct. 3291901Swollman */ 3301901Swollmanstatic struct svc_callout * 33174462Salfredsvc_find(prog, vers, prev, netid) 33274462Salfred rpcprog_t prog; 33374462Salfred rpcvers_t vers; 3341901Swollman struct svc_callout **prev; 33574462Salfred char *netid; 3361901Swollman{ 33774462Salfred struct svc_callout *s, *p; 3381901Swollman 33974462Salfred assert(prev != NULL); 34074462Salfred 34174462Salfred p = NULL; 34274462Salfred for (s = svc_head; s != NULL; s = s->sc_next) { 34374462Salfred if (((s->sc_prog == prog) && (s->sc_vers == vers)) && 34474462Salfred ((netid == NULL) || (s->sc_netid == NULL) || 34574462Salfred (strcmp(netid, s->sc_netid) == 0))) 34674462Salfred break; 3471901Swollman p = s; 3481901Swollman } 3491901Swollman *prev = p; 3501901Swollman return (s); 3511901Swollman} 3521901Swollman 3531901Swollman/* ******************* REPLY GENERATION ROUTINES ************ */ 3541901Swollman 3551901Swollman/* 3561901Swollman * Send a reply to an rpc request 3571901Swollman */ 3581901Swollmanbool_t 3591901Swollmansvc_sendreply(xprt, xdr_results, xdr_location) 36074462Salfred SVCXPRT *xprt; 3611901Swollman xdrproc_t xdr_results; 3621901Swollman caddr_t xdr_location; 3631901Swollman{ 36474462Salfred struct rpc_msg rply; 3651901Swollman 36674462Salfred assert(xprt != NULL); 36774462Salfred 36874462Salfred rply.rm_direction = REPLY; 36974462Salfred rply.rm_reply.rp_stat = MSG_ACCEPTED; 37074462Salfred rply.acpted_rply.ar_verf = xprt->xp_verf; 3711901Swollman rply.acpted_rply.ar_stat = SUCCESS; 3721901Swollman rply.acpted_rply.ar_results.where = xdr_location; 3731901Swollman rply.acpted_rply.ar_results.proc = xdr_results; 37474462Salfred return (SVC_REPLY(xprt, &rply)); 3751901Swollman} 3761901Swollman 3771901Swollman/* 3781901Swollman * No procedure error reply 3791901Swollman */ 3801901Swollmanvoid 3811901Swollmansvcerr_noproc(xprt) 38274462Salfred SVCXPRT *xprt; 3831901Swollman{ 3841901Swollman struct rpc_msg rply; 3851901Swollman 38674462Salfred assert(xprt != NULL); 38774462Salfred 3881901Swollman rply.rm_direction = REPLY; 3891901Swollman rply.rm_reply.rp_stat = MSG_ACCEPTED; 3901901Swollman rply.acpted_rply.ar_verf = xprt->xp_verf; 3911901Swollman rply.acpted_rply.ar_stat = PROC_UNAVAIL; 3921901Swollman SVC_REPLY(xprt, &rply); 3931901Swollman} 3941901Swollman 3951901Swollman/* 3961901Swollman * Can't decode args error reply 3971901Swollman */ 3981901Swollmanvoid 3991901Swollmansvcerr_decode(xprt) 40074462Salfred SVCXPRT *xprt; 4011901Swollman{ 40274462Salfred struct rpc_msg rply; 4031901Swollman 40474462Salfred assert(xprt != NULL); 40574462Salfred 40674462Salfred rply.rm_direction = REPLY; 40774462Salfred rply.rm_reply.rp_stat = MSG_ACCEPTED; 4081901Swollman rply.acpted_rply.ar_verf = xprt->xp_verf; 4091901Swollman rply.acpted_rply.ar_stat = GARBAGE_ARGS; 41074462Salfred SVC_REPLY(xprt, &rply); 4111901Swollman} 4121901Swollman 4131901Swollman/* 4141901Swollman * Some system error 4151901Swollman */ 4161901Swollmanvoid 4171901Swollmansvcerr_systemerr(xprt) 41874462Salfred SVCXPRT *xprt; 4191901Swollman{ 42074462Salfred struct rpc_msg rply; 4211901Swollman 42274462Salfred assert(xprt != NULL); 42374462Salfred 42474462Salfred rply.rm_direction = REPLY; 42574462Salfred rply.rm_reply.rp_stat = MSG_ACCEPTED; 4261901Swollman rply.acpted_rply.ar_verf = xprt->xp_verf; 4271901Swollman rply.acpted_rply.ar_stat = SYSTEM_ERR; 42874462Salfred SVC_REPLY(xprt, &rply); 4291901Swollman} 4301901Swollman 43174462Salfred#if 0 4321901Swollman/* 43374462Salfred * Tell RPC package to not complain about version errors to the client. This 43474462Salfred * is useful when revving broadcast protocols that sit on a fixed address. 43574462Salfred * There is really one (or should be only one) example of this kind of 43674462Salfred * protocol: the portmapper (or rpc binder). 43774462Salfred */ 43874462Salfredvoid 43974462Salfred__svc_versquiet_on(xprt) 44074462Salfred SVCXPRT *xprt; 44174462Salfred{ 44274462Salfred u_long tmp; 44374462Salfred 44474462Salfred tmp = ((u_long) xprt->xp_p3) | SVC_VERSQUIET; 44574462Salfred xprt->xp_p3 = (caddr_t) tmp; 44674462Salfred} 44774462Salfred 44874462Salfredvoid 44974462Salfred__svc_versquiet_off(xprt) 45074462Salfred SVCXPRT *xprt; 45174462Salfred{ 45274462Salfred u_long tmp; 45374462Salfred 45474462Salfred tmp = ((u_long) xprt->xp_p3) & ~SVC_VERSQUIET; 45574462Salfred xprt->xp_p3 = (caddr_t) tmp; 45674462Salfred} 45774462Salfred 45874462Salfredvoid 45974462Salfredsvc_versquiet(xprt) 46074462Salfred SVCXPRT *xprt; 46174462Salfred{ 46274462Salfred __svc_versquiet_on(xprt); 46374462Salfred} 46474462Salfred 46574462Salfredint 46674462Salfred__svc_versquiet_get(xprt) 46774462Salfred SVCXPRT *xprt; 46874462Salfred{ 46974462Salfred return ((int) xprt->xp_p3) & SVC_VERSQUIET; 47074462Salfred} 47174462Salfred#endif 47274462Salfred 47374462Salfred/* 4741901Swollman * Authentication error reply 4751901Swollman */ 4761901Swollmanvoid 4771901Swollmansvcerr_auth(xprt, why) 4781901Swollman SVCXPRT *xprt; 4791901Swollman enum auth_stat why; 4801901Swollman{ 4811901Swollman struct rpc_msg rply; 4821901Swollman 48374462Salfred assert(xprt != NULL); 48474462Salfred 4851901Swollman rply.rm_direction = REPLY; 4861901Swollman rply.rm_reply.rp_stat = MSG_DENIED; 4871901Swollman rply.rjcted_rply.rj_stat = AUTH_ERROR; 4881901Swollman rply.rjcted_rply.rj_why = why; 4891901Swollman SVC_REPLY(xprt, &rply); 4901901Swollman} 4911901Swollman 4921901Swollman/* 4931901Swollman * Auth too weak error reply 4941901Swollman */ 4951901Swollmanvoid 4961901Swollmansvcerr_weakauth(xprt) 4971901Swollman SVCXPRT *xprt; 4981901Swollman{ 4991901Swollman 50074462Salfred assert(xprt != NULL); 50174462Salfred 5021901Swollman svcerr_auth(xprt, AUTH_TOOWEAK); 5031901Swollman} 5041901Swollman 5051901Swollman/* 5061901Swollman * Program unavailable error reply 5071901Swollman */ 50874462Salfredvoid 5091901Swollmansvcerr_noprog(xprt) 51074462Salfred SVCXPRT *xprt; 5111901Swollman{ 51274462Salfred struct rpc_msg rply; 5131901Swollman 51474462Salfred assert(xprt != NULL); 51574462Salfred 51674462Salfred rply.rm_direction = REPLY; 51774462Salfred rply.rm_reply.rp_stat = MSG_ACCEPTED; 51874462Salfred rply.acpted_rply.ar_verf = xprt->xp_verf; 5191901Swollman rply.acpted_rply.ar_stat = PROG_UNAVAIL; 5201901Swollman SVC_REPLY(xprt, &rply); 5211901Swollman} 5221901Swollman 5231901Swollman/* 5241901Swollman * Program version mismatch error reply 5251901Swollman */ 52674462Salfredvoid 5271901Swollmansvcerr_progvers(xprt, low_vers, high_vers) 52874462Salfred SVCXPRT *xprt; 52974462Salfred rpcvers_t low_vers; 53074462Salfred rpcvers_t high_vers; 5311901Swollman{ 5321901Swollman struct rpc_msg rply; 5331901Swollman 53474462Salfred assert(xprt != NULL); 53574462Salfred 5361901Swollman rply.rm_direction = REPLY; 5371901Swollman rply.rm_reply.rp_stat = MSG_ACCEPTED; 5381901Swollman rply.acpted_rply.ar_verf = xprt->xp_verf; 5391901Swollman rply.acpted_rply.ar_stat = PROG_MISMATCH; 54074462Salfred rply.acpted_rply.ar_vers.low = (u_int32_t)low_vers; 54174462Salfred rply.acpted_rply.ar_vers.high = (u_int32_t)high_vers; 5421901Swollman SVC_REPLY(xprt, &rply); 5431901Swollman} 5441901Swollman 5451901Swollman/* ******************* SERVER INPUT STUFF ******************* */ 5461901Swollman 5471901Swollman/* 5481901Swollman * Get server side input from some transport. 5491901Swollman * 5501901Swollman * Statement of authentication parameters management: 5511901Swollman * This function owns and manages all authentication parameters, specifically 5521901Swollman * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and 5531901Swollman * the "cooked" credentials (rqst->rq_clntcred). 5541901Swollman * However, this function does not know the structure of the cooked 5558870Srgrimes * credentials, so it make the following assumptions: 5561901Swollman * a) the structure is contiguous (no pointers), and 5578870Srgrimes * b) the cred structure size does not exceed RQCRED_SIZE bytes. 5581901Swollman * In all events, all three parameters are freed upon exit from this routine. 5591901Swollman * The storage is trivially management on the call stack in user land, but 5601901Swollman * is mallocated in kernel land. 5611901Swollman */ 5621901Swollman 5631901Swollmanvoid 5641901Swollmansvc_getreq(rdfds) 5651901Swollman int rdfds; 5661901Swollman{ 5671901Swollman fd_set readfds; 5681901Swollman 5691901Swollman FD_ZERO(&readfds); 5701901Swollman readfds.fds_bits[0] = rdfds; 5711901Swollman svc_getreqset(&readfds); 5721901Swollman} 5731901Swollman 5741901Swollmanvoid 5751901Swollmansvc_getreqset(readfds) 5761901Swollman fd_set *readfds; 5771901Swollman{ 57874462Salfred int bit, fd; 57974462Salfred fd_mask mask, *maskp; 58074462Salfred int sock; 58174462Salfred 58274462Salfred assert(readfds != NULL); 58374462Salfred 58474462Salfred maskp = readfds->fds_bits; 58574462Salfred for (sock = 0; sock < FD_SETSIZE; sock += NFDBITS) { 58674462Salfred for (mask = *maskp++; (bit = ffs(mask)) != 0; 58774462Salfred mask ^= (1 << (bit - 1))) { 58874462Salfred /* sock has input waiting */ 58974462Salfred fd = sock + bit - 1; 59074462Salfred svc_getreq_common(fd); 59174462Salfred } 59274462Salfred } 59321087Speter} 59421087Speter 59521087Spetervoid 59674462Salfredsvc_getreq_common(fd) 59774462Salfred int fd; 5981901Swollman{ 59974462Salfred SVCXPRT *xprt; 60074462Salfred struct svc_req r; 6011901Swollman struct rpc_msg msg; 6021901Swollman int prog_found; 60374462Salfred rpcvers_t low_vers; 60474462Salfred rpcvers_t high_vers; 60574462Salfred enum xprt_stat stat; 6061901Swollman char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE]; 60774462Salfred 6081901Swollman msg.rm_call.cb_cred.oa_base = cred_area; 6091901Swollman msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); 6101901Swollman r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]); 6111901Swollman 61274462Salfred rwlock_rdlock(&svc_fd_lock); 61374462Salfred xprt = xports[fd]; 61474462Salfred rwlock_unlock(&svc_fd_lock); 61574462Salfred if (xprt == NULL) 61674462Salfred /* But do we control sock? */ 61774462Salfred return; 61874462Salfred /* now receive msgs from xprtprt (support batch calls) */ 61974462Salfred do { 62074462Salfred if (SVC_RECV(xprt, &msg)) { 6211901Swollman 62274462Salfred /* now find the exported program and call it */ 62374462Salfred struct svc_callout *s; 62474462Salfred enum auth_stat why; 6251901Swollman 62674462Salfred r.rq_xprt = xprt; 62774462Salfred r.rq_prog = msg.rm_call.cb_prog; 62874462Salfred r.rq_vers = msg.rm_call.cb_vers; 62974462Salfred r.rq_proc = msg.rm_call.cb_proc; 63074462Salfred r.rq_cred = msg.rm_call.cb_cred; 63174462Salfred /* first authenticate the message */ 63274462Salfred if ((why = _authenticate(&r, &msg)) != AUTH_OK) { 63374462Salfred svcerr_auth(xprt, why); 63474462Salfred goto call_done; 6351901Swollman } 63674462Salfred /* now match message with a registered service*/ 63774462Salfred prog_found = FALSE; 63874462Salfred low_vers = (rpcvers_t) -1L; 63974462Salfred high_vers = (rpcvers_t) 0L; 64074462Salfred for (s = svc_head; s != NULL; s = s->sc_next) { 64174462Salfred if (s->sc_prog == r.rq_prog) { 64274462Salfred if (s->sc_vers == r.rq_vers) { 64374462Salfred (*s->sc_dispatch)(&r, xprt); 64474462Salfred goto call_done; 64574462Salfred } /* found correct version */ 64674462Salfred prog_found = TRUE; 64774462Salfred if (s->sc_vers < low_vers) 64874462Salfred low_vers = s->sc_vers; 64974462Salfred if (s->sc_vers > high_vers) 65074462Salfred high_vers = s->sc_vers; 65174462Salfred } /* found correct program */ 6521901Swollman } 65374462Salfred /* 65474462Salfred * if we got here, the program or version 65574462Salfred * is not served ... 65674462Salfred */ 65774462Salfred if (prog_found) 65874462Salfred svcerr_progvers(xprt, low_vers, high_vers); 65974462Salfred else 66074462Salfred svcerr_noprog(xprt); 66174462Salfred /* Fall through to ... */ 66274462Salfred } 66374462Salfred /* 66474462Salfred * Check if the xprt has been disconnected in a 66574462Salfred * recursive call in the service dispatch routine. 66674462Salfred * If so, then break. 66774462Salfred */ 66874462Salfred rwlock_rdlock(&svc_fd_lock); 66974462Salfred if (xprt != xports[fd]) { 67074462Salfred rwlock_unlock(&svc_fd_lock); 67174462Salfred break; 67274462Salfred } 67374462Salfred rwlock_unlock(&svc_fd_lock); 67474462Salfredcall_done: 67574462Salfred if ((stat = SVC_STAT(xprt)) == XPRT_DIED){ 67674462Salfred SVC_DESTROY(xprt); 67774462Salfred break; 67874462Salfred } 67974462Salfred } while (stat == XPRT_MOREREQS); 68074462Salfred} 68174462Salfred 68274462Salfred 68374462Salfredvoid 68474462Salfredsvc_getreq_poll(pfdp, pollretval) 68574462Salfred struct pollfd *pfdp; 68674462Salfred int pollretval; 68774462Salfred{ 68874462Salfred int i; 68974462Salfred int fds_found; 69074462Salfred 69174462Salfred for (i = fds_found = 0; fds_found < pollretval; i++) { 69274462Salfred struct pollfd *p = &pfdp[i]; 69374462Salfred 69474462Salfred if (p->revents) { 69574462Salfred /* fd has input waiting */ 69674462Salfred fds_found++; 69774462Salfred /* 69874462Salfred * We assume that this function is only called 69974462Salfred * via someone _select()ing from svc_fdset or 70074462Salfred * _poll()ing from svc_pollset[]. Thus it's safe 70174462Salfred * to handle the POLLNVAL event by simply turning 70274462Salfred * the corresponding bit off in svc_fdset. The 70374462Salfred * svc_pollset[] array is derived from svc_fdset 70474462Salfred * and so will also be updated eventually. 70574462Salfred * 70674462Salfred * XXX Should we do an xprt_unregister() instead? 70774462Salfred */ 70874462Salfred if (p->revents & POLLNVAL) { 70974462Salfred rwlock_wrlock(&svc_fd_lock); 71074462Salfred FD_CLR(p->fd, &svc_fdset); 71174462Salfred rwlock_unlock(&svc_fd_lock); 71274462Salfred } else 71374462Salfred svc_getreq_common(p->fd); 71474462Salfred } 7151901Swollman } 7161901Swollman} 717