xref: /illumos-gate/usr/src/cmd/ypcmd/yp_b_subr.c (revision 2a8bcb4e)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved   */
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate /*
31*7c478bd9Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley
32*7c478bd9Sstevel@tonic-gate  * under license from the Regents of the University of
33*7c478bd9Sstevel@tonic-gate  * California.
34*7c478bd9Sstevel@tonic-gate  */
35*7c478bd9Sstevel@tonic-gate 
36*7c478bd9Sstevel@tonic-gate #include "ypsym.h"
37*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
38*7c478bd9Sstevel@tonic-gate #include "yp_b.h"
39*7c478bd9Sstevel@tonic-gate #include <string.h>
40*7c478bd9Sstevel@tonic-gate #include <limits.h>
41*7c478bd9Sstevel@tonic-gate #include <netconfig.h>
42*7c478bd9Sstevel@tonic-gate #include <netdir.h>
43*7c478bd9Sstevel@tonic-gate #include <rpc/clnt.h>
44*7c478bd9Sstevel@tonic-gate #include <syslog.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
46*7c478bd9Sstevel@tonic-gate #include <unistd.h>
47*7c478bd9Sstevel@tonic-gate #include <netinet/in.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/statvfs.h>
49*7c478bd9Sstevel@tonic-gate #include <rpcsvc/nis.h>
50*7c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate #ifndef NULL
53*7c478bd9Sstevel@tonic-gate #define	NULL	0
54*7c478bd9Sstevel@tonic-gate #endif
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate #define	YPSERVERS	"ypservers"
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate void ypbind_init_default();
59*7c478bd9Sstevel@tonic-gate static int ypbind_pipe_setdom();
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate static bool firsttime = TRUE;
62*7c478bd9Sstevel@tonic-gate static struct domain *known_domains;
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate extern struct netconfig *__rpc_getconf();
65*7c478bd9Sstevel@tonic-gate extern void *__rpc_setconf(), *__rpc_endconf();
66*7c478bd9Sstevel@tonic-gate extern CLIENT *__clnt_tp_create_bootstrap();
67*7c478bd9Sstevel@tonic-gate extern char *inet_ntoa();
68*7c478bd9Sstevel@tonic-gate extern int __rpc_get_local_uid();
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate extern listofnames *names();
71*7c478bd9Sstevel@tonic-gate extern void free_listofnames();
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate #define	PINGTIME	10	/* Timeout for the ypservers list */
74*7c478bd9Sstevel@tonic-gate #define	PINGTOTTIM 5	/* Total seconds for ping timeout */
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate static void broadcast_setup();
77*7c478bd9Sstevel@tonic-gate static void sigcld_handler();
78*7c478bd9Sstevel@tonic-gate static struct ypbind_binding *dup_ypbind_binding();
79*7c478bd9Sstevel@tonic-gate static struct netbuf *dup_netbuf();
80*7c478bd9Sstevel@tonic-gate static void free_ypbind_binding();
81*7c478bd9Sstevel@tonic-gate static void enable_exit();
82*7c478bd9Sstevel@tonic-gate static void ypbind_ping();
83*7c478bd9Sstevel@tonic-gate static struct domain *ypbind_point_to_domain();
84*7c478bd9Sstevel@tonic-gate static bool ypbind_broadcast_ack();
85*7c478bd9Sstevel@tonic-gate static int pong_servers();
86*7c478bd9Sstevel@tonic-gate void cache_binding();
87*7c478bd9Sstevel@tonic-gate void uncache_binding();
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate extern int setok;
90*7c478bd9Sstevel@tonic-gate extern int broadcast;
91*7c478bd9Sstevel@tonic-gate extern int cache_okay;
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate /*
94*7c478bd9Sstevel@tonic-gate  * Need to differentiate between RPC_UNKNOWNHOST returned by the RPC
95*7c478bd9Sstevel@tonic-gate  * library, and the same error caused by a local lookup failure in
96*7c478bd9Sstevel@tonic-gate  * /etc/hosts and/or /etc/inet/ipnodes.
97*7c478bd9Sstevel@tonic-gate  */
98*7c478bd9Sstevel@tonic-gate int hostNotKnownLocally;
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
101*7c478bd9Sstevel@tonic-gate void	*
ypbindproc_null_3(argp,clnt)102*7c478bd9Sstevel@tonic-gate ypbindproc_null_3(argp, clnt)
103*7c478bd9Sstevel@tonic-gate void	*argp;
104*7c478bd9Sstevel@tonic-gate CLIENT *clnt;
105*7c478bd9Sstevel@tonic-gate {
106*7c478bd9Sstevel@tonic-gate 	static char	res;
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate 	return ((void *) & res);
109*7c478bd9Sstevel@tonic-gate }
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate static void
enable_exit()112*7c478bd9Sstevel@tonic-gate enable_exit()
113*7c478bd9Sstevel@tonic-gate {
114*7c478bd9Sstevel@tonic-gate 	static bool	done = FALSE;
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate 	if (!done) {
117*7c478bd9Sstevel@tonic-gate 		done = TRUE;
118*7c478bd9Sstevel@tonic-gate 		sigset(SIGCHLD, (void (*)())sigcld_handler);
119*7c478bd9Sstevel@tonic-gate 	}
120*7c478bd9Sstevel@tonic-gate }
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate int sigcld_event = 0;
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate static void
sigcld_handler()125*7c478bd9Sstevel@tonic-gate sigcld_handler()
126*7c478bd9Sstevel@tonic-gate {
127*7c478bd9Sstevel@tonic-gate 	sigcld_event++;
128*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
129*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "ypbind sighandler: got SIGCLD signal (event=%d)\n",
130*7c478bd9Sstevel@tonic-gate 		sigcld_event);
131*7c478bd9Sstevel@tonic-gate #endif
132*7c478bd9Sstevel@tonic-gate }
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate 
135*7c478bd9Sstevel@tonic-gate /*
136*7c478bd9Sstevel@tonic-gate  * This is a Unix SIGCHILD handler that notices when a broadcaster child
137*7c478bd9Sstevel@tonic-gate  * process has exited, and retrieves the exit status.  The broadcaster pid
138*7c478bd9Sstevel@tonic-gate  * is set to 0.  If the broadcaster succeeded, dom_report_success will be
139*7c478bd9Sstevel@tonic-gate  * be set to -1.
140*7c478bd9Sstevel@tonic-gate  */
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate void
broadcast_proc_exit()143*7c478bd9Sstevel@tonic-gate broadcast_proc_exit()
144*7c478bd9Sstevel@tonic-gate {
145*7c478bd9Sstevel@tonic-gate 	int pid, ret;
146*7c478bd9Sstevel@tonic-gate 	siginfo_t infop;
147*7c478bd9Sstevel@tonic-gate 	register struct domain *pdom;
148*7c478bd9Sstevel@tonic-gate 	bool	succeeded = FALSE;
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate 	sigcld_event = 0;
151*7c478bd9Sstevel@tonic-gate 					/* ==== Why WEXITED? */
152*7c478bd9Sstevel@tonic-gate 	while ((ret = waitid(P_ALL, 0, &infop, WNOHANG | WEXITED)) != -1) {
153*7c478bd9Sstevel@tonic-gate 		switch (infop.si_code) {
154*7c478bd9Sstevel@tonic-gate 		case CLD_EXITED:
155*7c478bd9Sstevel@tonic-gate 			succeeded = infop.si_status == 0;
156*7c478bd9Sstevel@tonic-gate 			break;
157*7c478bd9Sstevel@tonic-gate 		case CLD_KILLED:
158*7c478bd9Sstevel@tonic-gate 		case CLD_DUMPED:
159*7c478bd9Sstevel@tonic-gate 			succeeded = FALSE;
160*7c478bd9Sstevel@tonic-gate 			break;
161*7c478bd9Sstevel@tonic-gate 		case CLD_TRAPPED:
162*7c478bd9Sstevel@tonic-gate 		case CLD_STOPPED:
163*7c478bd9Sstevel@tonic-gate 		case CLD_CONTINUED:
164*7c478bd9Sstevel@tonic-gate 			enable_exit();
165*7c478bd9Sstevel@tonic-gate 			return;
166*7c478bd9Sstevel@tonic-gate 		}
167*7c478bd9Sstevel@tonic-gate 		pid = infop.si_pid;
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
170*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
171*7c478bd9Sstevel@tonic-gate 			"ypbind event_handler: got wait from %d status = %d\n",
172*7c478bd9Sstevel@tonic-gate 			pid, infop.si_status);
173*7c478bd9Sstevel@tonic-gate #endif
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 	/* to aid the progeny print the infamous "not responding" message */
176*7c478bd9Sstevel@tonic-gate 		firsttime = FALSE;
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate 		for (pdom = known_domains; pdom != (struct domain *)NULL;
179*7c478bd9Sstevel@tonic-gate 				pdom = pdom->dom_pnext) {
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate 			if (pdom->dom_broadcaster_pid == pid) {
182*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
183*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
184*7c478bd9Sstevel@tonic-gate 			"ypbind event_handler: got match %s\n", pdom->dom_name);
185*7c478bd9Sstevel@tonic-gate #endif
186*7c478bd9Sstevel@tonic-gate 				if (succeeded) {
187*7c478bd9Sstevel@tonic-gate 					broadcast_setup(pdom);
188*7c478bd9Sstevel@tonic-gate 				}
189*7c478bd9Sstevel@tonic-gate 				if (pdom->broadcaster_pipe != 0) {
190*7c478bd9Sstevel@tonic-gate 					xdr_destroy(&(pdom->broadcaster_xdr));
191*7c478bd9Sstevel@tonic-gate 					fclose(pdom->broadcaster_pipe);
192*7c478bd9Sstevel@tonic-gate 					pdom->broadcaster_pipe = 0;
193*7c478bd9Sstevel@tonic-gate 					pdom->broadcaster_fd = -1;
194*7c478bd9Sstevel@tonic-gate 				}
195*7c478bd9Sstevel@tonic-gate 				pdom->dom_broadcaster_pid = 0;
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate 				break;
198*7c478bd9Sstevel@tonic-gate 			}
199*7c478bd9Sstevel@tonic-gate 		}
200*7c478bd9Sstevel@tonic-gate 	}	/* while loop */
201*7c478bd9Sstevel@tonic-gate 	enable_exit();
202*7c478bd9Sstevel@tonic-gate }
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate static void
broadcast_setup(pdom)205*7c478bd9Sstevel@tonic-gate broadcast_setup(pdom)
206*7c478bd9Sstevel@tonic-gate struct domain *pdom;
207*7c478bd9Sstevel@tonic-gate {
208*7c478bd9Sstevel@tonic-gate 	ypbind_setdom req;
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 	memset(&req, 0, sizeof (req));
211*7c478bd9Sstevel@tonic-gate 	if (pdom->broadcaster_pipe) {
212*7c478bd9Sstevel@tonic-gate 		pdom->dom_report_success = -1;
213*7c478bd9Sstevel@tonic-gate 		if (xdr_ypbind_setdom(&(pdom->broadcaster_xdr), &req)) {
214*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
215*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "parent: broadcast_setup: got xdr ok \n");
216*7c478bd9Sstevel@tonic-gate #endif
217*7c478bd9Sstevel@tonic-gate 			ypbindproc_setdom_3(&req, (struct svc_req *)NULL,
218*7c478bd9Sstevel@tonic-gate 			    (SVCXPRT *)NULL);
219*7c478bd9Sstevel@tonic-gate 			xdr_free(xdr_ypbind_setdom, (char *)&req);
220*7c478bd9Sstevel@tonic-gate 			gettimeofday(&(pdom->lastping), NULL);
221*7c478bd9Sstevel@tonic-gate 		}
222*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
223*7c478bd9Sstevel@tonic-gate 		    else {
224*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "ypbind parent: xdr_ypbind_setdom failed\n");
225*7c478bd9Sstevel@tonic-gate 		}
226*7c478bd9Sstevel@tonic-gate #endif
227*7c478bd9Sstevel@tonic-gate 	}
228*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
229*7c478bd9Sstevel@tonic-gate 	    else {
230*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "ypbind: internal error -- no broadcaster pipe\n");
231*7c478bd9Sstevel@tonic-gate 	}
232*7c478bd9Sstevel@tonic-gate #endif
233*7c478bd9Sstevel@tonic-gate }
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate #define	YPBIND_PINGHOLD_DOWN 5
236*7c478bd9Sstevel@tonic-gate /* Same as the ypbind_get_binding() routine in SunOS */
237*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
238*7c478bd9Sstevel@tonic-gate ypbind_resp *
ypbindproc_domain_3(argp,clnt)239*7c478bd9Sstevel@tonic-gate ypbindproc_domain_3(argp, clnt)
240*7c478bd9Sstevel@tonic-gate ypbind_domain *argp;
241*7c478bd9Sstevel@tonic-gate CLIENT *clnt;
242*7c478bd9Sstevel@tonic-gate {
243*7c478bd9Sstevel@tonic-gate 	static ypbind_resp resp;
244*7c478bd9Sstevel@tonic-gate 	struct domain *cur_domain;
245*7c478bd9Sstevel@tonic-gate 	int bpid;
246*7c478bd9Sstevel@tonic-gate 	int fildes[2];
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate 	memset((char *)&resp, 0, sizeof (resp));
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
251*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "\nypbindproc_domain_3: domain: %s\n",
252*7c478bd9Sstevel@tonic-gate 		argp->ypbind_domainname);
253*7c478bd9Sstevel@tonic-gate #endif
254*7c478bd9Sstevel@tonic-gate 
255*7c478bd9Sstevel@tonic-gate 	if ((int)strlen(argp->ypbind_domainname) > YPMAXDOMAIN) {
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate 		resp.ypbind_status = YPBIND_FAIL_VAL;
258*7c478bd9Sstevel@tonic-gate 		resp.ypbind_resp_u.ypbind_error = YPBIND_ERR_NOSERV;
259*7c478bd9Sstevel@tonic-gate 		return (&resp);
260*7c478bd9Sstevel@tonic-gate 	}
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate 	if ((cur_domain = ypbind_point_to_domain(argp->ypbind_domainname)) !=
263*7c478bd9Sstevel@tonic-gate 	    (struct domain *)NULL) {
264*7c478bd9Sstevel@tonic-gate 		if (cur_domain->dom_boundp) {
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate 			struct timeval tp;
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate 			(void) gettimeofday(&tp, NULL);
269*7c478bd9Sstevel@tonic-gate 			if ((tp.tv_sec - cur_domain->lastping.tv_sec) >
270*7c478bd9Sstevel@tonic-gate 					YPBIND_PINGHOLD_DOWN) {
271*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
272*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "domain is bound pinging: %s\n",
273*7c478bd9Sstevel@tonic-gate 		argp->ypbind_domainname);
274*7c478bd9Sstevel@tonic-gate #endif
275*7c478bd9Sstevel@tonic-gate 				(void) ypbind_ping(cur_domain);
276*7c478bd9Sstevel@tonic-gate 			}
277*7c478bd9Sstevel@tonic-gate 		}
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate 		/*
280*7c478bd9Sstevel@tonic-gate 		 * Bound or not, return the current state of the binding.
281*7c478bd9Sstevel@tonic-gate 		 */
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate 		if (cur_domain->dom_boundp) {
284*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
285*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "server is up for domain: %s\n",
286*7c478bd9Sstevel@tonic-gate 		argp->ypbind_domainname);
287*7c478bd9Sstevel@tonic-gate #endif
288*7c478bd9Sstevel@tonic-gate 			resp.ypbind_status = YPBIND_SUCC_VAL;
289*7c478bd9Sstevel@tonic-gate 			resp.ypbind_resp_u.ypbind_bindinfo =
290*7c478bd9Sstevel@tonic-gate 			    cur_domain->dom_binding;
291*7c478bd9Sstevel@tonic-gate 		} else {
292*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
293*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "domain is NOT bound returning: %s %d\n",
294*7c478bd9Sstevel@tonic-gate 		argp->ypbind_domainname, cur_domain->dom_error);
295*7c478bd9Sstevel@tonic-gate #endif
296*7c478bd9Sstevel@tonic-gate 			resp.ypbind_status = YPBIND_FAIL_VAL;
297*7c478bd9Sstevel@tonic-gate 			resp.ypbind_resp_u.ypbind_error =
298*7c478bd9Sstevel@tonic-gate 			    cur_domain->dom_error;
299*7c478bd9Sstevel@tonic-gate 		}
300*7c478bd9Sstevel@tonic-gate 
301*7c478bd9Sstevel@tonic-gate 	} else {
302*7c478bd9Sstevel@tonic-gate 		resp.ypbind_status = YPBIND_FAIL_VAL;
303*7c478bd9Sstevel@tonic-gate 		resp.ypbind_resp_u.ypbind_error = YPBIND_ERR_RESC;
304*7c478bd9Sstevel@tonic-gate 	}
305*7c478bd9Sstevel@tonic-gate 	/*
306*7c478bd9Sstevel@tonic-gate 	 * RETURN NOW: if successful, otherwise
307*7c478bd9Sstevel@tonic-gate 	 * RETURN LATER: after spawning off a child to do the "broadcast" work.
308*7c478bd9Sstevel@tonic-gate 	 */
309*7c478bd9Sstevel@tonic-gate 	if (resp.ypbind_status == YPBIND_SUCC_VAL) {
310*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
311*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "yp_b_subr: returning success to yp_b_svc %d\n",
312*7c478bd9Sstevel@tonic-gate 		resp.ypbind_status);
313*7c478bd9Sstevel@tonic-gate #endif
314*7c478bd9Sstevel@tonic-gate 		return (&resp);
315*7c478bd9Sstevel@tonic-gate 	}
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate 	/* Go about the broadcast (really, pinging here) business */
318*7c478bd9Sstevel@tonic-gate 
319*7c478bd9Sstevel@tonic-gate 	if ((cur_domain) && (!cur_domain->dom_boundp) &&
320*7c478bd9Sstevel@tonic-gate 	    (!cur_domain->dom_broadcaster_pid)) {
321*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
322*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "yp_b_subr: fork: boundp=%d broadcast_pid=%d\n",
323*7c478bd9Sstevel@tonic-gate 		cur_domain->dom_boundp, cur_domain->dom_broadcaster_pid);
324*7c478bd9Sstevel@tonic-gate #endif
325*7c478bd9Sstevel@tonic-gate 		/*
326*7c478bd9Sstevel@tonic-gate 		 * The current domain is unbound, and there is no child
327*7c478bd9Sstevel@tonic-gate 		 * process active now.  Fork off a child who will beg to the
328*7c478bd9Sstevel@tonic-gate 		 * ypservers list one by one or broadcast and accept whoever
329*7c478bd9Sstevel@tonic-gate 		 * commands the right domain.
330*7c478bd9Sstevel@tonic-gate 		 */
331*7c478bd9Sstevel@tonic-gate 		if (pipe(fildes) < 0) {
332*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
333*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "yp_b_subr: returning pipe failure to yp_b_svc %d\n",
334*7c478bd9Sstevel@tonic-gate 		resp.ypbind_status);
335*7c478bd9Sstevel@tonic-gate #endif
336*7c478bd9Sstevel@tonic-gate 			return (&resp);
337*7c478bd9Sstevel@tonic-gate 		}
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate 		enable_exit();
340*7c478bd9Sstevel@tonic-gate 		sighold(SIGCLD); /* add it to ypbind's signal mask */
341*7c478bd9Sstevel@tonic-gate 		cur_domain->dom_report_success++;
342*7c478bd9Sstevel@tonic-gate 		bpid = fork();
343*7c478bd9Sstevel@tonic-gate 		if (bpid != 0) { /* parent */
344*7c478bd9Sstevel@tonic-gate 			if (bpid > 0) { /* parent started */
345*7c478bd9Sstevel@tonic-gate 				close(fildes[1]);
346*7c478bd9Sstevel@tonic-gate 				cur_domain->dom_broadcaster_pid = bpid;
347*7c478bd9Sstevel@tonic-gate 				cur_domain->broadcaster_fd = fildes[0];
348*7c478bd9Sstevel@tonic-gate 				cur_domain->broadcaster_pipe =
349*7c478bd9Sstevel@tonic-gate 						fdopen(fildes[0], "r");
350*7c478bd9Sstevel@tonic-gate 				if (cur_domain->broadcaster_pipe)
351*7c478bd9Sstevel@tonic-gate 			xdrstdio_create(&(cur_domain->broadcaster_xdr),
352*7c478bd9Sstevel@tonic-gate 			(cur_domain->broadcaster_pipe), XDR_DECODE);
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
355*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "ypbindproc_domain_3: %s starting pid = %d try = %d\n",
356*7c478bd9Sstevel@tonic-gate 	    cur_domain->dom_name, bpid,
357*7c478bd9Sstevel@tonic-gate 	    cur_domain->dom_report_success);
358*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "yp_b_subr: returning after spawning, to yp_b_svc %d\n",
359*7c478bd9Sstevel@tonic-gate 		resp.ypbind_status);
360*7c478bd9Sstevel@tonic-gate #endif
361*7c478bd9Sstevel@tonic-gate 				sigrelse(SIGCLD);
362*7c478bd9Sstevel@tonic-gate 				/* remove it from ypbind's signal mask */
363*7c478bd9Sstevel@tonic-gate 				return (&resp);
364*7c478bd9Sstevel@tonic-gate 			} else { /* fork failed */
365*7c478bd9Sstevel@tonic-gate 				perror("fork");
366*7c478bd9Sstevel@tonic-gate 				close(fildes[0]);
367*7c478bd9Sstevel@tonic-gate 				close(fildes[1]);
368*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
369*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "yp_b_subr: returning fork failure to yp_b_svc %d\n",
370*7c478bd9Sstevel@tonic-gate 		resp.ypbind_status);
371*7c478bd9Sstevel@tonic-gate #endif
372*7c478bd9Sstevel@tonic-gate 				sigrelse(SIGCLD);
373*7c478bd9Sstevel@tonic-gate 				return (&resp);
374*7c478bd9Sstevel@tonic-gate 			}
375*7c478bd9Sstevel@tonic-gate 		} /* end parent */
376*7c478bd9Sstevel@tonic-gate 		/* child only code */
377*7c478bd9Sstevel@tonic-gate 		sigrelse(SIGCLD);
378*7c478bd9Sstevel@tonic-gate 		close(fildes[0]);
379*7c478bd9Sstevel@tonic-gate 		cur_domain->broadcaster_fd = fildes[1];
380*7c478bd9Sstevel@tonic-gate 		cur_domain->broadcaster_pipe = fdopen(fildes[1], "w");
381*7c478bd9Sstevel@tonic-gate 		if (cur_domain->broadcaster_pipe)
382*7c478bd9Sstevel@tonic-gate 			xdrstdio_create(&(cur_domain->broadcaster_xdr),
383*7c478bd9Sstevel@tonic-gate 				(cur_domain->broadcaster_pipe), XDR_ENCODE);
384*7c478bd9Sstevel@tonic-gate 		else {
385*7c478bd9Sstevel@tonic-gate 			perror("fdopen-pipe");
386*7c478bd9Sstevel@tonic-gate 			exit(-1);
387*7c478bd9Sstevel@tonic-gate 		}
388*7c478bd9Sstevel@tonic-gate 		exit(pong_servers(cur_domain));
389*7c478bd9Sstevel@tonic-gate 	}
390*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
391*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "yp_b_subr: lazy returns failure status yp_b_svc %d\n",
392*7c478bd9Sstevel@tonic-gate 			resp.ypbind_status);
393*7c478bd9Sstevel@tonic-gate #endif
394*7c478bd9Sstevel@tonic-gate 	return (&resp);
395*7c478bd9Sstevel@tonic-gate }
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate 
398*7c478bd9Sstevel@tonic-gate /*
399*7c478bd9Sstevel@tonic-gate  * call ypbindproc_domain_3 and convert results
400*7c478bd9Sstevel@tonic-gate  *
401*7c478bd9Sstevel@tonic-gate  * This adds support for YP clients that send requests on
402*7c478bd9Sstevel@tonic-gate  * ypbind version 1 & 2 (i.e. clients before we started
403*7c478bd9Sstevel@tonic-gate  * using universal addresses and netbufs). This is supported
404*7c478bd9Sstevel@tonic-gate  * for binary compatibility for static 4.x programs. The
405*7c478bd9Sstevel@tonic-gate  * assumption used to be that clients coming in with ypbind vers 1
406*7c478bd9Sstevel@tonic-gate  * should be given the address of a server serving ypserv version 1.
407*7c478bd9Sstevel@tonic-gate  * However, since yp_bind routines in 4.x YP library try
408*7c478bd9Sstevel@tonic-gate  * to connect with ypserv version 2, even if they requested
409*7c478bd9Sstevel@tonic-gate  * binding using ypbind version 1, the ypbind process will
410*7c478bd9Sstevel@tonic-gate  * "always" look for only ypserv version 2 servers for all
411*7c478bd9Sstevel@tonic-gate  * (ypbind vers 1, 2, & 3) clients.
412*7c478bd9Sstevel@tonic-gate  */
413*7c478bd9Sstevel@tonic-gate ypbind_resp_2 *
ypbindproc_domain_2(argp,clnt)414*7c478bd9Sstevel@tonic-gate ypbindproc_domain_2(argp, clnt)
415*7c478bd9Sstevel@tonic-gate domainname_2 *argp;
416*7c478bd9Sstevel@tonic-gate CLIENT *clnt;
417*7c478bd9Sstevel@tonic-gate {
418*7c478bd9Sstevel@tonic-gate 	ypbind_domain arg_3;
419*7c478bd9Sstevel@tonic-gate 	ypbind_resp *resp_3;
420*7c478bd9Sstevel@tonic-gate 	static ypbind_resp_2 resp;
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate 	arg_3.ypbind_domainname = *argp;
423*7c478bd9Sstevel@tonic-gate 	resp_3 = ypbindproc_domain_3(&arg_3, clnt);
424*7c478bd9Sstevel@tonic-gate 	if (resp_3 == NULL)
425*7c478bd9Sstevel@tonic-gate 		return (NULL);
426*7c478bd9Sstevel@tonic-gate 	resp.ypbind_status = resp_3->ypbind_status;
427*7c478bd9Sstevel@tonic-gate 	if (resp_3->ypbind_status == YPBIND_SUCC_VAL) {
428*7c478bd9Sstevel@tonic-gate 		struct sockaddr_in *sin;
429*7c478bd9Sstevel@tonic-gate 		struct ypbind_binding_2 *bi;
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate 		sin = (struct sockaddr_in *)
432*7c478bd9Sstevel@tonic-gate 		    resp_3->ypbind_resp_u.ypbind_bindinfo->ypbind_svcaddr->buf;
433*7c478bd9Sstevel@tonic-gate 		if (sin->sin_family == AF_INET) {
434*7c478bd9Sstevel@tonic-gate 			bi = &resp.ypbind_respbody_2.ypbind_bindinfo;
435*7c478bd9Sstevel@tonic-gate 			memcpy(&(bi->ypbind_binding_port), &sin->sin_port, 2);
436*7c478bd9Sstevel@tonic-gate 			memcpy(&(bi->ypbind_binding_addr), &sin->sin_addr, 4);
437*7c478bd9Sstevel@tonic-gate 		} else {
438*7c478bd9Sstevel@tonic-gate 			resp.ypbind_respbody_2.ypbind_error = YPBIND_ERR_NOSERV;
439*7c478bd9Sstevel@tonic-gate 		}
440*7c478bd9Sstevel@tonic-gate 	} else {
441*7c478bd9Sstevel@tonic-gate 		resp.ypbind_respbody_2.ypbind_error =
442*7c478bd9Sstevel@tonic-gate 		    resp_3->ypbind_resp_u.ypbind_error;
443*7c478bd9Sstevel@tonic-gate 	}
444*7c478bd9Sstevel@tonic-gate 	return (&resp);
445*7c478bd9Sstevel@tonic-gate }
446*7c478bd9Sstevel@tonic-gate 
447*7c478bd9Sstevel@tonic-gate /* used to exchange information between pong_servers and ypbind_broadcast_ack */
448*7c478bd9Sstevel@tonic-gate struct domain *process_current_domain;
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate int
pong_servers(domain_struct)451*7c478bd9Sstevel@tonic-gate pong_servers(domain_struct)
452*7c478bd9Sstevel@tonic-gate struct domain *domain_struct; /* to pass back */
453*7c478bd9Sstevel@tonic-gate {
454*7c478bd9Sstevel@tonic-gate 	char *domain = domain_struct->dom_name;
455*7c478bd9Sstevel@tonic-gate 	CLIENT *clnt2;
456*7c478bd9Sstevel@tonic-gate 	char *servername;
457*7c478bd9Sstevel@tonic-gate 	listofnames *list, *lin;
458*7c478bd9Sstevel@tonic-gate 	char serverfile[MAXNAMLEN];
459*7c478bd9Sstevel@tonic-gate 	struct timeval timeout;
460*7c478bd9Sstevel@tonic-gate 	int isok = 0, res = -1;
461*7c478bd9Sstevel@tonic-gate 	struct netconfig *nconf;
462*7c478bd9Sstevel@tonic-gate 	void *handle;
463*7c478bd9Sstevel@tonic-gate 	int nconf_count;
464*7c478bd9Sstevel@tonic-gate 	char rpcdomain[YPMAXDOMAIN+1];
465*7c478bd9Sstevel@tonic-gate 	long inforet;
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate 	/*
468*7c478bd9Sstevel@tonic-gate 	 * If the ``domain'' name passed in is not the same as the RPC
469*7c478bd9Sstevel@tonic-gate 	 * domain set from /etc/defaultdomain.  Then we set ``firsttime''
470*7c478bd9Sstevel@tonic-gate 	 * to TRUE so no error messages are ever syslog()-ed this
471*7c478bd9Sstevel@tonic-gate 	 * prevents a possible Denial of Service attack.
472*7c478bd9Sstevel@tonic-gate 	 */
473*7c478bd9Sstevel@tonic-gate 	inforet = sysinfo(SI_SRPC_DOMAIN, &(rpcdomain[0]), YPMAXDOMAIN);
474*7c478bd9Sstevel@tonic-gate 	if ((inforet > 0) && (strcmp(domain, rpcdomain) != 0))
475*7c478bd9Sstevel@tonic-gate 		firsttime = TRUE;
476*7c478bd9Sstevel@tonic-gate 
477*7c478bd9Sstevel@tonic-gate 	if (broadcast) {
478*7c478bd9Sstevel@tonic-gate 		enum clnt_stat stat = RPC_SUCCESS;
479*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
480*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "pong_servers: doing an rpc_broadcast\n");
481*7c478bd9Sstevel@tonic-gate #endif
482*7c478bd9Sstevel@tonic-gate 		/*
483*7c478bd9Sstevel@tonic-gate 		 * Here we do the real SunOS thing that users love. Do a
484*7c478bd9Sstevel@tonic-gate 		 * broadcast on the network and find out the ypserv. No need
485*7c478bd9Sstevel@tonic-gate 		 * to do "ypinit -c", no setting up /etc/hosts file, and no
486*7c478bd9Sstevel@tonic-gate 		 * recursion looking up the server's IP address.
487*7c478bd9Sstevel@tonic-gate 		 */
488*7c478bd9Sstevel@tonic-gate 		process_current_domain = domain_struct;
489*7c478bd9Sstevel@tonic-gate 		stat = rpc_broadcast(YPPROG, YPVERS, YPPROC_DOMAIN_NONACK,
490*7c478bd9Sstevel@tonic-gate 			(xdrproc_t)xdr_ypdomain_wrap_string, (caddr_t)&domain,
491*7c478bd9Sstevel@tonic-gate 			xdr_int,  (caddr_t)&isok,
492*7c478bd9Sstevel@tonic-gate 			(resultproc_t)ypbind_broadcast_ack, "udp");
493*7c478bd9Sstevel@tonic-gate 		if (stat == RPC_SYSTEMERROR || stat == RPC_UNKNOWNPROTO ||
494*7c478bd9Sstevel@tonic-gate 			stat == RPC_CANTRECV || stat == RPC_CANTSEND ||
495*7c478bd9Sstevel@tonic-gate 			stat == RPC_NOBROADCAST ||
496*7c478bd9Sstevel@tonic-gate 			stat == RPC_N2AXLATEFAILURE) {
497*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "RPC/Transport subsystem failure %s\n",
498*7c478bd9Sstevel@tonic-gate 				clnt_sperrno(stat));
499*7c478bd9Sstevel@tonic-gate 			exit(-1);
500*7c478bd9Sstevel@tonic-gate 		}
501*7c478bd9Sstevel@tonic-gate 		if (domain_struct->broadcaster_pipe == 0)
502*7c478bd9Sstevel@tonic-gate 			/* init binding case */
503*7c478bd9Sstevel@tonic-gate 			return (domain_struct->dom_boundp - 1);
504*7c478bd9Sstevel@tonic-gate 		if (domain_struct->dom_boundp) {
505*7c478bd9Sstevel@tonic-gate 			res = ypbind_pipe_setdom(NULL, domain,
506*7c478bd9Sstevel@tonic-gate 					NULL, domain_struct);
507*7c478bd9Sstevel@tonic-gate 			if (domain_struct->dom_report_success > 0)
508*7c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR,
509*7c478bd9Sstevel@tonic-gate 			"NIS server for domain \"%s\" OK", domain);
510*7c478bd9Sstevel@tonic-gate 		} else if (firsttime == FALSE)
511*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
512*7c478bd9Sstevel@tonic-gate 	"NIS server not responding for domain \"%s\"; still trying", domain);
513*7c478bd9Sstevel@tonic-gate 		return (res);
514*7c478bd9Sstevel@tonic-gate 	}
515*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
516*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "pong_servers: ponging servers one by one\n");
517*7c478bd9Sstevel@tonic-gate #endif
518*7c478bd9Sstevel@tonic-gate 	/*
519*7c478bd9Sstevel@tonic-gate 	 * Do the politically correct thing.. transport independent and
520*7c478bd9Sstevel@tonic-gate 	 * secure (trusts only listed servers).
521*7c478bd9Sstevel@tonic-gate 	 */
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate 	/*
524*7c478bd9Sstevel@tonic-gate 	 * get list of possible servers for this domain
525*7c478bd9Sstevel@tonic-gate 	 */
526*7c478bd9Sstevel@tonic-gate 
527*7c478bd9Sstevel@tonic-gate 	/*
528*7c478bd9Sstevel@tonic-gate 	 * get alias for domain: Things of the past..
529*7c478bd9Sstevel@tonic-gate 	 * sysvconfig();
530*7c478bd9Sstevel@tonic-gate 	 * (void) yp_getalias(domain, domain_alias, NAME_MAX);
531*7c478bd9Sstevel@tonic-gate 	 */
532*7c478bd9Sstevel@tonic-gate 	sprintf(serverfile, "%s/%s/%s", BINDING, domain, YPSERVERS);
533*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
534*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "pong_servers: serverfile %s\n", serverfile);
535*7c478bd9Sstevel@tonic-gate #endif
536*7c478bd9Sstevel@tonic-gate 	list = names(serverfile);
537*7c478bd9Sstevel@tonic-gate 	if (list == NULL) {
538*7c478bd9Sstevel@tonic-gate 		if (firsttime == FALSE)
539*7c478bd9Sstevel@tonic-gate 		    syslog(LOG_ERR,
540*7c478bd9Sstevel@tonic-gate 			"service not installed, use /usr/sbin/ypinit -c");
541*7c478bd9Sstevel@tonic-gate 		return (-1);
542*7c478bd9Sstevel@tonic-gate 	}
543*7c478bd9Sstevel@tonic-gate 	lin = list;
544*7c478bd9Sstevel@tonic-gate 	for (list = lin; list; list = list->nextname) {
545*7c478bd9Sstevel@tonic-gate 		servername = strtok(list->name, " \t\n");
546*7c478bd9Sstevel@tonic-gate 		if (servername == NULL) continue;
547*7c478bd9Sstevel@tonic-gate 
548*7c478bd9Sstevel@tonic-gate 		/* Check all datagram_v transports for this server */
549*7c478bd9Sstevel@tonic-gate 		if ((handle = __rpc_setconf("datagram_v")) == NULL) {
550*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
551*7c478bd9Sstevel@tonic-gate 			"ypbind: RPC operation on /etc/netconfig failed");
552*7c478bd9Sstevel@tonic-gate 			free_listofnames(lin);
553*7c478bd9Sstevel@tonic-gate 			return (-1);
554*7c478bd9Sstevel@tonic-gate 		}
555*7c478bd9Sstevel@tonic-gate 
556*7c478bd9Sstevel@tonic-gate 		nconf_count = 0;
557*7c478bd9Sstevel@tonic-gate 		clnt2 = 0;
558*7c478bd9Sstevel@tonic-gate 		while (clnt2 == 0 && (nconf = __rpc_getconf(handle)) != 0) {
559*7c478bd9Sstevel@tonic-gate 			nconf_count++;
560*7c478bd9Sstevel@tonic-gate 			/*
561*7c478bd9Sstevel@tonic-gate 			 * We use only datagram here. It is expected to be udp.
562*7c478bd9Sstevel@tonic-gate 			 * VERY IMPORTANT: __clnt_tp_create_bootstrap is a
563*7c478bd9Sstevel@tonic-gate 			 * hacked up version that does not do netdir_getbyname.
564*7c478bd9Sstevel@tonic-gate 			 */
565*7c478bd9Sstevel@tonic-gate 			hostNotKnownLocally = 0;
566*7c478bd9Sstevel@tonic-gate 			clnt2 =
567*7c478bd9Sstevel@tonic-gate 	__clnt_tp_create_bootstrap(servername, YPPROG, YPVERS, nconf);
568*7c478bd9Sstevel@tonic-gate 		}
569*7c478bd9Sstevel@tonic-gate 		if (nconf_count == 0) {
570*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
571*7c478bd9Sstevel@tonic-gate 			"ypbind: RPC operation on /etc/netconfig failed");
572*7c478bd9Sstevel@tonic-gate 			free_listofnames(lin);
573*7c478bd9Sstevel@tonic-gate 			return (-1);
574*7c478bd9Sstevel@tonic-gate 		}
575*7c478bd9Sstevel@tonic-gate 
576*7c478bd9Sstevel@tonic-gate 		if (clnt2 == 0) {
577*7c478bd9Sstevel@tonic-gate 			if (rpc_createerr.cf_stat == RPC_UNKNOWNHOST &&
578*7c478bd9Sstevel@tonic-gate 				hostNotKnownLocally) {
579*7c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR,
580*7c478bd9Sstevel@tonic-gate 		"NIS server %s is not in local host files !", servername);
581*7c478bd9Sstevel@tonic-gate 			}
582*7c478bd9Sstevel@tonic-gate 			perror(servername);
583*7c478bd9Sstevel@tonic-gate 			clnt_pcreateerror("ypbind");
584*7c478bd9Sstevel@tonic-gate 			continue;
585*7c478bd9Sstevel@tonic-gate 		}
586*7c478bd9Sstevel@tonic-gate 
587*7c478bd9Sstevel@tonic-gate 		timeout.tv_sec = PINGTIME;
588*7c478bd9Sstevel@tonic-gate 		timeout.tv_usec = 0;
589*7c478bd9Sstevel@tonic-gate 		if ((enum clnt_stat) clnt_call(clnt2,
590*7c478bd9Sstevel@tonic-gate 		    YPPROC_DOMAIN, (xdrproc_t)xdr_ypdomain_wrap_string,
591*7c478bd9Sstevel@tonic-gate 		    (char *)&domain, xdr_int,
592*7c478bd9Sstevel@tonic-gate 		    (char *)&isok, timeout) == RPC_SUCCESS) {
593*7c478bd9Sstevel@tonic-gate 			if (isok) {
594*7c478bd9Sstevel@tonic-gate 				if (domain_struct->dom_report_success > 0) {
595*7c478bd9Sstevel@tonic-gate 					syslog(LOG_ERR,
596*7c478bd9Sstevel@tonic-gate 				"NIS server for domain \"%s\" OK", domain);
597*7c478bd9Sstevel@tonic-gate 				}
598*7c478bd9Sstevel@tonic-gate 				if (domain_struct->broadcaster_pipe == 0) {
599*7c478bd9Sstevel@tonic-gate 					/* init binding case --parent */
600*7c478bd9Sstevel@tonic-gate 					struct netconfig *setnc;
601*7c478bd9Sstevel@tonic-gate 					struct netbuf setua;
602*7c478bd9Sstevel@tonic-gate 					struct ypbind_binding *b =
603*7c478bd9Sstevel@tonic-gate 						domain_struct->dom_binding;
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate 					setnc =
606*7c478bd9Sstevel@tonic-gate 				getnetconfigent(clnt2->cl_netid);
607*7c478bd9Sstevel@tonic-gate 					if (b == NULL) {
608*7c478bd9Sstevel@tonic-gate 					/* ASSERT: This shouldn't happen ! */
609*7c478bd9Sstevel@tonic-gate 						b =
610*7c478bd9Sstevel@tonic-gate 				(struct ypbind_binding *)calloc(1, sizeof (*b));
611*7c478bd9Sstevel@tonic-gate 						domain_struct->dom_binding = b;
612*7c478bd9Sstevel@tonic-gate 						if (b == NULL) {
613*7c478bd9Sstevel@tonic-gate 							__rpc_endconf(handle);
614*7c478bd9Sstevel@tonic-gate 							clnt_destroy(clnt2);
615*7c478bd9Sstevel@tonic-gate 							free_listofnames(lin);
616*7c478bd9Sstevel@tonic-gate 							return (-2);
617*7c478bd9Sstevel@tonic-gate 						}
618*7c478bd9Sstevel@tonic-gate 					}
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate 
621*7c478bd9Sstevel@tonic-gate 					b->ypbind_nconf = setnc;
622*7c478bd9Sstevel@tonic-gate 					clnt_control(clnt2, CLGET_SVC_ADDR,
623*7c478bd9Sstevel@tonic-gate 						(char *)&setua);
624*7c478bd9Sstevel@tonic-gate 					if (b->ypbind_svcaddr) {
625*7c478bd9Sstevel@tonic-gate 						if (b->ypbind_svcaddr->buf)
626*7c478bd9Sstevel@tonic-gate 				free(b->ypbind_svcaddr->buf);
627*7c478bd9Sstevel@tonic-gate 						free(b->ypbind_svcaddr);
628*7c478bd9Sstevel@tonic-gate 					}
629*7c478bd9Sstevel@tonic-gate 					b->ypbind_svcaddr = dup_netbuf(&setua);
630*7c478bd9Sstevel@tonic-gate 					if (b->ypbind_servername)
631*7c478bd9Sstevel@tonic-gate 						free(b->ypbind_servername);
632*7c478bd9Sstevel@tonic-gate 					b->ypbind_servername =
633*7c478bd9Sstevel@tonic-gate 						strdup(servername);
634*7c478bd9Sstevel@tonic-gate 					b->ypbind_hi_vers = YPVERS;
635*7c478bd9Sstevel@tonic-gate 					b->ypbind_lo_vers = YPVERS;
636*7c478bd9Sstevel@tonic-gate 					__rpc_endconf(handle);
637*7c478bd9Sstevel@tonic-gate 					domain_struct->dom_boundp = TRUE;
638*7c478bd9Sstevel@tonic-gate 					clnt_destroy(clnt2);
639*7c478bd9Sstevel@tonic-gate 					free_listofnames(lin);
640*7c478bd9Sstevel@tonic-gate 					return (0);
641*7c478bd9Sstevel@tonic-gate 				}
642*7c478bd9Sstevel@tonic-gate 				res = ypbind_pipe_setdom(clnt2, domain,
643*7c478bd9Sstevel@tonic-gate 					servername, domain_struct);
644*7c478bd9Sstevel@tonic-gate 				__rpc_endconf(handle);
645*7c478bd9Sstevel@tonic-gate 				clnt_destroy(clnt2);
646*7c478bd9Sstevel@tonic-gate 				free_listofnames(lin);
647*7c478bd9Sstevel@tonic-gate 				return (res);
648*7c478bd9Sstevel@tonic-gate 			} else {
649*7c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR,
650*7c478bd9Sstevel@tonic-gate 				    "server %s doesn't serve domain %s\n",
651*7c478bd9Sstevel@tonic-gate 				    servername, domain);
652*7c478bd9Sstevel@tonic-gate 			}
653*7c478bd9Sstevel@tonic-gate 		} else {
654*7c478bd9Sstevel@tonic-gate 			clnt_perror(clnt2, servername);
655*7c478bd9Sstevel@tonic-gate 		}
656*7c478bd9Sstevel@tonic-gate 		clnt_destroy(clnt2);
657*7c478bd9Sstevel@tonic-gate 	}
658*7c478bd9Sstevel@tonic-gate 	/*
659*7c478bd9Sstevel@tonic-gate 	 * We tried all servers, none obliged !
660*7c478bd9Sstevel@tonic-gate 	 * After ypbind is started up it will not be bound
661*7c478bd9Sstevel@tonic-gate 	 * immediately.  This is normal, no error message
662*7c478bd9Sstevel@tonic-gate 	 * is needed. Although, with the ypbind_init_default
663*7c478bd9Sstevel@tonic-gate 	 * it will be bound immediately.
664*7c478bd9Sstevel@tonic-gate 	 */
665*7c478bd9Sstevel@tonic-gate 	if (firsttime == FALSE) {
666*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR,
667*7c478bd9Sstevel@tonic-gate "NIS server not responding for domain \"%s\"; still trying", domain);
668*7c478bd9Sstevel@tonic-gate 	}
669*7c478bd9Sstevel@tonic-gate 	free_listofnames(lin);
670*7c478bd9Sstevel@tonic-gate 	__rpc_endconf(handle);
671*7c478bd9Sstevel@tonic-gate 	return (-2);
672*7c478bd9Sstevel@tonic-gate }
673*7c478bd9Sstevel@tonic-gate 
674*7c478bd9Sstevel@tonic-gate struct netbuf *
dup_netbuf(inbuf)675*7c478bd9Sstevel@tonic-gate dup_netbuf(inbuf)
676*7c478bd9Sstevel@tonic-gate 	struct netbuf *inbuf;
677*7c478bd9Sstevel@tonic-gate {
678*7c478bd9Sstevel@tonic-gate 	struct netbuf *outbuf;
679*7c478bd9Sstevel@tonic-gate 
680*7c478bd9Sstevel@tonic-gate 	if (inbuf == NULL)
681*7c478bd9Sstevel@tonic-gate 		return (NULL);
682*7c478bd9Sstevel@tonic-gate 	if ((outbuf =
683*7c478bd9Sstevel@tonic-gate 		(struct netbuf *)calloc(1, sizeof (struct netbuf))) == NULL)
684*7c478bd9Sstevel@tonic-gate 		return (NULL);
685*7c478bd9Sstevel@tonic-gate 	if ((outbuf->buf = malloc(inbuf->len)) == NULL) {
686*7c478bd9Sstevel@tonic-gate 		free(outbuf);
687*7c478bd9Sstevel@tonic-gate 		return (NULL);
688*7c478bd9Sstevel@tonic-gate 	}
689*7c478bd9Sstevel@tonic-gate 	outbuf->len = inbuf->len;
690*7c478bd9Sstevel@tonic-gate 	outbuf->maxlen = inbuf->len;
691*7c478bd9Sstevel@tonic-gate 	(void) memcpy(outbuf->buf, inbuf->buf, inbuf->len);
692*7c478bd9Sstevel@tonic-gate 	return (outbuf);
693*7c478bd9Sstevel@tonic-gate }
694*7c478bd9Sstevel@tonic-gate 
695*7c478bd9Sstevel@tonic-gate /*
696*7c478bd9Sstevel@tonic-gate  * This is called by the broadcast rpc routines to process the responses
697*7c478bd9Sstevel@tonic-gate  * coming back from the broadcast request. Since the form of the request
698*7c478bd9Sstevel@tonic-gate  * which is used in ypbind_broadcast_bind is "respond only in the positive
699*7c478bd9Sstevel@tonic-gate  * case", we know that we have a server.
700*7c478bd9Sstevel@tonic-gate  * The internet address of the responding server will be picked up from
701*7c478bd9Sstevel@tonic-gate  * the saddr parameter, and stuffed into the domain.  The domain's boundp
702*7c478bd9Sstevel@tonic-gate  * field will be set TRUE.  The first responding server (or the first one
703*7c478bd9Sstevel@tonic-gate  * which is on a reserved port) will be the bound server for the domain.
704*7c478bd9Sstevel@tonic-gate  */
705*7c478bd9Sstevel@tonic-gate bool
ypbind_broadcast_ack(ptrue,nbuf,nconf)706*7c478bd9Sstevel@tonic-gate ypbind_broadcast_ack(ptrue, nbuf, nconf)
707*7c478bd9Sstevel@tonic-gate 	bool *ptrue;
708*7c478bd9Sstevel@tonic-gate 	struct netbuf *nbuf;
709*7c478bd9Sstevel@tonic-gate 	struct netconfig *nconf;
710*7c478bd9Sstevel@tonic-gate {
711*7c478bd9Sstevel@tonic-gate 	struct ypbind_binding b;
712*7c478bd9Sstevel@tonic-gate 
713*7c478bd9Sstevel@tonic-gate 	process_current_domain->dom_boundp = TRUE;
714*7c478bd9Sstevel@tonic-gate 	b.ypbind_nconf = nconf;
715*7c478bd9Sstevel@tonic-gate 	b.ypbind_svcaddr = nbuf;
716*7c478bd9Sstevel@tonic-gate 	b.ypbind_servername = "\000";
717*7c478bd9Sstevel@tonic-gate 	b.ypbind_hi_vers = YPVERS;
718*7c478bd9Sstevel@tonic-gate 	b.ypbind_lo_vers = YPVERS;
719*7c478bd9Sstevel@tonic-gate 	free_ypbind_binding(process_current_domain->dom_binding);
720*7c478bd9Sstevel@tonic-gate 	process_current_domain->dom_binding = dup_ypbind_binding(&b);
721*7c478bd9Sstevel@tonic-gate 	return (TRUE);
722*7c478bd9Sstevel@tonic-gate }
723*7c478bd9Sstevel@tonic-gate 
724*7c478bd9Sstevel@tonic-gate /*
725*7c478bd9Sstevel@tonic-gate  * WARNING: This routine is entered only by the child process.
726*7c478bd9Sstevel@tonic-gate  * Called if it pongs/broadcasts okay.
727*7c478bd9Sstevel@tonic-gate  */
728*7c478bd9Sstevel@tonic-gate static int
ypbind_pipe_setdom(client,domain,servername,opaque_domain)729*7c478bd9Sstevel@tonic-gate ypbind_pipe_setdom(client, domain, servername, opaque_domain)
730*7c478bd9Sstevel@tonic-gate CLIENT *client;
731*7c478bd9Sstevel@tonic-gate char *servername;
732*7c478bd9Sstevel@tonic-gate char *domain;
733*7c478bd9Sstevel@tonic-gate struct domain *opaque_domain;
734*7c478bd9Sstevel@tonic-gate {
735*7c478bd9Sstevel@tonic-gate 	struct netconfig *setnc;
736*7c478bd9Sstevel@tonic-gate 	struct netbuf setua;
737*7c478bd9Sstevel@tonic-gate 	ypbind_binding setb;
738*7c478bd9Sstevel@tonic-gate 	ypbind_setdom setd;
739*7c478bd9Sstevel@tonic-gate 	int retval;
740*7c478bd9Sstevel@tonic-gate 
741*7c478bd9Sstevel@tonic-gate 	setd.ypsetdom_domain = domain;
742*7c478bd9Sstevel@tonic-gate 	if (client == NULL && opaque_domain->dom_binding) {
743*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
744*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "ypbind_pipe_setdom: child broadcast case ");
745*7c478bd9Sstevel@tonic-gate #endif
746*7c478bd9Sstevel@tonic-gate 		/* ypbind_broadcast_ack already setup dom_binding for us */
747*7c478bd9Sstevel@tonic-gate 		setd.ypsetdom_bindinfo = opaque_domain->dom_binding;
748*7c478bd9Sstevel@tonic-gate 	} else if (client) {
749*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
750*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "ypbind_pipe_setdom: child unicast case ");
751*7c478bd9Sstevel@tonic-gate #endif
752*7c478bd9Sstevel@tonic-gate 		setnc = getnetconfigent(client->cl_netid);
753*7c478bd9Sstevel@tonic-gate 		if (setnc == NULL) {
754*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
755*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "PANIC: shouldn't happen\n");
756*7c478bd9Sstevel@tonic-gate #endif
757*7c478bd9Sstevel@tonic-gate 			fclose(opaque_domain->broadcaster_pipe);
758*7c478bd9Sstevel@tonic-gate 			close(opaque_domain->broadcaster_fd);
759*7c478bd9Sstevel@tonic-gate 			return (-2);
760*7c478bd9Sstevel@tonic-gate 		}
761*7c478bd9Sstevel@tonic-gate 		clnt_control(client, CLGET_SVC_ADDR, (char *)&setua);
762*7c478bd9Sstevel@tonic-gate 		setb.ypbind_nconf = setnc;
763*7c478bd9Sstevel@tonic-gate 		setb.ypbind_svcaddr = &setua;
764*7c478bd9Sstevel@tonic-gate 		setb.ypbind_servername = servername;
765*7c478bd9Sstevel@tonic-gate 		setb.ypbind_hi_vers = YPVERS;
766*7c478bd9Sstevel@tonic-gate 		setb.ypbind_lo_vers = YPVERS;
767*7c478bd9Sstevel@tonic-gate 		setd.ypsetdom_bindinfo = &setb;
768*7c478bd9Sstevel@tonic-gate 	/*
769*7c478bd9Sstevel@tonic-gate 	 * Let's hardcode versions, that is the only ypserv we support anyway.
770*7c478bd9Sstevel@tonic-gate 	 * Avoid the song and dance of recursively calling ypbind_ping
771*7c478bd9Sstevel@tonic-gate 	 * for no reason. Consistent with the 4.1 policy, that if ypbind gets
772*7c478bd9Sstevel@tonic-gate 	 * a request on new binder protocol, the requestor is looking for the
773*7c478bd9Sstevel@tonic-gate 	 * new ypserv. And, we have even higher binder protocol version i.e. 3.
774*7c478bd9Sstevel@tonic-gate 	 */
775*7c478bd9Sstevel@tonic-gate 	} else
776*7c478bd9Sstevel@tonic-gate 		return (-1);
777*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
778*7c478bd9Sstevel@tonic-gate 	fprintf(stderr,
779*7c478bd9Sstevel@tonic-gate 		" saving server settings, \nsupports versions %d thru %d\n",
780*7c478bd9Sstevel@tonic-gate 		setd.ypsetdom_bindinfo->ypbind_lo_vers,
781*7c478bd9Sstevel@tonic-gate 		setd.ypsetdom_bindinfo->ypbind_hi_vers);
782*7c478bd9Sstevel@tonic-gate #endif
783*7c478bd9Sstevel@tonic-gate 
784*7c478bd9Sstevel@tonic-gate 	if (opaque_domain->broadcaster_pipe == 0) {
785*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
786*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "PANIC: shouldn't be in this function\n");
787*7c478bd9Sstevel@tonic-gate #endif
788*7c478bd9Sstevel@tonic-gate 		return (-2);
789*7c478bd9Sstevel@tonic-gate 	}
790*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
791*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "child: doing xdr_ypbind_setdom\n");
792*7c478bd9Sstevel@tonic-gate #endif
793*7c478bd9Sstevel@tonic-gate 	retval = xdr_ypbind_setdom(&(opaque_domain->broadcaster_xdr), &setd);
794*7c478bd9Sstevel@tonic-gate 	xdr_destroy(&(opaque_domain->broadcaster_xdr));
795*7c478bd9Sstevel@tonic-gate 	fclose(opaque_domain->broadcaster_pipe);
796*7c478bd9Sstevel@tonic-gate 	close(opaque_domain->broadcaster_fd);
797*7c478bd9Sstevel@tonic-gate 	/*
798*7c478bd9Sstevel@tonic-gate 	 * This child process is about to exit. Don't bother freeing memory.
799*7c478bd9Sstevel@tonic-gate 	 */
800*7c478bd9Sstevel@tonic-gate 	if (!retval) {
801*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
802*7c478bd9Sstevel@tonic-gate 	fprintf(stderr,
803*7c478bd9Sstevel@tonic-gate 		"YPBIND pipe_setdom failed \n(xdr failure) to server %s\n",
804*7c478bd9Sstevel@tonic-gate 		servername ? servername : "");
805*7c478bd9Sstevel@tonic-gate #endif
806*7c478bd9Sstevel@tonic-gate 		return (-3);
807*7c478bd9Sstevel@tonic-gate 	}
808*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
809*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "ypbind_pipe_setdom: YPBIND OK-set to server %s\n",
810*7c478bd9Sstevel@tonic-gate 		servername ? servername : "");
811*7c478bd9Sstevel@tonic-gate #endif
812*7c478bd9Sstevel@tonic-gate 	return (0);
813*7c478bd9Sstevel@tonic-gate }
814*7c478bd9Sstevel@tonic-gate 
815*7c478bd9Sstevel@tonic-gate /* Same as ypbind_set_binding in SunOS */
816*7c478bd9Sstevel@tonic-gate /*
817*7c478bd9Sstevel@tonic-gate  *  We use a trick from SunOS to return an error to the ypset command
818*7c478bd9Sstevel@tonic-gate  *  when we are not allowing the domain to be set.  We do a svcerr_noprog()
819*7c478bd9Sstevel@tonic-gate  *  to send RPC_PROGUNAVAIL to ypset.  We also return NULL so that
820*7c478bd9Sstevel@tonic-gate  *  our caller (ypbindprog_3) won't try to return a result.  This
821*7c478bd9Sstevel@tonic-gate  *  hack is necessary because the YPBINDPROC_SETDOM procedure is defined
822*7c478bd9Sstevel@tonic-gate  *  in the protocol to return xdr_void, so we don't have a direct way to
823*7c478bd9Sstevel@tonic-gate  *  return an error to the client.
824*7c478bd9Sstevel@tonic-gate  */
825*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
826*7c478bd9Sstevel@tonic-gate void	*
ypbindproc_setdom_3(argp,rqstp,transp)827*7c478bd9Sstevel@tonic-gate ypbindproc_setdom_3(argp, rqstp, transp)
828*7c478bd9Sstevel@tonic-gate ypbind_setdom *argp;
829*7c478bd9Sstevel@tonic-gate struct svc_req *rqstp;
830*7c478bd9Sstevel@tonic-gate SVCXPRT *transp;
831*7c478bd9Sstevel@tonic-gate {
832*7c478bd9Sstevel@tonic-gate 	struct domain *a_domain;
833*7c478bd9Sstevel@tonic-gate 	struct netbuf *who;
834*7c478bd9Sstevel@tonic-gate 	static char res; /* dummy for void * return */
835*7c478bd9Sstevel@tonic-gate 	uid_t caller_uid;
836*7c478bd9Sstevel@tonic-gate 
837*7c478bd9Sstevel@tonic-gate 	if ((int)strlen(argp->ypsetdom_domain) > YPMAXDOMAIN) {
838*7c478bd9Sstevel@tonic-gate 
839*7c478bd9Sstevel@tonic-gate 		if (transp) {
840*7c478bd9Sstevel@tonic-gate 			svcerr_systemerr(transp);
841*7c478bd9Sstevel@tonic-gate 			return (0);
842*7c478bd9Sstevel@tonic-gate 		}
843*7c478bd9Sstevel@tonic-gate 		return (&res);
844*7c478bd9Sstevel@tonic-gate 	}
845*7c478bd9Sstevel@tonic-gate 
846*7c478bd9Sstevel@tonic-gate 	if (transp != NULL) {
847*7c478bd9Sstevel@tonic-gate 		/* find out who originated the request */
848*7c478bd9Sstevel@tonic-gate 		char *uaddr;
849*7c478bd9Sstevel@tonic-gate 		struct netconfig *nconf;
850*7c478bd9Sstevel@tonic-gate 
851*7c478bd9Sstevel@tonic-gate 		who = svc_getrpccaller(transp);
852*7c478bd9Sstevel@tonic-gate 		if ((nconf = getnetconfigent(transp->xp_netid))
853*7c478bd9Sstevel@tonic-gate 			== (struct netconfig *)NULL) {
854*7c478bd9Sstevel@tonic-gate 			svcerr_systemerr(transp);
855*7c478bd9Sstevel@tonic-gate 			return (0);
856*7c478bd9Sstevel@tonic-gate 		}
857*7c478bd9Sstevel@tonic-gate 		if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
858*7c478bd9Sstevel@tonic-gate 			uaddr = strdup("local host");
859*7c478bd9Sstevel@tonic-gate 		} else {
860*7c478bd9Sstevel@tonic-gate 			uaddr = taddr2uaddr(nconf, who);
861*7c478bd9Sstevel@tonic-gate 		}
862*7c478bd9Sstevel@tonic-gate 		if (setok != YPSETALL) {
863*7c478bd9Sstevel@tonic-gate 		/* for -ypset, it falls through and let anybody do a setdom ! */
864*7c478bd9Sstevel@tonic-gate 			if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) != 0) {
865*7c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR,
866*7c478bd9Sstevel@tonic-gate "ypset request from %s not on loopback, \
867*7c478bd9Sstevel@tonic-gate cannot set ypbind to %s", uaddr ? uaddr : "unknown source",
868*7c478bd9Sstevel@tonic-gate argp->ypsetdom_bindinfo->ypbind_servername);
869*7c478bd9Sstevel@tonic-gate 				if (uaddr)
870*7c478bd9Sstevel@tonic-gate 					free(uaddr);
871*7c478bd9Sstevel@tonic-gate 				freenetconfigent(nconf);
872*7c478bd9Sstevel@tonic-gate 				svcerr_noprog(transp);
873*7c478bd9Sstevel@tonic-gate 				return (0);
874*7c478bd9Sstevel@tonic-gate 			}
875*7c478bd9Sstevel@tonic-gate 			switch (setok) {
876*7c478bd9Sstevel@tonic-gate 			case YPSETNONE:
877*7c478bd9Sstevel@tonic-gate 				if (strcmp(nconf->nc_protofmly,
878*7c478bd9Sstevel@tonic-gate 					NC_LOOPBACK) == 0)
879*7c478bd9Sstevel@tonic-gate 					syslog(LOG_ERR,
880*7c478bd9Sstevel@tonic-gate "ypset request to %s from %s failed - ypset not allowed",
881*7c478bd9Sstevel@tonic-gate argp->ypsetdom_bindinfo->ypbind_servername, uaddr);
882*7c478bd9Sstevel@tonic-gate 				if (uaddr)
883*7c478bd9Sstevel@tonic-gate 					free(uaddr);
884*7c478bd9Sstevel@tonic-gate 				freenetconfigent(nconf);
885*7c478bd9Sstevel@tonic-gate 				svcerr_noprog(transp);
886*7c478bd9Sstevel@tonic-gate 				return (0);
887*7c478bd9Sstevel@tonic-gate 			case YPSETLOCAL:
888*7c478bd9Sstevel@tonic-gate 				if (__rpc_get_local_uid(transp,
889*7c478bd9Sstevel@tonic-gate 					&caller_uid) < 0) {
890*7c478bd9Sstevel@tonic-gate 					syslog(LOG_ERR, "ypset request from \
891*7c478bd9Sstevel@tonic-gate unidentified local user on %s - ypset not allowed",
892*7c478bd9Sstevel@tonic-gate transp->xp_netid);
893*7c478bd9Sstevel@tonic-gate 					if (uaddr)
894*7c478bd9Sstevel@tonic-gate 						free(uaddr);
895*7c478bd9Sstevel@tonic-gate 					freenetconfigent(nconf);
896*7c478bd9Sstevel@tonic-gate 					svcerr_noprog(transp);
897*7c478bd9Sstevel@tonic-gate 					return (0);
898*7c478bd9Sstevel@tonic-gate 				}
899*7c478bd9Sstevel@tonic-gate 				if (caller_uid != 0) {
900*7c478bd9Sstevel@tonic-gate 					syslog(LOG_ERR,
901*7c478bd9Sstevel@tonic-gate "Set domain request to host %s \
902*7c478bd9Sstevel@tonic-gate from local non-root user %ld failed - ypset not allowed",
903*7c478bd9Sstevel@tonic-gate argp->ypsetdom_bindinfo->ypbind_servername, caller_uid);
904*7c478bd9Sstevel@tonic-gate 					if (uaddr)
905*7c478bd9Sstevel@tonic-gate 						free(uaddr);
906*7c478bd9Sstevel@tonic-gate 					freenetconfigent(nconf);
907*7c478bd9Sstevel@tonic-gate 					svcerr_noprog(transp);
908*7c478bd9Sstevel@tonic-gate 					return (0);
909*7c478bd9Sstevel@tonic-gate 				}
910*7c478bd9Sstevel@tonic-gate 			}
911*7c478bd9Sstevel@tonic-gate 		}
912*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "Set domain request from %s : \
913*7c478bd9Sstevel@tonic-gate setting server for domain %s to %s", uaddr ? uaddr : "UNKNOWN SOURCE",
914*7c478bd9Sstevel@tonic-gate argp->ypsetdom_domain, argp->ypsetdom_bindinfo->ypbind_servername);
915*7c478bd9Sstevel@tonic-gate 		if (uaddr)
916*7c478bd9Sstevel@tonic-gate 			free(uaddr);
917*7c478bd9Sstevel@tonic-gate 		freenetconfigent(nconf);
918*7c478bd9Sstevel@tonic-gate 	}
919*7c478bd9Sstevel@tonic-gate 
920*7c478bd9Sstevel@tonic-gate 	if ((a_domain = ypbind_point_to_domain(argp->ypsetdom_domain))
921*7c478bd9Sstevel@tonic-gate 	    != (struct domain *)NULL) {
922*7c478bd9Sstevel@tonic-gate 		/* setting binding; old may be invalid */
923*7c478bd9Sstevel@tonic-gate 		uncache_binding(a_domain);
924*7c478bd9Sstevel@tonic-gate 
925*7c478bd9Sstevel@tonic-gate 		/* this does the set -- should copy the structure */
926*7c478bd9Sstevel@tonic-gate 		free_ypbind_binding(a_domain->dom_binding);
927*7c478bd9Sstevel@tonic-gate 		if ((a_domain->dom_binding =
928*7c478bd9Sstevel@tonic-gate 		    dup_ypbind_binding(argp->ypsetdom_bindinfo)) == NULL) {
929*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "ypbindproc_setdom_3: out of memory, ",
930*7c478bd9Sstevel@tonic-gate 				"dup_ypbind_binding failed\n");
931*7c478bd9Sstevel@tonic-gate 			if (transp) {
932*7c478bd9Sstevel@tonic-gate 				svcerr_noprog(transp);
933*7c478bd9Sstevel@tonic-gate 				return (0);
934*7c478bd9Sstevel@tonic-gate 			}
935*7c478bd9Sstevel@tonic-gate 			return (&res);
936*7c478bd9Sstevel@tonic-gate 		}
937*7c478bd9Sstevel@tonic-gate 		gettimeofday(&(a_domain->lastping), NULL);
938*7c478bd9Sstevel@tonic-gate 		a_domain->dom_boundp = TRUE;
939*7c478bd9Sstevel@tonic-gate 		cache_binding(a_domain);
940*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
941*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "ypbindproc_setdom_3: setting domain %s to server %s\n",
942*7c478bd9Sstevel@tonic-gate 		argp->ypsetdom_domain,
943*7c478bd9Sstevel@tonic-gate 		argp->ypsetdom_bindinfo->ypbind_servername);
944*7c478bd9Sstevel@tonic-gate #endif
945*7c478bd9Sstevel@tonic-gate 	}
946*7c478bd9Sstevel@tonic-gate 
947*7c478bd9Sstevel@tonic-gate 	return (&res);
948*7c478bd9Sstevel@tonic-gate }
949*7c478bd9Sstevel@tonic-gate 
950*7c478bd9Sstevel@tonic-gate /*
951*7c478bd9Sstevel@tonic-gate  * This returns a pointer to a domain entry.  If no such domain existed on
952*7c478bd9Sstevel@tonic-gate  * the list previously, an entry will be allocated, initialized, and linked
953*7c478bd9Sstevel@tonic-gate  * to the list.  Note:  If no memory can be malloc-ed for the domain structure,
954*7c478bd9Sstevel@tonic-gate  * the functional value will be (struct domain *) NULL.
955*7c478bd9Sstevel@tonic-gate  */
956*7c478bd9Sstevel@tonic-gate static struct domain *
ypbind_point_to_domain(pname)957*7c478bd9Sstevel@tonic-gate ypbind_point_to_domain(pname)
958*7c478bd9Sstevel@tonic-gate register char	*pname;
959*7c478bd9Sstevel@tonic-gate {
960*7c478bd9Sstevel@tonic-gate 	register struct domain *pdom;
961*7c478bd9Sstevel@tonic-gate 	char buf[300];
962*7c478bd9Sstevel@tonic-gate 
963*7c478bd9Sstevel@tonic-gate 	for (pdom = known_domains; pdom != (struct domain *)NULL;
964*7c478bd9Sstevel@tonic-gate 	    pdom = pdom->dom_pnext) {
965*7c478bd9Sstevel@tonic-gate 		if (strcmp(pname, pdom->dom_name) == 0)
966*7c478bd9Sstevel@tonic-gate 			return (pdom);
967*7c478bd9Sstevel@tonic-gate 	}
968*7c478bd9Sstevel@tonic-gate 
969*7c478bd9Sstevel@tonic-gate 	/* Not found.  Add it to the list */
970*7c478bd9Sstevel@tonic-gate 
971*7c478bd9Sstevel@tonic-gate 	if (pdom = (struct domain *)calloc(1, sizeof (struct domain))) {
972*7c478bd9Sstevel@tonic-gate 		pdom->dom_name = strdup(pname);
973*7c478bd9Sstevel@tonic-gate 		if (pdom->dom_name == NULL) {
974*7c478bd9Sstevel@tonic-gate 			free((char *)pdom);
975*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
976*7c478bd9Sstevel@tonic-gate 				"ypbind_point_to_domain: strdup failed\n");
977*7c478bd9Sstevel@tonic-gate 			return (NULL);
978*7c478bd9Sstevel@tonic-gate 		}
979*7c478bd9Sstevel@tonic-gate 		pdom->dom_pnext = known_domains;
980*7c478bd9Sstevel@tonic-gate 		known_domains = pdom;
981*7c478bd9Sstevel@tonic-gate 		pdom->dom_boundp = FALSE;
982*7c478bd9Sstevel@tonic-gate 		pdom->dom_vers = YPVERS; /* This doesn't talk to old ypserv */
983*7c478bd9Sstevel@tonic-gate 		pdom->dom_binding = NULL;
984*7c478bd9Sstevel@tonic-gate 		pdom->dom_error = YPBIND_ERR_NOSERV;
985*7c478bd9Sstevel@tonic-gate 		pdom->ping_clnt = (CLIENT *)NULL;
986*7c478bd9Sstevel@tonic-gate 		pdom->dom_report_success = -1;
987*7c478bd9Sstevel@tonic-gate 		pdom->dom_broadcaster_pid = 0;
988*7c478bd9Sstevel@tonic-gate 		pdom->broadcaster_pipe = 0;
989*7c478bd9Sstevel@tonic-gate 		pdom->bindfile = -1;
990*7c478bd9Sstevel@tonic-gate 		pdom->lastping.tv_sec = 0;
991*7c478bd9Sstevel@tonic-gate 		pdom->lastping.tv_usec = 0; /* require ping */
992*7c478bd9Sstevel@tonic-gate 		pdom->cache_fp = 0;
993*7c478bd9Sstevel@tonic-gate 		sprintf(buf, "%s/%s/cache_binding", BINDING, pdom->dom_name);
994*7c478bd9Sstevel@tonic-gate 		pdom->cache_file = strdup(buf);
995*7c478bd9Sstevel@tonic-gate 		/*
996*7c478bd9Sstevel@tonic-gate 		 *  We don't give an error if pdom->cache_file is not set.
997*7c478bd9Sstevel@tonic-gate 		 *  If we got null (out of memory), then we just won't use
998*7c478bd9Sstevel@tonic-gate 		 *  the cache file in cache_binding() (assuming the
999*7c478bd9Sstevel@tonic-gate 		 *  application gets that far.
1000*7c478bd9Sstevel@tonic-gate 		 */
1001*7c478bd9Sstevel@tonic-gate 	}
1002*7c478bd9Sstevel@tonic-gate 	else
1003*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "ypbind_point_to_domain: malloc failed\n");
1004*7c478bd9Sstevel@tonic-gate 
1005*7c478bd9Sstevel@tonic-gate 	return (pdom);
1006*7c478bd9Sstevel@tonic-gate }
1007*7c478bd9Sstevel@tonic-gate 
1008*7c478bd9Sstevel@tonic-gate static void
ypbind_ping(pdom)1009*7c478bd9Sstevel@tonic-gate ypbind_ping(pdom)
1010*7c478bd9Sstevel@tonic-gate struct domain *pdom;
1011*7c478bd9Sstevel@tonic-gate {
1012*7c478bd9Sstevel@tonic-gate 	struct timeval timeout;
1013*7c478bd9Sstevel@tonic-gate 	int	vers;
1014*7c478bd9Sstevel@tonic-gate 	int	isok;
1015*7c478bd9Sstevel@tonic-gate 
1016*7c478bd9Sstevel@tonic-gate 	if (pdom->dom_boundp == FALSE)
1017*7c478bd9Sstevel@tonic-gate 		return;
1018*7c478bd9Sstevel@tonic-gate 	vers = pdom->dom_vers;
1019*7c478bd9Sstevel@tonic-gate 
1020*7c478bd9Sstevel@tonic-gate 	if (pdom->ping_clnt == (CLIENT *) NULL) {
1021*7c478bd9Sstevel@tonic-gate 		pdom->ping_clnt = __nis_clnt_create(RPC_ANYFD,
1022*7c478bd9Sstevel@tonic-gate 					pdom->dom_binding->ypbind_nconf, 0,
1023*7c478bd9Sstevel@tonic-gate 					pdom->dom_binding->ypbind_svcaddr, 0,
1024*7c478bd9Sstevel@tonic-gate 					YPPROG, vers, 0, 0);
1025*7c478bd9Sstevel@tonic-gate 	}
1026*7c478bd9Sstevel@tonic-gate 
1027*7c478bd9Sstevel@tonic-gate 	if (pdom->ping_clnt == (CLIENT *) NULL) {
1028*7c478bd9Sstevel@tonic-gate 		perror("clnt_tli_create");
1029*7c478bd9Sstevel@tonic-gate 		clnt_pcreateerror("ypbind_ping()");
1030*7c478bd9Sstevel@tonic-gate 		pdom->dom_boundp = FALSE;
1031*7c478bd9Sstevel@tonic-gate 		pdom->dom_error = YPBIND_ERR_NOSERV;
1032*7c478bd9Sstevel@tonic-gate 		return;
1033*7c478bd9Sstevel@tonic-gate 	}
1034*7c478bd9Sstevel@tonic-gate 
1035*7c478bd9Sstevel@tonic-gate 
1036*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
1037*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "ypbind: ypbind_ping()\n");
1038*7c478bd9Sstevel@tonic-gate #endif
1039*7c478bd9Sstevel@tonic-gate 	timeout.tv_sec = PINGTOTTIM;
1040*7c478bd9Sstevel@tonic-gate 	timeout.tv_usec =  0;
1041*7c478bd9Sstevel@tonic-gate 	if (clnt_call(pdom->ping_clnt,
1042*7c478bd9Sstevel@tonic-gate 	    YPPROC_DOMAIN, (xdrproc_t)xdr_ypdomain_wrap_string,
1043*7c478bd9Sstevel@tonic-gate 		(char *)&pdom->dom_name, xdr_int, (char *)&isok,
1044*7c478bd9Sstevel@tonic-gate 		timeout) == RPC_SUCCESS) {
1045*7c478bd9Sstevel@tonic-gate 			pdom->dom_boundp = isok;
1046*7c478bd9Sstevel@tonic-gate 			pdom->dom_binding->ypbind_lo_vers = vers;
1047*7c478bd9Sstevel@tonic-gate 			pdom->dom_binding->ypbind_hi_vers = vers;
1048*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
1049*7c478bd9Sstevel@tonic-gate 	fprintf(stderr,
1050*7c478bd9Sstevel@tonic-gate 		"Server pinged successfully, supports versions %d thru %d\n",
1051*7c478bd9Sstevel@tonic-gate 		pdom->dom_binding->ypbind_lo_vers,
1052*7c478bd9Sstevel@tonic-gate 		pdom->dom_binding->ypbind_hi_vers);
1053*7c478bd9Sstevel@tonic-gate #endif
1054*7c478bd9Sstevel@tonic-gate 	} else {
1055*7c478bd9Sstevel@tonic-gate 		clnt_perror(pdom->ping_clnt, "ping");
1056*7c478bd9Sstevel@tonic-gate 		pdom->dom_boundp = FALSE;
1057*7c478bd9Sstevel@tonic-gate 		pdom->dom_error = YPBIND_ERR_NOSERV;
1058*7c478bd9Sstevel@tonic-gate 	}
1059*7c478bd9Sstevel@tonic-gate 	(void) gettimeofday(&(pdom->lastping), NULL);
1060*7c478bd9Sstevel@tonic-gate 	if (pdom->ping_clnt)
1061*7c478bd9Sstevel@tonic-gate 		clnt_destroy(pdom->ping_clnt);
1062*7c478bd9Sstevel@tonic-gate 	pdom->ping_clnt = (CLIENT *)NULL;
1063*7c478bd9Sstevel@tonic-gate 	if (pdom->dom_boundp)
1064*7c478bd9Sstevel@tonic-gate 		cache_binding(pdom);
1065*7c478bd9Sstevel@tonic-gate }
1066*7c478bd9Sstevel@tonic-gate 
1067*7c478bd9Sstevel@tonic-gate static struct ypbind_binding *
dup_ypbind_binding(a)1068*7c478bd9Sstevel@tonic-gate dup_ypbind_binding(a)
1069*7c478bd9Sstevel@tonic-gate struct ypbind_binding *a;
1070*7c478bd9Sstevel@tonic-gate {
1071*7c478bd9Sstevel@tonic-gate 	struct ypbind_binding *b;
1072*7c478bd9Sstevel@tonic-gate 	struct netconfig *nca, *ncb;
1073*7c478bd9Sstevel@tonic-gate 	struct netbuf *nxa, *nxb;
1074*7c478bd9Sstevel@tonic-gate 	int i;
1075*7c478bd9Sstevel@tonic-gate 
1076*7c478bd9Sstevel@tonic-gate 	b = (struct ypbind_binding *)calloc(1, sizeof (*b));
1077*7c478bd9Sstevel@tonic-gate 	if (b == NULL)
1078*7c478bd9Sstevel@tonic-gate 		return (b);
1079*7c478bd9Sstevel@tonic-gate 	b->ypbind_hi_vers = a->ypbind_hi_vers;
1080*7c478bd9Sstevel@tonic-gate 	b->ypbind_lo_vers = a->ypbind_lo_vers;
1081*7c478bd9Sstevel@tonic-gate 	b->ypbind_servername =
1082*7c478bd9Sstevel@tonic-gate 		a->ypbind_servername ? strdup(a->ypbind_servername) : NULL;
1083*7c478bd9Sstevel@tonic-gate 	ncb = (b->ypbind_nconf =
1084*7c478bd9Sstevel@tonic-gate 		(struct netconfig *)calloc(1, sizeof (struct netconfig)));
1085*7c478bd9Sstevel@tonic-gate 	nxb = (b->ypbind_svcaddr =
1086*7c478bd9Sstevel@tonic-gate 		(struct netbuf *)calloc(1, sizeof (struct netbuf)));
1087*7c478bd9Sstevel@tonic-gate 	nca = a->ypbind_nconf;
1088*7c478bd9Sstevel@tonic-gate 	nxa = a->ypbind_svcaddr;
1089*7c478bd9Sstevel@tonic-gate 	ncb->nc_flag = nca->nc_flag;
1090*7c478bd9Sstevel@tonic-gate 	ncb->nc_protofmly =
1091*7c478bd9Sstevel@tonic-gate 		nca->nc_protofmly ? strdup(nca->nc_protofmly) : NULL;
1092*7c478bd9Sstevel@tonic-gate 	ncb->nc_proto =
1093*7c478bd9Sstevel@tonic-gate 		nca->nc_proto ? strdup(nca->nc_proto) : NULL;
1094*7c478bd9Sstevel@tonic-gate 	ncb->nc_semantics = nca->nc_semantics;
1095*7c478bd9Sstevel@tonic-gate 	ncb->nc_netid =
1096*7c478bd9Sstevel@tonic-gate 		nca->nc_netid ? strdup(nca->nc_netid) : NULL;
1097*7c478bd9Sstevel@tonic-gate 	ncb->nc_device =
1098*7c478bd9Sstevel@tonic-gate 		nca->nc_device ? strdup(nca->nc_device) : NULL;
1099*7c478bd9Sstevel@tonic-gate 	ncb->nc_nlookups = nca->nc_nlookups;
1100*7c478bd9Sstevel@tonic-gate 	ncb->nc_lookups = (char **)calloc(nca->nc_nlookups, sizeof (char *));
1101*7c478bd9Sstevel@tonic-gate 	if (ncb->nc_lookups == NULL) {
1102*7c478bd9Sstevel@tonic-gate 		if (ncb->nc_device)
1103*7c478bd9Sstevel@tonic-gate 			free(ncb->nc_device);
1104*7c478bd9Sstevel@tonic-gate 		if (ncb->nc_netid)
1105*7c478bd9Sstevel@tonic-gate 			free(ncb->nc_netid);
1106*7c478bd9Sstevel@tonic-gate 		if (ncb->nc_proto)
1107*7c478bd9Sstevel@tonic-gate 			free(ncb->nc_proto);
1108*7c478bd9Sstevel@tonic-gate 		if (ncb->nc_protofmly)
1109*7c478bd9Sstevel@tonic-gate 			free(ncb->nc_protofmly);
1110*7c478bd9Sstevel@tonic-gate 		if (nxb)
1111*7c478bd9Sstevel@tonic-gate 			free(nxb);
1112*7c478bd9Sstevel@tonic-gate 		if (ncb)
1113*7c478bd9Sstevel@tonic-gate 			free(ncb);
1114*7c478bd9Sstevel@tonic-gate 		if (b->ypbind_servername)
1115*7c478bd9Sstevel@tonic-gate 			free(b->ypbind_servername);
1116*7c478bd9Sstevel@tonic-gate 		if (b)
1117*7c478bd9Sstevel@tonic-gate 			free(b);
1118*7c478bd9Sstevel@tonic-gate 		return (NULL);
1119*7c478bd9Sstevel@tonic-gate 	}
1120*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < nca->nc_nlookups; i++)
1121*7c478bd9Sstevel@tonic-gate 		ncb->nc_lookups[i] =
1122*7c478bd9Sstevel@tonic-gate 			nca->nc_lookups[i] ? strdup(nca->nc_lookups[i]) : NULL;
1123*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < 8; i++)
1124*7c478bd9Sstevel@tonic-gate 		ncb->nc_unused[i] = nca->nc_unused[i];
1125*7c478bd9Sstevel@tonic-gate 	nxb->maxlen = nxa->maxlen;
1126*7c478bd9Sstevel@tonic-gate 	nxb->len = nxa->len;
1127*7c478bd9Sstevel@tonic-gate 	nxb->buf = malloc(nxa->maxlen);
1128*7c478bd9Sstevel@tonic-gate 	if (nxb->buf == NULL) {
1129*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < nca->nc_nlookups; i++)
1130*7c478bd9Sstevel@tonic-gate 			if (ncb->nc_lookups[i])
1131*7c478bd9Sstevel@tonic-gate 				free(ncb->nc_lookups[i]);
1132*7c478bd9Sstevel@tonic-gate 		free(ncb->nc_lookups);
1133*7c478bd9Sstevel@tonic-gate 		if (ncb->nc_device)
1134*7c478bd9Sstevel@tonic-gate 			free(ncb->nc_device);
1135*7c478bd9Sstevel@tonic-gate 		if (ncb->nc_netid)
1136*7c478bd9Sstevel@tonic-gate 			free(ncb->nc_netid);
1137*7c478bd9Sstevel@tonic-gate 		if (ncb->nc_proto)
1138*7c478bd9Sstevel@tonic-gate 			free(ncb->nc_proto);
1139*7c478bd9Sstevel@tonic-gate 		if (ncb->nc_protofmly)
1140*7c478bd9Sstevel@tonic-gate 			free(ncb->nc_protofmly);
1141*7c478bd9Sstevel@tonic-gate 		if (nxb)
1142*7c478bd9Sstevel@tonic-gate 			free(nxb);
1143*7c478bd9Sstevel@tonic-gate 		if (ncb)
1144*7c478bd9Sstevel@tonic-gate 			free(ncb);
1145*7c478bd9Sstevel@tonic-gate 		if (b->ypbind_servername)
1146*7c478bd9Sstevel@tonic-gate 			free(b->ypbind_servername);
1147*7c478bd9Sstevel@tonic-gate 		if (b)
1148*7c478bd9Sstevel@tonic-gate 			free(b);
1149*7c478bd9Sstevel@tonic-gate 		return (NULL);
1150*7c478bd9Sstevel@tonic-gate 	}
1151*7c478bd9Sstevel@tonic-gate 	memcpy(nxb->buf, nxa->buf, nxb->len);
1152*7c478bd9Sstevel@tonic-gate 	return (b);
1153*7c478bd9Sstevel@tonic-gate }
1154*7c478bd9Sstevel@tonic-gate 
1155*7c478bd9Sstevel@tonic-gate static void
free_ypbind_binding(b)1156*7c478bd9Sstevel@tonic-gate free_ypbind_binding(b)
1157*7c478bd9Sstevel@tonic-gate struct ypbind_binding *b;
1158*7c478bd9Sstevel@tonic-gate {
1159*7c478bd9Sstevel@tonic-gate 	if (b == NULL)
1160*7c478bd9Sstevel@tonic-gate 		return;
1161*7c478bd9Sstevel@tonic-gate 	netdir_free((char *)b->ypbind_svcaddr, ND_ADDR);
1162*7c478bd9Sstevel@tonic-gate 	free(b->ypbind_servername);
1163*7c478bd9Sstevel@tonic-gate 	freenetconfigent(b->ypbind_nconf);
1164*7c478bd9Sstevel@tonic-gate 	free(b);
1165*7c478bd9Sstevel@tonic-gate }
1166*7c478bd9Sstevel@tonic-gate 
1167*7c478bd9Sstevel@tonic-gate /*
1168*7c478bd9Sstevel@tonic-gate  * Preloads teh default domain's domain binding. Domain binding for the
1169*7c478bd9Sstevel@tonic-gate  * local node's default domain for ypserv version 2 (YPVERS) will be
1170*7c478bd9Sstevel@tonic-gate  * set up. This may make it a little slower to start ypbind during
1171*7c478bd9Sstevel@tonic-gate  * boot time, but would make it easy on other domains that rely on
1172*7c478bd9Sstevel@tonic-gate  * this binding.
1173*7c478bd9Sstevel@tonic-gate  */
1174*7c478bd9Sstevel@tonic-gate void
ypbind_init_default()1175*7c478bd9Sstevel@tonic-gate ypbind_init_default()
1176*7c478bd9Sstevel@tonic-gate {
1177*7c478bd9Sstevel@tonic-gate 	char domain[256];
1178*7c478bd9Sstevel@tonic-gate 	struct domain *cur_domain;
1179*7c478bd9Sstevel@tonic-gate 
1180*7c478bd9Sstevel@tonic-gate 	if (getdomainname(domain, 256) == 0) {
1181*7c478bd9Sstevel@tonic-gate 		cur_domain = ypbind_point_to_domain(domain);
1182*7c478bd9Sstevel@tonic-gate 
1183*7c478bd9Sstevel@tonic-gate 		if (cur_domain == (struct domain *)NULL) {
1184*7c478bd9Sstevel@tonic-gate 			abort();
1185*7c478bd9Sstevel@tonic-gate 		}
1186*7c478bd9Sstevel@tonic-gate 		(void) pong_servers(cur_domain);
1187*7c478bd9Sstevel@tonic-gate 	}
1188*7c478bd9Sstevel@tonic-gate }
1189*7c478bd9Sstevel@tonic-gate 
1190*7c478bd9Sstevel@tonic-gate bool_t
xdr_ypbind_binding_2(xdrs,objp)1191*7c478bd9Sstevel@tonic-gate xdr_ypbind_binding_2(xdrs, objp)
1192*7c478bd9Sstevel@tonic-gate 	register XDR *xdrs;
1193*7c478bd9Sstevel@tonic-gate 	ypbind_binding_2 *objp;
1194*7c478bd9Sstevel@tonic-gate {
1195*7c478bd9Sstevel@tonic-gate 	if (!xdr_opaque(xdrs, (char *)&(objp->ypbind_binding_addr), 4))
1196*7c478bd9Sstevel@tonic-gate 		return (FALSE);
1197*7c478bd9Sstevel@tonic-gate 	if (!xdr_opaque(xdrs, (char *)&(objp->ypbind_binding_port), 2))
1198*7c478bd9Sstevel@tonic-gate 		return (FALSE);
1199*7c478bd9Sstevel@tonic-gate 	return (TRUE);
1200*7c478bd9Sstevel@tonic-gate }
1201*7c478bd9Sstevel@tonic-gate 
1202*7c478bd9Sstevel@tonic-gate bool_t
xdr_ypbind_resp_2(xdrs,objp)1203*7c478bd9Sstevel@tonic-gate xdr_ypbind_resp_2(xdrs, objp)
1204*7c478bd9Sstevel@tonic-gate 	register XDR *xdrs;
1205*7c478bd9Sstevel@tonic-gate 	ypbind_resp_2 *objp;
1206*7c478bd9Sstevel@tonic-gate {
1207*7c478bd9Sstevel@tonic-gate 	if (!xdr_ypbind_resptype(xdrs, &objp->ypbind_status))
1208*7c478bd9Sstevel@tonic-gate 		return (FALSE);
1209*7c478bd9Sstevel@tonic-gate 	switch (objp->ypbind_status) {
1210*7c478bd9Sstevel@tonic-gate 	case YPBIND_FAIL_VAL:
1211*7c478bd9Sstevel@tonic-gate 		if (!xdr_u_long(xdrs, &objp->ypbind_respbody_2.ypbind_error))
1212*7c478bd9Sstevel@tonic-gate 			return (FALSE);
1213*7c478bd9Sstevel@tonic-gate 		break;
1214*7c478bd9Sstevel@tonic-gate 	case YPBIND_SUCC_VAL:
1215*7c478bd9Sstevel@tonic-gate 		if (!xdr_ypbind_binding_2(xdrs,
1216*7c478bd9Sstevel@tonic-gate 		    &objp->ypbind_respbody_2.ypbind_bindinfo))
1217*7c478bd9Sstevel@tonic-gate 			return (FALSE);
1218*7c478bd9Sstevel@tonic-gate 		break;
1219*7c478bd9Sstevel@tonic-gate 	default:
1220*7c478bd9Sstevel@tonic-gate 		return (FALSE);
1221*7c478bd9Sstevel@tonic-gate 	}
1222*7c478bd9Sstevel@tonic-gate 	return (TRUE);
1223*7c478bd9Sstevel@tonic-gate }
1224*7c478bd9Sstevel@tonic-gate 
1225*7c478bd9Sstevel@tonic-gate /*
1226*7c478bd9Sstevel@tonic-gate  *  The following is some caching code to improve the performance of
1227*7c478bd9Sstevel@tonic-gate  *  yp clients.  In the days of yore, a client would talk to rpcbind
1228*7c478bd9Sstevel@tonic-gate  *  to get the address for ypbind, then talk to ypbind to get the
1229*7c478bd9Sstevel@tonic-gate  *  address of the server.  If a lot of clients are doing this at
1230*7c478bd9Sstevel@tonic-gate  *  the same time, then rpcbind and ypbind get bogged down and clients
1231*7c478bd9Sstevel@tonic-gate  *  start to time out.
1232*7c478bd9Sstevel@tonic-gate  *
1233*7c478bd9Sstevel@tonic-gate  *  We cache two things:  the current address for ypserv, and the
1234*7c478bd9Sstevel@tonic-gate  *  transport addresses for talking to ypbind.  These are saved in
1235*7c478bd9Sstevel@tonic-gate  *  files in /var/yp.  To get the address of ypserv, the client opens
1236*7c478bd9Sstevel@tonic-gate  *  a file and reads the address.  It does not have to talk to rpcbind
1237*7c478bd9Sstevel@tonic-gate  *  or ypbind.  If this file is not available, then it can read the
1238*7c478bd9Sstevel@tonic-gate  *  the transport address for talking to ypbind without bothering
1239*7c478bd9Sstevel@tonic-gate  *  rpcbind.  If this also fails, then it uses the old method of
1240*7c478bd9Sstevel@tonic-gate  *  talking to rpcbind and then ypbind.
1241*7c478bd9Sstevel@tonic-gate  *
1242*7c478bd9Sstevel@tonic-gate  *  We lock the first byte of the cache files after writing to them.
1243*7c478bd9Sstevel@tonic-gate  *  This indicates to the client that they contents are valid.  The
1244*7c478bd9Sstevel@tonic-gate  *  client should test the lock.  If the lock is held, then it can
1245*7c478bd9Sstevel@tonic-gate  *  use the contents.  If the lock test fails, then the contents should
1246*7c478bd9Sstevel@tonic-gate  *  be ignored.
1247*7c478bd9Sstevel@tonic-gate  */
1248*7c478bd9Sstevel@tonic-gate 
1249*7c478bd9Sstevel@tonic-gate /*
1250*7c478bd9Sstevel@tonic-gate  *  Cache new binding information for a domain in a file.  If the
1251*7c478bd9Sstevel@tonic-gate  *  new binding is the same as the old, then we skip it.  We xdr
1252*7c478bd9Sstevel@tonic-gate  *  a 'ypbind_resp', which is what would be returned by a call to
1253*7c478bd9Sstevel@tonic-gate  *  the YBINDPROCP_DOMAIN service.  We xdr the data because it is
1254*7c478bd9Sstevel@tonic-gate  *  easier than writing the data out field by field.  It would be
1255*7c478bd9Sstevel@tonic-gate  *  nice if there were an xdrfd_create() that was similar to
1256*7c478bd9Sstevel@tonic-gate  *  xdrstdio_create().  Instead, we do an fdopen and use xdrstdio_create().
1257*7c478bd9Sstevel@tonic-gate  */
1258*7c478bd9Sstevel@tonic-gate void
cache_binding(pdom)1259*7c478bd9Sstevel@tonic-gate cache_binding(pdom)
1260*7c478bd9Sstevel@tonic-gate 	struct domain *pdom;
1261*7c478bd9Sstevel@tonic-gate {
1262*7c478bd9Sstevel@tonic-gate 	int st;
1263*7c478bd9Sstevel@tonic-gate 	int fd;
1264*7c478bd9Sstevel@tonic-gate 	XDR xdrs;
1265*7c478bd9Sstevel@tonic-gate 	struct ypbind_resp resp;
1266*7c478bd9Sstevel@tonic-gate 
1267*7c478bd9Sstevel@tonic-gate 	if (!cache_okay)
1268*7c478bd9Sstevel@tonic-gate 		return;
1269*7c478bd9Sstevel@tonic-gate 
1270*7c478bd9Sstevel@tonic-gate 	/* if the domain doesn't have a cache file, then skip it */
1271*7c478bd9Sstevel@tonic-gate 	if (pdom->cache_file == 0)
1272*7c478bd9Sstevel@tonic-gate 		return;
1273*7c478bd9Sstevel@tonic-gate 
1274*7c478bd9Sstevel@tonic-gate 	/*
1275*7c478bd9Sstevel@tonic-gate 	 *  If we already had a cache file for this domain, remove it.  If
1276*7c478bd9Sstevel@tonic-gate 	 *  a client just started accessing it, then it will either find
1277*7c478bd9Sstevel@tonic-gate 	 *  it unlocked (and not use it), or continue to use it with
1278*7c478bd9Sstevel@tonic-gate 	 *  old information.  This is not a problem, the client will
1279*7c478bd9Sstevel@tonic-gate 	 *  either fail to talk to ypserv and try to bind again, or
1280*7c478bd9Sstevel@tonic-gate 	 *  will continue to use the old server.
1281*7c478bd9Sstevel@tonic-gate 	 */
1282*7c478bd9Sstevel@tonic-gate 	if (pdom->cache_fp) {
1283*7c478bd9Sstevel@tonic-gate 		fclose(pdom->cache_fp);    /* automatically unlocks */
1284*7c478bd9Sstevel@tonic-gate 		unlink(pdom->cache_file);
1285*7c478bd9Sstevel@tonic-gate 		pdom->cache_fp = 0;
1286*7c478bd9Sstevel@tonic-gate 	}
1287*7c478bd9Sstevel@tonic-gate 
1288*7c478bd9Sstevel@tonic-gate 	fd = open(pdom->cache_file, O_CREAT|O_WRONLY, 0444);
1289*7c478bd9Sstevel@tonic-gate 	if (fd == -1)
1290*7c478bd9Sstevel@tonic-gate 		return;
1291*7c478bd9Sstevel@tonic-gate 
1292*7c478bd9Sstevel@tonic-gate 	pdom->cache_fp = fdopen(fd, "w");
1293*7c478bd9Sstevel@tonic-gate 	if (pdom->cache_fp == 0) {
1294*7c478bd9Sstevel@tonic-gate 		close(fd);
1295*7c478bd9Sstevel@tonic-gate 		return;
1296*7c478bd9Sstevel@tonic-gate 	}
1297*7c478bd9Sstevel@tonic-gate 
1298*7c478bd9Sstevel@tonic-gate 	xdrstdio_create(&xdrs, pdom->cache_fp, XDR_ENCODE);
1299*7c478bd9Sstevel@tonic-gate 	resp.ypbind_status = YPBIND_SUCC_VAL;
1300*7c478bd9Sstevel@tonic-gate 	resp.ypbind_resp_u.ypbind_bindinfo = pdom->dom_binding;
1301*7c478bd9Sstevel@tonic-gate 
1302*7c478bd9Sstevel@tonic-gate 	if (!xdr_ypbind_resp(&xdrs, &resp)) {
1303*7c478bd9Sstevel@tonic-gate 		xdr_destroy(&xdrs);
1304*7c478bd9Sstevel@tonic-gate 		unlink(pdom->cache_file);
1305*7c478bd9Sstevel@tonic-gate 		fclose(pdom->cache_fp);
1306*7c478bd9Sstevel@tonic-gate 		pdom->cache_fp = 0;
1307*7c478bd9Sstevel@tonic-gate 		return;
1308*7c478bd9Sstevel@tonic-gate 	}
1309*7c478bd9Sstevel@tonic-gate 	xdr_destroy(&xdrs);    /* flushes xdr but leaves fp open */
1310*7c478bd9Sstevel@tonic-gate 
1311*7c478bd9Sstevel@tonic-gate 	/* we lock the first byte to indicate that the file is valid */
1312*7c478bd9Sstevel@tonic-gate 	lseek(fd, 0L, SEEK_SET);
1313*7c478bd9Sstevel@tonic-gate 	st = lockf(fd, F_LOCK, 1);
1314*7c478bd9Sstevel@tonic-gate 	if (st == -1) {
1315*7c478bd9Sstevel@tonic-gate 		unlink(pdom->cache_file);
1316*7c478bd9Sstevel@tonic-gate 		fclose(pdom->cache_fp);
1317*7c478bd9Sstevel@tonic-gate 		pdom->cache_fp = 0;
1318*7c478bd9Sstevel@tonic-gate 	}
1319*7c478bd9Sstevel@tonic-gate }
1320*7c478bd9Sstevel@tonic-gate 
1321*7c478bd9Sstevel@tonic-gate void
uncache_binding(pdom)1322*7c478bd9Sstevel@tonic-gate uncache_binding(pdom)
1323*7c478bd9Sstevel@tonic-gate 	struct domain *pdom;
1324*7c478bd9Sstevel@tonic-gate {
1325*7c478bd9Sstevel@tonic-gate 	if (!cache_okay)
1326*7c478bd9Sstevel@tonic-gate 		return;
1327*7c478bd9Sstevel@tonic-gate 
1328*7c478bd9Sstevel@tonic-gate 	if (pdom->cache_fp != 0) {
1329*7c478bd9Sstevel@tonic-gate 		unlink(pdom->cache_file);
1330*7c478bd9Sstevel@tonic-gate 		fclose(pdom->cache_fp);
1331*7c478bd9Sstevel@tonic-gate 		pdom->cache_fp = 0;
1332*7c478bd9Sstevel@tonic-gate 	}
1333*7c478bd9Sstevel@tonic-gate }
1334*7c478bd9Sstevel@tonic-gate 
1335*7c478bd9Sstevel@tonic-gate /*
1336*7c478bd9Sstevel@tonic-gate  *  Cache a transport address for talking to ypbind.  We convert the
1337*7c478bd9Sstevel@tonic-gate  *  transport address to a universal address and save that in a file.
1338*7c478bd9Sstevel@tonic-gate  *  The file lives in the binding directory because it does not depend
1339*7c478bd9Sstevel@tonic-gate  *  on the domain.
1340*7c478bd9Sstevel@tonic-gate  */
1341*7c478bd9Sstevel@tonic-gate void
cache_transport(nconf,xprt,vers)1342*7c478bd9Sstevel@tonic-gate cache_transport(nconf, xprt, vers)
1343*7c478bd9Sstevel@tonic-gate 	struct netconfig *nconf;
1344*7c478bd9Sstevel@tonic-gate 	SVCXPRT *xprt;
1345*7c478bd9Sstevel@tonic-gate 	int vers;
1346*7c478bd9Sstevel@tonic-gate {
1347*7c478bd9Sstevel@tonic-gate 	char filename[300];
1348*7c478bd9Sstevel@tonic-gate 	char *uaddr;
1349*7c478bd9Sstevel@tonic-gate 	int fd;
1350*7c478bd9Sstevel@tonic-gate 	int st;
1351*7c478bd9Sstevel@tonic-gate 	int len;
1352*7c478bd9Sstevel@tonic-gate 
1353*7c478bd9Sstevel@tonic-gate 	if (!cache_okay)
1354*7c478bd9Sstevel@tonic-gate 		return;
1355*7c478bd9Sstevel@tonic-gate 
1356*7c478bd9Sstevel@tonic-gate 	sprintf(filename, "%s/xprt.%s.%d",
1357*7c478bd9Sstevel@tonic-gate 		BINDING, nconf->nc_netid, vers);
1358*7c478bd9Sstevel@tonic-gate 
1359*7c478bd9Sstevel@tonic-gate 	unlink(filename);    /* remove any old version */
1360*7c478bd9Sstevel@tonic-gate 
1361*7c478bd9Sstevel@tonic-gate 	uaddr = taddr2uaddr(nconf, &xprt->xp_ltaddr);
1362*7c478bd9Sstevel@tonic-gate 	if (uaddr == 0)
1363*7c478bd9Sstevel@tonic-gate 		return;
1364*7c478bd9Sstevel@tonic-gate 
1365*7c478bd9Sstevel@tonic-gate 	fd = open(filename, O_CREAT|O_WRONLY, 0444);    /* readable by all */
1366*7c478bd9Sstevel@tonic-gate 	if (fd == -1) {
1367*7c478bd9Sstevel@tonic-gate 		free(uaddr);
1368*7c478bd9Sstevel@tonic-gate 		return;
1369*7c478bd9Sstevel@tonic-gate 	}
1370*7c478bd9Sstevel@tonic-gate 
1371*7c478bd9Sstevel@tonic-gate 	len = strlen(uaddr) + 1;    /* include terminating null */
1372*7c478bd9Sstevel@tonic-gate 	st = write(fd, uaddr, len);
1373*7c478bd9Sstevel@tonic-gate 	if (st != len) {
1374*7c478bd9Sstevel@tonic-gate 		close(fd);
1375*7c478bd9Sstevel@tonic-gate 		unlink(filename);
1376*7c478bd9Sstevel@tonic-gate 		free(uaddr);
1377*7c478bd9Sstevel@tonic-gate 		return;
1378*7c478bd9Sstevel@tonic-gate 	}
1379*7c478bd9Sstevel@tonic-gate 
1380*7c478bd9Sstevel@tonic-gate 	free(uaddr);
1381*7c478bd9Sstevel@tonic-gate 
1382*7c478bd9Sstevel@tonic-gate 	/* we lock the first byte to indicate that the file is valid */
1383*7c478bd9Sstevel@tonic-gate 	lseek(fd, 0L, SEEK_SET);
1384*7c478bd9Sstevel@tonic-gate 	st = lockf(fd, F_LOCK, 1);
1385*7c478bd9Sstevel@tonic-gate 	if (st == -1) {
1386*7c478bd9Sstevel@tonic-gate 		close(fd);
1387*7c478bd9Sstevel@tonic-gate 		unlink(filename);
1388*7c478bd9Sstevel@tonic-gate 	}
1389*7c478bd9Sstevel@tonic-gate }
1390*7c478bd9Sstevel@tonic-gate 
1391*7c478bd9Sstevel@tonic-gate /*
1392*7c478bd9Sstevel@tonic-gate  *  Create a file that clients can check to see if we are running.
1393*7c478bd9Sstevel@tonic-gate  */
1394*7c478bd9Sstevel@tonic-gate void
cache_pid()1395*7c478bd9Sstevel@tonic-gate cache_pid()
1396*7c478bd9Sstevel@tonic-gate {
1397*7c478bd9Sstevel@tonic-gate 	char filename[300];
1398*7c478bd9Sstevel@tonic-gate 	char spid[15];
1399*7c478bd9Sstevel@tonic-gate 	int fd;
1400*7c478bd9Sstevel@tonic-gate 	int st;
1401*7c478bd9Sstevel@tonic-gate 	int len;
1402*7c478bd9Sstevel@tonic-gate 
1403*7c478bd9Sstevel@tonic-gate 	if (!cache_okay)
1404*7c478bd9Sstevel@tonic-gate 		return;
1405*7c478bd9Sstevel@tonic-gate 
1406*7c478bd9Sstevel@tonic-gate 	sprintf(filename, "%s/ypbind.pid", BINDING);
1407*7c478bd9Sstevel@tonic-gate 
1408*7c478bd9Sstevel@tonic-gate 	unlink(filename);    /* remove any old version */
1409*7c478bd9Sstevel@tonic-gate 
1410*7c478bd9Sstevel@tonic-gate 	fd = open(filename, O_CREAT|O_WRONLY, 0444);    /* readable by all */
1411*7c478bd9Sstevel@tonic-gate 	if (fd == -1) {
1412*7c478bd9Sstevel@tonic-gate 		return;
1413*7c478bd9Sstevel@tonic-gate 	}
1414*7c478bd9Sstevel@tonic-gate 
1415*7c478bd9Sstevel@tonic-gate 	sprintf(spid, "%d\n", getpid());
1416*7c478bd9Sstevel@tonic-gate 
1417*7c478bd9Sstevel@tonic-gate 	len = strlen(spid);
1418*7c478bd9Sstevel@tonic-gate 	st = write(fd, spid, len);
1419*7c478bd9Sstevel@tonic-gate 	if (st != len) {
1420*7c478bd9Sstevel@tonic-gate 		close(fd);
1421*7c478bd9Sstevel@tonic-gate 		unlink(filename);
1422*7c478bd9Sstevel@tonic-gate 		return;
1423*7c478bd9Sstevel@tonic-gate 	}
1424*7c478bd9Sstevel@tonic-gate 
1425*7c478bd9Sstevel@tonic-gate 	/* we lock the first byte to indicate that the file is valid */
1426*7c478bd9Sstevel@tonic-gate 	lseek(fd, 0L, SEEK_SET);
1427*7c478bd9Sstevel@tonic-gate 	st = lockf(fd, F_LOCK, 1);
1428*7c478bd9Sstevel@tonic-gate 	if (st == -1) {
1429*7c478bd9Sstevel@tonic-gate 		close(fd);
1430*7c478bd9Sstevel@tonic-gate 		unlink(filename);
1431*7c478bd9Sstevel@tonic-gate 	}
1432*7c478bd9Sstevel@tonic-gate 
1433*7c478bd9Sstevel@tonic-gate 	/* we keep 'fd' open so that the lock will continue to be held */
1434*7c478bd9Sstevel@tonic-gate }
1435*7c478bd9Sstevel@tonic-gate 
1436*7c478bd9Sstevel@tonic-gate /*
1437*7c478bd9Sstevel@tonic-gate  *  We are called once at startup (when the known_domains list is empty)
1438*7c478bd9Sstevel@tonic-gate  *  to clean up left-over files.  We are also called right before
1439*7c478bd9Sstevel@tonic-gate  *  exiting.  In the latter case case we don't bother closing descriptors
1440*7c478bd9Sstevel@tonic-gate  *  in the entries in the domain list because they will be closed
1441*7c478bd9Sstevel@tonic-gate  *  automatically (and unlocked) when we exit.
1442*7c478bd9Sstevel@tonic-gate  *
1443*7c478bd9Sstevel@tonic-gate  *  We ignore the cache_okay flag because it is important that we remove
1444*7c478bd9Sstevel@tonic-gate  *  all cache files (left-over files can temporarily confuse clients).
1445*7c478bd9Sstevel@tonic-gate  */
1446*7c478bd9Sstevel@tonic-gate void
clean_cache()1447*7c478bd9Sstevel@tonic-gate clean_cache()
1448*7c478bd9Sstevel@tonic-gate {
1449*7c478bd9Sstevel@tonic-gate 	struct domain *pdom;
1450*7c478bd9Sstevel@tonic-gate 	DIR *dir;
1451*7c478bd9Sstevel@tonic-gate 	struct dirent *dirent;
1452*7c478bd9Sstevel@tonic-gate 	char filename[300];
1453*7c478bd9Sstevel@tonic-gate 
1454*7c478bd9Sstevel@tonic-gate 	/* close and unlink cache files for each domain */
1455*7c478bd9Sstevel@tonic-gate 	for (pdom = known_domains; pdom != (struct domain *)NULL;
1456*7c478bd9Sstevel@tonic-gate 	    pdom = pdom->dom_pnext) {
1457*7c478bd9Sstevel@tonic-gate 		if (pdom->cache_file)
1458*7c478bd9Sstevel@tonic-gate 			unlink(pdom->cache_file);
1459*7c478bd9Sstevel@tonic-gate 	}
1460*7c478bd9Sstevel@tonic-gate 
1461*7c478bd9Sstevel@tonic-gate 	sprintf(filename, "%s/ypbind.pid", BINDING);
1462*7c478bd9Sstevel@tonic-gate 	unlink(filename);
1463*7c478bd9Sstevel@tonic-gate 
1464*7c478bd9Sstevel@tonic-gate 	dir = opendir(BINDING);
1465*7c478bd9Sstevel@tonic-gate 
1466*7c478bd9Sstevel@tonic-gate 	if (dir == NULL) {
1467*7c478bd9Sstevel@tonic-gate 		/* Directory could not be opened. */
1468*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "opendir failed with [%s]", strerror(errno));
1469*7c478bd9Sstevel@tonic-gate 		return;
1470*7c478bd9Sstevel@tonic-gate 	}
1471*7c478bd9Sstevel@tonic-gate 
1472*7c478bd9Sstevel@tonic-gate 	while ((dirent = readdir(dir)) != 0) {
1473*7c478bd9Sstevel@tonic-gate 		if (strncmp(dirent->d_name, "xprt.", 5) == 0) {
1474*7c478bd9Sstevel@tonic-gate 			sprintf(filename, "%s/%s", BINDING, dirent->d_name);
1475*7c478bd9Sstevel@tonic-gate 			unlink(filename);
1476*7c478bd9Sstevel@tonic-gate 			rewinddir(dir);  /* removing file may harm iteration */
1477*7c478bd9Sstevel@tonic-gate 		}
1478*7c478bd9Sstevel@tonic-gate 	}
1479*7c478bd9Sstevel@tonic-gate 	closedir(dir);
1480*7c478bd9Sstevel@tonic-gate }
1481*7c478bd9Sstevel@tonic-gate 
1482*7c478bd9Sstevel@tonic-gate /*
1483*7c478bd9Sstevel@tonic-gate  *  We only want to use the cache stuff on local file systems.
1484*7c478bd9Sstevel@tonic-gate  *  For remote file systems (e.g., NFS, the locking overhead is
1485*7c478bd9Sstevel@tonic-gate  *  worse than the overhead of loopback RPC, so the caching
1486*7c478bd9Sstevel@tonic-gate  *  wouldn't buy us anything.  In addition, if the remote locking
1487*7c478bd9Sstevel@tonic-gate  *  software isn't configured before we start, then we would
1488*7c478bd9Sstevel@tonic-gate  *  block when we try to lock.
1489*7c478bd9Sstevel@tonic-gate  *
1490*7c478bd9Sstevel@tonic-gate  *  We don't have a direct way to tell if a file system is local
1491*7c478bd9Sstevel@tonic-gate  *  or remote, so we assume it is local unless it is NFS.
1492*7c478bd9Sstevel@tonic-gate  */
1493*7c478bd9Sstevel@tonic-gate int
cache_check()1494*7c478bd9Sstevel@tonic-gate cache_check()
1495*7c478bd9Sstevel@tonic-gate {
1496*7c478bd9Sstevel@tonic-gate 	int st;
1497*7c478bd9Sstevel@tonic-gate 	struct statvfs stbuf;
1498*7c478bd9Sstevel@tonic-gate 
1499*7c478bd9Sstevel@tonic-gate 	st = statvfs(BINDING, &stbuf);
1500*7c478bd9Sstevel@tonic-gate 	if (st == -1) {
1501*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "statvfs failed with [%s]", strerror(errno));
1502*7c478bd9Sstevel@tonic-gate 		return (0);
1503*7c478bd9Sstevel@tonic-gate 	}
1504*7c478bd9Sstevel@tonic-gate 
1505*7c478bd9Sstevel@tonic-gate 	/* we use strncasecmp to get NFS, NFS3, nfs, nfs3, etc. */
1506*7c478bd9Sstevel@tonic-gate 	if (strncasecmp(stbuf.f_basetype, "NFS", 3) == 0)
1507*7c478bd9Sstevel@tonic-gate 		return (0);
1508*7c478bd9Sstevel@tonic-gate 	return (1);
1509*7c478bd9Sstevel@tonic-gate }
1510