xref: /freebsd/lib/libc/rpc/svc.c (revision 4c3af266f6ed1d7255aa89c13405b5db0a37fc3e)
199064799SGarrett Wollman /*
299064799SGarrett Wollman  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
399064799SGarrett Wollman  * unrestricted use provided that this legend is included on all tape
499064799SGarrett Wollman  * media and as a part of the software program in whole or part.  Users
599064799SGarrett Wollman  * may copy or modify Sun RPC without charge, but are not authorized
699064799SGarrett Wollman  * to license or distribute it to anyone else except as part of a product or
799064799SGarrett Wollman  * program developed by the user.
899064799SGarrett Wollman  *
999064799SGarrett Wollman  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
1099064799SGarrett Wollman  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
1199064799SGarrett Wollman  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
1299064799SGarrett Wollman  *
1399064799SGarrett Wollman  * Sun RPC is provided with no support and without any obligation on the
1499064799SGarrett Wollman  * part of Sun Microsystems, Inc. to assist in its use, correction,
1599064799SGarrett Wollman  * modification or enhancement.
1699064799SGarrett Wollman  *
1799064799SGarrett Wollman  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
1899064799SGarrett Wollman  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
1999064799SGarrett Wollman  * OR ANY PART THEREOF.
2099064799SGarrett Wollman  *
2199064799SGarrett Wollman  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
2299064799SGarrett Wollman  * or profits or other special, indirect and consequential damages, even if
2399064799SGarrett Wollman  * Sun has been advised of the possibility of such damages.
2499064799SGarrett Wollman  *
2599064799SGarrett Wollman  * Sun Microsystems, Inc.
2699064799SGarrett Wollman  * 2550 Garcia Avenue
2799064799SGarrett Wollman  * Mountain View, California  94043
2899064799SGarrett Wollman  */
2999064799SGarrett Wollman 
3099064799SGarrett Wollman #if defined(LIBC_SCCS) && !defined(lint)
3199064799SGarrett Wollman /*static char *sccsid = "from: @(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro";*/
3299064799SGarrett Wollman /*static char *sccsid = "from: @(#)svc.c	2.4 88/08/11 4.0 RPCSRC";*/
334c3af266SPoul-Henning Kamp static char *rcsid = "$Id: svc.c,v 1.2 1995/05/30 05:41:31 rgrimes Exp $";
3499064799SGarrett Wollman #endif
3599064799SGarrett Wollman 
3699064799SGarrett Wollman /*
3799064799SGarrett Wollman  * svc.c, Server-side remote procedure call interface.
3899064799SGarrett Wollman  *
3999064799SGarrett Wollman  * There are two sets of procedures here.  The xprt routines are
4099064799SGarrett Wollman  * for handling transport handles.  The svc routines handle the
4199064799SGarrett Wollman  * list of service routines.
4299064799SGarrett Wollman  *
4399064799SGarrett Wollman  * Copyright (C) 1984, Sun Microsystems, Inc.
4499064799SGarrett Wollman  */
4599064799SGarrett Wollman 
464c3af266SPoul-Henning Kamp #include <string.h>
474c3af266SPoul-Henning Kamp #include <stdlib.h>
4899064799SGarrett Wollman #include <sys/errno.h>
4999064799SGarrett Wollman #include <rpc/rpc.h>
5099064799SGarrett Wollman #include <rpc/pmap_clnt.h>
5199064799SGarrett Wollman 
5299064799SGarrett Wollman extern int errno;
5399064799SGarrett Wollman 
5499064799SGarrett Wollman #ifdef FD_SETSIZE
5599064799SGarrett Wollman static SVCXPRT **xports;
5699064799SGarrett Wollman #else
5799064799SGarrett Wollman #define NOFILE 32
5899064799SGarrett Wollman 
5999064799SGarrett Wollman static SVCXPRT *xports[NOFILE];
6099064799SGarrett Wollman #endif /* def FD_SETSIZE */
6199064799SGarrett Wollman 
6299064799SGarrett Wollman #define NULL_SVC ((struct svc_callout *)0)
6399064799SGarrett Wollman #define	RQCRED_SIZE	400		/* this size is excessive */
6499064799SGarrett Wollman 
6599064799SGarrett Wollman /*
6699064799SGarrett Wollman  * The services list
6799064799SGarrett Wollman  * Each entry represents a set of procedures (an rpc program).
6899064799SGarrett Wollman  * The dispatch routine takes request structs and runs the
6999064799SGarrett Wollman  * apropriate procedure.
7099064799SGarrett Wollman  */
7199064799SGarrett Wollman static struct svc_callout {
7299064799SGarrett Wollman 	struct svc_callout *sc_next;
7399064799SGarrett Wollman 	u_long		    sc_prog;
7499064799SGarrett Wollman 	u_long		    sc_vers;
7599064799SGarrett Wollman 	void		    (*sc_dispatch)();
7699064799SGarrett Wollman } *svc_head;
7799064799SGarrett Wollman 
7899064799SGarrett Wollman static struct svc_callout *svc_find();
7999064799SGarrett Wollman 
8099064799SGarrett Wollman /* ***************  SVCXPRT related stuff **************** */
8199064799SGarrett Wollman 
8299064799SGarrett Wollman /*
8399064799SGarrett Wollman  * Activate a transport handle.
8499064799SGarrett Wollman  */
8599064799SGarrett Wollman void
8699064799SGarrett Wollman xprt_register(xprt)
8799064799SGarrett Wollman 	SVCXPRT *xprt;
8899064799SGarrett Wollman {
8999064799SGarrett Wollman 	register int sock = xprt->xp_sock;
9099064799SGarrett Wollman 
9199064799SGarrett Wollman #ifdef FD_SETSIZE
9299064799SGarrett Wollman 	if (xports == NULL) {
9399064799SGarrett Wollman 		xports = (SVCXPRT **)
9499064799SGarrett Wollman 			mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *));
9599064799SGarrett Wollman 	}
9699064799SGarrett Wollman 	if (sock < _rpc_dtablesize()) {
9799064799SGarrett Wollman 		xports[sock] = xprt;
9899064799SGarrett Wollman 		FD_SET(sock, &svc_fdset);
9999064799SGarrett Wollman 	}
10099064799SGarrett Wollman #else
10199064799SGarrett Wollman 	if (sock < NOFILE) {
10299064799SGarrett Wollman 		xports[sock] = xprt;
10399064799SGarrett Wollman 		svc_fds |= (1 << sock);
10499064799SGarrett Wollman 	}
10599064799SGarrett Wollman #endif /* def FD_SETSIZE */
10699064799SGarrett Wollman 
10799064799SGarrett Wollman }
10899064799SGarrett Wollman 
10999064799SGarrett Wollman /*
11099064799SGarrett Wollman  * De-activate a transport handle.
11199064799SGarrett Wollman  */
11299064799SGarrett Wollman void
11399064799SGarrett Wollman xprt_unregister(xprt)
11499064799SGarrett Wollman 	SVCXPRT *xprt;
11599064799SGarrett Wollman {
11699064799SGarrett Wollman 	register int sock = xprt->xp_sock;
11799064799SGarrett Wollman 
11899064799SGarrett Wollman #ifdef FD_SETSIZE
11999064799SGarrett Wollman 	if ((sock < _rpc_dtablesize()) && (xports[sock] == xprt)) {
12099064799SGarrett Wollman 		xports[sock] = (SVCXPRT *)0;
12199064799SGarrett Wollman 		FD_CLR(sock, &svc_fdset);
12299064799SGarrett Wollman 	}
12399064799SGarrett Wollman #else
12499064799SGarrett Wollman 	if ((sock < NOFILE) && (xports[sock] == xprt)) {
12599064799SGarrett Wollman 		xports[sock] = (SVCXPRT *)0;
12699064799SGarrett Wollman 		svc_fds &= ~(1 << sock);
12799064799SGarrett Wollman 	}
12899064799SGarrett Wollman #endif /* def FD_SETSIZE */
12999064799SGarrett Wollman }
13099064799SGarrett Wollman 
13199064799SGarrett Wollman 
13299064799SGarrett Wollman /* ********************** CALLOUT list related stuff ************* */
13399064799SGarrett Wollman 
13499064799SGarrett Wollman /*
13599064799SGarrett Wollman  * Add a service program to the callout list.
13699064799SGarrett Wollman  * The dispatch routine will be called when a rpc request for this
13799064799SGarrett Wollman  * program number comes in.
13899064799SGarrett Wollman  */
13999064799SGarrett Wollman bool_t
14099064799SGarrett Wollman svc_register(xprt, prog, vers, dispatch, protocol)
14199064799SGarrett Wollman 	SVCXPRT *xprt;
14299064799SGarrett Wollman 	u_long prog;
14399064799SGarrett Wollman 	u_long vers;
14499064799SGarrett Wollman 	void (*dispatch)();
14599064799SGarrett Wollman 	int protocol;
14699064799SGarrett Wollman {
14799064799SGarrett Wollman 	struct svc_callout *prev;
14899064799SGarrett Wollman 	register struct svc_callout *s;
14999064799SGarrett Wollman 
15099064799SGarrett Wollman 	if ((s = svc_find(prog, vers, &prev)) != NULL_SVC) {
15199064799SGarrett Wollman 		if (s->sc_dispatch == dispatch)
15299064799SGarrett Wollman 			goto pmap_it;  /* he is registering another xptr */
15399064799SGarrett Wollman 		return (FALSE);
15499064799SGarrett Wollman 	}
15599064799SGarrett Wollman 	s = (struct svc_callout *)mem_alloc(sizeof(struct svc_callout));
15699064799SGarrett Wollman 	if (s == (struct svc_callout *)0) {
15799064799SGarrett Wollman 		return (FALSE);
15899064799SGarrett Wollman 	}
15999064799SGarrett Wollman 	s->sc_prog = prog;
16099064799SGarrett Wollman 	s->sc_vers = vers;
16199064799SGarrett Wollman 	s->sc_dispatch = dispatch;
16299064799SGarrett Wollman 	s->sc_next = svc_head;
16399064799SGarrett Wollman 	svc_head = s;
16499064799SGarrett Wollman pmap_it:
16599064799SGarrett Wollman 	/* now register the information with the local binder service */
16699064799SGarrett Wollman 	if (protocol) {
16799064799SGarrett Wollman 		return (pmap_set(prog, vers, protocol, xprt->xp_port));
16899064799SGarrett Wollman 	}
16999064799SGarrett Wollman 	return (TRUE);
17099064799SGarrett Wollman }
17199064799SGarrett Wollman 
17299064799SGarrett Wollman /*
17399064799SGarrett Wollman  * Remove a service program from the callout list.
17499064799SGarrett Wollman  */
17599064799SGarrett Wollman void
17699064799SGarrett Wollman svc_unregister(prog, vers)
17799064799SGarrett Wollman 	u_long prog;
17899064799SGarrett Wollman 	u_long vers;
17999064799SGarrett Wollman {
18099064799SGarrett Wollman 	struct svc_callout *prev;
18199064799SGarrett Wollman 	register struct svc_callout *s;
18299064799SGarrett Wollman 
18399064799SGarrett Wollman 	if ((s = svc_find(prog, vers, &prev)) == NULL_SVC)
18499064799SGarrett Wollman 		return;
18599064799SGarrett Wollman 	if (prev == NULL_SVC) {
18699064799SGarrett Wollman 		svc_head = s->sc_next;
18799064799SGarrett Wollman 	} else {
18899064799SGarrett Wollman 		prev->sc_next = s->sc_next;
18999064799SGarrett Wollman 	}
19099064799SGarrett Wollman 	s->sc_next = NULL_SVC;
19199064799SGarrett Wollman 	mem_free((char *) s, (u_int) sizeof(struct svc_callout));
19299064799SGarrett Wollman 	/* now unregister the information with the local binder service */
19399064799SGarrett Wollman 	(void)pmap_unset(prog, vers);
19499064799SGarrett Wollman }
19599064799SGarrett Wollman 
19699064799SGarrett Wollman /*
19799064799SGarrett Wollman  * Search the callout list for a program number, return the callout
19899064799SGarrett Wollman  * struct.
19999064799SGarrett Wollman  */
20099064799SGarrett Wollman static struct svc_callout *
20199064799SGarrett Wollman svc_find(prog, vers, prev)
20299064799SGarrett Wollman 	u_long prog;
20399064799SGarrett Wollman 	u_long vers;
20499064799SGarrett Wollman 	struct svc_callout **prev;
20599064799SGarrett Wollman {
20699064799SGarrett Wollman 	register struct svc_callout *s, *p;
20799064799SGarrett Wollman 
20899064799SGarrett Wollman 	p = NULL_SVC;
20999064799SGarrett Wollman 	for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
21099064799SGarrett Wollman 		if ((s->sc_prog == prog) && (s->sc_vers == vers))
21199064799SGarrett Wollman 			goto done;
21299064799SGarrett Wollman 		p = s;
21399064799SGarrett Wollman 	}
21499064799SGarrett Wollman done:
21599064799SGarrett Wollman 	*prev = p;
21699064799SGarrett Wollman 	return (s);
21799064799SGarrett Wollman }
21899064799SGarrett Wollman 
21999064799SGarrett Wollman /* ******************* REPLY GENERATION ROUTINES  ************ */
22099064799SGarrett Wollman 
22199064799SGarrett Wollman /*
22299064799SGarrett Wollman  * Send a reply to an rpc request
22399064799SGarrett Wollman  */
22499064799SGarrett Wollman bool_t
22599064799SGarrett Wollman svc_sendreply(xprt, xdr_results, xdr_location)
22699064799SGarrett Wollman 	register SVCXPRT *xprt;
22799064799SGarrett Wollman 	xdrproc_t xdr_results;
22899064799SGarrett Wollman 	caddr_t xdr_location;
22999064799SGarrett Wollman {
23099064799SGarrett Wollman 	struct rpc_msg rply;
23199064799SGarrett Wollman 
23299064799SGarrett Wollman 	rply.rm_direction = REPLY;
23399064799SGarrett Wollman 	rply.rm_reply.rp_stat = MSG_ACCEPTED;
23499064799SGarrett Wollman 	rply.acpted_rply.ar_verf = xprt->xp_verf;
23599064799SGarrett Wollman 	rply.acpted_rply.ar_stat = SUCCESS;
23699064799SGarrett Wollman 	rply.acpted_rply.ar_results.where = xdr_location;
23799064799SGarrett Wollman 	rply.acpted_rply.ar_results.proc = xdr_results;
23899064799SGarrett Wollman 	return (SVC_REPLY(xprt, &rply));
23999064799SGarrett Wollman }
24099064799SGarrett Wollman 
24199064799SGarrett Wollman /*
24299064799SGarrett Wollman  * No procedure error reply
24399064799SGarrett Wollman  */
24499064799SGarrett Wollman void
24599064799SGarrett Wollman svcerr_noproc(xprt)
24699064799SGarrett Wollman 	register SVCXPRT *xprt;
24799064799SGarrett Wollman {
24899064799SGarrett Wollman 	struct rpc_msg rply;
24999064799SGarrett Wollman 
25099064799SGarrett Wollman 	rply.rm_direction = REPLY;
25199064799SGarrett Wollman 	rply.rm_reply.rp_stat = MSG_ACCEPTED;
25299064799SGarrett Wollman 	rply.acpted_rply.ar_verf = xprt->xp_verf;
25399064799SGarrett Wollman 	rply.acpted_rply.ar_stat = PROC_UNAVAIL;
25499064799SGarrett Wollman 	SVC_REPLY(xprt, &rply);
25599064799SGarrett Wollman }
25699064799SGarrett Wollman 
25799064799SGarrett Wollman /*
25899064799SGarrett Wollman  * Can't decode args error reply
25999064799SGarrett Wollman  */
26099064799SGarrett Wollman void
26199064799SGarrett Wollman svcerr_decode(xprt)
26299064799SGarrett Wollman 	register SVCXPRT *xprt;
26399064799SGarrett Wollman {
26499064799SGarrett Wollman 	struct rpc_msg rply;
26599064799SGarrett Wollman 
26699064799SGarrett Wollman 	rply.rm_direction = REPLY;
26799064799SGarrett Wollman 	rply.rm_reply.rp_stat = MSG_ACCEPTED;
26899064799SGarrett Wollman 	rply.acpted_rply.ar_verf = xprt->xp_verf;
26999064799SGarrett Wollman 	rply.acpted_rply.ar_stat = GARBAGE_ARGS;
27099064799SGarrett Wollman 	SVC_REPLY(xprt, &rply);
27199064799SGarrett Wollman }
27299064799SGarrett Wollman 
27399064799SGarrett Wollman /*
27499064799SGarrett Wollman  * Some system error
27599064799SGarrett Wollman  */
27699064799SGarrett Wollman void
27799064799SGarrett Wollman svcerr_systemerr(xprt)
27899064799SGarrett Wollman 	register SVCXPRT *xprt;
27999064799SGarrett Wollman {
28099064799SGarrett Wollman 	struct rpc_msg rply;
28199064799SGarrett Wollman 
28299064799SGarrett Wollman 	rply.rm_direction = REPLY;
28399064799SGarrett Wollman 	rply.rm_reply.rp_stat = MSG_ACCEPTED;
28499064799SGarrett Wollman 	rply.acpted_rply.ar_verf = xprt->xp_verf;
28599064799SGarrett Wollman 	rply.acpted_rply.ar_stat = SYSTEM_ERR;
28699064799SGarrett Wollman 	SVC_REPLY(xprt, &rply);
28799064799SGarrett Wollman }
28899064799SGarrett Wollman 
28999064799SGarrett Wollman /*
29099064799SGarrett Wollman  * Authentication error reply
29199064799SGarrett Wollman  */
29299064799SGarrett Wollman void
29399064799SGarrett Wollman svcerr_auth(xprt, why)
29499064799SGarrett Wollman 	SVCXPRT *xprt;
29599064799SGarrett Wollman 	enum auth_stat why;
29699064799SGarrett Wollman {
29799064799SGarrett Wollman 	struct rpc_msg rply;
29899064799SGarrett Wollman 
29999064799SGarrett Wollman 	rply.rm_direction = REPLY;
30099064799SGarrett Wollman 	rply.rm_reply.rp_stat = MSG_DENIED;
30199064799SGarrett Wollman 	rply.rjcted_rply.rj_stat = AUTH_ERROR;
30299064799SGarrett Wollman 	rply.rjcted_rply.rj_why = why;
30399064799SGarrett Wollman 	SVC_REPLY(xprt, &rply);
30499064799SGarrett Wollman }
30599064799SGarrett Wollman 
30699064799SGarrett Wollman /*
30799064799SGarrett Wollman  * Auth too weak error reply
30899064799SGarrett Wollman  */
30999064799SGarrett Wollman void
31099064799SGarrett Wollman svcerr_weakauth(xprt)
31199064799SGarrett Wollman 	SVCXPRT *xprt;
31299064799SGarrett Wollman {
31399064799SGarrett Wollman 
31499064799SGarrett Wollman 	svcerr_auth(xprt, AUTH_TOOWEAK);
31599064799SGarrett Wollman }
31699064799SGarrett Wollman 
31799064799SGarrett Wollman /*
31899064799SGarrett Wollman  * Program unavailable error reply
31999064799SGarrett Wollman  */
32099064799SGarrett Wollman void
32199064799SGarrett Wollman svcerr_noprog(xprt)
32299064799SGarrett Wollman 	register SVCXPRT *xprt;
32399064799SGarrett Wollman {
32499064799SGarrett Wollman 	struct rpc_msg rply;
32599064799SGarrett Wollman 
32699064799SGarrett Wollman 	rply.rm_direction = REPLY;
32799064799SGarrett Wollman 	rply.rm_reply.rp_stat = MSG_ACCEPTED;
32899064799SGarrett Wollman 	rply.acpted_rply.ar_verf = xprt->xp_verf;
32999064799SGarrett Wollman 	rply.acpted_rply.ar_stat = PROG_UNAVAIL;
33099064799SGarrett Wollman 	SVC_REPLY(xprt, &rply);
33199064799SGarrett Wollman }
33299064799SGarrett Wollman 
33399064799SGarrett Wollman /*
33499064799SGarrett Wollman  * Program version mismatch error reply
33599064799SGarrett Wollman  */
33699064799SGarrett Wollman void
33799064799SGarrett Wollman svcerr_progvers(xprt, low_vers, high_vers)
33899064799SGarrett Wollman 	register SVCXPRT *xprt;
33999064799SGarrett Wollman 	u_long low_vers;
34099064799SGarrett Wollman 	u_long high_vers;
34199064799SGarrett Wollman {
34299064799SGarrett Wollman 	struct rpc_msg rply;
34399064799SGarrett Wollman 
34499064799SGarrett Wollman 	rply.rm_direction = REPLY;
34599064799SGarrett Wollman 	rply.rm_reply.rp_stat = MSG_ACCEPTED;
34699064799SGarrett Wollman 	rply.acpted_rply.ar_verf = xprt->xp_verf;
34799064799SGarrett Wollman 	rply.acpted_rply.ar_stat = PROG_MISMATCH;
34899064799SGarrett Wollman 	rply.acpted_rply.ar_vers.low = low_vers;
34999064799SGarrett Wollman 	rply.acpted_rply.ar_vers.high = high_vers;
35099064799SGarrett Wollman 	SVC_REPLY(xprt, &rply);
35199064799SGarrett Wollman }
35299064799SGarrett Wollman 
35399064799SGarrett Wollman /* ******************* SERVER INPUT STUFF ******************* */
35499064799SGarrett Wollman 
35599064799SGarrett Wollman /*
35699064799SGarrett Wollman  * Get server side input from some transport.
35799064799SGarrett Wollman  *
35899064799SGarrett Wollman  * Statement of authentication parameters management:
35999064799SGarrett Wollman  * This function owns and manages all authentication parameters, specifically
36099064799SGarrett Wollman  * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
36199064799SGarrett Wollman  * the "cooked" credentials (rqst->rq_clntcred).
36299064799SGarrett Wollman  * However, this function does not know the structure of the cooked
36399064799SGarrett Wollman  * credentials, so it make the following assumptions:
36499064799SGarrett Wollman  *   a) the structure is contiguous (no pointers), and
36599064799SGarrett Wollman  *   b) the cred structure size does not exceed RQCRED_SIZE bytes.
36699064799SGarrett Wollman  * In all events, all three parameters are freed upon exit from this routine.
36799064799SGarrett Wollman  * The storage is trivially management on the call stack in user land, but
36899064799SGarrett Wollman  * is mallocated in kernel land.
36999064799SGarrett Wollman  */
37099064799SGarrett Wollman 
37199064799SGarrett Wollman void
37299064799SGarrett Wollman svc_getreq(rdfds)
37399064799SGarrett Wollman 	int rdfds;
37499064799SGarrett Wollman {
37599064799SGarrett Wollman #ifdef FD_SETSIZE
37699064799SGarrett Wollman 	fd_set readfds;
37799064799SGarrett Wollman 
37899064799SGarrett Wollman 	FD_ZERO(&readfds);
37999064799SGarrett Wollman 	readfds.fds_bits[0] = rdfds;
38099064799SGarrett Wollman 	svc_getreqset(&readfds);
38199064799SGarrett Wollman #else
38299064799SGarrett Wollman 	int readfds = rdfds & svc_fds;
38399064799SGarrett Wollman 
38499064799SGarrett Wollman 	svc_getreqset(&readfds);
38599064799SGarrett Wollman #endif /* def FD_SETSIZE */
38699064799SGarrett Wollman }
38799064799SGarrett Wollman 
38899064799SGarrett Wollman void
38999064799SGarrett Wollman svc_getreqset(readfds)
39099064799SGarrett Wollman #ifdef FD_SETSIZE
39199064799SGarrett Wollman 	fd_set *readfds;
39299064799SGarrett Wollman {
39399064799SGarrett Wollman #else
39499064799SGarrett Wollman 	int *readfds;
39599064799SGarrett Wollman {
39699064799SGarrett Wollman     int readfds_local = *readfds;
39799064799SGarrett Wollman #endif /* def FD_SETSIZE */
39899064799SGarrett Wollman 	enum xprt_stat stat;
39999064799SGarrett Wollman 	struct rpc_msg msg;
40099064799SGarrett Wollman 	int prog_found;
40199064799SGarrett Wollman 	u_long low_vers;
40299064799SGarrett Wollman 	u_long high_vers;
40399064799SGarrett Wollman 	struct svc_req r;
40499064799SGarrett Wollman 	register SVCXPRT *xprt;
40599064799SGarrett Wollman 	register u_long mask;
40699064799SGarrett Wollman 	register int bit;
40799064799SGarrett Wollman 	register u_long *maskp;
40899064799SGarrett Wollman 	register int setsize;
40999064799SGarrett Wollman 	register int sock;
41099064799SGarrett Wollman 	char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];
41199064799SGarrett Wollman 	msg.rm_call.cb_cred.oa_base = cred_area;
41299064799SGarrett Wollman 	msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
41399064799SGarrett Wollman 	r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]);
41499064799SGarrett Wollman 
41599064799SGarrett Wollman 
41699064799SGarrett Wollman #ifdef FD_SETSIZE
41799064799SGarrett Wollman 	setsize = _rpc_dtablesize();
41899064799SGarrett Wollman 	maskp = (u_long *)readfds->fds_bits;
41999064799SGarrett Wollman 	for (sock = 0; sock < setsize; sock += NFDBITS) {
42099064799SGarrett Wollman 	    for (mask = *maskp++; bit = ffs(mask); mask ^= (1 << (bit - 1))) {
42199064799SGarrett Wollman 		/* sock has input waiting */
42299064799SGarrett Wollman 		xprt = xports[sock + bit - 1];
42399064799SGarrett Wollman #else
42499064799SGarrett Wollman 	for (sock = 0; readfds_local != 0; sock++, readfds_local >>= 1) {
42599064799SGarrett Wollman 	    if ((readfds_local & 1) != 0) {
42699064799SGarrett Wollman 		/* sock has input waiting */
42799064799SGarrett Wollman 		xprt = xports[sock];
42899064799SGarrett Wollman #endif /* def FD_SETSIZE */
42999064799SGarrett Wollman 		/* now receive msgs from xprtprt (support batch calls) */
43099064799SGarrett Wollman 		do {
43199064799SGarrett Wollman 			if (SVC_RECV(xprt, &msg)) {
43299064799SGarrett Wollman 
43399064799SGarrett Wollman 				/* now find the exported program and call it */
43499064799SGarrett Wollman 				register struct svc_callout *s;
43599064799SGarrett Wollman 				enum auth_stat why;
43699064799SGarrett Wollman 
43799064799SGarrett Wollman 				r.rq_xprt = xprt;
43899064799SGarrett Wollman 				r.rq_prog = msg.rm_call.cb_prog;
43999064799SGarrett Wollman 				r.rq_vers = msg.rm_call.cb_vers;
44099064799SGarrett Wollman 				r.rq_proc = msg.rm_call.cb_proc;
44199064799SGarrett Wollman 				r.rq_cred = msg.rm_call.cb_cred;
44299064799SGarrett Wollman 				/* first authenticate the message */
44399064799SGarrett Wollman 				if ((why= _authenticate(&r, &msg)) != AUTH_OK) {
44499064799SGarrett Wollman 					svcerr_auth(xprt, why);
44599064799SGarrett Wollman 					goto call_done;
44699064799SGarrett Wollman 				}
44799064799SGarrett Wollman 				/* now match message with a registered service*/
44899064799SGarrett Wollman 				prog_found = FALSE;
44999064799SGarrett Wollman 				low_vers = 0 - 1;
45099064799SGarrett Wollman 				high_vers = 0;
45199064799SGarrett Wollman 				for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
45299064799SGarrett Wollman 					if (s->sc_prog == r.rq_prog) {
45399064799SGarrett Wollman 						if (s->sc_vers == r.rq_vers) {
45499064799SGarrett Wollman 							(*s->sc_dispatch)(&r, xprt);
45599064799SGarrett Wollman 							goto call_done;
45699064799SGarrett Wollman 						}  /* found correct version */
45799064799SGarrett Wollman 						prog_found = TRUE;
45899064799SGarrett Wollman 						if (s->sc_vers < low_vers)
45999064799SGarrett Wollman 							low_vers = s->sc_vers;
46099064799SGarrett Wollman 						if (s->sc_vers > high_vers)
46199064799SGarrett Wollman 							high_vers = s->sc_vers;
46299064799SGarrett Wollman 					}   /* found correct program */
46399064799SGarrett Wollman 				}
46499064799SGarrett Wollman 				/*
46599064799SGarrett Wollman 				 * if we got here, the program or version
46699064799SGarrett Wollman 				 * is not served ...
46799064799SGarrett Wollman 				 */
46899064799SGarrett Wollman 				if (prog_found)
46999064799SGarrett Wollman 					svcerr_progvers(xprt,
47099064799SGarrett Wollman 					low_vers, high_vers);
47199064799SGarrett Wollman 				else
47299064799SGarrett Wollman 					 svcerr_noprog(xprt);
47399064799SGarrett Wollman 				/* Fall through to ... */
47499064799SGarrett Wollman 			}
47599064799SGarrett Wollman 		call_done:
47699064799SGarrett Wollman 			if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
47799064799SGarrett Wollman 				SVC_DESTROY(xprt);
47899064799SGarrett Wollman 				break;
47999064799SGarrett Wollman 			}
48099064799SGarrett Wollman 		} while (stat == XPRT_MOREREQS);
48199064799SGarrett Wollman 	    }
48299064799SGarrett Wollman 	}
48399064799SGarrett Wollman }
484