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