xref: /onnv-gate/usr/src/lib/libnsl/yp/yp_bind.c (revision 12264:0dd1980ff11a)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51914Scasper  * Common Development and Distribution License (the "License").
61914Scasper  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
20132Srobinson  */
21132Srobinson 
22132Srobinson /*
23*12264SGirish.Moodalbail@oracle.COM  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
270Sstevel@tonic-gate /*	  All Rights Reserved   */
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley
310Sstevel@tonic-gate  * under license from the Regents of the University of
320Sstevel@tonic-gate  * California.
330Sstevel@tonic-gate  */
340Sstevel@tonic-gate #include "mt.h"
350Sstevel@tonic-gate #include "../rpc/rpc_mt.h"
360Sstevel@tonic-gate #include <stdio.h>
370Sstevel@tonic-gate #include <stdlib.h>
380Sstevel@tonic-gate #include <string.h>
390Sstevel@tonic-gate #include <sys/types.h>
400Sstevel@tonic-gate #include <sys/stat.h>
410Sstevel@tonic-gate #include <errno.h>
420Sstevel@tonic-gate #include <unistd.h>
430Sstevel@tonic-gate #include <rpc/rpc.h>
440Sstevel@tonic-gate #include <netconfig.h>
450Sstevel@tonic-gate #include <netdir.h>
460Sstevel@tonic-gate #include <syslog.h>
470Sstevel@tonic-gate #include "yp_b.h"
480Sstevel@tonic-gate #include <rpcsvc/yp_prot.h>
490Sstevel@tonic-gate #include <rpcsvc/ypclnt.h>
500Sstevel@tonic-gate #include <sys/tiuser.h>
510Sstevel@tonic-gate 
520Sstevel@tonic-gate #define	BFSIZE	(YPMAXDOMAIN + 32)	/* size of binding file */
530Sstevel@tonic-gate int	 __ypipbufsize = 8192;		/* size used for clnt_tli_create */
540Sstevel@tonic-gate 
550Sstevel@tonic-gate /* This should match the one in ypbind.c */
560Sstevel@tonic-gate 
570Sstevel@tonic-gate extern int getdomainname(char *, int);
580Sstevel@tonic-gate 
590Sstevel@tonic-gate static CLIENT *getclnt(rpcprog_t, rpcvers_t, struct netconfig *, int *);
600Sstevel@tonic-gate static struct dom_binding *load_dom_binding(struct ypbind_resp *, char *,
610Sstevel@tonic-gate     int *);
620Sstevel@tonic-gate static ypbind_resp *get_cached_domain(char *);
630Sstevel@tonic-gate static int get_cached_transport(struct netconfig *, int, char *, int);
640Sstevel@tonic-gate static int ypbind_running(int, int);
650Sstevel@tonic-gate static void set_rdev(struct dom_binding *);
660Sstevel@tonic-gate static int check_rdev(struct dom_binding *);
670Sstevel@tonic-gate 
680Sstevel@tonic-gate static char nullstring[] = "";
690Sstevel@tonic-gate /*
700Sstevel@tonic-gate  * Time parameters when talking to the ypbind and pmap processes
710Sstevel@tonic-gate  */
720Sstevel@tonic-gate 
730Sstevel@tonic-gate #define	YPSLEEPTIME	5		/* Time to sleep between tries */
740Sstevel@tonic-gate unsigned int _ypsleeptime = YPSLEEPTIME;
750Sstevel@tonic-gate 
760Sstevel@tonic-gate /*
770Sstevel@tonic-gate  * Time parameters when talking to the ypserv process
780Sstevel@tonic-gate  */
790Sstevel@tonic-gate 
800Sstevel@tonic-gate #ifdef  DEBUG
810Sstevel@tonic-gate #define	YPTIMEOUT	120		/* Total seconds for timeout */
820Sstevel@tonic-gate #define	YPINTER_TRY	60		/* Seconds between tries */
830Sstevel@tonic-gate #else
840Sstevel@tonic-gate #define	YPTIMEOUT	20		/* Total seconds for timeout */
850Sstevel@tonic-gate #define	YPINTER_TRY	5		/* Seconds between tries */
860Sstevel@tonic-gate #endif
870Sstevel@tonic-gate 
880Sstevel@tonic-gate #define	MAX_TRIES_FOR_NEW_YP	1	/* Number of times we'll try to */
890Sstevel@tonic-gate 					/* get a new YP server before   */
900Sstevel@tonic-gate 					/* we'll settle for an old one. */
910Sstevel@tonic-gate struct timeval _ypserv_timeout = {
920Sstevel@tonic-gate 	YPTIMEOUT,			/* Seconds */
930Sstevel@tonic-gate 	0				/* Microseconds */
940Sstevel@tonic-gate 	};
950Sstevel@tonic-gate 
960Sstevel@tonic-gate static mutex_t			default_domain_lock = DEFAULTMUTEX;
970Sstevel@tonic-gate static char			*default_domain;
980Sstevel@tonic-gate 
990Sstevel@tonic-gate /*
1000Sstevel@tonic-gate  * The bound_domains_lock serializes all action in yp_unbind(), __yp_dobind(),
1010Sstevel@tonic-gate  *   newborn(), check_binding() and laod_dom_binding(), not just the direct
1020Sstevel@tonic-gate  *   manipulation of the bound_domains list.
1030Sstevel@tonic-gate  * It also protects all of the fields within a domain binding except
1040Sstevel@tonic-gate  *   the server_name field (which is protected by the server_name_lock).
1050Sstevel@tonic-gate  * A better implementation might try to serialize each domain separately,
1060Sstevel@tonic-gate  *   but normally we're only dealing with one domain (the default) anyway.
1070Sstevel@tonic-gate  * To avoid one thread freeing a domain binding while another is using
1080Sstevel@tonic-gate  *   the binding, we maintain a reference count for each binding.  The
1090Sstevel@tonic-gate  *   reference count is incremented in __yp_dobind.  The thread calls
1100Sstevel@tonic-gate  *   __yp_rel_binding() when it has finished using the binding (which
1110Sstevel@tonic-gate  *   decrements the reference count).  If the reference count is non-zero
1120Sstevel@tonic-gate  *   when a thread tries to free a binding, the need_free flag is set and
1130Sstevel@tonic-gate  *   the free is delayed.  The __yp_rel_binding() routine checks the flag
1140Sstevel@tonic-gate  *   and calls the free routine if the flag is set and the reference
1150Sstevel@tonic-gate  *   count is zero.
1160Sstevel@tonic-gate  */
1170Sstevel@tonic-gate static mutex_t			bound_domains_lock = DEFAULTMUTEX;
1180Sstevel@tonic-gate static struct dom_binding	*bound_domains; /* List of bound domains */
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate /*
1220Sstevel@tonic-gate  *  Must be called with bound_domains_lock held or with a dom_binding
1230Sstevel@tonic-gate  *  that cannot be referenced by another thread.
1240Sstevel@tonic-gate  */
1250Sstevel@tonic-gate void
free_dom_binding(struct dom_binding * p)126132Srobinson free_dom_binding(struct dom_binding *p)
1270Sstevel@tonic-gate {
1280Sstevel@tonic-gate 	if (p->ref_count != 0) {
1290Sstevel@tonic-gate 		p->need_free = 1;
1300Sstevel@tonic-gate 		return;
1310Sstevel@tonic-gate 	}
1320Sstevel@tonic-gate 	(void) check_rdev(p);
1330Sstevel@tonic-gate 	clnt_destroy(p->dom_client);
1340Sstevel@tonic-gate 	free(p->dom_domain);
135132Srobinson 	free(p);
1360Sstevel@tonic-gate }
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate /*
1390Sstevel@tonic-gate  * Attempts to find a dom_binding in the list at bound_domains having the
1400Sstevel@tonic-gate  * domain name field equal to the passed domain name, and removes it if found.
1410Sstevel@tonic-gate  * The domain-server binding will not exist after the call to this function.
1420Sstevel@tonic-gate  * All resources associated with the binding will be freed.
1430Sstevel@tonic-gate  *
1440Sstevel@tonic-gate  * yp_unbind is MT-safe because it serializes on bound_domains_lock.
1450Sstevel@tonic-gate  */
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate static void
__yp_unbind_nolock(char * domain)148132Srobinson __yp_unbind_nolock(char *domain)
1490Sstevel@tonic-gate {
1500Sstevel@tonic-gate 	struct dom_binding *p;
1510Sstevel@tonic-gate 	struct dom_binding **prev;
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	if ((domain == NULL) || (strlen(domain) == 0)) {
1540Sstevel@tonic-gate 		return;
1550Sstevel@tonic-gate 	}
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	/*
1580Sstevel@tonic-gate 	 *  If we used a cache file to bind, then we will mark the
1590Sstevel@tonic-gate 	 *  cache bad.  This will cause a subsequent call to __yp_dobind
1600Sstevel@tonic-gate 	 *  to ignore the cache and talk to ypbind.  Otherwise, we
1610Sstevel@tonic-gate 	 *  have already gotten a binding by talking to ypbind and
1620Sstevel@tonic-gate 	 *  the binding is not good.
1630Sstevel@tonic-gate 	 *
1640Sstevel@tonic-gate 	 *  An optimization could be to check to see if the cache
1650Sstevel@tonic-gate 	 *  file has changed (ypbind is pointing at a new server) and
1660Sstevel@tonic-gate 	 *  reload the binding from it.  But that is too much work
1670Sstevel@tonic-gate 	 *  for now.
1680Sstevel@tonic-gate 	 */
1690Sstevel@tonic-gate 	for (prev = &bound_domains;  (p = *prev) != 0;  prev = &p->dom_pnext) {
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 		if (strcmp(domain, p->dom_domain) == 0) {
1720Sstevel@tonic-gate 			if (!p->cache_bad) {
1730Sstevel@tonic-gate 				p->cache_bad = 1;
1740Sstevel@tonic-gate 				break;
1750Sstevel@tonic-gate 			}
1760Sstevel@tonic-gate 			*prev = p->dom_pnext;
1770Sstevel@tonic-gate 			free_dom_binding(p);
1780Sstevel@tonic-gate 			break;
1790Sstevel@tonic-gate 		}
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	}
1820Sstevel@tonic-gate }
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate void
yp_unbind(char * domain)186132Srobinson yp_unbind(char *domain)
1870Sstevel@tonic-gate {
188132Srobinson 	(void) mutex_lock(&bound_domains_lock);
1890Sstevel@tonic-gate 	__yp_unbind_nolock(domain);
190132Srobinson 	(void) mutex_unlock(&bound_domains_lock);
1910Sstevel@tonic-gate }
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate /*
1950Sstevel@tonic-gate  * This checks to see if this is a new process incarnation which has
1960Sstevel@tonic-gate  * inherited bindings from a parent, and unbinds the world if so.
1970Sstevel@tonic-gate  *
1980Sstevel@tonic-gate  * MT-safe because it is only invoked from __yp_dobind(), which serializes
1990Sstevel@tonic-gate  * all requests.
2000Sstevel@tonic-gate  */
2010Sstevel@tonic-gate static void
newborn(void)202132Srobinson newborn(void)
2030Sstevel@tonic-gate {
2040Sstevel@tonic-gate 	static pid_t mypid;	/* Cached to detect forks */
2050Sstevel@tonic-gate 	pid_t testpid;
2060Sstevel@tonic-gate 	struct dom_binding *p, *q;
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 	if ((testpid = getpid()) != mypid) {
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 		mypid = testpid;
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 		for (p = bound_domains;  p != 0;  p = q) {
2130Sstevel@tonic-gate 			q = p->dom_pnext;
2140Sstevel@tonic-gate 			free_dom_binding(p);
2150Sstevel@tonic-gate 		}
2160Sstevel@tonic-gate 		bound_domains = 0;
2170Sstevel@tonic-gate 	}
2180Sstevel@tonic-gate }
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate /*
2210Sstevel@tonic-gate  * This checks that the socket for a domain which has already been bound
2220Sstevel@tonic-gate  * hasn't been closed or changed under us.  If it has, unbind the domain
2230Sstevel@tonic-gate  * without closing the socket, which may be in use by some higher level
2240Sstevel@tonic-gate  * code.  This returns TRUE and points the binding parameter at the found
2250Sstevel@tonic-gate  * dom_binding if the binding is found and the socket looks OK, and FALSE
2260Sstevel@tonic-gate  * otherwise.
2270Sstevel@tonic-gate  *
2280Sstevel@tonic-gate  * MT-safe because it is only invoked from __yp_dobind(), which serializes
2290Sstevel@tonic-gate  * all requests.
2300Sstevel@tonic-gate  */
2310Sstevel@tonic-gate static bool
check_binding(char * domain,struct dom_binding ** binding)232132Srobinson check_binding(char *domain, struct dom_binding **binding)
2330Sstevel@tonic-gate {
2340Sstevel@tonic-gate 	struct dom_binding *pdomb;
2350Sstevel@tonic-gate 	struct ypbind_resp *ypbind_resp;
2360Sstevel@tonic-gate 	int status;
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate 	for (pdomb = bound_domains; pdomb != NULL; pdomb = pdomb->dom_pnext) {
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 		if (strcmp(domain, pdomb->dom_domain) == 0) {
2410Sstevel@tonic-gate 		/*
2420Sstevel@tonic-gate 		 * XXX How do we really make sure the udp connection hasn't
2430Sstevel@tonic-gate 		 * changes under us ? If it happens and we can't detect it,
2440Sstevel@tonic-gate 		 * the appliction is doomed !
2450Sstevel@tonic-gate 		 * POLICY: Let nobody do a yp_bind or __yp_dobind explicitly
2460Sstevel@tonic-gate 		 * and forget to to yp_unbind it. All apps should go
2470Sstevel@tonic-gate 		 * through the standard yp_match/first etc. functions.
2480Sstevel@tonic-gate 		 */
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 			*binding = pdomb;
2510Sstevel@tonic-gate 			return (TRUE);
2520Sstevel@tonic-gate 		}
2530Sstevel@tonic-gate 	}
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 	/*
2560Sstevel@tonic-gate 	 *  We check to see if we can do a quick bind to ypserv.
2570Sstevel@tonic-gate 	 *  If we can, then we load the binding (i.e., add it to our
2580Sstevel@tonic-gate 	 *  cache of bindings) and then return it.
2590Sstevel@tonic-gate 	 */
2600Sstevel@tonic-gate 	if ((ypbind_resp = get_cached_domain(domain)) != 0) {
2610Sstevel@tonic-gate 		pdomb = load_dom_binding(ypbind_resp, domain, &status);
262132Srobinson 		if (pdomb == 0)
2630Sstevel@tonic-gate 			return (FALSE);
2640Sstevel@tonic-gate 		*binding = pdomb;
2650Sstevel@tonic-gate 		return (TRUE);
2660Sstevel@tonic-gate 	}
2670Sstevel@tonic-gate 	return (FALSE);
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate /*
2710Sstevel@tonic-gate  *  This routine adds a binding for a particular server to our
2720Sstevel@tonic-gate  *  list of bound domains.  We check to see if there is actually
2730Sstevel@tonic-gate  *  a yp server at the given address.  If not, or if there is
2740Sstevel@tonic-gate  *  any other error, we return 0.  We have to malloc the binding
2750Sstevel@tonic-gate  *  structure because that is what a call to ypbind returns and
2760Sstevel@tonic-gate  *  we are basically doing what a call to ypbind would do.
2770Sstevel@tonic-gate  */
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate #define	SOCKADDR_SIZE (sizeof (struct sockaddr_in6))
2800Sstevel@tonic-gate static int
__yp_add_binding_netid(char * domain,char * addr,char * netid)2810Sstevel@tonic-gate __yp_add_binding_netid(char *domain, char *addr, char *netid)
2820Sstevel@tonic-gate {
2830Sstevel@tonic-gate 	struct netconfig *nconf = 0;
2840Sstevel@tonic-gate 	struct netbuf *svcaddr = 0;
2850Sstevel@tonic-gate 	struct ypbind_binding *binding = 0;
2860Sstevel@tonic-gate 	int status;
2870Sstevel@tonic-gate 	struct ypbind_resp resp;
2880Sstevel@tonic-gate 	struct dom_binding *pdomb;
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 	nconf = getnetconfigent(netid);
2910Sstevel@tonic-gate 	if (nconf == 0)
2920Sstevel@tonic-gate 		goto err;
2930Sstevel@tonic-gate 
294132Srobinson 	svcaddr = malloc(sizeof (struct netbuf));
2950Sstevel@tonic-gate 	if (svcaddr == 0)
2960Sstevel@tonic-gate 		goto err;
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 	svcaddr->maxlen = SOCKADDR_SIZE;
299132Srobinson 	svcaddr->buf = malloc(SOCKADDR_SIZE);
3000Sstevel@tonic-gate 	if (svcaddr->buf == 0)
3010Sstevel@tonic-gate 		goto err;
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 	if (!rpcb_getaddr(YPPROG, YPVERS, nconf, svcaddr, addr))
3040Sstevel@tonic-gate 		goto err;
3050Sstevel@tonic-gate 
306132Srobinson 	binding = malloc(sizeof (struct ypbind_binding));
3070Sstevel@tonic-gate 	if (binding == 0)
3080Sstevel@tonic-gate 		goto err;
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate 	binding->ypbind_hi_vers = YPVERS;
3110Sstevel@tonic-gate 	binding->ypbind_lo_vers = YPVERS;
3120Sstevel@tonic-gate 	binding->ypbind_nconf = nconf;
3130Sstevel@tonic-gate 	binding->ypbind_svcaddr = svcaddr;
3140Sstevel@tonic-gate 	binding->ypbind_servername = (char *)strdup(addr);
3150Sstevel@tonic-gate 	if (binding->ypbind_servername == 0)
3160Sstevel@tonic-gate 		goto err;
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 	resp.ypbind_status = YPBIND_SUCC_VAL;
3190Sstevel@tonic-gate 	resp.ypbind_resp_u.ypbind_bindinfo = binding;
3200Sstevel@tonic-gate 
321132Srobinson 	(void) mutex_lock(&bound_domains_lock);
3220Sstevel@tonic-gate 	newborn();
3230Sstevel@tonic-gate 	pdomb = load_dom_binding(&resp, domain, &status);
324132Srobinson 	(void) mutex_unlock(&bound_domains_lock);
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 	return (pdomb != 0);
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate err:
3290Sstevel@tonic-gate 	if (nconf)
3300Sstevel@tonic-gate 		freenetconfigent(nconf);
3310Sstevel@tonic-gate 	if (svcaddr) {
3320Sstevel@tonic-gate 		if (svcaddr->buf)
333132Srobinson 			free(svcaddr->buf);
334132Srobinson 		free(svcaddr);
3350Sstevel@tonic-gate 	}
3360Sstevel@tonic-gate 	if (binding) {
3370Sstevel@tonic-gate 		if (binding->ypbind_servername)
3380Sstevel@tonic-gate 			free(binding->ypbind_servername);
3390Sstevel@tonic-gate 		free(binding);
3400Sstevel@tonic-gate 	}
3410Sstevel@tonic-gate 	return (0);
3420Sstevel@tonic-gate }
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate int
__yp_add_binding(char * domain,char * addr)3460Sstevel@tonic-gate __yp_add_binding(char *domain, char *addr) {
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate 	int ret = __yp_add_binding_netid(domain, addr, "udp6");
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate 	if (ret == 0)
3510Sstevel@tonic-gate 		ret = __yp_add_binding_netid(domain, addr, "udp");
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 	return (ret);
3540Sstevel@tonic-gate }
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate /*
3580Sstevel@tonic-gate  * This allocates some memory for a domain binding, initialize it, and
3590Sstevel@tonic-gate  * returns a pointer to it.  Based on the program version we ended up
3600Sstevel@tonic-gate  * talking to ypbind with, fill out an opvector of appropriate protocol
3610Sstevel@tonic-gate  * modules.
3620Sstevel@tonic-gate  *
3630Sstevel@tonic-gate  * MT-safe because it is only invoked from __yp_dobind(), which serializes
3640Sstevel@tonic-gate  * all requests.
3650Sstevel@tonic-gate  */
3660Sstevel@tonic-gate static struct dom_binding *
load_dom_binding(struct ypbind_resp * ypbind_res,char * domain,int * err)367132Srobinson load_dom_binding(struct ypbind_resp *ypbind_res, char *domain, int *err)
3680Sstevel@tonic-gate {
3690Sstevel@tonic-gate 	int fd;
3700Sstevel@tonic-gate 	struct dom_binding *pdomb;
3710Sstevel@tonic-gate 
372132Srobinson 	pdomb = NULL;
3730Sstevel@tonic-gate 
374132Srobinson 	if ((pdomb = malloc(sizeof (struct dom_binding))) == NULL) {
3750Sstevel@tonic-gate 		syslog(LOG_ERR, "load_dom_binding:  malloc failure.");
3760Sstevel@tonic-gate 		*err = YPERR_RESRC;
377132Srobinson 		return (NULL);
3780Sstevel@tonic-gate 	}
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate 	pdomb->dom_binding = ypbind_res->ypbind_resp_u.ypbind_bindinfo;
3810Sstevel@tonic-gate 	/*
3820Sstevel@tonic-gate 	 * Open up a path to the server, which will remain active globally.
3830Sstevel@tonic-gate 	 */
3840Sstevel@tonic-gate 	pdomb->dom_client = clnt_tli_create(RPC_ANYFD,
3850Sstevel@tonic-gate 					    pdomb->dom_binding->ypbind_nconf,
3860Sstevel@tonic-gate 					    pdomb->dom_binding->ypbind_svcaddr,
3870Sstevel@tonic-gate 					    YPPROG, YPVERS, __ypipbufsize,
3880Sstevel@tonic-gate 					    __ypipbufsize);
3890Sstevel@tonic-gate 	if (pdomb->dom_client == NULL) {
3900Sstevel@tonic-gate 		clnt_pcreateerror("yp_bind: clnt_tli_create");
391132Srobinson 		free(pdomb);
3920Sstevel@tonic-gate 		*err = YPERR_RPC;
393132Srobinson 		return (NULL);
3940Sstevel@tonic-gate 	}
3950Sstevel@tonic-gate #ifdef DEBUG
3960Sstevel@tonic-gate (void) printf("yp_bind: clnt_tli_create suceeded\n");
3970Sstevel@tonic-gate #endif
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 	pdomb->dom_pnext = bound_domains;	/* Link this to the list as */
400132Srobinson 	pdomb->dom_domain = malloc(strlen(domain) + (unsigned)1);
4010Sstevel@tonic-gate 	if (pdomb->dom_domain == NULL) {
4020Sstevel@tonic-gate 		clnt_destroy(pdomb->dom_client);
403132Srobinson 		free(pdomb);
4040Sstevel@tonic-gate 		*err = YPERR_RESRC;
405132Srobinson 		return (NULL);
4060Sstevel@tonic-gate 	}
4070Sstevel@tonic-gate 	/*
4080Sstevel@tonic-gate 	 *  We may not have loaded from a cache file, but we assume the
4090Sstevel@tonic-gate 	 *  cache is good until we find out otherwise.
4100Sstevel@tonic-gate 	 */
4110Sstevel@tonic-gate 	pdomb->cache_bad = 0;
4120Sstevel@tonic-gate 	set_rdev(pdomb);
4130Sstevel@tonic-gate 	if (clnt_control(pdomb->dom_client, CLGET_FD, (char *)&fd))
4141219Sraf 		(void) fcntl(fd, F_SETFD, 1);  /* make it "close on exec" */
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 	(void) strcpy(pdomb->dom_domain, domain); /* Remember the domain name */
4170Sstevel@tonic-gate 	pdomb->ref_count = 0;
4180Sstevel@tonic-gate 	pdomb->need_free = 0;
419132Srobinson 	(void) mutex_init(&pdomb->server_name_lock, USYNC_THREAD, 0);
4200Sstevel@tonic-gate 	bound_domains = pdomb;			/* ... the head entry */
4210Sstevel@tonic-gate 	return (pdomb);
4220Sstevel@tonic-gate }
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate /*
4250Sstevel@tonic-gate  * XXX special code for handling C2 (passwd.adjunct) lookups when we need
4260Sstevel@tonic-gate  * a reserved port.
4270Sstevel@tonic-gate  */
4280Sstevel@tonic-gate static int
tli_open_rsvdport(struct netconfig * nconf)429132Srobinson tli_open_rsvdport(struct netconfig *nconf)
4300Sstevel@tonic-gate {
4310Sstevel@tonic-gate 	int fd;
4320Sstevel@tonic-gate 
433132Srobinson 	if (nconf == NULL)
4340Sstevel@tonic-gate 		return (-1);
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 	fd = t_open(nconf->nc_device, O_RDWR, NULL);
437132Srobinson 	if (fd == -1)
4380Sstevel@tonic-gate 		return (-1);
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate 	if (netdir_options(nconf, ND_SET_RESERVEDPORT, fd, NULL) == -1) {
441132Srobinson 		if (t_bind(fd, NULL, NULL) == -1) {
4420Sstevel@tonic-gate 			(void) t_close(fd);
4430Sstevel@tonic-gate 			return (-1);
4440Sstevel@tonic-gate 		}
4450Sstevel@tonic-gate 	}
4460Sstevel@tonic-gate 	return (fd);
4470Sstevel@tonic-gate }
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate /*
4500Sstevel@tonic-gate  * This allocates some memory for a domain binding, initialize it, and
4510Sstevel@tonic-gate  * returns a pointer to it.  Based on the program version we ended up
4520Sstevel@tonic-gate  * talking to ypbind with, fill out an opvector of appropriate protocol
4530Sstevel@tonic-gate  * modules.
4540Sstevel@tonic-gate  *
4550Sstevel@tonic-gate  * MT-safe because it is only invoked from __yp_dobind(), which serializes
4560Sstevel@tonic-gate  * all requests.
4570Sstevel@tonic-gate  *
4580Sstevel@tonic-gate  * XXX special version for handling C2 (passwd.adjunct) lookups when we need
4590Sstevel@tonic-gate  * a reserved port.
4600Sstevel@tonic-gate  *
4610Sstevel@tonic-gate  * Note that the binding is not cached. The caller has to free the binding
4620Sstevel@tonic-gate  * using free_dom_binding().
4630Sstevel@tonic-gate  */
4640Sstevel@tonic-gate static struct dom_binding *
load_dom_binding_rsvdport(struct ypbind_binding * dom_binding,char * domain,int * err)465132Srobinson load_dom_binding_rsvdport(struct ypbind_binding *dom_binding, char *domain,
466132Srobinson 								int *err)
4670Sstevel@tonic-gate {
4680Sstevel@tonic-gate 	struct dom_binding *pdomb;
4690Sstevel@tonic-gate 	int fd;
4700Sstevel@tonic-gate 
471132Srobinson 	pdomb = NULL;
4720Sstevel@tonic-gate 
473132Srobinson 	if ((pdomb = malloc(sizeof (struct dom_binding))) == NULL) {
474132Srobinson 		syslog(LOG_ERR, "load_dom_binding_rsvdport:  malloc failure.");
4750Sstevel@tonic-gate 		*err = YPERR_RESRC;
476132Srobinson 		return (NULL);
4770Sstevel@tonic-gate 	}
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate 	pdomb->dom_binding = dom_binding;
4800Sstevel@tonic-gate 	/*
4810Sstevel@tonic-gate 	 * Open up a path to the server, which will remain active globally.
4820Sstevel@tonic-gate 	 */
4830Sstevel@tonic-gate 	fd = tli_open_rsvdport(pdomb->dom_binding->ypbind_nconf);
4840Sstevel@tonic-gate 	if (fd < 0) {
4850Sstevel@tonic-gate 		clnt_pcreateerror("yp_bind: tli_open_rsvdport");
486132Srobinson 		free(pdomb);
4870Sstevel@tonic-gate 		*err = YPERR_RPC;
488132Srobinson 		return (NULL);
4890Sstevel@tonic-gate 	}
4900Sstevel@tonic-gate 	pdomb->dom_client = clnt_tli_create(fd,
4910Sstevel@tonic-gate 					    pdomb->dom_binding->ypbind_nconf,
4920Sstevel@tonic-gate 					    pdomb->dom_binding->ypbind_svcaddr,
4930Sstevel@tonic-gate 					    YPPROG, YPVERS, __ypipbufsize,
4940Sstevel@tonic-gate 					    __ypipbufsize);
4950Sstevel@tonic-gate 	if (pdomb->dom_client == NULL) {
4960Sstevel@tonic-gate 		clnt_pcreateerror("yp_bind: clnt_tli_create");
497132Srobinson 		free(pdomb);
4980Sstevel@tonic-gate 		*err = YPERR_RPC;
499132Srobinson 		return (NULL);
5000Sstevel@tonic-gate 	}
5010Sstevel@tonic-gate #ifdef DEBUG
5020Sstevel@tonic-gate (void) printf("yp_bind: clnt_tli_create suceeded\n");
5030Sstevel@tonic-gate #endif
504132Srobinson 	(void) CLNT_CONTROL(pdomb->dom_client, CLSET_FD_CLOSE, NULL);
5050Sstevel@tonic-gate 
506132Srobinson 	pdomb->dom_domain = malloc(strlen(domain) + (unsigned)1);
5070Sstevel@tonic-gate 	if (pdomb->dom_domain == NULL) {
5080Sstevel@tonic-gate 		clnt_destroy(pdomb->dom_client);
509132Srobinson 		free(pdomb);
5100Sstevel@tonic-gate 		*err = YPERR_RESRC;
511132Srobinson 		return (NULL);
5120Sstevel@tonic-gate 	}
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 	(void) strcpy(pdomb->dom_domain, domain); /* Remember the domain name */
5150Sstevel@tonic-gate 	pdomb->ref_count = 0;
5160Sstevel@tonic-gate 	pdomb->need_free = 0;
5170Sstevel@tonic-gate 	set_rdev(pdomb);
518132Srobinson 	(void) mutex_init(&pdomb->server_name_lock, USYNC_THREAD, 0);
5190Sstevel@tonic-gate 	return (pdomb);
5200Sstevel@tonic-gate }
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate /*
5230Sstevel@tonic-gate  * Attempts to locate a yellow pages server that serves a passed domain.  If
5240Sstevel@tonic-gate  * one is found, an entry is created on the static list of domain-server pairs
5250Sstevel@tonic-gate  * pointed to by cell bound_domains, a udp path to the server is created and
5260Sstevel@tonic-gate  * the function returns 0.  Otherwise, the function returns a defined errorcode
5270Sstevel@tonic-gate  * YPERR_xxxx.
5280Sstevel@tonic-gate  *
5290Sstevel@tonic-gate  * MT-safe because it serializes on bound_domains_lock.
5300Sstevel@tonic-gate  *
5310Sstevel@tonic-gate  * If hardlookup is set then loop forever until success, else try 4
5320Sstevel@tonic-gate  * times (each try is relatively short) max.
5330Sstevel@tonic-gate  */
5340Sstevel@tonic-gate int
__yp_dobind_cflookup(char * domain,struct dom_binding ** binding,int hardlookup)5350Sstevel@tonic-gate __yp_dobind_cflookup(
5360Sstevel@tonic-gate 	char *domain,
5370Sstevel@tonic-gate 	struct dom_binding **binding,	/* if result==0, ptr to dom_binding */
5380Sstevel@tonic-gate 	int hardlookup)
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate {
5410Sstevel@tonic-gate 	struct dom_binding *pdomb;	/* Ptr to new domain binding */
5420Sstevel@tonic-gate 	struct ypbind_resp *ypbind_resp; /* Response from local ypbinder */
5430Sstevel@tonic-gate 	struct ypbind_domain ypbd;
5440Sstevel@tonic-gate 	int status, err = YPERR_DOMAIN;
5450Sstevel@tonic-gate 	int first_try = 1;
546132Srobinson 	CLIENT *tb = NULL;
5470Sstevel@tonic-gate 
548132Srobinson 	if ((domain == NULL) ||(strlen(domain) == 0))
5490Sstevel@tonic-gate 		return (YPERR_BADARGS);
5500Sstevel@tonic-gate 
551132Srobinson 	(void) mutex_lock(&bound_domains_lock);
5520Sstevel@tonic-gate 	/*
5530Sstevel@tonic-gate 	 * ===>
5540Sstevel@tonic-gate 	 * If someone managed to fork() while we were holding this lock,
5550Sstevel@tonic-gate 	 *   we'll probably end up hanging on the lock.  Tant pis.
5560Sstevel@tonic-gate 	 */
5570Sstevel@tonic-gate 	newborn();
5580Sstevel@tonic-gate 
5590Sstevel@tonic-gate 	if (check_binding(domain, binding)) {
5600Sstevel@tonic-gate 		/*
5610Sstevel@tonic-gate 		 *  If the cache is okay and if the underlying file
5620Sstevel@tonic-gate 		 *  descriptor is okay (application did not close it).
5630Sstevel@tonic-gate 		 *  then use the binding.
5640Sstevel@tonic-gate 		 */
5650Sstevel@tonic-gate 		if (!(*binding)->cache_bad && check_rdev(*binding)) {
5660Sstevel@tonic-gate 			(*binding)->ref_count += 1;
567132Srobinson 			(void) mutex_unlock(&bound_domains_lock);
5680Sstevel@tonic-gate 			return (0);		/* We are bound */
5690Sstevel@tonic-gate 		}
5700Sstevel@tonic-gate 
5710Sstevel@tonic-gate 		/*
5720Sstevel@tonic-gate 		 *  If we get here, one of two things happened:  the
5730Sstevel@tonic-gate 		 *  cache is bad, or the underlying file descriptor
5740Sstevel@tonic-gate 		 *  had changed.
5750Sstevel@tonic-gate 		 *
5760Sstevel@tonic-gate 		 *  If the cache is bad, then we call yp_unbind to remove
5770Sstevel@tonic-gate 		 *  the binding.
5780Sstevel@tonic-gate 		 *
5790Sstevel@tonic-gate 		 *  If the file descriptor has changed, then we call
5800Sstevel@tonic-gate 		 *  yp_unbind to remove the binding (we set cache_bad
5810Sstevel@tonic-gate 		 *  to force yp_unbind to do the remove), and then
5820Sstevel@tonic-gate 		 *  call check_binding to reload the binding from the
5830Sstevel@tonic-gate 		 *  cache again.
5840Sstevel@tonic-gate 		 */
5850Sstevel@tonic-gate 		if ((*binding)->cache_bad) {
5860Sstevel@tonic-gate 			__yp_unbind_nolock(domain);
5870Sstevel@tonic-gate 		} else {
5880Sstevel@tonic-gate 			(*binding)->cache_bad = 1;
589132Srobinson 			(void) mutex_unlock(&bound_domains_lock);
5900Sstevel@tonic-gate 			yp_unbind(domain);
591132Srobinson 			(void) mutex_lock(&bound_domains_lock);
5920Sstevel@tonic-gate 			if (check_binding(domain, binding)) {
5930Sstevel@tonic-gate 				(*binding)->ref_count += 1;
594132Srobinson 				(void) mutex_unlock(&bound_domains_lock);
5950Sstevel@tonic-gate 				return (0);
5960Sstevel@tonic-gate 			}
5970Sstevel@tonic-gate 		}
5980Sstevel@tonic-gate 	}
5990Sstevel@tonic-gate 
600*12264SGirish.Moodalbail@oracle.COM 	do {
6010Sstevel@tonic-gate 		if (first_try)
6020Sstevel@tonic-gate 			first_try = 0;
6030Sstevel@tonic-gate 		else {
6040Sstevel@tonic-gate 			/*
6050Sstevel@tonic-gate 			 * ===> sleep() -- Ugh.  And with the lock held, too.
6060Sstevel@tonic-gate 			 */
6070Sstevel@tonic-gate 			(void) sleep(_ypsleeptime);
6080Sstevel@tonic-gate 		}
6090Sstevel@tonic-gate 		tb = __clnt_create_loopback(YPBINDPROG, YPBINDVERS, &err);
6100Sstevel@tonic-gate 		if (tb == NULL) {
6110Sstevel@tonic-gate 			if (ypbind_running(err, rpc_createerr.cf_stat))
6120Sstevel@tonic-gate 				continue;
6130Sstevel@tonic-gate 			break;
6140Sstevel@tonic-gate 		}
6150Sstevel@tonic-gate 		ypbd.ypbind_domainname = domain;
6160Sstevel@tonic-gate 		ypbd.ypbind_vers = YPVERS;
6170Sstevel@tonic-gate 		/*
6180Sstevel@tonic-gate 		 * The interface to ypbindproc_domain_3 is MT-unsafe, but we're
6190Sstevel@tonic-gate 		 *   OK as long as we're the only ones who call it and we
6200Sstevel@tonic-gate 		 *   serialize all requests (for all domains).  Otherwise,
6210Sstevel@tonic-gate 		 *   change the interface (pass in the ypbind_resp struct).
6220Sstevel@tonic-gate 		 */
6230Sstevel@tonic-gate 		ypbind_resp = ypbindproc_domain_3(&ypbd, tb);
6240Sstevel@tonic-gate 		/*
6250Sstevel@tonic-gate 		 * Although we talk to ypbind on loopback,
6260Sstevel@tonic-gate 		 * it gives us a udp address for the ypserv.
6270Sstevel@tonic-gate 		 */
6280Sstevel@tonic-gate 		if (ypbind_resp == NULL) {
6290Sstevel@tonic-gate 			/* lost ypbind? */
6300Sstevel@tonic-gate 			clnt_perror(tb,
6310Sstevel@tonic-gate 				"ypbindproc_domain_3: can't contact ypbind");
6320Sstevel@tonic-gate 			clnt_destroy(tb);
633132Srobinson 			tb = NULL;
6340Sstevel@tonic-gate 			continue;
6350Sstevel@tonic-gate 		}
6360Sstevel@tonic-gate 		if (ypbind_resp->ypbind_status == YPBIND_SUCC_VAL) {
6370Sstevel@tonic-gate 			/*
6380Sstevel@tonic-gate 			 * Local ypbind has let us in on the ypserv's address,
6390Sstevel@tonic-gate 			 * go get in touch with it !
6400Sstevel@tonic-gate 			 */
6410Sstevel@tonic-gate 			pdomb = load_dom_binding(ypbind_resp, domain, &status);
6420Sstevel@tonic-gate 			if (pdomb == 0) {
6430Sstevel@tonic-gate 				err = status;
6440Sstevel@tonic-gate 				clnt_destroy(tb);
645132Srobinson 				tb = NULL;
6460Sstevel@tonic-gate 				continue;
6470Sstevel@tonic-gate 			}
6480Sstevel@tonic-gate 			clnt_destroy(tb);
6490Sstevel@tonic-gate 			pdomb->ref_count += 1;
650132Srobinson 			(void) mutex_unlock(&bound_domains_lock);
6510Sstevel@tonic-gate 			*binding = pdomb; /* Return ptr to the binding entry */
6520Sstevel@tonic-gate 			return (0);		/* This is the go path */
6530Sstevel@tonic-gate 		}
6540Sstevel@tonic-gate 		if (ypbind_resp->ypbind_resp_u.ypbind_error ==
6550Sstevel@tonic-gate 		    YPBIND_ERR_NOSERV)
6560Sstevel@tonic-gate 			err = YPERR_DOMAIN;
6570Sstevel@tonic-gate 		else
6580Sstevel@tonic-gate 			err = YPERR_YPBIND;
6590Sstevel@tonic-gate 		clnt_destroy(tb);
660132Srobinson 		tb = NULL;
661*12264SGirish.Moodalbail@oracle.COM 	} while (hardlookup);
662*12264SGirish.Moodalbail@oracle.COM 
663132Srobinson 	if (tb != NULL)
6640Sstevel@tonic-gate 		clnt_destroy(tb);
665132Srobinson 	(void) mutex_unlock(&bound_domains_lock);
6660Sstevel@tonic-gate 	if (err)
6670Sstevel@tonic-gate 		return (err);
6680Sstevel@tonic-gate 	return (YPERR_DOMAIN);
6690Sstevel@tonic-gate }
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate int
__yp_dobind(char * domain,struct dom_binding ** binding)6720Sstevel@tonic-gate __yp_dobind(
6730Sstevel@tonic-gate 	char *domain,
6740Sstevel@tonic-gate 	struct dom_binding **binding)	/* if result == 0, ptr to dom_binding */
6750Sstevel@tonic-gate {
6760Sstevel@tonic-gate 	/* traditional __yp_dobind loops forever so set hardlookup */
6770Sstevel@tonic-gate 	return (__yp_dobind_cflookup(domain, binding, 1));
6780Sstevel@tonic-gate }
6790Sstevel@tonic-gate 
6800Sstevel@tonic-gate void
__yp_rel_binding(struct dom_binding * binding)681132Srobinson __yp_rel_binding(struct dom_binding *binding)
6820Sstevel@tonic-gate {
683132Srobinson 	(void) mutex_lock(&bound_domains_lock);
6840Sstevel@tonic-gate 	binding->ref_count -= 1;
6850Sstevel@tonic-gate 	if (binding->need_free && binding->ref_count == 0)
6860Sstevel@tonic-gate 		free_dom_binding(binding);
687132Srobinson 	(void) mutex_unlock(&bound_domains_lock);
6880Sstevel@tonic-gate }
6890Sstevel@tonic-gate 
6900Sstevel@tonic-gate /*
6910Sstevel@tonic-gate  * Attempts to locate a yellow pages server that serves a passed domain.  If
6920Sstevel@tonic-gate  * one is found, an entry is created on the static list of domain-server pairs
6930Sstevel@tonic-gate  * pointed to by cell bound_domains, a udp path to the server is created and
6940Sstevel@tonic-gate  * the function returns 0.  Otherwise, the function returns a defined errorcode
6950Sstevel@tonic-gate  * YPERR_xxxx.
6960Sstevel@tonic-gate  *
6970Sstevel@tonic-gate  * MT-safe because it serializes on bound_domains_lock.
6980Sstevel@tonic-gate  *
6990Sstevel@tonic-gate  * XXX special version for handling C2 (passwd.adjunct) lookups when we need
7000Sstevel@tonic-gate  * a reserved port.
7010Sstevel@tonic-gate  * This returns an uncached binding which the caller has to free using
7020Sstevel@tonic-gate  * free_dom_binding().
7030Sstevel@tonic-gate  */
7040Sstevel@tonic-gate int
__yp_dobind_rsvdport_cflookup(char * domain,struct dom_binding ** binding,int hardlookup)7050Sstevel@tonic-gate __yp_dobind_rsvdport_cflookup(
7060Sstevel@tonic-gate 	char *domain,
7070Sstevel@tonic-gate 	struct dom_binding **binding,	/* if result==0, ptr to dom_binding */
7080Sstevel@tonic-gate 	int hardlookup)
7090Sstevel@tonic-gate {
7100Sstevel@tonic-gate 	struct dom_binding *pdomb;	/* Ptr to new domain binding */
7110Sstevel@tonic-gate 	struct ypbind_resp *ypbind_resp; /* Response from local ypbinder */
7120Sstevel@tonic-gate 	struct ypbind_domain ypbd;
7130Sstevel@tonic-gate 	int status,  err = YPERR_DOMAIN;
7140Sstevel@tonic-gate 	int first_try = 1;
715132Srobinson 	CLIENT *tb = NULL;
7160Sstevel@tonic-gate 
717132Srobinson 	if ((domain == NULL) ||(strlen(domain) == 0))
7180Sstevel@tonic-gate 		return (YPERR_BADARGS);
7190Sstevel@tonic-gate 
720132Srobinson 	(void) mutex_lock(&bound_domains_lock);
7210Sstevel@tonic-gate 	/*
7220Sstevel@tonic-gate 	 * ===>
7230Sstevel@tonic-gate 	 * If someone managed to fork() while we were holding this lock,
7240Sstevel@tonic-gate 	 *   we'll probably end up hanging on the lock.  Tant pis.
7250Sstevel@tonic-gate 	 */
7260Sstevel@tonic-gate 	newborn();
7270Sstevel@tonic-gate 
7280Sstevel@tonic-gate 	/*
7290Sstevel@tonic-gate 	 * Check for existing bindings and use the information in the binding
7300Sstevel@tonic-gate 	 * to create a transport endpoint with a reserved port.
7310Sstevel@tonic-gate 	 */
7320Sstevel@tonic-gate 	if (check_binding(domain, binding)) {
7330Sstevel@tonic-gate 		/*
7340Sstevel@tonic-gate 		 * If the cache is bad, yp_unbind() the entry again and then
7350Sstevel@tonic-gate 		 * talk to ypbind.
7360Sstevel@tonic-gate 		 */
7370Sstevel@tonic-gate 		if ((*binding)->cache_bad) {
7380Sstevel@tonic-gate 			__yp_unbind_nolock(domain);
7390Sstevel@tonic-gate 		} else {
7400Sstevel@tonic-gate 			pdomb = load_dom_binding_rsvdport(
7410Sstevel@tonic-gate 						(*binding)->dom_binding,
7420Sstevel@tonic-gate 							domain, &status);
7430Sstevel@tonic-gate 			if (pdomb == 0) {
744132Srobinson 				(void) mutex_unlock(&bound_domains_lock);
7450Sstevel@tonic-gate 				return (status);
7460Sstevel@tonic-gate 			}
7470Sstevel@tonic-gate 			pdomb->ref_count += 1;
748132Srobinson 			(void) mutex_unlock(&bound_domains_lock);
7490Sstevel@tonic-gate 			*binding = pdomb; /* Return ptr to the binding entry */
7500Sstevel@tonic-gate 			return (0);
7510Sstevel@tonic-gate 		}
7520Sstevel@tonic-gate 	}
7530Sstevel@tonic-gate 
754*12264SGirish.Moodalbail@oracle.COM 	do {
7550Sstevel@tonic-gate 		if (first_try)
7560Sstevel@tonic-gate 			first_try = 0;
7570Sstevel@tonic-gate 		else {
7580Sstevel@tonic-gate 			/*
7590Sstevel@tonic-gate 			 * ===> sleep() -- Ugh.  And with the lock held, too.
7600Sstevel@tonic-gate 			 */
761*12264SGirish.Moodalbail@oracle.COM 			(void) sleep(_ypsleeptime);
7620Sstevel@tonic-gate 		}
7630Sstevel@tonic-gate 		tb = __clnt_create_loopback(YPBINDPROG, YPBINDVERS, &err);
7640Sstevel@tonic-gate 		if (tb == NULL) {
7650Sstevel@tonic-gate 			if (ypbind_running(err, rpc_createerr.cf_stat))
7660Sstevel@tonic-gate 				continue;
7670Sstevel@tonic-gate 			break;
7680Sstevel@tonic-gate 		}
7690Sstevel@tonic-gate 		ypbd.ypbind_domainname = domain;
7700Sstevel@tonic-gate 		ypbd.ypbind_vers = YPVERS;
7710Sstevel@tonic-gate 		/*
7720Sstevel@tonic-gate 		 * The interface to ypbindproc_domain_3 is MT-unsafe, but we're
7730Sstevel@tonic-gate 		 *   OK as long as we're the only ones who call it and we
7740Sstevel@tonic-gate 		 *   serialize all requests (for all domains).  Otherwise,
7750Sstevel@tonic-gate 		 *   change the interface (pass in the ypbind_resp struct).
7760Sstevel@tonic-gate 		 */
7770Sstevel@tonic-gate 		ypbind_resp = ypbindproc_domain_3(&ypbd, tb);
7780Sstevel@tonic-gate 		/*
7790Sstevel@tonic-gate 		 * Although we talk to ypbind on loopback,
7800Sstevel@tonic-gate 		 * it gives us a udp address for the ypserv.
7810Sstevel@tonic-gate 		 */
7820Sstevel@tonic-gate 		if (ypbind_resp == NULL) {
7830Sstevel@tonic-gate 			/* lost ypbind? */
7840Sstevel@tonic-gate 			clnt_perror(tb,
7850Sstevel@tonic-gate 				"ypbindproc_domain_3: can't contact ypbind");
7860Sstevel@tonic-gate 			clnt_destroy(tb);
787132Srobinson 			tb = NULL;
7880Sstevel@tonic-gate 			continue;
7890Sstevel@tonic-gate 		}
7900Sstevel@tonic-gate 		if (ypbind_resp->ypbind_status == YPBIND_SUCC_VAL) {
7910Sstevel@tonic-gate 			/*
7920Sstevel@tonic-gate 			 * Local ypbind has let us in on the ypserv's address,
7930Sstevel@tonic-gate 			 * go get in touch with it !
7940Sstevel@tonic-gate 			 */
7950Sstevel@tonic-gate 			pdomb = load_dom_binding_rsvdport(
7960Sstevel@tonic-gate 				    ypbind_resp->ypbind_resp_u.ypbind_bindinfo,
7970Sstevel@tonic-gate 				    domain, &status);
7980Sstevel@tonic-gate 			if (pdomb == 0) {
7990Sstevel@tonic-gate 				err = status;
8000Sstevel@tonic-gate 				clnt_destroy(tb);
801132Srobinson 				tb = NULL;
8020Sstevel@tonic-gate 				continue;
8030Sstevel@tonic-gate 			}
8040Sstevel@tonic-gate 			clnt_destroy(tb);
8050Sstevel@tonic-gate 			pdomb->ref_count += 1;
806132Srobinson 			(void) mutex_unlock(&bound_domains_lock);
8070Sstevel@tonic-gate 			*binding = pdomb; /* Return ptr to the binding entry */
8080Sstevel@tonic-gate 			return (0);		/* This is the go path */
8090Sstevel@tonic-gate 		}
8100Sstevel@tonic-gate 		if (ypbind_resp->ypbind_resp_u.ypbind_error ==
8110Sstevel@tonic-gate 		    YPBIND_ERR_NOSERV)
8120Sstevel@tonic-gate 			err = YPERR_DOMAIN;
8130Sstevel@tonic-gate 		else
8140Sstevel@tonic-gate 			err = YPERR_YPBIND;
8150Sstevel@tonic-gate 		clnt_destroy(tb);
816132Srobinson 		tb = NULL;
817*12264SGirish.Moodalbail@oracle.COM 	} while (hardlookup);
818*12264SGirish.Moodalbail@oracle.COM 
819132Srobinson 	if (tb != NULL)
8200Sstevel@tonic-gate 		clnt_destroy(tb);
821132Srobinson 	(void) mutex_unlock(&bound_domains_lock);
8220Sstevel@tonic-gate 	if (err)
8230Sstevel@tonic-gate 		return (err);
8240Sstevel@tonic-gate 	return (YPERR_DOMAIN);
8250Sstevel@tonic-gate }
8260Sstevel@tonic-gate 
8270Sstevel@tonic-gate int
__yp_dobind_rsvdport(char * domain,struct dom_binding ** binding)8280Sstevel@tonic-gate __yp_dobind_rsvdport(
8290Sstevel@tonic-gate 	char *domain,
8300Sstevel@tonic-gate 	struct dom_binding **binding)	/* if result==0, ptr to dom_binding */
8310Sstevel@tonic-gate {
8320Sstevel@tonic-gate 	/* traditional __yp_dobind_rsvdport loops forever so set hardlookup */
8330Sstevel@tonic-gate 	return (__yp_dobind_rsvdport_cflookup(domain, binding, 1));
8340Sstevel@tonic-gate }
8350Sstevel@tonic-gate 
8360Sstevel@tonic-gate /*
8370Sstevel@tonic-gate  * This is a "wrapper" function for __yp_dobind for vanilla user-level
8380Sstevel@tonic-gate  * functions which neither know nor care about struct dom_bindings.
8390Sstevel@tonic-gate  */
8400Sstevel@tonic-gate int
yp_bind(char * domain)841132Srobinson yp_bind(char *domain)
8420Sstevel@tonic-gate {
8430Sstevel@tonic-gate 
8440Sstevel@tonic-gate 	struct dom_binding *binding;
845132Srobinson 	int    res;
8460Sstevel@tonic-gate 
847132Srobinson 	res = __yp_dobind(domain, &binding);
848132Srobinson 	if (res == 0)
8490Sstevel@tonic-gate 		__yp_rel_binding(binding);
850132Srobinson 	return (res);
8510Sstevel@tonic-gate }
8520Sstevel@tonic-gate 
8530Sstevel@tonic-gate static char *
__default_domain(void)854132Srobinson __default_domain(void)
8550Sstevel@tonic-gate {
8560Sstevel@tonic-gate 	char temp[256];
8570Sstevel@tonic-gate 
858132Srobinson 	(void) mutex_lock(&default_domain_lock);
8590Sstevel@tonic-gate 
8600Sstevel@tonic-gate 	if (default_domain) {
861132Srobinson 		(void) mutex_unlock(&default_domain_lock);
8620Sstevel@tonic-gate 		return (default_domain);
8630Sstevel@tonic-gate 	}
8640Sstevel@tonic-gate 	if (getdomainname(temp, sizeof (temp)) < 0) {
865132Srobinson 		(void) mutex_unlock(&default_domain_lock);
8660Sstevel@tonic-gate 		return (0);
8670Sstevel@tonic-gate 	}
8680Sstevel@tonic-gate 	if (strlen(temp) > 0) {
869132Srobinson 		default_domain = malloc((strlen(temp) + 1));
8700Sstevel@tonic-gate 		if (default_domain == 0) {
871132Srobinson 			(void) mutex_unlock(&default_domain_lock);
8720Sstevel@tonic-gate 			return (0);
8730Sstevel@tonic-gate 		}
8740Sstevel@tonic-gate 		(void) strcpy(default_domain, temp);
875132Srobinson 		(void) mutex_unlock(&default_domain_lock);
8760Sstevel@tonic-gate 		return (default_domain);
8770Sstevel@tonic-gate 	}
878132Srobinson 	(void) mutex_unlock(&default_domain_lock);
8790Sstevel@tonic-gate 	return (0);
8800Sstevel@tonic-gate }
8810Sstevel@tonic-gate 
8820Sstevel@tonic-gate /*
8830Sstevel@tonic-gate  * This is a wrapper for the system call getdomainname which returns a
8840Sstevel@tonic-gate  * ypclnt.h error code in the failure case.  It also checks to see that
8850Sstevel@tonic-gate  * the domain name is non-null, knowing that the null string is going to
8860Sstevel@tonic-gate  * get rejected elsewhere in the yp client package.
8870Sstevel@tonic-gate  */
8880Sstevel@tonic-gate int
yp_get_default_domain(char ** domain)889132Srobinson yp_get_default_domain(char **domain)
8900Sstevel@tonic-gate {
891132Srobinson 	if ((*domain = __default_domain()) != 0)
8920Sstevel@tonic-gate 		return (0);
8930Sstevel@tonic-gate 	return (YPERR_YPERR);
8940Sstevel@tonic-gate }
8950Sstevel@tonic-gate 
8960Sstevel@tonic-gate /*
8970Sstevel@tonic-gate  * ===> Nobody uses this, do they?  Can we nuke it?
8980Sstevel@tonic-gate  */
8990Sstevel@tonic-gate int
usingypmap(char ** ddn,char * map)900132Srobinson usingypmap(char **ddn, char *map)
9010Sstevel@tonic-gate {
9020Sstevel@tonic-gate 	char in, *outval = NULL;
9030Sstevel@tonic-gate 	int outvallen, stat;
9040Sstevel@tonic-gate 	char *domain;
9050Sstevel@tonic-gate 
906132Srobinson 	if ((domain = __default_domain()) == 0)
9070Sstevel@tonic-gate 		return (FALSE);
9080Sstevel@tonic-gate 	*ddn = domain;
9090Sstevel@tonic-gate 	/* does the map exist ? */
9100Sstevel@tonic-gate 	in = (char)0xff;
9110Sstevel@tonic-gate 	stat = yp_match(domain, map, &in, 1, &outval, &outvallen);
9120Sstevel@tonic-gate 	if (outval != NULL)
9130Sstevel@tonic-gate 		free(outval);
9140Sstevel@tonic-gate 	switch (stat) {
9150Sstevel@tonic-gate 
9160Sstevel@tonic-gate 	case 0:  /* it actually succeeded! */
9170Sstevel@tonic-gate 	case YPERR_KEY:  /* no such key in map */
9180Sstevel@tonic-gate 	case YPERR_NOMORE:
9190Sstevel@tonic-gate 	case YPERR_BUSY:
9200Sstevel@tonic-gate 		return (TRUE);
9210Sstevel@tonic-gate 	}
9220Sstevel@tonic-gate 	return (FALSE);
9230Sstevel@tonic-gate }
9240Sstevel@tonic-gate 
9250Sstevel@tonic-gate /*
9260Sstevel@tonic-gate  * Creates a quick connection on a connection oriented loopback
9270Sstevel@tonic-gate  * transport. Fails quickly without timeout. Only naming service
9280Sstevel@tonic-gate  * it goes to is straddr.so.
9290Sstevel@tonic-gate  */
9300Sstevel@tonic-gate CLIENT *
__clnt_create_loopback(rpcprog_t prog,rpcvers_t vers,int * err)931132Srobinson __clnt_create_loopback(rpcprog_t prog, rpcvers_t vers, int *err)
9320Sstevel@tonic-gate {
9330Sstevel@tonic-gate 	struct netconfig *nconf;
9340Sstevel@tonic-gate 	CLIENT *clnt = NULL;
9350Sstevel@tonic-gate 	void *nc_handle;	/* Net config handle */
9360Sstevel@tonic-gate 
9370Sstevel@tonic-gate 	*err = 0;
9380Sstevel@tonic-gate 	nc_handle = setnetconfig();
939132Srobinson 	if (nc_handle == NULL) {
9400Sstevel@tonic-gate 		/* fails to open netconfig file */
9410Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_FAILED;
9420Sstevel@tonic-gate 		*err = YPERR_RPC;
943132Srobinson 		return (NULL);
9440Sstevel@tonic-gate 	}
9450Sstevel@tonic-gate 	while (nconf = getnetconfig(nc_handle))
9460Sstevel@tonic-gate 		/* Try only one connection oriented loopback transport */
9470Sstevel@tonic-gate 		if ((strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) &&
9480Sstevel@tonic-gate 			((nconf->nc_semantics == NC_TPI_COTS) ||
9490Sstevel@tonic-gate 			(nconf->nc_semantics == NC_TPI_COTS_ORD))) {
9500Sstevel@tonic-gate 			clnt = getclnt(prog, vers, nconf, err);
9510Sstevel@tonic-gate 			break;
9520Sstevel@tonic-gate 		}
953132Srobinson 	(void) endnetconfig(nc_handle);
9540Sstevel@tonic-gate 
955132Srobinson 	if (clnt == NULL) {	/* no loopback transport available */
9560Sstevel@tonic-gate 		if (rpc_createerr.cf_stat == 0)
9570Sstevel@tonic-gate 			rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
9580Sstevel@tonic-gate 		if (*err == 0) *err = YPERR_RPC;
9590Sstevel@tonic-gate 	}
9600Sstevel@tonic-gate 	return (clnt);
9610Sstevel@tonic-gate }
9620Sstevel@tonic-gate 
9630Sstevel@tonic-gate static CLIENT *
getclnt(rpcprog_t prog,rpcvers_t vers,struct netconfig * nconf,int * err)964132Srobinson getclnt(rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf, int *err)
9650Sstevel@tonic-gate {
9660Sstevel@tonic-gate 	int fd;
9670Sstevel@tonic-gate 	struct netbuf *svcaddr;			/* servers address */
9680Sstevel@tonic-gate 	CLIENT *cl;
9690Sstevel@tonic-gate 	struct nd_addrlist *nas;
9700Sstevel@tonic-gate 	struct nd_hostserv rpcbind_hs;
9710Sstevel@tonic-gate 	struct t_call sndcall;
9720Sstevel@tonic-gate 	char uaddress[1024]; /* XXX maxlen ?? */
9730Sstevel@tonic-gate 	RPCB parms;
9740Sstevel@tonic-gate 	enum clnt_stat clnt_st;
9750Sstevel@tonic-gate 	char *ua;
9760Sstevel@tonic-gate 	struct timeval tv = { 30, 0 };
9770Sstevel@tonic-gate 
978132Srobinson 	if (nconf == NULL) {
9790Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_TLIERROR;
9800Sstevel@tonic-gate 		*err = YPERR_RPC;
981132Srobinson 		return (NULL);
9820Sstevel@tonic-gate 	}
9830Sstevel@tonic-gate 
9840Sstevel@tonic-gate 	/*
9850Sstevel@tonic-gate 	 *  The ypbind process might cache its transport address.
9860Sstevel@tonic-gate 	 *  If we can get at it, then we will use it and avoid
9870Sstevel@tonic-gate 	 *  wasting time talking to rpcbind.
9880Sstevel@tonic-gate 	 */
9890Sstevel@tonic-gate 
9900Sstevel@tonic-gate 	if (get_cached_transport(nconf, vers, uaddress, sizeof (uaddress))) {
9910Sstevel@tonic-gate 		goto create_client;
9920Sstevel@tonic-gate 	}
9930Sstevel@tonic-gate 
9940Sstevel@tonic-gate 	/*
9950Sstevel@tonic-gate 	 * Check to see if local rpcbind is up or not. If it
9960Sstevel@tonic-gate 	 * isn't, it is best that the application should realize
9970Sstevel@tonic-gate 	 * yp is not up and take a remedial action. This is to
9980Sstevel@tonic-gate 	 * avoid the minute long timeout incurred by rpcbind_getaddr.
9990Sstevel@tonic-gate 	 * Looks like the only way to accomplish this it is to unfold
10000Sstevel@tonic-gate 	 * rpcb_getaddr and make a few changes. Alas !
10010Sstevel@tonic-gate 	 */
10020Sstevel@tonic-gate 	rpcbind_hs.h_host = HOST_SELF_CONNECT;
10030Sstevel@tonic-gate 	rpcbind_hs.h_serv = "rpcbind";
10040Sstevel@tonic-gate 	if (netdir_getbyname(nconf, &rpcbind_hs, &nas) != ND_OK) {
10050Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
10060Sstevel@tonic-gate 		*err = YPERR_RPC;
1007132Srobinson 		return (NULL);
10080Sstevel@tonic-gate 	}
10090Sstevel@tonic-gate 	if ((fd = t_open(nconf->nc_device, O_RDWR, NULL)) == -1) {
10100Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_TLIERROR;
10110Sstevel@tonic-gate 		*err = YPERR_RPC;
1012132Srobinson 		return (NULL);
10130Sstevel@tonic-gate 	}
1014132Srobinson 	if (t_bind(fd, NULL, NULL) == -1) {
10150Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_TLIERROR;
10160Sstevel@tonic-gate 		*err = YPERR_RPC;
10170Sstevel@tonic-gate 		(void) t_close(fd);
1018132Srobinson 		return (NULL);
10190Sstevel@tonic-gate 	}
10200Sstevel@tonic-gate 	sndcall.addr = *(nas->n_addrs);
10210Sstevel@tonic-gate 	sndcall.opt.len = 0;
10220Sstevel@tonic-gate 	sndcall.udata.len = 0;
10230Sstevel@tonic-gate 	if (t_connect(fd, &sndcall, NULL) == -1) {
10240Sstevel@tonic-gate 		netdir_free((char *)nas, ND_ADDRLIST);
10250Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_TLIERROR;
10260Sstevel@tonic-gate 		(void) t_close(fd);
10270Sstevel@tonic-gate 		*err = YPERR_PMAP;
1028132Srobinson 		return (NULL);
10290Sstevel@tonic-gate 	}
10300Sstevel@tonic-gate 
10310Sstevel@tonic-gate 	/*
10320Sstevel@tonic-gate 	 * Get the address of the server
10330Sstevel@tonic-gate 	 */
10340Sstevel@tonic-gate 	cl = clnt_tli_create(fd, nconf, nas->n_addrs,
10350Sstevel@tonic-gate 		RPCBPROG, RPCBVERS, __ypipbufsize, __ypipbufsize);
10360Sstevel@tonic-gate 	netdir_free((char *)nas, ND_ADDRLIST);
1037132Srobinson 	if (cl == NULL) {
10380Sstevel@tonic-gate 		(void) t_close(fd);
10390Sstevel@tonic-gate 		*err = YPERR_PMAP;
1040132Srobinson 		return (NULL);
10410Sstevel@tonic-gate 	}
10420Sstevel@tonic-gate 	parms.r_prog = prog;
10430Sstevel@tonic-gate 	parms.r_vers = vers;
10440Sstevel@tonic-gate 	parms.r_netid = nconf->nc_netid;
10450Sstevel@tonic-gate 	parms.r_addr = nullstring;
10460Sstevel@tonic-gate 	parms.r_owner = nullstring;
10470Sstevel@tonic-gate 	ua = uaddress;
10480Sstevel@tonic-gate 	clnt_st = CLNT_CALL(cl, RPCBPROC_GETADDR, xdr_rpcb, (char *)&parms,
10490Sstevel@tonic-gate 		xdr_wrapstring, (char *)&ua, tv);
10500Sstevel@tonic-gate 	(void) t_close(fd);
10510Sstevel@tonic-gate 	clnt_destroy(cl);
10520Sstevel@tonic-gate 	if (clnt_st != RPC_SUCCESS) {
10530Sstevel@tonic-gate 		*err = YPERR_YPBIND;
1054132Srobinson 		return (NULL);
10550Sstevel@tonic-gate 	}
10560Sstevel@tonic-gate 	if (strlen(uaddress) == 0) {
10570Sstevel@tonic-gate 		*err = YPERR_YPBIND;
10580Sstevel@tonic-gate 		rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
1059132Srobinson 		return (NULL);
10600Sstevel@tonic-gate 	}
10610Sstevel@tonic-gate 
10620Sstevel@tonic-gate create_client:
10630Sstevel@tonic-gate 	svcaddr = uaddr2taddr(nconf, uaddress);
10640Sstevel@tonic-gate 	cl = clnt_tli_create(RPC_ANYFD, nconf, svcaddr, prog, vers,
10650Sstevel@tonic-gate 					__ypipbufsize, __ypipbufsize);
10660Sstevel@tonic-gate 	netdir_free((char *)svcaddr, ND_ADDR);
1067132Srobinson 	if (cl == NULL) {
10680Sstevel@tonic-gate 		*err = YPERR_YPBIND;
1069132Srobinson 		return (NULL);
10700Sstevel@tonic-gate 	}
10710Sstevel@tonic-gate 	/*
10720Sstevel@tonic-gate 	 * The fd should be closed while destroying the handle.
10730Sstevel@tonic-gate 	 */
10740Sstevel@tonic-gate 	return (cl);
10750Sstevel@tonic-gate }
10760Sstevel@tonic-gate 
1077132Srobinson static int
get_cached_transport(struct netconfig * nconf,int vers,char * uaddress,int ulen)1078132Srobinson get_cached_transport(struct netconfig *nconf, int vers, char *uaddress,
1079132Srobinson 								int ulen)
10800Sstevel@tonic-gate {
10810Sstevel@tonic-gate 	ssize_t st;
10820Sstevel@tonic-gate 	int fd;
10830Sstevel@tonic-gate 
1084132Srobinson 	(void) snprintf(uaddress, ulen,
1085132Srobinson 		"%s/xprt.%s.%d", BINDING, nconf->nc_netid, vers);
10860Sstevel@tonic-gate 	fd = open(uaddress, O_RDONLY);
10870Sstevel@tonic-gate 	if (fd == -1)
10880Sstevel@tonic-gate 		return (0);
10890Sstevel@tonic-gate 
10900Sstevel@tonic-gate 	/* if first byte is not locked, then ypbind must not be running */
10910Sstevel@tonic-gate 	st = lockf(fd, F_TEST, 1);
10920Sstevel@tonic-gate 	if (st != -1 || (errno != EAGAIN && errno != EACCES)) {
10930Sstevel@tonic-gate 		(void) close(fd);
10940Sstevel@tonic-gate 		return (0);
10950Sstevel@tonic-gate 	}
10960Sstevel@tonic-gate 
10970Sstevel@tonic-gate 	st = read(fd, uaddress, ulen);
10980Sstevel@tonic-gate 	if (st == -1) {
10990Sstevel@tonic-gate 		(void) close(fd);
11000Sstevel@tonic-gate 		return (0);
11010Sstevel@tonic-gate 	}
11020Sstevel@tonic-gate 
11030Sstevel@tonic-gate 	(void) close(fd);
11040Sstevel@tonic-gate 	return (1);
11050Sstevel@tonic-gate }
11060Sstevel@tonic-gate 
1107132Srobinson static ypbind_resp *
get_cached_domain(char * domain)1108132Srobinson get_cached_domain(char *domain)
11090Sstevel@tonic-gate {
11101914Scasper 	FILE *fp;
11110Sstevel@tonic-gate 	int st;
11120Sstevel@tonic-gate 	char filename[300];
11130Sstevel@tonic-gate 	static ypbind_resp res;
11140Sstevel@tonic-gate 	XDR xdrs;
11150Sstevel@tonic-gate 
1116132Srobinson 	(void) snprintf(filename, sizeof (filename),
1117132Srobinson 					"%s/%s/cache_binding", BINDING, domain);
11181914Scasper 	fp = fopen(filename, "rF");
11190Sstevel@tonic-gate 	if (fp == 0)
11200Sstevel@tonic-gate 		return (0);
11210Sstevel@tonic-gate 
11220Sstevel@tonic-gate 	/* if first byte is not locked, then ypbind must not be running */
11231914Scasper 	st = lockf(fileno(fp), F_TEST, 1);
11240Sstevel@tonic-gate 	if (st != -1 || (errno != EAGAIN && errno != EACCES)) {
11251914Scasper 		(void) fclose(fp);
11260Sstevel@tonic-gate 		return (0);
11270Sstevel@tonic-gate 	}
11280Sstevel@tonic-gate 
11291914Scasper 	xdrstdio_create(&xdrs, fp, XDR_DECODE);
11300Sstevel@tonic-gate 
11310Sstevel@tonic-gate 	(void) memset((char *)&res, 0, sizeof (res));
11320Sstevel@tonic-gate 	st = xdr_ypbind_resp(&xdrs, &res);
11330Sstevel@tonic-gate 
11340Sstevel@tonic-gate 	xdr_destroy(&xdrs);
11351914Scasper 	(void) fclose(fp);
11360Sstevel@tonic-gate 
11370Sstevel@tonic-gate 	if (st)
11380Sstevel@tonic-gate 		return (&res);
11390Sstevel@tonic-gate 
11400Sstevel@tonic-gate 	return (0);
11410Sstevel@tonic-gate }
11420Sstevel@tonic-gate 
1143132Srobinson static int
ypbind_running(int err,int status)1144132Srobinson ypbind_running(int err, int status)
11450Sstevel@tonic-gate {
11460Sstevel@tonic-gate 	char filename[300];
11470Sstevel@tonic-gate 	int st;
11480Sstevel@tonic-gate 	int fd;
11490Sstevel@tonic-gate 
1150132Srobinson 	(void) snprintf(filename, sizeof (filename), "%s/ypbind.pid", BINDING);
11510Sstevel@tonic-gate 	fd = open(filename, O_RDONLY);
11520Sstevel@tonic-gate 	if (fd == -1) {
11530Sstevel@tonic-gate 		if ((err == YPERR_YPBIND) && (status != RPC_PROGNOTREGISTERED))
11540Sstevel@tonic-gate 			return (1);
11550Sstevel@tonic-gate 		return (0);
11560Sstevel@tonic-gate 	}
11570Sstevel@tonic-gate 
11580Sstevel@tonic-gate 	/* if first byte is not locked, then ypbind must not be running */
11590Sstevel@tonic-gate 	st = lockf(fd, F_TEST, 1);
11600Sstevel@tonic-gate 	if (st != -1 || (errno != EAGAIN && errno != EACCES)) {
11610Sstevel@tonic-gate 		(void) close(fd);
11620Sstevel@tonic-gate 		return (0);
11630Sstevel@tonic-gate 	}
11640Sstevel@tonic-gate 
11650Sstevel@tonic-gate 	(void) close(fd);
11660Sstevel@tonic-gate 	return (1);
11670Sstevel@tonic-gate }
11680Sstevel@tonic-gate 
1169132Srobinson static void
set_rdev(struct dom_binding * pdomb)1170132Srobinson set_rdev(struct dom_binding *pdomb)
11710Sstevel@tonic-gate {
11720Sstevel@tonic-gate 	int fd;
11730Sstevel@tonic-gate 	struct stat stbuf;
11740Sstevel@tonic-gate 
11750Sstevel@tonic-gate 	if (clnt_control(pdomb->dom_client, CLGET_FD, (char *)&fd) != TRUE ||
11761219Sraf 	    fstat(fd, &stbuf) == -1) {
11770Sstevel@tonic-gate 		syslog(LOG_DEBUG, "ypbind client:  can't get rdev");
11780Sstevel@tonic-gate 		pdomb->fd = -1;
11790Sstevel@tonic-gate 		return;
11800Sstevel@tonic-gate 	}
11810Sstevel@tonic-gate 	pdomb->fd = fd;
11820Sstevel@tonic-gate 	pdomb->rdev = stbuf.st_rdev;
11830Sstevel@tonic-gate }
11840Sstevel@tonic-gate 
1185132Srobinson static int
check_rdev(struct dom_binding * pdomb)1186132Srobinson check_rdev(struct dom_binding *pdomb)
11870Sstevel@tonic-gate {
11880Sstevel@tonic-gate 	struct stat stbuf;
11890Sstevel@tonic-gate 
11900Sstevel@tonic-gate 	if (pdomb->fd == -1)
11910Sstevel@tonic-gate 		return (1);    /* can't check it, assume it is okay */
11920Sstevel@tonic-gate 
11931219Sraf 	if (fstat(pdomb->fd, &stbuf) == -1) {
11940Sstevel@tonic-gate 		syslog(LOG_DEBUG, "yp_bind client:  can't stat %d", pdomb->fd);
11950Sstevel@tonic-gate 		/* could be because file descriptor was closed */
11960Sstevel@tonic-gate 		/* it's not our file descriptor, so don't try to close it */
1197132Srobinson 		clnt_control(pdomb->dom_client, CLSET_FD_NCLOSE, NULL);
11980Sstevel@tonic-gate 		return (0);
11990Sstevel@tonic-gate 	}
12000Sstevel@tonic-gate 	if (pdomb->rdev != stbuf.st_rdev) {
12010Sstevel@tonic-gate 		syslog(LOG_DEBUG,
12020Sstevel@tonic-gate 		    "yp_bind client:  fd %d changed, old=0x%x, new=0x%x",
12030Sstevel@tonic-gate 		    pdomb->fd, pdomb->rdev, stbuf.st_rdev);
12040Sstevel@tonic-gate 		/* it's not our file descriptor, so don't try to close it */
1205132Srobinson 		clnt_control(pdomb->dom_client, CLSET_FD_NCLOSE, NULL);
12060Sstevel@tonic-gate 		return (0);
12070Sstevel@tonic-gate 	}
12080Sstevel@tonic-gate 	return (1);    /* fd is okay */
12090Sstevel@tonic-gate }
1210