Home | History | Annotate | Download | only in usr.sbin
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
     26 /*	  All Rights Reserved  	*/
     27 
     28 /*
     29  * Portions of this source code were derived from Berkeley 4.3 BSD
     30  * under license from the Regents of the University of California.
     31  */
     32 
     33 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     34 
     35 /*
     36  * rarpd.c  Reverse-ARP server.
     37  * Refer to RFC 903 "A Reverse Address Resolution Protocol".
     38  */
     39 
     40 #define	_REENTRANT
     41 
     42 #include	<thread.h>
     43 #include	<synch.h>
     44 #include	<stdlib.h>
     45 #include	<unistd.h>
     46 #include	<sys/resource.h>
     47 #include	<stdio.h>
     48 #include	<stdio_ext.h>
     49 #include	<stdarg.h>
     50 #include	<string.h>
     51 #include	<fcntl.h>
     52 #include	<sys/types.h>
     53 #include	<dirent.h>
     54 #include	<syslog.h>
     55 #include	<netdb.h>
     56 #include	<errno.h>
     57 #include	<sys/socket.h>
     58 #include	<sys/sockio.h>
     59 #include	<net/if.h>
     60 #include	<netinet/if_ether.h>
     61 #include	<netinet/in.h>
     62 #include	<arpa/inet.h>
     63 #include	<stropts.h>
     64 #include	<libinetutil.h>
     65 #include	<libdlpi.h>
     66 #include	<net/if_types.h>
     67 #include	<net/if_dl.h>
     68 
     69 #define	BOOTDIR		"/tftpboot"	/* boot files directory */
     70 #define	DEVIP		"/dev/ip"	/* path to ip driver */
     71 #define	DEVARP		"/dev/arp"	/* path to arp driver */
     72 
     73 #define	BUFSIZE		2048		/* max receive frame length */
     74 #define	MAXPATHL	128		/* max path length */
     75 #define	MAXHOSTL	128		/* max host name length */
     76 #define	MAXIFS		256
     77 
     78 /*
     79  * Logical network devices
     80  */
     81 struct	ifdev {
     82 	char		ldevice[IFNAMSIZ];
     83 	int		lunit;
     84 	ipaddr_t	ipaddr;			/* network order */
     85 	ipaddr_t	if_netmask;		/* host order */
     86 	ipaddr_t	if_ipaddr;		/* host order */
     87 	ipaddr_t	if_netnum;		/* host order, with subnet */
     88 	struct ifdev *next;
     89 };
     90 
     91 /*
     92  * Physical network device
     93  */
     94 struct	rarpdev {
     95 	char		device[DLPI_LINKNAME_MAX];
     96 	uint_t		unit;
     97 	dlpi_handle_t	dh_rarp;
     98 	uchar_t		physaddr[DLPI_PHYSADDR_MAX];
     99 						/* mac address of interface */
    100 	uint_t		physaddrlen;		/* mac address length */
    101 	int		ifrarplen;		/* size of rarp data packet */
    102 	struct ifdev	*ifdev;			/* private interface info */
    103 	struct rarpdev	*next;			/* list of managed devices */
    104 };
    105 
    106 struct	rarpreply {
    107 	struct rarpdev		*rdev;		/* which device reply for */
    108 	struct timeval		tv;		/* send RARP reply by when */
    109 	uchar_t			*lldest;	/* target mac to send reply */
    110 	uchar_t			*arprep;	/* [R]ARP response */
    111 	struct rarpreply	*next;
    112 };
    113 
    114 static struct rarpreply	*delay_list;
    115 static sema_t		delay_sema;
    116 static mutex_t		delay_mutex;
    117 static mutex_t		debug_mutex;
    118 
    119 static struct rarpdev	*rarpdev_head;
    120 
    121 /*
    122  * Globals initialized before multi-threading
    123  */
    124 static char	*cmdname;		/* command name from argv[0] */
    125 static int	dflag = 0;		/* enable diagnostics */
    126 static int	aflag = 0;		/* start rarpd on all interfaces */
    127 
    128 static void	getintf(void);
    129 static struct rarpdev *find_device(ifspec_t *);
    130 static void	init_rarpdev(struct rarpdev *);
    131 static void	do_rarp(void *);
    132 static void	rarp_request(struct rarpdev *, struct arphdr *,
    133 		    uchar_t *);
    134 static void	add_arp(struct rarpdev *, uchar_t *, uchar_t *);
    135 static void	arp_request(struct rarpdev *, struct arphdr *, uchar_t *);
    136 static void	do_delay_write(void *);
    137 static void	delay_write(struct rarpdev *, struct rarpreply *);
    138 static int	mightboot(ipaddr_t);
    139 static void	get_ifdata(char *, int, ipaddr_t *, ipaddr_t *);
    140 static int	get_ipaddr(struct rarpdev *, uchar_t *, uchar_t *, ipaddr_t *);
    141 static int	strioctl(int, int, int, int, char *);
    142 static void	usage();
    143 static void	syserr(const char *);
    144 /*PRINTFLIKE1*/
    145 static void	error(const char *, ...);
    146 static void	debug(char *, ...);
    147 
    148 extern	int	optind;
    149 extern	char	*optarg;
    150 
    151 int
    152 main(int argc, char *argv[])
    153 {
    154 	int		c;
    155 	struct rlimit rl;
    156 	struct rarpdev	*rdev;
    157 	int		i;
    158 
    159 	cmdname = argv[0];
    160 
    161 	while ((c = getopt(argc, argv, "ad")) != -1) {
    162 		switch (c) {
    163 		case 'a':
    164 			aflag = 1;
    165 			break;
    166 
    167 		case 'd':
    168 			dflag = 1;
    169 			break;
    170 
    171 		default:
    172 			usage();
    173 		}
    174 	}
    175 
    176 	if ((!aflag && (argc - optind) != 2) ||
    177 	    (aflag && (argc - optind) != 0)) {
    178 		usage();
    179 		/* NOTREACHED */
    180 	}
    181 
    182 	if (!dflag) {
    183 		/*
    184 		 * Background
    185 		 */
    186 		switch (fork()) {
    187 			case -1:	/* error */
    188 				syserr("fork");
    189 				/*NOTREACHED*/
    190 
    191 			case 0:		/* child */
    192 				break;
    193 
    194 			default:	/* parent */
    195 				return (0);
    196 		}
    197 		for (i = 0; i < 3; i++) {
    198 			(void) close(i);
    199 		}
    200 		(void) open("/", O_RDONLY, 0);
    201 		(void) dup2(0, 1);
    202 		(void) dup2(0, 2);
    203 		/*
    204 		 * Detach terminal
    205 		 */
    206 		if (setsid() < 0)
    207 			syserr("setsid");
    208 	}
    209 
    210 	rl.rlim_cur = RLIM_INFINITY;
    211 	rl.rlim_max = RLIM_INFINITY;
    212 	if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
    213 		syserr("setrlimit");
    214 	(void) enable_extended_FILE_stdio(-1, -1);
    215 
    216 	(void) openlog(cmdname, LOG_PID, LOG_DAEMON);
    217 
    218 	if (aflag) {
    219 		/*
    220 		 * Get each interface name and load rarpdev list.
    221 		 */
    222 		getintf();
    223 	} else {
    224 		ifspec_t	ifsp;
    225 		struct ifdev	*ifdev;
    226 		char		buf[IFNAMSIZ + 1];
    227 
    228 		/*
    229 		 * Load specified device as only element of the list.
    230 		 */
    231 		rarpdev_head = (struct rarpdev *)calloc(1,
    232 		    sizeof (struct rarpdev));
    233 		if (rarpdev_head == NULL) {
    234 			error("out of memory");
    235 		}
    236 		(void) strncpy(buf, argv[optind], IFNAMSIZ);
    237 		(void) strncat(buf, argv[optind + 1], IFNAMSIZ - strlen(buf));
    238 
    239 		if ((ifdev = calloc(1, sizeof (struct ifdev))) == NULL) {
    240 			error("out of memory");
    241 		}
    242 
    243 		if (!ifparse_ifspec(buf, &ifsp) || ifsp.ifsp_modcnt != 0) {
    244 			error("invalid interface specification");
    245 		}
    246 
    247 		if (ifsp.ifsp_lunvalid) {
    248 			(void) snprintf(ifdev->ldevice,
    249 			    sizeof (ifdev->ldevice), "%s%d:",
    250 			    ifsp.ifsp_devnm, ifsp.ifsp_ppa);
    251 			ifdev->lunit = ifsp.ifsp_lun;
    252 		} else {
    253 			ifdev->lunit = -1; /* no logical unit */
    254 		}
    255 		(void) strlcpy(rarpdev_head->device, ifsp.ifsp_devnm,
    256 		    sizeof (rarpdev_head->device));
    257 		rarpdev_head->unit = ifsp.ifsp_ppa;
    258 
    259 		ifdev->next = rarpdev_head->ifdev;
    260 		rarpdev_head->ifdev = ifdev;
    261 	}
    262 
    263 	/*
    264 	 * Initialize each rarpdev.
    265 	 */
    266 	for (rdev = rarpdev_head; rdev != NULL; rdev = rdev->next) {
    267 		init_rarpdev(rdev);
    268 	}
    269 
    270 	(void) sema_init(&delay_sema, 0, USYNC_THREAD, NULL);
    271 	(void) mutex_init(&delay_mutex, USYNC_THREAD, NULL);
    272 	(void) mutex_init(&debug_mutex, USYNC_THREAD, NULL);
    273 
    274 	/*
    275 	 * Start delayed processing thread.
    276 	 */
    277 	(void) thr_create(NULL, NULL, (void *(*)(void *))do_delay_write, NULL,
    278 	    THR_NEW_LWP, NULL);
    279 
    280 	/*
    281 	 * Start RARP processing for each device.
    282 	 */
    283 	for (rdev = rarpdev_head; rdev != NULL; rdev = rdev->next) {
    284 		if (rdev->dh_rarp != NULL) {
    285 			(void) thr_create(NULL, NULL,
    286 			    (void *(*)(void *))do_rarp, (void *)rdev,
    287 			    THR_NEW_LWP, NULL);
    288 		}
    289 	}
    290 
    291 	/*
    292 	 * Exit main() thread
    293 	 */
    294 	thr_exit(NULL);
    295 
    296 	return (0);
    297 }
    298 
    299 static void
    300 getintf(void)
    301 {
    302 	int		fd;
    303 	int		numifs;
    304 	unsigned	bufsize;
    305 	struct ifreq	*reqbuf;
    306 	struct ifconf	ifconf;
    307 	struct ifreq	*ifr;
    308 	struct rarpdev	*rdev;
    309 	struct ifdev	*ifdev;
    310 
    311 	/*
    312 	 * Open the IP provider.
    313 	 */
    314 	if ((fd = open(DEVIP, 0)) < 0)
    315 		syserr(DEVIP);
    316 
    317 	/*
    318 	 * Ask IP for the list of configured interfaces.
    319 	 */
    320 	if (ioctl(fd, SIOCGIFNUM, (char *)&numifs) < 0) {
    321 		numifs = MAXIFS;
    322 	}
    323 	bufsize = numifs * sizeof (struct ifreq);
    324 	reqbuf = (struct ifreq *)malloc(bufsize);
    325 	if (reqbuf == NULL) {
    326 		error("out of memory");
    327 	}
    328 
    329 	ifconf.ifc_len = bufsize;
    330 	ifconf.ifc_buf = (caddr_t)reqbuf;
    331 	if (ioctl(fd, SIOCGIFCONF, (char *)&ifconf) < 0)
    332 		syserr("SIOCGIFCONF");
    333 
    334 	/*
    335 	 * Initialize a rarpdev for each interface.
    336 	 */
    337 	for (ifr = ifconf.ifc_req; ifconf.ifc_len > 0;
    338 	    ifr++, ifconf.ifc_len -= sizeof (struct ifreq)) {
    339 		ifspec_t	ifsp;
    340 
    341 		if (ioctl(fd, SIOCGIFFLAGS, (char *)ifr) < 0) {
    342 			syserr("ioctl SIOCGIFFLAGS");
    343 			exit(1);
    344 		}
    345 		if ((ifr->ifr_flags & IFF_LOOPBACK) ||
    346 		    !(ifr->ifr_flags & IFF_UP) ||
    347 		    !(ifr->ifr_flags & IFF_BROADCAST) ||
    348 		    (ifr->ifr_flags & IFF_NOARP) ||
    349 		    (ifr->ifr_flags & IFF_POINTOPOINT))
    350 			continue;
    351 
    352 		if (!ifparse_ifspec(ifr->ifr_name, &ifsp))
    353 			error("ifparse_ifspec failed");
    354 
    355 		/*
    356 		 * Look for an existing device for logical interfaces.
    357 		 */
    358 		if ((rdev = find_device(&ifsp)) == NULL) {
    359 			rdev = calloc(1, sizeof (struct rarpdev));
    360 			if (rdev == NULL)
    361 				error("out of memory");
    362 
    363 			(void) strlcpy(rdev->device, ifsp.ifsp_devnm,
    364 			    sizeof (rdev->device));
    365 			rdev->unit = ifsp.ifsp_ppa;
    366 
    367 			rdev->next = rarpdev_head;
    368 			rarpdev_head = rdev;
    369 		}
    370 
    371 		if ((ifdev = calloc(1, sizeof (struct ifdev))) == NULL)
    372 			error("out of memory");
    373 
    374 		if (ifsp.ifsp_lunvalid) {
    375 			(void) snprintf(ifdev->ldevice,
    376 			    sizeof (ifdev->ldevice), "%s%d:",
    377 			    ifsp.ifsp_devnm, ifsp.ifsp_ppa);
    378 			ifdev->lunit = ifsp.ifsp_lun;
    379 		} else
    380 			ifdev->lunit = -1; /* no logical unit */
    381 
    382 		ifdev->next = rdev->ifdev;
    383 		rdev->ifdev = ifdev;
    384 	}
    385 	(void) free((char *)reqbuf);
    386 }
    387 
    388 static struct rarpdev *
    389 find_device(ifspec_t *specp)
    390 {
    391 	struct rarpdev	*rdev;
    392 
    393 	for (rdev = rarpdev_head; rdev != NULL; rdev = rdev->next) {
    394 		if (specp->ifsp_ppa == rdev->unit &&
    395 		    strcmp(specp->ifsp_devnm, rdev->device) == 0)
    396 			return (rdev);
    397 	}
    398 	return (NULL);
    399 }
    400 
    401 static void
    402 init_rarpdev(struct rarpdev *rdev)
    403 {
    404 	char 		*dev;
    405 	int 		unit;
    406 	struct ifdev 	*ifdev;
    407 	int		retval;
    408 	char		*str = NULL;
    409 	uint_t		physaddrlen = DLPI_PHYSADDR_MAX;
    410 	char		linkname[DLPI_LINKNAME_MAX];
    411 	dlpi_handle_t	dh;
    412 
    413 	(void) snprintf(linkname, DLPI_LINKNAME_MAX, "%s%d", rdev->device,
    414 	    rdev->unit);
    415 	/*
    416 	 * Open datalink provider and get our mac address.
    417 	 */
    418 	if ((retval = dlpi_open(linkname, &dh, 0)) != DLPI_SUCCESS) {
    419 		error("cannot open link %s: %s", linkname,
    420 		    dlpi_strerror(retval));
    421 	}
    422 
    423 	if ((retval = dlpi_bind(dh, ETHERTYPE_REVARP, NULL)) != DLPI_SUCCESS) {
    424 		dlpi_close(dh);
    425 		error("dlpi_bind failed: %s", dlpi_strerror(retval));
    426 	}
    427 
    428 	/*
    429 	 * Save our mac address.
    430 	 */
    431 	if ((retval = dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR, rdev->physaddr,
    432 	    &physaddrlen)) != DLPI_SUCCESS) {
    433 		dlpi_close(dh);
    434 		error("dlpi_get_physaddr failed: %s", dlpi_strerror(retval));
    435 	}
    436 
    437 	rdev->physaddrlen = physaddrlen;
    438 	rdev->ifrarplen = sizeof (struct arphdr) + (2 * sizeof (ipaddr_t)) +
    439 	    (2 * physaddrlen);
    440 
    441 	if (dflag) {
    442 		str = _link_ntoa(rdev->physaddr, str,
    443 		    rdev->physaddrlen, IFT_OTHER);
    444 		if (str != NULL) {
    445 			debug("device %s physical address %s", linkname, str);
    446 			free(str);
    447 		}
    448 	}
    449 
    450 	/*
    451 	 * Assign dlpi handle to rdev.
    452 	 */
    453 	rdev->dh_rarp = dh;
    454 
    455 	/*
    456 	 * Get the IP address and netmask from directory service for
    457 	 * each logical interface.
    458 	 */
    459 	for (ifdev = rdev->ifdev; ifdev != NULL; ifdev = ifdev->next) {
    460 		/*
    461 		 * If lunit == -1 then this is the primary interface name.
    462 		 */
    463 		if (ifdev->lunit == -1) {
    464 			dev = rdev->device;
    465 			unit = rdev->unit;
    466 		} else {
    467 			dev = ifdev->ldevice;
    468 			unit = ifdev->lunit;
    469 		}
    470 		get_ifdata(dev, unit, &ifdev->if_ipaddr, &ifdev->if_netmask);
    471 
    472 		/*
    473 		 * Use IP address of the interface.
    474 		 */
    475 		ifdev->if_netnum = ifdev->if_ipaddr & ifdev->if_netmask;
    476 		ifdev->ipaddr = (ipaddr_t)htonl(ifdev->if_ipaddr);
    477 	}
    478 }
    479 
    480 static void
    481 do_rarp(void *buf)
    482 {
    483 	struct rarpdev *rdev = buf;
    484 	char	*cause;
    485 	struct arphdr *ans;
    486 	uchar_t *shost;
    487 	uint_t	saddrlen;
    488 	size_t	anslen = rdev->ifrarplen;
    489 	char	*str = NULL;
    490 	int	retval;
    491 
    492 	if (((shost = malloc(rdev->physaddrlen)) == NULL) ||
    493 	    ((ans = malloc(rdev->ifrarplen)) == NULL))
    494 		syserr("malloc");
    495 
    496 	if (dflag) {
    497 		str = _link_ntoa(rdev->physaddr, str, rdev->physaddrlen,
    498 		    IFT_OTHER);
    499 		if (str != NULL) {
    500 			debug("starting rarp service on device %s%d physical"
    501 			    " address %s", rdev->device, rdev->unit, str);
    502 			free(str);
    503 		}
    504 	}
    505 
    506 	/*
    507 	 * Read RARP packets and respond to them.
    508 	 */
    509 	for (;;) {
    510 		saddrlen = DLPI_PHYSADDR_MAX;
    511 		retval = dlpi_recv(rdev->dh_rarp, shost,
    512 		    &saddrlen, ans, &anslen, -1, NULL);
    513 		if (retval == DLPI_ETIMEDOUT) {
    514 			continue;
    515 		} else if (retval != DLPI_SUCCESS) {
    516 			error("error in dlpi_recv %s: %s", rdev->dh_rarp,
    517 			    dlpi_strerror(retval));
    518 		}
    519 
    520 		cause = NULL;
    521 
    522 		if (anslen < rdev->ifrarplen)
    523 			cause = "short packet";
    524 		else if (ans->ar_hrd != htons(ARPHRD_ETHER))
    525 			cause = "hardware type not Ethernet";
    526 		else if (ans->ar_pro != htons(ETHERTYPE_IP))
    527 			cause = "protocol type not IP";
    528 		else if (ans->ar_hln != rdev->physaddrlen)
    529 			cause = "unexpected hardware address length";
    530 		else if (ans->ar_pln != sizeof (ipaddr_t))
    531 			cause = "unexpected protocol address length";
    532 		if (cause != NULL) {
    533 			if (dflag)
    534 				debug("RARP packet received but "
    535 				    "discarded: %s", cause);
    536 			continue;
    537 		}
    538 
    539 		/*
    540 		 * Handle the request.
    541 		 */
    542 		switch (ntohs(ans->ar_op)) {
    543 		case REVARP_REQUEST:
    544 			rarp_request(rdev, ans, shost);
    545 			break;
    546 
    547 		case ARPOP_REQUEST:
    548 			arp_request(rdev, ans, shost);
    549 			break;
    550 
    551 		case REVARP_REPLY:
    552 			if (dflag)
    553 				debug("REVARP_REPLY ignored");
    554 			break;
    555 
    556 		case ARPOP_REPLY:
    557 			if (dflag)
    558 				debug("ARPOP_REPLY ignored");
    559 			break;
    560 
    561 		default:
    562 			if (dflag)
    563 				debug("unknown opcode 0x%x", ans->ar_op);
    564 			break;
    565 		}
    566 	}
    567 }
    568 
    569 /*
    570  * Reverse address determination and allocation code.
    571  */
    572 static void
    573 rarp_request(struct rarpdev *rdev, struct arphdr *rp, uchar_t *shost)
    574 {
    575 	ipaddr_t		tpa,  spa;
    576 	struct	rarpreply	*rrp;
    577 	uchar_t			*shap, *thap, *spap, *tpap;
    578 	char			*str = NULL;
    579 	int			retval;
    580 
    581 	shap = (uchar_t *)rp + sizeof (struct arphdr);
    582 	spap = shap + rp->ar_hln;
    583 	thap = spap + rp->ar_pln;
    584 	tpap = thap + rp->ar_hln;
    585 
    586 	if (dflag) {
    587 		str = _link_ntoa(thap, str, rdev->physaddrlen, IFT_OTHER);
    588 		if (str != NULL) {
    589 			debug("RARP_REQUEST for %s", str);
    590 			free(str);
    591 		}
    592 	}
    593 
    594 	/*
    595 	 * Third party lookups are rare and wonderful.
    596 	 */
    597 	if ((memcmp(shap, thap, rdev->physaddrlen) != 0) ||
    598 	    (memcmp(shap, shost, rdev->physaddrlen) != 0)) {
    599 		if (dflag)
    600 			debug("weird (3rd party lookup)");
    601 	}
    602 
    603 	/*
    604 	 * Fill in given parts of reply packet.
    605 	 */
    606 	(void) memcpy(shap, rdev->physaddr, rdev->physaddrlen);
    607 
    608 	/*
    609 	 * If a good address is stored in our lookup tables, return it
    610 	 * immediately or after a delay.  Store it in our kernel's ARP cache.
    611 	 */
    612 	if (get_ipaddr(rdev, thap, tpap, &spa))
    613 		return;
    614 	(void) memcpy(spap, &spa, sizeof (spa));
    615 
    616 	add_arp(rdev, tpap, thap);
    617 
    618 	rp->ar_op = htons(REVARP_REPLY);
    619 
    620 	if (dflag) {
    621 		struct in_addr addr;
    622 
    623 		(void) memcpy(&addr, tpap, sizeof (ipaddr_t));
    624 		debug("good lookup, maps to %s", inet_ntoa(addr));
    625 	}
    626 
    627 	rrp = calloc(1, sizeof (struct rarpreply) + rdev->physaddrlen +
    628 	    rdev->ifrarplen);
    629 	if (rrp == NULL)
    630 		error("out of memory");
    631 	rrp->lldest = (uchar_t *)rrp + sizeof (struct rarpreply);
    632 	rrp->arprep = rrp->lldest + rdev->physaddrlen;
    633 
    634 	/*
    635 	 * Create rarpreply structure.
    636 	 */
    637 	(void) gettimeofday(&rrp->tv, NULL);
    638 	rrp->tv.tv_sec += 3;	/* delay */
    639 	rrp->rdev = rdev;
    640 	(void) memcpy(rrp->lldest, shost, rdev->physaddrlen);
    641 	(void) memcpy(rrp->arprep, rp, rdev->ifrarplen);
    642 
    643 	/*
    644 	 * If this is diskless and we're not its bootserver, let the
    645 	 * bootserver reply first by delaying a while.
    646 	 */
    647 	(void) memcpy(&tpa, tpap, sizeof (ipaddr_t));
    648 	if (mightboot(ntohl(tpa))) {
    649 		retval = dlpi_send(rdev->dh_rarp, rrp->lldest,
    650 		    rdev->physaddrlen, rrp->arprep, rdev->ifrarplen, NULL);
    651 		if (retval != DLPI_SUCCESS) {
    652 			error("dlpi_send failed: %s", dlpi_strerror(retval));
    653 		} else if (dflag) {
    654 			debug("immediate reply sent");
    655 		}
    656 		(void) free(rrp);
    657 	} else {
    658 		delay_write(rdev, rrp);
    659 	}
    660 }
    661 
    662 /*
    663  * Download an ARP entry into our kernel.
    664  */
    665 static void
    666 add_arp(struct rarpdev *rdev, uchar_t *ip, uchar_t *laddr)
    667 {
    668 	struct xarpreq ar;
    669 	struct sockaddr_in	*sin;
    670 	int	fd;
    671 
    672 	/*
    673 	 * Common part of query or set.
    674 	 */
    675 	(void) memset(&ar, 0, sizeof (ar));
    676 	ar.xarp_pa.ss_family = AF_INET;
    677 	sin = (struct sockaddr_in *)&ar.xarp_pa;
    678 	(void) memcpy(&sin->sin_addr, ip, sizeof (ipaddr_t));
    679 
    680 	/*
    681 	 * Open the IP provider.
    682 	 */
    683 	if ((fd = open(DEVARP, 0)) < 0)
    684 		syserr(DEVARP);
    685 
    686 	/*
    687 	 * Set the entry.
    688 	 */
    689 	(void) memcpy(LLADDR(&ar.xarp_ha), laddr, rdev->physaddrlen);
    690 	ar.xarp_ha.sdl_alen = rdev->physaddrlen;
    691 	ar.xarp_ha.sdl_family = AF_LINK;
    692 	(void) strioctl(fd, SIOCDXARP, -1, sizeof (struct xarpreq),
    693 	    (char *)&ar);
    694 	if (strioctl(fd, SIOCSXARP, -1, sizeof (struct xarpreq),
    695 	    (char *)&ar) < 0)
    696 		syserr("SIOCSXARP");
    697 
    698 	(void) close(fd);
    699 }
    700 
    701 /*
    702  * The RARP spec says we must be able to process ARP requests,
    703  * even through the packet type is RARP.  Let's hope this feature
    704  * is not heavily used.
    705  */
    706 static void
    707 arp_request(struct rarpdev *rdev, struct arphdr *rp, uchar_t *shost)
    708 {
    709 	struct	rarpreply	*rrp;
    710 	struct ifdev		*ifdev;
    711 	uchar_t			*shap, *thap, *spap, *tpap;
    712 	int			retval;
    713 
    714 	shap = (uchar_t *)rp + sizeof (struct arphdr);
    715 	spap = shap + rp->ar_hln;
    716 	thap = spap + rp->ar_pln;
    717 	tpap = thap + rp->ar_hln;
    718 
    719 	if (dflag)
    720 		debug("ARPOP_REQUEST");
    721 
    722 	for (ifdev = rdev->ifdev; ifdev != NULL; ifdev = ifdev->next) {
    723 		if (memcmp(&ifdev->ipaddr, tpap, sizeof (ipaddr_t)) == 0)
    724 			break;
    725 	}
    726 	if (ifdev == NULL)
    727 		return;
    728 
    729 	rp->ar_op = ARPOP_REPLY;
    730 	(void) memcpy(shap, rdev->physaddr, rdev->physaddrlen);
    731 	(void) memcpy(spap, &ifdev->ipaddr, sizeof (ipaddr_t));
    732 	(void) memcpy(thap, rdev->physaddr, rdev->physaddrlen);
    733 
    734 	add_arp(rdev, tpap, thap);
    735 
    736 	/*
    737 	 * Create rarp reply structure.
    738 	 */
    739 	rrp = calloc(1, sizeof (struct rarpreply) + rdev->physaddrlen +
    740 	    rdev->ifrarplen);
    741 	if (rrp == NULL)
    742 		error("out of memory");
    743 	rrp->lldest = (uchar_t *)rrp + sizeof (struct rarpreply);
    744 	rrp->arprep = rrp->lldest + rdev->physaddrlen;
    745 	rrp->rdev = rdev;
    746 
    747 	(void) memcpy(rrp->lldest, shost, rdev->physaddrlen);
    748 	(void) memcpy(rrp->arprep, rp, rdev->ifrarplen);
    749 
    750 	retval = dlpi_send(rdev->dh_rarp, rrp->lldest, rdev->physaddrlen,
    751 	    rrp->arprep, rdev->ifrarplen, NULL);
    752 	free(rrp);
    753 	if (retval != DLPI_SUCCESS)
    754 		error("dlpi_send failed: %s", dlpi_strerror(retval));
    755 }
    756 
    757 /* ARGSUSED */
    758 static void
    759 do_delay_write(void *buf)
    760 {
    761 	struct	timeval		tv;
    762 	struct	rarpreply	*rrp;
    763 	struct	rarpdev		*rdev;
    764 	int			err;
    765 
    766 	for (;;) {
    767 		if ((err = sema_wait(&delay_sema)) != 0) {
    768 			if (err == EINTR)
    769 				continue;
    770 			error("do_delay_write: sema_wait failed");
    771 		}
    772 
    773 		(void) mutex_lock(&delay_mutex);
    774 		rrp = delay_list;
    775 		rdev = rrp->rdev;
    776 		delay_list = delay_list->next;
    777 		(void) mutex_unlock(&delay_mutex);
    778 
    779 		(void) gettimeofday(&tv, NULL);
    780 		if (tv.tv_sec < rrp->tv.tv_sec)
    781 			(void) sleep(rrp->tv.tv_sec - tv.tv_sec);
    782 
    783 		err = dlpi_send(rdev->dh_rarp, rrp->lldest, rdev->physaddrlen,
    784 		    rrp->arprep, rdev->ifrarplen, NULL);
    785 		if (err != DLPI_SUCCESS)
    786 			error("dlpi_send failed: %s", dlpi_strerror(err));
    787 
    788 		(void) free(rrp);
    789 	}
    790 }
    791 
    792 /* ARGSUSED */
    793 static void
    794 delay_write(struct rarpdev *rdev, struct rarpreply *rrp)
    795 {
    796 	struct	rarpreply	*trp;
    797 
    798 	(void) mutex_lock(&delay_mutex);
    799 	if (delay_list == NULL) {
    800 		delay_list = rrp;
    801 	} else {
    802 		trp = delay_list;
    803 		while (trp->next != NULL)
    804 			trp = trp->next;
    805 		trp->next = rrp;
    806 	}
    807 	(void) mutex_unlock(&delay_mutex);
    808 
    809 	(void) sema_post(&delay_sema);
    810 }
    811 
    812 /*
    813  * See if we have a TFTP boot file for this guy. Filenames in TFTP
    814  * boot requests are of the form <ipaddr> for Sun-3's and of the form
    815  * <ipaddr>.<arch> for all other architectures.  Since we don't know
    816  * the client's architecture, either format will do.
    817  */
    818 static int
    819 mightboot(ipaddr_t ipa)
    820 {
    821 	char path[MAXPATHL];
    822 	DIR *dirp;
    823 	struct dirent *dp;
    824 
    825 	(void) snprintf(path, sizeof (path), "%s/%08X", BOOTDIR, ipa);
    826 
    827 	/*
    828 	 * Try a quick access() first.
    829 	 */
    830 	if (access(path, 0) == 0)
    831 		return (1);
    832 
    833 	/*
    834 	 * Not there, do it the slow way by
    835 	 * reading through the directory.
    836 	 */
    837 	(void) sprintf(path, "%08X", ipa);
    838 
    839 	if (!(dirp = opendir(BOOTDIR)))
    840 		return (0);
    841 
    842 	while ((dp = readdir(dirp)) != NULL) {
    843 		if (strncmp(dp->d_name, path, 8) != 0)
    844 			continue;
    845 		if ((strlen(dp->d_name) != 8) && (dp->d_name[8] != '.'))
    846 			continue;
    847 		break;
    848 	}
    849 
    850 	(void) closedir(dirp);
    851 
    852 	return ((dp != NULL) ? 1 : 0);
    853 }
    854 
    855 /*
    856  * Get our IP address and local netmask.
    857  */
    858 static void
    859 get_ifdata(char *dev, int unit, ipaddr_t *ipp, ipaddr_t *maskp)
    860 {
    861 	int	fd;
    862 	struct	ifreq	ifr;
    863 	struct	sockaddr_in	*sin;
    864 
    865 	/* LINTED pointer */
    866 	sin = (struct sockaddr_in *)&ifr.ifr_addr;
    867 
    868 	/*
    869 	 * Open the IP provider.
    870 	 */
    871 	if ((fd = open(DEVIP, 0)) < 0)
    872 		syserr(DEVIP);
    873 
    874 	/*
    875 	 * Ask IP for our IP address.
    876 	 */
    877 	(void) snprintf(ifr.ifr_name, sizeof (ifr.ifr_name), "%s%d", dev, unit);
    878 	if (strioctl(fd, SIOCGIFADDR, -1, sizeof (struct ifreq),
    879 	    (char *)&ifr) < 0)
    880 		syserr("SIOCGIFADDR");
    881 	*ipp = (ipaddr_t)ntohl(sin->sin_addr.s_addr);
    882 
    883 	if (dflag)
    884 		debug("device %s%d address %s", dev, unit,
    885 		    inet_ntoa(sin->sin_addr));
    886 
    887 	/*
    888 	 * Ask IP for our netmask.
    889 	 */
    890 	if (strioctl(fd, SIOCGIFNETMASK, -1, sizeof (struct ifreq),
    891 	    (char *)&ifr) < 0)
    892 		syserr("SIOCGIFNETMASK");
    893 	*maskp = (ipaddr_t)ntohl(sin->sin_addr.s_addr);
    894 
    895 	if (dflag)
    896 		debug("device %s%d subnet mask %s", dev, unit,
    897 		    inet_ntoa(sin->sin_addr));
    898 
    899 	/*
    900 	 * Thankyou ip.
    901 	 */
    902 	(void) close(fd);
    903 }
    904 
    905 /*
    906  * Translate mac address to IP address.
    907  * Return 0 on success, nonzero on failure.
    908  */
    909 static int
    910 get_ipaddr(struct rarpdev *rdev, uchar_t *laddr, uchar_t *ipp, ipaddr_t *ipaddr)
    911 {
    912 	char host[MAXHOSTL];
    913 	char hbuffer[BUFSIZE];
    914 	struct hostent *hp, res;
    915 	int herror;
    916 	struct in_addr addr;
    917 	char	**p;
    918 	struct ifdev *ifdev;
    919 
    920 	if (rdev->physaddrlen != ETHERADDRL) {
    921 		if (dflag)
    922 			debug("%s %s", " cannot map non 6 byte hardware ",
    923 			    "address to IP address");
    924 		return (1);
    925 	}
    926 
    927 	/*
    928 	 * Translate mac address to hostname and IP address.
    929 	 */
    930 	if (ether_ntohost(host, (struct ether_addr *)laddr) != 0 ||
    931 	    !(hp = gethostbyname_r(host, &res, hbuffer, sizeof (hbuffer),
    932 	    &herror)) ||
    933 	    hp->h_addrtype != AF_INET || hp->h_length != sizeof (ipaddr_t)) {
    934 		if (dflag)
    935 			debug("could not map hardware address to IP address");
    936 		return (1);
    937 	}
    938 
    939 	/*
    940 	 * Find the IP address on the right net.
    941 	 */
    942 	for (p = hp->h_addr_list; *p; p++) {
    943 		(void) memcpy(&addr, *p, sizeof (ipaddr_t));
    944 		for (ifdev = rdev->ifdev; ifdev != NULL; ifdev = ifdev->next) {
    945 			if (dflag) {
    946 				struct in_addr daddr;
    947 				ipaddr_t netnum;
    948 
    949 				netnum = htonl(ifdev->if_netnum);
    950 				(void) memcpy(&daddr, &netnum,
    951 				    sizeof (ipaddr_t));
    952 				if (ifdev->lunit == -1)
    953 					debug("trying physical netnum %s"
    954 					    " mask %x", inet_ntoa(daddr),
    955 					    ifdev->if_netmask);
    956 				else
    957 					debug("trying logical %d netnum %s"
    958 					    " mask %x", ifdev->lunit,
    959 					    inet_ntoa(daddr),
    960 					    ifdev->if_netmask);
    961 			}
    962 			if ((ntohl(addr.s_addr) & ifdev->if_netmask) ==
    963 			    ifdev->if_netnum) {
    964 				/*
    965 				 * Return the correct IP address.
    966 				 */
    967 				(void) memcpy(ipp, &addr, sizeof (ipaddr_t));
    968 
    969 				/*
    970 				 * Return the interface's ipaddr
    971 				 */
    972 				(void) memcpy(ipaddr, &ifdev->ipaddr,
    973 				    sizeof (ipaddr_t));
    974 
    975 				return (0);
    976 			}
    977 		}
    978 	}
    979 
    980 	if (dflag)
    981 		debug("got host entry but no IP address on this net");
    982 	return (1);
    983 }
    984 
    985 static int
    986 strioctl(int fd, int cmd, int timout, int len, char *dp)
    987 {
    988 	struct	strioctl	si;
    989 
    990 	si.ic_cmd = cmd;
    991 	si.ic_timout = timout;
    992 	si.ic_len = len;
    993 	si.ic_dp = dp;
    994 	return (ioctl(fd, I_STR, &si));
    995 }
    996 
    997 static void
    998 usage(void)
    999 {
   1000 	error("Usage:  %s [ -ad ] device unit", cmdname);
   1001 }
   1002 
   1003 static void
   1004 syserr(const char *s)
   1005 {
   1006 	char buf[256];
   1007 	int status = 1;
   1008 
   1009 	(void) snprintf(buf, sizeof (buf), "%s: %s", s, strerror(errno));
   1010 	(void) fprintf(stderr, "%s:  %s\n", cmdname, buf);
   1011 	syslog(LOG_ERR, "%s", buf);
   1012 	thr_exit(&status);
   1013 }
   1014 
   1015 static void
   1016 error(const char *fmt, ...)
   1017 {
   1018 	char buf[256];
   1019 	va_list ap;
   1020 	int status = 1;
   1021 
   1022 	va_start(ap, fmt);
   1023 	(void) vsprintf(buf, fmt, ap);
   1024 	va_end(ap);
   1025 	(void) fprintf(stderr, "%s:  %s\n", cmdname, buf);
   1026 	syslog(LOG_ERR, buf);
   1027 	thr_exit(&status);
   1028 }
   1029 
   1030 /*PRINTFLIKE1*/
   1031 static void
   1032 debug(char *fmt, ...)
   1033 {
   1034 	va_list ap;
   1035 
   1036 	(void) mutex_lock(&debug_mutex);
   1037 	va_start(ap, fmt);
   1038 	(void) fprintf(stderr, "%s:[%u]  ", cmdname, thr_self());
   1039 	(void) vfprintf(stderr, fmt, ap);
   1040 	(void) fprintf(stderr, "\n");
   1041 	va_end(ap);
   1042 	(void) mutex_unlock(&debug_mutex);
   1043 }
   1044