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