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