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 1995 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 void 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 exit(status); 120 /* NOTREACHED */ 121 } 122 123 /* 124 * This does the command line argument processing. 125 */ 126 static void 127 get_command_line_args(argc, argv) 128 int argc; 129 char **argv; 130 131 { 132 argv++; 133 134 while (--argc) { 135 136 if ((*argv)[0] == '-') { 137 138 switch ((*argv)[1]) { 139 140 case 'h': 141 142 if (argc > 1) { 143 argv++; 144 argc--; 145 host = *argv; 146 argv++; 147 148 if ((int)strlen(host) > 256) { 149 (void) fprintf(stderr, 150 err_bad_args, 151 err_bad_hostname); 152 exit(1); 153 } 154 155 } else { 156 (void) fprintf(stderr, err_usage); 157 exit(1); 158 } 159 160 break; 161 162 case 'd': 163 164 if (argc > 1) { 165 argv++; 166 argc--; 167 domain = *argv; 168 argv++; 169 170 if ((int)strlen(domain) > YPMAXDOMAIN) { 171 (void) fprintf(stderr, 172 err_bad_args, 173 err_bad_domainname); 174 exit(1); 175 } 176 177 } else { 178 (void) fprintf(stderr, err_usage); 179 exit(1); 180 } 181 182 break; 183 184 default: 185 (void) fprintf(stderr, err_usage); 186 exit(1); 187 188 } 189 190 } else { 191 if (!map) { 192 map = *argv; 193 194 if ((int)strlen(map) > YPMAXMAP) { 195 (void) fprintf(stderr, err_bad_args, 196 err_bad_mapname); 197 exit(1); 198 } 199 200 } else { 201 (void) fprintf(stderr, err_usage); 202 exit(1); 203 } 204 } 205 } 206 207 if (!map) { 208 (void) fprintf(stderr, err_usage); 209 exit(1); 210 } 211 } 212 213 /* 214 * This gets the local default domainname, and makes sure that it's set 215 * to something reasonable. domain is set here. 216 */ 217 static void 218 getdomain() 219 { 220 if (!getdomainname(default_domain_name, YPMAXDOMAIN)) { 221 domain = default_domain_name; 222 } else { 223 (void) fprintf(stderr, err_cant_get_kname, err_bad_domainname); 224 exit(1); 225 } 226 227 if ((int)strlen(domain) == 0) { 228 (void) fprintf(stderr, err_null_kname, err_bad_domainname); 229 exit(1); 230 } 231 } 232 233 /* 234 * This gets the local hostname back from the kernel 235 */ 236 static void 237 getlochost() 238 { 239 240 if (! gethostname(default_host_name, 256)) { 241 host = default_host_name; 242 } else { 243 (void) fprintf(stderr, err_cant_get_kname, err_bad_hostname); 244 exit(1); 245 } 246 } 247 248 static void 249 getmapparms() 250 { 251 CLIENT * map_clnt; 252 struct ypresp_order oresp; 253 struct ypreq_nokey req; 254 struct ypresp_master mresp; 255 struct ypresp_master *mresults = (struct ypresp_master *) NULL; 256 struct ypresp_order *oresults = (struct ypresp_order *) NULL; 257 258 struct timeval timeout; 259 enum clnt_stat s; 260 261 if ((map_clnt = clnt_create(host, YPPROG, YPVERS, 262 "netpath")) == NULL) { 263 (void) fprintf(stderr, 264 "Can't create connection to %s.\n", host); 265 clnt_pcreateerror("Reason"); 266 exit(1); 267 } 268 269 timeout.tv_sec = TIMEOUT; 270 timeout.tv_usec = 0; 271 req.domain = domain; 272 req.map = map; 273 mresp.master = NULL; 274 275 if (clnt_call(map_clnt, YPPROC_MASTER, (xdrproc_t)xdr_ypreq_nokey, 276 (caddr_t) &req, (xdrproc_t)xdr_ypresp_master, 277 (caddr_t) &mresp, timeout) == RPC_SUCCESS) { 278 mresults = &mresp; 279 s = (enum clnt_stat) clnt_call(map_clnt, YPPROC_ORDER, 280 (xdrproc_t)xdr_ypreq_nokey, (char *)&req, 281 (xdrproc_t)xdr_ypresp_order, (char *)&oresp, timeout); 282 283 if (s == RPC_SUCCESS) { 284 oresults = &oresp; 285 newresults(mresults, oresults); 286 } else { 287 (void) fprintf(stderr, 288 "Can't make YPPROC_ORDER call to ypserv at %s.\n ", 289 host); 290 clnt_perror(map_clnt, "Reason"); 291 exit(1); 292 } 293 294 } else { 295 clnt_destroy(map_clnt); 296 } 297 } 298 299 static void 300 newresults(m, o) 301 struct ypresp_master *m; 302 struct ypresp_order *o; 303 { 304 char *s_domok = "Domain %s is supported.\n"; 305 char *s_ook = "Map %s has order number %d.\n"; 306 char *s_mok = "The master server is %s.\n"; 307 char *s_mbad = "Can't get master for map %s.\n Reason: %s\n"; 308 char *s_obad = "Can't get order number for map %s.\n Reason: %s\n"; 309 310 if (m->status == YP_TRUE && o->status == YP_TRUE) { 311 (void) printf(s_domok, domain); 312 (void) printf(s_ook, map, o->ordernum); 313 (void) printf(s_mok, m->master); 314 } else if (o->status == YP_TRUE) { 315 (void) printf(s_domok, domain); 316 (void) printf(s_ook, map, o->ordernum); 317 (void) fprintf(stderr, s_mbad, map, 318 yperr_string(ypprot_err(m->status))); 319 status = 1; 320 } else if (m->status == YP_TRUE) { 321 (void) printf(s_domok, domain); 322 (void) fprintf(stderr, s_obad, map, 323 yperr_string(ypprot_err(o->status))); 324 (void) printf(s_mok, m->master); 325 status = 1; 326 } else { 327 (void) fprintf(stderr, 328 "Can't get any map parameter information.\n"); 329 (void) fprintf(stderr, s_obad, map, 330 yperr_string(ypprot_err(o->status))); 331 (void) fprintf(stderr, s_mbad, map, 332 yperr_string(ypprot_err(m->status))); 333 status = 1; 334 } 335 } 336 337 static void 338 getypserv() 339 { 340 struct ypbind_resp response; 341 struct ypbind_domain ypdomain; 342 struct ypbind_binding *binding; 343 static char hostbuf[256]; 344 345 getlochost(); 346 347 (void) memset((char *)&response, 0, sizeof (response)); 348 ypdomain.ypbind_domainname = domain; 349 ypdomain.ypbind_vers = YPBINDVERS; 350 (void) rpc_call(host, YPBINDPROG, YPBINDVERS, YPBINDPROC_DOMAIN, 351 xdr_ypbind_domain, (char *)&ypdomain, xdr_ypbind_resp, 352 (char *)&response, "netpath"); 353 if (response.ypbind_status != YPBIND_SUCC_VAL) { 354 (void) fprintf(stderr, "couldn't get yp server - status %u\n", 355 response.ypbind_status); 356 exit(1); 357 } 358 binding = response.ypbind_resp_u.ypbind_bindinfo; 359 host = binding->ypbind_servername; 360 361 /* 362 * When ypbind is running in broadcast mode, it sets the 363 * servername to "". To get the real name of the server, 364 * we need to do a host lookup on the svcaddr. This code 365 * is similar to code in ypwhich. 366 */ 367 if (strcmp(host, "") == 0) { 368 struct nd_hostservlist *nhs; 369 struct netconfig *nconf = binding->ypbind_nconf; 370 struct netbuf *svcaddr = binding->ypbind_svcaddr; 371 372 if (netdir_getbyaddr(nconf, &nhs, svcaddr) != ND_OK) { 373 struct sockaddr_in *sa; 374 375 sa = (struct sockaddr_in *)svcaddr->buf; 376 377 strcpy(hostbuf, inet_ntoa(sa->sin_addr)); 378 } else { 379 sprintf(hostbuf, "%s", nhs->h_hostservs->h_host); 380 } 381 host = hostbuf; 382 netdir_free((char *)nhs, ND_HOSTSERVLIST); 383 } 384 } 385