1/*	$NetBSD: rpcb_svc_com.c,v 1.15 2011/08/31 13:32:40 joerg Exp $	*/
2
3/*
4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5 * unrestricted use provided that this legend is included on all tape
6 * media and as a part of the software program in whole or part.  Users
7 * may copy or modify Sun RPC without charge, but are not authorized
8 * to license or distribute it to anyone else except as part of a product or
9 * program developed by the user.
10 *
11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14 *
15 * Sun RPC is provided with no support and without any obligation on the
16 * part of Sun Microsystems, Inc. to assist in its use, correction,
17 * modification or enhancement.
18 *
19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21 * OR ANY PART THEREOF.
22 *
23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24 * or profits or other special, indirect and consequential damages, even if
25 * Sun has been advised of the possibility of such damages.
26 *
27 * Sun Microsystems, Inc.
28 * 2550 Garcia Avenue
29 * Mountain View, California  94043
30 */
31/*
32 * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
33 */
34
35/* #ident	"@(#)rpcb_svc_com.c	1.18	94/05/02 SMI" */
36
37/*
38 * rpcb_svc_com.c
39 * The commom server procedure for the rpcbind.
40 */
41
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <sys/param.h>
45#include <sys/socket.h>
46#include <rpc/rpc.h>
47#include <rpc/rpcb_prot.h>
48#include <netconfig.h>
49#include <errno.h>
50#include <syslog.h>
51#include <unistd.h>
52#include <stdio.h>
53#include <poll.h>
54#ifdef PORTMAP
55#include <netinet/in.h>
56#include <rpc/pmap_prot.h>
57#endif /* PORTMAP */
58#include <string.h>
59#include <stdlib.h>
60
61#include "rpcbind.h"
62#include "svc_dg.h"
63
64#define RPC_BUF_MAX	65536	/* can be raised if required */
65
66static char emptystring[] = "";
67static int rpcb_rmtcalls;
68
69struct rmtcallfd_list {
70	int fd;
71	SVCXPRT *xprt;
72	char *netid;
73	struct rmtcallfd_list *next;
74};
75
76#define NFORWARD        64
77#define MAXTIME_OFF     300     /* 5 minutes */
78
79struct finfo {
80	int             flag;
81#define FINFO_ACTIVE    0x1
82	u_int32_t       caller_xid;
83        struct netbuf   *caller_addr;
84	u_int32_t       forward_xid;
85	int             forward_fd;
86	char            *uaddr;
87	rpcproc_t       reply_type;
88	rpcvers_t       versnum;
89	time_t          time;
90};
91static struct finfo     FINFO[NFORWARD];
92
93
94static bool_t xdr_encap_parms(XDR *, struct encap_parms *);
95static bool_t xdr_rmtcall_args(XDR *, struct r_rmtcall_args *);
96static bool_t xdr_rmtcall_result(XDR *, struct r_rmtcall_args *);
97static bool_t xdr_opaque_parms(XDR *, struct r_rmtcall_args *);
98static int find_rmtcallfd_by_netid(char *);
99static SVCXPRT *find_rmtcallxprt_by_fd(int);
100static u_int32_t forward_register(u_int32_t, struct netbuf *, int, char *,
101				    rpcproc_t, rpcvers_t);
102static struct finfo *forward_find(u_int32_t);
103static int free_slot_by_xid(u_int32_t);
104static int free_slot_by_index(int);
105static int netbufcmp(struct netbuf *, struct netbuf *);
106static struct netbuf *netbufdup(struct netbuf *);
107static void netbuffree(struct netbuf *);
108static int check_rmtcalls(struct pollfd *, int);
109static void xprt_set_caller(SVCXPRT *, struct finfo *);
110static void send_svcsyserr(SVCXPRT *, struct finfo *);
111static void handle_reply(int, SVCXPRT *);
112static void find_versions(rpcprog_t, char *, rpcvers_t *, rpcvers_t *);
113static rpcblist_ptr find_service(rpcprog_t, rpcvers_t, char *);
114static char *getowner(SVCXPRT *, char *, size_t);
115static int add_pmaplist(RPCB *);
116static int del_pmaplist(RPCB *);
117
118/*
119 * Set a mapping of program, version, netid
120 */
121/* ARGSUSED */
122void *
123rpcbproc_set_com(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
124		 rpcvers_t rpcbversnum)
125{
126	RPCB *regp = (RPCB *)arg;
127	static bool_t ans;
128	char owner[64];
129
130#ifdef RPCBIND_DEBUG
131	if (debugging)
132		fprintf(stderr, "RPCB_SET request for (%lu, %lu, %s, %s) : ",
133		    (unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
134		    regp->r_netid, regp->r_addr);
135#endif
136	ans = map_set(regp, getowner(transp, owner, sizeof owner));
137#ifdef RPCBIND_DEBUG
138	if (debugging)
139		fprintf(stderr, "%s\n", ans == TRUE ? "succeeded" : "failed");
140#endif
141	/* XXX: should have used some defined constant here */
142	rpcbs_set(rpcbversnum - 2, ans);
143	return (void *)&ans;
144}
145
146bool_t
147map_set(RPCB *regp, char *owner)
148{
149	RPCB reg, *a;
150	rpcblist_ptr rbl, fnd;
151
152	reg = *regp;
153	/*
154	 * check to see if already used
155	 * find_service returns a hit even if
156	 * the versions don't match, so check for it
157	 */
158	fnd = find_service(reg.r_prog, reg.r_vers, reg.r_netid);
159	if (fnd && (fnd->rpcb_map.r_vers == reg.r_vers)) {
160		if (!strcmp(fnd->rpcb_map.r_addr, reg.r_addr))
161			/*
162			 * if these match then it is already
163			 * registered so just say "OK".
164			 */
165			return (TRUE);
166		else
167			return (FALSE);
168	}
169	/*
170	 * add to the end of the list
171	 */
172	rbl = (rpcblist_ptr) malloc((u_int)sizeof (RPCBLIST));
173	if (rbl == NULL) {
174		return (FALSE);
175	}
176	a = &(rbl->rpcb_map);
177	a->r_prog = reg.r_prog;
178	a->r_vers = reg.r_vers;
179	a->r_netid = strdup(reg.r_netid);
180	a->r_addr = strdup(reg.r_addr);
181	a->r_owner = strdup(owner);
182	if (!a->r_addr || !a->r_netid || !a->r_owner) {
183		if (a->r_netid)
184			free((void *) a->r_netid);
185		if (a->r_addr)
186			free((void *) a->r_addr);
187		if (a->r_owner)
188			free((void *) a->r_owner);
189		free((void *)rbl);
190		return (FALSE);
191	}
192	rbl->rpcb_next = NULL;
193	if (list_rbl == NULL) {
194		list_rbl = rbl;
195	} else {
196		for (fnd = list_rbl; fnd->rpcb_next;
197			fnd = fnd->rpcb_next)
198			;
199		fnd->rpcb_next = rbl;
200	}
201#ifdef PORTMAP
202	(void) add_pmaplist(regp);
203#endif
204	return (TRUE);
205}
206
207/*
208 * Unset a mapping of program, version, netid
209 */
210/* ARGSUSED */
211void *
212rpcbproc_unset_com(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
213		   rpcvers_t rpcbversnum)
214{
215	RPCB *regp = (RPCB *)arg;
216	static bool_t ans;
217	char owner[64];
218
219#ifdef RPCBIND_DEBUG
220	if (debugging)
221		fprintf(stderr, "RPCB_UNSET request for (%lu, %lu, %s) : ",
222		    (unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
223		    regp->r_netid);
224#endif
225	ans = map_unset(regp, getowner(transp, owner, sizeof owner));
226#ifdef RPCBIND_DEBUG
227	if (debugging)
228		fprintf(stderr, "%s\n", ans == TRUE ? "succeeded" : "failed");
229#endif
230	/* XXX: should have used some defined constant here */
231	rpcbs_unset(rpcbversnum - 2, ans);
232	return (void *)&ans;
233}
234
235bool_t
236map_unset(RPCB *regp, const char *owner)
237{
238	int ans = 0;
239	rpcblist_ptr rbl, prev, tmp;
240
241	if (owner == NULL)
242		return (0);
243
244	for (prev = NULL, rbl = list_rbl; rbl; /* cstyle */) {
245		if ((rbl->rpcb_map.r_prog != regp->r_prog) ||
246			(rbl->rpcb_map.r_vers != regp->r_vers) ||
247			(regp->r_netid[0] && strcasecmp(regp->r_netid,
248				rbl->rpcb_map.r_netid))) {
249			/* both rbl & prev move forwards */
250			prev = rbl;
251			rbl = rbl->rpcb_next;
252			continue;
253		}
254		/*
255		 * Check whether appropriate uid. Unset only
256		 * if superuser or the owner itself.
257		 */
258		if (strcmp(owner, rpcbind_superuser) &&
259			strcmp(rbl->rpcb_map.r_owner, owner))
260			return (0);
261		/* found it; rbl moves forward, prev stays */
262		ans = 1;
263		tmp = rbl;
264		rbl = rbl->rpcb_next;
265		if (prev == NULL)
266			list_rbl = rbl;
267		else
268			prev->rpcb_next = rbl;
269		free((void *) tmp->rpcb_map.r_addr);
270		free((void *) tmp->rpcb_map.r_netid);
271		free((void *) tmp->rpcb_map.r_owner);
272		free((void *) tmp);
273	}
274#ifdef PORTMAP
275	if (ans)
276		(void) del_pmaplist(regp);
277#endif
278	/*
279	 * We return 1 either when the entry was not there or it
280	 * was able to unset it.  It can come to this point only if
281	 * atleast one of the conditions is true.
282	 */
283	return (1);
284}
285
286void
287delete_prog(rpcprog_t prog)
288{
289	RPCB reg;
290	register rpcblist_ptr rbl;
291
292	for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) {
293		if ((rbl->rpcb_map.r_prog != prog))
294			continue;
295		if (is_bound(rbl->rpcb_map.r_netid, rbl->rpcb_map.r_addr))
296			continue;
297		reg.r_prog = rbl->rpcb_map.r_prog;
298		reg.r_vers = rbl->rpcb_map.r_vers;
299		reg.r_netid = strdup(rbl->rpcb_map.r_netid);
300		(void)map_unset(&reg, rpcbind_superuser);
301		free(reg.r_netid);
302	}
303}
304
305void *
306rpcbproc_getaddr_com(RPCB *regp, struct svc_req *rqstp, SVCXPRT *transp,
307		     rpcvers_t rpcbversnum, rpcvers_t verstype)
308{
309	static char *uaddr;
310	char *saddr = NULL;
311	rpcblist_ptr fnd;
312
313	if (uaddr && uaddr[0])
314		free((void *) uaddr);
315	fnd = find_service(regp->r_prog, regp->r_vers, transp->xp_netid);
316	if (fnd && ((verstype == RPCB_ALLVERS) ||
317		    (regp->r_vers == fnd->rpcb_map.r_vers))) {
318		if (*(regp->r_addr) != '\0') {  /* may contain a hint about */
319			saddr = regp->r_addr;   /* the interface that we    */
320		}				/* should use */
321		if (!(uaddr = mergeaddr(transp, transp->xp_netid,
322				fnd->rpcb_map.r_addr, saddr))) {
323			/* Try whatever we have */
324			uaddr = strdup(fnd->rpcb_map.r_addr);
325		} else if (!uaddr[0]) {
326			/*
327			 * The server died.  Unset all versions of this prog.
328			 */
329			delete_prog(regp->r_prog);
330			uaddr = emptystring;
331		}
332	} else {
333		uaddr = emptystring;
334	}
335#ifdef RPCBIND_DEBUG
336	if (debugging)
337		fprintf(stderr, "getaddr: %s\n", uaddr);
338#endif
339	/* XXX: should have used some defined constant here */
340	rpcbs_getaddr(rpcbversnum - 2, regp->r_prog, regp->r_vers,
341		transp->xp_netid, uaddr);
342	return (void *)&uaddr;
343}
344
345/* ARGSUSED */
346void *
347rpcbproc_gettime_com(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
348		     rpcvers_t rpcbversnum)
349{
350	static time_t curtime;
351
352	(void) time(&curtime);
353	return (void *)&curtime;
354}
355
356/*
357 * Convert uaddr to taddr. Should be used only by
358 * local servers/clients. (kernel level stuff only)
359 */
360/* ARGSUSED */
361void *
362rpcbproc_uaddr2taddr_com(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
363			 rpcvers_t rpcbversnum)
364{
365	char **uaddrp = (char **)arg;
366	struct netconfig *nconf;
367	static struct netbuf nbuf;
368	static struct netbuf *taddr;
369
370	if (taddr) {
371		free((void *) taddr->buf);
372		free((void *) taddr);
373	}
374	if (((nconf = rpcbind_get_conf(transp->xp_netid)) == NULL) ||
375	    ((taddr = uaddr2taddr(nconf, *uaddrp)) == NULL)) {
376		(void) memset((char *)&nbuf, 0, sizeof (struct netbuf));
377		return (void *)&nbuf;
378	}
379	return (void *)taddr;
380}
381
382/*
383 * Convert taddr to uaddr. Should be used only by
384 * local servers/clients. (kernel level stuff only)
385 */
386/* ARGSUSED */
387void *
388rpcbproc_taddr2uaddr_com(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
389			 rpcvers_t rpcbversnum)
390{
391	struct netbuf *taddr = (struct netbuf *)arg;
392	static char *uaddr;
393	struct netconfig *nconf;
394
395#ifdef CHEW_FDS
396	int fd;
397
398	if ((fd = open("/dev/null", O_RDONLY)) == -1) {
399		uaddr = strerror(errno);
400		return (&uaddr);
401	}
402#endif /* CHEW_FDS */
403	if (uaddr && !uaddr[0])
404		free((void *) uaddr);
405	if (((nconf = rpcbind_get_conf(transp->xp_netid)) == NULL) ||
406		((uaddr = taddr2uaddr(nconf, taddr)) == NULL)) {
407		uaddr = emptystring;
408	}
409	return (void *)&uaddr;
410}
411
412
413static bool_t
414xdr_encap_parms(XDR *xdrs, struct encap_parms *epp)
415{
416	return (xdr_bytes(xdrs, &(epp->args), (u_int *) &(epp->arglen), ~0));
417}
418
419/*
420 * XDR remote call arguments.  It ignores the address part.
421 * written for XDR_DECODE direction only
422 */
423static bool_t
424xdr_rmtcall_args(XDR *xdrs, struct r_rmtcall_args *cap)
425{
426	/* does not get the address or the arguments */
427	if (xdr_u_int32_t(xdrs, &(cap->rmt_prog)) &&
428	    xdr_u_int32_t(xdrs, &(cap->rmt_vers)) &&
429	    xdr_u_int32_t(xdrs, &(cap->rmt_proc))) {
430		return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
431	}
432	return (FALSE);
433}
434
435/*
436 * XDR remote call results along with the address.  Ignore
437 * program number, version  number and proc number.
438 * Written for XDR_ENCODE direction only.
439 */
440static bool_t
441xdr_rmtcall_result(XDR *xdrs, struct r_rmtcall_args *cap)
442{
443	bool_t result;
444
445#ifdef PORTMAP
446	if (cap->rmt_localvers == PMAPVERS) {
447		int h1, h2, h3, h4, p1, p2;
448		u_long port;
449
450		/* interpret the universal address for TCP/IP */
451		if (sscanf(cap->rmt_uaddr, "%d.%d.%d.%d.%d.%d",
452			&h1, &h2, &h3, &h4, &p1, &p2) != 6)
453			return (FALSE);
454		port = ((p1 & 0xff) << 8) + (p2 & 0xff);
455		result = xdr_u_long(xdrs, &port);
456	} else
457#endif
458		if ((cap->rmt_localvers == RPCBVERS) ||
459		    (cap->rmt_localvers == RPCBVERS4)) {
460		result = xdr_wrapstring(xdrs, &(cap->rmt_uaddr));
461	} else {
462		return (FALSE);
463	}
464	if (result == TRUE)
465		return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
466	return (FALSE);
467}
468
469/*
470 * only worries about the struct encap_parms part of struct r_rmtcall_args.
471 * The arglen must already be set!!
472 */
473static bool_t
474xdr_opaque_parms(XDR *xdrs, struct r_rmtcall_args *cap)
475{
476	return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen));
477}
478
479static struct rmtcallfd_list *rmthead;
480static struct rmtcallfd_list *rmttail;
481
482int
483create_rmtcall_fd(struct netconfig *nconf)
484{
485	int fd;
486	struct rmtcallfd_list *rmt;
487	SVCXPRT *xprt;
488
489	if ((fd = __rpc_nconf2fd(nconf)) == -1) {
490		if (debugging)
491			fprintf(stderr,
492	"create_rmtcall_fd: couldn't open \"%s\" (errno %d)\n",
493			nconf->nc_device, errno);
494		return (-1);
495	}
496	xprt = svc_tli_create(fd, 0, (struct t_bind *) 0, 0, 0);
497	if (xprt == NULL) {
498		if (debugging)
499			fprintf(stderr,
500				"create_rmtcall_fd: svc_tli_create failed\n");
501		return (-1);
502	}
503	rmt = (struct rmtcallfd_list *)malloc((u_int)
504		sizeof (struct rmtcallfd_list));
505	if (rmt == NULL) {
506		syslog(LOG_ERR, "create_rmtcall_fd: no memory!");
507		return (-1);
508	}
509	rmt->xprt = xprt;
510	rmt->netid = strdup(nconf->nc_netid);
511	xprt->xp_netid = rmt->netid;
512	rmt->fd = fd;
513	rmt->next = NULL;
514	if (rmthead == NULL) {
515		rmthead = rmt;
516		rmttail = rmt;
517	} else {
518		rmttail->next = rmt;
519		rmttail = rmt;
520	}
521	/* XXX not threadsafe */
522	if (fd > svc_maxfd)
523		svc_maxfd = fd;
524	FD_SET(fd, &svc_fdset);
525	return (fd);
526}
527
528static int
529find_rmtcallfd_by_netid(char *netid)
530{
531	struct rmtcallfd_list *rmt;
532
533	for (rmt = rmthead; rmt != NULL; rmt = rmt->next) {
534		if (strcmp(netid, rmt->netid) == 0) {
535			return (rmt->fd);
536		}
537	}
538	return (-1);
539}
540
541static SVCXPRT *
542find_rmtcallxprt_by_fd(int fd)
543{
544	struct rmtcallfd_list *rmt;
545
546	for (rmt = rmthead; rmt != NULL; rmt = rmt->next) {
547		if (fd == rmt->fd) {
548			return (rmt->xprt);
549		}
550	}
551	return (NULL);
552}
553
554
555/*
556 * Call a remote procedure service.  This procedure is very quiet when things
557 * go wrong.  The proc is written to support broadcast rpc.  In the broadcast
558 * case, a machine should shut-up instead of complain, lest the requestor be
559 * overrun with complaints at the expense of not hearing a valid reply.
560 * When receiving a request and verifying that the service exists, we
561 *
562 *	receive the request
563 *
564 *	open a new TLI endpoint on the same transport on which we received
565 *	the original request
566 *
567 *	remember the original request's XID (which requires knowing the format
568 *	of the svc_dg_data structure)
569 *
570 *	forward the request, with a new XID, to the requested service,
571 *	remembering the XID used to send this request (for later use in
572 *	reassociating the answer with the original request), the requestor's
573 *	address, the file descriptor on which the forwarded request is
574 *	made and the service's address.
575 *
576 *	mark the file descriptor on which we anticipate receiving a reply from
577 *	the service and one to select for in our private svc_run procedure
578 *
579 * At some time in the future, a reply will be received from the service to
580 * which we forwarded the request.  At that time, we detect that the socket
581 * used was for forwarding (by looking through the finfo structures to see
582 * whether the fd corresponds to one of those) and call handle_reply() to
583 *
584 *	receive the reply
585 *
586 *	bundle the reply, along with the service's universal address
587 *
588 *	create a SVCXPRT structure and use a version of svc_sendreply
589 *	that allows us to specify the reply XID and destination, send the reply
590 *	to the original requestor.
591 */
592
593void
594rpcbproc_callit_com(struct svc_req *rqstp, SVCXPRT *transp,
595		    rpcproc_t reply_type, rpcvers_t versnum)
596{
597	register rpcblist_ptr rbl;
598	struct netconfig *nconf;
599	struct netbuf *caller;
600	struct r_rmtcall_args a;
601	char *buf_alloc = NULL, *outbufp;
602	char *outbuf_alloc = NULL;
603	char buf[RPC_BUF_MAX], outbuf[RPC_BUF_MAX];
604	struct netbuf *na = NULL;
605	struct rpc_msg call_msg;
606	int outlen;
607	u_int sendsz;
608	XDR outxdr;
609	AUTH *auth;
610	int fd = -1;
611	char *uaddr, *m_uaddr, *local_uaddr = NULL;
612	u_int32_t *xidp;
613	struct __rpc_sockinfo si;
614	struct sockaddr *localsa;
615	struct netbuf tbuf;
616
617	if (!__rpc_fd2sockinfo(transp->xp_fd, &si)) {
618		if (reply_type == RPCBPROC_INDIRECT)
619			svcerr_systemerr(transp);
620		return;
621	}
622	if (si.si_socktype != SOCK_DGRAM)
623		return;	/* Only datagram type accepted */
624	sendsz = __rpc_get_t_size(si.si_af, si.si_proto, UDPMSGSIZE);
625	if (sendsz == 0) {	/* data transfer not supported */
626		if (reply_type == RPCBPROC_INDIRECT)
627			svcerr_systemerr(transp);
628		return;
629	}
630	/*
631	 * Should be multiple of 4 for XDR.
632	 */
633	sendsz = ((sendsz + 3) / 4) * 4;
634	if (sendsz > RPC_BUF_MAX) {
635#ifdef	notyet
636		buf_alloc = alloca(sendsz);		/* not in IDR2? */
637#else
638		buf_alloc = malloc(sendsz);
639#endif	/* notyet */
640		if (buf_alloc == NULL) {
641			if (debugging)
642				fprintf(stderr,
643					"rpcbproc_callit_com:  No Memory!\n");
644			if (reply_type == RPCBPROC_INDIRECT)
645				svcerr_systemerr(transp);
646			return;
647		}
648		a.rmt_args.args = buf_alloc;
649	} else {
650		a.rmt_args.args = buf;
651	}
652
653	call_msg.rm_xid = 0;	/* For error checking purposes */
654	if (!svc_getargs(transp, (xdrproc_t) xdr_rmtcall_args, (char *) &a)) {
655		if (reply_type == RPCBPROC_INDIRECT)
656			svcerr_decode(transp);
657		if (debugging)
658			fprintf(stderr,
659			"rpcbproc_callit_com:  svc_getargs failed\n");
660		goto error;
661	}
662
663	if (!check_callit(transp, &a, versnum)) {
664		svcerr_weakauth(transp);
665		goto error;
666	}
667
668	caller = svc_getrpccaller(transp);
669#ifdef RPCBIND_DEBUG
670	if (debugging) {
671		uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid), caller);
672		fprintf(stderr, "%s %s req for (%lu, %lu, %lu, %s) from %s : ",
673			versnum == PMAPVERS ? "pmap_rmtcall" :
674			versnum == RPCBVERS ? "rpcb_rmtcall" :
675			versnum == RPCBVERS4 ? "rpcb_indirect" :
676			rpcbind_unknown,
677			reply_type == RPCBPROC_INDIRECT ? "indirect" : "callit",
678			(unsigned long)a.rmt_prog, (unsigned long)a.rmt_vers,
679			(unsigned long)a.rmt_proc, transp->xp_netid,
680			uaddr ? uaddr : rpcbind_unknown);
681		if (uaddr)
682			free((void *) uaddr);
683	}
684#endif
685
686	rbl = find_service(a.rmt_prog, a.rmt_vers, transp->xp_netid);
687
688	rpcbs_rmtcall(versnum - 2, reply_type, a.rmt_prog, a.rmt_vers,
689			a.rmt_proc, transp->xp_netid, rbl);
690
691	if (rbl == NULL) {
692#ifdef RPCBIND_DEBUG
693		if (debugging)
694			fprintf(stderr, "not found\n");
695#endif
696		if (reply_type == RPCBPROC_INDIRECT)
697			svcerr_noprog(transp);
698		goto error;
699	}
700	if (rbl->rpcb_map.r_vers != a.rmt_vers) {
701		if (reply_type == RPCBPROC_INDIRECT) {
702			rpcvers_t vers_low, vers_high;
703
704			find_versions(a.rmt_prog, transp->xp_netid,
705				&vers_low, &vers_high);
706			svcerr_progvers(transp, vers_low, vers_high);
707		}
708		goto error;
709	}
710
711#ifdef RPCBIND_DEBUG
712	if (debugging)
713		fprintf(stderr, "found at uaddr %s\n", rbl->rpcb_map.r_addr);
714#endif
715	/*
716	 *	Check whether this entry is valid and a server is present
717	 *	Mergeaddr() returns NULL if no such entry is present, and
718	 *	returns "" if the entry was present but the server is not
719	 *	present (i.e., it crashed).
720	 */
721	if (reply_type == RPCBPROC_INDIRECT) {
722		uaddr = mergeaddr(transp, transp->xp_netid,
723			rbl->rpcb_map.r_addr, NULL);
724		if ((uaddr == NULL) || uaddr[0] == '\0') {
725			svcerr_noprog(transp);
726			if (uaddr != NULL) {
727				free((void *) uaddr);
728			}
729			goto error;
730		}
731		if (uaddr != NULL) {
732			free((void *) uaddr);
733		}
734	}
735	nconf = rpcbind_get_conf(transp->xp_netid);
736	if (nconf == NULL) {
737		if (reply_type == RPCBPROC_INDIRECT)
738			svcerr_systemerr(transp);
739		if (debugging)
740			fprintf(stderr,
741			"rpcbproc_callit_com:  rpcbind_get_conf failed\n");
742		goto error;
743	}
744	localsa = local_sa(((struct sockaddr *)caller->buf)->sa_family);
745	if (localsa == NULL) {
746		if (debugging)
747			fprintf(stderr,
748			"rpcbproc_callit_com: no local address\n");
749		goto error;
750	}
751	tbuf.len = tbuf.maxlen = localsa->sa_len;
752	tbuf.buf = localsa;
753	local_uaddr =
754	    addrmerge(&tbuf, rbl->rpcb_map.r_addr, NULL, nconf->nc_netid);
755	m_uaddr = addrmerge(caller, rbl->rpcb_map.r_addr, NULL,
756			nconf->nc_netid);
757#ifdef RPCBIND_DEBUG
758	if (debugging)
759		fprintf(stderr, "merged uaddr %s\n", m_uaddr);
760#endif
761	if ((fd = find_rmtcallfd_by_netid(nconf->nc_netid)) == -1) {
762		if (reply_type == RPCBPROC_INDIRECT)
763			svcerr_systemerr(transp);
764		free((void *) m_uaddr);
765		goto error;
766	}
767	xidp = __rpcb_get_dg_xidp(transp);
768	call_msg.rm_xid = forward_register(*xidp,
769			caller, fd, m_uaddr, reply_type, versnum);
770	if (call_msg.rm_xid == 0) {
771		/*
772		 * A duplicate request for the slow server.  Let's not
773		 * beat on it any more.
774		 */
775		if (debugging)
776			fprintf(stderr,
777			"rpcbproc_callit_com:  duplicate request\n");
778		free((void *) m_uaddr);
779		goto error;
780	} else 	if (call_msg.rm_xid == (uint32_t)-1) {
781		/*  forward_register failed.  Perhaps no memory. */
782		if (debugging)
783			fprintf(stderr,
784			"rpcbproc_callit_com:  forward_register failed\n");
785		free((void *) m_uaddr);
786		goto error;
787	}
788
789#ifdef DEBUG_RMTCALL
790	if (debugging)
791		fprintf(stderr,
792			"rpcbproc_callit_com:  original XID %x, new XID %x\n",
793				*xidp, call_msg.rm_xid);
794#endif
795	call_msg.rm_direction = CALL;
796	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
797	call_msg.rm_call.cb_prog = a.rmt_prog;
798	call_msg.rm_call.cb_vers = a.rmt_vers;
799	if (sendsz > RPC_BUF_MAX) {
800#ifdef	notyet
801		outbuf_alloc = alloca(sendsz);	/* not in IDR2? */
802#else
803		outbuf_alloc = malloc(sendsz);
804#endif	/* notyet */
805		if (outbuf_alloc == NULL) {
806			if (reply_type == RPCBPROC_INDIRECT)
807				svcerr_systemerr(transp);
808			if (debugging)
809				fprintf(stderr,
810				"rpcbproc_callit_com:  No memory!\n");
811			goto error;
812		}
813		xdrmem_create(&outxdr, outbuf_alloc, sendsz, XDR_ENCODE);
814	} else {
815		xdrmem_create(&outxdr, outbuf, sendsz, XDR_ENCODE);
816	}
817	if (!xdr_callhdr(&outxdr, &call_msg)) {
818		if (reply_type == RPCBPROC_INDIRECT)
819			svcerr_systemerr(transp);
820		if (debugging)
821			fprintf(stderr,
822			"rpcbproc_callit_com:  xdr_callhdr failed\n");
823		goto error;
824	}
825	if (!xdr_u_int32_t(&outxdr, &(a.rmt_proc))) {
826		if (reply_type == RPCBPROC_INDIRECT)
827			svcerr_systemerr(transp);
828		if (debugging)
829			fprintf(stderr,
830			"rpcbproc_callit_com:  xdr_u_long failed\n");
831		goto error;
832	}
833
834	if (rqstp->rq_cred.oa_flavor == AUTH_NULL) {
835		auth = authnone_create();
836	} else if (rqstp->rq_cred.oa_flavor == AUTH_SYS) {
837		struct authunix_parms *au;
838
839		au = (struct authunix_parms *)rqstp->rq_clntcred;
840		auth = authunix_create(au->aup_machname,
841				au->aup_uid, au->aup_gid,
842				au->aup_len, au->aup_gids);
843		if (auth == NULL) /* fall back */
844			auth = authnone_create();
845	} else {
846		/* we do not support any other authentication scheme */
847		if (debugging)
848			fprintf(stderr,
849"rpcbproc_callit_com:  oa_flavor != AUTH_NONE and oa_flavor != AUTH_SYS\n");
850		if (reply_type == RPCBPROC_INDIRECT)
851			svcerr_weakauth(transp); /* XXX too strong.. */
852		goto error;
853	}
854	if (auth == NULL) {
855		if (reply_type == RPCBPROC_INDIRECT)
856			svcerr_systemerr(transp);
857		if (debugging)
858			fprintf(stderr,
859		"rpcbproc_callit_com:  authwhatever_create returned NULL\n");
860		goto error;
861	}
862	if (!AUTH_MARSHALL(auth, &outxdr)) {
863		if (reply_type == RPCBPROC_INDIRECT)
864			svcerr_systemerr(transp);
865		AUTH_DESTROY(auth);
866		if (debugging)
867			fprintf(stderr,
868		"rpcbproc_callit_com:  AUTH_MARSHALL failed\n");
869		goto error;
870	}
871	AUTH_DESTROY(auth);
872	if (!xdr_opaque_parms(&outxdr, &a)) {
873		if (reply_type == RPCBPROC_INDIRECT)
874			svcerr_systemerr(transp);
875		if (debugging)
876			fprintf(stderr,
877		"rpcbproc_callit_com:  xdr_opaque_parms failed\n");
878		goto error;
879	}
880	outlen = (int) XDR_GETPOS(&outxdr);
881	if (outbuf_alloc)
882		outbufp = outbuf_alloc;
883	else
884		outbufp = outbuf;
885
886	na = uaddr2taddr(nconf, local_uaddr);
887	if (!na) {
888		if (reply_type == RPCBPROC_INDIRECT)
889			svcerr_systemerr(transp);
890		goto error;
891	}
892
893	if (sendto(fd, outbufp, outlen, 0, (struct sockaddr *)na->buf, na->len)
894	    != outlen) {
895		if (debugging)
896			fprintf(stderr,
897	"rpcbproc_callit_com:  sendto failed:  errno %d\n", errno);
898		if (reply_type == RPCBPROC_INDIRECT)
899			svcerr_systemerr(transp);
900		goto error;
901	}
902	goto out;
903
904error:
905	if (call_msg.rm_xid != 0)
906		(void) free_slot_by_xid(call_msg.rm_xid);
907out:
908	if (local_uaddr)
909		free(local_uaddr);
910	if (buf_alloc)
911		free((void *) buf_alloc);
912	if (outbuf_alloc)
913		free((void *) outbuf_alloc);
914	if (na) {
915		free(na->buf);
916		free(na);
917	}
918}
919
920/*
921 * Makes an entry into the FIFO for the given request.
922 * If duplicate request, returns a 0, else returns the xid of its call.
923 */
924static u_int32_t
925forward_register(u_int32_t caller_xid, struct netbuf *caller_addr,
926		 int forward_fd, char *uaddr, rpcproc_t reply_type,
927		 rpcvers_t versnum)
928{
929	int		i;
930	int		j = 0;
931	time_t		min_time, time_now;
932	static u_int32_t	lastxid;
933	int		entry = -1;
934
935	min_time = FINFO[0].time;
936	time_now = time((time_t *)0);
937	/* initialization */
938	if (lastxid == 0)
939		lastxid = time_now * NFORWARD;
940
941	/*
942	 * Check if it is an duplicate entry. Then,
943	 * try to find an empty slot.  If not available, then
944	 * use the slot with the earliest time.
945	 */
946	for (i = 0; i < NFORWARD; i++) {
947		if (FINFO[i].flag & FINFO_ACTIVE) {
948			if ((FINFO[i].caller_xid == caller_xid) &&
949			    (FINFO[i].reply_type == reply_type) &&
950			    (FINFO[i].versnum == versnum) &&
951			    (!netbufcmp(FINFO[i].caller_addr,
952					    caller_addr))) {
953				FINFO[i].time = time((time_t *)0);
954				return (0);	/* Duplicate entry */
955			} else {
956				/* Should we wait any longer */
957				if ((time_now - FINFO[i].time) > MAXTIME_OFF)
958					(void) free_slot_by_index(i);
959			}
960		}
961		if (entry == -1) {
962			if ((FINFO[i].flag & FINFO_ACTIVE) == 0) {
963				entry = i;
964			} else if (FINFO[i].time < min_time) {
965				j = i;
966				min_time = FINFO[i].time;
967			}
968		}
969	}
970	if (entry != -1) {
971		/* use this empty slot */
972		j = entry;
973	} else {
974		(void) free_slot_by_index(j);
975	}
976	if ((FINFO[j].caller_addr = netbufdup(caller_addr)) == NULL) {
977		return (-1);
978	}
979	rpcb_rmtcalls++;	/* no of pending calls */
980	FINFO[j].flag = FINFO_ACTIVE;
981	FINFO[j].reply_type = reply_type;
982	FINFO[j].versnum = versnum;
983	FINFO[j].time = time_now;
984	FINFO[j].caller_xid = caller_xid;
985	FINFO[j].forward_fd = forward_fd;
986	/*
987	 * Though uaddr is not allocated here, it will still be freed
988	 * from free_slot_*().
989	 */
990	FINFO[j].uaddr = uaddr;
991	lastxid = lastxid + NFORWARD;
992	FINFO[j].forward_xid = lastxid + j;	/* encode slot */
993	return (FINFO[j].forward_xid);		/* forward on this xid */
994}
995
996static struct finfo *
997forward_find(u_int32_t reply_xid)
998{
999	int		i;
1000
1001	i = reply_xid % NFORWARD;
1002	if (i < 0)
1003		i += NFORWARD;
1004	if ((FINFO[i].flag & FINFO_ACTIVE) &&
1005	    (FINFO[i].forward_xid == reply_xid)) {
1006		return (&FINFO[i]);
1007	}
1008	return (NULL);
1009}
1010
1011static int
1012free_slot_by_xid(u_int32_t xid)
1013{
1014	int entry;
1015
1016	entry = xid % NFORWARD;
1017	if (entry < 0)
1018		entry += NFORWARD;
1019	return (free_slot_by_index(entry));
1020}
1021
1022static int
1023free_slot_by_index(int idx)
1024{
1025	struct finfo	*fi;
1026
1027	fi = &FINFO[idx];
1028	if (fi->flag & FINFO_ACTIVE) {
1029		netbuffree(fi->caller_addr);
1030		/* XXX may be too big, but can't access xprt array here */
1031		if (fi->forward_fd >= svc_maxfd)
1032			svc_maxfd--;
1033		free((void *) fi->uaddr);
1034		fi->flag &= ~FINFO_ACTIVE;
1035		rpcb_rmtcalls--;
1036		return (1);
1037	}
1038	return (0);
1039}
1040
1041static int
1042netbufcmp(struct netbuf *n1, struct netbuf *n2)
1043{
1044	return ((n1->len != n2->len) || memcmp(n1->buf, n2->buf, n1->len));
1045}
1046
1047static struct netbuf *
1048netbufdup(struct netbuf *ap)
1049{
1050	struct netbuf  *np;
1051
1052	np = (struct netbuf *) malloc(sizeof (struct netbuf) + ap->len);
1053	if (np) {
1054		np->maxlen = np->len = ap->len;
1055		np->buf = ((char *) np) + sizeof (struct netbuf);
1056		(void) memcpy(np->buf, ap->buf, ap->len);
1057	}
1058	return (np);
1059}
1060
1061static void
1062netbuffree(struct netbuf *ap)
1063{
1064	free((void *) ap);
1065}
1066
1067
1068#define	MASKVAL	(POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)
1069extern bool_t __svc_clean_idle(fd_set *, int, bool_t);
1070
1071void
1072my_svc_run(void)
1073{
1074	size_t nfds;
1075	struct pollfd pollfds[FD_SETSIZE];
1076	int poll_ret, check_ret;
1077	int n;
1078#ifdef SVC_RUN_DEBUG
1079	int i;
1080#endif
1081	register struct pollfd	*p;
1082	fd_set cleanfds;
1083
1084	for (;;) {
1085		p = pollfds;
1086		for (n = 0; n <= svc_maxfd; n++) {
1087			if (FD_ISSET(n, &svc_fdset)) {
1088				p->fd = n;
1089				p->events = MASKVAL;
1090				p++;
1091			}
1092		}
1093		nfds = p - pollfds;
1094		poll_ret = 0;
1095#ifdef SVC_RUN_DEBUG
1096		if (debugging) {
1097			fprintf(stderr, "polling for read on fd < ");
1098			for (i = 0, p = pollfds; i < nfds; i++, p++)
1099				if (p->events)
1100					fprintf(stderr, "%d ", p->fd);
1101			fprintf(stderr, ">\n");
1102		}
1103#endif
1104		switch (poll_ret = poll(pollfds, nfds, 30 * 1000)) {
1105		case -1:
1106			/*
1107			 * We ignore all errors, continuing with the assumption
1108			 * that it was set by the signal handlers (or any
1109			 * other outside event) and not caused by poll().
1110			 */
1111		case 0:
1112			cleanfds = svc_fdset;
1113			__svc_clean_idle(&cleanfds, 30, FALSE);
1114			continue;
1115		default:
1116#ifdef SVC_RUN_DEBUG
1117			if (debugging) {
1118				fprintf(stderr, "poll returned read fds < ");
1119				for (i = 0, p = pollfds; i < nfds; i++, p++)
1120					if (p->revents)
1121						fprintf(stderr, "%d ", p->fd);
1122				fprintf(stderr, ">\n");
1123			}
1124#endif
1125			/*
1126			 * If we found as many replies on callback fds
1127			 * as the number of descriptors selectable which
1128			 * poll() returned, there can be no more so we
1129			 * don't call svc_getreq_poll.  Otherwise, there
1130			 * must be another so we must call svc_getreq_poll.
1131			 */
1132			if ((check_ret = check_rmtcalls(pollfds, nfds)) ==
1133			    poll_ret)
1134				continue;
1135			svc_getreq_poll(pollfds, poll_ret-check_ret);
1136		}
1137#ifdef SVC_RUN_DEBUG
1138		if (debugging) {
1139			fprintf(stderr, "svc_maxfd now %u\n", svc_maxfd);
1140		}
1141#endif
1142	}
1143}
1144
1145static int
1146check_rmtcalls(struct pollfd *pfds, int nfds)
1147{
1148	int j, ncallbacks_found = 0, rmtcalls_pending;
1149	SVCXPRT *xprt;
1150
1151	if (rpcb_rmtcalls == 0)
1152		return (0);
1153
1154	rmtcalls_pending = rpcb_rmtcalls;
1155	for (j = 0; j < nfds; j++) {
1156		if ((xprt = find_rmtcallxprt_by_fd(pfds[j].fd)) != NULL) {
1157			if (pfds[j].revents) {
1158				ncallbacks_found++;
1159#ifdef DEBUG_RMTCALL
1160			if (debugging)
1161				fprintf(stderr,
1162"my_svc_run:  polled on forwarding fd %d, netid %s - calling handle_reply\n",
1163		pfds[j].fd, xprt->xp_netid);
1164#endif
1165				handle_reply(pfds[j].fd, xprt);
1166				pfds[j].revents = 0;
1167				if (ncallbacks_found >= rmtcalls_pending) {
1168					break;
1169				}
1170			}
1171		}
1172	}
1173	return (ncallbacks_found);
1174}
1175
1176static void
1177xprt_set_caller(SVCXPRT *xprt, struct finfo *fi)
1178{
1179	u_int32_t *xidp;
1180
1181	*(svc_getrpccaller(xprt)) = *(fi->caller_addr);
1182	xidp = __rpcb_get_dg_xidp(xprt);
1183	*xidp = fi->caller_xid;
1184}
1185
1186/*
1187 * Call svcerr_systemerr() only if RPCBVERS4
1188 */
1189static void
1190send_svcsyserr(SVCXPRT *xprt, struct finfo *fi)
1191{
1192	if (fi->reply_type == RPCBPROC_INDIRECT) {
1193		xprt_set_caller(xprt, fi);
1194		svcerr_systemerr(xprt);
1195	}
1196	return;
1197}
1198
1199static void
1200handle_reply(int fd, SVCXPRT *xprt)
1201{
1202	XDR		reply_xdrs;
1203	struct rpc_msg	reply_msg;
1204	struct rpc_err	reply_error;
1205	char		*buffer;
1206	struct finfo	*fi;
1207	int		inlen, pos, len;
1208	struct r_rmtcall_args a;
1209	struct sockaddr_storage ss;
1210	socklen_t fromlen;
1211#ifdef SVC_RUN_DEBUG
1212	char *uaddr;
1213#endif
1214
1215	buffer = malloc(RPC_BUF_MAX);
1216	if (buffer == NULL)
1217		goto done;
1218
1219	do {
1220		fromlen = sizeof ss;
1221		inlen = recvfrom(fd, buffer, RPC_BUF_MAX, 0,
1222			    (struct sockaddr *)&ss, &fromlen);
1223	} while (inlen < 0 && errno == EINTR);
1224	if (inlen < 0) {
1225		if (debugging)
1226			fprintf(stderr,
1227	"handle_reply:  recvfrom returned %d, errno %d\n", inlen, errno);
1228		goto done;
1229	}
1230
1231	reply_msg.acpted_rply.ar_verf = _null_auth;
1232	reply_msg.acpted_rply.ar_results.where = 0;
1233	reply_msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_void;
1234
1235	xdrmem_create(&reply_xdrs, buffer, (u_int)inlen, XDR_DECODE);
1236	if (!xdr_replymsg(&reply_xdrs, &reply_msg)) {
1237		if (debugging)
1238			(void) fprintf(stderr,
1239				"handle_reply:  xdr_replymsg failed\n");
1240		goto done;
1241	}
1242	fi = forward_find(reply_msg.rm_xid);
1243#ifdef	SVC_RUN_DEBUG
1244	if (debugging) {
1245		fprintf(stderr, "handle_reply:  reply xid: %d fi addr: %p\n",
1246			reply_msg.rm_xid, fi);
1247	}
1248#endif
1249	if (fi == NULL) {
1250		goto done;
1251	}
1252	_seterr_reply(&reply_msg, &reply_error);
1253	if (reply_error.re_status != RPC_SUCCESS) {
1254		if (debugging)
1255			(void) fprintf(stderr, "handle_reply:  %s\n",
1256				clnt_sperrno(reply_error.re_status));
1257		send_svcsyserr(xprt, fi);
1258		goto done;
1259	}
1260	pos = XDR_GETPOS(&reply_xdrs);
1261	len = inlen - pos;
1262	a.rmt_args.args = &buffer[pos];
1263	a.rmt_args.arglen = len;
1264	a.rmt_uaddr = fi->uaddr;
1265	a.rmt_localvers = fi->versnum;
1266
1267	xprt_set_caller(xprt, fi);
1268#ifdef	SVC_RUN_DEBUG
1269	uaddr =	taddr2uaddr(rpcbind_get_conf("udp"),
1270				    svc_getrpccaller(xprt));
1271	if (debugging) {
1272		fprintf(stderr, "handle_reply:  forwarding address %s to %s\n",
1273			a.rmt_uaddr, uaddr ? uaddr : rpcbind_unknown);
1274	}
1275	if (uaddr)
1276		free((void *) uaddr);
1277#endif
1278	svc_sendreply(xprt, (xdrproc_t) xdr_rmtcall_result, (char *) &a);
1279done:
1280	if (buffer)
1281		free(buffer);
1282
1283	if (reply_msg.rm_xid == 0) {
1284#ifdef	SVC_RUN_DEBUG
1285	if (debugging) {
1286		fprintf(stderr, "handle_reply:  NULL xid on exit!\n");
1287	}
1288#endif
1289	} else
1290		(void) free_slot_by_xid(reply_msg.rm_xid);
1291	return;
1292}
1293
1294static void
1295find_versions(rpcprog_t prog, char *netid, rpcvers_t *lowvp, rpcvers_t *highvp)
1296{
1297	register rpcblist_ptr rbl;
1298	rpcvers_t lowv = 0;
1299	rpcvers_t highv = 0;
1300
1301	for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) {
1302		if ((rbl->rpcb_map.r_prog != prog) ||
1303		    ((rbl->rpcb_map.r_netid != NULL) &&
1304			(strcasecmp(rbl->rpcb_map.r_netid, netid) != 0)))
1305			continue;
1306		if (lowv == 0) {
1307			highv = rbl->rpcb_map.r_vers;
1308			lowv = highv;
1309		} else if (rbl->rpcb_map.r_vers < lowv) {
1310			lowv = rbl->rpcb_map.r_vers;
1311		} else if (rbl->rpcb_map.r_vers > highv) {
1312			highv = rbl->rpcb_map.r_vers;
1313		}
1314	}
1315	*lowvp = lowv;
1316	*highvp = highv;
1317	return;
1318}
1319
1320/*
1321 * returns the item with the given program, version number and netid.
1322 * If that version number is not found, it returns the item with that
1323 * program number, so that address is now returned to the caller. The
1324 * caller when makes a call to this program, version number, the call
1325 * will fail and it will return with PROGVERS_MISMATCH. The user can
1326 * then determine the highest and the lowest version number for this
1327 * program using clnt_geterr() and use those program version numbers.
1328 *
1329 * Returns the RPCBLIST for the given prog, vers and netid
1330 */
1331static rpcblist_ptr
1332find_service(rpcprog_t prog, rpcvers_t vers, char *netid)
1333{
1334	register rpcblist_ptr hit = NULL;
1335	register rpcblist_ptr rbl;
1336
1337	for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) {
1338		if ((rbl->rpcb_map.r_prog != prog) ||
1339		    ((rbl->rpcb_map.r_netid != NULL) &&
1340			(strcasecmp(rbl->rpcb_map.r_netid, netid) != 0)))
1341			continue;
1342		hit = rbl;
1343		if (rbl->rpcb_map.r_vers == vers)
1344			break;
1345	}
1346	return (hit);
1347}
1348
1349/*
1350 * Copies the name associated with the uid of the caller and returns
1351 * a pointer to it.  Similar to getwd().
1352 */
1353static char *
1354getowner(SVCXPRT *transp, char *owner, size_t ownersize)
1355{
1356	struct sockcred *sc;
1357
1358	sc = __svc_getcallercreds(transp);
1359	if (sc == NULL)
1360		strlcpy(owner, rpcbind_unknown, ownersize);
1361	else if (sc->sc_uid == 0)
1362		strlcpy(owner, rpcbind_superuser, ownersize);
1363	else
1364		snprintf(owner, ownersize, "%d", sc->sc_uid);
1365
1366	return owner;
1367}
1368
1369#ifdef PORTMAP
1370/*
1371 * Add this to the pmap list only if it is UDP or TCP.
1372 */
1373static int
1374add_pmaplist(RPCB *arg)
1375{
1376	struct pmap pmap;
1377	struct pmaplist *pml;
1378	int h1, h2, h3, h4, p1, p2;
1379
1380	if (strcmp(arg->r_netid, udptrans) == 0) {
1381		/* It is UDP! */
1382		pmap.pm_prot = IPPROTO_UDP;
1383	} else if (strcmp(arg->r_netid, tcptrans) == 0) {
1384		/* It is TCP */
1385		pmap.pm_prot = IPPROTO_TCP;
1386	} else
1387		/* Not a IP protocol */
1388		return (0);
1389
1390	/* interpret the universal address for TCP/IP */
1391	if (sscanf(arg->r_addr, "%d.%d.%d.%d.%d.%d",
1392		&h1, &h2, &h3, &h4, &p1, &p2) != 6)
1393		return (0);
1394	pmap.pm_port = ((p1 & 0xff) << 8) + (p2 & 0xff);
1395	pmap.pm_prog = arg->r_prog;
1396	pmap.pm_vers = arg->r_vers;
1397	/*
1398	 * add to END of list
1399	 */
1400	pml = (struct pmaplist *) malloc((u_int)sizeof (struct pmaplist));
1401	if (pml == NULL) {
1402		(void) syslog(LOG_ERR, "rpcbind: no memory!\n");
1403		return (1);
1404	}
1405	pml->pml_map = pmap;
1406	pml->pml_next = NULL;
1407	if (list_pml == NULL) {
1408		list_pml = pml;
1409	} else {
1410		struct pmaplist *fnd;
1411
1412		/* Attach to the end of the list */
1413		for (fnd = list_pml; fnd->pml_next; fnd = fnd->pml_next)
1414			;
1415		fnd->pml_next = pml;
1416	}
1417	return (0);
1418}
1419
1420/*
1421 * Delete this from the pmap list only if it is UDP or TCP.
1422 */
1423static int
1424del_pmaplist(RPCB *arg)
1425{
1426	struct pmaplist *pml;
1427	struct pmaplist *prevpml, *fnd;
1428	unsigned long prot;
1429
1430	if (strcmp(arg->r_netid, udptrans) == 0) {
1431		/* It is UDP! */
1432		prot = IPPROTO_UDP;
1433	} else if (strcmp(arg->r_netid, tcptrans) == 0) {
1434		/* It is TCP */
1435		prot = IPPROTO_TCP;
1436	} else if (arg->r_netid[0] == 0) {
1437		prot = 0;	/* Remove all occurrences */
1438	} else {
1439		/* Not a IP protocol */
1440		return (0);
1441	}
1442	for (prevpml = NULL, pml = list_pml; pml; /* cstyle */) {
1443		if ((pml->pml_map.pm_prog != arg->r_prog) ||
1444			(pml->pml_map.pm_vers != arg->r_vers) ||
1445			(prot && (pml->pml_map.pm_prot != prot))) {
1446			/* both pml & prevpml move forwards */
1447			prevpml = pml;
1448			pml = pml->pml_next;
1449			continue;
1450		}
1451		/* found it; pml moves forward, prevpml stays */
1452		fnd = pml;
1453		pml = pml->pml_next;
1454		if (prevpml == NULL)
1455			list_pml = pml;
1456		else
1457			prevpml->pml_next = pml;
1458		free((void *) fnd);
1459	}
1460	return (0);
1461}
1462#endif /* PORTMAP */
1463