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