2 * Copyright (c) 1990, 1991, 1992, 1993, 1996
3 * The Regents of the University of California. All rights reserved.
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
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.
21 * @(#) Copyright (c) 1990, 1991, 1992, 1993, 1996 The Regents of the University of California. All rights reserved.
22 * $FreeBSD: src/usr.sbin/rarpd/rarpd.c,v 1.23.2.4 2002/12/01 19:19:34 dwmalone Exp $
23 * $DragonFly: src/usr.sbin/rarpd/rarpd.c,v 1.4 2004/12/18 22:48:05 swildner Exp $
27 * rarpd - Reverse ARP Daemon
29 * Usage: rarpd -a [ -dfsv ] [-t directory] [ hostname ]
30 * rarpd [ -dfsv ] [-t directory] interface [ hostname ]
32 * 'hostname' is optional solely for backwards compatibility with Sun's rarpd.
33 * Currently, the argument is ignored.
35 #include <sys/param.h>
37 #include <sys/ioctl.h>
38 #include <sys/socket.h>
42 #include <net/ethernet.h>
44 #include <net/if_types.h>
45 #include <net/if_dl.h>
46 #include <net/route.h>
48 #include <netinet/in.h>
49 #include <netinet/if_ether.h>
51 #include <arpa/inet.h>
62 #if defined(SUNOS4) || defined(__DragonFly__) /* XXX */
72 /* Cast a struct sockaddr to a structaddr_in */
73 #define SATOSIN(sa) ((struct sockaddr_in *)(sa))
76 #define TFTP_DIR "/tftpboot"
80 #define ARPSECS (20 * 60) /* as per code in netinet/if_ether.c */
81 #define REVARP_REQUEST ARPOP_REVREQUEST
82 #define REVARP_REPLY ARPOP_REVREPLY
85 #ifndef ETHERTYPE_REVARP
86 #define ETHERTYPE_REVARP 0x8035
87 #define REVARP_REQUEST 3
88 #define REVARP_REPLY 4
92 * Map field names in ether_arp struct. What a pain in the neck.
99 #define arp_sha arp_xsha
100 #define arp_spa arp_xspa
101 #define arp_tha arp_xtha
102 #define arp_tpa arp_xtpa
106 * The structure for each interface.
109 struct if_info
*ii_next
;
110 int ii_fd
; /* BPF file descriptor */
111 u_long ii_ipaddr
; /* IP address of this interface */
112 u_long ii_netmask
; /* subnet or net mask */
113 u_char ii_eaddr
[6]; /* Ethernet address of this interface */
114 char ii_ifname
[sizeof(((struct ifreq
*)0)->ifr_name
) + 1];
118 * The list of all interfaces that are being listened to. rarp_loop()
119 * "selects" on the descriptors in this list.
121 struct if_info
*iflist
;
123 int verbose
; /* verbose messages */
124 int s
; /* inet datagram socket */
125 const char *tftp_dir
= TFTP_DIR
; /* tftp directory */
127 int dflag
; /* messages to stdout/stderr, not syslog(3) */
128 int sflag
; /* ignore /tftpboot */
130 static u_char zero
[6];
132 static int bpf_open(void);
133 static u_long
choose_ipaddr(u_long
**, u_long
, u_long
);
134 static char *eatoa(u_char
*);
135 static int expand_syslog_m(const char *fmt
, char **newfmt
);
136 static void init(char *);
137 static void init_one(struct ifreq
*, char *);
138 static char *intoa(u_long
);
139 static u_long
ipaddrtonetmask(u_long
);
140 static void logmsg(int, const char *, ...) __printflike(2, 3);
141 static int rarp_bootable(u_long
);
142 static int rarp_check(u_char
*, u_int
);
143 static void rarp_loop(void);
144 static int rarp_open(char *);
145 static void rarp_process(struct if_info
*, u_char
*, u_int
);
146 static void rarp_reply(struct if_info
*, struct ether_header
*,
148 static void update_arptab(u_char
*, u_long
);
149 static void usage(void);
152 main(int argc
, char *argv
[])
155 char *ifname
, *hostname
, *name
;
157 int aflag
= 0; /* listen on "all" interfaces */
158 int fflag
= 0; /* don't fork */
160 if ((name
= strrchr(argv
[0], '/')) != NULL
)
168 * All error reporting is done through syslog, unless -d is specified
170 openlog(name
, LOG_PID
| LOG_CONS
, LOG_DAEMON
);
173 while ((op
= getopt(argc
, argv
, "adfst:v")) != -1) {
204 ifname
= argv
[optind
++];
205 hostname
= ifname
? argv
[optind
] : NULL
;
206 if ((aflag
&& ifname
) || (!aflag
&& ifname
== NULL
))
216 logmsg(LOG_ERR
, "cannot fork");
225 * Add to the interface list.
228 init_one(struct ifreq
*ifrp
, char *target
)
231 struct sockaddr_dl
*ll
;
235 family
= ifrp
->ifr_addr
.sa_family
;
242 strncpy(ifr
.ifr_name
, ifrp
->ifr_name
, sizeof(ifrp
->ifr_name
));
243 if (ioctl(s
, SIOCGIFFLAGS
, (char *)&ifr
) == -1) {
245 "SIOCGIFFLAGS: %.*s: %m",
246 (int)sizeof(ifrp
->ifr_name
), ifrp
->ifr_name
);
249 if ((ifr
.ifr_flags
& IFF_UP
) == 0 ||
250 (ifr
.ifr_flags
& (IFF_LOOPBACK
| IFF_POINTOPOINT
)) != 0)
259 /* Don't bother going any further if not the target interface */
260 if (target
!= NULL
&&
261 strncmp(ifrp
->ifr_name
, target
, sizeof(ifrp
->ifr_name
)) != 0)
264 /* Look for interface in list */
265 for (ii
= iflist
; ii
!= NULL
; ii
= ii
->ii_next
)
266 if (strncmp(ifrp
->ifr_name
, ii
->ii_ifname
,
267 sizeof(ifrp
->ifr_name
)) == 0)
270 /* Allocate a new one if not found */
272 ii
= (struct if_info
*)malloc(sizeof(*ii
));
274 logmsg(LOG_ERR
, "malloc: %m");
277 bzero(ii
, sizeof(*ii
));
279 strncpy(ii
->ii_ifname
, ifrp
->ifr_name
, sizeof(ifrp
->ifr_name
));
280 ii
->ii_ifname
[sizeof(ii
->ii_ifname
) - 1] = '\0';
281 ii
->ii_next
= iflist
;
288 if (ioctl(s
, SIOCGIFADDR
, (char *)&ifr
) == -1) {
289 logmsg(LOG_ERR
, "ipaddr SIOCGIFADDR: %s: %m",
293 ii
->ii_ipaddr
= SATOSIN(&ifr
.ifr_addr
)->sin_addr
.s_addr
;
294 if (ioctl(s
, SIOCGIFNETMASK
, (char *)&ifr
) == -1) {
295 logmsg(LOG_ERR
, "SIOCGIFNETMASK: %m");
298 ii
->ii_netmask
= SATOSIN(&ifr
.ifr_addr
)->sin_addr
.s_addr
;
299 if (ii
->ii_netmask
== 0)
300 ii
->ii_netmask
= ipaddrtonetmask(ii
->ii_ipaddr
);
302 ii
->ii_fd
= rarp_open(ii
->ii_ifname
);
304 /* Use BPF descriptor to get ethernet address. */
305 if (ioctl(ii
->ii_fd
, SIOCGIFADDR
, (char *)&ifr
) == -1) {
306 logmsg(LOG_ERR
, "eaddr SIOCGIFADDR: %s: %m",
310 bcopy(&ifr
.ifr_addr
.sa_data
[0], ii
->ii_eaddr
, 6);
317 ll
= (struct sockaddr_dl
*)&ifrp
->ifr_addr
;
318 if (ll
->sdl_type
== IFT_ETHER
)
319 bcopy(LLADDR(ll
), ii
->ii_eaddr
, 6);
325 * Initialize all "candidate" interfaces that are in the system
326 * configuration list. A "candidate" is up, not loopback and not
333 struct ifreq
*ifrp
, *ifend
;
334 struct if_info
*ii
, *nii
, *lii
;
336 struct ifreq ibuf
[16];
338 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1) {
339 logmsg(LOG_ERR
, "socket: %m");
342 ifc
.ifc_len
= sizeof ibuf
;
343 ifc
.ifc_buf
= (caddr_t
)ibuf
;
344 if ((ioctl(s
, SIOCGIFCONF
, (char *)&ifc
) == -1) ||
345 ((u_int
)ifc
.ifc_len
< sizeof(struct ifreq
))) {
346 logmsg(LOG_ERR
, "SIOCGIFCONF: %m");
350 ifend
= (struct ifreq
*)((char *)ibuf
+ ifc
.ifc_len
);
351 while (ifrp
< ifend
) {
352 init_one(ifrp
, target
);
355 n
= ifrp
->ifr_addr
.sa_len
+ sizeof(ifrp
->ifr_name
);
356 if (n
< sizeof(*ifrp
))
358 ifrp
= (struct ifreq
*)((char *)ifrp
+ n
);
364 /* Throw away incomplete interfaces */
366 for (ii
= iflist
; ii
!= NULL
; ii
= nii
) {
368 if (ii
->ii_ipaddr
== 0 ||
369 bcmp(ii
->ii_eaddr
, zero
, 6) == 0) {
384 for (ii
= iflist
; ii
!= NULL
; ii
= ii
->ii_next
)
385 logmsg(LOG_DEBUG
, "%s %s 0x%08lx %s",
386 ii
->ii_ifname
, intoa(ntohl(ii
->ii_ipaddr
)),
387 (u_long
)ntohl(ii
->ii_netmask
), eatoa(ii
->ii_eaddr
));
393 fprintf(stderr
, "usage: rarpd [-adfsv] [-t directory] [interface]\n");
402 char device
[sizeof "/dev/bpf000"];
405 * Go through all the minors and find one that isn't in use.
408 sprintf(device
, "/dev/bpf%d", n
++);
409 fd
= open(device
, O_RDWR
);
410 } while ((fd
== -1) && (errno
== EBUSY
));
413 logmsg(LOG_ERR
, "%s: %m", device
);
420 * Open a BPF file and attach it to the interface named 'device'.
421 * Set immediate mode, and set a filter that accepts only RARP requests.
424 rarp_open(char *device
)
431 static struct bpf_insn insns
[] = {
432 BPF_STMT(BPF_LD
|BPF_H
|BPF_ABS
, 12),
433 BPF_JUMP(BPF_JMP
|BPF_JEQ
|BPF_K
, ETHERTYPE_REVARP
, 0, 3),
434 BPF_STMT(BPF_LD
|BPF_H
|BPF_ABS
, 20),
435 BPF_JUMP(BPF_JMP
|BPF_JEQ
|BPF_K
, REVARP_REQUEST
, 0, 1),
436 BPF_STMT(BPF_RET
|BPF_K
, sizeof(struct ether_arp
) +
437 sizeof(struct ether_header
)),
438 BPF_STMT(BPF_RET
|BPF_K
, 0),
440 static struct bpf_program filter
= {
441 sizeof insns
/ sizeof(insns
[0]),
447 * Set immediate mode so packets are processed as they arrive.
450 if (ioctl(fd
, BIOCIMMEDIATE
, &immediate
) == -1) {
451 logmsg(LOG_ERR
, "BIOCIMMEDIATE: %m");
454 strncpy(ifr
.ifr_name
, device
, sizeof ifr
.ifr_name
);
455 if (ioctl(fd
, BIOCSETIF
, (caddr_t
)&ifr
) == -1) {
456 logmsg(LOG_ERR
, "BIOCSETIF: %m");
460 * Check that the data link layer is an Ethernet; this code won't
461 * work with anything else.
463 if (ioctl(fd
, BIOCGDLT
, (caddr_t
)&dlt
) == -1) {
464 logmsg(LOG_ERR
, "BIOCGDLT: %m");
467 if (dlt
!= DLT_EN10MB
) {
468 logmsg(LOG_ERR
, "%s is not an ethernet", device
);
472 * Set filter program.
474 if (ioctl(fd
, BIOCSETF
, (caddr_t
)&filter
) == -1) {
475 logmsg(LOG_ERR
, "BIOCSETF: %m");
482 * Perform various sanity checks on the RARP request packet. Return
483 * false on failure and log the reason.
486 rarp_check(u_char
*p
, u_int len
)
488 struct ether_header
*ep
= (struct ether_header
*)p
;
489 struct ether_arp
*ap
= (struct ether_arp
*)(p
+ sizeof(*ep
));
491 if (len
< sizeof(*ep
) + sizeof(*ap
)) {
492 logmsg(LOG_ERR
, "truncated request, got %u, expected %lu",
493 len
, (u_long
)(sizeof(*ep
) + sizeof(*ap
)));
497 * XXX This test might be better off broken out...
499 if (ntohs(ep
->ether_type
) != ETHERTYPE_REVARP
||
500 ntohs(ap
->arp_hrd
) != ARPHRD_ETHER
||
501 ntohs(ap
->arp_op
) != REVARP_REQUEST
||
502 ntohs(ap
->arp_pro
) != ETHERTYPE_IP
||
503 ap
->arp_hln
!= 6 || ap
->arp_pln
!= 4) {
504 logmsg(LOG_DEBUG
, "request fails sanity check");
507 if (bcmp((char *)&ep
->ether_shost
, (char *)&ap
->arp_sha
, 6) != 0) {
508 logmsg(LOG_DEBUG
, "ether/arp sender address mismatch");
511 if (bcmp((char *)&ap
->arp_sha
, (char *)&ap
->arp_tha
, 6) != 0) {
512 logmsg(LOG_DEBUG
, "ether/arp target address mismatch");
519 #define FD_SET(n, fdp) ((fdp)->fds_bits[0] |= (1 << (n)))
520 #define FD_ISSET(n, fdp) ((fdp)->fds_bits[0] & (1 << (n)))
521 #define FD_ZERO(fdp) ((fdp)->fds_bits[0] = 0)
525 * Loop indefinitely listening for RARP requests on the
526 * interfaces in 'iflist'.
531 u_char
*buf
, *bp
, *ep
;
533 fd_set fds
, listeners
;
534 int bufsize
, maxfd
= 0;
537 if (iflist
== NULL
) {
538 logmsg(LOG_ERR
, "no interfaces");
541 if (ioctl(iflist
->ii_fd
, BIOCGBLEN
, (caddr_t
)&bufsize
) == -1) {
542 logmsg(LOG_ERR
, "BIOCGBLEN: %m");
545 buf
= malloc(bufsize
);
547 logmsg(LOG_ERR
, "malloc: %m");
553 * Find the highest numbered file descriptor for select().
554 * Initialize the set of descriptors to listen to.
557 for (ii
= iflist
; ii
!= NULL
; ii
= ii
->ii_next
) {
558 FD_SET(ii
->ii_fd
, &fds
);
559 if (ii
->ii_fd
> maxfd
)
563 if (select(maxfd
+ 1, &listeners
, NULL
, NULL
, NULL
) == -1) {
564 /* Don't choke when we get ptraced */
567 logmsg(LOG_ERR
, "select: %m");
570 for (ii
= iflist
; ii
!= NULL
; ii
= ii
->ii_next
) {
572 if (!FD_ISSET(fd
, &listeners
))
575 cc
= read(fd
, (char *)buf
, bufsize
);
576 /* Don't choke when we get ptraced */
577 if ((cc
== -1) && (errno
== EINTR
))
579 #if defined(SUNOS3) || defined(SUNOS4)
581 * Due to a SunOS bug, after 2^31 bytes, the
582 * file offset overflows and read fails with
583 * EINVAL. The lseek() to 0 will fix things.
586 if (errno
== EINVAL
&&
587 (long)(tell(fd
) + bufsize
) < 0) {
591 logmsg(LOG_ERR
, "read: %m");
596 /* Loop through the packet(s) */
597 #define bhp ((struct bpf_hdr *)bp)
601 u_int caplen
, hdrlen
;
603 caplen
= bhp
->bh_caplen
;
604 hdrlen
= bhp
->bh_hdrlen
;
605 if (rarp_check(bp
+ hdrlen
, caplen
))
606 rarp_process(ii
, bp
+ hdrlen
, caplen
);
607 bp
+= BPF_WORDALIGN(hdrlen
+ caplen
);
615 * True if this server can boot the host whose IP address is 'addr'.
616 * This check is made by looking in the tftp directory for the
617 * configuration file.
620 rarp_bootable(u_long addr
)
629 static DIR *dd
= NULL
;
631 sprintf(ipname
, "%08lX", (u_long
)ntohl(addr
));
634 * If directory is already open, rewind it. Otherwise, open it.
636 if ((d
= dd
) != NULL
)
639 if (chdir(tftp_dir
) == -1) {
640 logmsg(LOG_ERR
, "chdir: %s: %m", tftp_dir
);
645 logmsg(LOG_ERR
, "opendir: %m");
650 while ((dent
= readdir(d
)) != NULL
)
651 if (strncmp(dent
->d_name
, ipname
, 8) == 0)
657 * Given a list of IP addresses, 'alist', return the first address that
658 * is on network 'net'; 'netmask' is a mask indicating the network portion
662 choose_ipaddr(u_long
**alist
, u_long net
, u_long netmask
)
664 for (; *alist
; ++alist
)
665 if ((**alist
& netmask
) == net
)
671 * Answer the RARP request in 'pkt', on the interface 'ii'. 'pkt' has
672 * already been checked for validity. The reply is overlaid on the request.
675 rarp_process(struct if_info
*ii
, u_char
*pkt
, u_int len
)
677 struct ether_header
*ep
;
679 u_long target_ipaddr
;
682 ep
= (struct ether_header
*)pkt
;
683 /* should this be arp_tha? */
684 if (ether_ntohost(ename
, (struct ether_addr
*)&ep
->ether_shost
) != 0) {
685 logmsg(LOG_ERR
, "cannot map %s to name",
686 eatoa(ep
->ether_shost
));
690 if ((hp
= gethostbyname(ename
)) == NULL
) {
691 logmsg(LOG_ERR
, "cannot map %s to IP address", ename
);
696 * Choose correct address from list.
698 if (hp
->h_addrtype
!= AF_INET
) {
699 logmsg(LOG_ERR
, "cannot handle non IP addresses for %s",
703 target_ipaddr
= choose_ipaddr((u_long
**)hp
->h_addr_list
,
704 ii
->ii_ipaddr
& ii
->ii_netmask
,
706 if (target_ipaddr
== 0) {
707 logmsg(LOG_ERR
, "cannot find %s on net %s",
708 ename
, intoa(ntohl(ii
->ii_ipaddr
& ii
->ii_netmask
)));
711 if (sflag
|| rarp_bootable(target_ipaddr
))
712 rarp_reply(ii
, ep
, target_ipaddr
, len
);
713 else if (verbose
> 1)
714 logmsg(LOG_INFO
, "%s %s at %s DENIED (not bootable)",
716 eatoa(ep
->ether_shost
),
717 intoa(ntohl(target_ipaddr
)));
721 * Poke the kernel arp tables with the ethernet/ip address combinataion
722 * given. When processing a reply, we must do this so that the booting
723 * host (i.e. the guy running rarpd), won't try to ARP for the hardware
724 * address of the guy being booted (he cannot answer the ARP).
727 struct sockaddr_inarp sin_inarp
= {
728 sizeof(struct sockaddr_inarp
), AF_INET
, 0,
733 struct sockaddr_dl sin_dl
= {
734 sizeof(struct sockaddr_dl
), AF_LINK
, 0, IFT_ETHER
, 0, 6,
738 struct rt_msghdr rthdr
;
743 update_arptab(u_char
*ep
, u_long ipaddr
)
746 struct sockaddr_inarp
*ar
, *ar2
;
747 struct sockaddr_dl
*ll
, *ll2
;
748 struct rt_msghdr
*rt
;
754 r
= socket(PF_ROUTE
, SOCK_RAW
, 0);
756 logmsg(LOG_ERR
, "raw route socket: %m");
762 ar
->sin_addr
.s_addr
= ipaddr
;
764 bcopy(ep
, LLADDR(ll
), 6);
766 /* Get the type and interface index */
768 bzero(rt
, sizeof(rtmsg
));
769 rt
->rtm_version
= RTM_VERSION
;
770 rt
->rtm_addrs
= RTA_DST
;
771 rt
->rtm_type
= RTM_GET
;
773 ar2
= (struct sockaddr_inarp
*)rtmsg
.rtspace
;
774 bcopy(ar
, ar2
, sizeof(*ar
));
775 rt
->rtm_msglen
= sizeof(*rt
) + sizeof(*ar
);
777 if ((write(r
, rt
, rt
->rtm_msglen
) == -1) && (errno
!= ESRCH
)) {
778 logmsg(LOG_ERR
, "rtmsg get write: %m");
783 cc
= read(r
, rt
, sizeof(rtmsg
));
784 } while (cc
> 0 && (rt
->rtm_seq
!= seq
|| rt
->rtm_pid
!= pid
));
786 logmsg(LOG_ERR
, "rtmsg get read: %m");
790 ll2
= (struct sockaddr_dl
*)((u_char
*)ar2
+ ar2
->sin_len
);
791 if (ll2
->sdl_family
!= AF_LINK
) {
793 * XXX I think this means the ip address is not on a
794 * directly connected network (the family is AF_INET in
797 logmsg(LOG_ERR
, "bogus link family (%d) wrong net for %08lX?\n",
798 ll2
->sdl_family
, ipaddr
);
802 xtype
= ll2
->sdl_type
;
803 xindex
= ll2
->sdl_index
;
805 /* Set the new arp entry */
806 bzero(rt
, sizeof(rtmsg
));
807 rt
->rtm_version
= RTM_VERSION
;
808 rt
->rtm_addrs
= RTA_DST
| RTA_GATEWAY
;
809 rt
->rtm_inits
= RTV_EXPIRE
;
810 rt
->rtm_rmx
.rmx_expire
= time(0) + ARPSECS
;
811 rt
->rtm_flags
= RTF_HOST
| RTF_STATIC
;
812 rt
->rtm_type
= RTM_ADD
;
815 bcopy(ar
, ar2
, sizeof(*ar
));
817 ll2
= (struct sockaddr_dl
*)((u_char
*)ar2
+ sizeof(*ar2
));
818 bcopy(ll
, ll2
, sizeof(*ll
));
819 ll2
->sdl_type
= xtype
;
820 ll2
->sdl_index
= xindex
;
822 rt
->rtm_msglen
= sizeof(*rt
) + sizeof(*ar2
) + sizeof(*ll2
);
824 if ((write(r
, rt
, rt
->rtm_msglen
) == -1) && (errno
!= EEXIST
)) {
825 logmsg(LOG_ERR
, "rtmsg add write: %m");
830 cc
= read(r
, rt
, sizeof(rtmsg
));
831 } while (cc
> 0 && (rt
->rtm_seq
!= seq
|| rt
->rtm_pid
!= pid
));
834 logmsg(LOG_ERR
, "rtmsg add read: %m");
840 update_arptab(u_char
*ep
, u_long ipaddr
)
842 struct arpreq request
;
843 struct sockaddr_in
*sin
;
845 request
.arp_flags
= 0;
846 sin
= (struct sockaddr_in
*)&request
.arp_pa
;
847 sin
->sin_family
= AF_INET
;
848 sin
->sin_addr
.s_addr
= ipaddr
;
849 request
.arp_ha
.sa_family
= AF_UNSPEC
;
850 bcopy((char *)ep
, (char *)request
.arp_ha
.sa_data
, 6);
852 if (ioctl(s
, SIOCSARP
, (caddr_t
)&request
) == -1)
853 logmsg(LOG_ERR
, "SIOCSARP: %m");
858 * Build a reverse ARP packet and sent it out on the interface.
859 * 'ep' points to a valid REVARP_REQUEST. The REVARP_REPLY is built
860 * on top of the request, then written to the network.
862 * RFC 903 defines the ether_arp fields as follows. The following comments
863 * are taken (more or less) straight from this document.
867 * arp_sha is the hardware address of the sender of the packet.
868 * arp_spa is undefined.
869 * arp_tha is the 'target' hardware address.
870 * In the case where the sender wishes to determine his own
871 * protocol address, this, like arp_sha, will be the hardware
872 * address of the sender.
873 * arp_tpa is undefined.
877 * arp_sha is the hardware address of the responder (the sender of the
879 * arp_spa is the protocol address of the responder (see the note below).
880 * arp_tha is the hardware address of the target, and should be the same as
881 * that which was given in the request.
882 * arp_tpa is the protocol address of the target, that is, the desired address.
884 * Note that the requirement that arp_spa be filled in with the responder's
885 * protocol is purely for convenience. For instance, if a system were to use
886 * both ARP and RARP, then the inclusion of the valid protocol-hardware
887 * address pair (arp_spa, arp_sha) may eliminate the need for a subsequent
891 rarp_reply(struct if_info
*ii
, struct ether_header
*ep
, u_long ipaddr
,
895 struct ether_arp
*ap
= (struct ether_arp
*)(ep
+ 1);
897 update_arptab((u_char
*)&ap
->arp_sha
, ipaddr
);
900 * Build the rarp reply by modifying the rarp request in place.
902 ap
->arp_op
= htons(REVARP_REPLY
);
905 ep
->ether_type
= ETHERTYPE_REVARP
;
907 bcopy((char *)&ap
->arp_sha
, (char *)&ep
->ether_dhost
, 6);
908 bcopy((char *)ii
->ii_eaddr
, (char *)&ep
->ether_shost
, 6);
909 bcopy((char *)ii
->ii_eaddr
, (char *)&ap
->arp_sha
, 6);
911 bcopy((char *)&ipaddr
, (char *)ap
->arp_tpa
, 4);
912 /* Target hardware is unchanged. */
913 bcopy((char *)&ii
->ii_ipaddr
, (char *)ap
->arp_spa
, 4);
915 /* Zero possible garbage after packet. */
916 bzero((char *)ep
+ (sizeof(*ep
) + sizeof(*ap
)),
917 len
- (sizeof(*ep
) + sizeof(*ap
)));
918 n
= write(ii
->ii_fd
, (char *)ep
, len
);
920 logmsg(LOG_ERR
, "write: only %d of %d bytes written", n
, len
);
922 logmsg(LOG_INFO
, "%s %s at %s REPLIED", ii
->ii_ifname
,
924 intoa(ntohl(ipaddr
)));
928 * Get the netmask of an IP address. This routine is used if
929 * SIOCGIFNETMASK doesn't work.
932 ipaddrtonetmask(u_long addr
)
936 return htonl(IN_CLASSA_NET
);
938 return htonl(IN_CLASSB_NET
);
940 return htonl(IN_CLASSC_NET
);
941 logmsg(LOG_DEBUG
, "unknown IP address class: %08lX", addr
);
942 return htonl(0xffffffff);
946 * A faster replacement for inet_ntoa().
954 static char buf
[sizeof(".xxx.xxx.xxx.xxx")];
956 cp
= &buf
[sizeof buf
];
962 *--cp
= byte
% 10 + '0';
965 *--cp
= byte
% 10 + '0';
980 static char buf
[sizeof("xx:xx:xx:xx:xx:xx")];
982 sprintf(buf
, "%x:%x:%x:%x:%x:%x",
983 ea
[0], ea
[1], ea
[2], ea
[3], ea
[4], ea
[5]);
988 logmsg(int pri
, const char *fmt
, ...)
1000 if (expand_syslog_m(fmt
, &newfmt
) == -1) {
1001 vfprintf(fp
, fmt
, v
);
1003 vfprintf(fp
, newfmt
, v
);
1009 vsyslog(pri
, fmt
, v
);
1015 expand_syslog_m(const char *fmt
, char **newfmt
) {
1016 const char *str
, *m
;
1021 while ((m
= strstr(str
, "%m")) != NULL
) {
1022 asprintf(&np
, "%s%.*s%s", p
, (int)(m
- str
),
1023 str
, strerror(errno
));
1034 asprintf(&np
, "%s%s", p
, str
);