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