xref: /illumos-gate/usr/src/cmd/ypcmd/yppoll.c (revision 4f364e7c95ee7fd9d5bbeddc1940e92405bb0e72)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  *
22  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /*	  All Rights Reserved   */
28 
29 /*
30  * Portions of this source code were derived from Berkeley
31  * under license from the Regents of the University of
32  * California.
33  */
34 
35 #pragma ident	"%Z%%M%	%I%	%E% SMI"
36 
37 /*
38  * This is a user command which asks a particular ypserv which version of a
39  * map it is using.  Usage is:
40  *
41  * yppoll [-h <host>] [-d <domainname>] mapname
42  *
43  * If the host is ommitted, the local host will be used.  If host is specified
44  * as an internet address, no yp services need to be locally available.
45  *
46  */
47 #include <stdio.h>
48 #include <ctype.h>
49 #include <rpc/rpc.h>
50 #include <rpcsvc/ypclnt.h>
51 #include <rpcsvc/yp_prot.h>
52 #include <netdir.h>
53 #include <arpa/inet.h>
54 #include "yp_b.h"
55 
56 #ifdef NULL
57 #undef NULL
58 #endif
59 #define	NULL 0
60 
61 #define	TIMEOUT 30			/* Total seconds for timeout */
62 
63 static int status = 0;				/* exit status */
64 static char *domain = NULL;
65 static char default_domain_name[YPMAXDOMAIN];
66 static char *map = NULL;
67 static char *host = NULL;
68 static char default_host_name[256];
69 
70 static char err_usage[] =
71 "Usage:\n\
72 	yppoll [ -h host ] [ -d domainname ] mapname\n\n";
73 static char err_bad_args[] =
74 	"Bad %s argument.\n";
75 static char err_cant_get_kname[] =
76 	"Can't get %s back from system call.\n";
77 static char err_null_kname[] =
78 	"%s hasn't been set on this machine.\n";
79 static char err_bad_hostname[] = "hostname";
80 static char err_bad_mapname[] = "mapname";
81 static char err_bad_domainname[] = "domainname";
82 static char err_bad_resp[] =
83 	"Ill-formed response returned from ypserv on host %s.\n";
84 
85 static void get_command_line_args();
86 static void getdomain();
87 static void getlochost();
88 static void getmapparms();
89 static void newresults();
90 static void getypserv();
91 
92 extern void exit();
93 extern int getdomainname();
94 extern int gethostname();
95 extern unsigned int strlen();
96 extern int strcmp();
97 
98 /*
99  * This is the mainline for the yppoll process.
100  */
101 
102 int
103 main(argc, argv)
104 	int argc;
105 	char **argv;
106 
107 {
108 	get_command_line_args(argc, argv);
109 
110 	if (!domain) {
111 		getdomain();
112 	}
113 
114 	if (!host) {
115 		getypserv();
116 	}
117 
118 	getmapparms();
119 	return (status);
120 }
121 
122 /*
123  * This does the command line argument processing.
124  */
125 static void
126 get_command_line_args(argc, argv)
127 	int argc;
128 	char **argv;
129 
130 {
131 	argv++;
132 
133 	while (--argc) {
134 
135 		if ((*argv)[0] == '-') {
136 
137 			switch ((*argv)[1]) {
138 
139 			case 'h':
140 
141 				if (argc > 1) {
142 					argv++;
143 					argc--;
144 					host = *argv;
145 					argv++;
146 
147 					if ((int)strlen(host) > 256) {
148 						(void) fprintf(stderr,
149 						    err_bad_args,
150 						    err_bad_hostname);
151 						exit(1);
152 					}
153 
154 				} else {
155 					(void) fprintf(stderr, err_usage);
156 					exit(1);
157 				}
158 
159 				break;
160 
161 			case 'd':
162 
163 				if (argc > 1) {
164 					argv++;
165 					argc--;
166 					domain = *argv;
167 					argv++;
168 
169 					if ((int)strlen(domain) > YPMAXDOMAIN) {
170 						(void) fprintf(stderr,
171 						    err_bad_args,
172 						    err_bad_domainname);
173 						exit(1);
174 					}
175 
176 				} else {
177 					(void) fprintf(stderr, err_usage);
178 					exit(1);
179 				}
180 
181 				break;
182 
183 			default:
184 				(void) fprintf(stderr, err_usage);
185 				exit(1);
186 
187 			}
188 
189 		} else {
190 			if (!map) {
191 				map = *argv;
192 
193 				if ((int)strlen(map) > YPMAXMAP) {
194 					(void) fprintf(stderr, err_bad_args,
195 					    err_bad_mapname);
196 					exit(1);
197 				}
198 
199 			} else {
200 				(void) fprintf(stderr, err_usage);
201 				exit(1);
202 			}
203 		}
204 	}
205 
206 	if (!map) {
207 		(void) fprintf(stderr, err_usage);
208 		exit(1);
209 	}
210 }
211 
212 /*
213  * This gets the local default domainname, and makes sure that it's set
214  * to something reasonable.  domain is set here.
215  */
216 static void
217 getdomain()
218 {
219 	if (!getdomainname(default_domain_name, YPMAXDOMAIN)) {
220 		domain = default_domain_name;
221 	} else {
222 		(void) fprintf(stderr, err_cant_get_kname, err_bad_domainname);
223 		exit(1);
224 	}
225 
226 	if ((int)strlen(domain) == 0) {
227 		(void) fprintf(stderr, err_null_kname, err_bad_domainname);
228 		exit(1);
229 	}
230 }
231 
232 /*
233  * This gets the local hostname back from the kernel
234  */
235 static void
236 getlochost()
237 {
238 
239 	if (! gethostname(default_host_name, 256)) {
240 		host = default_host_name;
241 	} else {
242 		(void) fprintf(stderr, err_cant_get_kname, err_bad_hostname);
243 		exit(1);
244 	}
245 }
246 
247 static void
248 getmapparms()
249 {
250 	CLIENT * map_clnt;
251 	struct ypresp_order oresp;
252 	struct ypreq_nokey req;
253 	struct ypresp_master mresp;
254 	struct ypresp_master *mresults = (struct ypresp_master *)NULL;
255 	struct ypresp_order *oresults = (struct ypresp_order *)NULL;
256 
257 	struct timeval timeout;
258 	enum clnt_stat s;
259 
260 	if ((map_clnt = clnt_create(host, YPPROG, YPVERS,
261 	    "netpath"))  == NULL) {
262 		(void) fprintf(stderr,
263 		    "Can't create connection to %s.\n", host);
264 		clnt_pcreateerror("Reason");
265 		exit(1);
266 	}
267 
268 	timeout.tv_sec = TIMEOUT;
269 	timeout.tv_usec = 0;
270 	req.domain = domain;
271 	req.map = map;
272 	mresp.master = NULL;
273 
274 	if (clnt_call(map_clnt, YPPROC_MASTER,  (xdrproc_t)xdr_ypreq_nokey,
275 		    (caddr_t)&req, (xdrproc_t)xdr_ypresp_master,
276 		    (caddr_t)&mresp, timeout) == RPC_SUCCESS) {
277 		mresults = &mresp;
278 		s = (enum clnt_stat) clnt_call(map_clnt, YPPROC_ORDER,
279 		    (xdrproc_t)xdr_ypreq_nokey, (char *)&req,
280 			(xdrproc_t)xdr_ypresp_order, (char *)&oresp, timeout);
281 
282 		if (s == RPC_SUCCESS) {
283 			oresults = &oresp;
284 			newresults(mresults, oresults);
285 		} else {
286 			(void) fprintf(stderr,
287 		"Can't make YPPROC_ORDER call to ypserv at %s.\n	",
288 				host);
289 			clnt_perror(map_clnt, "Reason");
290 			exit(1);
291 		}
292 
293 	} else {
294 		clnt_destroy(map_clnt);
295 	}
296 }
297 
298 static void
299 newresults(m, o)
300 	struct ypresp_master *m;
301 	struct ypresp_order *o;
302 {
303 	char *s_domok = "Domain %s is supported.\n";
304 	char *s_ook = "Map %s has order number %d.\n";
305 	char *s_mok = "The master server is %s.\n";
306 	char *s_mbad = "Can't get master for map %s.\n	Reason:  %s\n";
307 	char *s_obad = "Can't get order number for map %s.\n	Reason:  %s\n";
308 
309 	if (m->status == YP_TRUE && o->status == YP_TRUE) {
310 		(void) printf(s_domok, domain);
311 		(void) printf(s_ook, map, o->ordernum);
312 		(void) printf(s_mok, m->master);
313 	} else if (o->status == YP_TRUE)  {
314 		(void) printf(s_domok, domain);
315 		(void) printf(s_ook, map, o->ordernum);
316 		(void) fprintf(stderr, s_mbad, map,
317 		    yperr_string(ypprot_err(m->status)));
318 		status = 1;
319 	} else if (m->status == YP_TRUE)  {
320 		(void) printf(s_domok, domain);
321 		(void) fprintf(stderr, s_obad, map,
322 		    yperr_string(ypprot_err(o->status)));
323 		(void) printf(s_mok, m->master);
324 		status = 1;
325 	} else {
326 		(void) fprintf(stderr,
327 			"Can't get any map parameter information.\n");
328 		(void) fprintf(stderr, s_obad, map,
329 		    yperr_string(ypprot_err(o->status)));
330 		(void) fprintf(stderr, s_mbad, map,
331 		    yperr_string(ypprot_err(m->status)));
332 		status = 1;
333 	}
334 }
335 
336 static void
337 getypserv()
338 {
339 	struct ypbind_resp response;
340 	struct ypbind_domain ypdomain;
341 	struct ypbind_binding *binding;
342 	static char hostbuf[256];
343 
344 	getlochost();
345 
346 	(void) memset((char *)&response, 0, sizeof (response));
347 	ypdomain.ypbind_domainname = domain;
348 	ypdomain.ypbind_vers = YPBINDVERS;
349 	(void) rpc_call(host, YPBINDPROG, YPBINDVERS, YPBINDPROC_DOMAIN,
350 	    xdr_ypbind_domain, (char *)&ypdomain, xdr_ypbind_resp,
351 	    (char *)&response, "netpath");
352 	if (response.ypbind_status != YPBIND_SUCC_VAL) {
353 		(void) fprintf(stderr, "couldn't get yp server - status %u\n",
354 		    response.ypbind_status);
355 		exit(1);
356 	}
357 	binding = response.ypbind_resp_u.ypbind_bindinfo;
358 	host = binding->ypbind_servername;
359 
360 	/*
361 	 *  When ypbind is running in broadcast mode, it sets the
362 	 *  servername to "".  To get the real name of the server,
363 	 *  we need to do a host lookup on the svcaddr.  This code
364 	 *  is similar to code in ypwhich.
365 	 */
366 	if (strcmp(host, "") == 0) {
367 		struct nd_hostservlist *nhs;
368 		struct netconfig *nconf = binding->ypbind_nconf;
369 		struct netbuf *svcaddr = binding->ypbind_svcaddr;
370 
371 		if (netdir_getbyaddr(nconf, &nhs, svcaddr) != ND_OK) {
372 			struct sockaddr_in *sa;
373 
374 			sa = (struct sockaddr_in *)svcaddr->buf;
375 
376 			strcpy(hostbuf, inet_ntoa(sa->sin_addr));
377 		} else {
378 			sprintf(hostbuf, "%s", nhs->h_hostservs->h_host);
379 		}
380 		host = hostbuf;
381 		netdir_free((char *)nhs, ND_HOSTSERVLIST);
382 	}
383 }
384