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 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 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 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 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 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 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 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