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