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