1/*	$NetBSD: rpcb_clnt.c,v 1.6 2000/07/16 06:41:43 itojun Exp $	*/
2
3/*-
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 * Copyright (c) 2010, Oracle America, Inc.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 * - Redistributions of source code must retain the above copyright notice,
12 *   this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above copyright notice,
14 *   this list of conditions and the following disclaimer in the documentation
15 *   and/or other materials provided with the distribution.
16 * - Neither the name of the "Oracle America, Inc." nor the names of its
17 *   contributors may be used to endorse or promote products derived
18 *   from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * rpcb_clnt.c
35 * interface to rpcbind rpc service.
36 */
37
38#include "namespace.h"
39#include "reentrant.h"
40#include <sys/types.h>
41#include <sys/socket.h>
42#include <sys/un.h>
43#include <sys/utsname.h>
44#include <rpc/rpc.h>
45#include <rpc/rpcb_prot.h>
46#include <rpc/nettype.h>
47#include <netconfig.h>
48#ifdef PORTMAP
49#include <netinet/in.h>		/* FOR IPPROTO_TCP/UDP definitions */
50#include <rpc/pmap_prot.h>
51#endif				/* PORTMAP */
52#include <stdio.h>
53#include <errno.h>
54#include <stdlib.h>
55#include <string.h>
56#include <unistd.h>
57#include <netdb.h>
58#include <syslog.h>
59#include "un-namespace.h"
60
61#include "rpc_com.h"
62#include "mt_misc.h"
63
64static struct timeval tottimeout = { 60, 0 };
65static const struct timeval rmttimeout = { 3, 0 };
66static struct timeval rpcbrmttime = { 15, 0 };
67
68extern bool_t xdr_wrapstring(XDR *, char **);
69
70static const char nullstring[] = "\000";
71
72#define	CACHESIZE 6
73
74struct address_cache {
75	char *ac_host;
76	char *ac_netid;
77	char *ac_uaddr;
78	struct netbuf *ac_taddr;
79	struct address_cache *ac_next;
80};
81
82static struct address_cache *front;
83static int cachesize;
84
85#define	CLCR_GET_RPCB_TIMEOUT	1
86#define	CLCR_SET_RPCB_TIMEOUT	2
87
88
89extern int __rpc_lowvers;
90
91static struct address_cache *check_cache(const char *, const char *);
92static void delete_cache(struct netbuf *);
93static void add_cache(const char *, const char *, struct netbuf *, char *);
94static CLIENT *getclnthandle(const char *, const struct netconfig *, char **);
95static CLIENT *local_rpcb(void);
96static struct netbuf *got_entry(rpcb_entry_list_ptr, const struct netconfig *);
97
98/*
99 * This routine adjusts the timeout used for calls to the remote rpcbind.
100 * Also, this routine can be used to set the use of portmapper version 2
101 * only when doing rpc_broadcasts
102 * These are private routines that may not be provided in future releases.
103 */
104bool_t
105__rpc_control(int request, void *info)
106{
107	switch (request) {
108	case CLCR_GET_RPCB_TIMEOUT:
109		*(struct timeval *)info = tottimeout;
110		break;
111	case CLCR_SET_RPCB_TIMEOUT:
112		tottimeout = *(struct timeval *)info;
113		break;
114	case CLCR_SET_LOWVERS:
115		__rpc_lowvers = *(int *)info;
116		break;
117	case CLCR_GET_LOWVERS:
118		*(int *)info = __rpc_lowvers;
119		break;
120	default:
121		return (FALSE);
122	}
123	return (TRUE);
124}
125
126/*
127 *	It might seem that a reader/writer lock would be more reasonable here.
128 *	However because getclnthandle(), the only user of the cache functions,
129 *	may do a delete_cache() operation if a check_cache() fails to return an
130 *	address useful to clnt_tli_create(), we may as well use a mutex.
131 */
132/*
133 * As it turns out, if the cache lock is *not* a reader/writer lock, we will
134 * block all clnt_create's if we are trying to connect to a host that's down,
135 * since the lock will be held all during that time.
136 */
137
138/*
139 * The routines check_cache(), add_cache(), delete_cache() manage the
140 * cache of rpcbind addresses for (host, netid).
141 */
142
143static struct address_cache *
144check_cache(const char *host, const char *netid)
145{
146	struct address_cache *cptr;
147
148	/* READ LOCK HELD ON ENTRY: rpcbaddr_cache_lock */
149
150	for (cptr = front; cptr != NULL; cptr = cptr->ac_next) {
151		if (!strcmp(cptr->ac_host, host) &&
152		    !strcmp(cptr->ac_netid, netid)) {
153#ifdef ND_DEBUG
154			fprintf(stderr, "Found cache entry for %s: %s\n",
155				host, netid);
156#endif
157			return (cptr);
158		}
159	}
160	return ((struct address_cache *) NULL);
161}
162
163static void
164delete_cache(struct netbuf *addr)
165{
166	struct address_cache *cptr, *prevptr = NULL;
167
168	/* WRITE LOCK HELD ON ENTRY: rpcbaddr_cache_lock */
169	for (cptr = front; cptr != NULL; cptr = cptr->ac_next) {
170		if (!memcmp(cptr->ac_taddr->buf, addr->buf, addr->len)) {
171			free(cptr->ac_host);
172			free(cptr->ac_netid);
173			free(cptr->ac_taddr->buf);
174			free(cptr->ac_taddr);
175			free(cptr->ac_uaddr);
176			if (prevptr)
177				prevptr->ac_next = cptr->ac_next;
178			else
179				front = cptr->ac_next;
180			free(cptr);
181			cachesize--;
182			break;
183		}
184		prevptr = cptr;
185	}
186}
187
188static void
189add_cache(const char *host, const char *netid, struct netbuf *taddr,
190    char *uaddr)
191{
192	struct address_cache  *ad_cache, *cptr, *prevptr;
193
194	ad_cache = (struct address_cache *)
195			malloc(sizeof (struct address_cache));
196	if (!ad_cache) {
197		return;
198	}
199	ad_cache->ac_host = strdup(host);
200	ad_cache->ac_netid = strdup(netid);
201	ad_cache->ac_uaddr = uaddr ? strdup(uaddr) : NULL;
202	ad_cache->ac_taddr = (struct netbuf *)malloc(sizeof (struct netbuf));
203	if (!ad_cache->ac_host || !ad_cache->ac_netid || !ad_cache->ac_taddr ||
204		(uaddr && !ad_cache->ac_uaddr)) {
205		goto out;
206	}
207	ad_cache->ac_taddr->len = ad_cache->ac_taddr->maxlen = taddr->len;
208	ad_cache->ac_taddr->buf = (char *) malloc(taddr->len);
209	if (ad_cache->ac_taddr->buf == NULL) {
210out:
211		free(ad_cache->ac_host);
212		free(ad_cache->ac_netid);
213		free(ad_cache->ac_uaddr);
214		free(ad_cache->ac_taddr);
215		free(ad_cache);
216		return;
217	}
218	memcpy(ad_cache->ac_taddr->buf, taddr->buf, taddr->len);
219#ifdef ND_DEBUG
220	fprintf(stderr, "Added to cache: %s : %s\n", host, netid);
221#endif
222
223/* VARIABLES PROTECTED BY rpcbaddr_cache_lock:  cptr */
224
225	rwlock_wrlock(&rpcbaddr_cache_lock);
226	if (cachesize < CACHESIZE) {
227		ad_cache->ac_next = front;
228		front = ad_cache;
229		cachesize++;
230	} else {
231		/* Free the last entry */
232		cptr = front;
233		prevptr = NULL;
234		while (cptr->ac_next) {
235			prevptr = cptr;
236			cptr = cptr->ac_next;
237		}
238
239#ifdef ND_DEBUG
240		fprintf(stderr, "Deleted from cache: %s : %s\n",
241			cptr->ac_host, cptr->ac_netid);
242#endif
243		free(cptr->ac_host);
244		free(cptr->ac_netid);
245		free(cptr->ac_taddr->buf);
246		free(cptr->ac_taddr);
247		free(cptr->ac_uaddr);
248
249		if (prevptr) {
250			prevptr->ac_next = NULL;
251			ad_cache->ac_next = front;
252			front = ad_cache;
253		} else {
254			front = ad_cache;
255			ad_cache->ac_next = NULL;
256		}
257		free(cptr);
258	}
259	rwlock_unlock(&rpcbaddr_cache_lock);
260}
261
262/*
263 * This routine will return a client handle that is connected to the
264 * rpcbind. If targaddr is non-NULL, the "universal address" of the
265 * host will be stored in *targaddr; the caller is responsible for
266 * freeing this string.
267 * On error, returns NULL and free's everything.
268 */
269static CLIENT *
270getclnthandle(const char *host, const struct netconfig *nconf, char **targaddr)
271{
272	CLIENT *client;
273	struct netbuf *addr, taddr;
274	struct netbuf addr_to_delete;
275	struct __rpc_sockinfo si;
276	struct addrinfo hints, *res, *tres;
277	struct address_cache *ad_cache;
278	char *tmpaddr;
279
280/* VARIABLES PROTECTED BY rpcbaddr_cache_lock:  ad_cache */
281
282	/* Get the address of the rpcbind.  Check cache first */
283	client = NULL;
284	addr_to_delete.len = 0;
285	rwlock_rdlock(&rpcbaddr_cache_lock);
286	ad_cache = NULL;
287	if (host != NULL)
288		ad_cache = check_cache(host, nconf->nc_netid);
289	if (ad_cache != NULL) {
290		addr = ad_cache->ac_taddr;
291		client = clnt_tli_create(RPC_ANYFD, nconf, addr,
292		    (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0);
293		if (client != NULL) {
294			if (targaddr)
295				*targaddr = strdup(ad_cache->ac_uaddr);
296			rwlock_unlock(&rpcbaddr_cache_lock);
297			return (client);
298		}
299		addr_to_delete.len = addr->len;
300		addr_to_delete.buf = (char *)malloc(addr->len);
301		if (addr_to_delete.buf == NULL) {
302			addr_to_delete.len = 0;
303		} else {
304			memcpy(addr_to_delete.buf, addr->buf, addr->len);
305		}
306	}
307	rwlock_unlock(&rpcbaddr_cache_lock);
308	if (addr_to_delete.len != 0) {
309		/*
310		 * Assume this may be due to cache data being
311		 *  outdated
312		 */
313		rwlock_wrlock(&rpcbaddr_cache_lock);
314		delete_cache(&addr_to_delete);
315		rwlock_unlock(&rpcbaddr_cache_lock);
316		free(addr_to_delete.buf);
317	}
318	if (!__rpc_nconf2sockinfo(nconf, &si)) {
319		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
320		return NULL;
321	}
322
323	memset(&hints, 0, sizeof hints);
324	hints.ai_family = si.si_af;
325	hints.ai_socktype = si.si_socktype;
326	hints.ai_protocol = si.si_proto;
327
328#ifdef CLNT_DEBUG
329	printf("trying netid %s family %d proto %d socktype %d\n",
330	    nconf->nc_netid, si.si_af, si.si_proto, si.si_socktype);
331#endif
332
333	if (nconf->nc_protofmly != NULL && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
334		client = local_rpcb();
335		if (! client) {
336#ifdef ND_DEBUG
337			clnt_pcreateerror("rpcbind clnt interface");
338#endif
339			return (NULL);
340		} else {
341			struct sockaddr_un sun;
342			if (targaddr) {
343			    *targaddr = malloc(sizeof(sun.sun_path));
344			    if (*targaddr == NULL) {
345				CLNT_DESTROY(client);
346				return (NULL);
347			    }
348			    strncpy(*targaddr, _PATH_RPCBINDSOCK,
349				sizeof(sun.sun_path));
350			}
351			return (client);
352		}
353	} else {
354		if (getaddrinfo(host, "sunrpc", &hints, &res) != 0) {
355			rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
356			return NULL;
357		}
358	}
359
360	for (tres = res; tres != NULL; tres = tres->ai_next) {
361		taddr.buf = tres->ai_addr;
362		taddr.len = taddr.maxlen = tres->ai_addrlen;
363
364#ifdef ND_DEBUG
365		{
366			char *ua;
367
368			ua = taddr2uaddr(nconf, &taddr);
369			fprintf(stderr, "Got it [%s]\n", ua);
370			free(ua);
371		}
372#endif
373
374#ifdef ND_DEBUG
375		{
376			int i;
377
378			fprintf(stderr, "\tnetbuf len = %d, maxlen = %d\n",
379				taddr.len, taddr.maxlen);
380			fprintf(stderr, "\tAddress is ");
381			for (i = 0; i < taddr.len; i++)
382				fprintf(stderr, "%u.", ((char *)(taddr.buf))[i]);
383			fprintf(stderr, "\n");
384		}
385#endif
386		client = clnt_tli_create(RPC_ANYFD, nconf, &taddr,
387		    (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0);
388#ifdef ND_DEBUG
389		if (! client) {
390			clnt_pcreateerror("rpcbind clnt interface");
391		}
392#endif
393
394		if (client) {
395			tmpaddr = targaddr ? taddr2uaddr(nconf, &taddr) : NULL;
396			add_cache(host, nconf->nc_netid, &taddr, tmpaddr);
397			if (targaddr)
398				*targaddr = tmpaddr;
399			break;
400		}
401	}
402	if (res)
403		freeaddrinfo(res);
404	return (client);
405}
406
407/* XXX */
408#define IN4_LOCALHOST_STRING	"127.0.0.1"
409#define IN6_LOCALHOST_STRING	"::1"
410
411/*
412 * This routine will return a client handle that is connected to the local
413 * rpcbind. Returns NULL on error and free's everything.
414 */
415static CLIENT *
416local_rpcb(void)
417{
418	CLIENT *client;
419	static struct netconfig *loopnconf;
420	static char *hostname;
421	int sock;
422	size_t tsize;
423	struct netbuf nbuf;
424	struct sockaddr_un sun;
425
426	/*
427	 * Try connecting to the local rpcbind through a local socket
428	 * first. If this doesn't work, try all transports defined in
429	 * the netconfig file.
430	 */
431	memset(&sun, 0, sizeof sun);
432	sock = _socket(AF_LOCAL, SOCK_STREAM, 0);
433	if (sock < 0)
434		goto try_nconf;
435	sun.sun_family = AF_LOCAL;
436	strcpy(sun.sun_path, _PATH_RPCBINDSOCK);
437	nbuf.len = sun.sun_len = SUN_LEN(&sun);
438	nbuf.maxlen = sizeof (struct sockaddr_un);
439	nbuf.buf = &sun;
440
441	tsize = __rpc_get_t_size(AF_LOCAL, 0, 0);
442	client = clnt_vc_create(sock, &nbuf, (rpcprog_t)RPCBPROG,
443	    (rpcvers_t)RPCBVERS, tsize, tsize);
444
445	if (client != NULL) {
446		/* Mark the socket to be closed in destructor */
447		(void) CLNT_CONTROL(client, CLSET_FD_CLOSE, NULL);
448		return client;
449	}
450
451	/* Nobody needs this socket anymore; free the descriptor. */
452	_close(sock);
453
454try_nconf:
455
456/* VARIABLES PROTECTED BY loopnconf_lock: loopnconf */
457	mutex_lock(&loopnconf_lock);
458	if (loopnconf == NULL) {
459		struct netconfig *nconf, *tmpnconf = NULL;
460		void *nc_handle;
461		int fd;
462
463		nc_handle = setnetconfig();
464		if (nc_handle == NULL) {
465			/* fails to open netconfig file */
466			syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
467			rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
468			mutex_unlock(&loopnconf_lock);
469			return (NULL);
470		}
471		while ((nconf = getnetconfig(nc_handle)) != NULL) {
472#ifdef INET6
473			if ((strcmp(nconf->nc_protofmly, NC_INET6) == 0 ||
474#else
475			if ((
476#endif
477			     strcmp(nconf->nc_protofmly, NC_INET) == 0) &&
478			    (nconf->nc_semantics == NC_TPI_COTS ||
479			     nconf->nc_semantics == NC_TPI_COTS_ORD)) {
480				fd = __rpc_nconf2fd(nconf);
481				/*
482				 * Can't create a socket, assume that
483				 * this family isn't configured in the kernel.
484				 */
485				if (fd < 0)
486					continue;
487				_close(fd);
488				tmpnconf = nconf;
489				if (!strcmp(nconf->nc_protofmly, NC_INET))
490					hostname = IN4_LOCALHOST_STRING;
491				else
492					hostname = IN6_LOCALHOST_STRING;
493			}
494		}
495		if (tmpnconf == NULL) {
496			endnetconfig(nc_handle);
497			rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
498			mutex_unlock(&loopnconf_lock);
499			return (NULL);
500		}
501		loopnconf = getnetconfigent(tmpnconf->nc_netid);
502		/* loopnconf is never freed */
503		endnetconfig(nc_handle);
504	}
505	mutex_unlock(&loopnconf_lock);
506	client = getclnthandle(hostname, loopnconf, NULL);
507	return (client);
508}
509
510/*
511 * Set a mapping between program, version and address.
512 * Calls the rpcbind service to do the mapping.
513 *
514 * nconf   - Network structure of transport
515 * address - Services netconfig address
516 */
517bool_t
518rpcb_set(rpcprog_t program, rpcvers_t version, const struct netconfig *nconf,
519    const struct netbuf *address)
520{
521	CLIENT *client;
522	bool_t rslt = FALSE;
523	RPCB parms;
524	char uidbuf[32];
525
526	/* parameter checking */
527	if (nconf == NULL) {
528		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
529		return (FALSE);
530	}
531	if (address == NULL) {
532		rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
533		return (FALSE);
534	}
535	client = local_rpcb();
536	if (! client) {
537		return (FALSE);
538	}
539
540	/* convert to universal */
541	/*LINTED const castaway*/
542	parms.r_addr = taddr2uaddr((struct netconfig *) nconf,
543				   (struct netbuf *)address);
544	if (!parms.r_addr) {
545		CLNT_DESTROY(client);
546		rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
547		return (FALSE); /* no universal address */
548	}
549	parms.r_prog = program;
550	parms.r_vers = version;
551	parms.r_netid = nconf->nc_netid;
552	/*
553	 * Though uid is not being used directly, we still send it for
554	 * completeness.  For non-unix platforms, perhaps some other
555	 * string or an empty string can be sent.
556	 */
557	(void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid());
558	parms.r_owner = uidbuf;
559
560	CLNT_CALL(client, (rpcproc_t)RPCBPROC_SET, (xdrproc_t) xdr_rpcb,
561	    (char *)(void *)&parms, (xdrproc_t) xdr_bool,
562	    (char *)(void *)&rslt, tottimeout);
563
564	CLNT_DESTROY(client);
565	free(parms.r_addr);
566	return (rslt);
567}
568
569/*
570 * Remove the mapping between program, version and netbuf address.
571 * Calls the rpcbind service to do the un-mapping.
572 * If netbuf is NULL, unset for all the transports, otherwise unset
573 * only for the given transport.
574 */
575bool_t
576rpcb_unset(rpcprog_t program, rpcvers_t version, const struct netconfig *nconf)
577{
578	CLIENT *client;
579	bool_t rslt = FALSE;
580	RPCB parms;
581	char uidbuf[32];
582
583	client = local_rpcb();
584	if (! client) {
585		return (FALSE);
586	}
587
588	parms.r_prog = program;
589	parms.r_vers = version;
590	if (nconf)
591		parms.r_netid = nconf->nc_netid;
592	else {
593		/*LINTED const castaway*/
594		parms.r_netid = (char *) &nullstring[0]; /* unsets  all */
595	}
596	/*LINTED const castaway*/
597	parms.r_addr = (char *) &nullstring[0];
598	(void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid());
599	parms.r_owner = uidbuf;
600
601	CLNT_CALL(client, (rpcproc_t)RPCBPROC_UNSET, (xdrproc_t) xdr_rpcb,
602	    (char *)(void *)&parms, (xdrproc_t) xdr_bool,
603	    (char *)(void *)&rslt, tottimeout);
604
605	CLNT_DESTROY(client);
606	return (rslt);
607}
608
609/*
610 * From the merged list, find the appropriate entry
611 */
612static struct netbuf *
613got_entry(rpcb_entry_list_ptr relp, const struct netconfig *nconf)
614{
615	struct netbuf *na = NULL;
616	rpcb_entry_list_ptr sp;
617	rpcb_entry *rmap;
618
619	for (sp = relp; sp != NULL; sp = sp->rpcb_entry_next) {
620		rmap = &sp->rpcb_entry_map;
621		if ((strcmp(nconf->nc_proto, rmap->r_nc_proto) == 0) &&
622		    (strcmp(nconf->nc_protofmly, rmap->r_nc_protofmly) == 0) &&
623		    (nconf->nc_semantics == rmap->r_nc_semantics) &&
624		    (rmap->r_maddr != NULL) && (rmap->r_maddr[0] != 0)) {
625			na = uaddr2taddr(nconf, rmap->r_maddr);
626#ifdef ND_DEBUG
627			fprintf(stderr, "\tRemote address is [%s].\n",
628				rmap->r_maddr);
629			if (!na)
630				fprintf(stderr,
631				    "\tCouldn't resolve remote address!\n");
632#endif
633			break;
634		}
635	}
636	return (na);
637}
638
639/*
640 * Quick check to see if rpcbind is up.  Tries to connect over
641 * local transport.
642 */
643static bool_t
644__rpcbind_is_up(void)
645{
646	struct netconfig *nconf;
647	struct sockaddr_un sun;
648	void *localhandle;
649	int sock;
650
651	nconf = NULL;
652	localhandle = setnetconfig();
653	while ((nconf = getnetconfig(localhandle)) != NULL) {
654		if (nconf->nc_protofmly != NULL &&
655		    strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
656			 break;
657	}
658	endnetconfig(localhandle);
659
660	if (nconf == NULL)
661		return (FALSE);
662
663	memset(&sun, 0, sizeof sun);
664	sock = _socket(AF_LOCAL, SOCK_STREAM, 0);
665	if (sock < 0)
666		return (FALSE);
667	sun.sun_family = AF_LOCAL;
668	strncpy(sun.sun_path, _PATH_RPCBINDSOCK, sizeof(sun.sun_path));
669	sun.sun_len = SUN_LEN(&sun);
670
671	if (_connect(sock, (struct sockaddr *)&sun, sun.sun_len) < 0) {
672		_close(sock);
673		return (FALSE);
674	}
675
676	_close(sock);
677	return (TRUE);
678}
679
680/*
681 * An internal function which optimizes rpcb_getaddr function.  It also
682 * returns the client handle that it uses to contact the remote rpcbind.
683 *
684 * The algorithm used: If the transports is TCP or UDP, it first tries
685 * version 2 (portmap), 4 and then 3 (svr4).  This order should be
686 * changed in the next OS release to 4, 2 and 3.  We are assuming that by
687 * that time, version 4 would be available on many machines on the network.
688 * With this algorithm, we get performance as well as a plan for
689 * obsoleting version 2.
690 *
691 * For all other transports, the algorithm remains as 4 and then 3.
692 *
693 * XXX: Due to some problems with t_connect(), we do not reuse the same client
694 * handle for COTS cases and hence in these cases we do not return the
695 * client handle.  This code will change if t_connect() ever
696 * starts working properly.  Also look under clnt_vc.c.
697 */
698struct netbuf *
699__rpcb_findaddr_timed(rpcprog_t program, rpcvers_t version,
700    const struct netconfig *nconf, const char *host,
701    CLIENT **clpp, struct timeval *tp)
702{
703	static bool_t check_rpcbind = TRUE;
704	CLIENT *client = NULL;
705	RPCB parms;
706	enum clnt_stat clnt_st;
707	char *ua = NULL;
708	rpcvers_t vers;
709	struct netbuf *address = NULL;
710	rpcvers_t start_vers = RPCBVERS4;
711	struct netbuf servaddr;
712
713	/* parameter checking */
714	if (nconf == NULL) {
715		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
716		return (NULL);
717	}
718
719	parms.r_addr = NULL;
720
721	/*
722	 * Use default total timeout if no timeout is specified.
723	 */
724	if (tp == NULL)
725		tp = &tottimeout;
726
727#ifdef PORTMAP
728	/* Try version 2 for TCP or UDP */
729	if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
730		u_short port = 0;
731		struct netbuf remote;
732		rpcvers_t pmapvers = 2;
733		struct pmap pmapparms;
734
735		/*
736		 * The comment below is now very old, having
737		 * been committed to FreeBSD during an import
738		 * from NetBSD in 2001.  I do not believe there
739		 * will still be any rpcbind servers that do
740		 * UDP only and, since Azure requires use of
741		 * TCP for NFSv3 mounts, comment this out
742		 * so that NFSv3 mounts on Azure can work.
743		 */
744#ifdef notnow
745		/*
746		 * Try UDP only - there are some portmappers out
747		 * there that use UDP only.
748		 */
749		if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
750			struct netconfig *newnconf;
751
752			if ((newnconf = getnetconfigent("udp")) == NULL) {
753				rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
754				return (NULL);
755			}
756			client = getclnthandle(host, newnconf, &parms.r_addr);
757			freenetconfigent(newnconf);
758		} else
759#endif
760			client = getclnthandle(host, nconf, &parms.r_addr);
761		if (client == NULL)
762			return (NULL);
763
764		/*
765		 * Set version and retry timeout.
766		 */
767		CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime);
768		CLNT_CONTROL(client, CLSET_VERS, (char *)&pmapvers);
769
770		pmapparms.pm_prog = program;
771		pmapparms.pm_vers = version;
772		pmapparms.pm_prot = strcmp(nconf->nc_proto, NC_TCP) ?
773					IPPROTO_UDP : IPPROTO_TCP;
774		pmapparms.pm_port = 0;	/* not needed */
775		clnt_st = CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT,
776		    (xdrproc_t) xdr_pmap, (caddr_t)(void *)&pmapparms,
777		    (xdrproc_t) xdr_u_short, (caddr_t)(void *)&port,
778		    *tp);
779		if (clnt_st != RPC_SUCCESS) {
780			if ((clnt_st == RPC_PROGVERSMISMATCH) ||
781				(clnt_st == RPC_PROGUNAVAIL))
782				goto try_rpcbind; /* Try different versions */
783			rpc_createerr.cf_stat = RPC_PMAPFAILURE;
784			clnt_geterr(client, &rpc_createerr.cf_error);
785			goto error;
786		} else if (port == 0) {
787			address = NULL;
788			rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
789			goto error;
790		}
791		port = htons(port);
792		CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)&remote);
793		if (((address = (struct netbuf *)
794			malloc(sizeof (struct netbuf))) == NULL) ||
795		    ((address->buf = (char *)
796			malloc(remote.len)) == NULL)) {
797			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
798			clnt_geterr(client, &rpc_createerr.cf_error);
799			free(address);
800			address = NULL;
801			goto error;
802		}
803		memcpy(address->buf, remote.buf, remote.len);
804		memcpy(&((char *)address->buf)[sizeof (short)],
805				(char *)(void *)&port, sizeof (short));
806		address->len = address->maxlen = remote.len;
807		goto done;
808	}
809#endif				/* PORTMAP */
810
811try_rpcbind:
812	/*
813	 * Check if rpcbind is up.  This prevents needless delays when
814	 * accessing applications such as the keyserver while booting
815	 * disklessly.
816	 */
817	if (check_rpcbind && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
818		if (!__rpcbind_is_up()) {
819			rpc_createerr.cf_stat = RPC_PMAPFAILURE;
820			rpc_createerr.cf_error.re_errno = 0;
821			goto error;
822		}
823		check_rpcbind = FALSE;
824	}
825
826	/*
827	 * Now we try version 4 and then 3.
828	 * We also send the remote system the address we used to
829	 * contact it in case it can help to connect back with us
830	 */
831	parms.r_prog = program;
832	parms.r_vers = version;
833	/*LINTED const castaway*/
834	parms.r_owner = (char *) &nullstring[0];	/* not needed; */
835							/* just for xdring */
836	parms.r_netid = nconf->nc_netid; /* not really needed */
837
838	/*
839	 * If a COTS transport is being used, try getting address via CLTS
840	 * transport.  This works only with version 4.
841	 */
842	if (nconf->nc_semantics == NC_TPI_COTS_ORD ||
843			nconf->nc_semantics == NC_TPI_COTS) {
844
845		void *handle;
846		struct netconfig *nconf_clts;
847		rpcb_entry_list_ptr relp = NULL;
848
849		if (client == NULL) {
850			/* This did not go through the above PORTMAP/TCP code */
851			if ((handle = __rpc_setconf("datagram_v")) != NULL) {
852				while ((nconf_clts = __rpc_getconf(handle))
853					!= NULL) {
854					if (strcmp(nconf_clts->nc_protofmly,
855						nconf->nc_protofmly) != 0) {
856						continue;
857					}
858					client = getclnthandle(host, nconf_clts,
859							&parms.r_addr);
860					break;
861				}
862				__rpc_endconf(handle);
863			}
864			if (client == NULL)
865				goto regular_rpcbind;	/* Go the regular way */
866		} else {
867			/* This is a UDP PORTMAP handle.  Change to version 4 */
868			vers = RPCBVERS4;
869			CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
870		}
871		/*
872		 * We also send the remote system the address we used to
873		 * contact it in case it can help it connect back with us
874		 */
875		if (parms.r_addr == NULL) {
876			/*LINTED const castaway*/
877			parms.r_addr = (char *) &nullstring[0]; /* for XDRing */
878		}
879
880		CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime);
881
882		clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDRLIST,
883		    (xdrproc_t) xdr_rpcb, (char *)(void *)&parms,
884		    (xdrproc_t) xdr_rpcb_entry_list_ptr,
885		    (char *)(void *)&relp, *tp);
886		if (clnt_st == RPC_SUCCESS) {
887			if ((address = got_entry(relp, nconf)) != NULL) {
888				xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr,
889				    (char *)(void *)&relp);
890				CLNT_CONTROL(client, CLGET_SVC_ADDR,
891					(char *)(void *)&servaddr);
892				__rpc_fixup_addr(address, &servaddr);
893				goto done;
894			}
895			/* Entry not found for this transport */
896			xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr,
897			    (char *)(void *)&relp);
898			/*
899			 * XXX: should have perhaps returned with error but
900			 * since the remote machine might not always be able
901			 * to send the address on all transports, we try the
902			 * regular way with regular_rpcbind
903			 */
904			goto regular_rpcbind;
905		} else if ((clnt_st == RPC_PROGVERSMISMATCH) ||
906			(clnt_st == RPC_PROGUNAVAIL)) {
907			start_vers = RPCBVERS;	/* Try version 3 now */
908			goto regular_rpcbind; /* Try different versions */
909		} else {
910			rpc_createerr.cf_stat = RPC_PMAPFAILURE;
911			clnt_geterr(client, &rpc_createerr.cf_error);
912			goto error;
913		}
914	}
915
916regular_rpcbind:
917
918	/* Now the same transport is to be used to get the address */
919	if (client && ((nconf->nc_semantics == NC_TPI_COTS_ORD) ||
920			(nconf->nc_semantics == NC_TPI_COTS))) {
921		/* A CLTS type of client - destroy it */
922		CLNT_DESTROY(client);
923		client = NULL;
924	}
925
926	if (client == NULL) {
927		client = getclnthandle(host, nconf, &parms.r_addr);
928		if (client == NULL) {
929			goto error;
930		}
931	}
932	if (parms.r_addr == NULL) {
933		/*LINTED const castaway*/
934		parms.r_addr = (char *) &nullstring[0];
935	}
936
937	/* First try from start_vers and then version 3 (RPCBVERS) */
938
939	CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *) &rpcbrmttime);
940	for (vers = start_vers;  vers >= RPCBVERS; vers--) {
941		/* Set the version */
942		CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
943		clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDR,
944		    (xdrproc_t) xdr_rpcb, (char *)(void *)&parms,
945		    (xdrproc_t) xdr_wrapstring, (char *)(void *) &ua, *tp);
946		if (clnt_st == RPC_SUCCESS) {
947			if ((ua == NULL) || (ua[0] == 0)) {
948				/* address unknown */
949				rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
950				goto error;
951			}
952			address = uaddr2taddr(nconf, ua);
953#ifdef ND_DEBUG
954			fprintf(stderr, "\tRemote address is [%s]\n", ua);
955			if (!address)
956				fprintf(stderr,
957					"\tCouldn't resolve remote address!\n");
958#endif
959			xdr_free((xdrproc_t)xdr_wrapstring,
960			    (char *)(void *)&ua);
961
962			if (! address) {
963				/* We don't know about your universal address */
964				rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
965				goto error;
966			}
967			CLNT_CONTROL(client, CLGET_SVC_ADDR,
968			    (char *)(void *)&servaddr);
969			__rpc_fixup_addr(address, &servaddr);
970			goto done;
971		} else if (clnt_st == RPC_PROGVERSMISMATCH) {
972			struct rpc_err rpcerr;
973
974			clnt_geterr(client, &rpcerr);
975			if (rpcerr.re_vers.low > RPCBVERS4)
976				goto error;  /* a new version, can't handle */
977		} else if (clnt_st != RPC_PROGUNAVAIL) {
978			/* Cant handle this error */
979			rpc_createerr.cf_stat = clnt_st;
980			clnt_geterr(client, &rpc_createerr.cf_error);
981			goto error;
982		}
983	}
984
985error:
986	if (client) {
987		CLNT_DESTROY(client);
988		client = NULL;
989	}
990done:
991	if (nconf->nc_semantics != NC_TPI_CLTS) {
992		/* This client is the connectionless one */
993		if (client) {
994			CLNT_DESTROY(client);
995			client = NULL;
996		}
997	}
998	if (clpp) {
999		*clpp = client;
1000	} else if (client) {
1001		CLNT_DESTROY(client);
1002	}
1003	if (parms.r_addr != NULL && parms.r_addr != nullstring)
1004		free(parms.r_addr);
1005	return (address);
1006}
1007
1008
1009/*
1010 * Find the mapped address for program, version.
1011 * Calls the rpcbind service remotely to do the lookup.
1012 * Uses the transport specified in nconf.
1013 * Returns FALSE (0) if no map exists, else returns 1.
1014 *
1015 * Assuming that the address is all properly allocated
1016 */
1017bool_t
1018rpcb_getaddr(rpcprog_t program, rpcvers_t version, const struct netconfig *nconf,
1019    struct netbuf *address, const char *host)
1020{
1021	struct netbuf *na;
1022
1023	if ((na = __rpcb_findaddr_timed(program, version,
1024	    (struct netconfig *) nconf, (char *) host,
1025	    (CLIENT **) NULL, (struct timeval *) NULL)) == NULL)
1026		return (FALSE);
1027
1028	if (na->len > address->maxlen) {
1029		/* Too long address */
1030		free(na->buf);
1031		free(na);
1032		rpc_createerr.cf_stat = RPC_FAILED;
1033		return (FALSE);
1034	}
1035	memcpy(address->buf, na->buf, (size_t)na->len);
1036	address->len = na->len;
1037	free(na->buf);
1038	free(na);
1039	return (TRUE);
1040}
1041
1042/*
1043 * Get a copy of the current maps.
1044 * Calls the rpcbind service remotely to get the maps.
1045 *
1046 * It returns only a list of the services
1047 * It returns NULL on failure.
1048 */
1049rpcblist *
1050rpcb_getmaps(const struct netconfig *nconf, const char *host)
1051{
1052	rpcblist_ptr head = NULL;
1053	CLIENT *client;
1054	enum clnt_stat clnt_st;
1055	rpcvers_t vers = 0;
1056
1057	client = getclnthandle(host, nconf, NULL);
1058	if (client == NULL) {
1059		return (head);
1060	}
1061	clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP,
1062	    (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr,
1063	    (char *)(void *)&head, tottimeout);
1064	if (clnt_st == RPC_SUCCESS)
1065		goto done;
1066
1067	if ((clnt_st != RPC_PROGVERSMISMATCH) &&
1068	    (clnt_st != RPC_PROGUNAVAIL)) {
1069		rpc_createerr.cf_stat = RPC_RPCBFAILURE;
1070		clnt_geterr(client, &rpc_createerr.cf_error);
1071		goto done;
1072	}
1073
1074	/* fall back to earlier version */
1075	CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers);
1076	if (vers == RPCBVERS4) {
1077		vers = RPCBVERS;
1078		CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
1079		if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP,
1080		    (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr,
1081		    (char *)(void *)&head, tottimeout) == RPC_SUCCESS)
1082			goto done;
1083	}
1084	rpc_createerr.cf_stat = RPC_RPCBFAILURE;
1085	clnt_geterr(client, &rpc_createerr.cf_error);
1086
1087done:
1088	CLNT_DESTROY(client);
1089	return (head);
1090}
1091
1092/*
1093 * rpcbinder remote-call-service interface.
1094 * This routine is used to call the rpcbind remote call service
1095 * which will look up a service program in the address maps, and then
1096 * remotely call that routine with the given parameters. This allows
1097 * programs to do a lookup and call in one step.
1098 *
1099 * nconf    -Netconfig structure
1100 * host     - Remote host name
1101 * proc     - Remote proc identifiers
1102 * xdrargs, xdrres;  XDR routines
1103 * argsp, resp - Argument and Result
1104 * tout     - Timeout value for this call
1105 * addr_ptr - Preallocated netbuf address
1106 */
1107enum clnt_stat
1108rpcb_rmtcall(const struct netconfig *nconf, const char *host, rpcprog_t prog,
1109    rpcvers_t vers, rpcproc_t proc, xdrproc_t xdrargs, caddr_t argsp,
1110    xdrproc_t xdrres, caddr_t resp, struct timeval tout,
1111    const struct netbuf *addr_ptr)
1112{
1113	CLIENT *client;
1114	enum clnt_stat stat;
1115	struct r_rpcb_rmtcallargs a;
1116	struct r_rpcb_rmtcallres r;
1117	rpcvers_t rpcb_vers;
1118
1119	stat = 0;
1120	client = getclnthandle(host, nconf, NULL);
1121	if (client == NULL) {
1122		return (RPC_FAILED);
1123	}
1124	/*LINTED const castaway*/
1125	CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)(void *)&rmttimeout);
1126	a.prog = prog;
1127	a.vers = vers;
1128	a.proc = proc;
1129	a.args.args_val = argsp;
1130	a.xdr_args = xdrargs;
1131	r.addr = NULL;
1132	r.results.results_val = resp;
1133	r.xdr_res = xdrres;
1134
1135	for (rpcb_vers = RPCBVERS4; rpcb_vers >= RPCBVERS; rpcb_vers--) {
1136		CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&rpcb_vers);
1137		stat = CLNT_CALL(client, (rpcproc_t)RPCBPROC_CALLIT,
1138		    (xdrproc_t) xdr_rpcb_rmtcallargs, (char *)(void *)&a,
1139		    (xdrproc_t) xdr_rpcb_rmtcallres, (char *)(void *)&r, tout);
1140		if ((stat == RPC_SUCCESS) && (addr_ptr != NULL)) {
1141			struct netbuf *na;
1142			/*LINTED const castaway*/
1143			na = uaddr2taddr((struct netconfig *) nconf, r.addr);
1144			if (!na) {
1145				stat = RPC_N2AXLATEFAILURE;
1146				/*LINTED const castaway*/
1147				((struct netbuf *) addr_ptr)->len = 0;
1148				goto error;
1149			}
1150			if (na->len > addr_ptr->maxlen) {
1151				/* Too long address */
1152				stat = RPC_FAILED; /* XXX A better error no */
1153				free(na->buf);
1154				free(na);
1155				/*LINTED const castaway*/
1156				((struct netbuf *) addr_ptr)->len = 0;
1157				goto error;
1158			}
1159			memcpy(addr_ptr->buf, na->buf, (size_t)na->len);
1160			/*LINTED const castaway*/
1161			((struct netbuf *)addr_ptr)->len = na->len;
1162			free(na->buf);
1163			free(na);
1164			break;
1165		} else if ((stat != RPC_PROGVERSMISMATCH) &&
1166			    (stat != RPC_PROGUNAVAIL)) {
1167			goto error;
1168		}
1169	}
1170error:
1171	CLNT_DESTROY(client);
1172	if (r.addr)
1173		xdr_free((xdrproc_t) xdr_wrapstring, (char *)(void *)&r.addr);
1174	return (stat);
1175}
1176
1177/*
1178 * Gets the time on the remote host.
1179 * Returns 1 if succeeds else 0.
1180 */
1181bool_t
1182rpcb_gettime(const char *host, time_t *timep)
1183{
1184	CLIENT *client = NULL;
1185	void *handle;
1186	struct netconfig *nconf;
1187	rpcvers_t vers;
1188	enum clnt_stat st;
1189
1190
1191	if ((host == NULL) || (host[0] == 0)) {
1192		time(timep);
1193		return (TRUE);
1194	}
1195
1196	if ((handle = __rpc_setconf("netpath")) == NULL) {
1197		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
1198		return (FALSE);
1199	}
1200	rpc_createerr.cf_stat = RPC_SUCCESS;
1201	while (client == NULL) {
1202		if ((nconf = __rpc_getconf(handle)) == NULL) {
1203			if (rpc_createerr.cf_stat == RPC_SUCCESS)
1204				rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
1205			break;
1206		}
1207		client = getclnthandle(host, nconf, NULL);
1208		if (client)
1209			break;
1210	}
1211	__rpc_endconf(handle);
1212	if (client == (CLIENT *) NULL) {
1213		return (FALSE);
1214	}
1215
1216	st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME,
1217		(xdrproc_t) xdr_void, NULL,
1218		(xdrproc_t) xdr_int, (char *)(void *)timep, tottimeout);
1219
1220	if ((st == RPC_PROGVERSMISMATCH) || (st == RPC_PROGUNAVAIL)) {
1221		CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers);
1222		if (vers == RPCBVERS4) {
1223			/* fall back to earlier version */
1224			vers = RPCBVERS;
1225			CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
1226			st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME,
1227				(xdrproc_t) xdr_void, NULL,
1228				(xdrproc_t) xdr_int, (char *)(void *)timep,
1229				tottimeout);
1230		}
1231	}
1232	CLNT_DESTROY(client);
1233	return (st == RPC_SUCCESS? TRUE: FALSE);
1234}
1235
1236/*
1237 * Converts taddr to universal address.  This routine should never
1238 * really be called because local n2a libraries are always provided.
1239 */
1240char *
1241rpcb_taddr2uaddr(struct netconfig *nconf, struct netbuf *taddr)
1242{
1243	CLIENT *client;
1244	char *uaddr = NULL;
1245
1246
1247	/* parameter checking */
1248	if (nconf == NULL) {
1249		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
1250		return (NULL);
1251	}
1252	if (taddr == NULL) {
1253		rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
1254		return (NULL);
1255	}
1256	client = local_rpcb();
1257	if (! client) {
1258		return (NULL);
1259	}
1260
1261	CLNT_CALL(client, (rpcproc_t)RPCBPROC_TADDR2UADDR,
1262	    (xdrproc_t) xdr_netbuf, (char *)(void *)taddr,
1263	    (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr, tottimeout);
1264	CLNT_DESTROY(client);
1265	return (uaddr);
1266}
1267
1268/*
1269 * Converts universal address to netbuf.  This routine should never
1270 * really be called because local n2a libraries are always provided.
1271 */
1272struct netbuf *
1273rpcb_uaddr2taddr(struct netconfig *nconf, char *uaddr)
1274{
1275	CLIENT *client;
1276	struct netbuf *taddr;
1277
1278
1279	/* parameter checking */
1280	if (nconf == NULL) {
1281		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
1282		return (NULL);
1283	}
1284	if (uaddr == NULL) {
1285		rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
1286		return (NULL);
1287	}
1288	client = local_rpcb();
1289	if (! client) {
1290		return (NULL);
1291	}
1292
1293	taddr = (struct netbuf *)calloc(1, sizeof (struct netbuf));
1294	if (taddr == NULL) {
1295		CLNT_DESTROY(client);
1296		return (NULL);
1297	}
1298	if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_UADDR2TADDR,
1299	    (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr,
1300	    (xdrproc_t) xdr_netbuf, (char *)(void *)taddr,
1301	    tottimeout) != RPC_SUCCESS) {
1302		free(taddr);
1303		taddr = NULL;
1304	}
1305	CLNT_DESTROY(client);
1306	return (taddr);
1307}
1308