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