]>
git.saurik.com Git - apple/network_cmds.git/blob - rarpd.tproj/rarpd.c
02a08315afac16db80af878f333d6d48084f96d9
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * Copyright (c) 1990 The Regents of the University of California.
25 * All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that: (1) source code distributions
29 * retain the above copyright notice and this paragraph in its entirety, (2)
30 * distributions including binary code include the above copyright notice and
31 * this paragraph in its entirety in the documentation or other materials
32 * provided with the distribution, and (3) all advertising materials mentioning
33 * features or use of this software display the following acknowledgement:
34 * ``This product includes software developed by the University of California,
35 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
36 * the University nor the names of its contributors may be used to endorse
37 * or promote products derived from this software without specific prior
39 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
40 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
41 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
45 "@(#) Copyright (c) 1990 The Regents of the University of California.\n\
46 All rights reserved.\n";
51 "@(#) $Id: rarpd.c,v 1.1.1.1 1999/05/02 03:57:59 wsanchez Exp $";
56 * rarpd - Reverse ARP Daemon
58 * Usage: rarpd -a [ -d -f ]
59 * rarpd [ -d -f ] interface
67 #include <sys/types.h>
71 #include <sys/socket.h>
72 #include <sys/ioctl.h>
74 #include <net/if_dl.h>
75 #include <net/if_types.h>
76 #include <netinet/in.h>
77 #include <netinet/if_ether.h>
78 #include <sys/errno.h>
81 #include <arpa/inet.h>
84 #define FATAL 1 /* fatal error occurred */
85 #define NONFATAL 0 /* non fatal error occurred */
88 * The structure for each interface.
91 int ii_fd
; /* BPF file descriptor */
92 u_char ii_eaddr
[6]; /* Ethernet address of this interface */
93 u_long ii_ipaddr
; /* IP address of this interface */
94 u_long ii_netmask
; /* subnet or net mask */
95 struct if_info
*ii_next
;
98 * The list of all interfaces that are being listened to. rarp_loop()
99 * "selects" on the descriptors in this list.
101 struct if_info
*iflist
;
103 int rarp_open
__P((char *));
104 int rarp_bootable
__P((u_long
));
105 void init_one
__P((char *));
106 void init_all
__P((void));
107 void rarp_loop
__P((void));
108 void lookup_eaddr
__P((char *, u_char
*));
109 void lookup_ipaddr
__P((char *, u_long
*, u_long
*));
110 void usage
__P((void));
111 void rarp_process
__P((struct if_info
*, u_char
*));
112 void rarp_reply
__P((struct if_info
*, struct ether_header
*, u_long
));
113 void update_arptab
__P((u_char
*, u_long
));
114 void err
__P((int, const char *,...));
115 void debug
__P((const char *,...));
116 u_long ipaddrtonetmask
__P((u_long
));
118 int aflag
= 0; /* listen on "all" interfaces */
119 int dflag
= 0; /* print debugging messages */
120 int fflag
= 0; /* don't fork */
127 int op
, pid
, devnull
, f
;
128 char *ifname
, *hostname
, *name
;
131 extern int optind
, opterr
;
133 if (name
= strrchr(argv
[0], '/'))
140 /* All error reporting is done through syslogs. */
141 openlog(name
, LOG_PID
| LOG_CONS
, LOG_DAEMON
);
144 while ((op
= getopt(argc
, argv
, "adf")) != EOF
) {
163 ifname
= argv
[optind
++];
164 hostname
= ifname
? argv
[optind
] : 0;
165 if ((aflag
&& ifname
) || (!aflag
&& ifname
== 0))
173 if ((!fflag
) && (!dflag
)) {
176 /* Parent exits, leaving child in background. */
180 err(FATAL
, "cannot fork");
183 /* Fade into the background */
184 f
= open("/dev/tty", O_RDWR
);
186 if (ioctl(f
, TIOCNOTTY
, 0) < 0) {
187 err(FATAL
, "TIOCNOTTY: %s", strerror(errno
));
193 (void) setpgrp(0, getpid());
194 devnull
= open("/dev/null", O_RDWR
);
196 (void) dup2(devnull
, 0);
197 (void) dup2(devnull
, 1);
198 (void) dup2(devnull
, 2);
200 (void) close(devnull
);
206 * Add 'ifname' to the interface list. Lookup its IP address and network
207 * mask and Ethernet address, and open a BPF file for it.
215 p
= (struct if_info
*)malloc(sizeof(*p
));
217 err(FATAL
, "malloc: %s", strerror(errno
));
223 p
->ii_fd
= rarp_open(ifname
);
224 lookup_eaddr(ifname
, p
->ii_eaddr
);
225 lookup_ipaddr(ifname
, &p
->ii_ipaddr
, &p
->ii_netmask
);
228 * Initialize all "candidate" interfaces that are in the system
229 * configuration list. A "candidate" is up, not loopback and not
241 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
242 err(FATAL
, "socket: %s", strerror(errno
));
246 ifc
.ifc_len
= sizeof(inbuf
);
248 if (ioctl(fd
, SIOCGIFCONF
, (caddr_t
)&ifc
) < 0 ||
249 ifc
.ifc_len
< sizeof(struct ifreq
)) {
250 err(FATAL
, "init_all: SIOCGIFCONF: %s", strerror(errno
));
254 for (i
= 0; i
< ifc
.ifc_len
;
255 i
+= len
, ifr
= (struct ifreq
*)((caddr_t
)ifr
+ len
)) {
256 len
= sizeof(ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
;
257 if (ioctl(fd
, SIOCGIFFLAGS
, (caddr_t
)ifr
) < 0) {
258 err(FATAL
, "init_all: SIOCGIFFLAGS: %s",
262 if ((ifr
->ifr_flags
&
263 (IFF_UP
| IFF_LOOPBACK
| IFF_POINTOPOINT
)) != IFF_UP
)
265 init_one(ifr
->ifr_name
);
273 (void) fprintf(stderr
, "usage: rarpd -a [ -d -f ]\n");
274 (void) fprintf(stderr
, " rarpd [ -d -f ] interface\n");
283 char device
[sizeof "/dev/bpf000"];
285 /* Go through all the minors and find one that isn't in use. */
287 (void) sprintf(device
, "/dev/bpf%d", n
++);
288 fd
= open(device
, O_RDWR
);
289 } while (fd
< 0 && errno
== EBUSY
);
292 err(FATAL
, "%s: %s", device
, strerror(errno
));
298 * Open a BPF file and attach it to the interface named 'device'.
299 * Set immediate mode, and set a filter that accepts only RARP requests.
310 static struct bpf_insn insns
[] = {
311 BPF_STMT(BPF_LD
| BPF_H
| BPF_ABS
, 12),
312 BPF_JUMP(BPF_JMP
| BPF_JEQ
| BPF_K
, ETHERTYPE_REVARP
, 0, 3),
313 BPF_STMT(BPF_LD
| BPF_H
| BPF_ABS
, 20),
314 BPF_JUMP(BPF_JMP
| BPF_JEQ
| BPF_K
, ARPOP_REVREQUEST
, 0, 1),
315 BPF_STMT(BPF_RET
| BPF_K
, sizeof(struct ether_arp
) +
316 sizeof(struct ether_header
)),
317 BPF_STMT(BPF_RET
| BPF_K
, 0),
319 static struct bpf_program filter
= {
320 sizeof insns
/ sizeof(insns
[0]),
326 /* Set immediate mode so packets are processed as they arrive. */
328 if (ioctl(fd
, BIOCIMMEDIATE
, &immediate
) < 0) {
329 err(FATAL
, "BIOCIMMEDIATE: %s", strerror(errno
));
332 (void) strncpy(ifr
.ifr_name
, device
, sizeof ifr
.ifr_name
);
333 if (ioctl(fd
, BIOCSETIF
, (caddr_t
) & ifr
) < 0) {
334 err(FATAL
, "BIOCSETIF: %s", strerror(errno
));
337 /* Check that the data link layer is an Ethernet; this code won't work
338 * with anything else. */
339 if (ioctl(fd
, BIOCGDLT
, (caddr_t
) & dlt
) < 0) {
340 err(FATAL
, "BIOCGDLT: %s", strerror(errno
));
343 if (dlt
!= DLT_EN10MB
) {
344 err(FATAL
, "%s is not an ethernet", device
);
347 /* Set filter program. */
348 if (ioctl(fd
, BIOCSETF
, (caddr_t
) & filter
) < 0) {
349 err(FATAL
, "BIOCSETF: %s", strerror(errno
));
355 * Perform various sanity checks on the RARP request packet. Return
356 * false on failure and log the reason.
363 struct ether_header
*ep
= (struct ether_header
*) p
;
364 struct ether_arp
*ap
= (struct ether_arp
*) (p
+ sizeof(*ep
));
366 (void) debug("got a packet");
368 if (len
< sizeof(*ep
) + sizeof(*ap
)) {
369 err(NONFATAL
, "truncated request");
372 /* XXX This test might be better off broken out... */
373 if (ntohs (ep
->ether_type
) != ETHERTYPE_REVARP
||
374 ntohs (ap
->arp_hrd
) != ARPHRD_ETHER
||
375 ntohs (ap
->arp_op
) != ARPOP_REVREQUEST
||
376 ntohs (ap
->arp_pro
) != ETHERTYPE_IP
||
377 ap
->arp_hln
!= 6 || ap
->arp_pln
!= 4) {
378 err(NONFATAL
, "request fails sanity check");
381 if (bcmp((char *) &ep
->ether_shost
, (char *) &ap
->arp_sha
, 6) != 0) {
382 err(NONFATAL
, "ether/arp sender address mismatch");
385 if (bcmp((char *) &ap
->arp_sha
, (char *) &ap
->arp_tha
, 6) != 0) {
386 err(NONFATAL
, "ether/arp target address mismatch");
393 * Loop indefinitely listening for RARP requests on the
394 * interfaces in 'iflist'.
399 u_char
*buf
, *bp
, *ep
;
401 fd_set fds
, listeners
;
402 int bufsize
, maxfd
= 0;
406 err(FATAL
, "no interfaces");
409 if (ioctl(iflist
->ii_fd
, BIOCGBLEN
, (caddr_t
) & bufsize
) < 0) {
410 err(FATAL
, "BIOCGBLEN: %s", strerror(errno
));
413 buf
= (u_char
*) malloc((unsigned) bufsize
);
415 err(FATAL
, "malloc: %s", strerror(errno
));
419 * Find the highest numbered file descriptor for select().
420 * Initialize the set of descriptors to listen to.
423 for (ii
= iflist
; ii
; ii
= ii
->ii_next
) {
424 FD_SET(ii
->ii_fd
, &fds
);
425 if (ii
->ii_fd
> maxfd
)
430 if (select(maxfd
+ 1, &listeners
, (struct fd_set
*) 0,
431 (struct fd_set
*) 0, (struct timeval
*) 0) < 0) {
432 err(FATAL
, "select: %s", strerror(errno
));
435 for (ii
= iflist
; ii
; ii
= ii
->ii_next
) {
437 if (!FD_ISSET(fd
, &listeners
))
440 cc
= read(fd
, (char *) buf
, bufsize
);
441 /* Don't choke when we get ptraced */
442 if (cc
< 0 && errno
== EINTR
)
444 /* Due to a SunOS bug, after 2^31 bytes, the file
445 * offset overflows and read fails with EINVAL. The
446 * lseek() to 0 will fix things. */
448 if (errno
== EINVAL
&&
449 (lseek(fd
, 0, SEEK_CUR
) + bufsize
) < 0) {
450 (void) lseek(fd
, 0, 0);
453 err(FATAL
, "read: %s", strerror(errno
));
456 /* Loop through the packet(s) */
457 #define bhp ((struct bpf_hdr *)bp)
461 register int caplen
, hdrlen
;
463 caplen
= bhp
->bh_caplen
;
464 hdrlen
= bhp
->bh_hdrlen
;
465 if (rarp_check(bp
+ hdrlen
, caplen
))
466 rarp_process(ii
, bp
+ hdrlen
);
467 bp
+= BPF_WORDALIGN(hdrlen
+ caplen
);
473 #define TFTP_DIR "/tftpboot"
477 * True if this server can boot the host whose IP address is 'addr'.
478 * This check is made by looking in the tftp directory for the
479 * configuration file.
485 register struct dirent
*dent
;
490 (void) sprintf(ipname
, "%08X", addr
);
491 /* If directory is already open, rewind it. Otherwise, open it. */
495 if (chdir(TFTP_DIR
) == -1) {
496 err(FATAL
, "chdir: %s", strerror(errno
));
501 err(FATAL
, "opendir: %s", strerror(errno
));
506 while (dent
= readdir(d
))
507 if (strncmp(dent
->d_name
, ipname
, 8) == 0)
512 * Given a list of IP addresses, 'alist', return the first address that
513 * is on network 'net'; 'netmask' is a mask indicating the network portion
517 choose_ipaddr(alist
, net
, netmask
)
522 for (; *alist
; ++alist
) {
523 if ((**alist
& netmask
) == net
)
529 * Answer the RARP request in 'pkt', on the interface 'ii'. 'pkt' has
530 * already been checked for validity. The reply is overlaid on the request.
533 rarp_process(ii
, pkt
)
537 struct ether_header
*ep
;
539 u_long target_ipaddr
;
543 ep
= (struct ether_header
*) pkt
;
545 if (ether_ntohost(ename
, &ep
->ether_shost
) != 0 ||
546 (hp
= gethostbyname(ename
)) == 0)
549 /* Choose correct address from list. */
550 if (hp
->h_addrtype
!= AF_INET
) {
551 err(FATAL
, "cannot handle non IP addresses");
554 target_ipaddr
= choose_ipaddr((u_long
**) hp
->h_addr_list
,
555 ii
->ii_ipaddr
& ii
->ii_netmask
, ii
->ii_netmask
);
557 if (target_ipaddr
== 0) {
558 in
.s_addr
= ii
->ii_ipaddr
& ii
->ii_netmask
;
559 err(NONFATAL
, "cannot find %s on net %s\n",
560 ename
, inet_ntoa(in
));
563 if (rarp_bootable(htonl(target_ipaddr
)))
564 rarp_reply(ii
, ep
, target_ipaddr
);
567 * Lookup the ethernet address of the interface attached to the BPF
568 * file descriptor 'fd'; return it in 'eaddr'.
571 lookup_eaddr(ifname
, eaddr
)
578 struct sockaddr_dl
*sdl
;
582 /* We cannot use SIOCGIFADDR on the BPF descriptor.
583 We must instead get all the interfaces with SIOCGIFCONF
584 and find the right one. */
586 /* Use datagram socket to get Ethernet address. */
587 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
588 err(FATAL
, "socket: %s", strerror(errno
));
592 ifc
.ifc_len
= sizeof(inbuf
);
594 if (ioctl(fd
, SIOCGIFCONF
, (caddr_t
)&ifc
) < 0 ||
595 ifc
.ifc_len
< sizeof(struct ifreq
)) {
596 err(FATAL
, "lookup_eaddr: SIOGIFCONF: %s", strerror(errno
));
600 for (i
= 0; i
< ifc
.ifc_len
;
601 i
+= len
, ifr
= (struct ifreq
*)((caddr_t
)ifr
+ len
)) {
602 len
= sizeof(ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
;
603 sdl
= (struct sockaddr_dl
*)&ifr
->ifr_addr
;
604 if (sdl
->sdl_family
!= AF_LINK
|| sdl
->sdl_type
!= IFT_ETHER
||
607 if (!strncmp(ifr
->ifr_name
, ifname
, sizeof(ifr
->ifr_name
))) {
608 bcopy((caddr_t
)LLADDR(sdl
), (caddr_t
)eaddr
, 6);
610 fprintf(stderr
, "%s: %x:%x:%x:%x:%x:%x\n",
611 ifr
->ifr_name
, eaddr
[0], eaddr
[1],
612 eaddr
[2], eaddr
[3], eaddr
[4], eaddr
[5]);
617 err(FATAL
, "lookup_eaddr: Never saw interface `%s'!", ifname
);
620 * Lookup the IP address and network mask of the interface named 'ifname'.
623 lookup_ipaddr(ifname
, addrp
, netmaskp
)
631 /* Use datagram socket to get IP address. */
632 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
633 err(FATAL
, "socket: %s", strerror(errno
));
636 (void) strncpy(ifr
.ifr_name
, ifname
, sizeof ifr
.ifr_name
);
637 if (ioctl(fd
, SIOCGIFADDR
, (char *) &ifr
) < 0) {
638 err(FATAL
, "SIOCGIFADDR: %s", strerror(errno
));
641 *addrp
= ((struct sockaddr_in
*) & ifr
.ifr_addr
)->sin_addr
.s_addr
;
642 if (ioctl(fd
, SIOCGIFNETMASK
, (char *) &ifr
) < 0) {
643 perror("SIOCGIFNETMASK");
646 *netmaskp
= ((struct sockaddr_in
*) & ifr
.ifr_addr
)->sin_addr
.s_addr
;
647 /* If SIOCGIFNETMASK didn't work, figure out a mask from the IP
650 *netmaskp
= ipaddrtonetmask(*addrp
);
655 * Poke the kernel arp tables with the ethernet/ip address combinataion
656 * given. When processing a reply, we must do this so that the booting
657 * host (i.e. the guy running rarpd), won't try to ARP for the hardware
658 * address of the guy being booted (he cannot answer the ARP).
661 update_arptab(ep
, ipaddr
)
666 struct arpreq request
;
667 struct sockaddr_in
*sin
;
669 request
.arp_flags
= 0;
670 sin
= (struct sockaddr_in
*) & request
.arp_pa
;
671 sin
->sin_family
= AF_INET
;
672 sin
->sin_addr
.s_addr
= ipaddr
;
673 request
.arp_ha
.sa_family
= AF_UNSPEC
;
674 /* This is needed #if defined(COMPAT_43) && BYTE_ORDER != BIG_ENDIAN,
675 because AF_UNSPEC is zero and the kernel assumes that a zero
676 sa_family means that the real sa_family value is in sa_len. */
677 request
.arp_ha
.sa_len
= 16; /* XXX */
678 bcopy((char *) ep
, (char *) request
.arp_ha
.sa_data
, 6);
681 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
682 if (ioctl(s
, SIOCSARP
, (caddr_t
) & request
) < 0) {
683 err(NONFATAL
, "SIOCSARP: %s", strerror(errno
));
689 * Build a reverse ARP packet and sent it out on the interface.
690 * 'ep' points to a valid ARPOP_REVREQUEST. The ARPOP_REVREPLY is built
691 * on top of the request, then written to the network.
693 * RFC 903 defines the ether_arp fields as follows. The following comments
694 * are taken (more or less) straight from this document.
698 * arp_sha is the hardware address of the sender of the packet.
699 * arp_spa is undefined.
700 * arp_tha is the 'target' hardware address.
701 * In the case where the sender wishes to determine his own
702 * protocol address, this, like arp_sha, will be the hardware
703 * address of the sender.
704 * arp_tpa is undefined.
708 * arp_sha is the hardware address of the responder (the sender of the
710 * arp_spa is the protocol address of the responder (see the note below).
711 * arp_tha is the hardware address of the target, and should be the same as
712 * that which was given in the request.
713 * arp_tpa is the protocol address of the target, that is, the desired address.
715 * Note that the requirement that arp_spa be filled in with the responder's
716 * protocol is purely for convenience. For instance, if a system were to use
717 * both ARP and RARP, then the inclusion of the valid protocol-hardware
718 * address pair (arp_spa, arp_sha) may eliminate the need for a subsequent
722 rarp_reply(ii
, ep
, ipaddr
)
724 struct ether_header
*ep
;
728 struct ether_arp
*ap
= (struct ether_arp
*) (ep
+ 1);
731 update_arptab((u_char
*) & ap
->arp_sha
, ipaddr
);
733 /* Build the rarp reply by modifying the rarp request in place. */
734 ep
->ether_type
= htons(ETHERTYPE_REVARP
);
735 ap
->ea_hdr
.ar_hrd
= htons(ARPHRD_ETHER
);
736 ap
->ea_hdr
.ar_pro
= htons(ETHERTYPE_IP
);
737 ap
->arp_op
= htons(ARPOP_REVREPLY
);
739 bcopy((char *) &ap
->arp_sha
, (char *) &ep
->ether_dhost
, 6);
740 bcopy((char *) ii
->ii_eaddr
, (char *) &ep
->ether_shost
, 6);
741 bcopy((char *) ii
->ii_eaddr
, (char *) &ap
->arp_sha
, 6);
743 bcopy((char *) &ipaddr
, (char *) ap
->arp_tpa
, 4);
744 /* Target hardware is unchanged. */
745 bcopy((char *) &ii
->ii_ipaddr
, (char *) ap
->arp_spa
, 4);
747 len
= sizeof(*ep
) + sizeof(*ap
);
748 n
= write(ii
->ii_fd
, (char *) ep
, len
);
750 err(NONFATAL
, "write: only %d of %d bytes written", n
, len
);
754 * Get the netmask of an IP address. This routine is used if
755 * SIOCGIFNETMASK doesn't work.
758 ipaddrtonetmask(addr
)
762 return IN_CLASSA_NET
;
764 return IN_CLASSB_NET
;
766 return IN_CLASSC_NET
;
767 err(FATAL
, "unknown IP address class: %08X", addr
);
779 err(int fatal
, const char *fmt
,...)
795 (void) fprintf(stderr
, "rarpd: error: ");
797 (void) fprintf(stderr
, "rarpd: warning: ");
798 (void) vfprintf(stderr
, fmt
, ap
);
799 (void) fprintf(stderr
, "\n");
801 vsyslog(LOG_ERR
, fmt
, ap
);
810 debug(const char *fmt
,...)
825 (void) fprintf(stderr
, "rarpd: ");
826 (void) vfprintf(stderr
, fmt
, ap
);
828 (void) fprintf(stderr
, "\n");