1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 1990-2002 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 31*7c478bd9Sstevel@tonic-gate #include <unistd.h> 32*7c478bd9Sstevel@tonic-gate #include <string.h> 33*7c478bd9Sstevel@tonic-gate #include <locale.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 36*7c478bd9Sstevel@tonic-gate #include <netdb.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/ioctl.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/signal.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/resource.h> 48*7c478bd9Sstevel@tonic-gate #include <net/if.h> 49*7c478bd9Sstevel@tonic-gate #include <net/if_arp.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/stream.h> 51*7c478bd9Sstevel@tonic-gate #include <net/route.h> 52*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 53*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 54*7c478bd9Sstevel@tonic-gate #include <netinet/if_ether.h> 55*7c478bd9Sstevel@tonic-gate #include <netinet/ip_var.h> 56*7c478bd9Sstevel@tonic-gate #include <netinet/udp.h> 57*7c478bd9Sstevel@tonic-gate #include <netinet/udp_var.h> 58*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 59*7c478bd9Sstevel@tonic-gate #include <rpcsvc/bootparam_prot.h> 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate #define MAXIFS 256 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate /* command line flags */ 64*7c478bd9Sstevel@tonic-gate int debug = 0; /* do debug printfs */ 65*7c478bd9Sstevel@tonic-gate int echo_host = 0; /* just echo hostname, don't set it */ 66*7c478bd9Sstevel@tonic-gate int verbose = 0; /* do verbose printfs */ 67*7c478bd9Sstevel@tonic-gate int safe = 0; /* don't change anything */ 68*7c478bd9Sstevel@tonic-gate int multiple = 0; /* take multiple replies */ 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate static ulong_t if_netmask; 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate void notsupported(), usage(), bp_whoami(); 73*7c478bd9Sstevel@tonic-gate int get_ifdata(); /* get IP addr, subnet mask from IF */ 74*7c478bd9Sstevel@tonic-gate extern char *inet_ntoa(); 75*7c478bd9Sstevel@tonic-gate extern int getopt(), setdomainname(); 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate struct prototab { 78*7c478bd9Sstevel@tonic-gate char *name; 79*7c478bd9Sstevel@tonic-gate void (*func)(); 80*7c478bd9Sstevel@tonic-gate } prototab[] = { 81*7c478bd9Sstevel@tonic-gate { "bootparams", bp_whoami }, 82*7c478bd9Sstevel@tonic-gate { "bootp", notsupported }, 83*7c478bd9Sstevel@tonic-gate { 0, 0 } 84*7c478bd9Sstevel@tonic-gate }; 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate /* 89*7c478bd9Sstevel@tonic-gate * usage: hostconfig [-p <protocol>] [-v] [-n] [-h] [<ifname>] [-f <hostname>] 90*7c478bd9Sstevel@tonic-gate * 91*7c478bd9Sstevel@tonic-gate * options: 92*7c478bd9Sstevel@tonic-gate * -d Debug mode. 93*7c478bd9Sstevel@tonic-gate * -v Verbose mode. 94*7c478bd9Sstevel@tonic-gate * -n Don't change anything. 95*7c478bd9Sstevel@tonic-gate * -h Don't set hostname, just echo to standard out. 96*7c478bd9Sstevel@tonic-gate * -m Wait for multiple answers (best used with the "-n" 97*7c478bd9Sstevel@tonic-gate * and "-v" flags). 98*7c478bd9Sstevel@tonic-gate * -f <hostname> Fake mode - get bootparams for <hostname> (also 99*7c478bd9Sstevel@tonic-gate * best used with the "-n" and "-v" flags). 100*7c478bd9Sstevel@tonic-gate * <ifname> Use IP address of <interface> in whoami request. 101*7c478bd9Sstevel@tonic-gate * 102*7c478bd9Sstevel@tonic-gate * If no interface name is specified, bp_whoami will cycle through the 103*7c478bd9Sstevel@tonic-gate * interfaces, using the IP address of each in turn until an answer is 104*7c478bd9Sstevel@tonic-gate * received. Note that rpc_broadcast() broadcasts the RPC call on all 105*7c478bd9Sstevel@tonic-gate * interfaces, so the <ifname> argument doesn't restrict the request 106*7c478bd9Sstevel@tonic-gate * to that interface, it just uses that interface to determine the IP 107*7c478bd9Sstevel@tonic-gate * address to put into the request. If "-f <hostname>" is specified, 108*7c478bd9Sstevel@tonic-gate * we put the IP address of <hostname> in the whoami request. Otherwise, 109*7c478bd9Sstevel@tonic-gate * we put the IP address of the interface in the whoami request. 110*7c478bd9Sstevel@tonic-gate * 111*7c478bd9Sstevel@tonic-gate */ 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate main(argc, argv) 115*7c478bd9Sstevel@tonic-gate int argc; 116*7c478bd9Sstevel@tonic-gate char **argv; 117*7c478bd9Sstevel@tonic-gate { 118*7c478bd9Sstevel@tonic-gate struct ifreq *reqbuf; 119*7c478bd9Sstevel@tonic-gate struct ifreq *ifr; 120*7c478bd9Sstevel@tonic-gate struct ifconf ifc; 121*7c478bd9Sstevel@tonic-gate struct in_addr targetaddr; 122*7c478bd9Sstevel@tonic-gate struct hostent *hp; 123*7c478bd9Sstevel@tonic-gate char *targethost = NULL; 124*7c478bd9Sstevel@tonic-gate char *cmdname; 125*7c478bd9Sstevel@tonic-gate int c; 126*7c478bd9Sstevel@tonic-gate int n; 127*7c478bd9Sstevel@tonic-gate struct prototab *ptp; 128*7c478bd9Sstevel@tonic-gate void (*protofunc)() = NULL; 129*7c478bd9Sstevel@tonic-gate int numifs; 130*7c478bd9Sstevel@tonic-gate unsigned bufsize; 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate extern char *optarg; 133*7c478bd9Sstevel@tonic-gate extern int optind; 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate cmdname = argv[0]; 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "dhvnmf:p:")) != -1) { 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate switch ((char)c) { 140*7c478bd9Sstevel@tonic-gate case 'd': 141*7c478bd9Sstevel@tonic-gate debug++; 142*7c478bd9Sstevel@tonic-gate break; 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate case 'h': 145*7c478bd9Sstevel@tonic-gate echo_host++; 146*7c478bd9Sstevel@tonic-gate break; 147*7c478bd9Sstevel@tonic-gate case 'v': 148*7c478bd9Sstevel@tonic-gate verbose++; 149*7c478bd9Sstevel@tonic-gate break; 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate case 'm': 152*7c478bd9Sstevel@tonic-gate multiple++; 153*7c478bd9Sstevel@tonic-gate break; 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate case 'n': 156*7c478bd9Sstevel@tonic-gate safe++; 157*7c478bd9Sstevel@tonic-gate break; 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate case 'f': 160*7c478bd9Sstevel@tonic-gate targethost = optarg; 161*7c478bd9Sstevel@tonic-gate break; 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate case 'p': 164*7c478bd9Sstevel@tonic-gate protofunc = NULL; 165*7c478bd9Sstevel@tonic-gate for (ptp = &prototab[0]; ptp->func; ptp++) 166*7c478bd9Sstevel@tonic-gate if (strcmp(optarg, ptp->name) == 0) { 167*7c478bd9Sstevel@tonic-gate protofunc = ptp->func; 168*7c478bd9Sstevel@tonic-gate break; 169*7c478bd9Sstevel@tonic-gate } 170*7c478bd9Sstevel@tonic-gate if (protofunc == NULL) 171*7c478bd9Sstevel@tonic-gate usage(cmdname); 172*7c478bd9Sstevel@tonic-gate break; 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate case '?': 175*7c478bd9Sstevel@tonic-gate usage(cmdname); 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate if (protofunc == NULL) 180*7c478bd9Sstevel@tonic-gate usage(cmdname); 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate if (targethost) { 183*7c478bd9Sstevel@tonic-gate /* we are faking it */ 184*7c478bd9Sstevel@tonic-gate if (debug) 185*7c478bd9Sstevel@tonic-gate fprintf(stdout, "targethost = %s\n", targethost); 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate if ((hp = gethostbyname(targethost)) == NULL) { 188*7c478bd9Sstevel@tonic-gate if ((targetaddr.s_addr = inet_addr(targethost)) == 189*7c478bd9Sstevel@tonic-gate (ulong_t)(-1)) { 190*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 191*7c478bd9Sstevel@tonic-gate "%s: cannot get IP address for %s\n", 192*7c478bd9Sstevel@tonic-gate cmdname, targethost); 193*7c478bd9Sstevel@tonic-gate return (1); 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate } else { 196*7c478bd9Sstevel@tonic-gate if (hp->h_length != sizeof (targetaddr)) { 197*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 198*7c478bd9Sstevel@tonic-gate "%s: cannot find host entry for %s\n", 199*7c478bd9Sstevel@tonic-gate cmdname, targethost); 200*7c478bd9Sstevel@tonic-gate return (1); 201*7c478bd9Sstevel@tonic-gate } else 202*7c478bd9Sstevel@tonic-gate (void) memcpy(&targetaddr.s_addr, hp->h_addr, 203*7c478bd9Sstevel@tonic-gate sizeof (targetaddr)); 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate } else 206*7c478bd9Sstevel@tonic-gate targetaddr.s_addr = 0; 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate if (optind < argc) { 209*7c478bd9Sstevel@tonic-gate /* interface names were specified */ 210*7c478bd9Sstevel@tonic-gate for (; optind < argc; optind++) { 211*7c478bd9Sstevel@tonic-gate if (debug) 212*7c478bd9Sstevel@tonic-gate fprintf(stdout, "Trying arg %s\n", 213*7c478bd9Sstevel@tonic-gate argv[optind]); 214*7c478bd9Sstevel@tonic-gate (*protofunc)(argv[optind], targetaddr); 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate } else { 217*7c478bd9Sstevel@tonic-gate /* no interface names specified - try them all */ 218*7c478bd9Sstevel@tonic-gate int ifcount = 0; /* count of useable interfaces */ 219*7c478bd9Sstevel@tonic-gate int s; 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 222*7c478bd9Sstevel@tonic-gate perror("socket"); 223*7c478bd9Sstevel@tonic-gate return (1); 224*7c478bd9Sstevel@tonic-gate } 225*7c478bd9Sstevel@tonic-gate #ifdef SIOCGIFNUM 226*7c478bd9Sstevel@tonic-gate if (ioctl(s, SIOCGIFNUM, (char *)&numifs) < 0) { 227*7c478bd9Sstevel@tonic-gate numifs = MAXIFS; 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate #else 230*7c478bd9Sstevel@tonic-gate numifs = MAXIFS; 231*7c478bd9Sstevel@tonic-gate #endif 232*7c478bd9Sstevel@tonic-gate bufsize = numifs * sizeof (struct ifreq); 233*7c478bd9Sstevel@tonic-gate reqbuf = (struct ifreq *)malloc(bufsize); 234*7c478bd9Sstevel@tonic-gate if (reqbuf == NULL) { 235*7c478bd9Sstevel@tonic-gate fprintf(stderr, "out of memory\n"); 236*7c478bd9Sstevel@tonic-gate return (1); 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate ifc.ifc_buf = (caddr_t)&reqbuf[0]; 239*7c478bd9Sstevel@tonic-gate ifc.ifc_len = bufsize; 240*7c478bd9Sstevel@tonic-gate if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { 241*7c478bd9Sstevel@tonic-gate perror("ioctl(SIOCGIFCONF)"); 242*7c478bd9Sstevel@tonic-gate return (1); 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate ifr = ifc.ifc_req; 245*7c478bd9Sstevel@tonic-gate n = ifc.ifc_len/sizeof (struct ifreq); 246*7c478bd9Sstevel@tonic-gate for (; n > 0; n--, ifr++) { 247*7c478bd9Sstevel@tonic-gate if (ioctl(s, SIOCGIFFLAGS, (char *)ifr) < 0) { 248*7c478bd9Sstevel@tonic-gate perror("ioctl(SIOCGIFFLAGS)"); 249*7c478bd9Sstevel@tonic-gate return (1); 250*7c478bd9Sstevel@tonic-gate } 251*7c478bd9Sstevel@tonic-gate if ((ifr->ifr_flags & IFF_LOOPBACK) || 252*7c478bd9Sstevel@tonic-gate !(ifr->ifr_flags & IFF_BROADCAST) || 253*7c478bd9Sstevel@tonic-gate !(ifr->ifr_flags & IFF_UP) || 254*7c478bd9Sstevel@tonic-gate (ifr->ifr_flags & IFF_NOARP) || 255*7c478bd9Sstevel@tonic-gate (ifr->ifr_flags & IFF_POINTOPOINT)) { 256*7c478bd9Sstevel@tonic-gate if (debug) 257*7c478bd9Sstevel@tonic-gate fprintf(stdout, "If %s not suitable\n", 258*7c478bd9Sstevel@tonic-gate ifr->ifr_name); 259*7c478bd9Sstevel@tonic-gate continue; 260*7c478bd9Sstevel@tonic-gate } else { 261*7c478bd9Sstevel@tonic-gate if (debug) 262*7c478bd9Sstevel@tonic-gate fprintf(stdout, "Trying device %s\n", 263*7c478bd9Sstevel@tonic-gate ifr->ifr_name); 264*7c478bd9Sstevel@tonic-gate (*protofunc)(ifr->ifr_name, targetaddr); 265*7c478bd9Sstevel@tonic-gate ifcount++; 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate } 268*7c478bd9Sstevel@tonic-gate if (verbose && ifcount == 0) { 269*7c478bd9Sstevel@tonic-gate fprintf(stderr, "No useable interfaces found.\n"); 270*7c478bd9Sstevel@tonic-gate return (1); 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate (void) close(s); 273*7c478bd9Sstevel@tonic-gate (void) free((char *)reqbuf); 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate return (0); 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate void 280*7c478bd9Sstevel@tonic-gate add_default_route(router_addr) 281*7c478bd9Sstevel@tonic-gate struct in_addr router_addr; 282*7c478bd9Sstevel@tonic-gate { 283*7c478bd9Sstevel@tonic-gate struct rtentry route; 284*7c478bd9Sstevel@tonic-gate struct sockaddr_in *sin; 285*7c478bd9Sstevel@tonic-gate int s; 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate (void) memset(&route, 0, sizeof (route)); 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate /* route destination is "default" - zero */ 290*7c478bd9Sstevel@tonic-gate /* LINTED - alignment OK (32bit) */ 291*7c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *)&route.rt_dst; 292*7c478bd9Sstevel@tonic-gate sin->sin_family = AF_INET; 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate /* LINTED - alignment OK (32bit) */ 295*7c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *)&route.rt_gateway; 296*7c478bd9Sstevel@tonic-gate sin->sin_family = AF_INET; 297*7c478bd9Sstevel@tonic-gate sin->sin_addr.s_addr = router_addr.s_addr; 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate route.rt_flags = RTF_GATEWAY | RTF_UP; 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 302*7c478bd9Sstevel@tonic-gate perror("socket"); 303*7c478bd9Sstevel@tonic-gate return; 304*7c478bd9Sstevel@tonic-gate } 305*7c478bd9Sstevel@tonic-gate if (ioctl(s, SIOCADDRT, (char *)&route) == -1) { 306*7c478bd9Sstevel@tonic-gate perror("add default route"); 307*7c478bd9Sstevel@tonic-gate return; 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate (void) close(s); 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate int 314*7c478bd9Sstevel@tonic-gate bpanswer(res, nb) 315*7c478bd9Sstevel@tonic-gate struct bp_whoami_res *res; 316*7c478bd9Sstevel@tonic-gate struct netbuf *nb; 317*7c478bd9Sstevel@tonic-gate { 318*7c478bd9Sstevel@tonic-gate struct in_addr router_addr; 319*7c478bd9Sstevel@tonic-gate static int set; 320*7c478bd9Sstevel@tonic-gate int len; 321*7c478bd9Sstevel@tonic-gate char errbuf[MAX_MACHINE_NAME + 28]; 322*7c478bd9Sstevel@tonic-gate /* MAX_MACHINE_NAME + strlen ("sysinfo(SI_SET_HOSTNAME)()") + null */ 323*7c478bd9Sstevel@tonic-gate 324*7c478bd9Sstevel@tonic-gate (void) memcpy(&router_addr, &res->router_address.bp_address_u.ip_addr, 325*7c478bd9Sstevel@tonic-gate sizeof (router_addr)); 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate if (verbose) { 328*7c478bd9Sstevel@tonic-gate struct sockaddr_in *addr; 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate if (nb) { 331*7c478bd9Sstevel@tonic-gate /* LINTED - alignment (32bit) OK */ 332*7c478bd9Sstevel@tonic-gate addr = (struct sockaddr_in *)nb->buf; 333*7c478bd9Sstevel@tonic-gate fprintf(stdout, "From [%s]: ", 334*7c478bd9Sstevel@tonic-gate inet_ntoa(addr->sin_addr)); 335*7c478bd9Sstevel@tonic-gate } else { 336*7c478bd9Sstevel@tonic-gate fprintf(stdout, "Reply:\\t\\t"); 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate fprintf(stdout, "hostname = %s\n", res->client_name); 339*7c478bd9Sstevel@tonic-gate fprintf(stdout, "\t\typdomain = %s\n", res->domain_name); 340*7c478bd9Sstevel@tonic-gate fprintf(stdout, "\t\trouter = %s\n", inet_ntoa(router_addr)); 341*7c478bd9Sstevel@tonic-gate } 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate if (!safe && !set) { 344*7c478bd9Sstevel@tonic-gate /* 345*7c478bd9Sstevel@tonic-gate * Stuff the values from the RPC reply into the kernel. 346*7c478bd9Sstevel@tonic-gate * Only allow one pass through this code; There's no reason 347*7c478bd9Sstevel@tonic-gate * why all replies should tweak the kernel. 348*7c478bd9Sstevel@tonic-gate */ 349*7c478bd9Sstevel@tonic-gate set++; 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate len = strlen(res->client_name); 352*7c478bd9Sstevel@tonic-gate if (len != 0) { 353*7c478bd9Sstevel@tonic-gate if (!echo_host) { 354*7c478bd9Sstevel@tonic-gate if (sysinfo(SI_SET_HOSTNAME, res->client_name, 355*7c478bd9Sstevel@tonic-gate len) < 0) { 356*7c478bd9Sstevel@tonic-gate (void) snprintf(errbuf, sizeof (errbuf), 357*7c478bd9Sstevel@tonic-gate "sysinfo(SI_SET_HOSTNAME)(%s)", 358*7c478bd9Sstevel@tonic-gate res->client_name); 359*7c478bd9Sstevel@tonic-gate perror(errbuf); 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate } else 362*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%s\n", 363*7c478bd9Sstevel@tonic-gate res->client_name); 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate len = strlen(res->domain_name); 367*7c478bd9Sstevel@tonic-gate if (len != 0) { 368*7c478bd9Sstevel@tonic-gate if (setdomainname(res->domain_name, len) == -1) { 369*7c478bd9Sstevel@tonic-gate (void) snprintf(errbuf, sizeof (errbuf), 370*7c478bd9Sstevel@tonic-gate "setdomainname(%s)", res->domain_name); 371*7c478bd9Sstevel@tonic-gate perror(errbuf); 372*7c478bd9Sstevel@tonic-gate } 373*7c478bd9Sstevel@tonic-gate } 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate /* we really should validate this router value */ 376*7c478bd9Sstevel@tonic-gate if (router_addr.s_addr != 0) 377*7c478bd9Sstevel@tonic-gate add_default_route(router_addr); 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate if (multiple) 381*7c478bd9Sstevel@tonic-gate return (NULL); 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate /* our job is done */ 384*7c478bd9Sstevel@tonic-gate exit(0); 385*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 386*7c478bd9Sstevel@tonic-gate } 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate void 389*7c478bd9Sstevel@tonic-gate bp_whoami(device, addr) 390*7c478bd9Sstevel@tonic-gate char *device; 391*7c478bd9Sstevel@tonic-gate struct in_addr addr; 392*7c478bd9Sstevel@tonic-gate { 393*7c478bd9Sstevel@tonic-gate struct bp_whoami_arg req; 394*7c478bd9Sstevel@tonic-gate struct bp_whoami_res res; 395*7c478bd9Sstevel@tonic-gate struct in_addr lookupaddr; 396*7c478bd9Sstevel@tonic-gate enum clnt_stat stat; 397*7c478bd9Sstevel@tonic-gate int val = 1; 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate if (debug) 400*7c478bd9Sstevel@tonic-gate fprintf(stdout, "bp_whoami on interface %s addr %s\n", device, 401*7c478bd9Sstevel@tonic-gate inet_ntoa(addr)); 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate if (addr.s_addr == 0) { 404*7c478bd9Sstevel@tonic-gate if (get_ifdata(device, &lookupaddr, &if_netmask) == -1) 405*7c478bd9Sstevel@tonic-gate exit(1); 406*7c478bd9Sstevel@tonic-gate } else 407*7c478bd9Sstevel@tonic-gate (void) memcpy(&lookupaddr, &addr, sizeof (addr)); 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate lookupaddr.s_addr = ntohl(lookupaddr.s_addr); 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate if (debug) 412*7c478bd9Sstevel@tonic-gate fprintf(stdout, "lookup address is %s\n", 413*7c478bd9Sstevel@tonic-gate inet_ntoa(lookupaddr)); 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate (void) memset(&req, 0, sizeof (req)); 416*7c478bd9Sstevel@tonic-gate (void) memset(&res, 0, sizeof (res)); 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate req.client_address.address_type = IP_ADDR_TYPE; 419*7c478bd9Sstevel@tonic-gate (void) memcpy(&req.client_address.bp_address_u.ip_addr, &lookupaddr, 420*7c478bd9Sstevel@tonic-gate sizeof (lookupaddr)); 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate /* 423*7c478bd9Sstevel@tonic-gate * Broadcast using portmap version number 2 ONLY to 424*7c478bd9Sstevel@tonic-gate * prevent broadcast storm 425*7c478bd9Sstevel@tonic-gate */ 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate (void) __rpc_control(CLCR_SET_LOWVERS, &val); 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate stat = rpc_broadcast(BOOTPARAMPROG, BOOTPARAMVERS, BOOTPARAMPROC_WHOAMI, 430*7c478bd9Sstevel@tonic-gate xdr_bp_whoami_arg, (caddr_t)&req, xdr_bp_whoami_res, (caddr_t)&res, 431*7c478bd9Sstevel@tonic-gate (resultproc_t)bpanswer, "udp"); 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate /* Now try version 3 as well */ 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate val = 0; 436*7c478bd9Sstevel@tonic-gate (void) __rpc_control(CLCR_SET_LOWVERS, &val); 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate stat = rpc_broadcast(BOOTPARAMPROG, BOOTPARAMVERS, 439*7c478bd9Sstevel@tonic-gate BOOTPARAMPROC_WHOAMI, xdr_bp_whoami_arg, (caddr_t)&req, 440*7c478bd9Sstevel@tonic-gate xdr_bp_whoami_res, (caddr_t)&res, (resultproc_t)bpanswer, "udp"); 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate if (stat != RPC_SUCCESS) { 443*7c478bd9Sstevel@tonic-gate clnt_perrno(stat); 444*7c478bd9Sstevel@tonic-gate exit(1); 445*7c478bd9Sstevel@tonic-gate } 446*7c478bd9Sstevel@tonic-gate } 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate /* 450*7c478bd9Sstevel@tonic-gate * Get IP address of an interface. As long as we are looking, get the 451*7c478bd9Sstevel@tonic-gate * netmask as well. 452*7c478bd9Sstevel@tonic-gate */ 453*7c478bd9Sstevel@tonic-gate int 454*7c478bd9Sstevel@tonic-gate get_ifdata(dev, ipp, maskp) 455*7c478bd9Sstevel@tonic-gate char *dev; 456*7c478bd9Sstevel@tonic-gate ulong_t *ipp, *maskp; 457*7c478bd9Sstevel@tonic-gate { 458*7c478bd9Sstevel@tonic-gate struct ifreq ifr; 459*7c478bd9Sstevel@tonic-gate /* LINTED - alignment OK (32bit) */ 460*7c478bd9Sstevel@tonic-gate struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr; 461*7c478bd9Sstevel@tonic-gate int s; 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 464*7c478bd9Sstevel@tonic-gate perror("socket"); 465*7c478bd9Sstevel@tonic-gate return (-1); 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate if (strlcpy(ifr.ifr_name, dev, sizeof (ifr.ifr_name)) >= 469*7c478bd9Sstevel@tonic-gate sizeof (ifr.ifr_name)) { 470*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Device name too long %s\n", 471*7c478bd9Sstevel@tonic-gate dev); 472*7c478bd9Sstevel@tonic-gate return (-1); 473*7c478bd9Sstevel@tonic-gate } 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate if (ipp) { 476*7c478bd9Sstevel@tonic-gate if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 477*7c478bd9Sstevel@tonic-gate perror("ioctl(SIOCGIFADDR)"); 478*7c478bd9Sstevel@tonic-gate return (-1); 479*7c478bd9Sstevel@tonic-gate } 480*7c478bd9Sstevel@tonic-gate *ipp = ntohl(sin->sin_addr.s_addr); 481*7c478bd9Sstevel@tonic-gate 482*7c478bd9Sstevel@tonic-gate if (debug) 483*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Interface '%s' address %s\n", 484*7c478bd9Sstevel@tonic-gate dev, inet_ntoa(sin->sin_addr)); 485*7c478bd9Sstevel@tonic-gate } 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate if (maskp) { 488*7c478bd9Sstevel@tonic-gate if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) { 489*7c478bd9Sstevel@tonic-gate perror("SIOCGIFNETMASK"); 490*7c478bd9Sstevel@tonic-gate return (-1); 491*7c478bd9Sstevel@tonic-gate } 492*7c478bd9Sstevel@tonic-gate *maskp = ntohl(sin->sin_addr.s_addr); 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate if (debug) 495*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 496*7c478bd9Sstevel@tonic-gate "Interface '%s' subnet mask %s\n", dev, 497*7c478bd9Sstevel@tonic-gate inet_ntoa(sin->sin_addr)); 498*7c478bd9Sstevel@tonic-gate } 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate (void) close(s); 501*7c478bd9Sstevel@tonic-gate return (0); 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate void 505*7c478bd9Sstevel@tonic-gate notsupported() 506*7c478bd9Sstevel@tonic-gate { 507*7c478bd9Sstevel@tonic-gate fprintf(stderr, "requested protocol is not supported\n"); 508*7c478bd9Sstevel@tonic-gate exit(1); 509*7c478bd9Sstevel@tonic-gate } 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate void 512*7c478bd9Sstevel@tonic-gate usage(cmdname) 513*7c478bd9Sstevel@tonic-gate char *cmdname; 514*7c478bd9Sstevel@tonic-gate { 515*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "usage: %s [-v] [-n] [-m] [-h] [<ifname>] " 516*7c478bd9Sstevel@tonic-gate "[-f <hostname>] -p bootparams|bootp\n", cmdname); 517*7c478bd9Sstevel@tonic-gate (void) fflush(stderr); 518*7c478bd9Sstevel@tonic-gate exit(1); 519*7c478bd9Sstevel@tonic-gate } 520