8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.sbin / in.rarpd.c
blob81039c3e868f5e2a53b32033473e8dcceda1660b
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 #define _REENTRANT
40 #include <thread.h>
41 #include <synch.h>
42 #include <stdlib.h>
43 #include <unistd.h>
44 #include <sys/resource.h>
45 #include <stdio.h>
46 #include <stdio_ext.h>
47 #include <stdarg.h>
48 #include <string.h>
49 #include <fcntl.h>
50 #include <sys/types.h>
51 #include <dirent.h>
52 #include <syslog.h>
53 #include <netdb.h>
54 #include <errno.h>
55 #include <sys/socket.h>
56 #include <sys/sockio.h>
57 #include <net/if.h>
58 #include <netinet/if_ether.h>
59 #include <netinet/in.h>
60 #include <arpa/inet.h>
61 #include <stropts.h>
62 #include <libinetutil.h>
63 #include <libdlpi.h>
64 #include <net/if_types.h>
65 #include <net/if_dl.h>
67 #define BOOTDIR "/tftpboot" /* boot files directory */
68 #define DEVIP "/dev/ip" /* path to ip driver */
69 #define DEVARP "/dev/arp" /* path to arp driver */
71 #define BUFSIZE 2048 /* max receive frame length */
72 #define MAXPATHL 128 /* max path length */
73 #define MAXHOSTL 128 /* max host name length */
74 #define MAXIFS 256
77 * Logical network devices
79 struct ifdev {
80 char ldevice[IFNAMSIZ];
81 int lunit;
82 ipaddr_t ipaddr; /* network order */
83 ipaddr_t if_netmask; /* host order */
84 ipaddr_t if_ipaddr; /* host order */
85 ipaddr_t if_netnum; /* host order, with subnet */
86 struct ifdev *next;
90 * Physical network device
92 struct rarpdev {
93 char device[DLPI_LINKNAME_MAX];
94 uint_t unit;
95 dlpi_handle_t dh_rarp;
96 uchar_t physaddr[DLPI_PHYSADDR_MAX];
97 /* mac address of interface */
98 uint_t physaddrlen; /* mac address length */
99 int ifrarplen; /* size of rarp data packet */
100 struct ifdev *ifdev; /* private interface info */
101 struct rarpdev *next; /* list of managed devices */
104 struct rarpreply {
105 struct rarpdev *rdev; /* which device reply for */
106 struct timeval tv; /* send RARP reply by when */
107 uchar_t *lldest; /* target mac to send reply */
108 uchar_t *arprep; /* [R]ARP response */
109 struct rarpreply *next;
112 static struct rarpreply *delay_list;
113 static sema_t delay_sema;
114 static mutex_t delay_mutex;
115 static mutex_t debug_mutex;
117 static struct rarpdev *rarpdev_head;
120 * Globals initialized before multi-threading
122 static char *cmdname; /* command name from argv[0] */
123 static int dflag = 0; /* enable diagnostics */
124 static int aflag = 0; /* start rarpd on all interfaces */
126 static void getintf(void);
127 static struct rarpdev *find_device(ifspec_t *);
128 static void init_rarpdev(struct rarpdev *);
129 static void do_rarp(void *);
130 static void rarp_request(struct rarpdev *, struct arphdr *,
131 uchar_t *);
132 static void add_arp(struct rarpdev *, uchar_t *, uchar_t *);
133 static void arp_request(struct rarpdev *, struct arphdr *, uchar_t *);
134 static void do_delay_write(void *);
135 static void delay_write(struct rarpdev *, struct rarpreply *);
136 static int mightboot(ipaddr_t);
137 static void get_ifdata(char *, int, ipaddr_t *, ipaddr_t *);
138 static int get_ipaddr(struct rarpdev *, uchar_t *, uchar_t *, ipaddr_t *);
139 static int strioctl(int, int, int, int, char *);
140 static void usage();
141 static void syserr(const char *);
142 /*PRINTFLIKE1*/
143 static void error(const char *, ...);
144 static void debug(char *, ...);
146 extern int optind;
147 extern char *optarg;
150 main(int argc, char *argv[])
152 int c;
153 struct rlimit rl;
154 struct rarpdev *rdev;
155 int i;
157 cmdname = argv[0];
159 while ((c = getopt(argc, argv, "ad")) != -1) {
160 switch (c) {
161 case 'a':
162 aflag = 1;
163 break;
165 case 'd':
166 dflag = 1;
167 break;
169 default:
170 usage();
174 if ((!aflag && (argc - optind) != 2) ||
175 (aflag && (argc - optind) != 0)) {
176 usage();
177 /* NOTREACHED */
180 if (!dflag) {
182 * Background
184 switch (fork()) {
185 case -1: /* error */
186 syserr("fork");
187 /*NOTREACHED*/
189 case 0: /* child */
190 break;
192 default: /* parent */
193 return (0);
195 for (i = 0; i < 3; i++) {
196 (void) close(i);
198 (void) open("/", O_RDONLY, 0);
199 (void) dup2(0, 1);
200 (void) dup2(0, 2);
202 * Detach terminal
204 if (setsid() < 0)
205 syserr("setsid");
208 rl.rlim_cur = RLIM_INFINITY;
209 rl.rlim_max = RLIM_INFINITY;
210 if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
211 syserr("setrlimit");
212 (void) enable_extended_FILE_stdio(-1, -1);
214 (void) openlog(cmdname, LOG_PID, LOG_DAEMON);
216 if (aflag) {
218 * Get each interface name and load rarpdev list.
220 getintf();
221 } else {
222 ifspec_t ifsp;
223 struct ifdev *ifdev;
224 char buf[IFNAMSIZ + 1];
227 * Load specified device as only element of the list.
229 rarpdev_head = (struct rarpdev *)calloc(1,
230 sizeof (struct rarpdev));
231 if (rarpdev_head == NULL) {
232 error("out of memory");
234 (void) strncpy(buf, argv[optind], IFNAMSIZ);
235 (void) strncat(buf, argv[optind + 1], IFNAMSIZ - strlen(buf));
237 if ((ifdev = calloc(1, sizeof (struct ifdev))) == NULL) {
238 error("out of memory");
241 if (!ifparse_ifspec(buf, &ifsp))
242 error("invalid interface specification");
244 if (ifsp.ifsp_lunvalid) {
245 (void) snprintf(ifdev->ldevice,
246 sizeof (ifdev->ldevice), "%s%d:",
247 ifsp.ifsp_devnm, ifsp.ifsp_ppa);
248 ifdev->lunit = ifsp.ifsp_lun;
249 } else {
250 ifdev->lunit = -1; /* no logical unit */
252 (void) strlcpy(rarpdev_head->device, ifsp.ifsp_devnm,
253 sizeof (rarpdev_head->device));
254 rarpdev_head->unit = ifsp.ifsp_ppa;
256 ifdev->next = rarpdev_head->ifdev;
257 rarpdev_head->ifdev = ifdev;
261 * Initialize each rarpdev.
263 for (rdev = rarpdev_head; rdev != NULL; rdev = rdev->next) {
264 init_rarpdev(rdev);
267 (void) sema_init(&delay_sema, 0, USYNC_THREAD, NULL);
268 (void) mutex_init(&delay_mutex, USYNC_THREAD, NULL);
269 (void) mutex_init(&debug_mutex, USYNC_THREAD, NULL);
272 * Start delayed processing thread.
274 (void) thr_create(NULL, NULL, (void *(*)(void *))do_delay_write, NULL,
275 THR_NEW_LWP, NULL);
278 * Start RARP processing for each device.
280 for (rdev = rarpdev_head; rdev != NULL; rdev = rdev->next) {
281 if (rdev->dh_rarp != NULL) {
282 (void) thr_create(NULL, NULL,
283 (void *(*)(void *))do_rarp, (void *)rdev,
284 THR_NEW_LWP, NULL);
289 * Exit main() thread
291 thr_exit(NULL);
293 return (0);
296 static void
297 getintf(void)
299 int fd;
300 int numifs;
301 unsigned bufsize;
302 struct ifreq *reqbuf;
303 struct ifconf ifconf;
304 struct ifreq *ifr;
305 struct rarpdev *rdev;
306 struct ifdev *ifdev;
309 * Open the IP provider.
311 if ((fd = open(DEVIP, 0)) < 0)
312 syserr(DEVIP);
315 * Ask IP for the list of configured interfaces.
317 if (ioctl(fd, SIOCGIFNUM, (char *)&numifs) < 0) {
318 numifs = MAXIFS;
320 bufsize = numifs * sizeof (struct ifreq);
321 reqbuf = (struct ifreq *)malloc(bufsize);
322 if (reqbuf == NULL) {
323 error("out of memory");
326 ifconf.ifc_len = bufsize;
327 ifconf.ifc_buf = (caddr_t)reqbuf;
328 if (ioctl(fd, SIOCGIFCONF, (char *)&ifconf) < 0)
329 syserr("SIOCGIFCONF");
332 * Initialize a rarpdev for each interface.
334 for (ifr = ifconf.ifc_req; ifconf.ifc_len > 0;
335 ifr++, ifconf.ifc_len -= sizeof (struct ifreq)) {
336 ifspec_t ifsp;
338 if (ioctl(fd, SIOCGIFFLAGS, (char *)ifr) < 0) {
339 syserr("ioctl SIOCGIFFLAGS");
340 exit(1);
342 if ((ifr->ifr_flags & IFF_LOOPBACK) ||
343 !(ifr->ifr_flags & IFF_UP) ||
344 !(ifr->ifr_flags & IFF_BROADCAST) ||
345 (ifr->ifr_flags & IFF_NOARP) ||
346 (ifr->ifr_flags & IFF_POINTOPOINT))
347 continue;
349 if (!ifparse_ifspec(ifr->ifr_name, &ifsp))
350 error("ifparse_ifspec failed");
353 * Look for an existing device for logical interfaces.
355 if ((rdev = find_device(&ifsp)) == NULL) {
356 rdev = calloc(1, sizeof (struct rarpdev));
357 if (rdev == NULL)
358 error("out of memory");
360 (void) strlcpy(rdev->device, ifsp.ifsp_devnm,
361 sizeof (rdev->device));
362 rdev->unit = ifsp.ifsp_ppa;
364 rdev->next = rarpdev_head;
365 rarpdev_head = rdev;
368 if ((ifdev = calloc(1, sizeof (struct ifdev))) == NULL)
369 error("out of memory");
371 if (ifsp.ifsp_lunvalid) {
372 (void) snprintf(ifdev->ldevice,
373 sizeof (ifdev->ldevice), "%s%d:",
374 ifsp.ifsp_devnm, ifsp.ifsp_ppa);
375 ifdev->lunit = ifsp.ifsp_lun;
376 } else
377 ifdev->lunit = -1; /* no logical unit */
379 ifdev->next = rdev->ifdev;
380 rdev->ifdev = ifdev;
382 (void) free((char *)reqbuf);
385 static struct rarpdev *
386 find_device(ifspec_t *specp)
388 struct rarpdev *rdev;
390 for (rdev = rarpdev_head; rdev != NULL; rdev = rdev->next) {
391 if (specp->ifsp_ppa == rdev->unit &&
392 strcmp(specp->ifsp_devnm, rdev->device) == 0)
393 return (rdev);
395 return (NULL);
398 static void
399 init_rarpdev(struct rarpdev *rdev)
401 char *dev;
402 int unit;
403 struct ifdev *ifdev;
404 int retval;
405 char *str = NULL;
406 uint_t physaddrlen = DLPI_PHYSADDR_MAX;
407 char linkname[DLPI_LINKNAME_MAX];
408 dlpi_handle_t dh;
410 (void) snprintf(linkname, DLPI_LINKNAME_MAX, "%s%d", rdev->device,
411 rdev->unit);
413 * Open datalink provider and get our mac address.
415 if ((retval = dlpi_open(linkname, &dh, 0)) != DLPI_SUCCESS) {
416 error("cannot open link %s: %s", linkname,
417 dlpi_strerror(retval));
420 if ((retval = dlpi_bind(dh, ETHERTYPE_REVARP, NULL)) != DLPI_SUCCESS) {
421 dlpi_close(dh);
422 error("dlpi_bind failed: %s", dlpi_strerror(retval));
426 * Save our mac address.
428 if ((retval = dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR, rdev->physaddr,
429 &physaddrlen)) != DLPI_SUCCESS) {
430 dlpi_close(dh);
431 error("dlpi_get_physaddr failed: %s", dlpi_strerror(retval));
434 rdev->physaddrlen = physaddrlen;
435 rdev->ifrarplen = sizeof (struct arphdr) + (2 * sizeof (ipaddr_t)) +
436 (2 * physaddrlen);
438 if (dflag) {
439 str = _link_ntoa(rdev->physaddr, str,
440 rdev->physaddrlen, IFT_OTHER);
441 if (str != NULL) {
442 debug("device %s physical address %s", linkname, str);
443 free(str);
448 * Assign dlpi handle to rdev.
450 rdev->dh_rarp = dh;
453 * Get the IP address and netmask from directory service for
454 * each logical interface.
456 for (ifdev = rdev->ifdev; ifdev != NULL; ifdev = ifdev->next) {
458 * If lunit == -1 then this is the primary interface name.
460 if (ifdev->lunit == -1) {
461 dev = rdev->device;
462 unit = rdev->unit;
463 } else {
464 dev = ifdev->ldevice;
465 unit = ifdev->lunit;
467 get_ifdata(dev, unit, &ifdev->if_ipaddr, &ifdev->if_netmask);
470 * Use IP address of the interface.
472 ifdev->if_netnum = ifdev->if_ipaddr & ifdev->if_netmask;
473 ifdev->ipaddr = (ipaddr_t)htonl(ifdev->if_ipaddr);
477 static void
478 do_rarp(void *buf)
480 struct rarpdev *rdev = buf;
481 char *cause;
482 struct arphdr *ans;
483 uchar_t *shost;
484 uint_t saddrlen;
485 size_t anslen = rdev->ifrarplen;
486 char *str = NULL;
487 int retval;
489 if (((shost = malloc(rdev->physaddrlen)) == NULL) ||
490 ((ans = malloc(rdev->ifrarplen)) == NULL))
491 syserr("malloc");
493 if (dflag) {
494 str = _link_ntoa(rdev->physaddr, str, rdev->physaddrlen,
495 IFT_OTHER);
496 if (str != NULL) {
497 debug("starting rarp service on device %s%d physical"
498 " address %s", rdev->device, rdev->unit, str);
499 free(str);
504 * Read RARP packets and respond to them.
506 for (;;) {
507 saddrlen = DLPI_PHYSADDR_MAX;
508 retval = dlpi_recv(rdev->dh_rarp, shost,
509 &saddrlen, ans, &anslen, -1, NULL);
510 if (retval == DLPI_ETIMEDOUT) {
511 continue;
512 } else if (retval != DLPI_SUCCESS) {
513 error("error in dlpi_recv %s: %s", rdev->dh_rarp,
514 dlpi_strerror(retval));
517 cause = NULL;
519 if (anslen < rdev->ifrarplen)
520 cause = "short packet";
521 else if (ans->ar_hrd != htons(ARPHRD_ETHER))
522 cause = "hardware type not Ethernet";
523 else if (ans->ar_pro != htons(ETHERTYPE_IP))
524 cause = "protocol type not IP";
525 else if (ans->ar_hln != rdev->physaddrlen)
526 cause = "unexpected hardware address length";
527 else if (ans->ar_pln != sizeof (ipaddr_t))
528 cause = "unexpected protocol address length";
529 if (cause != NULL) {
530 if (dflag)
531 debug("RARP packet received but "
532 "discarded: %s", cause);
533 continue;
537 * Handle the request.
539 switch (ntohs(ans->ar_op)) {
540 case REVARP_REQUEST:
541 rarp_request(rdev, ans, shost);
542 break;
544 case ARPOP_REQUEST:
545 arp_request(rdev, ans, shost);
546 break;
548 case REVARP_REPLY:
549 if (dflag)
550 debug("REVARP_REPLY ignored");
551 break;
553 case ARPOP_REPLY:
554 if (dflag)
555 debug("ARPOP_REPLY ignored");
556 break;
558 default:
559 if (dflag)
560 debug("unknown opcode 0x%x", ans->ar_op);
561 break;
567 * Reverse address determination and allocation code.
569 static void
570 rarp_request(struct rarpdev *rdev, struct arphdr *rp, uchar_t *shost)
572 ipaddr_t tpa, spa;
573 struct rarpreply *rrp;
574 uchar_t *shap, *thap, *spap, *tpap;
575 char *str = NULL;
576 int retval;
578 shap = (uchar_t *)rp + sizeof (struct arphdr);
579 spap = shap + rp->ar_hln;
580 thap = spap + rp->ar_pln;
581 tpap = thap + rp->ar_hln;
583 if (dflag) {
584 str = _link_ntoa(thap, str, rdev->physaddrlen, IFT_OTHER);
585 if (str != NULL) {
586 debug("RARP_REQUEST for %s", str);
587 free(str);
592 * Third party lookups are rare and wonderful.
594 if ((memcmp(shap, thap, rdev->physaddrlen) != 0) ||
595 (memcmp(shap, shost, rdev->physaddrlen) != 0)) {
596 if (dflag)
597 debug("weird (3rd party lookup)");
601 * Fill in given parts of reply packet.
603 (void) memcpy(shap, rdev->physaddr, rdev->physaddrlen);
606 * If a good address is stored in our lookup tables, return it
607 * immediately or after a delay. Store it in our kernel's ARP cache.
609 if (get_ipaddr(rdev, thap, tpap, &spa))
610 return;
611 (void) memcpy(spap, &spa, sizeof (spa));
613 add_arp(rdev, tpap, thap);
615 rp->ar_op = htons(REVARP_REPLY);
617 if (dflag) {
618 struct in_addr addr;
620 (void) memcpy(&addr, tpap, sizeof (ipaddr_t));
621 debug("good lookup, maps to %s", inet_ntoa(addr));
624 rrp = calloc(1, sizeof (struct rarpreply) + rdev->physaddrlen +
625 rdev->ifrarplen);
626 if (rrp == NULL)
627 error("out of memory");
628 rrp->lldest = (uchar_t *)rrp + sizeof (struct rarpreply);
629 rrp->arprep = rrp->lldest + rdev->physaddrlen;
632 * Create rarpreply structure.
634 (void) gettimeofday(&rrp->tv, NULL);
635 rrp->tv.tv_sec += 3; /* delay */
636 rrp->rdev = rdev;
637 (void) memcpy(rrp->lldest, shost, rdev->physaddrlen);
638 (void) memcpy(rrp->arprep, rp, rdev->ifrarplen);
641 * If this is diskless and we're not its bootserver, let the
642 * bootserver reply first by delaying a while.
644 (void) memcpy(&tpa, tpap, sizeof (ipaddr_t));
645 if (mightboot(ntohl(tpa))) {
646 retval = dlpi_send(rdev->dh_rarp, rrp->lldest,
647 rdev->physaddrlen, rrp->arprep, rdev->ifrarplen, NULL);
648 if (retval != DLPI_SUCCESS) {
649 error("dlpi_send failed: %s", dlpi_strerror(retval));
650 } else if (dflag) {
651 debug("immediate reply sent");
653 (void) free(rrp);
654 } else {
655 delay_write(rdev, rrp);
660 * Download an ARP entry into our kernel.
662 static void
663 add_arp(struct rarpdev *rdev, uchar_t *ip, uchar_t *laddr)
665 struct xarpreq ar;
666 struct sockaddr_in *sin;
667 int fd;
670 * Common part of query or set.
672 (void) memset(&ar, 0, sizeof (ar));
673 ar.xarp_pa.ss_family = AF_INET;
674 sin = (struct sockaddr_in *)&ar.xarp_pa;
675 (void) memcpy(&sin->sin_addr, ip, sizeof (ipaddr_t));
678 * Open the IP provider.
680 if ((fd = open(DEVARP, 0)) < 0)
681 syserr(DEVARP);
684 * Set the entry.
686 (void) memcpy(LLADDR(&ar.xarp_ha), laddr, rdev->physaddrlen);
687 ar.xarp_ha.sdl_alen = rdev->physaddrlen;
688 ar.xarp_ha.sdl_family = AF_LINK;
689 (void) strioctl(fd, SIOCDXARP, -1, sizeof (struct xarpreq),
690 (char *)&ar);
691 if (strioctl(fd, SIOCSXARP, -1, sizeof (struct xarpreq),
692 (char *)&ar) < 0)
693 syserr("SIOCSXARP");
695 (void) close(fd);
699 * The RARP spec says we must be able to process ARP requests,
700 * even through the packet type is RARP. Let's hope this feature
701 * is not heavily used.
703 static void
704 arp_request(struct rarpdev *rdev, struct arphdr *rp, uchar_t *shost)
706 struct rarpreply *rrp;
707 struct ifdev *ifdev;
708 uchar_t *shap, *thap, *spap, *tpap;
709 int retval;
711 shap = (uchar_t *)rp + sizeof (struct arphdr);
712 spap = shap + rp->ar_hln;
713 thap = spap + rp->ar_pln;
714 tpap = thap + rp->ar_hln;
716 if (dflag)
717 debug("ARPOP_REQUEST");
719 for (ifdev = rdev->ifdev; ifdev != NULL; ifdev = ifdev->next) {
720 if (memcmp(&ifdev->ipaddr, tpap, sizeof (ipaddr_t)) == 0)
721 break;
723 if (ifdev == NULL)
724 return;
726 rp->ar_op = ARPOP_REPLY;
727 (void) memcpy(shap, rdev->physaddr, rdev->physaddrlen);
728 (void) memcpy(spap, &ifdev->ipaddr, sizeof (ipaddr_t));
729 (void) memcpy(thap, rdev->physaddr, rdev->physaddrlen);
731 add_arp(rdev, tpap, thap);
734 * Create rarp reply structure.
736 rrp = calloc(1, sizeof (struct rarpreply) + rdev->physaddrlen +
737 rdev->ifrarplen);
738 if (rrp == NULL)
739 error("out of memory");
740 rrp->lldest = (uchar_t *)rrp + sizeof (struct rarpreply);
741 rrp->arprep = rrp->lldest + rdev->physaddrlen;
742 rrp->rdev = rdev;
744 (void) memcpy(rrp->lldest, shost, rdev->physaddrlen);
745 (void) memcpy(rrp->arprep, rp, rdev->ifrarplen);
747 retval = dlpi_send(rdev->dh_rarp, rrp->lldest, rdev->physaddrlen,
748 rrp->arprep, rdev->ifrarplen, NULL);
749 free(rrp);
750 if (retval != DLPI_SUCCESS)
751 error("dlpi_send failed: %s", dlpi_strerror(retval));
754 /* ARGSUSED */
755 static void
756 do_delay_write(void *buf)
758 struct timeval tv;
759 struct rarpreply *rrp;
760 struct rarpdev *rdev;
761 int err;
763 for (;;) {
764 if ((err = sema_wait(&delay_sema)) != 0) {
765 if (err == EINTR)
766 continue;
767 error("do_delay_write: sema_wait failed");
770 (void) mutex_lock(&delay_mutex);
771 rrp = delay_list;
772 rdev = rrp->rdev;
773 delay_list = delay_list->next;
774 (void) mutex_unlock(&delay_mutex);
776 (void) gettimeofday(&tv, NULL);
777 if (tv.tv_sec < rrp->tv.tv_sec)
778 (void) sleep(rrp->tv.tv_sec - tv.tv_sec);
780 err = dlpi_send(rdev->dh_rarp, rrp->lldest, rdev->physaddrlen,
781 rrp->arprep, rdev->ifrarplen, NULL);
782 if (err != DLPI_SUCCESS)
783 error("dlpi_send failed: %s", dlpi_strerror(err));
785 (void) free(rrp);
789 /* ARGSUSED */
790 static void
791 delay_write(struct rarpdev *rdev, struct rarpreply *rrp)
793 struct rarpreply *trp;
795 (void) mutex_lock(&delay_mutex);
796 if (delay_list == NULL) {
797 delay_list = rrp;
798 } else {
799 trp = delay_list;
800 while (trp->next != NULL)
801 trp = trp->next;
802 trp->next = rrp;
804 (void) mutex_unlock(&delay_mutex);
806 (void) sema_post(&delay_sema);
810 * See if we have a TFTP boot file for this guy. Filenames in TFTP
811 * boot requests are of the form <ipaddr> for Sun-3's and of the form
812 * <ipaddr>.<arch> for all other architectures. Since we don't know
813 * the client's architecture, either format will do.
815 static int
816 mightboot(ipaddr_t ipa)
818 char path[MAXPATHL];
819 DIR *dirp;
820 struct dirent *dp;
822 (void) snprintf(path, sizeof (path), "%s/%08X", BOOTDIR, ipa);
825 * Try a quick access() first.
827 if (access(path, 0) == 0)
828 return (1);
831 * Not there, do it the slow way by
832 * reading through the directory.
834 (void) sprintf(path, "%08X", ipa);
836 if (!(dirp = opendir(BOOTDIR)))
837 return (0);
839 while ((dp = readdir(dirp)) != NULL) {
840 if (strncmp(dp->d_name, path, 8) != 0)
841 continue;
842 if ((strlen(dp->d_name) != 8) && (dp->d_name[8] != '.'))
843 continue;
844 break;
847 (void) closedir(dirp);
849 return ((dp != NULL) ? 1 : 0);
853 * Get our IP address and local netmask.
855 static void
856 get_ifdata(char *dev, int unit, ipaddr_t *ipp, ipaddr_t *maskp)
858 int fd;
859 struct ifreq ifr;
860 struct sockaddr_in *sin;
862 /* LINTED pointer */
863 sin = (struct sockaddr_in *)&ifr.ifr_addr;
866 * Open the IP provider.
868 if ((fd = open(DEVIP, 0)) < 0)
869 syserr(DEVIP);
872 * Ask IP for our IP address.
874 (void) snprintf(ifr.ifr_name, sizeof (ifr.ifr_name), "%s%d", dev, unit);
875 if (strioctl(fd, SIOCGIFADDR, -1, sizeof (struct ifreq),
876 (char *)&ifr) < 0)
877 syserr("SIOCGIFADDR");
878 *ipp = (ipaddr_t)ntohl(sin->sin_addr.s_addr);
880 if (dflag)
881 debug("device %s%d address %s", dev, unit,
882 inet_ntoa(sin->sin_addr));
885 * Ask IP for our netmask.
887 if (strioctl(fd, SIOCGIFNETMASK, -1, sizeof (struct ifreq),
888 (char *)&ifr) < 0)
889 syserr("SIOCGIFNETMASK");
890 *maskp = (ipaddr_t)ntohl(sin->sin_addr.s_addr);
892 if (dflag)
893 debug("device %s%d subnet mask %s", dev, unit,
894 inet_ntoa(sin->sin_addr));
897 * Thankyou ip.
899 (void) close(fd);
903 * Translate mac address to IP address.
904 * Return 0 on success, nonzero on failure.
906 static int
907 get_ipaddr(struct rarpdev *rdev, uchar_t *laddr, uchar_t *ipp, ipaddr_t *ipaddr)
909 char host[MAXHOSTL];
910 char hbuffer[BUFSIZE];
911 struct hostent *hp, res;
912 int herror;
913 struct in_addr addr;
914 char **p;
915 struct ifdev *ifdev;
917 if (rdev->physaddrlen != ETHERADDRL) {
918 if (dflag)
919 debug("%s %s", " cannot map non 6 byte hardware ",
920 "address to IP address");
921 return (1);
925 * Translate mac address to hostname and IP address.
927 if (ether_ntohost(host, (struct ether_addr *)laddr) != 0 ||
928 !(hp = gethostbyname_r(host, &res, hbuffer, sizeof (hbuffer),
929 &herror)) ||
930 hp->h_addrtype != AF_INET || hp->h_length != sizeof (ipaddr_t)) {
931 if (dflag)
932 debug("could not map hardware address to IP address");
933 return (1);
937 * Find the IP address on the right net.
939 for (p = hp->h_addr_list; *p; p++) {
940 (void) memcpy(&addr, *p, sizeof (ipaddr_t));
941 for (ifdev = rdev->ifdev; ifdev != NULL; ifdev = ifdev->next) {
942 if (dflag) {
943 struct in_addr daddr;
944 ipaddr_t netnum;
946 netnum = htonl(ifdev->if_netnum);
947 (void) memcpy(&daddr, &netnum,
948 sizeof (ipaddr_t));
949 if (ifdev->lunit == -1)
950 debug("trying physical netnum %s"
951 " mask %x", inet_ntoa(daddr),
952 ifdev->if_netmask);
953 else
954 debug("trying logical %d netnum %s"
955 " mask %x", ifdev->lunit,
956 inet_ntoa(daddr),
957 ifdev->if_netmask);
959 if ((ntohl(addr.s_addr) & ifdev->if_netmask) ==
960 ifdev->if_netnum) {
962 * Return the correct IP address.
964 (void) memcpy(ipp, &addr, sizeof (ipaddr_t));
967 * Return the interface's ipaddr
969 (void) memcpy(ipaddr, &ifdev->ipaddr,
970 sizeof (ipaddr_t));
972 return (0);
977 if (dflag)
978 debug("got host entry but no IP address on this net");
979 return (1);
982 static int
983 strioctl(int fd, int cmd, int timout, int len, char *dp)
985 struct strioctl si;
987 si.ic_cmd = cmd;
988 si.ic_timout = timout;
989 si.ic_len = len;
990 si.ic_dp = dp;
991 return (ioctl(fd, I_STR, &si));
994 static void
995 usage(void)
997 error("Usage: %s [ -ad ] device unit", cmdname);
1000 static void
1001 syserr(const char *s)
1003 char buf[256];
1004 int status = 1;
1006 (void) snprintf(buf, sizeof (buf), "%s: %s", s, strerror(errno));
1007 (void) fprintf(stderr, "%s: %s\n", cmdname, buf);
1008 syslog(LOG_ERR, "%s", buf);
1009 thr_exit(&status);
1012 static void
1013 error(const char *fmt, ...)
1015 char buf[256];
1016 va_list ap;
1017 int status = 1;
1019 va_start(ap, fmt);
1020 (void) vsprintf(buf, fmt, ap);
1021 va_end(ap);
1022 (void) fprintf(stderr, "%s: %s\n", cmdname, buf);
1023 syslog(LOG_ERR, buf);
1024 thr_exit(&status);
1027 /*PRINTFLIKE1*/
1028 static void
1029 debug(char *fmt, ...)
1031 va_list ap;
1033 (void) mutex_lock(&debug_mutex);
1034 va_start(ap, fmt);
1035 (void) fprintf(stderr, "%s:[%u] ", cmdname, thr_self());
1036 (void) vfprintf(stderr, fmt, ap);
1037 (void) fprintf(stderr, "\n");
1038 va_end(ap);
1039 (void) mutex_unlock(&debug_mutex);