dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.sbin / in.rarpd.c
blob6126980cf0fedd5d3b516cc6a6ab10faf3ce6830
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
26 /* All Rights Reserved */
29 * Portions of this source code were derived from Berkeley 4.3 BSD
30 * under license from the Regents of the University of California.
34 * rarpd.c Reverse-ARP server.
35 * Refer to RFC 903 "A Reverse Address Resolution Protocol".
38 #include <thread.h>
39 #include <synch.h>
40 #include <stdlib.h>
41 #include <unistd.h>
42 #include <sys/resource.h>
43 #include <stdio.h>
44 #include <stdio_ext.h>
45 #include <stdarg.h>
46 #include <string.h>
47 #include <fcntl.h>
48 #include <sys/types.h>
49 #include <dirent.h>
50 #include <syslog.h>
51 #include <netdb.h>
52 #include <errno.h>
53 #include <sys/socket.h>
54 #include <sys/sockio.h>
55 #include <net/if.h>
56 #include <netinet/if_ether.h>
57 #include <netinet/in.h>
58 #include <arpa/inet.h>
59 #include <stropts.h>
60 #include <libinetutil.h>
61 #include <libdlpi.h>
62 #include <net/if_types.h>
63 #include <net/if_dl.h>
65 #define BOOTDIR "/tftpboot" /* boot files directory */
66 #define DEVIP "/dev/ip" /* path to ip driver */
67 #define DEVARP "/dev/arp" /* path to arp driver */
69 #define BUFSIZE 2048 /* max receive frame length */
70 #define MAXPATHL 128 /* max path length */
71 #define MAXHOSTL 128 /* max host name length */
72 #define MAXIFS 256
75 * Logical network devices
77 struct ifdev {
78 char ldevice[IFNAMSIZ];
79 int lunit;
80 ipaddr_t ipaddr; /* network order */
81 ipaddr_t if_netmask; /* host order */
82 ipaddr_t if_ipaddr; /* host order */
83 ipaddr_t if_netnum; /* host order, with subnet */
84 struct ifdev *next;
88 * Physical network device
90 struct rarpdev {
91 char device[DLPI_LINKNAME_MAX];
92 uint_t unit;
93 dlpi_handle_t dh_rarp;
94 uchar_t physaddr[DLPI_PHYSADDR_MAX];
95 /* mac address of interface */
96 uint_t physaddrlen; /* mac address length */
97 int ifrarplen; /* size of rarp data packet */
98 struct ifdev *ifdev; /* private interface info */
99 struct rarpdev *next; /* list of managed devices */
102 struct rarpreply {
103 struct rarpdev *rdev; /* which device reply for */
104 struct timeval tv; /* send RARP reply by when */
105 uchar_t *lldest; /* target mac to send reply */
106 uchar_t *arprep; /* [R]ARP response */
107 struct rarpreply *next;
110 static struct rarpreply *delay_list;
111 static sema_t delay_sema;
112 static mutex_t delay_mutex;
113 static mutex_t debug_mutex;
115 static struct rarpdev *rarpdev_head;
118 * Globals initialized before multi-threading
120 static char *cmdname; /* command name from argv[0] */
121 static int dflag = 0; /* enable diagnostics */
122 static int aflag = 0; /* start rarpd on all interfaces */
124 static void getintf(void);
125 static struct rarpdev *find_device(ifspec_t *);
126 static void init_rarpdev(struct rarpdev *);
127 static void do_rarp(void *);
128 static void rarp_request(struct rarpdev *, struct arphdr *,
129 uchar_t *);
130 static void add_arp(struct rarpdev *, uchar_t *, uchar_t *);
131 static void arp_request(struct rarpdev *, struct arphdr *, uchar_t *);
132 static void do_delay_write(void *);
133 static void delay_write(struct rarpdev *, struct rarpreply *);
134 static int mightboot(ipaddr_t);
135 static void get_ifdata(char *, int, ipaddr_t *, ipaddr_t *);
136 static int get_ipaddr(struct rarpdev *, uchar_t *, uchar_t *, ipaddr_t *);
137 static int strioctl(int, int, int, int, char *);
138 static void usage();
139 static void syserr(const char *);
140 /*PRINTFLIKE1*/
141 static void error(const char *, ...);
142 static void debug(char *, ...);
144 extern int optind;
145 extern char *optarg;
148 main(int argc, char *argv[])
150 int c;
151 struct rlimit rl;
152 struct rarpdev *rdev;
153 int i;
155 cmdname = argv[0];
157 while ((c = getopt(argc, argv, "ad")) != -1) {
158 switch (c) {
159 case 'a':
160 aflag = 1;
161 break;
163 case 'd':
164 dflag = 1;
165 break;
167 default:
168 usage();
172 if ((!aflag && (argc - optind) != 2) ||
173 (aflag && (argc - optind) != 0)) {
174 usage();
175 /* NOTREACHED */
178 if (!dflag) {
180 * Background
182 switch (fork()) {
183 case -1: /* error */
184 syserr("fork");
185 /*NOTREACHED*/
187 case 0: /* child */
188 break;
190 default: /* parent */
191 return (0);
193 for (i = 0; i < 3; i++) {
194 (void) close(i);
196 (void) open("/", O_RDONLY, 0);
197 (void) dup2(0, 1);
198 (void) dup2(0, 2);
200 * Detach terminal
202 if (setsid() < 0)
203 syserr("setsid");
206 rl.rlim_cur = RLIM_INFINITY;
207 rl.rlim_max = RLIM_INFINITY;
208 if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
209 syserr("setrlimit");
210 (void) enable_extended_FILE_stdio(-1, -1);
212 (void) openlog(cmdname, LOG_PID, LOG_DAEMON);
214 if (aflag) {
216 * Get each interface name and load rarpdev list.
218 getintf();
219 } else {
220 ifspec_t ifsp;
221 struct ifdev *ifdev;
222 char buf[IFNAMSIZ + 1];
225 * Load specified device as only element of the list.
227 rarpdev_head = (struct rarpdev *)calloc(1,
228 sizeof (struct rarpdev));
229 if (rarpdev_head == NULL) {
230 error("out of memory");
232 (void) strncpy(buf, argv[optind], IFNAMSIZ);
233 (void) strncat(buf, argv[optind + 1], IFNAMSIZ - strlen(buf));
235 if ((ifdev = calloc(1, sizeof (struct ifdev))) == NULL) {
236 error("out of memory");
239 if (!ifparse_ifspec(buf, &ifsp))
240 error("invalid interface specification");
242 if (ifsp.ifsp_lunvalid) {
243 (void) snprintf(ifdev->ldevice,
244 sizeof (ifdev->ldevice), "%s%d:",
245 ifsp.ifsp_devnm, ifsp.ifsp_ppa);
246 ifdev->lunit = ifsp.ifsp_lun;
247 } else {
248 ifdev->lunit = -1; /* no logical unit */
250 (void) strlcpy(rarpdev_head->device, ifsp.ifsp_devnm,
251 sizeof (rarpdev_head->device));
252 rarpdev_head->unit = ifsp.ifsp_ppa;
254 ifdev->next = rarpdev_head->ifdev;
255 rarpdev_head->ifdev = ifdev;
259 * Initialize each rarpdev.
261 for (rdev = rarpdev_head; rdev != NULL; rdev = rdev->next) {
262 init_rarpdev(rdev);
265 (void) sema_init(&delay_sema, 0, USYNC_THREAD, NULL);
266 (void) mutex_init(&delay_mutex, USYNC_THREAD, NULL);
267 (void) mutex_init(&debug_mutex, USYNC_THREAD, NULL);
270 * Start delayed processing thread.
272 (void) thr_create(NULL, 0, (void *(*)(void *))do_delay_write, NULL,
273 THR_NEW_LWP, NULL);
276 * Start RARP processing for each device.
278 for (rdev = rarpdev_head; rdev != NULL; rdev = rdev->next) {
279 if (rdev->dh_rarp != NULL) {
280 (void) thr_create(NULL, 0,
281 (void *(*)(void *))do_rarp, (void *)rdev,
282 THR_NEW_LWP, NULL);
287 * Exit main() thread
289 thr_exit(NULL);
291 return (0);
294 static void
295 getintf(void)
297 int fd;
298 int numifs;
299 unsigned bufsize;
300 struct ifreq *reqbuf;
301 struct ifconf ifconf;
302 struct ifreq *ifr;
303 struct rarpdev *rdev;
304 struct ifdev *ifdev;
307 * Open the IP provider.
309 if ((fd = open(DEVIP, O_RDONLY)) < 0)
310 syserr(DEVIP);
313 * Ask IP for the list of configured interfaces.
315 if (ioctl(fd, SIOCGIFNUM, (char *)&numifs) < 0) {
316 numifs = MAXIFS;
318 bufsize = numifs * sizeof (struct ifreq);
319 reqbuf = (struct ifreq *)malloc(bufsize);
320 if (reqbuf == NULL) {
321 error("out of memory");
324 ifconf.ifc_len = bufsize;
325 ifconf.ifc_buf = (caddr_t)reqbuf;
326 if (ioctl(fd, SIOCGIFCONF, (char *)&ifconf) < 0)
327 syserr("SIOCGIFCONF");
330 * Initialize a rarpdev for each interface.
332 for (ifr = ifconf.ifc_req; ifconf.ifc_len > 0;
333 ifr++, ifconf.ifc_len -= sizeof (struct ifreq)) {
334 ifspec_t ifsp;
336 if (ioctl(fd, SIOCGIFFLAGS, (char *)ifr) < 0) {
337 syserr("ioctl SIOCGIFFLAGS");
338 exit(1);
340 if ((ifr->ifr_flags & IFF_LOOPBACK) ||
341 !(ifr->ifr_flags & IFF_UP) ||
342 !(ifr->ifr_flags & IFF_BROADCAST) ||
343 (ifr->ifr_flags & IFF_NOARP) ||
344 (ifr->ifr_flags & IFF_POINTOPOINT))
345 continue;
347 if (!ifparse_ifspec(ifr->ifr_name, &ifsp))
348 error("ifparse_ifspec failed");
351 * Look for an existing device for logical interfaces.
353 if ((rdev = find_device(&ifsp)) == NULL) {
354 rdev = calloc(1, sizeof (struct rarpdev));
355 if (rdev == NULL)
356 error("out of memory");
358 (void) strlcpy(rdev->device, ifsp.ifsp_devnm,
359 sizeof (rdev->device));
360 rdev->unit = ifsp.ifsp_ppa;
362 rdev->next = rarpdev_head;
363 rarpdev_head = rdev;
366 if ((ifdev = calloc(1, sizeof (struct ifdev))) == NULL)
367 error("out of memory");
369 if (ifsp.ifsp_lunvalid) {
370 (void) snprintf(ifdev->ldevice,
371 sizeof (ifdev->ldevice), "%s%d:",
372 ifsp.ifsp_devnm, ifsp.ifsp_ppa);
373 ifdev->lunit = ifsp.ifsp_lun;
374 } else
375 ifdev->lunit = -1; /* no logical unit */
377 ifdev->next = rdev->ifdev;
378 rdev->ifdev = ifdev;
380 (void) free((char *)reqbuf);
383 static struct rarpdev *
384 find_device(ifspec_t *specp)
386 struct rarpdev *rdev;
388 for (rdev = rarpdev_head; rdev != NULL; rdev = rdev->next) {
389 if (specp->ifsp_ppa == rdev->unit &&
390 strcmp(specp->ifsp_devnm, rdev->device) == 0)
391 return (rdev);
393 return (NULL);
396 static void
397 init_rarpdev(struct rarpdev *rdev)
399 char *dev;
400 int unit;
401 struct ifdev *ifdev;
402 int retval;
403 char *str = NULL;
404 uint_t physaddrlen = DLPI_PHYSADDR_MAX;
405 char linkname[DLPI_LINKNAME_MAX];
406 dlpi_handle_t dh;
408 (void) snprintf(linkname, DLPI_LINKNAME_MAX, "%s%d", rdev->device,
409 rdev->unit);
411 * Open datalink provider and get our mac address.
413 if ((retval = dlpi_open(linkname, &dh, 0)) != DLPI_SUCCESS) {
414 error("cannot open link %s: %s", linkname,
415 dlpi_strerror(retval));
418 if ((retval = dlpi_bind(dh, ETHERTYPE_REVARP, NULL)) != DLPI_SUCCESS) {
419 dlpi_close(dh);
420 error("dlpi_bind failed: %s", dlpi_strerror(retval));
424 * Save our mac address.
426 if ((retval = dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR, rdev->physaddr,
427 &physaddrlen)) != DLPI_SUCCESS) {
428 dlpi_close(dh);
429 error("dlpi_get_physaddr failed: %s", dlpi_strerror(retval));
432 rdev->physaddrlen = physaddrlen;
433 rdev->ifrarplen = sizeof (struct arphdr) + (2 * sizeof (ipaddr_t)) +
434 (2 * physaddrlen);
436 if (dflag) {
437 str = _link_ntoa(rdev->physaddr, str,
438 rdev->physaddrlen, IFT_OTHER);
439 if (str != NULL) {
440 debug("device %s physical address %s", linkname, str);
441 free(str);
446 * Assign dlpi handle to rdev.
448 rdev->dh_rarp = dh;
451 * Get the IP address and netmask from directory service for
452 * each logical interface.
454 for (ifdev = rdev->ifdev; ifdev != NULL; ifdev = ifdev->next) {
456 * If lunit == -1 then this is the primary interface name.
458 if (ifdev->lunit == -1) {
459 dev = rdev->device;
460 unit = rdev->unit;
461 } else {
462 dev = ifdev->ldevice;
463 unit = ifdev->lunit;
465 get_ifdata(dev, unit, &ifdev->if_ipaddr, &ifdev->if_netmask);
468 * Use IP address of the interface.
470 ifdev->if_netnum = ifdev->if_ipaddr & ifdev->if_netmask;
471 ifdev->ipaddr = (ipaddr_t)htonl(ifdev->if_ipaddr);
475 static void
476 do_rarp(void *buf)
478 struct rarpdev *rdev = buf;
479 char *cause;
480 struct arphdr *ans;
481 uchar_t *shost;
482 uint_t saddrlen;
483 size_t anslen = rdev->ifrarplen;
484 char *str = NULL;
485 int retval;
487 if (((shost = malloc(rdev->physaddrlen)) == NULL) ||
488 ((ans = malloc(rdev->ifrarplen)) == NULL))
489 syserr("malloc");
491 if (dflag) {
492 str = _link_ntoa(rdev->physaddr, str, rdev->physaddrlen,
493 IFT_OTHER);
494 if (str != NULL) {
495 debug("starting rarp service on device %s%d physical"
496 " address %s", rdev->device, rdev->unit, str);
497 free(str);
502 * Read RARP packets and respond to them.
504 for (;;) {
505 saddrlen = DLPI_PHYSADDR_MAX;
506 retval = dlpi_recv(rdev->dh_rarp, shost,
507 &saddrlen, ans, &anslen, -1, NULL);
508 if (retval == DLPI_ETIMEDOUT) {
509 continue;
510 } else if (retval != DLPI_SUCCESS) {
511 error("error in dlpi_recv %s: %s", rdev->dh_rarp,
512 dlpi_strerror(retval));
515 cause = NULL;
517 if (anslen < rdev->ifrarplen)
518 cause = "short packet";
519 else if (ans->ar_hrd != htons(ARPHRD_ETHER))
520 cause = "hardware type not Ethernet";
521 else if (ans->ar_pro != htons(ETHERTYPE_IP))
522 cause = "protocol type not IP";
523 else if (ans->ar_hln != rdev->physaddrlen)
524 cause = "unexpected hardware address length";
525 else if (ans->ar_pln != sizeof (ipaddr_t))
526 cause = "unexpected protocol address length";
527 if (cause != NULL) {
528 if (dflag)
529 debug("RARP packet received but "
530 "discarded: %s", cause);
531 continue;
535 * Handle the request.
537 switch (ntohs(ans->ar_op)) {
538 case REVARP_REQUEST:
539 rarp_request(rdev, ans, shost);
540 break;
542 case ARPOP_REQUEST:
543 arp_request(rdev, ans, shost);
544 break;
546 case REVARP_REPLY:
547 if (dflag)
548 debug("REVARP_REPLY ignored");
549 break;
551 case ARPOP_REPLY:
552 if (dflag)
553 debug("ARPOP_REPLY ignored");
554 break;
556 default:
557 if (dflag)
558 debug("unknown opcode 0x%x", ans->ar_op);
559 break;
565 * Reverse address determination and allocation code.
567 static void
568 rarp_request(struct rarpdev *rdev, struct arphdr *rp, uchar_t *shost)
570 ipaddr_t tpa, spa;
571 struct rarpreply *rrp;
572 uchar_t *shap, *thap, *spap, *tpap;
573 char *str = NULL;
574 int retval;
576 shap = (uchar_t *)rp + sizeof (struct arphdr);
577 spap = shap + rp->ar_hln;
578 thap = spap + rp->ar_pln;
579 tpap = thap + rp->ar_hln;
581 if (dflag) {
582 str = _link_ntoa(thap, str, rdev->physaddrlen, IFT_OTHER);
583 if (str != NULL) {
584 debug("RARP_REQUEST for %s", str);
585 free(str);
590 * Third party lookups are rare and wonderful.
592 if ((memcmp(shap, thap, rdev->physaddrlen) != 0) ||
593 (memcmp(shap, shost, rdev->physaddrlen) != 0)) {
594 if (dflag)
595 debug("weird (3rd party lookup)");
599 * Fill in given parts of reply packet.
601 (void) memcpy(shap, rdev->physaddr, rdev->physaddrlen);
604 * If a good address is stored in our lookup tables, return it
605 * immediately or after a delay. Store it in our kernel's ARP cache.
607 if (get_ipaddr(rdev, thap, tpap, &spa))
608 return;
609 (void) memcpy(spap, &spa, sizeof (spa));
611 add_arp(rdev, tpap, thap);
613 rp->ar_op = htons(REVARP_REPLY);
615 if (dflag) {
616 struct in_addr addr;
618 (void) memcpy(&addr, tpap, sizeof (ipaddr_t));
619 debug("good lookup, maps to %s", inet_ntoa(addr));
622 rrp = calloc(1, sizeof (struct rarpreply) + rdev->physaddrlen +
623 rdev->ifrarplen);
624 if (rrp == NULL)
625 error("out of memory");
626 rrp->lldest = (uchar_t *)rrp + sizeof (struct rarpreply);
627 rrp->arprep = rrp->lldest + rdev->physaddrlen;
630 * Create rarpreply structure.
632 (void) gettimeofday(&rrp->tv, NULL);
633 rrp->tv.tv_sec += 3; /* delay */
634 rrp->rdev = rdev;
635 (void) memcpy(rrp->lldest, shost, rdev->physaddrlen);
636 (void) memcpy(rrp->arprep, rp, rdev->ifrarplen);
639 * If this is diskless and we're not its bootserver, let the
640 * bootserver reply first by delaying a while.
642 (void) memcpy(&tpa, tpap, sizeof (ipaddr_t));
643 if (mightboot(ntohl(tpa))) {
644 retval = dlpi_send(rdev->dh_rarp, rrp->lldest,
645 rdev->physaddrlen, rrp->arprep, rdev->ifrarplen, NULL);
646 if (retval != DLPI_SUCCESS) {
647 error("dlpi_send failed: %s", dlpi_strerror(retval));
648 } else if (dflag) {
649 debug("immediate reply sent");
651 (void) free(rrp);
652 } else {
653 delay_write(rdev, rrp);
658 * Download an ARP entry into our kernel.
660 static void
661 add_arp(struct rarpdev *rdev, uchar_t *ip, uchar_t *laddr)
663 struct xarpreq ar;
664 struct sockaddr_in *sin;
665 int fd;
668 * Common part of query or set.
670 (void) memset(&ar, 0, sizeof (ar));
671 ar.xarp_pa.ss_family = AF_INET;
672 sin = (struct sockaddr_in *)&ar.xarp_pa;
673 (void) memcpy(&sin->sin_addr, ip, sizeof (ipaddr_t));
676 * Open the IP provider.
678 if ((fd = open(DEVARP, O_RDONLY)) < 0)
679 syserr(DEVARP);
682 * Set the entry.
684 (void) memcpy(LLADDR(&ar.xarp_ha), laddr, rdev->physaddrlen);
685 ar.xarp_ha.sdl_alen = rdev->physaddrlen;
686 ar.xarp_ha.sdl_family = AF_LINK;
687 (void) strioctl(fd, SIOCDXARP, -1, sizeof (struct xarpreq),
688 (char *)&ar);
689 if (strioctl(fd, SIOCSXARP, -1, sizeof (struct xarpreq),
690 (char *)&ar) < 0)
691 syserr("SIOCSXARP");
693 (void) close(fd);
697 * The RARP spec says we must be able to process ARP requests,
698 * even through the packet type is RARP. Let's hope this feature
699 * is not heavily used.
701 static void
702 arp_request(struct rarpdev *rdev, struct arphdr *rp, uchar_t *shost)
704 struct rarpreply *rrp;
705 struct ifdev *ifdev;
706 uchar_t *shap, *thap, *spap, *tpap;
707 int retval;
709 shap = (uchar_t *)rp + sizeof (struct arphdr);
710 spap = shap + rp->ar_hln;
711 thap = spap + rp->ar_pln;
712 tpap = thap + rp->ar_hln;
714 if (dflag)
715 debug("ARPOP_REQUEST");
717 for (ifdev = rdev->ifdev; ifdev != NULL; ifdev = ifdev->next) {
718 if (memcmp(&ifdev->ipaddr, tpap, sizeof (ipaddr_t)) == 0)
719 break;
721 if (ifdev == NULL)
722 return;
724 rp->ar_op = ARPOP_REPLY;
725 (void) memcpy(shap, rdev->physaddr, rdev->physaddrlen);
726 (void) memcpy(spap, &ifdev->ipaddr, sizeof (ipaddr_t));
727 (void) memcpy(thap, rdev->physaddr, rdev->physaddrlen);
729 add_arp(rdev, tpap, thap);
732 * Create rarp reply structure.
734 rrp = calloc(1, sizeof (struct rarpreply) + rdev->physaddrlen +
735 rdev->ifrarplen);
736 if (rrp == NULL)
737 error("out of memory");
738 rrp->lldest = (uchar_t *)rrp + sizeof (struct rarpreply);
739 rrp->arprep = rrp->lldest + rdev->physaddrlen;
740 rrp->rdev = rdev;
742 (void) memcpy(rrp->lldest, shost, rdev->physaddrlen);
743 (void) memcpy(rrp->arprep, rp, rdev->ifrarplen);
745 retval = dlpi_send(rdev->dh_rarp, rrp->lldest, rdev->physaddrlen,
746 rrp->arprep, rdev->ifrarplen, NULL);
747 free(rrp);
748 if (retval != DLPI_SUCCESS)
749 error("dlpi_send failed: %s", dlpi_strerror(retval));
752 /* ARGSUSED */
753 static void
754 do_delay_write(void *buf)
756 struct timeval tv;
757 struct rarpreply *rrp;
758 struct rarpdev *rdev;
759 int err;
761 for (;;) {
762 if ((err = sema_wait(&delay_sema)) != 0) {
763 if (err == EINTR)
764 continue;
765 error("do_delay_write: sema_wait failed");
768 (void) mutex_lock(&delay_mutex);
769 rrp = delay_list;
770 rdev = rrp->rdev;
771 delay_list = delay_list->next;
772 (void) mutex_unlock(&delay_mutex);
774 (void) gettimeofday(&tv, NULL);
775 if (tv.tv_sec < rrp->tv.tv_sec)
776 (void) sleep(rrp->tv.tv_sec - tv.tv_sec);
778 err = dlpi_send(rdev->dh_rarp, rrp->lldest, rdev->physaddrlen,
779 rrp->arprep, rdev->ifrarplen, NULL);
780 if (err != DLPI_SUCCESS)
781 error("dlpi_send failed: %s", dlpi_strerror(err));
783 (void) free(rrp);
787 /* ARGSUSED */
788 static void
789 delay_write(struct rarpdev *rdev, struct rarpreply *rrp)
791 struct rarpreply *trp;
793 (void) mutex_lock(&delay_mutex);
794 if (delay_list == NULL) {
795 delay_list = rrp;
796 } else {
797 trp = delay_list;
798 while (trp->next != NULL)
799 trp = trp->next;
800 trp->next = rrp;
802 (void) mutex_unlock(&delay_mutex);
804 (void) sema_post(&delay_sema);
808 * See if we have a TFTP boot file for this guy. Filenames in TFTP
809 * boot requests are of the form <ipaddr> for Sun-3's and of the form
810 * <ipaddr>.<arch> for all other architectures. Since we don't know
811 * the client's architecture, either format will do.
813 static int
814 mightboot(ipaddr_t ipa)
816 char path[MAXPATHL];
817 DIR *dirp;
818 struct dirent *dp;
820 (void) snprintf(path, sizeof (path), "%s/%08X", BOOTDIR, ipa);
823 * Try a quick access() first.
825 if (access(path, 0) == 0)
826 return (1);
829 * Not there, do it the slow way by
830 * reading through the directory.
832 (void) sprintf(path, "%08X", ipa);
834 if (!(dirp = opendir(BOOTDIR)))
835 return (0);
837 while ((dp = readdir(dirp)) != NULL) {
838 if (strncmp(dp->d_name, path, 8) != 0)
839 continue;
840 if ((strlen(dp->d_name) != 8) && (dp->d_name[8] != '.'))
841 continue;
842 break;
845 (void) closedir(dirp);
847 return ((dp != NULL) ? 1 : 0);
851 * Get our IP address and local netmask.
853 static void
854 get_ifdata(char *dev, int unit, ipaddr_t *ipp, ipaddr_t *maskp)
856 int fd;
857 struct ifreq ifr;
858 struct sockaddr_in *sin;
860 /* LINTED pointer */
861 sin = (struct sockaddr_in *)&ifr.ifr_addr;
864 * Open the IP provider.
866 if ((fd = open(DEVIP, O_RDONLY)) < 0)
867 syserr(DEVIP);
870 * Ask IP for our IP address.
872 (void) snprintf(ifr.ifr_name, sizeof (ifr.ifr_name), "%s%d", dev, unit);
873 if (strioctl(fd, SIOCGIFADDR, -1, sizeof (struct ifreq),
874 (char *)&ifr) < 0)
875 syserr("SIOCGIFADDR");
876 *ipp = (ipaddr_t)ntohl(sin->sin_addr.s_addr);
878 if (dflag)
879 debug("device %s%d address %s", dev, unit,
880 inet_ntoa(sin->sin_addr));
883 * Ask IP for our netmask.
885 if (strioctl(fd, SIOCGIFNETMASK, -1, sizeof (struct ifreq),
886 (char *)&ifr) < 0)
887 syserr("SIOCGIFNETMASK");
888 *maskp = (ipaddr_t)ntohl(sin->sin_addr.s_addr);
890 if (dflag)
891 debug("device %s%d subnet mask %s", dev, unit,
892 inet_ntoa(sin->sin_addr));
895 * Thankyou ip.
897 (void) close(fd);
901 * Translate mac address to IP address.
902 * Return 0 on success, nonzero on failure.
904 static int
905 get_ipaddr(struct rarpdev *rdev, uchar_t *laddr, uchar_t *ipp, ipaddr_t *ipaddr)
907 char host[MAXHOSTL];
908 char hbuffer[BUFSIZE];
909 struct hostent *hp, res;
910 int herror;
911 struct in_addr addr;
912 char **p;
913 struct ifdev *ifdev;
915 if (rdev->physaddrlen != ETHERADDRL) {
916 if (dflag)
917 debug("%s %s", " cannot map non 6 byte hardware ",
918 "address to IP address");
919 return (1);
923 * Translate mac address to hostname and IP address.
925 if (ether_ntohost(host, (struct ether_addr *)laddr) != 0 ||
926 !(hp = gethostbyname_r(host, &res, hbuffer, sizeof (hbuffer),
927 &herror)) ||
928 hp->h_addrtype != AF_INET || hp->h_length != sizeof (ipaddr_t)) {
929 if (dflag)
930 debug("could not map hardware address to IP address");
931 return (1);
935 * Find the IP address on the right net.
937 for (p = hp->h_addr_list; *p; p++) {
938 (void) memcpy(&addr, *p, sizeof (ipaddr_t));
939 for (ifdev = rdev->ifdev; ifdev != NULL; ifdev = ifdev->next) {
940 if (dflag) {
941 struct in_addr daddr;
942 ipaddr_t netnum;
944 netnum = htonl(ifdev->if_netnum);
945 (void) memcpy(&daddr, &netnum,
946 sizeof (ipaddr_t));
947 if (ifdev->lunit == -1)
948 debug("trying physical netnum %s"
949 " mask %x", inet_ntoa(daddr),
950 ifdev->if_netmask);
951 else
952 debug("trying logical %d netnum %s"
953 " mask %x", ifdev->lunit,
954 inet_ntoa(daddr),
955 ifdev->if_netmask);
957 if ((ntohl(addr.s_addr) & ifdev->if_netmask) ==
958 ifdev->if_netnum) {
960 * Return the correct IP address.
962 (void) memcpy(ipp, &addr, sizeof (ipaddr_t));
965 * Return the interface's ipaddr
967 (void) memcpy(ipaddr, &ifdev->ipaddr,
968 sizeof (ipaddr_t));
970 return (0);
975 if (dflag)
976 debug("got host entry but no IP address on this net");
977 return (1);
980 static int
981 strioctl(int fd, int cmd, int timout, int len, char *dp)
983 struct strioctl si;
985 si.ic_cmd = cmd;
986 si.ic_timout = timout;
987 si.ic_len = len;
988 si.ic_dp = dp;
989 return (ioctl(fd, I_STR, &si));
992 static void
993 usage(void)
995 error("Usage: %s [ -ad ] device unit", cmdname);
998 static void
999 syserr(const char *s)
1001 char buf[256];
1002 int status = 1;
1004 (void) snprintf(buf, sizeof (buf), "%s: %s", s, strerror(errno));
1005 (void) fprintf(stderr, "%s: %s\n", cmdname, buf);
1006 syslog(LOG_ERR, "%s", buf);
1007 thr_exit(&status);
1010 static void
1011 error(const char *fmt, ...)
1013 char buf[256];
1014 va_list ap;
1015 int status = 1;
1017 va_start(ap, fmt);
1018 (void) vsprintf(buf, fmt, ap);
1019 va_end(ap);
1020 (void) fprintf(stderr, "%s: %s\n", cmdname, buf);
1021 syslog(LOG_ERR, buf);
1022 thr_exit(&status);
1025 /*PRINTFLIKE1*/
1026 static void
1027 debug(char *fmt, ...)
1029 va_list ap;
1031 (void) mutex_lock(&debug_mutex);
1032 va_start(ap, fmt);
1033 (void) fprintf(stderr, "%s:[%u] ", cmdname, thr_self());
1034 (void) vfprintf(stderr, fmt, ap);
1035 (void) fprintf(stderr, "\n");
1036 va_end(ap);
1037 (void) mutex_unlock(&debug_mutex);