1dfdcada3SDoug Rabson /* $NetBSD: svc.c,v 1.21 2000/07/06 03:10:35 christos Exp $ */ 2dfdcada3SDoug Rabson 3dfdcada3SDoug Rabson /* 4dfdcada3SDoug Rabson * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5dfdcada3SDoug Rabson * unrestricted use provided that this legend is included on all tape 6dfdcada3SDoug Rabson * media and as a part of the software program in whole or part. Users 7dfdcada3SDoug Rabson * may copy or modify Sun RPC without charge, but are not authorized 8dfdcada3SDoug Rabson * to license or distribute it to anyone else except as part of a product or 9dfdcada3SDoug Rabson * program developed by the user. 10dfdcada3SDoug Rabson * 11dfdcada3SDoug Rabson * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12dfdcada3SDoug Rabson * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13dfdcada3SDoug Rabson * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14dfdcada3SDoug Rabson * 15dfdcada3SDoug Rabson * Sun RPC is provided with no support and without any obligation on the 16dfdcada3SDoug Rabson * part of Sun Microsystems, Inc. to assist in its use, correction, 17dfdcada3SDoug Rabson * modification or enhancement. 18dfdcada3SDoug Rabson * 19dfdcada3SDoug Rabson * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20dfdcada3SDoug Rabson * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21dfdcada3SDoug Rabson * OR ANY PART THEREOF. 22dfdcada3SDoug Rabson * 23dfdcada3SDoug Rabson * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24dfdcada3SDoug Rabson * or profits or other special, indirect and consequential damages, even if 25dfdcada3SDoug Rabson * Sun has been advised of the possibility of such damages. 26dfdcada3SDoug Rabson * 27dfdcada3SDoug Rabson * Sun Microsystems, Inc. 28dfdcada3SDoug Rabson * 2550 Garcia Avenue 29dfdcada3SDoug Rabson * Mountain View, California 94043 30dfdcada3SDoug Rabson */ 31dfdcada3SDoug Rabson 32dfdcada3SDoug Rabson #if defined(LIBC_SCCS) && !defined(lint) 33dfdcada3SDoug Rabson static char *sccsid2 = "@(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro"; 34dfdcada3SDoug Rabson static char *sccsid = "@(#)svc.c 2.4 88/08/11 4.0 RPCSRC"; 35dfdcada3SDoug Rabson #endif 36dfdcada3SDoug Rabson #include <sys/cdefs.h> 37dfdcada3SDoug Rabson __FBSDID("$FreeBSD$"); 38dfdcada3SDoug Rabson 39dfdcada3SDoug Rabson /* 40dfdcada3SDoug Rabson * svc.c, Server-side remote procedure call interface. 41dfdcada3SDoug Rabson * 42dfdcada3SDoug Rabson * There are two sets of procedures here. The xprt routines are 43dfdcada3SDoug Rabson * for handling transport handles. The svc routines handle the 44dfdcada3SDoug Rabson * list of service routines. 45dfdcada3SDoug Rabson * 46dfdcada3SDoug Rabson * Copyright (C) 1984, Sun Microsystems, Inc. 47dfdcada3SDoug Rabson */ 48dfdcada3SDoug Rabson 49dfdcada3SDoug Rabson #include <sys/param.h> 50dfdcada3SDoug Rabson #include <sys/lock.h> 51dfdcada3SDoug Rabson #include <sys/kernel.h> 52dfdcada3SDoug Rabson #include <sys/malloc.h> 53dfdcada3SDoug Rabson #include <sys/mutex.h> 54dfdcada3SDoug Rabson #include <sys/queue.h> 55dfdcada3SDoug Rabson #include <sys/systm.h> 56dfdcada3SDoug Rabson #include <sys/ucred.h> 57dfdcada3SDoug Rabson 58dfdcada3SDoug Rabson #include <rpc/rpc.h> 59dfdcada3SDoug Rabson #include <rpc/rpcb_clnt.h> 60dfdcada3SDoug Rabson 61dfdcada3SDoug Rabson #include "rpc_com.h" 62dfdcada3SDoug Rabson 63dfdcada3SDoug Rabson #define SVC_VERSQUIET 0x0001 /* keep quiet about vers mismatch */ 64dfdcada3SDoug Rabson #define version_keepquiet(xp) ((u_long)(xp)->xp_p3 & SVC_VERSQUIET) 65dfdcada3SDoug Rabson 66dfdcada3SDoug Rabson static struct svc_callout *svc_find(SVCPOOL *pool, rpcprog_t, rpcvers_t, 67dfdcada3SDoug Rabson char *); 68dfdcada3SDoug Rabson static void __xprt_do_unregister (SVCXPRT *xprt, bool_t dolock); 69dfdcada3SDoug Rabson 70dfdcada3SDoug Rabson /* *************** SVCXPRT related stuff **************** */ 71dfdcada3SDoug Rabson 72dfdcada3SDoug Rabson SVCPOOL* 73dfdcada3SDoug Rabson svcpool_create(void) 74dfdcada3SDoug Rabson { 75dfdcada3SDoug Rabson SVCPOOL *pool; 76dfdcada3SDoug Rabson 77dfdcada3SDoug Rabson pool = malloc(sizeof(SVCPOOL), M_RPC, M_WAITOK|M_ZERO); 78dfdcada3SDoug Rabson 79dfdcada3SDoug Rabson mtx_init(&pool->sp_lock, "sp_lock", NULL, MTX_DEF); 80dfdcada3SDoug Rabson TAILQ_INIT(&pool->sp_xlist); 81dfdcada3SDoug Rabson TAILQ_INIT(&pool->sp_active); 82dfdcada3SDoug Rabson TAILQ_INIT(&pool->sp_callouts); 83dfdcada3SDoug Rabson 84dfdcada3SDoug Rabson return pool; 85dfdcada3SDoug Rabson } 86dfdcada3SDoug Rabson 87dfdcada3SDoug Rabson void 88dfdcada3SDoug Rabson svcpool_destroy(SVCPOOL *pool) 89dfdcada3SDoug Rabson { 90dfdcada3SDoug Rabson SVCXPRT *xprt; 91dfdcada3SDoug Rabson struct svc_callout *s; 92dfdcada3SDoug Rabson 93dfdcada3SDoug Rabson mtx_lock(&pool->sp_lock); 94dfdcada3SDoug Rabson 95dfdcada3SDoug Rabson while (TAILQ_FIRST(&pool->sp_xlist)) { 96dfdcada3SDoug Rabson xprt = TAILQ_FIRST(&pool->sp_xlist); 97dfdcada3SDoug Rabson mtx_unlock(&pool->sp_lock); 98dfdcada3SDoug Rabson SVC_DESTROY(xprt); 99dfdcada3SDoug Rabson mtx_lock(&pool->sp_lock); 100dfdcada3SDoug Rabson } 101dfdcada3SDoug Rabson 102dfdcada3SDoug Rabson while (TAILQ_FIRST(&pool->sp_callouts)) { 103dfdcada3SDoug Rabson s = TAILQ_FIRST(&pool->sp_callouts); 104dfdcada3SDoug Rabson mtx_unlock(&pool->sp_lock); 105dfdcada3SDoug Rabson svc_unreg(pool, s->sc_prog, s->sc_vers); 106dfdcada3SDoug Rabson mtx_lock(&pool->sp_lock); 107dfdcada3SDoug Rabson } 108dfdcada3SDoug Rabson 109dfdcada3SDoug Rabson mtx_destroy(&pool->sp_lock); 110dfdcada3SDoug Rabson free(pool, M_RPC); 111dfdcada3SDoug Rabson } 112dfdcada3SDoug Rabson 113dfdcada3SDoug Rabson /* 114dfdcada3SDoug Rabson * Activate a transport handle. 115dfdcada3SDoug Rabson */ 116dfdcada3SDoug Rabson void 117dfdcada3SDoug Rabson xprt_register(SVCXPRT *xprt) 118dfdcada3SDoug Rabson { 119dfdcada3SDoug Rabson SVCPOOL *pool = xprt->xp_pool; 120dfdcada3SDoug Rabson 121dfdcada3SDoug Rabson mtx_lock(&pool->sp_lock); 122dfdcada3SDoug Rabson xprt->xp_registered = TRUE; 123dfdcada3SDoug Rabson xprt->xp_active = FALSE; 124dfdcada3SDoug Rabson TAILQ_INSERT_TAIL(&pool->sp_xlist, xprt, xp_link); 125dfdcada3SDoug Rabson mtx_unlock(&pool->sp_lock); 126dfdcada3SDoug Rabson } 127dfdcada3SDoug Rabson 128dfdcada3SDoug Rabson void 129dfdcada3SDoug Rabson xprt_unregister(SVCXPRT *xprt) 130dfdcada3SDoug Rabson { 131dfdcada3SDoug Rabson __xprt_do_unregister(xprt, TRUE); 132dfdcada3SDoug Rabson } 133dfdcada3SDoug Rabson 134dfdcada3SDoug Rabson void 135dfdcada3SDoug Rabson __xprt_unregister_unlocked(SVCXPRT *xprt) 136dfdcada3SDoug Rabson { 137dfdcada3SDoug Rabson __xprt_do_unregister(xprt, FALSE); 138dfdcada3SDoug Rabson } 139dfdcada3SDoug Rabson 140dfdcada3SDoug Rabson /* 141dfdcada3SDoug Rabson * De-activate a transport handle. 142dfdcada3SDoug Rabson */ 143dfdcada3SDoug Rabson static void 144dfdcada3SDoug Rabson __xprt_do_unregister(SVCXPRT *xprt, bool_t dolock) 145dfdcada3SDoug Rabson { 146dfdcada3SDoug Rabson SVCPOOL *pool = xprt->xp_pool; 147dfdcada3SDoug Rabson 148dfdcada3SDoug Rabson //__svc_generic_cleanup(xprt); 149dfdcada3SDoug Rabson 150dfdcada3SDoug Rabson if (dolock) 151dfdcada3SDoug Rabson mtx_lock(&pool->sp_lock); 152dfdcada3SDoug Rabson 153dfdcada3SDoug Rabson if (xprt->xp_active) { 154dfdcada3SDoug Rabson TAILQ_REMOVE(&pool->sp_active, xprt, xp_alink); 155dfdcada3SDoug Rabson xprt->xp_active = FALSE; 156dfdcada3SDoug Rabson } 157dfdcada3SDoug Rabson TAILQ_REMOVE(&pool->sp_xlist, xprt, xp_link); 158dfdcada3SDoug Rabson xprt->xp_registered = FALSE; 159dfdcada3SDoug Rabson 160dfdcada3SDoug Rabson if (dolock) 161dfdcada3SDoug Rabson mtx_unlock(&pool->sp_lock); 162dfdcada3SDoug Rabson } 163dfdcada3SDoug Rabson 164dfdcada3SDoug Rabson void 165dfdcada3SDoug Rabson xprt_active(SVCXPRT *xprt) 166dfdcada3SDoug Rabson { 167dfdcada3SDoug Rabson SVCPOOL *pool = xprt->xp_pool; 168dfdcada3SDoug Rabson 169dfdcada3SDoug Rabson mtx_lock(&pool->sp_lock); 170dfdcada3SDoug Rabson 171dfdcada3SDoug Rabson if (!xprt->xp_active) { 172dfdcada3SDoug Rabson TAILQ_INSERT_TAIL(&pool->sp_active, xprt, xp_alink); 173dfdcada3SDoug Rabson xprt->xp_active = TRUE; 174dfdcada3SDoug Rabson } 175dfdcada3SDoug Rabson wakeup(&pool->sp_active); 176dfdcada3SDoug Rabson 177dfdcada3SDoug Rabson mtx_unlock(&pool->sp_lock); 178dfdcada3SDoug Rabson } 179dfdcada3SDoug Rabson 180dfdcada3SDoug Rabson void 181dfdcada3SDoug Rabson xprt_inactive(SVCXPRT *xprt) 182dfdcada3SDoug Rabson { 183dfdcada3SDoug Rabson SVCPOOL *pool = xprt->xp_pool; 184dfdcada3SDoug Rabson 185dfdcada3SDoug Rabson mtx_lock(&pool->sp_lock); 186dfdcada3SDoug Rabson 187dfdcada3SDoug Rabson if (xprt->xp_active) { 188dfdcada3SDoug Rabson TAILQ_REMOVE(&pool->sp_active, xprt, xp_alink); 189dfdcada3SDoug Rabson xprt->xp_active = FALSE; 190dfdcada3SDoug Rabson } 191dfdcada3SDoug Rabson wakeup(&pool->sp_active); 192dfdcada3SDoug Rabson 193dfdcada3SDoug Rabson mtx_unlock(&pool->sp_lock); 194dfdcada3SDoug Rabson } 195dfdcada3SDoug Rabson 196dfdcada3SDoug Rabson /* 197dfdcada3SDoug Rabson * Add a service program to the callout list. 198dfdcada3SDoug Rabson * The dispatch routine will be called when a rpc request for this 199dfdcada3SDoug Rabson * program number comes in. 200dfdcada3SDoug Rabson */ 201dfdcada3SDoug Rabson bool_t 202dfdcada3SDoug Rabson svc_reg(SVCXPRT *xprt, const rpcprog_t prog, const rpcvers_t vers, 203dfdcada3SDoug Rabson void (*dispatch)(struct svc_req *, SVCXPRT *), 204dfdcada3SDoug Rabson const struct netconfig *nconf) 205dfdcada3SDoug Rabson { 206dfdcada3SDoug Rabson SVCPOOL *pool = xprt->xp_pool; 207dfdcada3SDoug Rabson struct svc_callout *s; 208dfdcada3SDoug Rabson char *netid = NULL; 209dfdcada3SDoug Rabson int flag = 0; 210dfdcada3SDoug Rabson 211dfdcada3SDoug Rabson /* VARIABLES PROTECTED BY svc_lock: s, svc_head */ 212dfdcada3SDoug Rabson 213dfdcada3SDoug Rabson if (xprt->xp_netid) { 214dfdcada3SDoug Rabson netid = strdup(xprt->xp_netid, M_RPC); 215dfdcada3SDoug Rabson flag = 1; 216dfdcada3SDoug Rabson } else if (nconf && nconf->nc_netid) { 217dfdcada3SDoug Rabson netid = strdup(nconf->nc_netid, M_RPC); 218dfdcada3SDoug Rabson flag = 1; 219dfdcada3SDoug Rabson } /* must have been created with svc_raw_create */ 220dfdcada3SDoug Rabson if ((netid == NULL) && (flag == 1)) { 221dfdcada3SDoug Rabson return (FALSE); 222dfdcada3SDoug Rabson } 223dfdcada3SDoug Rabson 224dfdcada3SDoug Rabson mtx_lock(&pool->sp_lock); 225dfdcada3SDoug Rabson if ((s = svc_find(pool, prog, vers, netid)) != NULL) { 226dfdcada3SDoug Rabson if (netid) 227dfdcada3SDoug Rabson free(netid, M_RPC); 228dfdcada3SDoug Rabson if (s->sc_dispatch == dispatch) 229dfdcada3SDoug Rabson goto rpcb_it; /* he is registering another xptr */ 230dfdcada3SDoug Rabson mtx_unlock(&pool->sp_lock); 231dfdcada3SDoug Rabson return (FALSE); 232dfdcada3SDoug Rabson } 233dfdcada3SDoug Rabson s = malloc(sizeof (struct svc_callout), M_RPC, M_NOWAIT); 234dfdcada3SDoug Rabson if (s == NULL) { 235dfdcada3SDoug Rabson if (netid) 236dfdcada3SDoug Rabson free(netid, M_RPC); 237dfdcada3SDoug Rabson mtx_unlock(&pool->sp_lock); 238dfdcada3SDoug Rabson return (FALSE); 239dfdcada3SDoug Rabson } 240dfdcada3SDoug Rabson 241dfdcada3SDoug Rabson s->sc_prog = prog; 242dfdcada3SDoug Rabson s->sc_vers = vers; 243dfdcada3SDoug Rabson s->sc_dispatch = dispatch; 244dfdcada3SDoug Rabson s->sc_netid = netid; 245dfdcada3SDoug Rabson TAILQ_INSERT_TAIL(&pool->sp_callouts, s, sc_link); 246dfdcada3SDoug Rabson 247dfdcada3SDoug Rabson if ((xprt->xp_netid == NULL) && (flag == 1) && netid) 248dfdcada3SDoug Rabson ((SVCXPRT *) xprt)->xp_netid = strdup(netid, M_RPC); 249dfdcada3SDoug Rabson 250dfdcada3SDoug Rabson rpcb_it: 251dfdcada3SDoug Rabson mtx_unlock(&pool->sp_lock); 252dfdcada3SDoug Rabson /* now register the information with the local binder service */ 253dfdcada3SDoug Rabson if (nconf) { 254dfdcada3SDoug Rabson bool_t dummy; 255dfdcada3SDoug Rabson struct netconfig tnc; 256dfdcada3SDoug Rabson tnc = *nconf; 257dfdcada3SDoug Rabson dummy = rpcb_set(prog, vers, &tnc, 258dfdcada3SDoug Rabson &((SVCXPRT *) xprt)->xp_ltaddr); 259dfdcada3SDoug Rabson return (dummy); 260dfdcada3SDoug Rabson } 261dfdcada3SDoug Rabson return (TRUE); 262dfdcada3SDoug Rabson } 263dfdcada3SDoug Rabson 264dfdcada3SDoug Rabson /* 265dfdcada3SDoug Rabson * Remove a service program from the callout list. 266dfdcada3SDoug Rabson */ 267dfdcada3SDoug Rabson void 268dfdcada3SDoug Rabson svc_unreg(SVCPOOL *pool, const rpcprog_t prog, const rpcvers_t vers) 269dfdcada3SDoug Rabson { 270dfdcada3SDoug Rabson struct svc_callout *s; 271dfdcada3SDoug Rabson 272dfdcada3SDoug Rabson /* unregister the information anyway */ 273dfdcada3SDoug Rabson (void) rpcb_unset(prog, vers, NULL); 274dfdcada3SDoug Rabson mtx_lock(&pool->sp_lock); 275dfdcada3SDoug Rabson while ((s = svc_find(pool, prog, vers, NULL)) != NULL) { 276dfdcada3SDoug Rabson TAILQ_REMOVE(&pool->sp_callouts, s, sc_link); 277dfdcada3SDoug Rabson if (s->sc_netid) 278dfdcada3SDoug Rabson mem_free(s->sc_netid, sizeof (s->sc_netid) + 1); 279dfdcada3SDoug Rabson mem_free(s, sizeof (struct svc_callout)); 280dfdcada3SDoug Rabson } 281dfdcada3SDoug Rabson mtx_unlock(&pool->sp_lock); 282dfdcada3SDoug Rabson } 283dfdcada3SDoug Rabson 284dfdcada3SDoug Rabson /* ********************** CALLOUT list related stuff ************* */ 285dfdcada3SDoug Rabson 286dfdcada3SDoug Rabson /* 287dfdcada3SDoug Rabson * Search the callout list for a program number, return the callout 288dfdcada3SDoug Rabson * struct. 289dfdcada3SDoug Rabson */ 290dfdcada3SDoug Rabson static struct svc_callout * 291dfdcada3SDoug Rabson svc_find(SVCPOOL *pool, rpcprog_t prog, rpcvers_t vers, char *netid) 292dfdcada3SDoug Rabson { 293dfdcada3SDoug Rabson struct svc_callout *s; 294dfdcada3SDoug Rabson 295dfdcada3SDoug Rabson mtx_assert(&pool->sp_lock, MA_OWNED); 296dfdcada3SDoug Rabson TAILQ_FOREACH(s, &pool->sp_callouts, sc_link) { 297dfdcada3SDoug Rabson if (s->sc_prog == prog && s->sc_vers == vers 298dfdcada3SDoug Rabson && (netid == NULL || s->sc_netid == NULL || 299dfdcada3SDoug Rabson strcmp(netid, s->sc_netid) == 0)) 300dfdcada3SDoug Rabson break; 301dfdcada3SDoug Rabson } 302dfdcada3SDoug Rabson 303dfdcada3SDoug Rabson return (s); 304dfdcada3SDoug Rabson } 305dfdcada3SDoug Rabson 306dfdcada3SDoug Rabson /* ******************* REPLY GENERATION ROUTINES ************ */ 307dfdcada3SDoug Rabson 308dfdcada3SDoug Rabson /* 309dfdcada3SDoug Rabson * Send a reply to an rpc request 310dfdcada3SDoug Rabson */ 311dfdcada3SDoug Rabson bool_t 312dfdcada3SDoug Rabson svc_sendreply(SVCXPRT *xprt, xdrproc_t xdr_results, void * xdr_location) 313dfdcada3SDoug Rabson { 314dfdcada3SDoug Rabson struct rpc_msg rply; 315dfdcada3SDoug Rabson 316dfdcada3SDoug Rabson rply.rm_direction = REPLY; 317dfdcada3SDoug Rabson rply.rm_reply.rp_stat = MSG_ACCEPTED; 318dfdcada3SDoug Rabson rply.acpted_rply.ar_verf = xprt->xp_verf; 319dfdcada3SDoug Rabson rply.acpted_rply.ar_stat = SUCCESS; 320dfdcada3SDoug Rabson rply.acpted_rply.ar_results.where = xdr_location; 321dfdcada3SDoug Rabson rply.acpted_rply.ar_results.proc = xdr_results; 322dfdcada3SDoug Rabson 323dfdcada3SDoug Rabson return (SVC_REPLY(xprt, &rply)); 324dfdcada3SDoug Rabson } 325dfdcada3SDoug Rabson 326dfdcada3SDoug Rabson /* 327dfdcada3SDoug Rabson * No procedure error reply 328dfdcada3SDoug Rabson */ 329dfdcada3SDoug Rabson void 330dfdcada3SDoug Rabson svcerr_noproc(SVCXPRT *xprt) 331dfdcada3SDoug Rabson { 332dfdcada3SDoug Rabson struct rpc_msg rply; 333dfdcada3SDoug Rabson 334dfdcada3SDoug Rabson rply.rm_direction = REPLY; 335dfdcada3SDoug Rabson rply.rm_reply.rp_stat = MSG_ACCEPTED; 336dfdcada3SDoug Rabson rply.acpted_rply.ar_verf = xprt->xp_verf; 337dfdcada3SDoug Rabson rply.acpted_rply.ar_stat = PROC_UNAVAIL; 338dfdcada3SDoug Rabson 339dfdcada3SDoug Rabson SVC_REPLY(xprt, &rply); 340dfdcada3SDoug Rabson } 341dfdcada3SDoug Rabson 342dfdcada3SDoug Rabson /* 343dfdcada3SDoug Rabson * Can't decode args error reply 344dfdcada3SDoug Rabson */ 345dfdcada3SDoug Rabson void 346dfdcada3SDoug Rabson svcerr_decode(SVCXPRT *xprt) 347dfdcada3SDoug Rabson { 348dfdcada3SDoug Rabson struct rpc_msg rply; 349dfdcada3SDoug Rabson 350dfdcada3SDoug Rabson rply.rm_direction = REPLY; 351dfdcada3SDoug Rabson rply.rm_reply.rp_stat = MSG_ACCEPTED; 352dfdcada3SDoug Rabson rply.acpted_rply.ar_verf = xprt->xp_verf; 353dfdcada3SDoug Rabson rply.acpted_rply.ar_stat = GARBAGE_ARGS; 354dfdcada3SDoug Rabson 355dfdcada3SDoug Rabson SVC_REPLY(xprt, &rply); 356dfdcada3SDoug Rabson } 357dfdcada3SDoug Rabson 358dfdcada3SDoug Rabson /* 359dfdcada3SDoug Rabson * Some system error 360dfdcada3SDoug Rabson */ 361dfdcada3SDoug Rabson void 362dfdcada3SDoug Rabson svcerr_systemerr(SVCXPRT *xprt) 363dfdcada3SDoug Rabson { 364dfdcada3SDoug Rabson struct rpc_msg rply; 365dfdcada3SDoug Rabson 366dfdcada3SDoug Rabson rply.rm_direction = REPLY; 367dfdcada3SDoug Rabson rply.rm_reply.rp_stat = MSG_ACCEPTED; 368dfdcada3SDoug Rabson rply.acpted_rply.ar_verf = xprt->xp_verf; 369dfdcada3SDoug Rabson rply.acpted_rply.ar_stat = SYSTEM_ERR; 370dfdcada3SDoug Rabson 371dfdcada3SDoug Rabson SVC_REPLY(xprt, &rply); 372dfdcada3SDoug Rabson } 373dfdcada3SDoug Rabson 374dfdcada3SDoug Rabson /* 375dfdcada3SDoug Rabson * Authentication error reply 376dfdcada3SDoug Rabson */ 377dfdcada3SDoug Rabson void 378dfdcada3SDoug Rabson svcerr_auth(SVCXPRT *xprt, enum auth_stat why) 379dfdcada3SDoug Rabson { 380dfdcada3SDoug Rabson struct rpc_msg rply; 381dfdcada3SDoug Rabson 382dfdcada3SDoug Rabson rply.rm_direction = REPLY; 383dfdcada3SDoug Rabson rply.rm_reply.rp_stat = MSG_DENIED; 384dfdcada3SDoug Rabson rply.rjcted_rply.rj_stat = AUTH_ERROR; 385dfdcada3SDoug Rabson rply.rjcted_rply.rj_why = why; 386dfdcada3SDoug Rabson 387dfdcada3SDoug Rabson SVC_REPLY(xprt, &rply); 388dfdcada3SDoug Rabson } 389dfdcada3SDoug Rabson 390dfdcada3SDoug Rabson /* 391dfdcada3SDoug Rabson * Auth too weak error reply 392dfdcada3SDoug Rabson */ 393dfdcada3SDoug Rabson void 394dfdcada3SDoug Rabson svcerr_weakauth(SVCXPRT *xprt) 395dfdcada3SDoug Rabson { 396dfdcada3SDoug Rabson 397dfdcada3SDoug Rabson svcerr_auth(xprt, AUTH_TOOWEAK); 398dfdcada3SDoug Rabson } 399dfdcada3SDoug Rabson 400dfdcada3SDoug Rabson /* 401dfdcada3SDoug Rabson * Program unavailable error reply 402dfdcada3SDoug Rabson */ 403dfdcada3SDoug Rabson void 404dfdcada3SDoug Rabson svcerr_noprog(SVCXPRT *xprt) 405dfdcada3SDoug Rabson { 406dfdcada3SDoug Rabson struct rpc_msg rply; 407dfdcada3SDoug Rabson 408dfdcada3SDoug Rabson rply.rm_direction = REPLY; 409dfdcada3SDoug Rabson rply.rm_reply.rp_stat = MSG_ACCEPTED; 410dfdcada3SDoug Rabson rply.acpted_rply.ar_verf = xprt->xp_verf; 411dfdcada3SDoug Rabson rply.acpted_rply.ar_stat = PROG_UNAVAIL; 412dfdcada3SDoug Rabson 413dfdcada3SDoug Rabson SVC_REPLY(xprt, &rply); 414dfdcada3SDoug Rabson } 415dfdcada3SDoug Rabson 416dfdcada3SDoug Rabson /* 417dfdcada3SDoug Rabson * Program version mismatch error reply 418dfdcada3SDoug Rabson */ 419dfdcada3SDoug Rabson void 420dfdcada3SDoug Rabson svcerr_progvers(SVCXPRT *xprt, rpcvers_t low_vers, rpcvers_t high_vers) 421dfdcada3SDoug Rabson { 422dfdcada3SDoug Rabson struct rpc_msg rply; 423dfdcada3SDoug Rabson 424dfdcada3SDoug Rabson rply.rm_direction = REPLY; 425dfdcada3SDoug Rabson rply.rm_reply.rp_stat = MSG_ACCEPTED; 426dfdcada3SDoug Rabson rply.acpted_rply.ar_verf = xprt->xp_verf; 427dfdcada3SDoug Rabson rply.acpted_rply.ar_stat = PROG_MISMATCH; 428dfdcada3SDoug Rabson rply.acpted_rply.ar_vers.low = (uint32_t)low_vers; 429dfdcada3SDoug Rabson rply.acpted_rply.ar_vers.high = (uint32_t)high_vers; 430dfdcada3SDoug Rabson 431dfdcada3SDoug Rabson SVC_REPLY(xprt, &rply); 432dfdcada3SDoug Rabson } 433dfdcada3SDoug Rabson 434dfdcada3SDoug Rabson /* ******************* SERVER INPUT STUFF ******************* */ 435dfdcada3SDoug Rabson 436dfdcada3SDoug Rabson /* 437dfdcada3SDoug Rabson * Get server side input from some transport. 438dfdcada3SDoug Rabson * 439dfdcada3SDoug Rabson * Statement of authentication parameters management: 440dfdcada3SDoug Rabson * This function owns and manages all authentication parameters, specifically 441dfdcada3SDoug Rabson * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and 442dfdcada3SDoug Rabson * the "cooked" credentials (rqst->rq_clntcred). 443dfdcada3SDoug Rabson * In-kernel, we represent non-trivial cooked creds with struct ucred. 444dfdcada3SDoug Rabson * In all events, all three parameters are freed upon exit from this routine. 445dfdcada3SDoug Rabson * The storage is trivially management on the call stack in user land, but 446dfdcada3SDoug Rabson * is mallocated in kernel land. 447dfdcada3SDoug Rabson */ 448dfdcada3SDoug Rabson 449dfdcada3SDoug Rabson static void 450dfdcada3SDoug Rabson svc_getreq(SVCXPRT *xprt) 451dfdcada3SDoug Rabson { 452dfdcada3SDoug Rabson SVCPOOL *pool = xprt->xp_pool; 453dfdcada3SDoug Rabson struct svc_req r; 454dfdcada3SDoug Rabson struct rpc_msg msg; 455dfdcada3SDoug Rabson int prog_found; 456dfdcada3SDoug Rabson rpcvers_t low_vers; 457dfdcada3SDoug Rabson rpcvers_t high_vers; 458dfdcada3SDoug Rabson enum xprt_stat stat; 459dfdcada3SDoug Rabson char cred_area[2*MAX_AUTH_BYTES + sizeof(struct xucred)]; 460dfdcada3SDoug Rabson 461dfdcada3SDoug Rabson msg.rm_call.cb_cred.oa_base = cred_area; 462dfdcada3SDoug Rabson msg.rm_call.cb_verf.oa_base = &cred_area[MAX_AUTH_BYTES]; 463dfdcada3SDoug Rabson r.rq_clntcred = &cred_area[2*MAX_AUTH_BYTES]; 464dfdcada3SDoug Rabson 465dfdcada3SDoug Rabson /* now receive msgs from xprtprt (support batch calls) */ 466dfdcada3SDoug Rabson do { 467dfdcada3SDoug Rabson if (SVC_RECV(xprt, &msg)) { 468dfdcada3SDoug Rabson 469dfdcada3SDoug Rabson /* now find the exported program and call it */ 470dfdcada3SDoug Rabson struct svc_callout *s; 471dfdcada3SDoug Rabson enum auth_stat why; 472dfdcada3SDoug Rabson 473dfdcada3SDoug Rabson r.rq_xprt = xprt; 474dfdcada3SDoug Rabson r.rq_prog = msg.rm_call.cb_prog; 475dfdcada3SDoug Rabson r.rq_vers = msg.rm_call.cb_vers; 476dfdcada3SDoug Rabson r.rq_proc = msg.rm_call.cb_proc; 477dfdcada3SDoug Rabson r.rq_cred = msg.rm_call.cb_cred; 478dfdcada3SDoug Rabson /* first authenticate the message */ 479dfdcada3SDoug Rabson if ((why = _authenticate(&r, &msg)) != AUTH_OK) { 480dfdcada3SDoug Rabson svcerr_auth(xprt, why); 481dfdcada3SDoug Rabson goto call_done; 482dfdcada3SDoug Rabson } 483dfdcada3SDoug Rabson /* now match message with a registered service*/ 484dfdcada3SDoug Rabson prog_found = FALSE; 485dfdcada3SDoug Rabson low_vers = (rpcvers_t) -1L; 486dfdcada3SDoug Rabson high_vers = (rpcvers_t) 0L; 487dfdcada3SDoug Rabson TAILQ_FOREACH(s, &pool->sp_callouts, sc_link) { 488dfdcada3SDoug Rabson if (s->sc_prog == r.rq_prog) { 489dfdcada3SDoug Rabson if (s->sc_vers == r.rq_vers) { 490dfdcada3SDoug Rabson (*s->sc_dispatch)(&r, xprt); 491dfdcada3SDoug Rabson goto call_done; 492dfdcada3SDoug Rabson } /* found correct version */ 493dfdcada3SDoug Rabson prog_found = TRUE; 494dfdcada3SDoug Rabson if (s->sc_vers < low_vers) 495dfdcada3SDoug Rabson low_vers = s->sc_vers; 496dfdcada3SDoug Rabson if (s->sc_vers > high_vers) 497dfdcada3SDoug Rabson high_vers = s->sc_vers; 498dfdcada3SDoug Rabson } /* found correct program */ 499dfdcada3SDoug Rabson } 500dfdcada3SDoug Rabson /* 501dfdcada3SDoug Rabson * if we got here, the program or version 502dfdcada3SDoug Rabson * is not served ... 503dfdcada3SDoug Rabson */ 504dfdcada3SDoug Rabson if (prog_found) 505dfdcada3SDoug Rabson svcerr_progvers(xprt, low_vers, high_vers); 506dfdcada3SDoug Rabson else 507dfdcada3SDoug Rabson svcerr_noprog(xprt); 508dfdcada3SDoug Rabson /* Fall through to ... */ 509dfdcada3SDoug Rabson } 510dfdcada3SDoug Rabson /* 511dfdcada3SDoug Rabson * Check if the xprt has been disconnected in a 512dfdcada3SDoug Rabson * recursive call in the service dispatch routine. 513dfdcada3SDoug Rabson * If so, then break. 514dfdcada3SDoug Rabson */ 515dfdcada3SDoug Rabson mtx_lock(&pool->sp_lock); 516dfdcada3SDoug Rabson if (!xprt->xp_registered) { 517dfdcada3SDoug Rabson mtx_unlock(&pool->sp_lock); 518dfdcada3SDoug Rabson break; 519dfdcada3SDoug Rabson } 520dfdcada3SDoug Rabson mtx_unlock(&pool->sp_lock); 521dfdcada3SDoug Rabson call_done: 522dfdcada3SDoug Rabson if ((stat = SVC_STAT(xprt)) == XPRT_DIED) { 523dfdcada3SDoug Rabson SVC_DESTROY(xprt); 524dfdcada3SDoug Rabson break; 525dfdcada3SDoug Rabson } 526dfdcada3SDoug Rabson } while (stat == XPRT_MOREREQS); 527dfdcada3SDoug Rabson } 528dfdcada3SDoug Rabson 529dfdcada3SDoug Rabson void 530dfdcada3SDoug Rabson svc_run(SVCPOOL *pool) 531dfdcada3SDoug Rabson { 532dfdcada3SDoug Rabson SVCXPRT *xprt; 533dfdcada3SDoug Rabson int error; 534dfdcada3SDoug Rabson 535dfdcada3SDoug Rabson mtx_lock(&pool->sp_lock); 536dfdcada3SDoug Rabson 537dfdcada3SDoug Rabson pool->sp_exited = FALSE; 538dfdcada3SDoug Rabson 539dfdcada3SDoug Rabson while (!pool->sp_exited) { 540dfdcada3SDoug Rabson xprt = TAILQ_FIRST(&pool->sp_active); 541dfdcada3SDoug Rabson if (!xprt) { 542dfdcada3SDoug Rabson error = msleep(&pool->sp_active, &pool->sp_lock, PCATCH, 543dfdcada3SDoug Rabson "rpcsvc", 0); 544dfdcada3SDoug Rabson if (error) 545dfdcada3SDoug Rabson break; 546dfdcada3SDoug Rabson continue; 547dfdcada3SDoug Rabson } 548dfdcada3SDoug Rabson 549dfdcada3SDoug Rabson /* 550dfdcada3SDoug Rabson * Move this transport to the end to ensure fairness 551dfdcada3SDoug Rabson * when multiple transports are active. If this was 552dfdcada3SDoug Rabson * the last queued request, svc_getreq will end up 553dfdcada3SDoug Rabson * calling xprt_inactive to remove from the active 554dfdcada3SDoug Rabson * list. 555dfdcada3SDoug Rabson */ 556dfdcada3SDoug Rabson TAILQ_REMOVE(&pool->sp_active, xprt, xp_alink); 557dfdcada3SDoug Rabson TAILQ_INSERT_TAIL(&pool->sp_active, xprt, xp_alink); 558dfdcada3SDoug Rabson 559dfdcada3SDoug Rabson mtx_unlock(&pool->sp_lock); 560dfdcada3SDoug Rabson svc_getreq(xprt); 561dfdcada3SDoug Rabson mtx_lock(&pool->sp_lock); 562dfdcada3SDoug Rabson } 563dfdcada3SDoug Rabson 564dfdcada3SDoug Rabson mtx_unlock(&pool->sp_lock); 565dfdcada3SDoug Rabson } 566dfdcada3SDoug Rabson 567dfdcada3SDoug Rabson void 568dfdcada3SDoug Rabson svc_exit(SVCPOOL *pool) 569dfdcada3SDoug Rabson { 570dfdcada3SDoug Rabson mtx_lock(&pool->sp_lock); 571dfdcada3SDoug Rabson pool->sp_exited = TRUE; 572dfdcada3SDoug Rabson wakeup(&pool->sp_active); 573dfdcada3SDoug Rabson mtx_unlock(&pool->sp_lock); 574dfdcada3SDoug Rabson } 575