rarpd.c revision 1.8 1 /*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21 #ifndef lint
22 char copyright[] =
23 "@(#) Copyright (c) 1990 The Regents of the University of California.\n\
24 All rights reserved.\n";
25 #endif /* not lint */
26
27 #ifndef lint
28 static char rcsid[] =
29 "@(#) $Id: rarpd.c,v 1.8 1995/09/01 21:55:47 thorpej Exp $";
30 #endif
31
32
33 /*
34 * rarpd - Reverse ARP Daemon
35 *
36 * Usage: rarpd -a [ -d -f ]
37 * rarpd [ -d -f ] interface
38 */
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <syslog.h>
43 #include <string.h>
44 #include <strings.h>
45 #include <sys/types.h>
46 #include <unistd.h>
47 #include <sys/time.h>
48 #include <net/bpf.h>
49 #include <sys/socket.h>
50 #include <sys/ioctl.h>
51 #include <net/if.h>
52 #include <net/if_dl.h>
53 #include <net/if_types.h>
54 #include <netinet/in.h>
55 #include <netinet/if_ether.h>
56 #include <sys/errno.h>
57 #include <sys/file.h>
58 #include <netdb.h>
59 #include <arpa/inet.h>
60 #include <dirent.h>
61
62 #define FATAL 1 /* fatal error occurred */
63 #define NONFATAL 0 /* non fatal error occurred */
64
65 /*
66 * The structure for each interface.
67 */
68 struct if_info {
69 int ii_fd; /* BPF file descriptor */
70 u_char ii_eaddr[6]; /* Ethernet address of this interface */
71 u_long ii_ipaddr; /* IP address of this interface */
72 u_long ii_netmask; /* subnet or net mask */
73 struct if_info *ii_next;
74 };
75 /*
76 * The list of all interfaces that are being listened to. rarp_loop()
77 * "selects" on the descriptors in this list.
78 */
79 struct if_info *iflist;
80
81 int rarp_open __P((char *));
82 void init_one __P((char *));
83 void init_all __P((void));
84 void rarp_loop __P((void));
85 void lookup_eaddr __P((char *, u_char *));
86 void lookup_ipaddr __P((char *, u_long *, u_long *));
87 void usage __P((void));
88 void rarp_process __P((struct if_info *, u_char *));
89 void rarp_reply __P((struct if_info *, struct ether_header *, u_long));
90 void update_arptab __P((u_char *, u_long));
91 void err __P((int, const char *,...));
92 void debug __P((const char *,...));
93 u_long ipaddrtonetmask __P((u_long));
94
95 #ifdef REQUIRE_TFTPBOOT
96 int rarp_bootable __P((u_long));
97 #endif
98
99 int aflag = 0; /* listen on "all" interfaces */
100 int dflag = 0; /* print debugging messages */
101 int fflag = 0; /* don't fork */
102
103 void
104 main(argc, argv)
105 int argc;
106 char **argv;
107 {
108 int op, pid, devnull, f;
109 char *ifname, *hostname, *name;
110
111 extern char *optarg;
112 extern int optind, opterr;
113
114 if (name = strrchr(argv[0], '/'))
115 ++name;
116 else
117 name = argv[0];
118 if (*name == '-')
119 ++name;
120
121 /* All error reporting is done through syslogs. */
122 openlog(name, LOG_PID | LOG_CONS, LOG_DAEMON);
123
124 opterr = 0;
125 while ((op = getopt(argc, argv, "adf")) != EOF) {
126 switch (op) {
127 case 'a':
128 ++aflag;
129 break;
130
131 case 'd':
132 ++dflag;
133 break;
134
135 case 'f':
136 ++fflag;
137 break;
138
139 default:
140 usage();
141 /* NOTREACHED */
142 }
143 }
144 ifname = argv[optind++];
145 hostname = ifname ? argv[optind] : 0;
146 if ((aflag && ifname) || (!aflag && ifname == 0))
147 usage();
148
149 if (aflag)
150 init_all();
151 else
152 init_one(ifname);
153
154 if ((!fflag) && (!dflag)) {
155 pid = fork();
156 if (pid > 0)
157 /* Parent exits, leaving child in background. */
158 exit(0);
159 else
160 if (pid == -1) {
161 err(FATAL, "cannot fork");
162 /* NOTREACHED */
163 }
164 /* Fade into the background */
165 f = open("/dev/tty", O_RDWR);
166 if (f >= 0) {
167 if (ioctl(f, TIOCNOTTY, 0) < 0) {
168 err(FATAL, "TIOCNOTTY: %s", strerror(errno));
169 /* NOTREACHED */
170 }
171 (void) close(f);
172 }
173 (void) chdir("/");
174 (void) setpgrp(0, getpid());
175 devnull = open("/dev/null", O_RDWR);
176 if (devnull >= 0) {
177 (void) dup2(devnull, 0);
178 (void) dup2(devnull, 1);
179 (void) dup2(devnull, 2);
180 if (devnull > 2)
181 (void) close(devnull);
182 }
183 }
184 rarp_loop();
185 }
186 /*
187 * Add 'ifname' to the interface list. Lookup its IP address and network
188 * mask and Ethernet address, and open a BPF file for it.
189 */
190 void
191 init_one(ifname)
192 char *ifname;
193 {
194 struct if_info *p;
195
196 p = (struct if_info *)malloc(sizeof(*p));
197 if (p == 0) {
198 err(FATAL, "malloc: %s", strerror(errno));
199 /* NOTREACHED */
200 }
201 p->ii_next = iflist;
202 iflist = p;
203
204 p->ii_fd = rarp_open(ifname);
205 lookup_eaddr(ifname, p->ii_eaddr);
206 lookup_ipaddr(ifname, &p->ii_ipaddr, &p->ii_netmask);
207 }
208 /*
209 * Initialize all "candidate" interfaces that are in the system
210 * configuration list. A "candidate" is up, not loopback and not
211 * point to point.
212 */
213 void
214 init_all()
215 {
216 char inbuf[8192];
217 struct ifconf ifc;
218 struct ifreq *ifr;
219 int fd;
220 int i, len;
221
222 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
223 err(FATAL, "socket: %s", strerror(errno));
224 /* NOTREACHED */
225 }
226
227 ifc.ifc_len = sizeof(inbuf);
228 ifc.ifc_buf = inbuf;
229 if (ioctl(fd, SIOCGIFCONF, (caddr_t)&ifc) < 0 ||
230 ifc.ifc_len < sizeof(struct ifreq)) {
231 err(FATAL, "init_all: SIOCGIFCONF: %s", strerror(errno));
232 /* NOTREACHED */
233 }
234 ifr = ifc.ifc_req;
235 for (i = 0; i < ifc.ifc_len;
236 i += len, ifr = (struct ifreq *)((caddr_t)ifr + len)) {
237 len = sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;
238 if (ioctl(fd, SIOCGIFFLAGS, (caddr_t)ifr) < 0) {
239 err(FATAL, "init_all: SIOCGIFFLAGS: %s",
240 strerror(errno));
241 /* NOTREACHED */
242 }
243 if ((ifr->ifr_flags &
244 (IFF_UP | IFF_LOOPBACK | IFF_POINTOPOINT)) != IFF_UP)
245 continue;
246 init_one(ifr->ifr_name);
247 }
248 (void) close(fd);
249 }
250
251 void
252 usage()
253 {
254 (void) fprintf(stderr, "usage: rarpd -a [ -d -f ]\n");
255 (void) fprintf(stderr, " rarpd [ -d -f ] interface\n");
256 exit(1);
257 }
258
259 static int
260 bpf_open()
261 {
262 int fd;
263 int n = 0;
264 char device[sizeof "/dev/bpf000"];
265
266 /* Go through all the minors and find one that isn't in use. */
267 do {
268 (void) sprintf(device, "/dev/bpf%d", n++);
269 fd = open(device, O_RDWR);
270 } while (fd < 0 && errno == EBUSY);
271
272 if (fd < 0) {
273 err(FATAL, "%s: %s", device, strerror(errno));
274 /* NOTREACHED */
275 }
276 return fd;
277 }
278 /*
279 * Open a BPF file and attach it to the interface named 'device'.
280 * Set immediate mode, and set a filter that accepts only RARP requests.
281 */
282 int
283 rarp_open(device)
284 char *device;
285 {
286 int fd;
287 struct ifreq ifr;
288 u_int dlt;
289 int immediate;
290
291 static struct bpf_insn insns[] = {
292 BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 12),
293 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ETHERTYPE_REVARP, 0, 3),
294 BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 20),
295 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ARPOP_REVREQUEST, 0, 1),
296 BPF_STMT(BPF_RET | BPF_K, sizeof(struct ether_arp) +
297 sizeof(struct ether_header)),
298 BPF_STMT(BPF_RET | BPF_K, 0),
299 };
300 static struct bpf_program filter = {
301 sizeof insns / sizeof(insns[0]),
302 insns
303 };
304
305 fd = bpf_open();
306
307 /* Set immediate mode so packets are processed as they arrive. */
308 immediate = 1;
309 if (ioctl(fd, BIOCIMMEDIATE, &immediate) < 0) {
310 err(FATAL, "BIOCIMMEDIATE: %s", strerror(errno));
311 /* NOTREACHED */
312 }
313 (void) strncpy(ifr.ifr_name, device, sizeof ifr.ifr_name);
314 if (ioctl(fd, BIOCSETIF, (caddr_t) & ifr) < 0) {
315 err(FATAL, "BIOCSETIF: %s", strerror(errno));
316 /* NOTREACHED */
317 }
318 /* Check that the data link layer is an Ethernet; this code won't work
319 * with anything else. */
320 if (ioctl(fd, BIOCGDLT, (caddr_t) & dlt) < 0) {
321 err(FATAL, "BIOCGDLT: %s", strerror(errno));
322 /* NOTREACHED */
323 }
324 if (dlt != DLT_EN10MB) {
325 err(FATAL, "%s is not an ethernet", device);
326 /* NOTREACHED */
327 }
328 /* Set filter program. */
329 if (ioctl(fd, BIOCSETF, (caddr_t) & filter) < 0) {
330 err(FATAL, "BIOCSETF: %s", strerror(errno));
331 /* NOTREACHED */
332 }
333 return fd;
334 }
335 /*
336 * Perform various sanity checks on the RARP request packet. Return
337 * false on failure and log the reason.
338 */
339 static int
340 rarp_check(p, len)
341 u_char *p;
342 int len;
343 {
344 struct ether_header *ep = (struct ether_header *) p;
345 struct ether_arp *ap = (struct ether_arp *) (p + sizeof(*ep));
346
347 (void) debug("got a packet");
348
349 if (len < sizeof(*ep) + sizeof(*ap)) {
350 err(NONFATAL, "truncated request");
351 return 0;
352 }
353 /* XXX This test might be better off broken out... */
354 if (ntohs (ep->ether_type) != ETHERTYPE_REVARP ||
355 ntohs (ap->arp_hrd) != ARPHRD_ETHER ||
356 ntohs (ap->arp_op) != ARPOP_REVREQUEST ||
357 ntohs (ap->arp_pro) != ETHERTYPE_IP ||
358 ap->arp_hln != 6 || ap->arp_pln != 4) {
359 err(NONFATAL, "request fails sanity check");
360 return 0;
361 }
362 if (bcmp((char *) &ep->ether_shost, (char *) &ap->arp_sha, 6) != 0) {
363 err(NONFATAL, "ether/arp sender address mismatch");
364 return 0;
365 }
366 if (bcmp((char *) &ap->arp_sha, (char *) &ap->arp_tha, 6) != 0) {
367 err(NONFATAL, "ether/arp target address mismatch");
368 return 0;
369 }
370 return 1;
371 }
372
373 /*
374 * Loop indefinitely listening for RARP requests on the
375 * interfaces in 'iflist'.
376 */
377 void
378 rarp_loop()
379 {
380 u_char *buf, *bp, *ep;
381 int cc, fd;
382 fd_set fds, listeners;
383 int bufsize, maxfd = 0;
384 struct if_info *ii;
385
386 if (iflist == 0) {
387 err(FATAL, "no interfaces");
388 /* NOTREACHED */
389 }
390 if (ioctl(iflist->ii_fd, BIOCGBLEN, (caddr_t) & bufsize) < 0) {
391 err(FATAL, "BIOCGBLEN: %s", strerror(errno));
392 /* NOTREACHED */
393 }
394 buf = (u_char *) malloc((unsigned) bufsize);
395 if (buf == 0) {
396 err(FATAL, "malloc: %s", strerror(errno));
397 /* NOTREACHED */
398 }
399 /*
400 * Find the highest numbered file descriptor for select().
401 * Initialize the set of descriptors to listen to.
402 */
403 FD_ZERO(&fds);
404 for (ii = iflist; ii; ii = ii->ii_next) {
405 FD_SET(ii->ii_fd, &fds);
406 if (ii->ii_fd > maxfd)
407 maxfd = ii->ii_fd;
408 }
409 while (1) {
410 listeners = fds;
411 if (select(maxfd + 1, &listeners, (struct fd_set *) 0,
412 (struct fd_set *) 0, (struct timeval *) 0) < 0) {
413 err(FATAL, "select: %s", strerror(errno));
414 /* NOTREACHED */
415 }
416 for (ii = iflist; ii; ii = ii->ii_next) {
417 fd = ii->ii_fd;
418 if (!FD_ISSET(fd, &listeners))
419 continue;
420 again:
421 cc = read(fd, (char *) buf, bufsize);
422 /* Don't choke when we get ptraced */
423 if (cc < 0 && errno == EINTR)
424 goto again;
425 /* Due to a SunOS bug, after 2^31 bytes, the file
426 * offset overflows and read fails with EINVAL. The
427 * lseek() to 0 will fix things. */
428 if (cc < 0) {
429 if (errno == EINVAL &&
430 (lseek(fd, 0, SEEK_CUR) + bufsize) < 0) {
431 (void) lseek(fd, 0, 0);
432 goto again;
433 }
434 err(FATAL, "read: %s", strerror(errno));
435 /* NOTREACHED */
436 }
437 /* Loop through the packet(s) */
438 #define bhp ((struct bpf_hdr *)bp)
439 bp = buf;
440 ep = bp + cc;
441 while (bp < ep) {
442 register int caplen, hdrlen;
443
444 caplen = bhp->bh_caplen;
445 hdrlen = bhp->bh_hdrlen;
446 if (rarp_check(bp + hdrlen, caplen))
447 rarp_process(ii, bp + hdrlen);
448 bp += BPF_WORDALIGN(hdrlen + caplen);
449 }
450 }
451 }
452 }
453
454 #ifdef REQUIRE_TFTPBOOT
455
456 #ifndef TFTP_DIR
457 #define TFTP_DIR "/tftpboot"
458 #endif
459
460 /*
461 * True if this server can boot the host whose IP address is 'addr'.
462 * This check is made by looking in the tftp directory for the
463 * configuration file.
464 */
465 int
466 rarp_bootable(addr)
467 u_long addr;
468 {
469 register struct dirent *dent;
470 register DIR *d;
471 char ipname[9];
472 static DIR *dd = 0;
473
474 (void) sprintf(ipname, "%08X", addr);
475 /* If directory is already open, rewind it. Otherwise, open it. */
476 if (d = dd)
477 rewinddir(d);
478 else {
479 if (chdir(TFTP_DIR) == -1) {
480 err(FATAL, "chdir: %s", strerror(errno));
481 /* NOTREACHED */
482 }
483 d = opendir(".");
484 if (d == 0) {
485 err(FATAL, "opendir: %s", strerror(errno));
486 /* NOTREACHED */
487 }
488 dd = d;
489 }
490 while (dent = readdir(d))
491 if (strncmp(dent->d_name, ipname, 8) == 0)
492 return 1;
493 return 0;
494 }
495 #endif /* REQUIRE_TFTPBOOT */
496
497 /*
498 * Given a list of IP addresses, 'alist', return the first address that
499 * is on network 'net'; 'netmask' is a mask indicating the network portion
500 * of the address.
501 */
502 u_long
503 choose_ipaddr(alist, net, netmask)
504 u_long **alist;
505 u_long net;
506 u_long netmask;
507 {
508 for (; *alist; ++alist) {
509 if ((**alist & netmask) == net)
510 return **alist;
511 }
512 return 0;
513 }
514 /*
515 * Answer the RARP request in 'pkt', on the interface 'ii'. 'pkt' has
516 * already been checked for validity. The reply is overlaid on the request.
517 */
518 void
519 rarp_process(ii, pkt)
520 struct if_info *ii;
521 u_char *pkt;
522 {
523 struct ether_header *ep;
524 struct hostent *hp;
525 u_long target_ipaddr;
526 char ename[256];
527 struct in_addr in;
528
529 ep = (struct ether_header *) pkt;
530
531 if (ether_ntohost(ename, &ep->ether_shost) != 0 ||
532 (hp = gethostbyname(ename)) == 0)
533 return;
534
535 /* Choose correct address from list. */
536 if (hp->h_addrtype != AF_INET) {
537 err(FATAL, "cannot handle non IP addresses");
538 /* NOTREACHED */
539 }
540 target_ipaddr = choose_ipaddr((u_long **) hp->h_addr_list,
541 ii->ii_ipaddr & ii->ii_netmask, ii->ii_netmask);
542
543 if (target_ipaddr == 0) {
544 in.s_addr = ii->ii_ipaddr & ii->ii_netmask;
545 err(NONFATAL, "cannot find %s on net %s\n",
546 ename, inet_ntoa(in));
547 return;
548 }
549 #ifdef REQUIRE_TFTPBOOT
550 if (rarp_bootable(htonl(target_ipaddr)))
551 #endif
552 rarp_reply(ii, ep, target_ipaddr);
553 }
554 /*
555 * Lookup the ethernet address of the interface attached to the BPF
556 * file descriptor 'fd'; return it in 'eaddr'.
557 */
558 void
559 lookup_eaddr(ifname, eaddr)
560 char *ifname;
561 u_char *eaddr;
562 {
563 char inbuf[8192];
564 struct ifconf ifc;
565 struct ifreq *ifr;
566 struct sockaddr_dl *sdl;
567 int fd;
568 int i, len;
569
570 /* We cannot use SIOCGIFADDR on the BPF descriptor.
571 We must instead get all the interfaces with SIOCGIFCONF
572 and find the right one. */
573
574 /* Use datagram socket to get Ethernet address. */
575 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
576 err(FATAL, "socket: %s", strerror(errno));
577 /* NOTREACHED */
578 }
579
580 ifc.ifc_len = sizeof(inbuf);
581 ifc.ifc_buf = inbuf;
582 if (ioctl(fd, SIOCGIFCONF, (caddr_t)&ifc) < 0 ||
583 ifc.ifc_len < sizeof(struct ifreq)) {
584 err(FATAL, "lookup_eaddr: SIOGIFCONF: %s", strerror(errno));
585 /* NOTREACHED */
586 }
587 ifr = ifc.ifc_req;
588 for (i = 0; i < ifc.ifc_len;
589 i += len, ifr = (struct ifreq *)((caddr_t)ifr + len)) {
590 len = sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;
591 sdl = (struct sockaddr_dl *)&ifr->ifr_addr;
592 if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER ||
593 sdl->sdl_alen != 6)
594 continue;
595 if (!strncmp(ifr->ifr_name, ifname, sizeof(ifr->ifr_name))) {
596 bcopy((caddr_t)LLADDR(sdl), (caddr_t)eaddr, 6);
597 if (dflag)
598 fprintf(stderr, "%s: %x:%x:%x:%x:%x:%x\n",
599 ifr->ifr_name, eaddr[0], eaddr[1],
600 eaddr[2], eaddr[3], eaddr[4], eaddr[5]);
601 return;
602 }
603 }
604
605 err(FATAL, "lookup_eaddr: Never saw interface `%s'!", ifname);
606 }
607 /*
608 * Lookup the IP address and network mask of the interface named 'ifname'.
609 */
610 void
611 lookup_ipaddr(ifname, addrp, netmaskp)
612 char *ifname;
613 u_long *addrp;
614 u_long *netmaskp;
615 {
616 int fd;
617 struct ifreq ifr;
618
619 /* Use datagram socket to get IP address. */
620 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
621 err(FATAL, "socket: %s", strerror(errno));
622 /* NOTREACHED */
623 }
624 (void) strncpy(ifr.ifr_name, ifname, sizeof ifr.ifr_name);
625 if (ioctl(fd, SIOCGIFADDR, (char *) &ifr) < 0) {
626 err(FATAL, "SIOCGIFADDR: %s", strerror(errno));
627 /* NOTREACHED */
628 }
629 *addrp = ((struct sockaddr_in *) & ifr.ifr_addr)->sin_addr.s_addr;
630 if (ioctl(fd, SIOCGIFNETMASK, (char *) &ifr) < 0) {
631 perror("SIOCGIFNETMASK");
632 exit(1);
633 }
634 *netmaskp = ((struct sockaddr_in *) & ifr.ifr_addr)->sin_addr.s_addr;
635 /* If SIOCGIFNETMASK didn't work, figure out a mask from the IP
636 * address class. */
637 if (*netmaskp == 0)
638 *netmaskp = ipaddrtonetmask(*addrp);
639
640 (void) close(fd);
641 }
642 /*
643 * Poke the kernel arp tables with the ethernet/ip address combinataion
644 * given. When processing a reply, we must do this so that the booting
645 * host (i.e. the guy running rarpd), won't try to ARP for the hardware
646 * address of the guy being booted (he cannot answer the ARP).
647 */
648 void
649 update_arptab(ep, ipaddr)
650 u_char *ep;
651 u_long ipaddr;
652 {
653 int s;
654 struct arpreq request;
655 struct sockaddr_in *sin;
656
657 request.arp_flags = 0;
658 sin = (struct sockaddr_in *) & request.arp_pa;
659 sin->sin_family = AF_INET;
660 sin->sin_addr.s_addr = ipaddr;
661 request.arp_ha.sa_family = AF_UNSPEC;
662 /* This is needed #if defined(COMPAT_43) && BYTE_ORDER != BIG_ENDIAN,
663 because AF_UNSPEC is zero and the kernel assumes that a zero
664 sa_family means that the real sa_family value is in sa_len. */
665 request.arp_ha.sa_len = 16; /* XXX */
666 bcopy((char *) ep, (char *) request.arp_ha.sa_data, 6);
667
668 #if 0
669 s = socket(AF_INET, SOCK_DGRAM, 0);
670 if (ioctl(s, SIOCSARP, (caddr_t) & request) < 0) {
671 err(NONFATAL, "SIOCSARP: %s", strerror(errno));
672 }
673 (void) close(s);
674 #endif
675 }
676 /*
677 * Build a reverse ARP packet and sent it out on the interface.
678 * 'ep' points to a valid ARPOP_REVREQUEST. The ARPOP_REVREPLY is built
679 * on top of the request, then written to the network.
680 *
681 * RFC 903 defines the ether_arp fields as follows. The following comments
682 * are taken (more or less) straight from this document.
683 *
684 * ARPOP_REVREQUEST
685 *
686 * arp_sha is the hardware address of the sender of the packet.
687 * arp_spa is undefined.
688 * arp_tha is the 'target' hardware address.
689 * In the case where the sender wishes to determine his own
690 * protocol address, this, like arp_sha, will be the hardware
691 * address of the sender.
692 * arp_tpa is undefined.
693 *
694 * ARPOP_REVREPLY
695 *
696 * arp_sha is the hardware address of the responder (the sender of the
697 * reply packet).
698 * arp_spa is the protocol address of the responder (see the note below).
699 * arp_tha is the hardware address of the target, and should be the same as
700 * that which was given in the request.
701 * arp_tpa is the protocol address of the target, that is, the desired address.
702 *
703 * Note that the requirement that arp_spa be filled in with the responder's
704 * protocol is purely for convenience. For instance, if a system were to use
705 * both ARP and RARP, then the inclusion of the valid protocol-hardware
706 * address pair (arp_spa, arp_sha) may eliminate the need for a subsequent
707 * ARP request.
708 */
709 void
710 rarp_reply(ii, ep, ipaddr)
711 struct if_info *ii;
712 struct ether_header *ep;
713 u_long ipaddr;
714 {
715 int n;
716 struct ether_arp *ap = (struct ether_arp *) (ep + 1);
717 int len;
718
719 update_arptab((u_char *) & ap->arp_sha, ipaddr);
720
721 /* Build the rarp reply by modifying the rarp request in place. */
722 ep->ether_type = htons(ETHERTYPE_REVARP);
723 ap->ea_hdr.ar_hrd = htons(ARPHRD_ETHER);
724 ap->ea_hdr.ar_pro = htons(ETHERTYPE_IP);
725 ap->arp_op = htons(ARPOP_REVREPLY);
726
727 bcopy((char *) &ap->arp_sha, (char *) &ep->ether_dhost, 6);
728 bcopy((char *) ii->ii_eaddr, (char *) &ep->ether_shost, 6);
729 bcopy((char *) ii->ii_eaddr, (char *) &ap->arp_sha, 6);
730
731 bcopy((char *) &ipaddr, (char *) ap->arp_tpa, 4);
732 /* Target hardware is unchanged. */
733 bcopy((char *) &ii->ii_ipaddr, (char *) ap->arp_spa, 4);
734
735 len = sizeof(*ep) + sizeof(*ap);
736 n = write(ii->ii_fd, (char *) ep, len);
737 if (n != len) {
738 err(NONFATAL, "write: only %d of %d bytes written", n, len);
739 }
740 }
741 /*
742 * Get the netmask of an IP address. This routine is used if
743 * SIOCGIFNETMASK doesn't work.
744 */
745 u_long
746 ipaddrtonetmask(addr)
747 u_long addr;
748 {
749 if (IN_CLASSA(addr))
750 return IN_CLASSA_NET;
751 if (IN_CLASSB(addr))
752 return IN_CLASSB_NET;
753 if (IN_CLASSC(addr))
754 return IN_CLASSC_NET;
755 err(FATAL, "unknown IP address class: %08X", addr);
756 /* NOTREACHED */
757 }
758
759 #if __STDC__
760 #include <stdarg.h>
761 #else
762 #include <varargs.h>
763 #endif
764
765 void
766 #if __STDC__
767 err(int fatal, const char *fmt,...)
768 #else
769 err(fmt, va_alist)
770 int fatal;
771 char *fmt;
772 va_dcl
773 #endif
774 {
775 va_list ap;
776 #if __STDC__
777 va_start(ap, fmt);
778 #else
779 va_start(ap);
780 #endif
781 if (dflag) {
782 if (fatal)
783 (void) fprintf(stderr, "rarpd: error: ");
784 else
785 (void) fprintf(stderr, "rarpd: warning: ");
786 (void) vfprintf(stderr, fmt, ap);
787 (void) fprintf(stderr, "\n");
788 }
789 vsyslog(LOG_ERR, fmt, ap);
790 va_end(ap);
791 if (fatal)
792 exit(1);
793 /* NOTREACHED */
794 }
795
796 void
797 #if __STDC__
798 debug(const char *fmt,...)
799 #else
800 debug(fmt, va_alist)
801 char *fmt;
802 va_dcl
803 #endif
804 {
805 va_list ap;
806
807 if (dflag) {
808 #if __STDC__
809 va_start(ap, fmt);
810 #else
811 va_start(ap);
812 #endif
813 (void) fprintf(stderr, "rarpd: ");
814 (void) vfprintf(stderr, fmt, ap);
815 va_end(ap);
816 (void) fprintf(stderr, "\n");
817 }
818 }
819