rarpd.c revision 1.8.2.1 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.2.1 1996/02/23 23:41:22 hpeyerl 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 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 ifreq.ifr_name[0] = '\0';
236 for (i = 0; i < ifc.ifc_len;
237 i += len, ifr = (struct ifreq *)((caddr_t)ifr + len)) {
238 len = sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;
239 if (!strncmp(ifreq.ifr_name, ifr->ifr_name, sizeof(ifr->ifr_name)))
240 continue;
241 ifreq = *ifr;
242 if (ioctl(fd, SIOCGIFFLAGS, (caddr_t)ifr) < 0) {
243 err(FATAL, "init_all: SIOCGIFFLAGS: %s",
244 strerror(errno));
245 /* NOTREACHED */
246 }
247 if ((ifr->ifr_flags &
248 (IFF_UP | IFF_LOOPBACK | IFF_POINTOPOINT)) != IFF_UP)
249 continue;
250 init_one(ifr->ifr_name);
251 }
252 (void) close(fd);
253 }
254
255 void
256 usage()
257 {
258 (void) fprintf(stderr, "usage: rarpd -a [ -d -f ]\n");
259 (void) fprintf(stderr, " rarpd [ -d -f ] interface\n");
260 exit(1);
261 }
262
263 static int
264 bpf_open()
265 {
266 int fd;
267 int n = 0;
268 char device[sizeof "/dev/bpf000"];
269
270 /* Go through all the minors and find one that isn't in use. */
271 do {
272 (void) sprintf(device, "/dev/bpf%d", n++);
273 fd = open(device, O_RDWR);
274 } while (fd < 0 && errno == EBUSY);
275
276 if (fd < 0) {
277 err(FATAL, "%s: %s", device, strerror(errno));
278 /* NOTREACHED */
279 }
280 return fd;
281 }
282 /*
283 * Open a BPF file and attach it to the interface named 'device'.
284 * Set immediate mode, and set a filter that accepts only RARP requests.
285 */
286 int
287 rarp_open(device)
288 char *device;
289 {
290 int fd;
291 struct ifreq ifr;
292 u_int dlt;
293 int immediate;
294
295 static struct bpf_insn insns[] = {
296 BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 12),
297 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ETHERTYPE_REVARP, 0, 3),
298 BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 20),
299 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ARPOP_REVREQUEST, 0, 1),
300 BPF_STMT(BPF_RET | BPF_K, sizeof(struct ether_arp) +
301 sizeof(struct ether_header)),
302 BPF_STMT(BPF_RET | BPF_K, 0),
303 };
304 static struct bpf_program filter = {
305 sizeof insns / sizeof(insns[0]),
306 insns
307 };
308
309 fd = bpf_open();
310
311 /* Set immediate mode so packets are processed as they arrive. */
312 immediate = 1;
313 if (ioctl(fd, BIOCIMMEDIATE, &immediate) < 0) {
314 err(FATAL, "BIOCIMMEDIATE: %s", strerror(errno));
315 /* NOTREACHED */
316 }
317 (void) strncpy(ifr.ifr_name, device, sizeof ifr.ifr_name);
318 if (ioctl(fd, BIOCSETIF, (caddr_t) & ifr) < 0) {
319 err(FATAL, "BIOCSETIF: %s", strerror(errno));
320 /* NOTREACHED */
321 }
322 /* Check that the data link layer is an Ethernet; this code won't work
323 * with anything else. */
324 if (ioctl(fd, BIOCGDLT, (caddr_t) & dlt) < 0) {
325 err(FATAL, "BIOCGDLT: %s", strerror(errno));
326 /* NOTREACHED */
327 }
328 if (dlt != DLT_EN10MB) {
329 err(FATAL, "%s is not an ethernet", device);
330 /* NOTREACHED */
331 }
332 /* Set filter program. */
333 if (ioctl(fd, BIOCSETF, (caddr_t) & filter) < 0) {
334 err(FATAL, "BIOCSETF: %s", strerror(errno));
335 /* NOTREACHED */
336 }
337 return fd;
338 }
339 /*
340 * Perform various sanity checks on the RARP request packet. Return
341 * false on failure and log the reason.
342 */
343 static int
344 rarp_check(p, len)
345 u_char *p;
346 int len;
347 {
348 struct ether_header *ep = (struct ether_header *) p;
349 struct ether_arp *ap = (struct ether_arp *) (p + sizeof(*ep));
350
351 (void) debug("got a packet");
352
353 if (len < sizeof(*ep) + sizeof(*ap)) {
354 err(NONFATAL, "truncated request");
355 return 0;
356 }
357 /* XXX This test might be better off broken out... */
358 if (ntohs (ep->ether_type) != ETHERTYPE_REVARP ||
359 ntohs (ap->arp_hrd) != ARPHRD_ETHER ||
360 ntohs (ap->arp_op) != ARPOP_REVREQUEST ||
361 ntohs (ap->arp_pro) != ETHERTYPE_IP ||
362 ap->arp_hln != 6 || ap->arp_pln != 4) {
363 err(NONFATAL, "request fails sanity check");
364 return 0;
365 }
366 if (bcmp((char *) &ep->ether_shost, (char *) &ap->arp_sha, 6) != 0) {
367 err(NONFATAL, "ether/arp sender address mismatch");
368 return 0;
369 }
370 if (bcmp((char *) &ap->arp_sha, (char *) &ap->arp_tha, 6) != 0) {
371 err(NONFATAL, "ether/arp target address mismatch");
372 return 0;
373 }
374 return 1;
375 }
376
377 /*
378 * Loop indefinitely listening for RARP requests on the
379 * interfaces in 'iflist'.
380 */
381 void
382 rarp_loop()
383 {
384 u_char *buf, *bp, *ep;
385 int cc, fd;
386 fd_set fds, listeners;
387 int bufsize, maxfd = 0;
388 struct if_info *ii;
389
390 if (iflist == 0) {
391 err(FATAL, "no interfaces");
392 /* NOTREACHED */
393 }
394 if (ioctl(iflist->ii_fd, BIOCGBLEN, (caddr_t) & bufsize) < 0) {
395 err(FATAL, "BIOCGBLEN: %s", strerror(errno));
396 /* NOTREACHED */
397 }
398 buf = (u_char *) malloc((unsigned) bufsize);
399 if (buf == 0) {
400 err(FATAL, "malloc: %s", strerror(errno));
401 /* NOTREACHED */
402 }
403 /*
404 * Find the highest numbered file descriptor for select().
405 * Initialize the set of descriptors to listen to.
406 */
407 FD_ZERO(&fds);
408 for (ii = iflist; ii; ii = ii->ii_next) {
409 FD_SET(ii->ii_fd, &fds);
410 if (ii->ii_fd > maxfd)
411 maxfd = ii->ii_fd;
412 }
413 while (1) {
414 listeners = fds;
415 if (select(maxfd + 1, &listeners, (struct fd_set *) 0,
416 (struct fd_set *) 0, (struct timeval *) 0) < 0) {
417 err(FATAL, "select: %s", strerror(errno));
418 /* NOTREACHED */
419 }
420 for (ii = iflist; ii; ii = ii->ii_next) {
421 fd = ii->ii_fd;
422 if (!FD_ISSET(fd, &listeners))
423 continue;
424 again:
425 cc = read(fd, (char *) buf, bufsize);
426 /* Don't choke when we get ptraced */
427 if (cc < 0 && errno == EINTR)
428 goto again;
429 /* Due to a SunOS bug, after 2^31 bytes, the file
430 * offset overflows and read fails with EINVAL. The
431 * lseek() to 0 will fix things. */
432 if (cc < 0) {
433 if (errno == EINVAL &&
434 (lseek(fd, 0, SEEK_CUR) + bufsize) < 0) {
435 (void) lseek(fd, 0, 0);
436 goto again;
437 }
438 err(FATAL, "read: %s", strerror(errno));
439 /* NOTREACHED */
440 }
441 /* Loop through the packet(s) */
442 #define bhp ((struct bpf_hdr *)bp)
443 bp = buf;
444 ep = bp + cc;
445 while (bp < ep) {
446 register int caplen, hdrlen;
447
448 caplen = bhp->bh_caplen;
449 hdrlen = bhp->bh_hdrlen;
450 if (rarp_check(bp + hdrlen, caplen))
451 rarp_process(ii, bp + hdrlen);
452 bp += BPF_WORDALIGN(hdrlen + caplen);
453 }
454 }
455 }
456 }
457
458 #ifdef REQUIRE_TFTPBOOT
459
460 #ifndef TFTP_DIR
461 #define TFTP_DIR "/tftpboot"
462 #endif
463
464 /*
465 * True if this server can boot the host whose IP address is 'addr'.
466 * This check is made by looking in the tftp directory for the
467 * configuration file.
468 */
469 int
470 rarp_bootable(addr)
471 u_long addr;
472 {
473 register struct dirent *dent;
474 register DIR *d;
475 char ipname[9];
476 static DIR *dd = 0;
477
478 (void) sprintf(ipname, "%08X", addr);
479 /* If directory is already open, rewind it. Otherwise, open it. */
480 if (d = dd)
481 rewinddir(d);
482 else {
483 if (chdir(TFTP_DIR) == -1) {
484 err(FATAL, "chdir: %s", strerror(errno));
485 /* NOTREACHED */
486 }
487 d = opendir(".");
488 if (d == 0) {
489 err(FATAL, "opendir: %s", strerror(errno));
490 /* NOTREACHED */
491 }
492 dd = d;
493 }
494 while (dent = readdir(d))
495 if (strncmp(dent->d_name, ipname, 8) == 0)
496 return 1;
497 return 0;
498 }
499 #endif /* REQUIRE_TFTPBOOT */
500
501 /*
502 * Given a list of IP addresses, 'alist', return the first address that
503 * is on network 'net'; 'netmask' is a mask indicating the network portion
504 * of the address.
505 */
506 u_long
507 choose_ipaddr(alist, net, netmask)
508 u_long **alist;
509 u_long net;
510 u_long netmask;
511 {
512 for (; *alist; ++alist) {
513 if ((**alist & netmask) == net)
514 return **alist;
515 }
516 return 0;
517 }
518 /*
519 * Answer the RARP request in 'pkt', on the interface 'ii'. 'pkt' has
520 * already been checked for validity. The reply is overlaid on the request.
521 */
522 void
523 rarp_process(ii, pkt)
524 struct if_info *ii;
525 u_char *pkt;
526 {
527 struct ether_header *ep;
528 struct hostent *hp;
529 u_long target_ipaddr;
530 char ename[256];
531 struct in_addr in;
532
533 ep = (struct ether_header *) pkt;
534
535 if (ether_ntohost(ename, &ep->ether_shost) != 0 ||
536 (hp = gethostbyname(ename)) == 0)
537 return;
538
539 /* Choose correct address from list. */
540 if (hp->h_addrtype != AF_INET) {
541 err(FATAL, "cannot handle non IP addresses");
542 /* NOTREACHED */
543 }
544 target_ipaddr = choose_ipaddr((u_long **) hp->h_addr_list,
545 ii->ii_ipaddr & ii->ii_netmask, ii->ii_netmask);
546
547 if (target_ipaddr == 0) {
548 in.s_addr = ii->ii_ipaddr & ii->ii_netmask;
549 err(NONFATAL, "cannot find %s on net %s\n",
550 ename, inet_ntoa(in));
551 return;
552 }
553 #ifdef REQUIRE_TFTPBOOT
554 if (rarp_bootable(htonl(target_ipaddr)))
555 #endif
556 rarp_reply(ii, ep, target_ipaddr);
557 }
558 /*
559 * Lookup the ethernet address of the interface attached to the BPF
560 * file descriptor 'fd'; return it in 'eaddr'.
561 */
562 void
563 lookup_eaddr(ifname, eaddr)
564 char *ifname;
565 u_char *eaddr;
566 {
567 char inbuf[8192];
568 struct ifconf ifc;
569 struct ifreq *ifr;
570 struct sockaddr_dl *sdl;
571 int fd;
572 int i, len;
573
574 /* We cannot use SIOCGIFADDR on the BPF descriptor.
575 We must instead get all the interfaces with SIOCGIFCONF
576 and find the right one. */
577
578 /* Use datagram socket to get Ethernet address. */
579 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
580 err(FATAL, "socket: %s", strerror(errno));
581 /* NOTREACHED */
582 }
583
584 ifc.ifc_len = sizeof(inbuf);
585 ifc.ifc_buf = inbuf;
586 if (ioctl(fd, SIOCGIFCONF, (caddr_t)&ifc) < 0 ||
587 ifc.ifc_len < sizeof(struct ifreq)) {
588 err(FATAL, "lookup_eaddr: SIOGIFCONF: %s", strerror(errno));
589 /* NOTREACHED */
590 }
591 ifr = ifc.ifc_req;
592 for (i = 0; i < ifc.ifc_len;
593 i += len, ifr = (struct ifreq *)((caddr_t)ifr + len)) {
594 len = sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;
595 sdl = (struct sockaddr_dl *)&ifr->ifr_addr;
596 if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER ||
597 sdl->sdl_alen != 6)
598 continue;
599 if (!strncmp(ifr->ifr_name, ifname, sizeof(ifr->ifr_name))) {
600 bcopy((caddr_t)LLADDR(sdl), (caddr_t)eaddr, 6);
601 if (dflag)
602 fprintf(stderr, "%s: %x:%x:%x:%x:%x:%x\n",
603 ifr->ifr_name, eaddr[0], eaddr[1],
604 eaddr[2], eaddr[3], eaddr[4], eaddr[5]);
605 return;
606 }
607 }
608
609 err(FATAL, "lookup_eaddr: Never saw interface `%s'!", ifname);
610 }
611 /*
612 * Lookup the IP address and network mask of the interface named 'ifname'.
613 */
614 void
615 lookup_ipaddr(ifname, addrp, netmaskp)
616 char *ifname;
617 u_long *addrp;
618 u_long *netmaskp;
619 {
620 int fd;
621 struct ifreq ifr;
622
623 /* Use datagram socket to get IP address. */
624 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
625 err(FATAL, "socket: %s", strerror(errno));
626 /* NOTREACHED */
627 }
628 (void) strncpy(ifr.ifr_name, ifname, sizeof ifr.ifr_name);
629 if (ioctl(fd, SIOCGIFADDR, (char *) &ifr) < 0) {
630 err(FATAL, "SIOCGIFADDR: %s", strerror(errno));
631 /* NOTREACHED */
632 }
633 *addrp = ((struct sockaddr_in *) & ifr.ifr_addr)->sin_addr.s_addr;
634 if (ioctl(fd, SIOCGIFNETMASK, (char *) &ifr) < 0) {
635 perror("SIOCGIFNETMASK");
636 exit(1);
637 }
638 *netmaskp = ((struct sockaddr_in *) & ifr.ifr_addr)->sin_addr.s_addr;
639 /* If SIOCGIFNETMASK didn't work, figure out a mask from the IP
640 * address class. */
641 if (*netmaskp == 0)
642 *netmaskp = ipaddrtonetmask(*addrp);
643
644 (void) close(fd);
645 }
646 /*
647 * Poke the kernel arp tables with the ethernet/ip address combinataion
648 * given. When processing a reply, we must do this so that the booting
649 * host (i.e. the guy running rarpd), won't try to ARP for the hardware
650 * address of the guy being booted (he cannot answer the ARP).
651 */
652 void
653 update_arptab(ep, ipaddr)
654 u_char *ep;
655 u_long ipaddr;
656 {
657 int s;
658 struct arpreq request;
659 struct sockaddr_in *sin;
660
661 request.arp_flags = 0;
662 sin = (struct sockaddr_in *) & request.arp_pa;
663 sin->sin_family = AF_INET;
664 sin->sin_addr.s_addr = ipaddr;
665 request.arp_ha.sa_family = AF_UNSPEC;
666 /* This is needed #if defined(COMPAT_43) && BYTE_ORDER != BIG_ENDIAN,
667 because AF_UNSPEC is zero and the kernel assumes that a zero
668 sa_family means that the real sa_family value is in sa_len. */
669 request.arp_ha.sa_len = 16; /* XXX */
670 bcopy((char *) ep, (char *) request.arp_ha.sa_data, 6);
671
672 #if 0
673 s = socket(AF_INET, SOCK_DGRAM, 0);
674 if (ioctl(s, SIOCSARP, (caddr_t) & request) < 0) {
675 err(NONFATAL, "SIOCSARP: %s", strerror(errno));
676 }
677 (void) close(s);
678 #endif
679 }
680 /*
681 * Build a reverse ARP packet and sent it out on the interface.
682 * 'ep' points to a valid ARPOP_REVREQUEST. The ARPOP_REVREPLY is built
683 * on top of the request, then written to the network.
684 *
685 * RFC 903 defines the ether_arp fields as follows. The following comments
686 * are taken (more or less) straight from this document.
687 *
688 * ARPOP_REVREQUEST
689 *
690 * arp_sha is the hardware address of the sender of the packet.
691 * arp_spa is undefined.
692 * arp_tha is the 'target' hardware address.
693 * In the case where the sender wishes to determine his own
694 * protocol address, this, like arp_sha, will be the hardware
695 * address of the sender.
696 * arp_tpa is undefined.
697 *
698 * ARPOP_REVREPLY
699 *
700 * arp_sha is the hardware address of the responder (the sender of the
701 * reply packet).
702 * arp_spa is the protocol address of the responder (see the note below).
703 * arp_tha is the hardware address of the target, and should be the same as
704 * that which was given in the request.
705 * arp_tpa is the protocol address of the target, that is, the desired address.
706 *
707 * Note that the requirement that arp_spa be filled in with the responder's
708 * protocol is purely for convenience. For instance, if a system were to use
709 * both ARP and RARP, then the inclusion of the valid protocol-hardware
710 * address pair (arp_spa, arp_sha) may eliminate the need for a subsequent
711 * ARP request.
712 */
713 void
714 rarp_reply(ii, ep, ipaddr)
715 struct if_info *ii;
716 struct ether_header *ep;
717 u_long ipaddr;
718 {
719 int n;
720 struct ether_arp *ap = (struct ether_arp *) (ep + 1);
721 int len;
722
723 update_arptab((u_char *) & ap->arp_sha, ipaddr);
724
725 /* Build the rarp reply by modifying the rarp request in place. */
726 ep->ether_type = htons(ETHERTYPE_REVARP);
727 ap->ea_hdr.ar_hrd = htons(ARPHRD_ETHER);
728 ap->ea_hdr.ar_pro = htons(ETHERTYPE_IP);
729 ap->arp_op = htons(ARPOP_REVREPLY);
730
731 bcopy((char *) &ap->arp_sha, (char *) &ep->ether_dhost, 6);
732 bcopy((char *) ii->ii_eaddr, (char *) &ep->ether_shost, 6);
733 bcopy((char *) ii->ii_eaddr, (char *) &ap->arp_sha, 6);
734
735 bcopy((char *) &ipaddr, (char *) ap->arp_tpa, 4);
736 /* Target hardware is unchanged. */
737 bcopy((char *) &ii->ii_ipaddr, (char *) ap->arp_spa, 4);
738
739 len = sizeof(*ep) + sizeof(*ap);
740 n = write(ii->ii_fd, (char *) ep, len);
741 if (n != len) {
742 err(NONFATAL, "write: only %d of %d bytes written", n, len);
743 }
744 }
745 /*
746 * Get the netmask of an IP address. This routine is used if
747 * SIOCGIFNETMASK doesn't work.
748 */
749 u_long
750 ipaddrtonetmask(addr)
751 u_long addr;
752 {
753 if (IN_CLASSA(addr))
754 return IN_CLASSA_NET;
755 if (IN_CLASSB(addr))
756 return IN_CLASSB_NET;
757 if (IN_CLASSC(addr))
758 return IN_CLASSC_NET;
759 err(FATAL, "unknown IP address class: %08X", addr);
760 /* NOTREACHED */
761 }
762
763 #if __STDC__
764 #include <stdarg.h>
765 #else
766 #include <varargs.h>
767 #endif
768
769 void
770 #if __STDC__
771 err(int fatal, const char *fmt,...)
772 #else
773 err(fmt, va_alist)
774 int fatal;
775 char *fmt;
776 va_dcl
777 #endif
778 {
779 va_list ap;
780 #if __STDC__
781 va_start(ap, fmt);
782 #else
783 va_start(ap);
784 #endif
785 if (dflag) {
786 if (fatal)
787 (void) fprintf(stderr, "rarpd: error: ");
788 else
789 (void) fprintf(stderr, "rarpd: warning: ");
790 (void) vfprintf(stderr, fmt, ap);
791 (void) fprintf(stderr, "\n");
792 }
793 vsyslog(LOG_ERR, fmt, ap);
794 va_end(ap);
795 if (fatal)
796 exit(1);
797 /* NOTREACHED */
798 }
799
800 void
801 #if __STDC__
802 debug(const char *fmt,...)
803 #else
804 debug(fmt, va_alist)
805 char *fmt;
806 va_dcl
807 #endif
808 {
809 va_list ap;
810
811 if (dflag) {
812 #if __STDC__
813 va_start(ap, fmt);
814 #else
815 va_start(ap);
816 #endif
817 (void) fprintf(stderr, "rarpd: ");
818 (void) vfprintf(stderr, fmt, ap);
819 va_end(ap);
820 (void) fprintf(stderr, "\n");
821 }
822 }
823