svc.c revision 177633
1177633Sdfr/* $NetBSD: svc.c,v 1.21 2000/07/06 03:10:35 christos Exp $ */ 2177633Sdfr 3177633Sdfr/* 4177633Sdfr * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5177633Sdfr * unrestricted use provided that this legend is included on all tape 6177633Sdfr * media and as a part of the software program in whole or part. Users 7177633Sdfr * may copy or modify Sun RPC without charge, but are not authorized 8177633Sdfr * to license or distribute it to anyone else except as part of a product or 9177633Sdfr * program developed by the user. 10177633Sdfr * 11177633Sdfr * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12177633Sdfr * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13177633Sdfr * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14177633Sdfr * 15177633Sdfr * Sun RPC is provided with no support and without any obligation on the 16177633Sdfr * part of Sun Microsystems, Inc. to assist in its use, correction, 17177633Sdfr * modification or enhancement. 18177633Sdfr * 19177633Sdfr * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20177633Sdfr * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21177633Sdfr * OR ANY PART THEREOF. 22177633Sdfr * 23177633Sdfr * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24177633Sdfr * or profits or other special, indirect and consequential damages, even if 25177633Sdfr * Sun has been advised of the possibility of such damages. 26177633Sdfr * 27177633Sdfr * Sun Microsystems, Inc. 28177633Sdfr * 2550 Garcia Avenue 29177633Sdfr * Mountain View, California 94043 30177633Sdfr */ 31177633Sdfr 32177633Sdfr#if defined(LIBC_SCCS) && !defined(lint) 33177633Sdfrstatic char *sccsid2 = "@(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro"; 34177633Sdfrstatic char *sccsid = "@(#)svc.c 2.4 88/08/11 4.0 RPCSRC"; 35177633Sdfr#endif 36177633Sdfr#include <sys/cdefs.h> 37177633Sdfr__FBSDID("$FreeBSD: head/sys/rpc/svc.c 177633 2008-03-26 15:23:12Z dfr $"); 38177633Sdfr 39177633Sdfr/* 40177633Sdfr * svc.c, Server-side remote procedure call interface. 41177633Sdfr * 42177633Sdfr * There are two sets of procedures here. The xprt routines are 43177633Sdfr * for handling transport handles. The svc routines handle the 44177633Sdfr * list of service routines. 45177633Sdfr * 46177633Sdfr * Copyright (C) 1984, Sun Microsystems, Inc. 47177633Sdfr */ 48177633Sdfr 49177633Sdfr#include <sys/param.h> 50177633Sdfr#include <sys/lock.h> 51177633Sdfr#include <sys/kernel.h> 52177633Sdfr#include <sys/malloc.h> 53177633Sdfr#include <sys/mutex.h> 54177633Sdfr#include <sys/queue.h> 55177633Sdfr#include <sys/systm.h> 56177633Sdfr#include <sys/ucred.h> 57177633Sdfr 58177633Sdfr#include <rpc/rpc.h> 59177633Sdfr#include <rpc/rpcb_clnt.h> 60177633Sdfr 61177633Sdfr#include "rpc_com.h" 62177633Sdfr 63177633Sdfr#define SVC_VERSQUIET 0x0001 /* keep quiet about vers mismatch */ 64177633Sdfr#define version_keepquiet(xp) ((u_long)(xp)->xp_p3 & SVC_VERSQUIET) 65177633Sdfr 66177633Sdfrstatic struct svc_callout *svc_find(SVCPOOL *pool, rpcprog_t, rpcvers_t, 67177633Sdfr char *); 68177633Sdfrstatic void __xprt_do_unregister (SVCXPRT *xprt, bool_t dolock); 69177633Sdfr 70177633Sdfr/* *************** SVCXPRT related stuff **************** */ 71177633Sdfr 72177633SdfrSVCPOOL* 73177633Sdfrsvcpool_create(void) 74177633Sdfr{ 75177633Sdfr SVCPOOL *pool; 76177633Sdfr 77177633Sdfr pool = malloc(sizeof(SVCPOOL), M_RPC, M_WAITOK|M_ZERO); 78177633Sdfr 79177633Sdfr mtx_init(&pool->sp_lock, "sp_lock", NULL, MTX_DEF); 80177633Sdfr TAILQ_INIT(&pool->sp_xlist); 81177633Sdfr TAILQ_INIT(&pool->sp_active); 82177633Sdfr TAILQ_INIT(&pool->sp_callouts); 83177633Sdfr 84177633Sdfr return pool; 85177633Sdfr} 86177633Sdfr 87177633Sdfrvoid 88177633Sdfrsvcpool_destroy(SVCPOOL *pool) 89177633Sdfr{ 90177633Sdfr SVCXPRT *xprt; 91177633Sdfr struct svc_callout *s; 92177633Sdfr 93177633Sdfr mtx_lock(&pool->sp_lock); 94177633Sdfr 95177633Sdfr while (TAILQ_FIRST(&pool->sp_xlist)) { 96177633Sdfr xprt = TAILQ_FIRST(&pool->sp_xlist); 97177633Sdfr mtx_unlock(&pool->sp_lock); 98177633Sdfr SVC_DESTROY(xprt); 99177633Sdfr mtx_lock(&pool->sp_lock); 100177633Sdfr } 101177633Sdfr 102177633Sdfr while (TAILQ_FIRST(&pool->sp_callouts)) { 103177633Sdfr s = TAILQ_FIRST(&pool->sp_callouts); 104177633Sdfr mtx_unlock(&pool->sp_lock); 105177633Sdfr svc_unreg(pool, s->sc_prog, s->sc_vers); 106177633Sdfr mtx_lock(&pool->sp_lock); 107177633Sdfr } 108177633Sdfr 109177633Sdfr mtx_destroy(&pool->sp_lock); 110177633Sdfr free(pool, M_RPC); 111177633Sdfr} 112177633Sdfr 113177633Sdfr/* 114177633Sdfr * Activate a transport handle. 115177633Sdfr */ 116177633Sdfrvoid 117177633Sdfrxprt_register(SVCXPRT *xprt) 118177633Sdfr{ 119177633Sdfr SVCPOOL *pool = xprt->xp_pool; 120177633Sdfr 121177633Sdfr mtx_lock(&pool->sp_lock); 122177633Sdfr xprt->xp_registered = TRUE; 123177633Sdfr xprt->xp_active = FALSE; 124177633Sdfr TAILQ_INSERT_TAIL(&pool->sp_xlist, xprt, xp_link); 125177633Sdfr mtx_unlock(&pool->sp_lock); 126177633Sdfr} 127177633Sdfr 128177633Sdfrvoid 129177633Sdfrxprt_unregister(SVCXPRT *xprt) 130177633Sdfr{ 131177633Sdfr __xprt_do_unregister(xprt, TRUE); 132177633Sdfr} 133177633Sdfr 134177633Sdfrvoid 135177633Sdfr__xprt_unregister_unlocked(SVCXPRT *xprt) 136177633Sdfr{ 137177633Sdfr __xprt_do_unregister(xprt, FALSE); 138177633Sdfr} 139177633Sdfr 140177633Sdfr/* 141177633Sdfr * De-activate a transport handle. 142177633Sdfr */ 143177633Sdfrstatic void 144177633Sdfr__xprt_do_unregister(SVCXPRT *xprt, bool_t dolock) 145177633Sdfr{ 146177633Sdfr SVCPOOL *pool = xprt->xp_pool; 147177633Sdfr 148177633Sdfr //__svc_generic_cleanup(xprt); 149177633Sdfr 150177633Sdfr if (dolock) 151177633Sdfr mtx_lock(&pool->sp_lock); 152177633Sdfr 153177633Sdfr if (xprt->xp_active) { 154177633Sdfr TAILQ_REMOVE(&pool->sp_active, xprt, xp_alink); 155177633Sdfr xprt->xp_active = FALSE; 156177633Sdfr } 157177633Sdfr TAILQ_REMOVE(&pool->sp_xlist, xprt, xp_link); 158177633Sdfr xprt->xp_registered = FALSE; 159177633Sdfr 160177633Sdfr if (dolock) 161177633Sdfr mtx_unlock(&pool->sp_lock); 162177633Sdfr} 163177633Sdfr 164177633Sdfrvoid 165177633Sdfrxprt_active(SVCXPRT *xprt) 166177633Sdfr{ 167177633Sdfr SVCPOOL *pool = xprt->xp_pool; 168177633Sdfr 169177633Sdfr mtx_lock(&pool->sp_lock); 170177633Sdfr 171177633Sdfr if (!xprt->xp_active) { 172177633Sdfr TAILQ_INSERT_TAIL(&pool->sp_active, xprt, xp_alink); 173177633Sdfr xprt->xp_active = TRUE; 174177633Sdfr } 175177633Sdfr wakeup(&pool->sp_active); 176177633Sdfr 177177633Sdfr mtx_unlock(&pool->sp_lock); 178177633Sdfr} 179177633Sdfr 180177633Sdfrvoid 181177633Sdfrxprt_inactive(SVCXPRT *xprt) 182177633Sdfr{ 183177633Sdfr SVCPOOL *pool = xprt->xp_pool; 184177633Sdfr 185177633Sdfr mtx_lock(&pool->sp_lock); 186177633Sdfr 187177633Sdfr if (xprt->xp_active) { 188177633Sdfr TAILQ_REMOVE(&pool->sp_active, xprt, xp_alink); 189177633Sdfr xprt->xp_active = FALSE; 190177633Sdfr } 191177633Sdfr wakeup(&pool->sp_active); 192177633Sdfr 193177633Sdfr mtx_unlock(&pool->sp_lock); 194177633Sdfr} 195177633Sdfr 196177633Sdfr/* 197177633Sdfr * Add a service program to the callout list. 198177633Sdfr * The dispatch routine will be called when a rpc request for this 199177633Sdfr * program number comes in. 200177633Sdfr */ 201177633Sdfrbool_t 202177633Sdfrsvc_reg(SVCXPRT *xprt, const rpcprog_t prog, const rpcvers_t vers, 203177633Sdfr void (*dispatch)(struct svc_req *, SVCXPRT *), 204177633Sdfr const struct netconfig *nconf) 205177633Sdfr{ 206177633Sdfr SVCPOOL *pool = xprt->xp_pool; 207177633Sdfr struct svc_callout *s; 208177633Sdfr char *netid = NULL; 209177633Sdfr int flag = 0; 210177633Sdfr 211177633Sdfr/* VARIABLES PROTECTED BY svc_lock: s, svc_head */ 212177633Sdfr 213177633Sdfr if (xprt->xp_netid) { 214177633Sdfr netid = strdup(xprt->xp_netid, M_RPC); 215177633Sdfr flag = 1; 216177633Sdfr } else if (nconf && nconf->nc_netid) { 217177633Sdfr netid = strdup(nconf->nc_netid, M_RPC); 218177633Sdfr flag = 1; 219177633Sdfr } /* must have been created with svc_raw_create */ 220177633Sdfr if ((netid == NULL) && (flag == 1)) { 221177633Sdfr return (FALSE); 222177633Sdfr } 223177633Sdfr 224177633Sdfr mtx_lock(&pool->sp_lock); 225177633Sdfr if ((s = svc_find(pool, prog, vers, netid)) != NULL) { 226177633Sdfr if (netid) 227177633Sdfr free(netid, M_RPC); 228177633Sdfr if (s->sc_dispatch == dispatch) 229177633Sdfr goto rpcb_it; /* he is registering another xptr */ 230177633Sdfr mtx_unlock(&pool->sp_lock); 231177633Sdfr return (FALSE); 232177633Sdfr } 233177633Sdfr s = malloc(sizeof (struct svc_callout), M_RPC, M_NOWAIT); 234177633Sdfr if (s == NULL) { 235177633Sdfr if (netid) 236177633Sdfr free(netid, M_RPC); 237177633Sdfr mtx_unlock(&pool->sp_lock); 238177633Sdfr return (FALSE); 239177633Sdfr } 240177633Sdfr 241177633Sdfr s->sc_prog = prog; 242177633Sdfr s->sc_vers = vers; 243177633Sdfr s->sc_dispatch = dispatch; 244177633Sdfr s->sc_netid = netid; 245177633Sdfr TAILQ_INSERT_TAIL(&pool->sp_callouts, s, sc_link); 246177633Sdfr 247177633Sdfr if ((xprt->xp_netid == NULL) && (flag == 1) && netid) 248177633Sdfr ((SVCXPRT *) xprt)->xp_netid = strdup(netid, M_RPC); 249177633Sdfr 250177633Sdfrrpcb_it: 251177633Sdfr mtx_unlock(&pool->sp_lock); 252177633Sdfr /* now register the information with the local binder service */ 253177633Sdfr if (nconf) { 254177633Sdfr bool_t dummy; 255177633Sdfr struct netconfig tnc; 256177633Sdfr tnc = *nconf; 257177633Sdfr dummy = rpcb_set(prog, vers, &tnc, 258177633Sdfr &((SVCXPRT *) xprt)->xp_ltaddr); 259177633Sdfr return (dummy); 260177633Sdfr } 261177633Sdfr return (TRUE); 262177633Sdfr} 263177633Sdfr 264177633Sdfr/* 265177633Sdfr * Remove a service program from the callout list. 266177633Sdfr */ 267177633Sdfrvoid 268177633Sdfrsvc_unreg(SVCPOOL *pool, const rpcprog_t prog, const rpcvers_t vers) 269177633Sdfr{ 270177633Sdfr struct svc_callout *s; 271177633Sdfr 272177633Sdfr /* unregister the information anyway */ 273177633Sdfr (void) rpcb_unset(prog, vers, NULL); 274177633Sdfr mtx_lock(&pool->sp_lock); 275177633Sdfr while ((s = svc_find(pool, prog, vers, NULL)) != NULL) { 276177633Sdfr TAILQ_REMOVE(&pool->sp_callouts, s, sc_link); 277177633Sdfr if (s->sc_netid) 278177633Sdfr mem_free(s->sc_netid, sizeof (s->sc_netid) + 1); 279177633Sdfr mem_free(s, sizeof (struct svc_callout)); 280177633Sdfr } 281177633Sdfr mtx_unlock(&pool->sp_lock); 282177633Sdfr} 283177633Sdfr 284177633Sdfr/* ********************** CALLOUT list related stuff ************* */ 285177633Sdfr 286177633Sdfr/* 287177633Sdfr * Search the callout list for a program number, return the callout 288177633Sdfr * struct. 289177633Sdfr */ 290177633Sdfrstatic struct svc_callout * 291177633Sdfrsvc_find(SVCPOOL *pool, rpcprog_t prog, rpcvers_t vers, char *netid) 292177633Sdfr{ 293177633Sdfr struct svc_callout *s; 294177633Sdfr 295177633Sdfr mtx_assert(&pool->sp_lock, MA_OWNED); 296177633Sdfr TAILQ_FOREACH(s, &pool->sp_callouts, sc_link) { 297177633Sdfr if (s->sc_prog == prog && s->sc_vers == vers 298177633Sdfr && (netid == NULL || s->sc_netid == NULL || 299177633Sdfr strcmp(netid, s->sc_netid) == 0)) 300177633Sdfr break; 301177633Sdfr } 302177633Sdfr 303177633Sdfr return (s); 304177633Sdfr} 305177633Sdfr 306177633Sdfr/* ******************* REPLY GENERATION ROUTINES ************ */ 307177633Sdfr 308177633Sdfr/* 309177633Sdfr * Send a reply to an rpc request 310177633Sdfr */ 311177633Sdfrbool_t 312177633Sdfrsvc_sendreply(SVCXPRT *xprt, xdrproc_t xdr_results, void * xdr_location) 313177633Sdfr{ 314177633Sdfr struct rpc_msg rply; 315177633Sdfr 316177633Sdfr rply.rm_direction = REPLY; 317177633Sdfr rply.rm_reply.rp_stat = MSG_ACCEPTED; 318177633Sdfr rply.acpted_rply.ar_verf = xprt->xp_verf; 319177633Sdfr rply.acpted_rply.ar_stat = SUCCESS; 320177633Sdfr rply.acpted_rply.ar_results.where = xdr_location; 321177633Sdfr rply.acpted_rply.ar_results.proc = xdr_results; 322177633Sdfr 323177633Sdfr return (SVC_REPLY(xprt, &rply)); 324177633Sdfr} 325177633Sdfr 326177633Sdfr/* 327177633Sdfr * No procedure error reply 328177633Sdfr */ 329177633Sdfrvoid 330177633Sdfrsvcerr_noproc(SVCXPRT *xprt) 331177633Sdfr{ 332177633Sdfr struct rpc_msg rply; 333177633Sdfr 334177633Sdfr rply.rm_direction = REPLY; 335177633Sdfr rply.rm_reply.rp_stat = MSG_ACCEPTED; 336177633Sdfr rply.acpted_rply.ar_verf = xprt->xp_verf; 337177633Sdfr rply.acpted_rply.ar_stat = PROC_UNAVAIL; 338177633Sdfr 339177633Sdfr SVC_REPLY(xprt, &rply); 340177633Sdfr} 341177633Sdfr 342177633Sdfr/* 343177633Sdfr * Can't decode args error reply 344177633Sdfr */ 345177633Sdfrvoid 346177633Sdfrsvcerr_decode(SVCXPRT *xprt) 347177633Sdfr{ 348177633Sdfr struct rpc_msg rply; 349177633Sdfr 350177633Sdfr rply.rm_direction = REPLY; 351177633Sdfr rply.rm_reply.rp_stat = MSG_ACCEPTED; 352177633Sdfr rply.acpted_rply.ar_verf = xprt->xp_verf; 353177633Sdfr rply.acpted_rply.ar_stat = GARBAGE_ARGS; 354177633Sdfr 355177633Sdfr SVC_REPLY(xprt, &rply); 356177633Sdfr} 357177633Sdfr 358177633Sdfr/* 359177633Sdfr * Some system error 360177633Sdfr */ 361177633Sdfrvoid 362177633Sdfrsvcerr_systemerr(SVCXPRT *xprt) 363177633Sdfr{ 364177633Sdfr struct rpc_msg rply; 365177633Sdfr 366177633Sdfr rply.rm_direction = REPLY; 367177633Sdfr rply.rm_reply.rp_stat = MSG_ACCEPTED; 368177633Sdfr rply.acpted_rply.ar_verf = xprt->xp_verf; 369177633Sdfr rply.acpted_rply.ar_stat = SYSTEM_ERR; 370177633Sdfr 371177633Sdfr SVC_REPLY(xprt, &rply); 372177633Sdfr} 373177633Sdfr 374177633Sdfr/* 375177633Sdfr * Authentication error reply 376177633Sdfr */ 377177633Sdfrvoid 378177633Sdfrsvcerr_auth(SVCXPRT *xprt, enum auth_stat why) 379177633Sdfr{ 380177633Sdfr struct rpc_msg rply; 381177633Sdfr 382177633Sdfr rply.rm_direction = REPLY; 383177633Sdfr rply.rm_reply.rp_stat = MSG_DENIED; 384177633Sdfr rply.rjcted_rply.rj_stat = AUTH_ERROR; 385177633Sdfr rply.rjcted_rply.rj_why = why; 386177633Sdfr 387177633Sdfr SVC_REPLY(xprt, &rply); 388177633Sdfr} 389177633Sdfr 390177633Sdfr/* 391177633Sdfr * Auth too weak error reply 392177633Sdfr */ 393177633Sdfrvoid 394177633Sdfrsvcerr_weakauth(SVCXPRT *xprt) 395177633Sdfr{ 396177633Sdfr 397177633Sdfr svcerr_auth(xprt, AUTH_TOOWEAK); 398177633Sdfr} 399177633Sdfr 400177633Sdfr/* 401177633Sdfr * Program unavailable error reply 402177633Sdfr */ 403177633Sdfrvoid 404177633Sdfrsvcerr_noprog(SVCXPRT *xprt) 405177633Sdfr{ 406177633Sdfr struct rpc_msg rply; 407177633Sdfr 408177633Sdfr rply.rm_direction = REPLY; 409177633Sdfr rply.rm_reply.rp_stat = MSG_ACCEPTED; 410177633Sdfr rply.acpted_rply.ar_verf = xprt->xp_verf; 411177633Sdfr rply.acpted_rply.ar_stat = PROG_UNAVAIL; 412177633Sdfr 413177633Sdfr SVC_REPLY(xprt, &rply); 414177633Sdfr} 415177633Sdfr 416177633Sdfr/* 417177633Sdfr * Program version mismatch error reply 418177633Sdfr */ 419177633Sdfrvoid 420177633Sdfrsvcerr_progvers(SVCXPRT *xprt, rpcvers_t low_vers, rpcvers_t high_vers) 421177633Sdfr{ 422177633Sdfr struct rpc_msg rply; 423177633Sdfr 424177633Sdfr rply.rm_direction = REPLY; 425177633Sdfr rply.rm_reply.rp_stat = MSG_ACCEPTED; 426177633Sdfr rply.acpted_rply.ar_verf = xprt->xp_verf; 427177633Sdfr rply.acpted_rply.ar_stat = PROG_MISMATCH; 428177633Sdfr rply.acpted_rply.ar_vers.low = (uint32_t)low_vers; 429177633Sdfr rply.acpted_rply.ar_vers.high = (uint32_t)high_vers; 430177633Sdfr 431177633Sdfr SVC_REPLY(xprt, &rply); 432177633Sdfr} 433177633Sdfr 434177633Sdfr/* ******************* SERVER INPUT STUFF ******************* */ 435177633Sdfr 436177633Sdfr/* 437177633Sdfr * Get server side input from some transport. 438177633Sdfr * 439177633Sdfr * Statement of authentication parameters management: 440177633Sdfr * This function owns and manages all authentication parameters, specifically 441177633Sdfr * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and 442177633Sdfr * the "cooked" credentials (rqst->rq_clntcred). 443177633Sdfr * In-kernel, we represent non-trivial cooked creds with struct ucred. 444177633Sdfr * In all events, all three parameters are freed upon exit from this routine. 445177633Sdfr * The storage is trivially management on the call stack in user land, but 446177633Sdfr * is mallocated in kernel land. 447177633Sdfr */ 448177633Sdfr 449177633Sdfrstatic void 450177633Sdfrsvc_getreq(SVCXPRT *xprt) 451177633Sdfr{ 452177633Sdfr SVCPOOL *pool = xprt->xp_pool; 453177633Sdfr struct svc_req r; 454177633Sdfr struct rpc_msg msg; 455177633Sdfr int prog_found; 456177633Sdfr rpcvers_t low_vers; 457177633Sdfr rpcvers_t high_vers; 458177633Sdfr enum xprt_stat stat; 459177633Sdfr char cred_area[2*MAX_AUTH_BYTES + sizeof(struct xucred)]; 460177633Sdfr 461177633Sdfr msg.rm_call.cb_cred.oa_base = cred_area; 462177633Sdfr msg.rm_call.cb_verf.oa_base = &cred_area[MAX_AUTH_BYTES]; 463177633Sdfr r.rq_clntcred = &cred_area[2*MAX_AUTH_BYTES]; 464177633Sdfr 465177633Sdfr /* now receive msgs from xprtprt (support batch calls) */ 466177633Sdfr do { 467177633Sdfr if (SVC_RECV(xprt, &msg)) { 468177633Sdfr 469177633Sdfr /* now find the exported program and call it */ 470177633Sdfr struct svc_callout *s; 471177633Sdfr enum auth_stat why; 472177633Sdfr 473177633Sdfr r.rq_xprt = xprt; 474177633Sdfr r.rq_prog = msg.rm_call.cb_prog; 475177633Sdfr r.rq_vers = msg.rm_call.cb_vers; 476177633Sdfr r.rq_proc = msg.rm_call.cb_proc; 477177633Sdfr r.rq_cred = msg.rm_call.cb_cred; 478177633Sdfr /* first authenticate the message */ 479177633Sdfr if ((why = _authenticate(&r, &msg)) != AUTH_OK) { 480177633Sdfr svcerr_auth(xprt, why); 481177633Sdfr goto call_done; 482177633Sdfr } 483177633Sdfr /* now match message with a registered service*/ 484177633Sdfr prog_found = FALSE; 485177633Sdfr low_vers = (rpcvers_t) -1L; 486177633Sdfr high_vers = (rpcvers_t) 0L; 487177633Sdfr TAILQ_FOREACH(s, &pool->sp_callouts, sc_link) { 488177633Sdfr if (s->sc_prog == r.rq_prog) { 489177633Sdfr if (s->sc_vers == r.rq_vers) { 490177633Sdfr (*s->sc_dispatch)(&r, xprt); 491177633Sdfr goto call_done; 492177633Sdfr } /* found correct version */ 493177633Sdfr prog_found = TRUE; 494177633Sdfr if (s->sc_vers < low_vers) 495177633Sdfr low_vers = s->sc_vers; 496177633Sdfr if (s->sc_vers > high_vers) 497177633Sdfr high_vers = s->sc_vers; 498177633Sdfr } /* found correct program */ 499177633Sdfr } 500177633Sdfr /* 501177633Sdfr * if we got here, the program or version 502177633Sdfr * is not served ... 503177633Sdfr */ 504177633Sdfr if (prog_found) 505177633Sdfr svcerr_progvers(xprt, low_vers, high_vers); 506177633Sdfr else 507177633Sdfr svcerr_noprog(xprt); 508177633Sdfr /* Fall through to ... */ 509177633Sdfr } 510177633Sdfr /* 511177633Sdfr * Check if the xprt has been disconnected in a 512177633Sdfr * recursive call in the service dispatch routine. 513177633Sdfr * If so, then break. 514177633Sdfr */ 515177633Sdfr mtx_lock(&pool->sp_lock); 516177633Sdfr if (!xprt->xp_registered) { 517177633Sdfr mtx_unlock(&pool->sp_lock); 518177633Sdfr break; 519177633Sdfr } 520177633Sdfr mtx_unlock(&pool->sp_lock); 521177633Sdfrcall_done: 522177633Sdfr if ((stat = SVC_STAT(xprt)) == XPRT_DIED) { 523177633Sdfr SVC_DESTROY(xprt); 524177633Sdfr break; 525177633Sdfr } 526177633Sdfr } while (stat == XPRT_MOREREQS); 527177633Sdfr} 528177633Sdfr 529177633Sdfrvoid 530177633Sdfrsvc_run(SVCPOOL *pool) 531177633Sdfr{ 532177633Sdfr SVCXPRT *xprt; 533177633Sdfr int error; 534177633Sdfr 535177633Sdfr mtx_lock(&pool->sp_lock); 536177633Sdfr 537177633Sdfr pool->sp_exited = FALSE; 538177633Sdfr 539177633Sdfr while (!pool->sp_exited) { 540177633Sdfr xprt = TAILQ_FIRST(&pool->sp_active); 541177633Sdfr if (!xprt) { 542177633Sdfr error = msleep(&pool->sp_active, &pool->sp_lock, PCATCH, 543177633Sdfr "rpcsvc", 0); 544177633Sdfr if (error) 545177633Sdfr break; 546177633Sdfr continue; 547177633Sdfr } 548177633Sdfr 549177633Sdfr /* 550177633Sdfr * Move this transport to the end to ensure fairness 551177633Sdfr * when multiple transports are active. If this was 552177633Sdfr * the last queued request, svc_getreq will end up 553177633Sdfr * calling xprt_inactive to remove from the active 554177633Sdfr * list. 555177633Sdfr */ 556177633Sdfr TAILQ_REMOVE(&pool->sp_active, xprt, xp_alink); 557177633Sdfr TAILQ_INSERT_TAIL(&pool->sp_active, xprt, xp_alink); 558177633Sdfr 559177633Sdfr mtx_unlock(&pool->sp_lock); 560177633Sdfr svc_getreq(xprt); 561177633Sdfr mtx_lock(&pool->sp_lock); 562177633Sdfr } 563177633Sdfr 564177633Sdfr mtx_unlock(&pool->sp_lock); 565177633Sdfr} 566177633Sdfr 567177633Sdfrvoid 568177633Sdfrsvc_exit(SVCPOOL *pool) 569177633Sdfr{ 570177633Sdfr mtx_lock(&pool->sp_lock); 571177633Sdfr pool->sp_exited = TRUE; 572177633Sdfr wakeup(&pool->sp_active); 573177633Sdfr mtx_unlock(&pool->sp_lock); 574177633Sdfr} 575