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
main(argc,argv)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
get_command_line_args(argc,argv)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
getdomain()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
getlochost()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
getmapparms()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
newresults(m,o)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
getypserv()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