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 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 27*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD 31*7c478bd9Sstevel@tonic-gate * under license from the Regents of the University of California. 32*7c478bd9Sstevel@tonic-gate */ 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate /* 37*7c478bd9Sstevel@tonic-gate * rarpd.c Reverse-ARP server. 38*7c478bd9Sstevel@tonic-gate * Refer to RFC 903 "A Reverse Address Resolution Protocol". 39*7c478bd9Sstevel@tonic-gate */ 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #define _REENTRANT 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate #include <thread.h> 44*7c478bd9Sstevel@tonic-gate #include <synch.h> 45*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 46*7c478bd9Sstevel@tonic-gate #include <unistd.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/resource.h> 48*7c478bd9Sstevel@tonic-gate #include <stdio.h> 49*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 50*7c478bd9Sstevel@tonic-gate #include <string.h> 51*7c478bd9Sstevel@tonic-gate #include <ctype.h> 52*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 54*7c478bd9Sstevel@tonic-gate #include <dirent.h> 55*7c478bd9Sstevel@tonic-gate #include <syslog.h> 56*7c478bd9Sstevel@tonic-gate #include <signal.h> 57*7c478bd9Sstevel@tonic-gate #include <netdb.h> 58*7c478bd9Sstevel@tonic-gate #include <errno.h> 59*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 60*7c478bd9Sstevel@tonic-gate #include <sys/sockio.h> 61*7c478bd9Sstevel@tonic-gate #include <net/if.h> 62*7c478bd9Sstevel@tonic-gate #include <netinet/if_ether.h> 63*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 64*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 65*7c478bd9Sstevel@tonic-gate #include <stropts.h> 66*7c478bd9Sstevel@tonic-gate #include <sys/dlpi.h> 67*7c478bd9Sstevel@tonic-gate #include <libinetutil.h> 68*7c478bd9Sstevel@tonic-gate #include <net/if_types.h> 69*7c478bd9Sstevel@tonic-gate #include <net/if_dl.h> 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate #define BOOTDIR "/tftpboot" /* boot files directory */ 72*7c478bd9Sstevel@tonic-gate #define DEVDIR "/dev" /* devices directory */ 73*7c478bd9Sstevel@tonic-gate #define DEVIP "/dev/ip" /* path to ip driver */ 74*7c478bd9Sstevel@tonic-gate #define DEVARP "/dev/arp" /* path to arp driver */ 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate #define BUFSIZE 2048 /* max receive frame length */ 77*7c478bd9Sstevel@tonic-gate #define MAXPATHL 128 /* max path length */ 78*7c478bd9Sstevel@tonic-gate #define MAXHOSTL 128 /* max host name length */ 79*7c478bd9Sstevel@tonic-gate #define MAXIFS 256 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* 82*7c478bd9Sstevel@tonic-gate * Logical network devices 83*7c478bd9Sstevel@tonic-gate */ 84*7c478bd9Sstevel@tonic-gate struct ifdev { 85*7c478bd9Sstevel@tonic-gate char ldevice[IFNAMSIZ]; 86*7c478bd9Sstevel@tonic-gate int lunit; 87*7c478bd9Sstevel@tonic-gate ipaddr_t ipaddr; /* network order */ 88*7c478bd9Sstevel@tonic-gate ipaddr_t if_netmask; /* host order */ 89*7c478bd9Sstevel@tonic-gate ipaddr_t if_ipaddr; /* host order */ 90*7c478bd9Sstevel@tonic-gate ipaddr_t if_netnum; /* host order, with subnet */ 91*7c478bd9Sstevel@tonic-gate struct ifdev *next; 92*7c478bd9Sstevel@tonic-gate }; 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate /* 95*7c478bd9Sstevel@tonic-gate * Physical network device 96*7c478bd9Sstevel@tonic-gate */ 97*7c478bd9Sstevel@tonic-gate struct rarpdev { 98*7c478bd9Sstevel@tonic-gate char device[IFNAMSIZ]; 99*7c478bd9Sstevel@tonic-gate int unit; 100*7c478bd9Sstevel@tonic-gate int fd; 101*7c478bd9Sstevel@tonic-gate uchar_t *lladdr; /* mac address of interface */ 102*7c478bd9Sstevel@tonic-gate int ifaddrlen; /* mac address length */ 103*7c478bd9Sstevel@tonic-gate int ifsaplen; /* indicates dlsap format */ 104*7c478bd9Sstevel@tonic-gate int ifrarplen; /* size of rarp data packet */ 105*7c478bd9Sstevel@tonic-gate struct ifdev *ifdev; /* private interface info */ 106*7c478bd9Sstevel@tonic-gate struct rarpdev *next; /* list of managed devices */ 107*7c478bd9Sstevel@tonic-gate }; 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate struct rarpreply { 110*7c478bd9Sstevel@tonic-gate struct rarpdev *rdev; /* which device reply for */ 111*7c478bd9Sstevel@tonic-gate struct timeval tv; /* send RARP reply by when */ 112*7c478bd9Sstevel@tonic-gate uchar_t *lldest; /* target mac to send reply */ 113*7c478bd9Sstevel@tonic-gate uchar_t *arprep; /* [R]ARP response */ 114*7c478bd9Sstevel@tonic-gate struct rarpreply *next; 115*7c478bd9Sstevel@tonic-gate }; 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate static struct rarpreply *delay_list; 118*7c478bd9Sstevel@tonic-gate static sema_t delay_sema; 119*7c478bd9Sstevel@tonic-gate static mutex_t delay_mutex; 120*7c478bd9Sstevel@tonic-gate static mutex_t debug_mutex; 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate static struct rarpdev *rarpdev_head; 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate /* 125*7c478bd9Sstevel@tonic-gate * Globals initialized before multi-threading 126*7c478bd9Sstevel@tonic-gate */ 127*7c478bd9Sstevel@tonic-gate static char *cmdname; /* command name from argv[0] */ 128*7c478bd9Sstevel@tonic-gate static int dflag = 0; /* enable diagnostics */ 129*7c478bd9Sstevel@tonic-gate static int aflag = 0; /* start rarpd on all interfaces */ 130*7c478bd9Sstevel@tonic-gate static char *alarmmsg; /* alarm() error message */ 131*7c478bd9Sstevel@tonic-gate static long pc_name_max; /* pathconf maximum path name */ 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate static void getintf(void); 134*7c478bd9Sstevel@tonic-gate static struct rarpdev *find_device(ifspec_t *); 135*7c478bd9Sstevel@tonic-gate static void init_rarpdev(struct rarpdev *); 136*7c478bd9Sstevel@tonic-gate static void do_rarp(void *); 137*7c478bd9Sstevel@tonic-gate static void rarp_request(struct rarpdev *, struct arphdr *, 138*7c478bd9Sstevel@tonic-gate uchar_t *); 139*7c478bd9Sstevel@tonic-gate static void add_arp(struct rarpdev *, uchar_t *, uchar_t *); 140*7c478bd9Sstevel@tonic-gate static void arp_request(struct rarpdev *, struct arphdr *, uchar_t *); 141*7c478bd9Sstevel@tonic-gate static int rarp_open(struct rarpdev *, ushort_t); 142*7c478bd9Sstevel@tonic-gate static void do_delay_write(void *); 143*7c478bd9Sstevel@tonic-gate static void delay_write(struct rarpdev *, struct rarpreply *); 144*7c478bd9Sstevel@tonic-gate static int rarp_write(int, struct rarpreply *); 145*7c478bd9Sstevel@tonic-gate static int mightboot(ipaddr_t); 146*7c478bd9Sstevel@tonic-gate static void get_ifdata(char *, int, ipaddr_t *, ipaddr_t *); 147*7c478bd9Sstevel@tonic-gate static int get_ipaddr(struct rarpdev *, uchar_t *, uchar_t *, ipaddr_t *); 148*7c478bd9Sstevel@tonic-gate static void sigalarm(int); 149*7c478bd9Sstevel@tonic-gate static int strioctl(int, int, int, int, char *); 150*7c478bd9Sstevel@tonic-gate static void usage(); 151*7c478bd9Sstevel@tonic-gate static void syserr(char *); 152*7c478bd9Sstevel@tonic-gate static void error(char *, ...); 153*7c478bd9Sstevel@tonic-gate static void debug(char *, ...); 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate extern int optind; 156*7c478bd9Sstevel@tonic-gate extern char *optarg; 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate int 159*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 160*7c478bd9Sstevel@tonic-gate { 161*7c478bd9Sstevel@tonic-gate int c; 162*7c478bd9Sstevel@tonic-gate struct rlimit rl; 163*7c478bd9Sstevel@tonic-gate struct rarpdev *rdev; 164*7c478bd9Sstevel@tonic-gate int i; 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate cmdname = argv[0]; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "ad")) != -1) { 169*7c478bd9Sstevel@tonic-gate switch (c) { 170*7c478bd9Sstevel@tonic-gate case 'a': 171*7c478bd9Sstevel@tonic-gate aflag = 1; 172*7c478bd9Sstevel@tonic-gate break; 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate case 'd': 175*7c478bd9Sstevel@tonic-gate dflag = 1; 176*7c478bd9Sstevel@tonic-gate break; 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate default: 179*7c478bd9Sstevel@tonic-gate usage(); 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate if ((!aflag && (argc - optind) != 2) || 184*7c478bd9Sstevel@tonic-gate (aflag && (argc - optind) != 0)) { 185*7c478bd9Sstevel@tonic-gate usage(); 186*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 187*7c478bd9Sstevel@tonic-gate } 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate if (!dflag) { 190*7c478bd9Sstevel@tonic-gate /* 191*7c478bd9Sstevel@tonic-gate * Background 192*7c478bd9Sstevel@tonic-gate */ 193*7c478bd9Sstevel@tonic-gate switch (fork()) { 194*7c478bd9Sstevel@tonic-gate case -1: /* error */ 195*7c478bd9Sstevel@tonic-gate syserr("fork"); 196*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate case 0: /* child */ 199*7c478bd9Sstevel@tonic-gate break; 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate default: /* parent */ 202*7c478bd9Sstevel@tonic-gate return (0); 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate for (i = 0; i < 3; i++) { 205*7c478bd9Sstevel@tonic-gate (void) close(i); 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate (void) open("/", O_RDONLY, 0); 208*7c478bd9Sstevel@tonic-gate (void) dup2(0, 1); 209*7c478bd9Sstevel@tonic-gate (void) dup2(0, 2); 210*7c478bd9Sstevel@tonic-gate /* 211*7c478bd9Sstevel@tonic-gate * Detach terminal 212*7c478bd9Sstevel@tonic-gate */ 213*7c478bd9Sstevel@tonic-gate if (setsid() < 0) 214*7c478bd9Sstevel@tonic-gate syserr("setsid"); 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate rl.rlim_cur = RLIM_INFINITY; 218*7c478bd9Sstevel@tonic-gate rl.rlim_max = RLIM_INFINITY; 219*7c478bd9Sstevel@tonic-gate if (setrlimit(RLIMIT_NOFILE, &rl) == -1) 220*7c478bd9Sstevel@tonic-gate syserr("setrlimit"); 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate /* 223*7c478bd9Sstevel@tonic-gate * Look up the maximum name length of the BOOTDIR, it may not 224*7c478bd9Sstevel@tonic-gate * exist so use /, if that fails use a reasonable sized buffer. 225*7c478bd9Sstevel@tonic-gate */ 226*7c478bd9Sstevel@tonic-gate if ((pc_name_max = pathconf(BOOTDIR, _PC_NAME_MAX)) == -1) { 227*7c478bd9Sstevel@tonic-gate if ((pc_name_max = pathconf("/", _PC_NAME_MAX)) == -1) { 228*7c478bd9Sstevel@tonic-gate pc_name_max = 255; 229*7c478bd9Sstevel@tonic-gate } 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate (void) openlog(cmdname, LOG_PID, LOG_DAEMON); 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate if (aflag) { 235*7c478bd9Sstevel@tonic-gate /* 236*7c478bd9Sstevel@tonic-gate * Get each interface name and load rarpdev list 237*7c478bd9Sstevel@tonic-gate */ 238*7c478bd9Sstevel@tonic-gate getintf(); 239*7c478bd9Sstevel@tonic-gate } else { 240*7c478bd9Sstevel@tonic-gate ifspec_t ifsp; 241*7c478bd9Sstevel@tonic-gate struct ifdev *ifdev; 242*7c478bd9Sstevel@tonic-gate char buf[IFNAMSIZ + 1]; 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate /* 245*7c478bd9Sstevel@tonic-gate * Load specified device as only element of the list 246*7c478bd9Sstevel@tonic-gate */ 247*7c478bd9Sstevel@tonic-gate rarpdev_head = (struct rarpdev *)calloc(1, 248*7c478bd9Sstevel@tonic-gate sizeof (struct rarpdev)); 249*7c478bd9Sstevel@tonic-gate if (rarpdev_head == NULL) { 250*7c478bd9Sstevel@tonic-gate error("out of memory"); 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate (void) strncpy(buf, argv[optind], IFNAMSIZ); 253*7c478bd9Sstevel@tonic-gate (void) strncat(buf, argv[optind + 1], IFNAMSIZ - strlen(buf)); 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate if ((ifdev = calloc(1, sizeof (struct ifdev))) == NULL) { 256*7c478bd9Sstevel@tonic-gate error("out of memory"); 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate if (!ifparse_ifspec(buf, &ifsp) || ifsp.ifsp_modcnt != 0) { 260*7c478bd9Sstevel@tonic-gate error("invalid interface specification"); 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate if (ifsp.ifsp_lunvalid) { 264*7c478bd9Sstevel@tonic-gate (void) snprintf(ifdev->ldevice, 265*7c478bd9Sstevel@tonic-gate sizeof (ifdev->ldevice), "%s%d:", 266*7c478bd9Sstevel@tonic-gate ifsp.ifsp_devnm, ifsp.ifsp_ppa); 267*7c478bd9Sstevel@tonic-gate ifdev->lunit = ifsp.ifsp_lun; 268*7c478bd9Sstevel@tonic-gate } else 269*7c478bd9Sstevel@tonic-gate ifdev->lunit = -1; /* no logical unit */ 270*7c478bd9Sstevel@tonic-gate (void) strlcpy(rarpdev_head->device, ifsp.ifsp_devnm, 271*7c478bd9Sstevel@tonic-gate sizeof (rarpdev_head->device)); 272*7c478bd9Sstevel@tonic-gate rarpdev_head->unit = ifsp.ifsp_ppa; 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate ifdev->next = rarpdev_head->ifdev; 275*7c478bd9Sstevel@tonic-gate rarpdev_head->ifdev = ifdev; 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate /* 279*7c478bd9Sstevel@tonic-gate * Initialize each rarpdev 280*7c478bd9Sstevel@tonic-gate */ 281*7c478bd9Sstevel@tonic-gate for (rdev = rarpdev_head; rdev != NULL; rdev = rdev->next) { 282*7c478bd9Sstevel@tonic-gate init_rarpdev(rdev); 283*7c478bd9Sstevel@tonic-gate } 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate (void) sema_init(&delay_sema, 0, USYNC_THREAD, NULL); 286*7c478bd9Sstevel@tonic-gate (void) mutex_init(&delay_mutex, USYNC_THREAD, NULL); 287*7c478bd9Sstevel@tonic-gate (void) mutex_init(&debug_mutex, USYNC_THREAD, NULL); 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate /* 290*7c478bd9Sstevel@tonic-gate * Start delayed processing thread 291*7c478bd9Sstevel@tonic-gate */ 292*7c478bd9Sstevel@tonic-gate (void) thr_create(NULL, NULL, (void *(*)(void *))do_delay_write, NULL, 293*7c478bd9Sstevel@tonic-gate THR_NEW_LWP, NULL); 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate /* 296*7c478bd9Sstevel@tonic-gate * Start RARP processing for each device 297*7c478bd9Sstevel@tonic-gate */ 298*7c478bd9Sstevel@tonic-gate for (rdev = rarpdev_head; rdev != NULL; rdev = rdev->next) { 299*7c478bd9Sstevel@tonic-gate if (rdev->fd != -1) { 300*7c478bd9Sstevel@tonic-gate (void) thr_create(NULL, NULL, 301*7c478bd9Sstevel@tonic-gate (void *(*)(void *))do_rarp, (void *)rdev, 302*7c478bd9Sstevel@tonic-gate THR_NEW_LWP, NULL); 303*7c478bd9Sstevel@tonic-gate } 304*7c478bd9Sstevel@tonic-gate } 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate /* 307*7c478bd9Sstevel@tonic-gate * Exit main() thread 308*7c478bd9Sstevel@tonic-gate */ 309*7c478bd9Sstevel@tonic-gate thr_exit(NULL); 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate return (0); 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate static void 315*7c478bd9Sstevel@tonic-gate getintf(void) 316*7c478bd9Sstevel@tonic-gate { 317*7c478bd9Sstevel@tonic-gate int fd; 318*7c478bd9Sstevel@tonic-gate int numifs; 319*7c478bd9Sstevel@tonic-gate unsigned bufsize; 320*7c478bd9Sstevel@tonic-gate struct ifreq *reqbuf; 321*7c478bd9Sstevel@tonic-gate struct ifconf ifconf; 322*7c478bd9Sstevel@tonic-gate struct ifreq *ifr; 323*7c478bd9Sstevel@tonic-gate struct rarpdev *rdev; 324*7c478bd9Sstevel@tonic-gate struct ifdev *ifdev; 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate /* 327*7c478bd9Sstevel@tonic-gate * Open the IP provider. 328*7c478bd9Sstevel@tonic-gate */ 329*7c478bd9Sstevel@tonic-gate if ((fd = open(DEVIP, 0)) < 0) 330*7c478bd9Sstevel@tonic-gate syserr(DEVIP); 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate /* 333*7c478bd9Sstevel@tonic-gate * Ask IP for the list of configured interfaces. 334*7c478bd9Sstevel@tonic-gate */ 335*7c478bd9Sstevel@tonic-gate if (ioctl(fd, SIOCGIFNUM, (char *)&numifs) < 0) { 336*7c478bd9Sstevel@tonic-gate numifs = MAXIFS; 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate bufsize = numifs * sizeof (struct ifreq); 339*7c478bd9Sstevel@tonic-gate reqbuf = (struct ifreq *)malloc(bufsize); 340*7c478bd9Sstevel@tonic-gate if (reqbuf == NULL) { 341*7c478bd9Sstevel@tonic-gate error("out of memory"); 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate ifconf.ifc_len = bufsize; 345*7c478bd9Sstevel@tonic-gate ifconf.ifc_buf = (caddr_t)reqbuf; 346*7c478bd9Sstevel@tonic-gate if (ioctl(fd, SIOCGIFCONF, (char *)&ifconf) < 0) 347*7c478bd9Sstevel@tonic-gate syserr("SIOCGIFCONF"); 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate /* 350*7c478bd9Sstevel@tonic-gate * Initialize a rarpdev for each interface 351*7c478bd9Sstevel@tonic-gate */ 352*7c478bd9Sstevel@tonic-gate for (ifr = ifconf.ifc_req; ifconf.ifc_len > 0; 353*7c478bd9Sstevel@tonic-gate ifr++, ifconf.ifc_len -= sizeof (struct ifreq)) { 354*7c478bd9Sstevel@tonic-gate ifspec_t ifsp; 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate if (ioctl(fd, SIOCGIFFLAGS, (char *)ifr) < 0) { 357*7c478bd9Sstevel@tonic-gate syserr("ioctl SIOCGIFFLAGS"); 358*7c478bd9Sstevel@tonic-gate exit(1); 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate if ((ifr->ifr_flags & IFF_LOOPBACK) || 361*7c478bd9Sstevel@tonic-gate !(ifr->ifr_flags & IFF_UP) || 362*7c478bd9Sstevel@tonic-gate !(ifr->ifr_flags & IFF_BROADCAST) || 363*7c478bd9Sstevel@tonic-gate (ifr->ifr_flags & IFF_NOARP) || 364*7c478bd9Sstevel@tonic-gate (ifr->ifr_flags & IFF_POINTOPOINT)) 365*7c478bd9Sstevel@tonic-gate continue; 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate if (!ifparse_ifspec(ifr->ifr_name, &ifsp)) 368*7c478bd9Sstevel@tonic-gate error("ifparse_ifspec failed"); 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate /* 371*7c478bd9Sstevel@tonic-gate * Look for an existing device for logical interfaces 372*7c478bd9Sstevel@tonic-gate */ 373*7c478bd9Sstevel@tonic-gate if ((rdev = find_device(&ifsp)) == NULL) { 374*7c478bd9Sstevel@tonic-gate rdev = calloc(1, sizeof (struct rarpdev)); 375*7c478bd9Sstevel@tonic-gate if (rdev == NULL) 376*7c478bd9Sstevel@tonic-gate error("out of memory"); 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate (void) strlcpy(rdev->device, ifsp.ifsp_devnm, 379*7c478bd9Sstevel@tonic-gate sizeof (rdev->device)); 380*7c478bd9Sstevel@tonic-gate rdev->unit = ifsp.ifsp_ppa; 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate rdev->next = rarpdev_head; 383*7c478bd9Sstevel@tonic-gate rarpdev_head = rdev; 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate if ((ifdev = calloc(1, sizeof (struct ifdev))) == NULL) 387*7c478bd9Sstevel@tonic-gate error("out of memory"); 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate if (ifsp.ifsp_lunvalid) { 390*7c478bd9Sstevel@tonic-gate (void) snprintf(ifdev->ldevice, 391*7c478bd9Sstevel@tonic-gate sizeof (ifdev->ldevice), "%s%d:", 392*7c478bd9Sstevel@tonic-gate ifsp.ifsp_devnm, ifsp.ifsp_ppa); 393*7c478bd9Sstevel@tonic-gate ifdev->lunit = ifsp.ifsp_lun; 394*7c478bd9Sstevel@tonic-gate } else 395*7c478bd9Sstevel@tonic-gate ifdev->lunit = -1; /* no logical unit */ 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate ifdev->next = rdev->ifdev; 398*7c478bd9Sstevel@tonic-gate rdev->ifdev = ifdev; 399*7c478bd9Sstevel@tonic-gate } 400*7c478bd9Sstevel@tonic-gate (void) free((char *)reqbuf); 401*7c478bd9Sstevel@tonic-gate } 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate static struct rarpdev * 404*7c478bd9Sstevel@tonic-gate find_device(ifspec_t *specp) 405*7c478bd9Sstevel@tonic-gate { 406*7c478bd9Sstevel@tonic-gate struct rarpdev *rdev; 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate for (rdev = rarpdev_head; rdev != NULL; rdev = rdev->next) { 409*7c478bd9Sstevel@tonic-gate if (specp->ifsp_ppa == rdev->unit && 410*7c478bd9Sstevel@tonic-gate strcmp(specp->ifsp_devnm, rdev->device) == 0) 411*7c478bd9Sstevel@tonic-gate return (rdev); 412*7c478bd9Sstevel@tonic-gate } 413*7c478bd9Sstevel@tonic-gate return (NULL); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate static void 417*7c478bd9Sstevel@tonic-gate init_rarpdev(struct rarpdev *rdev) 418*7c478bd9Sstevel@tonic-gate { 419*7c478bd9Sstevel@tonic-gate char *dev; 420*7c478bd9Sstevel@tonic-gate int unit; 421*7c478bd9Sstevel@tonic-gate struct ifdev *ifdev; 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate /* 424*7c478bd9Sstevel@tonic-gate * Open datalink provider and get our mac address. 425*7c478bd9Sstevel@tonic-gate */ 426*7c478bd9Sstevel@tonic-gate rdev->fd = rarp_open(rdev, ETHERTYPE_REVARP); 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate /* 429*7c478bd9Sstevel@tonic-gate * rarp_open may fail on certain types of interfaces 430*7c478bd9Sstevel@tonic-gate */ 431*7c478bd9Sstevel@tonic-gate if (rdev->fd < 0) { 432*7c478bd9Sstevel@tonic-gate rdev->fd = -1; 433*7c478bd9Sstevel@tonic-gate return; 434*7c478bd9Sstevel@tonic-gate } 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate /* 437*7c478bd9Sstevel@tonic-gate * Get the IP address and netmask from directory service for 438*7c478bd9Sstevel@tonic-gate * each logical interface. 439*7c478bd9Sstevel@tonic-gate */ 440*7c478bd9Sstevel@tonic-gate for (ifdev = rdev->ifdev; ifdev != NULL; ifdev = ifdev->next) { 441*7c478bd9Sstevel@tonic-gate /* 442*7c478bd9Sstevel@tonic-gate * If lunit == -1 then this is the primary interface name 443*7c478bd9Sstevel@tonic-gate */ 444*7c478bd9Sstevel@tonic-gate if (ifdev->lunit == -1) { 445*7c478bd9Sstevel@tonic-gate dev = rdev->device; 446*7c478bd9Sstevel@tonic-gate unit = rdev->unit; 447*7c478bd9Sstevel@tonic-gate } else { 448*7c478bd9Sstevel@tonic-gate dev = ifdev->ldevice; 449*7c478bd9Sstevel@tonic-gate unit = ifdev->lunit; 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate get_ifdata(dev, unit, &ifdev->if_ipaddr, &ifdev->if_netmask); 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate /* 454*7c478bd9Sstevel@tonic-gate * Use IP address of the interface. 455*7c478bd9Sstevel@tonic-gate */ 456*7c478bd9Sstevel@tonic-gate ifdev->if_netnum = ifdev->if_ipaddr & ifdev->if_netmask; 457*7c478bd9Sstevel@tonic-gate ifdev->ipaddr = (ipaddr_t)htonl(ifdev->if_ipaddr); 458*7c478bd9Sstevel@tonic-gate } 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate static void 462*7c478bd9Sstevel@tonic-gate do_rarp(void *buf) 463*7c478bd9Sstevel@tonic-gate { 464*7c478bd9Sstevel@tonic-gate struct rarpdev *rdev = (struct rarpdev *)buf; 465*7c478bd9Sstevel@tonic-gate struct strbuf ctl; 466*7c478bd9Sstevel@tonic-gate char ctlbuf[BUFSIZE]; 467*7c478bd9Sstevel@tonic-gate struct strbuf data; 468*7c478bd9Sstevel@tonic-gate char databuf[BUFSIZE]; 469*7c478bd9Sstevel@tonic-gate char *cause; 470*7c478bd9Sstevel@tonic-gate struct arphdr *ans; 471*7c478bd9Sstevel@tonic-gate uchar_t *shost; 472*7c478bd9Sstevel@tonic-gate int flags, ret; 473*7c478bd9Sstevel@tonic-gate union DL_primitives *dlp; 474*7c478bd9Sstevel@tonic-gate uchar_t *laddrp; 475*7c478bd9Sstevel@tonic-gate char *str = NULL; 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate /* 478*7c478bd9Sstevel@tonic-gate * Sanity check; if we hit this limit, ctlbuf/databuf needs 479*7c478bd9Sstevel@tonic-gate * to be malloc'ed. 480*7c478bd9Sstevel@tonic-gate */ 481*7c478bd9Sstevel@tonic-gate if ((sizeof (ctlbuf) < (DL_UNITDATA_IND_SIZE + rdev->ifaddrlen)) || 482*7c478bd9Sstevel@tonic-gate (sizeof (databuf) < rdev->ifrarplen)) 483*7c478bd9Sstevel@tonic-gate error("unsupported media"); 484*7c478bd9Sstevel@tonic-gate 485*7c478bd9Sstevel@tonic-gate if (((shost = (uchar_t *)malloc(rdev->ifaddrlen)) == NULL) || 486*7c478bd9Sstevel@tonic-gate ((ans = (struct arphdr *)malloc(rdev->ifrarplen)) == NULL)) 487*7c478bd9Sstevel@tonic-gate syserr("malloc"); 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate if (dflag) { 490*7c478bd9Sstevel@tonic-gate str = _link_ntoa(rdev->lladdr, str, rdev->ifaddrlen, IFT_OTHER); 491*7c478bd9Sstevel@tonic-gate if (str != NULL) { 492*7c478bd9Sstevel@tonic-gate debug("starting rarp service on device %s%d address %s", 493*7c478bd9Sstevel@tonic-gate rdev->device, rdev->unit, str); 494*7c478bd9Sstevel@tonic-gate free(str); 495*7c478bd9Sstevel@tonic-gate } 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate /* 499*7c478bd9Sstevel@tonic-gate * read RARP packets and respond to them. 500*7c478bd9Sstevel@tonic-gate */ 501*7c478bd9Sstevel@tonic-gate for (;;) { 502*7c478bd9Sstevel@tonic-gate ctl.len = 0; 503*7c478bd9Sstevel@tonic-gate ctl.maxlen = BUFSIZE; 504*7c478bd9Sstevel@tonic-gate ctl.buf = ctlbuf; 505*7c478bd9Sstevel@tonic-gate data.len = 0; 506*7c478bd9Sstevel@tonic-gate data.maxlen = BUFSIZE; 507*7c478bd9Sstevel@tonic-gate data.buf = databuf; 508*7c478bd9Sstevel@tonic-gate flags = 0; 509*7c478bd9Sstevel@tonic-gate 510*7c478bd9Sstevel@tonic-gate if ((ret = getmsg(rdev->fd, &ctl, &data, &flags)) < 0) 511*7c478bd9Sstevel@tonic-gate syserr("getmsg"); 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate /* 514*7c478bd9Sstevel@tonic-gate * Validate DL_UNITDATA_IND. 515*7c478bd9Sstevel@tonic-gate */ 516*7c478bd9Sstevel@tonic-gate /* LINTED pointer */ 517*7c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)ctlbuf; 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate (void) memcpy(ans, databuf, rdev->ifrarplen); 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate cause = NULL; 522*7c478bd9Sstevel@tonic-gate if (ctl.len == 0) 523*7c478bd9Sstevel@tonic-gate cause = "missing control part of message"; 524*7c478bd9Sstevel@tonic-gate else if (ctl.len < 0) 525*7c478bd9Sstevel@tonic-gate cause = "short control part of message"; 526*7c478bd9Sstevel@tonic-gate else if (dlp->dl_primitive != DL_UNITDATA_IND) 527*7c478bd9Sstevel@tonic-gate cause = "not unitdata_ind"; 528*7c478bd9Sstevel@tonic-gate else if (ret & MORECTL) 529*7c478bd9Sstevel@tonic-gate cause = "MORECTL flag"; 530*7c478bd9Sstevel@tonic-gate else if (ret & MOREDATA) 531*7c478bd9Sstevel@tonic-gate cause = "MOREDATA flag"; 532*7c478bd9Sstevel@tonic-gate else if (ctl.len < DL_UNITDATA_IND_SIZE) 533*7c478bd9Sstevel@tonic-gate cause = "short unitdata_ind"; 534*7c478bd9Sstevel@tonic-gate else if (data.len < rdev->ifrarplen) 535*7c478bd9Sstevel@tonic-gate cause = "short arp"; 536*7c478bd9Sstevel@tonic-gate else if (ans->ar_hrd != htons(ARPHRD_ETHER)) 537*7c478bd9Sstevel@tonic-gate cause = "hrd"; 538*7c478bd9Sstevel@tonic-gate else if (ans->ar_pro != htons(ETHERTYPE_IP)) 539*7c478bd9Sstevel@tonic-gate cause = "pro"; 540*7c478bd9Sstevel@tonic-gate else if (ans->ar_hln != rdev->ifaddrlen) 541*7c478bd9Sstevel@tonic-gate cause = "hln"; 542*7c478bd9Sstevel@tonic-gate else if (ans->ar_pln != sizeof (ipaddr_t)) 543*7c478bd9Sstevel@tonic-gate cause = "pln"; 544*7c478bd9Sstevel@tonic-gate if (cause) { 545*7c478bd9Sstevel@tonic-gate if (dflag) 546*7c478bd9Sstevel@tonic-gate debug("receive check failed: cause: %s", 547*7c478bd9Sstevel@tonic-gate cause); 548*7c478bd9Sstevel@tonic-gate continue; 549*7c478bd9Sstevel@tonic-gate } 550*7c478bd9Sstevel@tonic-gate 551*7c478bd9Sstevel@tonic-gate /* 552*7c478bd9Sstevel@tonic-gate * Good request. 553*7c478bd9Sstevel@tonic-gate * Pick out the mac source address of this RARP request. 554*7c478bd9Sstevel@tonic-gate */ 555*7c478bd9Sstevel@tonic-gate laddrp = (uchar_t *)ctlbuf + 556*7c478bd9Sstevel@tonic-gate dlp->unitdata_ind.dl_src_addr_offset; 557*7c478bd9Sstevel@tonic-gate (void) memcpy(shost, laddrp, ans->ar_hln); 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate /* 560*7c478bd9Sstevel@tonic-gate * Handle the request. 561*7c478bd9Sstevel@tonic-gate */ 562*7c478bd9Sstevel@tonic-gate switch (ntohs(ans->ar_op)) { 563*7c478bd9Sstevel@tonic-gate case REVARP_REQUEST: 564*7c478bd9Sstevel@tonic-gate rarp_request(rdev, ans, shost); 565*7c478bd9Sstevel@tonic-gate break; 566*7c478bd9Sstevel@tonic-gate 567*7c478bd9Sstevel@tonic-gate case ARPOP_REQUEST: 568*7c478bd9Sstevel@tonic-gate arp_request(rdev, ans, shost); 569*7c478bd9Sstevel@tonic-gate break; 570*7c478bd9Sstevel@tonic-gate 571*7c478bd9Sstevel@tonic-gate case REVARP_REPLY: 572*7c478bd9Sstevel@tonic-gate if (dflag) 573*7c478bd9Sstevel@tonic-gate debug("REVARP_REPLY ignored"); 574*7c478bd9Sstevel@tonic-gate break; 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate case ARPOP_REPLY: 577*7c478bd9Sstevel@tonic-gate if (dflag) 578*7c478bd9Sstevel@tonic-gate debug("ARPOP_REPLY ignored"); 579*7c478bd9Sstevel@tonic-gate break; 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate default: 582*7c478bd9Sstevel@tonic-gate if (dflag) 583*7c478bd9Sstevel@tonic-gate debug("unknown opcode 0x%x", ans->ar_op); 584*7c478bd9Sstevel@tonic-gate break; 585*7c478bd9Sstevel@tonic-gate } 586*7c478bd9Sstevel@tonic-gate } 587*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 588*7c478bd9Sstevel@tonic-gate } 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate /* 591*7c478bd9Sstevel@tonic-gate * Reverse address determination and allocation code. 592*7c478bd9Sstevel@tonic-gate */ 593*7c478bd9Sstevel@tonic-gate static void 594*7c478bd9Sstevel@tonic-gate rarp_request(struct rarpdev *rdev, struct arphdr *rp, uchar_t *shost) 595*7c478bd9Sstevel@tonic-gate { 596*7c478bd9Sstevel@tonic-gate ipaddr_t tpa, spa; 597*7c478bd9Sstevel@tonic-gate struct rarpreply *rrp; 598*7c478bd9Sstevel@tonic-gate uchar_t *shap, *thap, *spap, *tpap; 599*7c478bd9Sstevel@tonic-gate char *str = NULL; 600*7c478bd9Sstevel@tonic-gate 601*7c478bd9Sstevel@tonic-gate shap = (uchar_t *)rp + sizeof (struct arphdr); 602*7c478bd9Sstevel@tonic-gate spap = shap + rp->ar_hln; 603*7c478bd9Sstevel@tonic-gate thap = spap + rp->ar_pln; 604*7c478bd9Sstevel@tonic-gate tpap = thap + rp->ar_hln; 605*7c478bd9Sstevel@tonic-gate 606*7c478bd9Sstevel@tonic-gate if (dflag) { 607*7c478bd9Sstevel@tonic-gate str = _link_ntoa(thap, str, rdev->ifaddrlen, IFT_OTHER); 608*7c478bd9Sstevel@tonic-gate if (str != NULL) { 609*7c478bd9Sstevel@tonic-gate debug("RARP_REQUEST for %s", str); 610*7c478bd9Sstevel@tonic-gate free(str); 611*7c478bd9Sstevel@tonic-gate } 612*7c478bd9Sstevel@tonic-gate } 613*7c478bd9Sstevel@tonic-gate 614*7c478bd9Sstevel@tonic-gate /* 615*7c478bd9Sstevel@tonic-gate * third party lookups are rare and wonderful 616*7c478bd9Sstevel@tonic-gate */ 617*7c478bd9Sstevel@tonic-gate if ((memcmp(shap, thap, rdev->ifaddrlen) != 0) || 618*7c478bd9Sstevel@tonic-gate (memcmp(shap, shost, rdev->ifaddrlen) != 0)) { 619*7c478bd9Sstevel@tonic-gate if (dflag) 620*7c478bd9Sstevel@tonic-gate debug("weird (3rd party lookup)"); 621*7c478bd9Sstevel@tonic-gate } 622*7c478bd9Sstevel@tonic-gate 623*7c478bd9Sstevel@tonic-gate /* 624*7c478bd9Sstevel@tonic-gate * fill in given parts of reply packet 625*7c478bd9Sstevel@tonic-gate */ 626*7c478bd9Sstevel@tonic-gate (void) memcpy(shap, rdev->lladdr, rdev->ifaddrlen); 627*7c478bd9Sstevel@tonic-gate 628*7c478bd9Sstevel@tonic-gate /* 629*7c478bd9Sstevel@tonic-gate * If a good address is stored in our lookup tables, return it 630*7c478bd9Sstevel@tonic-gate * immediately or after a delay. Store it our kernel's ARP cache. 631*7c478bd9Sstevel@tonic-gate */ 632*7c478bd9Sstevel@tonic-gate if (get_ipaddr(rdev, thap, tpap, &spa)) 633*7c478bd9Sstevel@tonic-gate return; 634*7c478bd9Sstevel@tonic-gate (void) memcpy(spap, &spa, sizeof (spa)); 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate add_arp(rdev, tpap, thap); 637*7c478bd9Sstevel@tonic-gate 638*7c478bd9Sstevel@tonic-gate rp->ar_op = htons(REVARP_REPLY); 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate if (dflag) { 641*7c478bd9Sstevel@tonic-gate struct in_addr addr; 642*7c478bd9Sstevel@tonic-gate 643*7c478bd9Sstevel@tonic-gate (void) memcpy(&addr, tpap, sizeof (ipaddr_t)); 644*7c478bd9Sstevel@tonic-gate debug("good lookup, maps to %s", inet_ntoa(addr)); 645*7c478bd9Sstevel@tonic-gate } 646*7c478bd9Sstevel@tonic-gate 647*7c478bd9Sstevel@tonic-gate rrp = (struct rarpreply *)calloc(1, sizeof (struct rarpreply) + 648*7c478bd9Sstevel@tonic-gate rdev->ifaddrlen + rdev->ifrarplen); 649*7c478bd9Sstevel@tonic-gate if (rrp == NULL) 650*7c478bd9Sstevel@tonic-gate error("out of memory"); 651*7c478bd9Sstevel@tonic-gate rrp->lldest = (uchar_t *)rrp + sizeof (struct rarpreply); 652*7c478bd9Sstevel@tonic-gate rrp->arprep = rrp->lldest + rdev->ifaddrlen; 653*7c478bd9Sstevel@tonic-gate 654*7c478bd9Sstevel@tonic-gate /* 655*7c478bd9Sstevel@tonic-gate * Create rarpreply structure. 656*7c478bd9Sstevel@tonic-gate */ 657*7c478bd9Sstevel@tonic-gate (void) gettimeofday(&rrp->tv, NULL); 658*7c478bd9Sstevel@tonic-gate rrp->tv.tv_sec += 3; /* delay */ 659*7c478bd9Sstevel@tonic-gate rrp->rdev = rdev; 660*7c478bd9Sstevel@tonic-gate (void) memcpy(rrp->lldest, shost, rdev->ifaddrlen); 661*7c478bd9Sstevel@tonic-gate (void) memcpy(rrp->arprep, rp, rdev->ifrarplen); 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate /* 664*7c478bd9Sstevel@tonic-gate * If this is diskless and we're not its bootserver, let the 665*7c478bd9Sstevel@tonic-gate * bootserver reply first by delaying a while. 666*7c478bd9Sstevel@tonic-gate */ 667*7c478bd9Sstevel@tonic-gate (void) memcpy(&tpa, tpap, sizeof (ipaddr_t)); 668*7c478bd9Sstevel@tonic-gate if (mightboot(ntohl(tpa))) { 669*7c478bd9Sstevel@tonic-gate if (rarp_write(rdev->fd, rrp) < 0) 670*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "Bad rarp_write: %m"); 671*7c478bd9Sstevel@tonic-gate if (dflag) 672*7c478bd9Sstevel@tonic-gate debug("immediate reply sent"); 673*7c478bd9Sstevel@tonic-gate (void) free(rrp); 674*7c478bd9Sstevel@tonic-gate } else { 675*7c478bd9Sstevel@tonic-gate delay_write(rdev, rrp); 676*7c478bd9Sstevel@tonic-gate } 677*7c478bd9Sstevel@tonic-gate } 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate /* 680*7c478bd9Sstevel@tonic-gate * Download an ARP entry into our kernel. 681*7c478bd9Sstevel@tonic-gate */ 682*7c478bd9Sstevel@tonic-gate static void 683*7c478bd9Sstevel@tonic-gate add_arp(struct rarpdev *rdev, uchar_t *ip, uchar_t *laddr) 684*7c478bd9Sstevel@tonic-gate { 685*7c478bd9Sstevel@tonic-gate struct xarpreq ar; 686*7c478bd9Sstevel@tonic-gate struct sockaddr_in *sin; 687*7c478bd9Sstevel@tonic-gate int fd; 688*7c478bd9Sstevel@tonic-gate 689*7c478bd9Sstevel@tonic-gate /* 690*7c478bd9Sstevel@tonic-gate * Common part of query or set 691*7c478bd9Sstevel@tonic-gate */ 692*7c478bd9Sstevel@tonic-gate (void) memset(&ar, 0, sizeof (ar)); 693*7c478bd9Sstevel@tonic-gate ar.xarp_pa.ss_family = AF_INET; 694*7c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *)&ar.xarp_pa; 695*7c478bd9Sstevel@tonic-gate (void) memcpy(&sin->sin_addr, ip, sizeof (ipaddr_t)); 696*7c478bd9Sstevel@tonic-gate 697*7c478bd9Sstevel@tonic-gate /* 698*7c478bd9Sstevel@tonic-gate * Open the IP provider. 699*7c478bd9Sstevel@tonic-gate */ 700*7c478bd9Sstevel@tonic-gate if ((fd = open(DEVARP, 0)) < 0) 701*7c478bd9Sstevel@tonic-gate syserr(DEVARP); 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate /* 704*7c478bd9Sstevel@tonic-gate * Set the entry 705*7c478bd9Sstevel@tonic-gate */ 706*7c478bd9Sstevel@tonic-gate (void) memcpy(LLADDR(&ar.xarp_ha), laddr, rdev->ifaddrlen); 707*7c478bd9Sstevel@tonic-gate ar.xarp_ha.sdl_alen = rdev->ifaddrlen; 708*7c478bd9Sstevel@tonic-gate ar.xarp_ha.sdl_family = AF_LINK; 709*7c478bd9Sstevel@tonic-gate (void) strioctl(fd, SIOCDXARP, -1, sizeof (struct xarpreq), 710*7c478bd9Sstevel@tonic-gate (char *)&ar); 711*7c478bd9Sstevel@tonic-gate if (strioctl(fd, SIOCSXARP, -1, sizeof (struct xarpreq), 712*7c478bd9Sstevel@tonic-gate (char *)&ar) < 0) 713*7c478bd9Sstevel@tonic-gate syserr("SIOCSXARP"); 714*7c478bd9Sstevel@tonic-gate 715*7c478bd9Sstevel@tonic-gate (void) close(fd); 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate /* 719*7c478bd9Sstevel@tonic-gate * The RARP spec says we must be able to process ARP requests, 720*7c478bd9Sstevel@tonic-gate * even through the packet type is RARP. Let's hope this feature 721*7c478bd9Sstevel@tonic-gate * is not heavily used. 722*7c478bd9Sstevel@tonic-gate */ 723*7c478bd9Sstevel@tonic-gate static void 724*7c478bd9Sstevel@tonic-gate arp_request(struct rarpdev *rdev, struct arphdr *rp, uchar_t *shost) 725*7c478bd9Sstevel@tonic-gate { 726*7c478bd9Sstevel@tonic-gate struct rarpreply *rrp; 727*7c478bd9Sstevel@tonic-gate struct ifdev *ifdev; 728*7c478bd9Sstevel@tonic-gate uchar_t *shap, *thap, *spap, *tpap; 729*7c478bd9Sstevel@tonic-gate int ret; 730*7c478bd9Sstevel@tonic-gate 731*7c478bd9Sstevel@tonic-gate shap = (uchar_t *)rp + sizeof (struct arphdr); 732*7c478bd9Sstevel@tonic-gate spap = shap + rp->ar_hln; 733*7c478bd9Sstevel@tonic-gate thap = spap + rp->ar_pln; 734*7c478bd9Sstevel@tonic-gate tpap = thap + rp->ar_hln; 735*7c478bd9Sstevel@tonic-gate 736*7c478bd9Sstevel@tonic-gate if (dflag) 737*7c478bd9Sstevel@tonic-gate debug("ARPOP_REQUEST"); 738*7c478bd9Sstevel@tonic-gate 739*7c478bd9Sstevel@tonic-gate for (ifdev = rdev->ifdev; ifdev != NULL; ifdev = ifdev->next) { 740*7c478bd9Sstevel@tonic-gate if (memcmp(&ifdev->ipaddr, tpap, sizeof (ipaddr_t)) == 0) 741*7c478bd9Sstevel@tonic-gate break; 742*7c478bd9Sstevel@tonic-gate } 743*7c478bd9Sstevel@tonic-gate if (ifdev == NULL) 744*7c478bd9Sstevel@tonic-gate return; 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate rp->ar_op = ARPOP_REPLY; 747*7c478bd9Sstevel@tonic-gate (void) memcpy(shap, rdev->lladdr, rdev->ifaddrlen); 748*7c478bd9Sstevel@tonic-gate (void) memcpy(spap, &ifdev->ipaddr, sizeof (ipaddr_t)); 749*7c478bd9Sstevel@tonic-gate (void) memcpy(thap, rdev->lladdr, rdev->ifaddrlen); 750*7c478bd9Sstevel@tonic-gate 751*7c478bd9Sstevel@tonic-gate add_arp(rdev, tpap, thap); 752*7c478bd9Sstevel@tonic-gate 753*7c478bd9Sstevel@tonic-gate /* 754*7c478bd9Sstevel@tonic-gate * Create rarp reply structure. 755*7c478bd9Sstevel@tonic-gate */ 756*7c478bd9Sstevel@tonic-gate rrp = (struct rarpreply *)calloc(1, sizeof (struct rarpreply) + 757*7c478bd9Sstevel@tonic-gate rdev->ifaddrlen + rdev->ifrarplen); 758*7c478bd9Sstevel@tonic-gate if (rrp == NULL) 759*7c478bd9Sstevel@tonic-gate error("out of memory"); 760*7c478bd9Sstevel@tonic-gate rrp->lldest = (uchar_t *)rrp + sizeof (struct rarpreply); 761*7c478bd9Sstevel@tonic-gate rrp->arprep = rrp->lldest + rdev->ifaddrlen; 762*7c478bd9Sstevel@tonic-gate rrp->rdev = rdev; 763*7c478bd9Sstevel@tonic-gate 764*7c478bd9Sstevel@tonic-gate (void) memcpy(rrp->lldest, shost, rdev->ifaddrlen); 765*7c478bd9Sstevel@tonic-gate (void) memcpy(rrp->arprep, rp, rdev->ifrarplen); 766*7c478bd9Sstevel@tonic-gate 767*7c478bd9Sstevel@tonic-gate ret = rarp_write(rdev->fd, rrp); 768*7c478bd9Sstevel@tonic-gate free(rrp); 769*7c478bd9Sstevel@tonic-gate if (ret < 0) 770*7c478bd9Sstevel@tonic-gate error("rarp_write error"); 771*7c478bd9Sstevel@tonic-gate } 772*7c478bd9Sstevel@tonic-gate 773*7c478bd9Sstevel@tonic-gate /* 774*7c478bd9Sstevel@tonic-gate * OPEN the datalink provider device, ATTACH to the unit, 775*7c478bd9Sstevel@tonic-gate * and BIND to the revarp type. 776*7c478bd9Sstevel@tonic-gate * Return the resulting descriptor. 777*7c478bd9Sstevel@tonic-gate * 778*7c478bd9Sstevel@tonic-gate * MT-UNSAFE 779*7c478bd9Sstevel@tonic-gate */ 780*7c478bd9Sstevel@tonic-gate static int 781*7c478bd9Sstevel@tonic-gate rarp_open(struct rarpdev *rarpdev, ushort_t type) 782*7c478bd9Sstevel@tonic-gate { 783*7c478bd9Sstevel@tonic-gate register int fd; 784*7c478bd9Sstevel@tonic-gate char path[MAXPATHL]; 785*7c478bd9Sstevel@tonic-gate union DL_primitives *dlp; 786*7c478bd9Sstevel@tonic-gate char buf[BUFSIZE]; 787*7c478bd9Sstevel@tonic-gate struct strbuf ctl; 788*7c478bd9Sstevel@tonic-gate int flags; 789*7c478bd9Sstevel@tonic-gate uchar_t *eap; 790*7c478bd9Sstevel@tonic-gate char *device = rarpdev->device; 791*7c478bd9Sstevel@tonic-gate int unit = rarpdev->unit; 792*7c478bd9Sstevel@tonic-gate char *str = NULL; 793*7c478bd9Sstevel@tonic-gate 794*7c478bd9Sstevel@tonic-gate /* 795*7c478bd9Sstevel@tonic-gate * Prefix the device name with "/dev/" if it doesn't 796*7c478bd9Sstevel@tonic-gate * start with a "/" . 797*7c478bd9Sstevel@tonic-gate */ 798*7c478bd9Sstevel@tonic-gate if (*device == '/') 799*7c478bd9Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "%s", device); 800*7c478bd9Sstevel@tonic-gate else 801*7c478bd9Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "%s/%s", DEVDIR, device); 802*7c478bd9Sstevel@tonic-gate 803*7c478bd9Sstevel@tonic-gate /* 804*7c478bd9Sstevel@tonic-gate * Open the datalink provider. 805*7c478bd9Sstevel@tonic-gate */ 806*7c478bd9Sstevel@tonic-gate if ((fd = open(path, O_RDWR)) < 0) 807*7c478bd9Sstevel@tonic-gate syserr(path); 808*7c478bd9Sstevel@tonic-gate 809*7c478bd9Sstevel@tonic-gate /* 810*7c478bd9Sstevel@tonic-gate * Issue DL_INFO_REQ and check DL_INFO_ACK for sanity. 811*7c478bd9Sstevel@tonic-gate */ 812*7c478bd9Sstevel@tonic-gate /* LINTED pointer */ 813*7c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)buf; 814*7c478bd9Sstevel@tonic-gate dlp->info_req.dl_primitive = DL_INFO_REQ; 815*7c478bd9Sstevel@tonic-gate 816*7c478bd9Sstevel@tonic-gate ctl.buf = (char *)dlp; 817*7c478bd9Sstevel@tonic-gate ctl.len = DL_INFO_REQ_SIZE; 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate if (putmsg(fd, &ctl, NULL, 0) < 0) 820*7c478bd9Sstevel@tonic-gate syserr("putmsg"); 821*7c478bd9Sstevel@tonic-gate 822*7c478bd9Sstevel@tonic-gate (void) signal(SIGALRM, sigalarm); 823*7c478bd9Sstevel@tonic-gate 824*7c478bd9Sstevel@tonic-gate alarmmsg = "DL_INFO_REQ failed: timeout waiting for DL_INFO_ACK"; 825*7c478bd9Sstevel@tonic-gate (void) alarm(10); 826*7c478bd9Sstevel@tonic-gate 827*7c478bd9Sstevel@tonic-gate ctl.buf = (char *)dlp; 828*7c478bd9Sstevel@tonic-gate ctl.len = 0; 829*7c478bd9Sstevel@tonic-gate ctl.maxlen = BUFSIZE; 830*7c478bd9Sstevel@tonic-gate flags = 0; 831*7c478bd9Sstevel@tonic-gate if (getmsg(fd, &ctl, NULL, &flags) < 0) 832*7c478bd9Sstevel@tonic-gate syserr("getmsg"); 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate (void) alarm(0); 835*7c478bd9Sstevel@tonic-gate (void) signal(SIGALRM, SIG_DFL); 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate /* 838*7c478bd9Sstevel@tonic-gate * Validate DL_INFO_ACK reply. 839*7c478bd9Sstevel@tonic-gate */ 840*7c478bd9Sstevel@tonic-gate if (ctl.len < sizeof (ulong_t)) 841*7c478bd9Sstevel@tonic-gate error("DL_INFO_REQ failed: short reply to DL_INFO_REQ"); 842*7c478bd9Sstevel@tonic-gate 843*7c478bd9Sstevel@tonic-gate if (dlp->dl_primitive != DL_INFO_ACK) 844*7c478bd9Sstevel@tonic-gate error("DL_INFO_REQ failed: dl_primitive 0x%lx received", 845*7c478bd9Sstevel@tonic-gate dlp->dl_primitive); 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate if (ctl.len < DL_INFO_ACK_SIZE) 848*7c478bd9Sstevel@tonic-gate error("DL_INFO_REQ failed: short info_ack: %d bytes", 849*7c478bd9Sstevel@tonic-gate ctl.len); 850*7c478bd9Sstevel@tonic-gate 851*7c478bd9Sstevel@tonic-gate if (dlp->info_ack.dl_version != DL_VERSION_2) 852*7c478bd9Sstevel@tonic-gate error("DL_INFO_ACK: incompatible version: %lu", 853*7c478bd9Sstevel@tonic-gate dlp->info_ack.dl_version); 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate if (dlp->info_ack.dl_sap_length != -2) { 856*7c478bd9Sstevel@tonic-gate if (dflag) 857*7c478bd9Sstevel@tonic-gate debug( 858*7c478bd9Sstevel@tonic-gate "%s%d DL_INFO_ACK: incompatible dl_sap_length: %ld", 859*7c478bd9Sstevel@tonic-gate device, unit, dlp->info_ack.dl_sap_length); 860*7c478bd9Sstevel@tonic-gate (void) close(fd); 861*7c478bd9Sstevel@tonic-gate return (-1); 862*7c478bd9Sstevel@tonic-gate } 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate if ((dlp->info_ack.dl_service_mode & DL_CLDLS) == 0) { 865*7c478bd9Sstevel@tonic-gate if (dflag) 866*7c478bd9Sstevel@tonic-gate debug( 867*7c478bd9Sstevel@tonic-gate "%s%d DL_INFO_ACK: incompatible dl_service_mode: 0x%lx", 868*7c478bd9Sstevel@tonic-gate device, unit, dlp->info_ack.dl_service_mode); 869*7c478bd9Sstevel@tonic-gate (void) close(fd); 870*7c478bd9Sstevel@tonic-gate return (-1); 871*7c478bd9Sstevel@tonic-gate } 872*7c478bd9Sstevel@tonic-gate 873*7c478bd9Sstevel@tonic-gate rarpdev->ifsaplen = dlp->info_ack.dl_sap_length; 874*7c478bd9Sstevel@tonic-gate rarpdev->ifaddrlen = dlp->info_ack.dl_addr_length - 875*7c478bd9Sstevel@tonic-gate abs(rarpdev->ifsaplen); 876*7c478bd9Sstevel@tonic-gate rarpdev->ifrarplen = sizeof (struct arphdr) + 877*7c478bd9Sstevel@tonic-gate (2 * sizeof (ipaddr_t)) + (2 * rarpdev->ifaddrlen); 878*7c478bd9Sstevel@tonic-gate 879*7c478bd9Sstevel@tonic-gate /* 880*7c478bd9Sstevel@tonic-gate * Issue DL_ATTACH_REQ. 881*7c478bd9Sstevel@tonic-gate */ 882*7c478bd9Sstevel@tonic-gate /* LINTED pointer */ 883*7c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)buf; 884*7c478bd9Sstevel@tonic-gate dlp->attach_req.dl_primitive = DL_ATTACH_REQ; 885*7c478bd9Sstevel@tonic-gate dlp->attach_req.dl_ppa = unit; 886*7c478bd9Sstevel@tonic-gate 887*7c478bd9Sstevel@tonic-gate ctl.buf = (char *)dlp; 888*7c478bd9Sstevel@tonic-gate ctl.len = DL_ATTACH_REQ_SIZE; 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate if (putmsg(fd, &ctl, NULL, 0) < 0) 891*7c478bd9Sstevel@tonic-gate syserr("putmsg"); 892*7c478bd9Sstevel@tonic-gate 893*7c478bd9Sstevel@tonic-gate (void) signal(SIGALRM, sigalarm); 894*7c478bd9Sstevel@tonic-gate alarmmsg = "DL_ATTACH_REQ failed: timeout waiting for DL_OK_ACK"; 895*7c478bd9Sstevel@tonic-gate 896*7c478bd9Sstevel@tonic-gate (void) alarm(10); 897*7c478bd9Sstevel@tonic-gate 898*7c478bd9Sstevel@tonic-gate ctl.buf = (char *)dlp; 899*7c478bd9Sstevel@tonic-gate ctl.len = 0; 900*7c478bd9Sstevel@tonic-gate ctl.maxlen = BUFSIZE; 901*7c478bd9Sstevel@tonic-gate flags = 0; 902*7c478bd9Sstevel@tonic-gate if (getmsg(fd, &ctl, NULL, &flags) < 0) 903*7c478bd9Sstevel@tonic-gate syserr("getmsg"); 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate (void) alarm(0); 906*7c478bd9Sstevel@tonic-gate (void) signal(SIGALRM, SIG_DFL); 907*7c478bd9Sstevel@tonic-gate 908*7c478bd9Sstevel@tonic-gate /* 909*7c478bd9Sstevel@tonic-gate * Validate DL_OK_ACK reply. 910*7c478bd9Sstevel@tonic-gate */ 911*7c478bd9Sstevel@tonic-gate if (ctl.len < sizeof (ulong_t)) 912*7c478bd9Sstevel@tonic-gate error("DL_ATTACH_REQ failed: short reply to attach request"); 913*7c478bd9Sstevel@tonic-gate 914*7c478bd9Sstevel@tonic-gate if (dlp->dl_primitive == DL_ERROR_ACK) 915*7c478bd9Sstevel@tonic-gate error("DL_ATTACH_REQ failed: dl_errno %lu unix_errno %lu", 916*7c478bd9Sstevel@tonic-gate dlp->error_ack.dl_errno, dlp->error_ack.dl_unix_errno); 917*7c478bd9Sstevel@tonic-gate 918*7c478bd9Sstevel@tonic-gate if (dlp->dl_primitive != DL_OK_ACK) 919*7c478bd9Sstevel@tonic-gate error("DL_ATTACH_REQ failed: dl_primitive 0x%lx received", 920*7c478bd9Sstevel@tonic-gate dlp->dl_primitive); 921*7c478bd9Sstevel@tonic-gate 922*7c478bd9Sstevel@tonic-gate if (ctl.len < DL_OK_ACK_SIZE) 923*7c478bd9Sstevel@tonic-gate error("attach failed: short ok_ack: %d bytes", 924*7c478bd9Sstevel@tonic-gate ctl.len); 925*7c478bd9Sstevel@tonic-gate 926*7c478bd9Sstevel@tonic-gate /* 927*7c478bd9Sstevel@tonic-gate * Issue DL_BIND_REQ. 928*7c478bd9Sstevel@tonic-gate */ 929*7c478bd9Sstevel@tonic-gate /* LINTED pointer */ 930*7c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)buf; 931*7c478bd9Sstevel@tonic-gate dlp->bind_req.dl_primitive = DL_BIND_REQ; 932*7c478bd9Sstevel@tonic-gate dlp->bind_req.dl_sap = type; 933*7c478bd9Sstevel@tonic-gate dlp->bind_req.dl_max_conind = 0; 934*7c478bd9Sstevel@tonic-gate dlp->bind_req.dl_service_mode = DL_CLDLS; 935*7c478bd9Sstevel@tonic-gate dlp->bind_req.dl_conn_mgmt = 0; 936*7c478bd9Sstevel@tonic-gate dlp->bind_req.dl_xidtest_flg = 0; 937*7c478bd9Sstevel@tonic-gate 938*7c478bd9Sstevel@tonic-gate ctl.buf = (char *)dlp; 939*7c478bd9Sstevel@tonic-gate ctl.len = DL_BIND_REQ_SIZE; 940*7c478bd9Sstevel@tonic-gate 941*7c478bd9Sstevel@tonic-gate if (putmsg(fd, &ctl, NULL, 0) < 0) 942*7c478bd9Sstevel@tonic-gate syserr("putmsg"); 943*7c478bd9Sstevel@tonic-gate 944*7c478bd9Sstevel@tonic-gate (void) signal(SIGALRM, sigalarm); 945*7c478bd9Sstevel@tonic-gate 946*7c478bd9Sstevel@tonic-gate alarmmsg = "DL_BIND_REQ failed: timeout waiting for DL_BIND_ACK"; 947*7c478bd9Sstevel@tonic-gate (void) alarm(10); 948*7c478bd9Sstevel@tonic-gate 949*7c478bd9Sstevel@tonic-gate ctl.buf = (char *)dlp; 950*7c478bd9Sstevel@tonic-gate ctl.len = 0; 951*7c478bd9Sstevel@tonic-gate ctl.maxlen = BUFSIZE; 952*7c478bd9Sstevel@tonic-gate flags = 0; 953*7c478bd9Sstevel@tonic-gate if (getmsg(fd, &ctl, NULL, &flags) < 0) 954*7c478bd9Sstevel@tonic-gate syserr("getmsg"); 955*7c478bd9Sstevel@tonic-gate 956*7c478bd9Sstevel@tonic-gate (void) alarm(0); 957*7c478bd9Sstevel@tonic-gate (void) signal(SIGALRM, SIG_DFL); 958*7c478bd9Sstevel@tonic-gate 959*7c478bd9Sstevel@tonic-gate /* 960*7c478bd9Sstevel@tonic-gate * Validate DL_BIND_ACK reply. 961*7c478bd9Sstevel@tonic-gate */ 962*7c478bd9Sstevel@tonic-gate if (ctl.len < sizeof (ulong_t)) 963*7c478bd9Sstevel@tonic-gate error("DL_BIND_REQ failed: short reply"); 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate if (dlp->dl_primitive == DL_ERROR_ACK) 966*7c478bd9Sstevel@tonic-gate error("DL_BIND_REQ failed: dl_errno %lu unix_errno %lu", 967*7c478bd9Sstevel@tonic-gate dlp->error_ack.dl_errno, dlp->error_ack.dl_unix_errno); 968*7c478bd9Sstevel@tonic-gate 969*7c478bd9Sstevel@tonic-gate if (dlp->dl_primitive != DL_BIND_ACK) 970*7c478bd9Sstevel@tonic-gate error("DL_BIND_REQ failed: dl_primitive 0x%lx received", 971*7c478bd9Sstevel@tonic-gate dlp->dl_primitive); 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate if (ctl.len < DL_BIND_ACK_SIZE) 974*7c478bd9Sstevel@tonic-gate error( 975*7c478bd9Sstevel@tonic-gate "DL_BIND_REQ failed: short bind acknowledgement received"); 976*7c478bd9Sstevel@tonic-gate 977*7c478bd9Sstevel@tonic-gate if (dlp->bind_ack.dl_sap != type) 978*7c478bd9Sstevel@tonic-gate error( 979*7c478bd9Sstevel@tonic-gate "DL_BIND_REQ failed: returned dl_sap %lu != requested sap %d", 980*7c478bd9Sstevel@tonic-gate dlp->bind_ack.dl_sap, type); 981*7c478bd9Sstevel@tonic-gate 982*7c478bd9Sstevel@tonic-gate /* 983*7c478bd9Sstevel@tonic-gate * Issue DL_PHYS_ADDR_REQ to get our local mac address. 984*7c478bd9Sstevel@tonic-gate */ 985*7c478bd9Sstevel@tonic-gate /* LINTED pointer */ 986*7c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)buf; 987*7c478bd9Sstevel@tonic-gate dlp->physaddr_req.dl_primitive = DL_PHYS_ADDR_REQ; 988*7c478bd9Sstevel@tonic-gate dlp->physaddr_req.dl_addr_type = DL_CURR_PHYS_ADDR; 989*7c478bd9Sstevel@tonic-gate 990*7c478bd9Sstevel@tonic-gate ctl.buf = (char *)dlp; 991*7c478bd9Sstevel@tonic-gate ctl.len = DL_PHYS_ADDR_REQ_SIZE; 992*7c478bd9Sstevel@tonic-gate 993*7c478bd9Sstevel@tonic-gate if (putmsg(fd, &ctl, NULL, 0) < 0) 994*7c478bd9Sstevel@tonic-gate syserr("putmsg"); 995*7c478bd9Sstevel@tonic-gate 996*7c478bd9Sstevel@tonic-gate (void) signal(SIGALRM, sigalarm); 997*7c478bd9Sstevel@tonic-gate 998*7c478bd9Sstevel@tonic-gate alarmmsg = 999*7c478bd9Sstevel@tonic-gate "DL_PHYS_ADDR_REQ failed: timeout waiting for DL_PHYS_ADDR_ACK"; 1000*7c478bd9Sstevel@tonic-gate (void) alarm(10); 1001*7c478bd9Sstevel@tonic-gate 1002*7c478bd9Sstevel@tonic-gate ctl.buf = (char *)dlp; 1003*7c478bd9Sstevel@tonic-gate ctl.len = 0; 1004*7c478bd9Sstevel@tonic-gate ctl.maxlen = BUFSIZE; 1005*7c478bd9Sstevel@tonic-gate flags = 0; 1006*7c478bd9Sstevel@tonic-gate if (getmsg(fd, &ctl, NULL, &flags) < 0) 1007*7c478bd9Sstevel@tonic-gate syserr("getmsg"); 1008*7c478bd9Sstevel@tonic-gate 1009*7c478bd9Sstevel@tonic-gate (void) alarm(0); 1010*7c478bd9Sstevel@tonic-gate (void) signal(SIGALRM, SIG_DFL); 1011*7c478bd9Sstevel@tonic-gate 1012*7c478bd9Sstevel@tonic-gate /* 1013*7c478bd9Sstevel@tonic-gate * Validate DL_PHYS_ADDR_ACK reply. 1014*7c478bd9Sstevel@tonic-gate */ 1015*7c478bd9Sstevel@tonic-gate if (ctl.len < sizeof (ulong_t)) 1016*7c478bd9Sstevel@tonic-gate error("DL_PHYS_ADDR_REQ failed: short reply"); 1017*7c478bd9Sstevel@tonic-gate 1018*7c478bd9Sstevel@tonic-gate if (dlp->dl_primitive == DL_ERROR_ACK) 1019*7c478bd9Sstevel@tonic-gate error("DL_PHYS_ADDR_REQ failed: dl_errno %lu unix_errno %lu", 1020*7c478bd9Sstevel@tonic-gate dlp->error_ack.dl_errno, dlp->error_ack.dl_unix_errno); 1021*7c478bd9Sstevel@tonic-gate 1022*7c478bd9Sstevel@tonic-gate if (dlp->dl_primitive != DL_PHYS_ADDR_ACK) 1023*7c478bd9Sstevel@tonic-gate error("DL_PHYS_ADDR_REQ failed: dl_primitive 0x%lx received", 1024*7c478bd9Sstevel@tonic-gate dlp->dl_primitive); 1025*7c478bd9Sstevel@tonic-gate 1026*7c478bd9Sstevel@tonic-gate if (ctl.len < DL_PHYS_ADDR_ACK_SIZE) 1027*7c478bd9Sstevel@tonic-gate error("DL_PHYS_ADDR_REQ failed: short ack received"); 1028*7c478bd9Sstevel@tonic-gate 1029*7c478bd9Sstevel@tonic-gate if (dlp->physaddr_ack.dl_addr_length != rarpdev->ifaddrlen) { 1030*7c478bd9Sstevel@tonic-gate if (dflag) 1031*7c478bd9Sstevel@tonic-gate debug( 1032*7c478bd9Sstevel@tonic-gate "%s%d DL_PHYS_ADDR_ACK failed: incompatible dl_addr_length: %lu", 1033*7c478bd9Sstevel@tonic-gate device, unit, dlp->physaddr_ack.dl_addr_length); 1034*7c478bd9Sstevel@tonic-gate (void) close(fd); 1035*7c478bd9Sstevel@tonic-gate return (-1); 1036*7c478bd9Sstevel@tonic-gate } 1037*7c478bd9Sstevel@tonic-gate 1038*7c478bd9Sstevel@tonic-gate /* 1039*7c478bd9Sstevel@tonic-gate * Save our mac address. 1040*7c478bd9Sstevel@tonic-gate */ 1041*7c478bd9Sstevel@tonic-gate if ((rarpdev->lladdr = (uchar_t *)malloc(rarpdev->ifaddrlen)) == NULL) { 1042*7c478bd9Sstevel@tonic-gate if (dflag) 1043*7c478bd9Sstevel@tonic-gate debug(" %s%d malloc failed: %d bytes", device, 1044*7c478bd9Sstevel@tonic-gate unit, rarpdev->ifaddrlen); 1045*7c478bd9Sstevel@tonic-gate (void) close(fd); 1046*7c478bd9Sstevel@tonic-gate return (-1); 1047*7c478bd9Sstevel@tonic-gate } 1048*7c478bd9Sstevel@tonic-gate 1049*7c478bd9Sstevel@tonic-gate eap = (uchar_t *)dlp + dlp->physaddr_ack.dl_addr_offset; 1050*7c478bd9Sstevel@tonic-gate (void) memcpy(rarpdev->lladdr, eap, dlp->physaddr_ack.dl_addr_length); 1051*7c478bd9Sstevel@tonic-gate 1052*7c478bd9Sstevel@tonic-gate if (dflag) { 1053*7c478bd9Sstevel@tonic-gate str = _link_ntoa(rarpdev->lladdr, str, rarpdev->ifaddrlen, 1054*7c478bd9Sstevel@tonic-gate IFT_OTHER); 1055*7c478bd9Sstevel@tonic-gate if (str != NULL) { 1056*7c478bd9Sstevel@tonic-gate debug("device %s%d lladdress %s", device, unit, str); 1057*7c478bd9Sstevel@tonic-gate free(str); 1058*7c478bd9Sstevel@tonic-gate } 1059*7c478bd9Sstevel@tonic-gate } 1060*7c478bd9Sstevel@tonic-gate 1061*7c478bd9Sstevel@tonic-gate return (fd); 1062*7c478bd9Sstevel@tonic-gate } 1063*7c478bd9Sstevel@tonic-gate 1064*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1065*7c478bd9Sstevel@tonic-gate static void 1066*7c478bd9Sstevel@tonic-gate do_delay_write(void *buf) 1067*7c478bd9Sstevel@tonic-gate { 1068*7c478bd9Sstevel@tonic-gate struct timeval tv; 1069*7c478bd9Sstevel@tonic-gate struct rarpreply *rrp; 1070*7c478bd9Sstevel@tonic-gate int err; 1071*7c478bd9Sstevel@tonic-gate 1072*7c478bd9Sstevel@tonic-gate for (;;) { 1073*7c478bd9Sstevel@tonic-gate if ((err = sema_wait(&delay_sema)) != 0) { 1074*7c478bd9Sstevel@tonic-gate if (err == EINTR) 1075*7c478bd9Sstevel@tonic-gate continue; 1076*7c478bd9Sstevel@tonic-gate error("do_delay_write: sema_wait failed"); 1077*7c478bd9Sstevel@tonic-gate } 1078*7c478bd9Sstevel@tonic-gate 1079*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&delay_mutex); 1080*7c478bd9Sstevel@tonic-gate rrp = delay_list; 1081*7c478bd9Sstevel@tonic-gate delay_list = delay_list->next; 1082*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&delay_mutex); 1083*7c478bd9Sstevel@tonic-gate 1084*7c478bd9Sstevel@tonic-gate (void) gettimeofday(&tv, NULL); 1085*7c478bd9Sstevel@tonic-gate if (tv.tv_sec < rrp->tv.tv_sec) 1086*7c478bd9Sstevel@tonic-gate (void) sleep(rrp->tv.tv_sec - tv.tv_sec); 1087*7c478bd9Sstevel@tonic-gate 1088*7c478bd9Sstevel@tonic-gate if (rarp_write(rrp->rdev->fd, rrp) < 0) 1089*7c478bd9Sstevel@tonic-gate error("rarp_write error"); 1090*7c478bd9Sstevel@tonic-gate 1091*7c478bd9Sstevel@tonic-gate (void) free(rrp); 1092*7c478bd9Sstevel@tonic-gate } 1093*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1094*7c478bd9Sstevel@tonic-gate } 1095*7c478bd9Sstevel@tonic-gate 1096*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1097*7c478bd9Sstevel@tonic-gate static void 1098*7c478bd9Sstevel@tonic-gate delay_write(struct rarpdev *rdev, struct rarpreply *rrp) 1099*7c478bd9Sstevel@tonic-gate { 1100*7c478bd9Sstevel@tonic-gate struct rarpreply *trp; 1101*7c478bd9Sstevel@tonic-gate 1102*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&delay_mutex); 1103*7c478bd9Sstevel@tonic-gate if (delay_list == NULL) { 1104*7c478bd9Sstevel@tonic-gate delay_list = rrp; 1105*7c478bd9Sstevel@tonic-gate } else { 1106*7c478bd9Sstevel@tonic-gate trp = delay_list; 1107*7c478bd9Sstevel@tonic-gate while (trp->next != NULL) 1108*7c478bd9Sstevel@tonic-gate trp = trp->next; 1109*7c478bd9Sstevel@tonic-gate trp->next = rrp; 1110*7c478bd9Sstevel@tonic-gate } 1111*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&delay_mutex); 1112*7c478bd9Sstevel@tonic-gate 1113*7c478bd9Sstevel@tonic-gate (void) sema_post(&delay_sema); 1114*7c478bd9Sstevel@tonic-gate } 1115*7c478bd9Sstevel@tonic-gate 1116*7c478bd9Sstevel@tonic-gate static int 1117*7c478bd9Sstevel@tonic-gate rarp_write(int fd, struct rarpreply *rrp) 1118*7c478bd9Sstevel@tonic-gate { 1119*7c478bd9Sstevel@tonic-gate struct strbuf ctl, data; 1120*7c478bd9Sstevel@tonic-gate union DL_primitives *dlp; 1121*7c478bd9Sstevel@tonic-gate char ctlbuf[BUFSIZE]; 1122*7c478bd9Sstevel@tonic-gate ushort_t etype = ETHERTYPE_REVARP; 1123*7c478bd9Sstevel@tonic-gate int ifaddrlen = rrp->rdev->ifaddrlen; 1124*7c478bd9Sstevel@tonic-gate 1125*7c478bd9Sstevel@tonic-gate /* 1126*7c478bd9Sstevel@tonic-gate * Construct DL_UNITDATA_REQ. 1127*7c478bd9Sstevel@tonic-gate */ 1128*7c478bd9Sstevel@tonic-gate /* LINTED pointer */ 1129*7c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)ctlbuf; 1130*7c478bd9Sstevel@tonic-gate ctl.len = DL_UNITDATA_REQ_SIZE + ifaddrlen + abs(rrp->rdev->ifsaplen); 1131*7c478bd9Sstevel@tonic-gate ctl.buf = ctlbuf; 1132*7c478bd9Sstevel@tonic-gate data.len = rrp->rdev->ifrarplen; 1133*7c478bd9Sstevel@tonic-gate data.buf = (char *)rrp->arprep; 1134*7c478bd9Sstevel@tonic-gate if (ctl.len > sizeof (ctlbuf)) 1135*7c478bd9Sstevel@tonic-gate return (-1); 1136*7c478bd9Sstevel@tonic-gate 1137*7c478bd9Sstevel@tonic-gate dlp->unitdata_req.dl_primitive = DL_UNITDATA_REQ; 1138*7c478bd9Sstevel@tonic-gate dlp->unitdata_req.dl_dest_addr_length = ifaddrlen + 1139*7c478bd9Sstevel@tonic-gate abs(rrp->rdev->ifsaplen); 1140*7c478bd9Sstevel@tonic-gate dlp->unitdata_req.dl_dest_addr_offset = DL_UNITDATA_REQ_SIZE; 1141*7c478bd9Sstevel@tonic-gate dlp->unitdata_req.dl_priority.dl_min = 0; 1142*7c478bd9Sstevel@tonic-gate dlp->unitdata_req.dl_priority.dl_max = 0; 1143*7c478bd9Sstevel@tonic-gate (void) memcpy(ctlbuf + DL_UNITDATA_REQ_SIZE, rrp->lldest, ifaddrlen); 1144*7c478bd9Sstevel@tonic-gate (void) memcpy(ctlbuf + DL_UNITDATA_REQ_SIZE + ifaddrlen, &etype, 1145*7c478bd9Sstevel@tonic-gate sizeof (etype)); 1146*7c478bd9Sstevel@tonic-gate 1147*7c478bd9Sstevel@tonic-gate /* 1148*7c478bd9Sstevel@tonic-gate * Send DL_UNITDATA_REQ. 1149*7c478bd9Sstevel@tonic-gate */ 1150*7c478bd9Sstevel@tonic-gate return (putmsg(fd, &ctl, &data, 0)); 1151*7c478bd9Sstevel@tonic-gate } 1152*7c478bd9Sstevel@tonic-gate 1153*7c478bd9Sstevel@tonic-gate /* 1154*7c478bd9Sstevel@tonic-gate * See if we have a TFTP boot file for this guy. Filenames in TFTP 1155*7c478bd9Sstevel@tonic-gate * boot requests are of the form <ipaddr> for Sun-3's and of the form 1156*7c478bd9Sstevel@tonic-gate * <ipaddr>.<arch> for all other architectures. Since we don't know 1157*7c478bd9Sstevel@tonic-gate * the client's architecture, either format will do. 1158*7c478bd9Sstevel@tonic-gate */ 1159*7c478bd9Sstevel@tonic-gate static int 1160*7c478bd9Sstevel@tonic-gate mightboot(ipaddr_t ipa) 1161*7c478bd9Sstevel@tonic-gate { 1162*7c478bd9Sstevel@tonic-gate char path[MAXPATHL]; 1163*7c478bd9Sstevel@tonic-gate DIR *dirp; 1164*7c478bd9Sstevel@tonic-gate struct dirent *dp; 1165*7c478bd9Sstevel@tonic-gate struct dirent *dentry; 1166*7c478bd9Sstevel@tonic-gate 1167*7c478bd9Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "%s/%08X", BOOTDIR, ipa); 1168*7c478bd9Sstevel@tonic-gate 1169*7c478bd9Sstevel@tonic-gate /* 1170*7c478bd9Sstevel@tonic-gate * Try a quick access() first. 1171*7c478bd9Sstevel@tonic-gate */ 1172*7c478bd9Sstevel@tonic-gate if (access(path, 0) == 0) 1173*7c478bd9Sstevel@tonic-gate return (1); 1174*7c478bd9Sstevel@tonic-gate 1175*7c478bd9Sstevel@tonic-gate /* 1176*7c478bd9Sstevel@tonic-gate * Not there, do it the slow way by 1177*7c478bd9Sstevel@tonic-gate * reading through the directory. 1178*7c478bd9Sstevel@tonic-gate */ 1179*7c478bd9Sstevel@tonic-gate (void) sprintf(path, "%08X", ipa); 1180*7c478bd9Sstevel@tonic-gate 1181*7c478bd9Sstevel@tonic-gate if (!(dirp = opendir(BOOTDIR))) 1182*7c478bd9Sstevel@tonic-gate return (0); 1183*7c478bd9Sstevel@tonic-gate 1184*7c478bd9Sstevel@tonic-gate dentry = (struct dirent *)malloc(sizeof (struct dirent) + 1185*7c478bd9Sstevel@tonic-gate pc_name_max + 1); 1186*7c478bd9Sstevel@tonic-gate if (dentry == NULL) { 1187*7c478bd9Sstevel@tonic-gate error("out of memory"); 1188*7c478bd9Sstevel@tonic-gate } 1189*7c478bd9Sstevel@tonic-gate #ifdef _POSIX_PTHREAD_SEMANTICS 1190*7c478bd9Sstevel@tonic-gate while ((readdir_r(dirp, dentry, &dp)) != 0) { 1191*7c478bd9Sstevel@tonic-gate if (dp == NULL) 1192*7c478bd9Sstevel@tonic-gate break; 1193*7c478bd9Sstevel@tonic-gate #else 1194*7c478bd9Sstevel@tonic-gate while ((dp = readdir_r(dirp, dentry)) != NULL) { 1195*7c478bd9Sstevel@tonic-gate #endif 1196*7c478bd9Sstevel@tonic-gate if (strncmp(dp->d_name, path, 8) != 0) 1197*7c478bd9Sstevel@tonic-gate continue; 1198*7c478bd9Sstevel@tonic-gate if ((strlen(dp->d_name) != 8) && (dp->d_name[8] != '.')) 1199*7c478bd9Sstevel@tonic-gate continue; 1200*7c478bd9Sstevel@tonic-gate break; 1201*7c478bd9Sstevel@tonic-gate } 1202*7c478bd9Sstevel@tonic-gate 1203*7c478bd9Sstevel@tonic-gate (void) closedir(dirp); 1204*7c478bd9Sstevel@tonic-gate (void) free(dentry); 1205*7c478bd9Sstevel@tonic-gate 1206*7c478bd9Sstevel@tonic-gate return (dp? 1: 0); 1207*7c478bd9Sstevel@tonic-gate } 1208*7c478bd9Sstevel@tonic-gate 1209*7c478bd9Sstevel@tonic-gate /* 1210*7c478bd9Sstevel@tonic-gate * Get our IP address and local netmask. 1211*7c478bd9Sstevel@tonic-gate */ 1212*7c478bd9Sstevel@tonic-gate static void 1213*7c478bd9Sstevel@tonic-gate get_ifdata(char *dev, int unit, ipaddr_t *ipp, ipaddr_t *maskp) 1214*7c478bd9Sstevel@tonic-gate { 1215*7c478bd9Sstevel@tonic-gate int fd; 1216*7c478bd9Sstevel@tonic-gate struct ifreq ifr; 1217*7c478bd9Sstevel@tonic-gate struct sockaddr_in *sin; 1218*7c478bd9Sstevel@tonic-gate 1219*7c478bd9Sstevel@tonic-gate /* LINTED pointer */ 1220*7c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *)&ifr.ifr_addr; 1221*7c478bd9Sstevel@tonic-gate 1222*7c478bd9Sstevel@tonic-gate /* 1223*7c478bd9Sstevel@tonic-gate * Open the IP provider. 1224*7c478bd9Sstevel@tonic-gate */ 1225*7c478bd9Sstevel@tonic-gate if ((fd = open(DEVIP, 0)) < 0) 1226*7c478bd9Sstevel@tonic-gate syserr(DEVIP); 1227*7c478bd9Sstevel@tonic-gate 1228*7c478bd9Sstevel@tonic-gate /* 1229*7c478bd9Sstevel@tonic-gate * Ask IP for our IP address. 1230*7c478bd9Sstevel@tonic-gate */ 1231*7c478bd9Sstevel@tonic-gate (void) snprintf(ifr.ifr_name, sizeof (ifr.ifr_name), "%s%d", dev, unit); 1232*7c478bd9Sstevel@tonic-gate if (strioctl(fd, SIOCGIFADDR, -1, sizeof (struct ifreq), 1233*7c478bd9Sstevel@tonic-gate (char *)&ifr) < 0) 1234*7c478bd9Sstevel@tonic-gate syserr("SIOCGIFADDR"); 1235*7c478bd9Sstevel@tonic-gate *ipp = (ipaddr_t)ntohl(sin->sin_addr.s_addr); 1236*7c478bd9Sstevel@tonic-gate 1237*7c478bd9Sstevel@tonic-gate if (dflag) 1238*7c478bd9Sstevel@tonic-gate debug("device %s%d address %s", 1239*7c478bd9Sstevel@tonic-gate dev, unit, inet_ntoa(sin->sin_addr)); 1240*7c478bd9Sstevel@tonic-gate 1241*7c478bd9Sstevel@tonic-gate /* 1242*7c478bd9Sstevel@tonic-gate * Ask IP for our netmask. 1243*7c478bd9Sstevel@tonic-gate */ 1244*7c478bd9Sstevel@tonic-gate if (strioctl(fd, SIOCGIFNETMASK, -1, sizeof (struct ifreq), 1245*7c478bd9Sstevel@tonic-gate (char *)&ifr) < 0) 1246*7c478bd9Sstevel@tonic-gate syserr("SIOCGIFNETMASK"); 1247*7c478bd9Sstevel@tonic-gate *maskp = (ipaddr_t)ntohl(sin->sin_addr.s_addr); 1248*7c478bd9Sstevel@tonic-gate 1249*7c478bd9Sstevel@tonic-gate if (dflag) 1250*7c478bd9Sstevel@tonic-gate debug("device %s%d subnet mask %s", 1251*7c478bd9Sstevel@tonic-gate dev, unit, inet_ntoa(sin->sin_addr)); 1252*7c478bd9Sstevel@tonic-gate 1253*7c478bd9Sstevel@tonic-gate /* 1254*7c478bd9Sstevel@tonic-gate * Thankyou ip. 1255*7c478bd9Sstevel@tonic-gate */ 1256*7c478bd9Sstevel@tonic-gate (void) close(fd); 1257*7c478bd9Sstevel@tonic-gate } 1258*7c478bd9Sstevel@tonic-gate 1259*7c478bd9Sstevel@tonic-gate /* 1260*7c478bd9Sstevel@tonic-gate * Translate mac address to IP address. 1261*7c478bd9Sstevel@tonic-gate * Return 0 on success, nonzero on failure. 1262*7c478bd9Sstevel@tonic-gate */ 1263*7c478bd9Sstevel@tonic-gate static int 1264*7c478bd9Sstevel@tonic-gate get_ipaddr(struct rarpdev *rdev, uchar_t *laddr, uchar_t *ipp, ipaddr_t *ipaddr) 1265*7c478bd9Sstevel@tonic-gate { 1266*7c478bd9Sstevel@tonic-gate char host[MAXHOSTL]; 1267*7c478bd9Sstevel@tonic-gate char hbuffer[BUFSIZE]; 1268*7c478bd9Sstevel@tonic-gate struct hostent *hp, res; 1269*7c478bd9Sstevel@tonic-gate int herror; 1270*7c478bd9Sstevel@tonic-gate struct in_addr addr; 1271*7c478bd9Sstevel@tonic-gate char **p; 1272*7c478bd9Sstevel@tonic-gate struct ifdev *ifdev; 1273*7c478bd9Sstevel@tonic-gate 1274*7c478bd9Sstevel@tonic-gate if (rdev->ifaddrlen != ETHERADDRL) { 1275*7c478bd9Sstevel@tonic-gate if (dflag) 1276*7c478bd9Sstevel@tonic-gate debug("%s %s", " can not map non 6 byte hardware ", 1277*7c478bd9Sstevel@tonic-gate "address to IP address"); 1278*7c478bd9Sstevel@tonic-gate return (1); 1279*7c478bd9Sstevel@tonic-gate } 1280*7c478bd9Sstevel@tonic-gate 1281*7c478bd9Sstevel@tonic-gate /* 1282*7c478bd9Sstevel@tonic-gate * Translate mac address to hostname 1283*7c478bd9Sstevel@tonic-gate * and IP address. 1284*7c478bd9Sstevel@tonic-gate */ 1285*7c478bd9Sstevel@tonic-gate if (ether_ntohost(host, (struct ether_addr *)laddr) != 0 || 1286*7c478bd9Sstevel@tonic-gate !(hp = gethostbyname_r(host, &res, hbuffer, sizeof (hbuffer), 1287*7c478bd9Sstevel@tonic-gate &herror)) || 1288*7c478bd9Sstevel@tonic-gate hp->h_addrtype != AF_INET || hp->h_length != sizeof (ipaddr_t)) { 1289*7c478bd9Sstevel@tonic-gate if (dflag) 1290*7c478bd9Sstevel@tonic-gate debug("could not map hardware address to IP address"); 1291*7c478bd9Sstevel@tonic-gate return (1); 1292*7c478bd9Sstevel@tonic-gate } 1293*7c478bd9Sstevel@tonic-gate 1294*7c478bd9Sstevel@tonic-gate /* 1295*7c478bd9Sstevel@tonic-gate * Find the IP address on the right net. 1296*7c478bd9Sstevel@tonic-gate */ 1297*7c478bd9Sstevel@tonic-gate for (p = hp->h_addr_list; *p; p++) { 1298*7c478bd9Sstevel@tonic-gate (void) memcpy(&addr, *p, sizeof (ipaddr_t)); 1299*7c478bd9Sstevel@tonic-gate for (ifdev = rdev->ifdev; ifdev != NULL; ifdev = ifdev->next) { 1300*7c478bd9Sstevel@tonic-gate if (dflag) { 1301*7c478bd9Sstevel@tonic-gate struct in_addr daddr; 1302*7c478bd9Sstevel@tonic-gate ipaddr_t netnum; 1303*7c478bd9Sstevel@tonic-gate 1304*7c478bd9Sstevel@tonic-gate netnum = htonl(ifdev->if_netnum); 1305*7c478bd9Sstevel@tonic-gate (void) memcpy(&daddr, &netnum, 1306*7c478bd9Sstevel@tonic-gate sizeof (ipaddr_t)); 1307*7c478bd9Sstevel@tonic-gate if (ifdev->lunit == -1) 1308*7c478bd9Sstevel@tonic-gate debug( 1309*7c478bd9Sstevel@tonic-gate "trying physical netnum %s mask %x", 1310*7c478bd9Sstevel@tonic-gate inet_ntoa(daddr), 1311*7c478bd9Sstevel@tonic-gate ifdev->if_netmask); 1312*7c478bd9Sstevel@tonic-gate else 1313*7c478bd9Sstevel@tonic-gate debug( 1314*7c478bd9Sstevel@tonic-gate "trying logical %d netnum %s mask %x", 1315*7c478bd9Sstevel@tonic-gate ifdev->lunit, 1316*7c478bd9Sstevel@tonic-gate inet_ntoa(daddr), 1317*7c478bd9Sstevel@tonic-gate ifdev->if_netmask); 1318*7c478bd9Sstevel@tonic-gate } 1319*7c478bd9Sstevel@tonic-gate if ((ntohl(addr.s_addr) & ifdev->if_netmask) == 1320*7c478bd9Sstevel@tonic-gate ifdev->if_netnum) { 1321*7c478bd9Sstevel@tonic-gate /* 1322*7c478bd9Sstevel@tonic-gate * Return the correct IP address. 1323*7c478bd9Sstevel@tonic-gate */ 1324*7c478bd9Sstevel@tonic-gate (void) memcpy(ipp, &addr, sizeof (ipaddr_t)); 1325*7c478bd9Sstevel@tonic-gate 1326*7c478bd9Sstevel@tonic-gate /* 1327*7c478bd9Sstevel@tonic-gate * Return the interface's ipaddr 1328*7c478bd9Sstevel@tonic-gate */ 1329*7c478bd9Sstevel@tonic-gate (void) memcpy(ipaddr, &ifdev->ipaddr, 1330*7c478bd9Sstevel@tonic-gate sizeof (ipaddr_t)); 1331*7c478bd9Sstevel@tonic-gate 1332*7c478bd9Sstevel@tonic-gate return (0); 1333*7c478bd9Sstevel@tonic-gate } 1334*7c478bd9Sstevel@tonic-gate } 1335*7c478bd9Sstevel@tonic-gate } 1336*7c478bd9Sstevel@tonic-gate 1337*7c478bd9Sstevel@tonic-gate if (dflag) 1338*7c478bd9Sstevel@tonic-gate debug("got host entry but no IP address on this net"); 1339*7c478bd9Sstevel@tonic-gate return (1); 1340*7c478bd9Sstevel@tonic-gate } 1341*7c478bd9Sstevel@tonic-gate 1342*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1343*7c478bd9Sstevel@tonic-gate void 1344*7c478bd9Sstevel@tonic-gate sigalarm(int i) 1345*7c478bd9Sstevel@tonic-gate { 1346*7c478bd9Sstevel@tonic-gate error(alarmmsg); 1347*7c478bd9Sstevel@tonic-gate } 1348*7c478bd9Sstevel@tonic-gate 1349*7c478bd9Sstevel@tonic-gate static int 1350*7c478bd9Sstevel@tonic-gate strioctl(int fd, int cmd, int timout, int len, char *dp) 1351*7c478bd9Sstevel@tonic-gate { 1352*7c478bd9Sstevel@tonic-gate struct strioctl si; 1353*7c478bd9Sstevel@tonic-gate 1354*7c478bd9Sstevel@tonic-gate si.ic_cmd = cmd; 1355*7c478bd9Sstevel@tonic-gate si.ic_timout = timout; 1356*7c478bd9Sstevel@tonic-gate si.ic_len = len; 1357*7c478bd9Sstevel@tonic-gate si.ic_dp = dp; 1358*7c478bd9Sstevel@tonic-gate return (ioctl(fd, I_STR, &si)); 1359*7c478bd9Sstevel@tonic-gate } 1360*7c478bd9Sstevel@tonic-gate 1361*7c478bd9Sstevel@tonic-gate static void 1362*7c478bd9Sstevel@tonic-gate usage() 1363*7c478bd9Sstevel@tonic-gate { 1364*7c478bd9Sstevel@tonic-gate error("Usage: %s [ -ad ] device unit", cmdname); 1365*7c478bd9Sstevel@tonic-gate } 1366*7c478bd9Sstevel@tonic-gate 1367*7c478bd9Sstevel@tonic-gate static void 1368*7c478bd9Sstevel@tonic-gate syserr(s) 1369*7c478bd9Sstevel@tonic-gate char *s; 1370*7c478bd9Sstevel@tonic-gate { 1371*7c478bd9Sstevel@tonic-gate char buf[256]; 1372*7c478bd9Sstevel@tonic-gate int status = 1; 1373*7c478bd9Sstevel@tonic-gate 1374*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s: %s", s, strerror(errno)); 1375*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s\n", cmdname, buf); 1376*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "%s", buf); 1377*7c478bd9Sstevel@tonic-gate thr_exit(&status); 1378*7c478bd9Sstevel@tonic-gate } 1379*7c478bd9Sstevel@tonic-gate 1380*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/ 1381*7c478bd9Sstevel@tonic-gate static void 1382*7c478bd9Sstevel@tonic-gate error(char *fmt, ...) 1383*7c478bd9Sstevel@tonic-gate { 1384*7c478bd9Sstevel@tonic-gate char buf[256]; 1385*7c478bd9Sstevel@tonic-gate va_list ap; 1386*7c478bd9Sstevel@tonic-gate int status = 1; 1387*7c478bd9Sstevel@tonic-gate 1388*7c478bd9Sstevel@tonic-gate va_start(ap, fmt); 1389*7c478bd9Sstevel@tonic-gate (void) vsprintf(buf, fmt, ap); 1390*7c478bd9Sstevel@tonic-gate va_end(ap); 1391*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s\n", cmdname, buf); 1392*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, buf); 1393*7c478bd9Sstevel@tonic-gate thr_exit(&status); 1394*7c478bd9Sstevel@tonic-gate } 1395*7c478bd9Sstevel@tonic-gate 1396*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/ 1397*7c478bd9Sstevel@tonic-gate static void 1398*7c478bd9Sstevel@tonic-gate debug(char *fmt, ...) 1399*7c478bd9Sstevel@tonic-gate { 1400*7c478bd9Sstevel@tonic-gate va_list ap; 1401*7c478bd9Sstevel@tonic-gate 1402*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&debug_mutex); 1403*7c478bd9Sstevel@tonic-gate va_start(ap, fmt); 1404*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s:[%u] ", cmdname, thr_self()); 1405*7c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, fmt, ap); 1406*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 1407*7c478bd9Sstevel@tonic-gate va_end(ap); 1408*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&debug_mutex); 1409*7c478bd9Sstevel@tonic-gate } 1410