1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate * 22*0Sstevel@tonic-gate * Copyright 2001 Sun Microsystems, Inc. All rights reserved. 23*0Sstevel@tonic-gate * Use is subject to license terms. 24*0Sstevel@tonic-gate */ 25*0Sstevel@tonic-gate 26*0Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 27*0Sstevel@tonic-gate /* All Rights Reserved */ 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 31*0Sstevel@tonic-gate * under license from the Regents of the University of 32*0Sstevel@tonic-gate * California. 33*0Sstevel@tonic-gate */ 34*0Sstevel@tonic-gate 35*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate /* 38*0Sstevel@tonic-gate * This is a user command which tells which yp server is being used by a 39*0Sstevel@tonic-gate * given machine, or which yp server is the master for a named map. 40*0Sstevel@tonic-gate * 41*0Sstevel@tonic-gate * Usage is: 42*0Sstevel@tonic-gate * ypwhich [-d domain] [-m [mname] [-t] | [-Vn] host] 43*0Sstevel@tonic-gate * ypwhich -x 44*0Sstevel@tonic-gate * where: the -d switch can be used to specify a domain other than the 45*0Sstevel@tonic-gate * default domain. -m tells the master of that map. mname is a mapname 46*0Sstevel@tonic-gate * If the -m option is used, ypwhich will act like a vanilla yp client, 47*0Sstevel@tonic-gate * and will not attempt to choose a particular yp server. On the 48*0Sstevel@tonic-gate * other hand, if no -m switch is used, ypwhich will talk directly to the yp 49*0Sstevel@tonic-gate * bind process on the named host, or to the local ypbind process if no host 50*0Sstevel@tonic-gate * name is specified. -t switch inhibits nickname translation of map names. 51*0Sstevel@tonic-gate * -x is to dump the nickname translation table from file /var/yp/nicknames. 52*0Sstevel@tonic-gate * 53*0Sstevel@tonic-gate */ 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate #include <stdio.h> 56*0Sstevel@tonic-gate #include <ctype.h> 57*0Sstevel@tonic-gate #include <rpc/rpc.h> 58*0Sstevel@tonic-gate #include <rpcsvc/yp_prot.h> 59*0Sstevel@tonic-gate #include <rpcsvc/ypclnt.h> 60*0Sstevel@tonic-gate #include "yp_b.h" 61*0Sstevel@tonic-gate #include "ypv2_bind.h" 62*0Sstevel@tonic-gate #include <string.h> 63*0Sstevel@tonic-gate #include <netdir.h> 64*0Sstevel@tonic-gate #include <unistd.h> 65*0Sstevel@tonic-gate #include <netdb.h> 66*0Sstevel@tonic-gate #include <arpa/inet.h> 67*0Sstevel@tonic-gate #include <inet/ip.h> 68*0Sstevel@tonic-gate #include <inet/ip6.h> 69*0Sstevel@tonic-gate #include <netinet/ip6.h> 70*0Sstevel@tonic-gate #include <sys/utsname.h> 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate #define YPSLEEPTIME 5 /* between two tries of bind */ 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate #define TIMEOUT 30 /* Total seconds for timeout */ 75*0Sstevel@tonic-gate #define INTER_TRY 10 /* Seconds between tries */ 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate static int translate = TRUE; 78*0Sstevel@tonic-gate static int dodump = FALSE; 79*0Sstevel@tonic-gate static char *domain = NULL; 80*0Sstevel@tonic-gate static char default_domain_name[YPMAXDOMAIN]; 81*0Sstevel@tonic-gate static char *host = NULL; 82*0Sstevel@tonic-gate static int vers = YPBINDVERS; 83*0Sstevel@tonic-gate static char default_host_name[256]; 84*0Sstevel@tonic-gate static bool get_master = FALSE; 85*0Sstevel@tonic-gate static bool get_server = FALSE; 86*0Sstevel@tonic-gate static char *map = NULL; 87*0Sstevel@tonic-gate static char nm[YPMAXMAP+1]; 88*0Sstevel@tonic-gate static struct timeval timeout = { 89*0Sstevel@tonic-gate TIMEOUT, /* Seconds */ 90*0Sstevel@tonic-gate 0 /* Microseconds */ 91*0Sstevel@tonic-gate }; 92*0Sstevel@tonic-gate static char nullstring[] = "\000"; 93*0Sstevel@tonic-gate static char err_usage[] = 94*0Sstevel@tonic-gate "Usage:\n\ 95*0Sstevel@tonic-gate ypwhich [-d domain] [[-t] -m [mname] | [-Vn] host]\n\ 96*0Sstevel@tonic-gate ypwhich -x\n\ 97*0Sstevel@tonic-gate where\n\ 98*0Sstevel@tonic-gate mname may be either a mapname or a nickname for a map.\n\ 99*0Sstevel@tonic-gate host if specified, is the machine whose NIS server is to be found.\n\ 100*0Sstevel@tonic-gate -t inhibits map nickname translation.\n\ 101*0Sstevel@tonic-gate -Vn version of ypbind, V3 is default.\n\ 102*0Sstevel@tonic-gate -x dumps the map nickname translation table.\n"; 103*0Sstevel@tonic-gate static char err_bad_args[] = 104*0Sstevel@tonic-gate "ypwhich: %s argument is bad.\n"; 105*0Sstevel@tonic-gate static char err_cant_get_kname[] = 106*0Sstevel@tonic-gate "ypwhich: can't get %s back from system call.\n"; 107*0Sstevel@tonic-gate static char err_null_kname[] = 108*0Sstevel@tonic-gate "ypwhich: the %s hasn't been set on this machine.\n"; 109*0Sstevel@tonic-gate static char err_bad_mapname[] = "mapname"; 110*0Sstevel@tonic-gate static char err_bad_domainname[] = "domainname"; 111*0Sstevel@tonic-gate static char err_bad_hostname[] = "hostname"; 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate static void get_command_line_args(); 114*0Sstevel@tonic-gate static void getdomain(); 115*0Sstevel@tonic-gate static void getlochost(); 116*0Sstevel@tonic-gate static void get_server_name(); 117*0Sstevel@tonic-gate static int call_binder(); 118*0Sstevel@tonic-gate static void get_map_master(); 119*0Sstevel@tonic-gate extern void maketable(); 120*0Sstevel@tonic-gate extern int getmapname(); 121*0Sstevel@tonic-gate #ifdef DEBUG 122*0Sstevel@tonic-gate static void dump_response(); 123*0Sstevel@tonic-gate #endif 124*0Sstevel@tonic-gate static void dump_ypmaps(); 125*0Sstevel@tonic-gate static void dumpmaps(); 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate static bool xdr_yp_inaddr (); 128*0Sstevel@tonic-gate static bool xdr_old_ypbind_resp (); 129*0Sstevel@tonic-gate static bool xdr_old_yp_binding(); 130*0Sstevel@tonic-gate static int old_call_binder(); 131*0Sstevel@tonic-gate static void print_server(); 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate /* need these for call to (remote) V2 ypbind */ 134*0Sstevel@tonic-gate struct old_ypbind_binding { 135*0Sstevel@tonic-gate struct in_addr ypbind_binding_addr; /* In network order */ 136*0Sstevel@tonic-gate unsigned short int ypbind_binding_port; /* In network order */ 137*0Sstevel@tonic-gate }; 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate struct old_ypbind_resp { 140*0Sstevel@tonic-gate enum ypbind_resptype ypbind_status; 141*0Sstevel@tonic-gate union { 142*0Sstevel@tonic-gate unsigned long ypbind_error; 143*0Sstevel@tonic-gate struct old_ypbind_binding ypbind_bindinfo; 144*0Sstevel@tonic-gate } ypbind_respbody; 145*0Sstevel@tonic-gate }; 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate /* 148*0Sstevel@tonic-gate * This is the main line for the ypwhich process. 149*0Sstevel@tonic-gate */ 150*0Sstevel@tonic-gate main(argc, argv) 151*0Sstevel@tonic-gate char **argv; 152*0Sstevel@tonic-gate { 153*0Sstevel@tonic-gate get_command_line_args(argc, argv); 154*0Sstevel@tonic-gate 155*0Sstevel@tonic-gate if (dodump) { 156*0Sstevel@tonic-gate maketable(dodump); 157*0Sstevel@tonic-gate exit(0); 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate if (!domain) { 161*0Sstevel@tonic-gate getdomain(); 162*0Sstevel@tonic-gate } 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate if (map && translate && (strchr(map, '.') == NULL) && 165*0Sstevel@tonic-gate (getmapname(map, nm))) { 166*0Sstevel@tonic-gate map = nm; 167*0Sstevel@tonic-gate } 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate if (get_server) { 170*0Sstevel@tonic-gate if (!host) 171*0Sstevel@tonic-gate getlochost(); 172*0Sstevel@tonic-gate get_server_name(); 173*0Sstevel@tonic-gate } else { 174*0Sstevel@tonic-gate if (map) 175*0Sstevel@tonic-gate get_map_master(); 176*0Sstevel@tonic-gate else 177*0Sstevel@tonic-gate dump_ypmaps(); 178*0Sstevel@tonic-gate } 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate return (0); 181*0Sstevel@tonic-gate } 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate /* 184*0Sstevel@tonic-gate * This does the command line argument processing. 185*0Sstevel@tonic-gate */ 186*0Sstevel@tonic-gate static void 187*0Sstevel@tonic-gate get_command_line_args(argc, argv) 188*0Sstevel@tonic-gate int argc; 189*0Sstevel@tonic-gate char **argv; 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate { 192*0Sstevel@tonic-gate argv++; 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate if (argc == 1) { 195*0Sstevel@tonic-gate get_server = TRUE; 196*0Sstevel@tonic-gate return; 197*0Sstevel@tonic-gate } 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate while (--argc) { 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate if ((*argv)[0] == '-') { 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate switch ((*argv)[1]) { 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate case 'V': 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate vers = atoi(argv[0]+2); 208*0Sstevel@tonic-gate if (vers < 1) { 209*0Sstevel@tonic-gate (void) fprintf(stderr, err_usage); 210*0Sstevel@tonic-gate exit(1); 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate argv++; 213*0Sstevel@tonic-gate break; 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate case 'm': 216*0Sstevel@tonic-gate get_master = TRUE; 217*0Sstevel@tonic-gate argv++; 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate if (argc > 1) { 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate if ((*(argv))[0] == '-') { 222*0Sstevel@tonic-gate break; 223*0Sstevel@tonic-gate } 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate argc--; 226*0Sstevel@tonic-gate map = *argv; 227*0Sstevel@tonic-gate argv++; 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate if ((int)strlen(map) > YPMAXMAP) { 230*0Sstevel@tonic-gate (void) fprintf(stderr, err_bad_args, 231*0Sstevel@tonic-gate err_bad_mapname); 232*0Sstevel@tonic-gate exit(1); 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate } 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate break; 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate case 'd': 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate if (argc > 1) { 242*0Sstevel@tonic-gate argv++; 243*0Sstevel@tonic-gate argc--; 244*0Sstevel@tonic-gate domain = *argv; 245*0Sstevel@tonic-gate argv++; 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate if ((int)strlen(domain) > YPMAXDOMAIN) { 248*0Sstevel@tonic-gate (void) fprintf(stderr, err_bad_args, 249*0Sstevel@tonic-gate err_bad_domainname); 250*0Sstevel@tonic-gate exit(1); 251*0Sstevel@tonic-gate } 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate } else { 254*0Sstevel@tonic-gate (void) fprintf(stderr, err_usage); 255*0Sstevel@tonic-gate exit(1); 256*0Sstevel@tonic-gate } 257*0Sstevel@tonic-gate 258*0Sstevel@tonic-gate break; 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate case 't': 261*0Sstevel@tonic-gate translate = FALSE; 262*0Sstevel@tonic-gate argv++; 263*0Sstevel@tonic-gate break; 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate case 'x': 266*0Sstevel@tonic-gate dodump = TRUE; 267*0Sstevel@tonic-gate argv++; 268*0Sstevel@tonic-gate break; 269*0Sstevel@tonic-gate 270*0Sstevel@tonic-gate default: 271*0Sstevel@tonic-gate (void) fprintf(stderr, err_usage); 272*0Sstevel@tonic-gate exit(1); 273*0Sstevel@tonic-gate } 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate } else { 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate if (get_server) { 278*0Sstevel@tonic-gate (void) fprintf(stderr, err_usage); 279*0Sstevel@tonic-gate exit(1); 280*0Sstevel@tonic-gate } 281*0Sstevel@tonic-gate 282*0Sstevel@tonic-gate get_server = TRUE; 283*0Sstevel@tonic-gate host = *argv; 284*0Sstevel@tonic-gate argv++; 285*0Sstevel@tonic-gate 286*0Sstevel@tonic-gate if ((int)strlen(host) > 256) { 287*0Sstevel@tonic-gate (void) fprintf(stderr, 288*0Sstevel@tonic-gate err_bad_args, err_bad_hostname); 289*0Sstevel@tonic-gate exit(1); 290*0Sstevel@tonic-gate } 291*0Sstevel@tonic-gate } 292*0Sstevel@tonic-gate } 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate if (get_master && get_server) { 295*0Sstevel@tonic-gate (void) fprintf(stderr, err_usage); 296*0Sstevel@tonic-gate exit(1); 297*0Sstevel@tonic-gate } 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gate if (!get_master && !get_server) { 300*0Sstevel@tonic-gate get_server = TRUE; 301*0Sstevel@tonic-gate } 302*0Sstevel@tonic-gate } 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate /* 305*0Sstevel@tonic-gate * This gets the local default domainname, and makes sure that it's set 306*0Sstevel@tonic-gate * to something reasonable. domain is set here. 307*0Sstevel@tonic-gate */ 308*0Sstevel@tonic-gate static void 309*0Sstevel@tonic-gate getdomain() 310*0Sstevel@tonic-gate { 311*0Sstevel@tonic-gate if (!getdomainname(default_domain_name, YPMAXDOMAIN)) { 312*0Sstevel@tonic-gate domain = default_domain_name; 313*0Sstevel@tonic-gate } else { 314*0Sstevel@tonic-gate (void) fprintf(stderr, err_cant_get_kname, err_bad_domainname); 315*0Sstevel@tonic-gate exit(1); 316*0Sstevel@tonic-gate } 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate if ((int)strlen(domain) == 0) { 319*0Sstevel@tonic-gate (void) fprintf(stderr, err_null_kname, err_bad_domainname); 320*0Sstevel@tonic-gate exit(1); 321*0Sstevel@tonic-gate } 322*0Sstevel@tonic-gate } 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gate /* 325*0Sstevel@tonic-gate * This gets the local hostname back from the kernel 326*0Sstevel@tonic-gate */ 327*0Sstevel@tonic-gate static void 328*0Sstevel@tonic-gate getlochost() 329*0Sstevel@tonic-gate { 330*0Sstevel@tonic-gate struct utsname utsname; 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate if (uname(&utsname) != -1) { 333*0Sstevel@tonic-gate strcpy(default_host_name, utsname.nodename); 334*0Sstevel@tonic-gate host = default_host_name; 335*0Sstevel@tonic-gate } else { 336*0Sstevel@tonic-gate (void) fprintf(stderr, err_cant_get_kname, err_bad_hostname); 337*0Sstevel@tonic-gate exit(1); 338*0Sstevel@tonic-gate } 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate } 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate /* 343*0Sstevel@tonic-gate * This tries to find the name of the server to which the binder in question 344*0Sstevel@tonic-gate * is bound. If one of the -Vx flags was specified, it will try only for 345*0Sstevel@tonic-gate * that protocol version, otherwise, it will start with the current version, 346*0Sstevel@tonic-gate * then drop back to the previous version. 347*0Sstevel@tonic-gate */ 348*0Sstevel@tonic-gate static void 349*0Sstevel@tonic-gate get_server_name() 350*0Sstevel@tonic-gate { 351*0Sstevel@tonic-gate char *notbound = "Domain %s not bound on %s.\n"; 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate if (vers >= 3){ 354*0Sstevel@tonic-gate if (!call_binder(vers)) 355*0Sstevel@tonic-gate (void) fprintf(stderr, notbound, domain, host); 356*0Sstevel@tonic-gate } else { 357*0Sstevel@tonic-gate if (!old_call_binder(vers)) 358*0Sstevel@tonic-gate (void) fprintf(stderr, notbound, domain, host); 359*0Sstevel@tonic-gate } 360*0Sstevel@tonic-gate } 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate extern CLIENT *__clnt_create_loopback(); 363*0Sstevel@tonic-gate 364*0Sstevel@tonic-gate /* 365*0Sstevel@tonic-gate * This sends a message to the ypbind process on the node with 366*0Sstevel@tonic-gate * the host name 367*0Sstevel@tonic-gate */ 368*0Sstevel@tonic-gate static int 369*0Sstevel@tonic-gate call_binder(vers) 370*0Sstevel@tonic-gate int vers; 371*0Sstevel@tonic-gate { 372*0Sstevel@tonic-gate CLIENT *client; 373*0Sstevel@tonic-gate struct ypbind_resp *response; 374*0Sstevel@tonic-gate struct ypbind_domain ypbd; 375*0Sstevel@tonic-gate char errstring[256]; 376*0Sstevel@tonic-gate extern struct rpc_createerr rpc_createerr; 377*0Sstevel@tonic-gate int yperr = 0; 378*0Sstevel@tonic-gate struct utsname utsname; 379*0Sstevel@tonic-gate const char *str; 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate /* 382*0Sstevel@tonic-gate * CAUTION: Do not go to NIS if the host is the same as the local host 383*0Sstevel@tonic-gate * XXX: Lots of special magic to distinguish between local and remote 384*0Sstevel@tonic-gate * case. We want to make sure the local case doesn't hang. 385*0Sstevel@tonic-gate */ 386*0Sstevel@tonic-gate 387*0Sstevel@tonic-gate if ((uname(&utsname) != -1) && 388*0Sstevel@tonic-gate (strcmp(host, utsname.nodename) == 0)) 389*0Sstevel@tonic-gate client = __clnt_create_loopback(YPBINDPROG, vers, &yperr); 390*0Sstevel@tonic-gate else 391*0Sstevel@tonic-gate client = clnt_create(host, YPBINDPROG, vers, "netpath"); 392*0Sstevel@tonic-gate if (client == NULL) { 393*0Sstevel@tonic-gate if (yperr) 394*0Sstevel@tonic-gate (void) fprintf(stderr, 395*0Sstevel@tonic-gate "ypwhich: %s\n", yperr_string(yperr)); 396*0Sstevel@tonic-gate else { 397*0Sstevel@tonic-gate if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED || 398*0Sstevel@tonic-gate rpc_createerr.cf_stat == RPC_PROGUNAVAIL) { 399*0Sstevel@tonic-gate (void) fprintf(stderr, 400*0Sstevel@tonic-gate "ypwhich: %s is not running ypbind\n", host); 401*0Sstevel@tonic-gate } else if (rpc_createerr.cf_stat == RPC_PMAPFAILURE) { 402*0Sstevel@tonic-gate (void) fprintf(stderr, 403*0Sstevel@tonic-gate "ypwhich: %s is not running rpcbind\n", 404*0Sstevel@tonic-gate host); 405*0Sstevel@tonic-gate } else 406*0Sstevel@tonic-gate (void) clnt_pcreateerror("ypwhich: \ 407*0Sstevel@tonic-gate clnt_create error"); 408*0Sstevel@tonic-gate } 409*0Sstevel@tonic-gate exit(1); 410*0Sstevel@tonic-gate } 411*0Sstevel@tonic-gate ypbd.ypbind_domainname = domain; 412*0Sstevel@tonic-gate ypbd.ypbind_vers = vers; 413*0Sstevel@tonic-gate response = ypbindproc_domain_3(&ypbd, client); 414*0Sstevel@tonic-gate 415*0Sstevel@tonic-gate if (response == NULL){ 416*0Sstevel@tonic-gate (void) sprintf(errstring, 417*0Sstevel@tonic-gate "ypwhich: can't call ypbind on %s", host); 418*0Sstevel@tonic-gate (void) clnt_perror(client, errstring); 419*0Sstevel@tonic-gate exit(1); 420*0Sstevel@tonic-gate } 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate clnt_destroy(client); 423*0Sstevel@tonic-gate 424*0Sstevel@tonic-gate if (response->ypbind_status != YPBIND_SUCC_VAL) { 425*0Sstevel@tonic-gate return (FALSE); 426*0Sstevel@tonic-gate } 427*0Sstevel@tonic-gate 428*0Sstevel@tonic-gate if (response->ypbind_resp_u.ypbind_bindinfo) { 429*0Sstevel@tonic-gate char *server = 430*0Sstevel@tonic-gate response->ypbind_resp_u.ypbind_bindinfo->ypbind_servername; 431*0Sstevel@tonic-gate 432*0Sstevel@tonic-gate if (strcmp(server, nullstring) == 0) { 433*0Sstevel@tonic-gate /* depends on a hack in ypbind */ 434*0Sstevel@tonic-gate struct nd_hostservlist *nhs = NULL; 435*0Sstevel@tonic-gate struct netconfig *nconf = 436*0Sstevel@tonic-gate response->ypbind_resp_u.ypbind_bindinfo->ypbind_nconf; 437*0Sstevel@tonic-gate struct netbuf *svcaddr = 438*0Sstevel@tonic-gate response->ypbind_resp_u.ypbind_bindinfo->ypbind_svcaddr; 439*0Sstevel@tonic-gate 440*0Sstevel@tonic-gate if (netdir_getbyaddr(nconf, &nhs, svcaddr) != ND_OK) { 441*0Sstevel@tonic-gate struct sockaddr_in *sa4; 442*0Sstevel@tonic-gate struct sockaddr_in6 *sa6; 443*0Sstevel@tonic-gate char buf[INET6_ADDRSTRLEN]; 444*0Sstevel@tonic-gate char xbuf[IPV6_ADDR_LEN]; 445*0Sstevel@tonic-gate int af; 446*0Sstevel@tonic-gate void *addr; 447*0Sstevel@tonic-gate XDR xdrs; 448*0Sstevel@tonic-gate 449*0Sstevel@tonic-gate sa4 = (struct sockaddr_in *)svcaddr->buf; 450*0Sstevel@tonic-gate af = ntohs(sa4->sin_family); 451*0Sstevel@tonic-gate if (af != sa4->sin_family) { 452*0Sstevel@tonic-gate xdrmem_create(&xdrs, 453*0Sstevel@tonic-gate (caddr_t)xbuf, IPV6_ADDR_LEN, 454*0Sstevel@tonic-gate XDR_DECODE); 455*0Sstevel@tonic-gate if (af == AF_INET6) { 456*0Sstevel@tonic-gate xdr_opaque(&xdrs, 457*0Sstevel@tonic-gate (caddr_t)svcaddr->buf, 458*0Sstevel@tonic-gate IPV6_ADDR_LEN); 459*0Sstevel@tonic-gate sa6 = (struct sockaddr_in6 *) 460*0Sstevel@tonic-gate xbuf; 461*0Sstevel@tonic-gate addr = &sa6->sin6_addr; 462*0Sstevel@tonic-gate } else { 463*0Sstevel@tonic-gate xdr_opaque(&xdrs, 464*0Sstevel@tonic-gate (caddr_t)svcaddr->buf, 465*0Sstevel@tonic-gate IPV4_ADDR_LEN); 466*0Sstevel@tonic-gate sa4 = (struct sockaddr_in *) 467*0Sstevel@tonic-gate xbuf; 468*0Sstevel@tonic-gate addr = &sa4->sin_addr; 469*0Sstevel@tonic-gate } 470*0Sstevel@tonic-gate } else { 471*0Sstevel@tonic-gate if (af == AF_INET6) { 472*0Sstevel@tonic-gate sa6 = (struct sockaddr_in6 *) 473*0Sstevel@tonic-gate svcaddr->buf; 474*0Sstevel@tonic-gate addr = &sa6->sin6_addr; 475*0Sstevel@tonic-gate } else { 476*0Sstevel@tonic-gate addr = &sa4->sin_addr; 477*0Sstevel@tonic-gate } 478*0Sstevel@tonic-gate } 479*0Sstevel@tonic-gate str = inet_ntop(af, addr, buf, sizeof (buf)); 480*0Sstevel@tonic-gate if (str == NULL) 481*0Sstevel@tonic-gate perror("inet_ntop"); 482*0Sstevel@tonic-gate else 483*0Sstevel@tonic-gate fprintf(stdout, "%s\n", str); 484*0Sstevel@tonic-gate } else { 485*0Sstevel@tonic-gate str = nhs->h_hostservs->h_host; 486*0Sstevel@tonic-gate if (str == NULL) 487*0Sstevel@tonic-gate str = "<unknown>"; 488*0Sstevel@tonic-gate fprintf(stdout, "%s\n", str); 489*0Sstevel@tonic-gate } 490*0Sstevel@tonic-gate netdir_free((char *)nhs, ND_HOSTSERVLIST); 491*0Sstevel@tonic-gate } else { 492*0Sstevel@tonic-gate fprintf(stdout, "%s\n", server); 493*0Sstevel@tonic-gate } 494*0Sstevel@tonic-gate } 495*0Sstevel@tonic-gate #ifdef DEBUG 496*0Sstevel@tonic-gate dump_response(response); 497*0Sstevel@tonic-gate #endif 498*0Sstevel@tonic-gate return (TRUE); 499*0Sstevel@tonic-gate } 500*0Sstevel@tonic-gate 501*0Sstevel@tonic-gate /* 502*0Sstevel@tonic-gate * Serializes/deserializes an in_addr struct. 503*0Sstevel@tonic-gate * 504*0Sstevel@tonic-gate * Note: There is a data coupling between the "definition" of a struct 505*0Sstevel@tonic-gate * in_addr implicit in this xdr routine, and the true data definition in 506*0Sstevel@tonic-gate * <netinet/in.h>. 507*0Sstevel@tonic-gate */ 508*0Sstevel@tonic-gate static bool xdr_yp_inaddr(xdrs, ps) 509*0Sstevel@tonic-gate XDR * xdrs; 510*0Sstevel@tonic-gate struct in_addr *ps; 511*0Sstevel@tonic-gate 512*0Sstevel@tonic-gate { 513*0Sstevel@tonic-gate return (xdr_opaque(xdrs, (caddr_t)&ps->s_addr, 4)); 514*0Sstevel@tonic-gate } 515*0Sstevel@tonic-gate 516*0Sstevel@tonic-gate /* 517*0Sstevel@tonic-gate * Serializes/deserializes an old ypbind_binding struct. 518*0Sstevel@tonic-gate */ 519*0Sstevel@tonic-gate static bool xdr_old_yp_binding(xdrs, ps) 520*0Sstevel@tonic-gate XDR * xdrs; 521*0Sstevel@tonic-gate struct old_ypbind_binding *ps; 522*0Sstevel@tonic-gate 523*0Sstevel@tonic-gate { 524*0Sstevel@tonic-gate return (xdr_yp_inaddr(xdrs, &ps->ypbind_binding_addr) && 525*0Sstevel@tonic-gate xdr_opaque(xdrs, (caddr_t)&ps->ypbind_binding_port, 2)); 526*0Sstevel@tonic-gate } 527*0Sstevel@tonic-gate 528*0Sstevel@tonic-gate /* 529*0Sstevel@tonic-gate * Serializes/deserializes a ypbind_resp structure. 530*0Sstevel@tonic-gate */ 531*0Sstevel@tonic-gate static bool xdr_old_ypbind_resp(xdrs, ps) 532*0Sstevel@tonic-gate XDR * xdrs; 533*0Sstevel@tonic-gate struct old_ypbind_resp *ps; 534*0Sstevel@tonic-gate 535*0Sstevel@tonic-gate { 536*0Sstevel@tonic-gate if (!xdr_enum(xdrs, (enum_t*)&ps->ypbind_status)) { 537*0Sstevel@tonic-gate return (FALSE); 538*0Sstevel@tonic-gate } 539*0Sstevel@tonic-gate switch (ps->ypbind_status) { 540*0Sstevel@tonic-gate case YPBIND_SUCC_VAL: 541*0Sstevel@tonic-gate return (xdr_old_yp_binding(xdrs, 542*0Sstevel@tonic-gate &ps->ypbind_respbody.ypbind_bindinfo)); 543*0Sstevel@tonic-gate case YPBIND_FAIL_VAL: 544*0Sstevel@tonic-gate return (xdr_u_long(xdrs, 545*0Sstevel@tonic-gate &ps->ypbind_respbody.ypbind_error)); 546*0Sstevel@tonic-gate } 547*0Sstevel@tonic-gate return (FALSE); 548*0Sstevel@tonic-gate } 549*0Sstevel@tonic-gate /* This sends a message to the old ypbind process on host. */ 550*0Sstevel@tonic-gate static int old_call_binder(vers) 551*0Sstevel@tonic-gate int vers; 552*0Sstevel@tonic-gate { 553*0Sstevel@tonic-gate CLIENT *client; 554*0Sstevel@tonic-gate struct hostent *hp; 555*0Sstevel@tonic-gate int sock = RPC_ANYSOCK; 556*0Sstevel@tonic-gate enum clnt_stat rpc_stat; 557*0Sstevel@tonic-gate struct old_ypbind_resp response; 558*0Sstevel@tonic-gate char errstring[256]; 559*0Sstevel@tonic-gate extern struct rpc_createerr rpc_createerr; 560*0Sstevel@tonic-gate struct in_addr *server; 561*0Sstevel@tonic-gate 562*0Sstevel@tonic-gate if ((client = clnt_create(host, YPBINDPROG, vers, "udp")) == NULL) { 563*0Sstevel@tonic-gate if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED) { 564*0Sstevel@tonic-gate (void) printf("ypwhich: %s is not running ypbind\n", 565*0Sstevel@tonic-gate host); 566*0Sstevel@tonic-gate exit(1); 567*0Sstevel@tonic-gate } 568*0Sstevel@tonic-gate if (rpc_createerr.cf_stat == RPC_PMAPFAILURE) { 569*0Sstevel@tonic-gate (void) printf("ypwhich: %s is not running port mapper\n", 570*0Sstevel@tonic-gate host); 571*0Sstevel@tonic-gate exit(1); 572*0Sstevel@tonic-gate } 573*0Sstevel@tonic-gate (void) clnt_pcreateerror("ypwhich: clnt_create error"); 574*0Sstevel@tonic-gate exit(1); 575*0Sstevel@tonic-gate } 576*0Sstevel@tonic-gate 577*0Sstevel@tonic-gate rpc_stat = clnt_call(client, YPBINDPROC_DOMAIN, 578*0Sstevel@tonic-gate (xdrproc_t)xdr_ypdomain_wrap_string, (caddr_t)&domain, 579*0Sstevel@tonic-gate (xdrproc_t)xdr_old_ypbind_resp, (caddr_t)&response, 580*0Sstevel@tonic-gate timeout); 581*0Sstevel@tonic-gate 582*0Sstevel@tonic-gate if ((rpc_stat != RPC_SUCCESS) && 583*0Sstevel@tonic-gate (rpc_stat != RPC_PROGVERSMISMATCH)) { 584*0Sstevel@tonic-gate (void) sprintf(errstring, 585*0Sstevel@tonic-gate "ypwhich: can't call ypbind on %s", host); 586*0Sstevel@tonic-gate (void) clnt_perror(client, errstring); 587*0Sstevel@tonic-gate exit(1); 588*0Sstevel@tonic-gate } 589*0Sstevel@tonic-gate 590*0Sstevel@tonic-gate clnt_destroy(client); 591*0Sstevel@tonic-gate close(sock); 592*0Sstevel@tonic-gate 593*0Sstevel@tonic-gate if ((rpc_stat != RPC_SUCCESS) || 594*0Sstevel@tonic-gate (response.ypbind_status != YPBIND_SUCC_VAL)) { 595*0Sstevel@tonic-gate return (FALSE); 596*0Sstevel@tonic-gate } 597*0Sstevel@tonic-gate 598*0Sstevel@tonic-gate server = &response.ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr; 599*0Sstevel@tonic-gate print_server (server); 600*0Sstevel@tonic-gate 601*0Sstevel@tonic-gate return (TRUE); 602*0Sstevel@tonic-gate } 603*0Sstevel@tonic-gate 604*0Sstevel@tonic-gate /* 605*0Sstevel@tonic-gate * For old version: 606*0Sstevel@tonic-gate * This translates a server address to a name and prints it. 607*0Sstevel@tonic-gate * We'll get a name by using the standard library routine. 608*0Sstevel@tonic-gate */ 609*0Sstevel@tonic-gate static void print_server(server) 610*0Sstevel@tonic-gate struct in_addr *server; 611*0Sstevel@tonic-gate { 612*0Sstevel@tonic-gate char buf[256]; 613*0Sstevel@tonic-gate struct hostent *hp; 614*0Sstevel@tonic-gate 615*0Sstevel@tonic-gate strcpy(buf, inet_ntoa(*server)); 616*0Sstevel@tonic-gate hp = gethostbyaddr((char*)&server->s_addr, 617*0Sstevel@tonic-gate sizeof (struct in_addr), AF_INET); 618*0Sstevel@tonic-gate 619*0Sstevel@tonic-gate printf("%s\n", hp ? hp->h_name : buf); 620*0Sstevel@tonic-gate } 621*0Sstevel@tonic-gate 622*0Sstevel@tonic-gate #ifdef DEBUG 623*0Sstevel@tonic-gate static void 624*0Sstevel@tonic-gate dump_response(which) 625*0Sstevel@tonic-gate ypbind_resp * which; 626*0Sstevel@tonic-gate { 627*0Sstevel@tonic-gate struct netconfig *nc; 628*0Sstevel@tonic-gate struct netbuf *ua; 629*0Sstevel@tonic-gate ypbind_binding * b; 630*0Sstevel@tonic-gate 631*0Sstevel@tonic-gate int i; 632*0Sstevel@tonic-gate 633*0Sstevel@tonic-gate { 634*0Sstevel@tonic-gate b = which->ypbind_resp_u.ypbind_bindinfo; 635*0Sstevel@tonic-gate if (b == NULL) 636*0Sstevel@tonic-gate (void) fprintf(stderr, "???NO Binding information\n"); 637*0Sstevel@tonic-gate else { 638*0Sstevel@tonic-gate (void) fprintf(stderr, 639*0Sstevel@tonic-gate "server=%s lovers=%ld hivers=%ld\n", 640*0Sstevel@tonic-gate b->ypbind_servername, 641*0Sstevel@tonic-gate b->ypbind_lo_vers, b->ypbind_hi_vers); 642*0Sstevel@tonic-gate nc = b->ypbind_nconf; 643*0Sstevel@tonic-gate ua = b->ypbind_svcaddr; 644*0Sstevel@tonic-gate if (nc == NULL) 645*0Sstevel@tonic-gate (void) fprintf(stderr, 646*0Sstevel@tonic-gate "ypwhich: NO netconfig information\n"); 647*0Sstevel@tonic-gate else { 648*0Sstevel@tonic-gate (void) fprintf(stderr, 649*0Sstevel@tonic-gate "ypwhich: id %s device %s flag %x protofmly %s proto %s\n", 650*0Sstevel@tonic-gate nc->nc_netid, nc->nc_device, 651*0Sstevel@tonic-gate (int) nc->nc_flag, nc->nc_protofmly, 652*0Sstevel@tonic-gate nc->nc_proto); 653*0Sstevel@tonic-gate } 654*0Sstevel@tonic-gate if (ua == NULL) 655*0Sstevel@tonic-gate (void) fprintf(stderr, 656*0Sstevel@tonic-gate "ypwhich: NO netbuf information available from binder\n"); 657*0Sstevel@tonic-gate else { 658*0Sstevel@tonic-gate (void) fprintf(stderr, 659*0Sstevel@tonic-gate "maxlen=%d len=%d\naddr=", ua->maxlen, ua->len); 660*0Sstevel@tonic-gate for (i = 0; i < ua->len; i++) { 661*0Sstevel@tonic-gate if (i != (ua->len - 1)) 662*0Sstevel@tonic-gate (void) fprintf(stderr, 663*0Sstevel@tonic-gate "%d.", ua->buf[i]); 664*0Sstevel@tonic-gate else 665*0Sstevel@tonic-gate (void) fprintf(stderr, 666*0Sstevel@tonic-gate "%d\n", ua->buf[i]); 667*0Sstevel@tonic-gate } 668*0Sstevel@tonic-gate } 669*0Sstevel@tonic-gate } 670*0Sstevel@tonic-gate } 671*0Sstevel@tonic-gate 672*0Sstevel@tonic-gate } 673*0Sstevel@tonic-gate #endif 674*0Sstevel@tonic-gate 675*0Sstevel@tonic-gate /* 676*0Sstevel@tonic-gate * This translates a server address to a name and prints it. If the address 677*0Sstevel@tonic-gate * is the same as the local address as returned by get_myaddress, the name 678*0Sstevel@tonic-gate * is that retrieved from the kernel. If it's any other address (including 679*0Sstevel@tonic-gate * another ip address for the local machine), we'll get a name by using the 680*0Sstevel@tonic-gate * standard library routine (which calls the yp). 681*0Sstevel@tonic-gate */ 682*0Sstevel@tonic-gate 683*0Sstevel@tonic-gate /* 684*0Sstevel@tonic-gate * This asks any yp server for the map's master. 685*0Sstevel@tonic-gate */ 686*0Sstevel@tonic-gate static void 687*0Sstevel@tonic-gate get_map_master() 688*0Sstevel@tonic-gate { 689*0Sstevel@tonic-gate int err; 690*0Sstevel@tonic-gate char *master; 691*0Sstevel@tonic-gate 692*0Sstevel@tonic-gate err = __yp_master_rsvdport(domain, map, &master); 693*0Sstevel@tonic-gate 694*0Sstevel@tonic-gate if (err) { 695*0Sstevel@tonic-gate (void) fprintf(stderr, 696*0Sstevel@tonic-gate "ypwhich: Can't find the master of %s. Reason: %s.\n", 697*0Sstevel@tonic-gate map, yperr_string(err)); 698*0Sstevel@tonic-gate exit(1); 699*0Sstevel@tonic-gate } else { 700*0Sstevel@tonic-gate (void) printf("%s\n", master); 701*0Sstevel@tonic-gate } 702*0Sstevel@tonic-gate } 703*0Sstevel@tonic-gate 704*0Sstevel@tonic-gate /* 705*0Sstevel@tonic-gate * This enumerates the entries within map "ypmaps" in the domain at global 706*0Sstevel@tonic-gate * "domain", and prints them out key and value per single line. dump_ypmaps 707*0Sstevel@tonic-gate * just decides whether we are (probably) able to speak the new YP protocol, 708*0Sstevel@tonic-gate * and dispatches to the appropriate function. 709*0Sstevel@tonic-gate */ 710*0Sstevel@tonic-gate static void 711*0Sstevel@tonic-gate dump_ypmaps() 712*0Sstevel@tonic-gate { 713*0Sstevel@tonic-gate int err; 714*0Sstevel@tonic-gate struct dom_binding *binding; 715*0Sstevel@tonic-gate 716*0Sstevel@tonic-gate if (err = __yp_dobind(domain, &binding)) { 717*0Sstevel@tonic-gate (void) fprintf(stderr, 718*0Sstevel@tonic-gate "dump_ypmaps: Can't bind for domain %s. Reason: %s\n", 719*0Sstevel@tonic-gate domain, yperr_string(err)); 720*0Sstevel@tonic-gate return; 721*0Sstevel@tonic-gate } 722*0Sstevel@tonic-gate 723*0Sstevel@tonic-gate if (binding->dom_binding->ypbind_hi_vers >= YPVERS) { 724*0Sstevel@tonic-gate dumpmaps(binding); 725*0Sstevel@tonic-gate } 726*0Sstevel@tonic-gate } 727*0Sstevel@tonic-gate 728*0Sstevel@tonic-gate static void 729*0Sstevel@tonic-gate dumpmaps(binding) 730*0Sstevel@tonic-gate struct dom_binding *binding; 731*0Sstevel@tonic-gate { 732*0Sstevel@tonic-gate enum clnt_stat rpc_stat; 733*0Sstevel@tonic-gate int err; 734*0Sstevel@tonic-gate char *master; 735*0Sstevel@tonic-gate struct ypmaplist *pmpl; 736*0Sstevel@tonic-gate struct ypresp_maplist maplist; 737*0Sstevel@tonic-gate 738*0Sstevel@tonic-gate maplist.list = (struct ypmaplist *) NULL; 739*0Sstevel@tonic-gate 740*0Sstevel@tonic-gate rpc_stat = clnt_call(binding->dom_client, YPPROC_MAPLIST, 741*0Sstevel@tonic-gate (xdrproc_t) xdr_ypdomain_wrap_string, (caddr_t) &domain, 742*0Sstevel@tonic-gate (xdrproc_t) xdr_ypresp_maplist, (caddr_t) &maplist, 743*0Sstevel@tonic-gate timeout); 744*0Sstevel@tonic-gate 745*0Sstevel@tonic-gate if (rpc_stat != RPC_SUCCESS) { 746*0Sstevel@tonic-gate (void) clnt_perror(binding->dom_client, 747*0Sstevel@tonic-gate "ypwhich(dumpmaps): can't get maplist"); 748*0Sstevel@tonic-gate __yp_rel_binding(binding); 749*0Sstevel@tonic-gate exit(1); 750*0Sstevel@tonic-gate } 751*0Sstevel@tonic-gate 752*0Sstevel@tonic-gate if (maplist.status != YP_TRUE) { 753*0Sstevel@tonic-gate (void) fprintf(stderr, 754*0Sstevel@tonic-gate "ypwhich: Can't get maplist. Reason: %s.\n", 755*0Sstevel@tonic-gate yperr_string(ypprot_err(maplist.status))); 756*0Sstevel@tonic-gate exit(1); 757*0Sstevel@tonic-gate } 758*0Sstevel@tonic-gate __yp_rel_binding(binding); 759*0Sstevel@tonic-gate 760*0Sstevel@tonic-gate for (pmpl = maplist.list; pmpl; pmpl = pmpl->ypml_next) { 761*0Sstevel@tonic-gate (void) printf("%s ", pmpl->ypml_name); 762*0Sstevel@tonic-gate 763*0Sstevel@tonic-gate err = __yp_master_rsvdport(domain, pmpl->ypml_name, &master); 764*0Sstevel@tonic-gate 765*0Sstevel@tonic-gate if (err) { 766*0Sstevel@tonic-gate (void) printf("????????\n"); 767*0Sstevel@tonic-gate (void) fprintf(stderr, 768*0Sstevel@tonic-gate "ypwhich: Can't find the master of %s. Reason: %s.\n", 769*0Sstevel@tonic-gate pmpl->ypml_name, yperr_string(err)); 770*0Sstevel@tonic-gate } else { 771*0Sstevel@tonic-gate (void) printf("%s\n", master); 772*0Sstevel@tonic-gate } 773*0Sstevel@tonic-gate } 774*0Sstevel@tonic-gate } 775