comparison usr/src/cmd/cmd-inet/usr.sbin/in.rarpd.c @ 0:c9caec207d52 b86

Initial porting based on b86
author Koji Uno <koji.uno@sun.com>
date Tue, 02 Jun 2009 18:56:50 +0900
parents
children 1a15d5aaf794
comparison
equal deleted inserted replaced
-1:000000000000 0:c9caec207d52
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 2007 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 "@(#)in.rarpd.c 1.39 07/06/12 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 <fcntl.h>
52 #include <sys/types.h>
53 #include <dirent.h>
54 #include <syslog.h>
55 #include <netdb.h>
56 #include <errno.h>
57 #include <sys/socket.h>
58 #include <sys/sockio.h>
59 #include <net/if.h>
60 #include <netinet/if_ether.h>
61 #include <netinet/in.h>
62 #include <arpa/inet.h>
63 #include <stropts.h>
64 #include <libinetutil.h>
65 #include <libdlpi.h>
66 #include <net/if_types.h>
67 #include <net/if_dl.h>
68
69 #define BOOTDIR "/tftpboot" /* boot files directory */
70 #define DEVIP "/dev/ip" /* path to ip driver */
71 #define DEVARP "/dev/arp" /* path to arp driver */
72
73 #define BUFSIZE 2048 /* max receive frame length */
74 #define MAXPATHL 128 /* max path length */
75 #define MAXHOSTL 128 /* max host name length */
76 #define MAXIFS 256
77
78 /*
79 * Logical network devices
80 */
81 struct ifdev {
82 char ldevice[IFNAMSIZ];
83 int lunit;
84 ipaddr_t ipaddr; /* network order */
85 ipaddr_t if_netmask; /* host order */
86 ipaddr_t if_ipaddr; /* host order */
87 ipaddr_t if_netnum; /* host order, with subnet */
88 struct ifdev *next;
89 };
90
91 /*
92 * Physical network device
93 */
94 struct rarpdev {
95 char device[DLPI_LINKNAME_MAX];
96 uint_t unit;
97 dlpi_handle_t dh_rarp;
98 uchar_t physaddr[DLPI_PHYSADDR_MAX];
99 /* mac address of interface */
100 uint_t physaddrlen; /* mac address length */
101 int ifrarplen; /* size of rarp data packet */
102 struct ifdev *ifdev; /* private interface info */
103 struct rarpdev *next; /* list of managed devices */
104 };
105
106 struct rarpreply {
107 struct rarpdev *rdev; /* which device reply for */
108 struct timeval tv; /* send RARP reply by when */
109 uchar_t *lldest; /* target mac to send reply */
110 uchar_t *arprep; /* [R]ARP response */
111 struct rarpreply *next;
112 };
113
114 static struct rarpreply *delay_list;
115 static sema_t delay_sema;
116 static mutex_t delay_mutex;
117 static mutex_t debug_mutex;
118
119 static struct rarpdev *rarpdev_head;
120
121 /*
122 * Globals initialized before multi-threading
123 */
124 static char *cmdname; /* command name from argv[0] */
125 static int dflag = 0; /* enable diagnostics */
126 static int aflag = 0; /* start rarpd on all interfaces */
127
128 static void getintf(void);
129 static struct rarpdev *find_device(ifspec_t *);
130 static void init_rarpdev(struct rarpdev *);
131 static void do_rarp(void *);
132 static void rarp_request(struct rarpdev *, struct arphdr *,
133 uchar_t *);
134 static void add_arp(struct rarpdev *, uchar_t *, uchar_t *);
135 static void arp_request(struct rarpdev *, struct arphdr *, uchar_t *);
136 static void do_delay_write(void *);
137 static void delay_write(struct rarpdev *, struct rarpreply *);
138 static int mightboot(ipaddr_t);
139 static void get_ifdata(char *, int, ipaddr_t *, ipaddr_t *);
140 static int get_ipaddr(struct rarpdev *, uchar_t *, uchar_t *, ipaddr_t *);
141 static int strioctl(int, int, int, int, char *);
142 static void usage();
143 static void syserr(const char *);
144 /*PRINTFLIKE1*/
145 static void error(const char *, ...);
146 static void debug(char *, ...);
147
148 extern int optind;
149 extern char *optarg;
150
151 int
152 main(int argc, char *argv[])
153 {
154 int c;
155 struct rlimit rl;
156 struct rarpdev *rdev;
157 int i;
158
159 cmdname = argv[0];
160
161 while ((c = getopt(argc, argv, "ad")) != -1) {
162 switch (c) {
163 case 'a':
164 aflag = 1;
165 break;
166
167 case 'd':
168 dflag = 1;
169 break;
170
171 default:
172 usage();
173 }
174 }
175
176 if ((!aflag && (argc - optind) != 2) ||
177 (aflag && (argc - optind) != 0)) {
178 usage();
179 /* NOTREACHED */
180 }
181
182 if (!dflag) {
183 /*
184 * Background
185 */
186 switch (fork()) {
187 case -1: /* error */
188 syserr("fork");
189 /*NOTREACHED*/
190
191 case 0: /* child */
192 break;
193
194 default: /* parent */
195 return (0);
196 }
197 for (i = 0; i < 3; i++) {
198 (void) close(i);
199 }
200 (void) open("/", O_RDONLY, 0);
201 (void) dup2(0, 1);
202 (void) dup2(0, 2);
203 /*
204 * Detach terminal
205 */
206 if (setsid() < 0)
207 syserr("setsid");
208 }
209
210 rl.rlim_cur = RLIM_INFINITY;
211 rl.rlim_max = RLIM_INFINITY;
212 if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
213 syserr("setrlimit");
214 (void) enable_extended_FILE_stdio(-1, -1);
215
216 (void) openlog(cmdname, LOG_PID, LOG_DAEMON);
217
218 if (aflag) {
219 /*
220 * Get each interface name and load rarpdev list.
221 */
222 getintf();
223 } else {
224 ifspec_t ifsp;
225 struct ifdev *ifdev;
226 char buf[IFNAMSIZ + 1];
227
228 /*
229 * Load specified device as only element of the list.
230 */
231 rarpdev_head = (struct rarpdev *)calloc(1,
232 sizeof (struct rarpdev));
233 if (rarpdev_head == NULL) {
234 error("out of memory");
235 }
236 (void) strncpy(buf, argv[optind], IFNAMSIZ);
237 (void) strncat(buf, argv[optind + 1], IFNAMSIZ - strlen(buf));
238
239 if ((ifdev = calloc(1, sizeof (struct ifdev))) == NULL) {
240 error("out of memory");
241 }
242
243 if (!ifparse_ifspec(buf, &ifsp) || ifsp.ifsp_modcnt != 0) {
244 error("invalid interface specification");
245 }
246
247 if (ifsp.ifsp_lunvalid) {
248 (void) snprintf(ifdev->ldevice,
249 sizeof (ifdev->ldevice), "%s%d:",
250 ifsp.ifsp_devnm, ifsp.ifsp_ppa);
251 ifdev->lunit = ifsp.ifsp_lun;
252 } else {
253 ifdev->lunit = -1; /* no logical unit */
254 }
255 (void) strlcpy(rarpdev_head->device, ifsp.ifsp_devnm,
256 sizeof (rarpdev_head->device));
257 rarpdev_head->unit = ifsp.ifsp_ppa;
258
259 ifdev->next = rarpdev_head->ifdev;
260 rarpdev_head->ifdev = ifdev;
261 }
262
263 /*
264 * Initialize each rarpdev.
265 */
266 for (rdev = rarpdev_head; rdev != NULL; rdev = rdev->next) {
267 init_rarpdev(rdev);
268 }
269
270 (void) sema_init(&delay_sema, 0, USYNC_THREAD, NULL);
271 (void) mutex_init(&delay_mutex, USYNC_THREAD, NULL);
272 (void) mutex_init(&debug_mutex, USYNC_THREAD, NULL);
273
274 /*
275 * Start delayed processing thread.
276 */
277 (void) thr_create(NULL, NULL, (void *(*)(void *))do_delay_write, NULL,
278 THR_NEW_LWP, NULL);
279
280 /*
281 * Start RARP processing for each device.
282 */
283 for (rdev = rarpdev_head; rdev != NULL; rdev = rdev->next) {
284 if (rdev->dh_rarp != NULL) {
285 (void) thr_create(NULL, NULL,
286 (void *(*)(void *))do_rarp, (void *)rdev,
287 THR_NEW_LWP, NULL);
288 }
289 }
290
291 /*
292 * Exit main() thread
293 */
294 thr_exit(NULL);
295
296 return (0);
297 }
298
299 static void
300 getintf(void)
301 {
302 int fd;
303 int numifs;
304 unsigned bufsize;
305 struct ifreq *reqbuf;
306 struct ifconf ifconf;
307 struct ifreq *ifr;
308 struct rarpdev *rdev;
309 struct ifdev *ifdev;
310
311 /*
312 * Open the IP provider.
313 */
314 if ((fd = open(DEVIP, 0)) < 0)
315 syserr(DEVIP);
316
317 /*
318 * Ask IP for the list of configured interfaces.
319 */
320 if (ioctl(fd, SIOCGIFNUM, (char *)&numifs) < 0) {
321 numifs = MAXIFS;
322 }
323 bufsize = numifs * sizeof (struct ifreq);
324 reqbuf = (struct ifreq *)malloc(bufsize);
325 if (reqbuf == NULL) {
326 error("out of memory");
327 }
328
329 ifconf.ifc_len = bufsize;
330 ifconf.ifc_buf = (caddr_t)reqbuf;
331 if (ioctl(fd, SIOCGIFCONF, (char *)&ifconf) < 0)
332 syserr("SIOCGIFCONF");
333
334 /*
335 * Initialize a rarpdev for each interface.
336 */
337 for (ifr = ifconf.ifc_req; ifconf.ifc_len > 0;
338 ifr++, ifconf.ifc_len -= sizeof (struct ifreq)) {
339 ifspec_t ifsp;
340
341 if (ioctl(fd, SIOCGIFFLAGS, (char *)ifr) < 0) {
342 syserr("ioctl SIOCGIFFLAGS");
343 exit(1);
344 }
345 if ((ifr->ifr_flags & IFF_LOOPBACK) ||
346 !(ifr->ifr_flags & IFF_UP) ||
347 !(ifr->ifr_flags & IFF_BROADCAST) ||
348 (ifr->ifr_flags & IFF_NOARP) ||
349 (ifr->ifr_flags & IFF_POINTOPOINT))
350 continue;
351
352 if (!ifparse_ifspec(ifr->ifr_name, &ifsp))
353 error("ifparse_ifspec failed");
354
355 /*
356 * Look for an existing device for logical interfaces.
357 */
358 if ((rdev = find_device(&ifsp)) == NULL) {
359 rdev = calloc(1, sizeof (struct rarpdev));
360 if (rdev == NULL)
361 error("out of memory");
362
363 (void) strlcpy(rdev->device, ifsp.ifsp_devnm,
364 sizeof (rdev->device));
365 rdev->unit = ifsp.ifsp_ppa;
366
367 rdev->next = rarpdev_head;
368 rarpdev_head = rdev;
369 }
370
371 if ((ifdev = calloc(1, sizeof (struct ifdev))) == NULL)
372 error("out of memory");
373
374 if (ifsp.ifsp_lunvalid) {
375 (void) snprintf(ifdev->ldevice,
376 sizeof (ifdev->ldevice), "%s%d:",
377 ifsp.ifsp_devnm, ifsp.ifsp_ppa);
378 ifdev->lunit = ifsp.ifsp_lun;
379 } else
380 ifdev->lunit = -1; /* no logical unit */
381
382 ifdev->next = rdev->ifdev;
383 rdev->ifdev = ifdev;
384 }
385 (void) free((char *)reqbuf);
386 }
387
388 static struct rarpdev *
389 find_device(ifspec_t *specp)
390 {
391 struct rarpdev *rdev;
392
393 for (rdev = rarpdev_head; rdev != NULL; rdev = rdev->next) {
394 if (specp->ifsp_ppa == rdev->unit &&
395 strcmp(specp->ifsp_devnm, rdev->device) == 0)
396 return (rdev);
397 }
398 return (NULL);
399 }
400
401 static void
402 init_rarpdev(struct rarpdev *rdev)
403 {
404 char *dev;
405 int unit;
406 struct ifdev *ifdev;
407 int retval;
408 char *str = NULL;
409 uint_t physaddrlen = DLPI_PHYSADDR_MAX;
410 char linkname[DLPI_LINKNAME_MAX];
411 dlpi_handle_t dh;
412
413 (void) snprintf(linkname, DLPI_LINKNAME_MAX, "%s%d", rdev->device,
414 rdev->unit);
415 /*
416 * Open datalink provider and get our mac address.
417 */
418 if ((retval = dlpi_open(linkname, &dh, 0)) != DLPI_SUCCESS) {
419 error("cannot open link %s: %s", linkname,
420 dlpi_strerror(retval));
421 }
422
423 if ((retval = dlpi_bind(dh, ETHERTYPE_REVARP, NULL)) != DLPI_SUCCESS) {
424 dlpi_close(dh);
425 error("dlpi_bind failed: %s", dlpi_strerror(retval));
426 }
427
428 /*
429 * Save our mac address.
430 */
431 if ((retval = dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR, rdev->physaddr,
432 &physaddrlen)) != DLPI_SUCCESS) {
433 dlpi_close(dh);
434 error("dlpi_get_physaddr failed: %s", dlpi_strerror(retval));
435 }
436
437 rdev->physaddrlen = physaddrlen;
438 rdev->ifrarplen = sizeof (struct arphdr) + (2 * sizeof (ipaddr_t)) +
439 (2 * physaddrlen);
440
441 if (dflag) {
442 str = _link_ntoa(rdev->physaddr, str,
443 rdev->physaddrlen, IFT_OTHER);
444 if (str != NULL) {
445 debug("device %s physical address %s", linkname, str);
446 free(str);
447 }
448 }
449
450 /*
451 * Assign dlpi handle to rdev.
452 */
453 rdev->dh_rarp = dh;
454
455 /*
456 * Get the IP address and netmask from directory service for
457 * each logical interface.
458 */
459 for (ifdev = rdev->ifdev; ifdev != NULL; ifdev = ifdev->next) {
460 /*
461 * If lunit == -1 then this is the primary interface name.
462 */
463 if (ifdev->lunit == -1) {
464 dev = rdev->device;
465 unit = rdev->unit;
466 } else {
467 dev = ifdev->ldevice;
468 unit = ifdev->lunit;
469 }
470 get_ifdata(dev, unit, &ifdev->if_ipaddr, &ifdev->if_netmask);
471
472 /*
473 * Use IP address of the interface.
474 */
475 ifdev->if_netnum = ifdev->if_ipaddr & ifdev->if_netmask;
476 ifdev->ipaddr = (ipaddr_t)htonl(ifdev->if_ipaddr);
477 }
478 }
479
480 static void
481 do_rarp(void *buf)
482 {
483 struct rarpdev *rdev = buf;
484 char *cause;
485 struct arphdr *ans;
486 uchar_t *shost;
487 uint_t saddrlen;
488 size_t anslen = rdev->ifrarplen;
489 char *str = NULL;
490 int retval;
491
492 if (((shost = malloc(rdev->physaddrlen)) == NULL) ||
493 ((ans = malloc(rdev->ifrarplen)) == NULL))
494 syserr("malloc");
495
496 if (dflag) {
497 str = _link_ntoa(rdev->physaddr, str, rdev->physaddrlen,
498 IFT_OTHER);
499 if (str != NULL) {
500 debug("starting rarp service on device %s%d physical"
501 " address %s", rdev->device, rdev->unit, str);
502 free(str);
503 }
504 }
505
506 /*
507 * Read RARP packets and respond to them.
508 */
509 for (;;) {
510 saddrlen = DLPI_PHYSADDR_MAX;
511 retval = dlpi_recv(rdev->dh_rarp, shost,
512 &saddrlen, ans, &anslen, -1, NULL);
513 if (retval == DLPI_ETIMEDOUT) {
514 continue;
515 } else if (retval != DLPI_SUCCESS) {
516 error("error in dlpi_recv %s: %s", rdev->dh_rarp,
517 dlpi_strerror(retval));
518 }
519
520 cause = NULL;
521
522 if (anslen < rdev->ifrarplen)
523 cause = "short packet";
524 else if (ans->ar_hrd != htons(ARPHRD_ETHER))
525 cause = "hardware type not Ethernet";
526 else if (ans->ar_pro != htons(ETHERTYPE_IP))
527 cause = "protocol type not IP";
528 else if (ans->ar_hln != rdev->physaddrlen)
529 cause = "unexpected hardware address length";
530 else if (ans->ar_pln != sizeof (ipaddr_t))
531 cause = "unexpected protocol address length";
532 if (cause != NULL) {
533 if (dflag)
534 debug("RARP packet received but "
535 "discarded: %s", cause);
536 continue;
537 }
538
539 /*
540 * Handle the request.
541 */
542 switch (ntohs(ans->ar_op)) {
543 case REVARP_REQUEST:
544 rarp_request(rdev, ans, shost);
545 break;
546
547 case ARPOP_REQUEST:
548 arp_request(rdev, ans, shost);
549 break;
550
551 case REVARP_REPLY:
552 if (dflag)
553 debug("REVARP_REPLY ignored");
554 break;
555
556 case ARPOP_REPLY:
557 if (dflag)
558 debug("ARPOP_REPLY ignored");
559 break;
560
561 default:
562 if (dflag)
563 debug("unknown opcode 0x%x", ans->ar_op);
564 break;
565 }
566 }
567 }
568
569 /*
570 * Reverse address determination and allocation code.
571 */
572 static void
573 rarp_request(struct rarpdev *rdev, struct arphdr *rp, uchar_t *shost)
574 {
575 ipaddr_t tpa, spa;
576 struct rarpreply *rrp;
577 uchar_t *shap, *thap, *spap, *tpap;
578 char *str = NULL;
579 int retval;
580
581 shap = (uchar_t *)rp + sizeof (struct arphdr);
582 spap = shap + rp->ar_hln;
583 thap = spap + rp->ar_pln;
584 tpap = thap + rp->ar_hln;
585
586 if (dflag) {
587 str = _link_ntoa(thap, str, rdev->physaddrlen, IFT_OTHER);
588 if (str != NULL) {
589 debug("RARP_REQUEST for %s", str);
590 free(str);
591 }
592 }
593
594 /*
595 * Third party lookups are rare and wonderful.
596 */
597 if ((memcmp(shap, thap, rdev->physaddrlen) != 0) ||
598 (memcmp(shap, shost, rdev->physaddrlen) != 0)) {
599 if (dflag)
600 debug("weird (3rd party lookup)");
601 }
602
603 /*
604 * Fill in given parts of reply packet.
605 */
606 (void) memcpy(shap, rdev->physaddr, rdev->physaddrlen);
607
608 /*
609 * If a good address is stored in our lookup tables, return it
610 * immediately or after a delay. Store it in our kernel's ARP cache.
611 */
612 if (get_ipaddr(rdev, thap, tpap, &spa))
613 return;
614 (void) memcpy(spap, &spa, sizeof (spa));
615
616 add_arp(rdev, tpap, thap);
617
618 rp->ar_op = htons(REVARP_REPLY);
619
620 if (dflag) {
621 struct in_addr addr;
622
623 (void) memcpy(&addr, tpap, sizeof (ipaddr_t));
624 debug("good lookup, maps to %s", inet_ntoa(addr));
625 }
626
627 rrp = calloc(1, sizeof (struct rarpreply) + rdev->physaddrlen +
628 rdev->ifrarplen);
629 if (rrp == NULL)
630 error("out of memory");
631 rrp->lldest = (uchar_t *)rrp + sizeof (struct rarpreply);
632 rrp->arprep = rrp->lldest + rdev->physaddrlen;
633
634 /*
635 * Create rarpreply structure.
636 */
637 (void) gettimeofday(&rrp->tv, NULL);
638 rrp->tv.tv_sec += 3; /* delay */
639 rrp->rdev = rdev;
640 (void) memcpy(rrp->lldest, shost, rdev->physaddrlen);
641 (void) memcpy(rrp->arprep, rp, rdev->ifrarplen);
642
643 /*
644 * If this is diskless and we're not its bootserver, let the
645 * bootserver reply first by delaying a while.
646 */
647 (void) memcpy(&tpa, tpap, sizeof (ipaddr_t));
648 if (mightboot(ntohl(tpa))) {
649 retval = dlpi_send(rdev->dh_rarp, rrp->lldest,
650 rdev->physaddrlen, rrp->arprep, rdev->ifrarplen, NULL);
651 if (retval != DLPI_SUCCESS) {
652 error("dlpi_send failed: %s", dlpi_strerror(retval));
653 } else if (dflag) {
654 debug("immediate reply sent");
655 }
656 (void) free(rrp);
657 } else {
658 delay_write(rdev, rrp);
659 }
660 }
661
662 /*
663 * Download an ARP entry into our kernel.
664 */
665 static void
666 add_arp(struct rarpdev *rdev, uchar_t *ip, uchar_t *laddr)
667 {
668 struct xarpreq ar;
669 struct sockaddr_in *sin;
670 int fd;
671
672 /*
673 * Common part of query or set.
674 */
675 (void) memset(&ar, 0, sizeof (ar));
676 ar.xarp_pa.ss_family = AF_INET;
677 sin = (struct sockaddr_in *)&ar.xarp_pa;
678 (void) memcpy(&sin->sin_addr, ip, sizeof (ipaddr_t));
679
680 /*
681 * Open the IP provider.
682 */
683 if ((fd = open(DEVARP, 0)) < 0)
684 syserr(DEVARP);
685
686 /*
687 * Set the entry.
688 */
689 (void) memcpy(LLADDR(&ar.xarp_ha), laddr, rdev->physaddrlen);
690 ar.xarp_ha.sdl_alen = rdev->physaddrlen;
691 ar.xarp_ha.sdl_family = AF_LINK;
692 (void) strioctl(fd, SIOCDXARP, -1, sizeof (struct xarpreq),
693 (char *)&ar);
694 if (strioctl(fd, SIOCSXARP, -1, sizeof (struct xarpreq),
695 (char *)&ar) < 0)
696 syserr("SIOCSXARP");
697
698 (void) close(fd);
699 }
700
701 /*
702 * The RARP spec says we must be able to process ARP requests,
703 * even through the packet type is RARP. Let's hope this feature
704 * is not heavily used.
705 */
706 static void
707 arp_request(struct rarpdev *rdev, struct arphdr *rp, uchar_t *shost)
708 {
709 struct rarpreply *rrp;
710 struct ifdev *ifdev;
711 uchar_t *shap, *thap, *spap, *tpap;
712 int retval;
713
714 shap = (uchar_t *)rp + sizeof (struct arphdr);
715 spap = shap + rp->ar_hln;
716 thap = spap + rp->ar_pln;
717 tpap = thap + rp->ar_hln;
718
719 if (dflag)
720 debug("ARPOP_REQUEST");
721
722 for (ifdev = rdev->ifdev; ifdev != NULL; ifdev = ifdev->next) {
723 if (memcmp(&ifdev->ipaddr, tpap, sizeof (ipaddr_t)) == 0)
724 break;
725 }
726 if (ifdev == NULL)
727 return;
728
729 rp->ar_op = ARPOP_REPLY;
730 (void) memcpy(shap, rdev->physaddr, rdev->physaddrlen);
731 (void) memcpy(spap, &ifdev->ipaddr, sizeof (ipaddr_t));
732 (void) memcpy(thap, rdev->physaddr, rdev->physaddrlen);
733
734 add_arp(rdev, tpap, thap);
735
736 /*
737 * Create rarp reply structure.
738 */
739 rrp = calloc(1, sizeof (struct rarpreply) + rdev->physaddrlen +
740 rdev->ifrarplen);
741 if (rrp == NULL)
742 error("out of memory");
743 rrp->lldest = (uchar_t *)rrp + sizeof (struct rarpreply);
744 rrp->arprep = rrp->lldest + rdev->physaddrlen;
745 rrp->rdev = rdev;
746
747 (void) memcpy(rrp->lldest, shost, rdev->physaddrlen);
748 (void) memcpy(rrp->arprep, rp, rdev->ifrarplen);
749
750 retval = dlpi_send(rdev->dh_rarp, rrp->lldest, rdev->physaddrlen,
751 rrp->arprep, rdev->ifrarplen, NULL);
752 free(rrp);
753 if (retval != DLPI_SUCCESS)
754 error("dlpi_send failed: %s", dlpi_strerror(retval));
755 }
756
757 /* ARGSUSED */
758 static void
759 do_delay_write(void *buf)
760 {
761 struct timeval tv;
762 struct rarpreply *rrp;
763 struct rarpdev *rdev;
764 int err;
765
766 for (;;) {
767 if ((err = sema_wait(&delay_sema)) != 0) {
768 if (err == EINTR)
769 continue;
770 error("do_delay_write: sema_wait failed");
771 }
772
773 (void) mutex_lock(&delay_mutex);
774 rrp = delay_list;
775 rdev = rrp->rdev;
776 delay_list = delay_list->next;
777 (void) mutex_unlock(&delay_mutex);
778
779 (void) gettimeofday(&tv, NULL);
780 if (tv.tv_sec < rrp->tv.tv_sec)
781 (void) sleep(rrp->tv.tv_sec - tv.tv_sec);
782
783 err = dlpi_send(rdev->dh_rarp, rrp->lldest, rdev->physaddrlen,
784 rrp->arprep, rdev->ifrarplen, NULL);
785 if (err != DLPI_SUCCESS)
786 error("dlpi_send failed: %s", dlpi_strerror(err));
787
788 (void) free(rrp);
789 }
790 }
791
792 /* ARGSUSED */
793 static void
794 delay_write(struct rarpdev *rdev, struct rarpreply *rrp)
795 {
796 struct rarpreply *trp;
797
798 (void) mutex_lock(&delay_mutex);
799 if (delay_list == NULL) {
800 delay_list = rrp;
801 } else {
802 trp = delay_list;
803 while (trp->next != NULL)
804 trp = trp->next;
805 trp->next = rrp;
806 }
807 (void) mutex_unlock(&delay_mutex);
808
809 (void) sema_post(&delay_sema);
810 }
811
812 /*
813 * See if we have a TFTP boot file for this guy. Filenames in TFTP
814 * boot requests are of the form <ipaddr> for Sun-3's and of the form
815 * <ipaddr>.<arch> for all other architectures. Since we don't know
816 * the client's architecture, either format will do.
817 */
818 static int
819 mightboot(ipaddr_t ipa)
820 {
821 char path[MAXPATHL];
822 DIR *dirp;
823 struct dirent *dp;
824
825 (void) snprintf(path, sizeof (path), "%s/%08X", BOOTDIR, ipa);
826
827 /*
828 * Try a quick access() first.
829 */
830 if (access(path, 0) == 0)
831 return (1);
832
833 /*
834 * Not there, do it the slow way by
835 * reading through the directory.
836 */
837 (void) sprintf(path, "%08X", ipa);
838
839 if (!(dirp = opendir(BOOTDIR)))
840 return (0);
841
842 while ((dp = readdir(dirp)) != NULL) {
843 if (strncmp(dp->d_name, path, 8) != 0)
844 continue;
845 if ((strlen(dp->d_name) != 8) && (dp->d_name[8] != '.'))
846 continue;
847 break;
848 }
849
850 (void) closedir(dirp);
851
852 return ((dp != NULL) ? 1 : 0);
853 }
854
855 /*
856 * Get our IP address and local netmask.
857 */
858 static void
859 get_ifdata(char *dev, int unit, ipaddr_t *ipp, ipaddr_t *maskp)
860 {
861 int fd;
862 struct ifreq ifr;
863 struct sockaddr_in *sin;
864
865 /* LINTED pointer */
866 sin = (struct sockaddr_in *)&ifr.ifr_addr;
867
868 /*
869 * Open the IP provider.
870 */
871 if ((fd = open(DEVIP, 0)) < 0)
872 syserr(DEVIP);
873
874 /*
875 * Ask IP for our IP address.
876 */
877 (void) snprintf(ifr.ifr_name, sizeof (ifr.ifr_name), "%s%d", dev, unit);
878 if (strioctl(fd, SIOCGIFADDR, -1, sizeof (struct ifreq),
879 (char *)&ifr) < 0)
880 syserr("SIOCGIFADDR");
881 *ipp = (ipaddr_t)ntohl(sin->sin_addr.s_addr);
882
883 if (dflag)
884 debug("device %s%d address %s", dev, unit,
885 inet_ntoa(sin->sin_addr));
886
887 /*
888 * Ask IP for our netmask.
889 */
890 if (strioctl(fd, SIOCGIFNETMASK, -1, sizeof (struct ifreq),
891 (char *)&ifr) < 0)
892 syserr("SIOCGIFNETMASK");
893 *maskp = (ipaddr_t)ntohl(sin->sin_addr.s_addr);
894
895 if (dflag)
896 debug("device %s%d subnet mask %s", dev, unit,
897 inet_ntoa(sin->sin_addr));
898
899 /*
900 * Thankyou ip.
901 */
902 (void) close(fd);
903 }
904
905 /*
906 * Translate mac address to IP address.
907 * Return 0 on success, nonzero on failure.
908 */
909 static int
910 get_ipaddr(struct rarpdev *rdev, uchar_t *laddr, uchar_t *ipp, ipaddr_t *ipaddr)
911 {
912 char host[MAXHOSTL];
913 char hbuffer[BUFSIZE];
914 struct hostent *hp, res;
915 int herror;
916 struct in_addr addr;
917 char **p;
918 struct ifdev *ifdev;
919
920 if (rdev->physaddrlen != ETHERADDRL) {
921 if (dflag)
922 debug("%s %s", " cannot map non 6 byte hardware ",
923 "address to IP address");
924 return (1);
925 }
926
927 /*
928 * Translate mac address to hostname and IP address.
929 */
930 if (ether_ntohost(host, (struct ether_addr *)laddr) != 0 ||
931 !(hp = gethostbyname_r(host, &res, hbuffer, sizeof (hbuffer),
932 &herror)) ||
933 hp->h_addrtype != AF_INET || hp->h_length != sizeof (ipaddr_t)) {
934 if (dflag)
935 debug("could not map hardware address to IP address");
936 return (1);
937 }
938
939 /*
940 * Find the IP address on the right net.
941 */
942 for (p = hp->h_addr_list; *p; p++) {
943 (void) memcpy(&addr, *p, sizeof (ipaddr_t));
944 for (ifdev = rdev->ifdev; ifdev != NULL; ifdev = ifdev->next) {
945 if (dflag) {
946 struct in_addr daddr;
947 ipaddr_t netnum;
948
949 netnum = htonl(ifdev->if_netnum);
950 (void) memcpy(&daddr, &netnum,
951 sizeof (ipaddr_t));
952 if (ifdev->lunit == -1)
953 debug("trying physical netnum %s"
954 " mask %x", inet_ntoa(daddr),
955 ifdev->if_netmask);
956 else
957 debug("trying logical %d netnum %s"
958 " mask %x", ifdev->lunit,
959 inet_ntoa(daddr),
960 ifdev->if_netmask);
961 }
962 if ((ntohl(addr.s_addr) & ifdev->if_netmask) ==
963 ifdev->if_netnum) {
964 /*
965 * Return the correct IP address.
966 */
967 (void) memcpy(ipp, &addr, sizeof (ipaddr_t));
968
969 /*
970 * Return the interface's ipaddr
971 */
972 (void) memcpy(ipaddr, &ifdev->ipaddr,
973 sizeof (ipaddr_t));
974
975 return (0);
976 }
977 }
978 }
979
980 if (dflag)
981 debug("got host entry but no IP address on this net");
982 return (1);
983 }
984
985 static int
986 strioctl(int fd, int cmd, int timout, int len, char *dp)
987 {
988 struct strioctl si;
989
990 si.ic_cmd = cmd;
991 si.ic_timout = timout;
992 si.ic_len = len;
993 si.ic_dp = dp;
994 return (ioctl(fd, I_STR, &si));
995 }
996
997 static void
998 usage(void)
999 {
1000 error("Usage: %s [ -ad ] device unit", cmdname);
1001 }
1002
1003 static void
1004 syserr(const char *s)
1005 {
1006 char buf[256];
1007 int status = 1;
1008
1009 (void) snprintf(buf, sizeof (buf), "%s: %s", s, strerror(errno));
1010 (void) fprintf(stderr, "%s: %s\n", cmdname, buf);
1011 syslog(LOG_ERR, "%s", buf);
1012 thr_exit(&status);
1013 }
1014
1015 static void
1016 error(const char *fmt, ...)
1017 {
1018 char buf[256];
1019 va_list ap;
1020 int status = 1;
1021
1022 va_start(ap, fmt);
1023 (void) vsprintf(buf, fmt, ap);
1024 va_end(ap);
1025 (void) fprintf(stderr, "%s: %s\n", cmdname, buf);
1026 syslog(LOG_ERR, buf);
1027 thr_exit(&status);
1028 }
1029
1030 /*PRINTFLIKE1*/
1031 static void
1032 debug(char *fmt, ...)
1033 {
1034 va_list ap;
1035
1036 (void) mutex_lock(&debug_mutex);
1037 va_start(ap, fmt);
1038 (void) fprintf(stderr, "%s:[%u] ", cmdname, thr_self());
1039 (void) vfprintf(stderr, fmt, ap);
1040 (void) fprintf(stderr, "\n");
1041 va_end(ap);
1042 (void) mutex_unlock(&debug_mutex);
1043 }