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