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