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 2009 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 /*
34 * rarpd.c Reverse-ARP server.
35 * Refer to RFC 903 "A Reverse Address Resolution Protocol".
36 */
37
38 #define _REENTRANT
39
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>
66
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 */
70
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
75
76 /*
77 * Logical network devices
78 */
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;
87 };
88
89 /*
90 * Physical network device
91 */
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 */
102 };
103
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;
110 };
111
112 static struct rarpreply *delay_list;
113 static sema_t delay_sema;
114 static mutex_t delay_mutex;
115 static mutex_t debug_mutex;
116
117 static struct rarpdev *rarpdev_head;
118
119 /*
120 * Globals initialized before multi-threading
121 */
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 */
125
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 *, ...);
145
146 extern int optind;
147 extern char *optarg;
148
149 int
main(int argc,char * argv[])150 main(int argc, char *argv[])
151 {
152 int c;
153 struct rlimit rl;
154 struct rarpdev *rdev;
155 int i;
156
157 cmdname = argv[0];
158
159 while ((c = getopt(argc, argv, "ad")) != -1) {
160 switch (c) {
161 case 'a':
162 aflag = 1;
163 break;
164
165 case 'd':
166 dflag = 1;
167 break;
168
169 default:
170 usage();
171 }
172 }
173
174 if ((!aflag && (argc - optind) != 2) ||
175 (aflag && (argc - optind) != 0)) {
176 usage();
177 /* NOTREACHED */
178 }
179
180 if (!dflag) {
181 /*
182 * Background
183 */
184 switch (fork()) {
185 case -1: /* error */
186 syserr("fork");
187 /*NOTREACHED*/
188
189 case 0: /* child */
190 break;
191
192 default: /* parent */
193 return (0);
194 }
195 for (i = 0; i < 3; i++) {
196 (void) close(i);
197 }
198 (void) open("/", O_RDONLY, 0);
199 (void) dup2(0, 1);
200 (void) dup2(0, 2);
201 /*
202 * Detach terminal
203 */
204 if (setsid() < 0)
205 syserr("setsid");
206 }
207
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);
213
214 (void) openlog(cmdname, LOG_PID, LOG_DAEMON);
215
216 if (aflag) {
217 /*
218 * Get each interface name and load rarpdev list.
219 */
220 getintf();
221 } else {
222 ifspec_t ifsp;
223 struct ifdev *ifdev;
224 char buf[IFNAMSIZ + 1];
225
226 /*
227 * Load specified device as only element of the list.
228 */
229 rarpdev_head = (struct rarpdev *)calloc(1,
230 sizeof (struct rarpdev));
231 if (rarpdev_head == NULL) {
232 error("out of memory");
233 }
234 (void) strncpy(buf, argv[optind], IFNAMSIZ);
235 (void) strncat(buf, argv[optind + 1], IFNAMSIZ - strlen(buf));
236
237 if ((ifdev = calloc(1, sizeof (struct ifdev))) == NULL) {
238 error("out of memory");
239 }
240
241 if (!ifparse_ifspec(buf, &ifsp))
242 error("invalid interface specification");
243
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 */
251 }
252 (void) strlcpy(rarpdev_head->device, ifsp.ifsp_devnm,
253 sizeof (rarpdev_head->device));
254 rarpdev_head->unit = ifsp.ifsp_ppa;
255
256 ifdev->next = rarpdev_head->ifdev;
257 rarpdev_head->ifdev = ifdev;
258 }
259
260 /*
261 * Initialize each rarpdev.
262 */
263 for (rdev = rarpdev_head; rdev != NULL; rdev = rdev->next) {
264 init_rarpdev(rdev);
265 }
266
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);
270
271 /*
272 * Start delayed processing thread.
273 */
274 (void) thr_create(NULL, 0, (void *(*)(void *))do_delay_write, NULL,
275 THR_NEW_LWP, NULL);
276
277 /*
278 * Start RARP processing for each device.
279 */
280 for (rdev = rarpdev_head; rdev != NULL; rdev = rdev->next) {
281 if (rdev->dh_rarp != NULL) {
282 (void) thr_create(NULL, 0,
283 (void *(*)(void *))do_rarp, (void *)rdev,
284 THR_NEW_LWP, NULL);
285 }
286 }
287
288 /*
289 * Exit main() thread
290 */
291 thr_exit(NULL);
292
293 return (0);
294 }
295
296 static void
getintf(void)297 getintf(void)
298 {
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;
307
308 /*
309 * Open the IP provider.
310 */
311 if ((fd = open(DEVIP, 0)) < 0)
312 syserr(DEVIP);
313
314 /*
315 * Ask IP for the list of configured interfaces.
316 */
317 if (ioctl(fd, SIOCGIFNUM, (char *)&numifs) < 0) {
318 numifs = MAXIFS;
319 }
320 bufsize = numifs * sizeof (struct ifreq);
321 reqbuf = (struct ifreq *)malloc(bufsize);
322 if (reqbuf == NULL) {
323 error("out of memory");
324 }
325
326 ifconf.ifc_len = bufsize;
327 ifconf.ifc_buf = (caddr_t)reqbuf;
328 if (ioctl(fd, SIOCGIFCONF, (char *)&ifconf) < 0)
329 syserr("SIOCGIFCONF");
330
331 /*
332 * Initialize a rarpdev for each interface.
333 */
334 for (ifr = ifconf.ifc_req; ifconf.ifc_len > 0;
335 ifr++, ifconf.ifc_len -= sizeof (struct ifreq)) {
336 ifspec_t ifsp;
337
338 if (ioctl(fd, SIOCGIFFLAGS, (char *)ifr) < 0) {
339 syserr("ioctl SIOCGIFFLAGS");
340 exit(1);
341 }
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;
348
349 if (!ifparse_ifspec(ifr->ifr_name, &ifsp))
350 error("ifparse_ifspec failed");
351
352 /*
353 * Look for an existing device for logical interfaces.
354 */
355 if ((rdev = find_device(&ifsp)) == NULL) {
356 rdev = calloc(1, sizeof (struct rarpdev));
357 if (rdev == NULL)
358 error("out of memory");
359
360 (void) strlcpy(rdev->device, ifsp.ifsp_devnm,
361 sizeof (rdev->device));
362 rdev->unit = ifsp.ifsp_ppa;
363
364 rdev->next = rarpdev_head;
365 rarpdev_head = rdev;
366 }
367
368 if ((ifdev = calloc(1, sizeof (struct ifdev))) == NULL)
369 error("out of memory");
370
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 */
378
379 ifdev->next = rdev->ifdev;
380 rdev->ifdev = ifdev;
381 }
382 (void) free((char *)reqbuf);
383 }
384
385 static struct rarpdev *
find_device(ifspec_t * specp)386 find_device(ifspec_t *specp)
387 {
388 struct rarpdev *rdev;
389
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);
394 }
395 return (NULL);
396 }
397
398 static void
init_rarpdev(struct rarpdev * rdev)399 init_rarpdev(struct rarpdev *rdev)
400 {
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;
409
410 (void) snprintf(linkname, DLPI_LINKNAME_MAX, "%s%d", rdev->device,
411 rdev->unit);
412 /*
413 * Open datalink provider and get our mac address.
414 */
415 if ((retval = dlpi_open(linkname, &dh, 0)) != DLPI_SUCCESS) {
416 error("cannot open link %s: %s", linkname,
417 dlpi_strerror(retval));
418 }
419
420 if ((retval = dlpi_bind(dh, ETHERTYPE_REVARP, NULL)) != DLPI_SUCCESS) {
421 dlpi_close(dh);
422 error("dlpi_bind failed: %s", dlpi_strerror(retval));
423 }
424
425 /*
426 * Save our mac address.
427 */
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));
432 }
433
434 rdev->physaddrlen = physaddrlen;
435 rdev->ifrarplen = sizeof (struct arphdr) + (2 * sizeof (ipaddr_t)) +
436 (2 * physaddrlen);
437
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);
444 }
445 }
446
447 /*
448 * Assign dlpi handle to rdev.
449 */
450 rdev->dh_rarp = dh;
451
452 /*
453 * Get the IP address and netmask from directory service for
454 * each logical interface.
455 */
456 for (ifdev = rdev->ifdev; ifdev != NULL; ifdev = ifdev->next) {
457 /*
458 * If lunit == -1 then this is the primary interface name.
459 */
460 if (ifdev->lunit == -1) {
461 dev = rdev->device;
462 unit = rdev->unit;
463 } else {
464 dev = ifdev->ldevice;
465 unit = ifdev->lunit;
466 }
467 get_ifdata(dev, unit, &ifdev->if_ipaddr, &ifdev->if_netmask);
468
469 /*
470 * Use IP address of the interface.
471 */
472 ifdev->if_netnum = ifdev->if_ipaddr & ifdev->if_netmask;
473 ifdev->ipaddr = (ipaddr_t)htonl(ifdev->if_ipaddr);
474 }
475 }
476
477 static void
do_rarp(void * buf)478 do_rarp(void *buf)
479 {
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;
488
489 if (((shost = malloc(rdev->physaddrlen)) == NULL) ||
490 ((ans = malloc(rdev->ifrarplen)) == NULL))
491 syserr("malloc");
492
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);
500 }
501 }
502
503 /*
504 * Read RARP packets and respond to them.
505 */
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));
515 }
516
517 cause = NULL;
518
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;
534 }
535
536 /*
537 * Handle the request.
538 */
539 switch (ntohs(ans->ar_op)) {
540 case REVARP_REQUEST:
541 rarp_request(rdev, ans, shost);
542 break;
543
544 case ARPOP_REQUEST:
545 arp_request(rdev, ans, shost);
546 break;
547
548 case REVARP_REPLY:
549 if (dflag)
550 debug("REVARP_REPLY ignored");
551 break;
552
553 case ARPOP_REPLY:
554 if (dflag)
555 debug("ARPOP_REPLY ignored");
556 break;
557
558 default:
559 if (dflag)
560 debug("unknown opcode 0x%x", ans->ar_op);
561 break;
562 }
563 }
564 }
565
566 /*
567 * Reverse address determination and allocation code.
568 */
569 static void
rarp_request(struct rarpdev * rdev,struct arphdr * rp,uchar_t * shost)570 rarp_request(struct rarpdev *rdev, struct arphdr *rp, uchar_t *shost)
571 {
572 ipaddr_t tpa, spa;
573 struct rarpreply *rrp;
574 uchar_t *shap, *thap, *spap, *tpap;
575 char *str = NULL;
576 int retval;
577
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;
582
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);
588 }
589 }
590
591 /*
592 * Third party lookups are rare and wonderful.
593 */
594 if ((memcmp(shap, thap, rdev->physaddrlen) != 0) ||
595 (memcmp(shap, shost, rdev->physaddrlen) != 0)) {
596 if (dflag)
597 debug("weird (3rd party lookup)");
598 }
599
600 /*
601 * Fill in given parts of reply packet.
602 */
603 (void) memcpy(shap, rdev->physaddr, rdev->physaddrlen);
604
605 /*
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.
608 */
609 if (get_ipaddr(rdev, thap, tpap, &spa))
610 return;
611 (void) memcpy(spap, &spa, sizeof (spa));
612
613 add_arp(rdev, tpap, thap);
614
615 rp->ar_op = htons(REVARP_REPLY);
616
617 if (dflag) {
618 struct in_addr addr;
619
620 (void) memcpy(&addr, tpap, sizeof (ipaddr_t));
621 debug("good lookup, maps to %s", inet_ntoa(addr));
622 }
623
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;
630
631 /*
632 * Create rarpreply structure.
633 */
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);
639
640 /*
641 * If this is diskless and we're not its bootserver, let the
642 * bootserver reply first by delaying a while.
643 */
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");
652 }
653 (void) free(rrp);
654 } else {
655 delay_write(rdev, rrp);
656 }
657 }
658
659 /*
660 * Download an ARP entry into our kernel.
661 */
662 static void
add_arp(struct rarpdev * rdev,uchar_t * ip,uchar_t * laddr)663 add_arp(struct rarpdev *rdev, uchar_t *ip, uchar_t *laddr)
664 {
665 struct xarpreq ar;
666 struct sockaddr_in *sin;
667 int fd;
668
669 /*
670 * Common part of query or set.
671 */
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));
676
677 /*
678 * Open the IP provider.
679 */
680 if ((fd = open(DEVARP, 0)) < 0)
681 syserr(DEVARP);
682
683 /*
684 * Set the entry.
685 */
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");
694
695 (void) close(fd);
696 }
697
698 /*
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.
702 */
703 static void
arp_request(struct rarpdev * rdev,struct arphdr * rp,uchar_t * shost)704 arp_request(struct rarpdev *rdev, struct arphdr *rp, uchar_t *shost)
705 {
706 struct rarpreply *rrp;
707 struct ifdev *ifdev;
708 uchar_t *shap, *thap, *spap, *tpap;
709 int retval;
710
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;
715
716 if (dflag)
717 debug("ARPOP_REQUEST");
718
719 for (ifdev = rdev->ifdev; ifdev != NULL; ifdev = ifdev->next) {
720 if (memcmp(&ifdev->ipaddr, tpap, sizeof (ipaddr_t)) == 0)
721 break;
722 }
723 if (ifdev == NULL)
724 return;
725
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);
730
731 add_arp(rdev, tpap, thap);
732
733 /*
734 * Create rarp reply structure.
735 */
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;
743
744 (void) memcpy(rrp->lldest, shost, rdev->physaddrlen);
745 (void) memcpy(rrp->arprep, rp, rdev->ifrarplen);
746
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));
752 }
753
754 /* ARGSUSED */
755 static void
do_delay_write(void * buf)756 do_delay_write(void *buf)
757 {
758 struct timeval tv;
759 struct rarpreply *rrp;
760 struct rarpdev *rdev;
761 int err;
762
763 for (;;) {
764 if ((err = sema_wait(&delay_sema)) != 0) {
765 if (err == EINTR)
766 continue;
767 error("do_delay_write: sema_wait failed");
768 }
769
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);
775
776 (void) gettimeofday(&tv, NULL);
777 if (tv.tv_sec < rrp->tv.tv_sec)
778 (void) sleep(rrp->tv.tv_sec - tv.tv_sec);
779
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));
784
785 (void) free(rrp);
786 }
787 }
788
789 /* ARGSUSED */
790 static void
delay_write(struct rarpdev * rdev,struct rarpreply * rrp)791 delay_write(struct rarpdev *rdev, struct rarpreply *rrp)
792 {
793 struct rarpreply *trp;
794
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;
803 }
804 (void) mutex_unlock(&delay_mutex);
805
806 (void) sema_post(&delay_sema);
807 }
808
809 /*
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.
814 */
815 static int
mightboot(ipaddr_t ipa)816 mightboot(ipaddr_t ipa)
817 {
818 char path[MAXPATHL];
819 DIR *dirp;
820 struct dirent *dp;
821
822 (void) snprintf(path, sizeof (path), "%s/%08X", BOOTDIR, ipa);
823
824 /*
825 * Try a quick access() first.
826 */
827 if (access(path, 0) == 0)
828 return (1);
829
830 /*
831 * Not there, do it the slow way by
832 * reading through the directory.
833 */
834 (void) sprintf(path, "%08X", ipa);
835
836 if (!(dirp = opendir(BOOTDIR)))
837 return (0);
838
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;
845 }
846
847 (void) closedir(dirp);
848
849 return ((dp != NULL) ? 1 : 0);
850 }
851
852 /*
853 * Get our IP address and local netmask.
854 */
855 static void
get_ifdata(char * dev,int unit,ipaddr_t * ipp,ipaddr_t * maskp)856 get_ifdata(char *dev, int unit, ipaddr_t *ipp, ipaddr_t *maskp)
857 {
858 int fd;
859 struct ifreq ifr;
860 struct sockaddr_in *sin;
861
862 /* LINTED pointer */
863 sin = (struct sockaddr_in *)&ifr.ifr_addr;
864
865 /*
866 * Open the IP provider.
867 */
868 if ((fd = open(DEVIP, 0)) < 0)
869 syserr(DEVIP);
870
871 /*
872 * Ask IP for our IP address.
873 */
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);
879
880 if (dflag)
881 debug("device %s%d address %s", dev, unit,
882 inet_ntoa(sin->sin_addr));
883
884 /*
885 * Ask IP for our netmask.
886 */
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);
891
892 if (dflag)
893 debug("device %s%d subnet mask %s", dev, unit,
894 inet_ntoa(sin->sin_addr));
895
896 /*
897 * Thankyou ip.
898 */
899 (void) close(fd);
900 }
901
902 /*
903 * Translate mac address to IP address.
904 * Return 0 on success, nonzero on failure.
905 */
906 static int
get_ipaddr(struct rarpdev * rdev,uchar_t * laddr,uchar_t * ipp,ipaddr_t * ipaddr)907 get_ipaddr(struct rarpdev *rdev, uchar_t *laddr, uchar_t *ipp, ipaddr_t *ipaddr)
908 {
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;
916
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);
922 }
923
924 /*
925 * Translate mac address to hostname and IP address.
926 */
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);
934 }
935
936 /*
937 * Find the IP address on the right net.
938 */
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;
945
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);
958 }
959 if ((ntohl(addr.s_addr) & ifdev->if_netmask) ==
960 ifdev->if_netnum) {
961 /*
962 * Return the correct IP address.
963 */
964 (void) memcpy(ipp, &addr, sizeof (ipaddr_t));
965
966 /*
967 * Return the interface's ipaddr
968 */
969 (void) memcpy(ipaddr, &ifdev->ipaddr,
970 sizeof (ipaddr_t));
971
972 return (0);
973 }
974 }
975 }
976
977 if (dflag)
978 debug("got host entry but no IP address on this net");
979 return (1);
980 }
981
982 static int
strioctl(int fd,int cmd,int timout,int len,char * dp)983 strioctl(int fd, int cmd, int timout, int len, char *dp)
984 {
985 struct strioctl si;
986
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));
992 }
993
994 static void
usage(void)995 usage(void)
996 {
997 error("Usage: %s [ -ad ] device unit", cmdname);
998 }
999
1000 static void
syserr(const char * s)1001 syserr(const char *s)
1002 {
1003 char buf[256];
1004 int status = 1;
1005
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);
1010 }
1011
1012 static void
error(const char * fmt,...)1013 error(const char *fmt, ...)
1014 {
1015 char buf[256];
1016 va_list ap;
1017 int status = 1;
1018
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);
1025 }
1026
1027 /*PRINTFLIKE1*/
1028 static void
debug(char * fmt,...)1029 debug(char *fmt, ...)
1030 {
1031 va_list ap;
1032
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);
1040 }
1041