4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
11 * Extricated from iputils by Nick Bowler (2023-07).
26 #include <arpa/inet.h>
27 #include <netinet/in.h>
29 #include <linux/if_arp.h>
30 #include <linux/if_packet.h>
31 #include <linux/filter.h>
32 #include <sys/ioctl.h>
33 #include <sys/socket.h>
45 char *tftp_dir = "/etc/tftpboot";
47 static const char *progname = "rarpd";
49 extern int ether_ntohost(char *name, unsigned char *ea);
56 unsigned char lladdr[16];
58 struct ifaddr *ifa_list;
71 struct rarp_map *next;
76 unsigned char lladdr[16];
80 static void print_usage(FILE *f)
82 fprintf(f, "Usage: %s [options] [interface]\n", progname);
84 fprintf(f, "Try %s -H for more information.\n", progname);
87 static void print_help(void)
93 puts(" -A listen also arp messages");
94 puts(" -a listen on all the interfaces");
95 puts(" -b <dir> tftpd boot directory");
96 puts(" -d debug mode");
97 puts(" -e /etc/ethers markup alone is fine");
98 puts(" -v verbose mode");
99 puts(" -V print version and then exit");
100 puts(" -H print this message and then exit");
103 puts("For more information, see the rarpd(8) man page.");
106 static void print_version(void)
108 printf("rarpd (%s) %s\n", PACKAGE, PACKAGE_VERSION);
109 puts("License GPLv2+: GNU GPL version 2 or any later version");
110 puts("This is free software: you are free to change and redistribute it.");
111 puts("There is NO WARRANTY, to the extent permitted by law.");
121 struct ifreq *ifrp, *ifend;
125 struct ifreq ibuf[256];
127 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
128 syslog(LOG_ERR, "socket: %s", strerror(errno));
132 ifc.ifc_len = sizeof ibuf;
133 ifc.ifc_buf = (char *)ibuf;
134 if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
135 ifc.ifc_len < (int)sizeof(struct ifreq)) {
136 syslog(LOG_ERR, "SIOCGIFCONF: %s", strerror(errno));
141 while ((ifl = ifl_list) != NULL) {
142 while ((ifa = ifl->ifa_list) != NULL) {
143 ifl->ifa_list = ifa->next;
146 ifl_list = ifl->next;
150 ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
151 for (ifrp = ibuf; ifrp < ifend; ifrp++) {
156 if (ifrp->ifr_addr.sa_family != AF_INET)
158 addr = ((struct sockaddr_in*)&ifrp->ifr_addr)->sin_addr.s_addr;
161 if (ioctl(fd, SIOCGIFINDEX, ifrp)) {
162 syslog(LOG_ERR, "ioctl(SIOCGIFNAME): %s", strerror(errno));
165 if (ifidx && ifrp->ifr_ifindex != ifidx)
167 for (ifl = ifl_list; ifl; ifl = ifl->next)
168 if (ifl->index == ifrp->ifr_ifindex)
172 int index = ifrp->ifr_ifindex;
174 if (ioctl(fd, SIOCGIFHWADDR, ifrp)) {
175 syslog(LOG_ERR, "ioctl(SIOCGIFHWADDR): %s", strerror(errno));
179 ifl = (struct iflink*)malloc(sizeof(*ifl));
182 memset(ifl, 0, sizeof(*ifl));
183 ifl->next = ifl_list;
186 ifl->hatype = ifrp->ifr_hwaddr.sa_family;
187 memcpy(ifl->lladdr, ifrp->ifr_hwaddr.sa_data, 14);
188 strncpy(ifl->name, ifrp->ifr_name, IFNAMSIZ);
189 p = strchr(ifl->name, ':');
193 syslog(LOG_INFO, "link %s", ifl->name);
195 if (ioctl(fd, SIOCGIFNETMASK, ifrp)) {
196 syslog(LOG_ERR, "ioctl(SIOCGIFMASK): %s", strerror(errno));
199 mask = ((struct sockaddr_in*)&ifrp->ifr_netmask)->sin_addr.s_addr;
200 if (ioctl(fd, SIOCGIFDSTADDR, ifrp)) {
201 syslog(LOG_ERR, "ioctl(SIOCGIFDSTADDR): %s", strerror(errno));
204 prefix = ((struct sockaddr_in*)&ifrp->ifr_dstaddr)->sin_addr.s_addr;
205 for (ifa = ifl->ifa_list; ifa; ifa = ifa->next) {
206 if (ifa->local == addr &&
207 ifa->prefix == prefix &&
212 if (mask == 0 || prefix == 0)
214 ifa = (struct ifaddr*)malloc(sizeof(*ifa));
215 memset(ifa, 0, sizeof(*ifa));
217 ifa->prefix = prefix;
219 ifa->next = ifl->ifa_list;
225 for (i=32; i>=0; i--) {
226 if (htonl(m) == mask)
230 if (addr == prefix) {
231 syslog(LOG_INFO, " addr %s/%d on %s\n",
232 inet_ntoa(*(struct in_addr*)&addr), i, ifl->name);
235 sprintf(tmpa, "%s", inet_ntoa(*(struct in_addr*)&addr));
236 syslog(LOG_INFO, " addr %s %s/%d on %s\n", tmpa,
237 inet_ntoa(*(struct in_addr*)&prefix), i, ifl->name);
250 int bootable(uint32_t addr)
256 sprintf(name, "%08X", (uint32_t)ntohl(addr));
257 d = opendir(tftp_dir);
259 syslog(LOG_ERR, "opendir: %s", strerror(errno));
262 while ((dent = readdir(d)) != NULL) {
263 if (strncmp(dent->d_name, name, 8) == 0)
270 struct ifaddr *select_ipaddr(int ifindex, uint32_t *sel_addr, uint32_t **alist)
278 for (ifl=ifl_list; ifl; ifl=ifl->next)
279 if (ifl->index == ifindex)
281 if (ifl == NULL && !retry) {
289 for (i=0; alist[i]; i++) {
290 uint32_t addr = *(alist[i]);
291 for (ifa=ifl->ifa_list; ifa; ifa=ifa->next) {
292 if (!((ifa->prefix^addr)&ifa->mask)) {
297 if (ifa == NULL && retry==0) {
303 if (i==1 && allow_offlink) {
304 *sel_addr = *(alist[0]);
305 return ifl->ifa_list;
307 syslog(LOG_ERR, "Off-link request on %s", ifl->name);
311 struct rarp_map *rarp_lookup(int ifindex, int hatype,
312 int halen, unsigned char *lladdr)
316 for (r=rarp_db; r; r=r->next) {
317 if (r->arp_type != hatype && r->arp_type != -1)
319 if (r->lladdr_len != halen)
321 if (r->ifindex != ifindex && r->ifindex != 0)
323 if (memcmp(r->lladdr, lladdr, halen) == 0)
328 if (hatype == ARPHRD_ETHER && halen == 6) {
332 static struct rarp_map emap = {
333 .arp_type = ARPHRD_ETHER,
337 if (ether_ntohost(ename, lladdr) != 0 ||
338 (hp = gethostbyname(ename)) == NULL) {
340 syslog(LOG_INFO, "not found in /etc/ethers");
343 if (hp->h_addrtype != AF_INET) {
344 syslog(LOG_ERR, "no IP address");
347 ifa = select_ipaddr(ifindex, &emap.ipaddr, (uint32_t **)hp->h_addr_list);
349 memcpy(emap.lladdr, lladdr, 6);
350 if (only_ethers || bootable(emap.ipaddr))
353 syslog(LOG_INFO, "not bootable");
360 static int load_arp_bpflet(int fd)
362 static struct sock_filter insns[] = {
363 BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 6),
364 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, ARPOP_RREQUEST, 0, 1),
365 BPF_STMT(BPF_RET|BPF_K, 1024),
366 BPF_STMT(BPF_RET|BPF_K, 0),
368 static struct sock_fprog filter = {
369 sizeof insns / sizeof(insns[0]),
373 return setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter));
376 int put_mylladdr(unsigned char **ptr_p, int ifindex, int alen)
380 for (ifl=ifl_list; ifl; ifl = ifl->next)
381 if (ifl->index == ifindex)
387 memcpy(*ptr_p, ifl->lladdr, alen);
392 int put_myipaddr(unsigned char **ptr_p, int ifindex, uint32_t hisipaddr)
398 for (ifl=ifl_list; ifl; ifl = ifl->next)
399 if (ifl->index == ifindex)
405 for (ifa=ifl->ifa_list; ifa; ifa=ifa->next) {
406 if (!((ifa->prefix^hisipaddr)&ifa->mask)) {
411 memcpy(*ptr_p, &laddr, 4);
416 void arp_advise(int ifindex, unsigned char *lladdr, int lllen, uint32_t ipaddr)
420 struct sockaddr_in *sin;
423 for (ifl=ifl_list; ifl; ifl = ifl->next)
424 if (ifl->index == ifindex)
430 fd = socket(AF_INET, SOCK_DGRAM, 0);
431 memset(&req, 0, sizeof(req));
432 req.arp_flags = ATF_COM;
433 sin = (struct sockaddr_in *)&req.arp_pa;
434 sin->sin_family = AF_INET;
435 sin->sin_addr.s_addr = ipaddr;
436 req.arp_ha.sa_family = ifl->hatype;
437 memcpy(req.arp_ha.sa_data, lladdr, lllen);
438 memcpy(req.arp_dev, ifl->name, IFNAMSIZ);
440 if (ioctl(fd, SIOCSARP, &req))
441 syslog(LOG_ERR, "SIOCSARP: %s", strerror(errno));
445 void serve_it(int fd)
447 unsigned char buf[1024];
448 struct sockaddr_ll sll = { 0 };
449 socklen_t sll_len = sizeof(sll);
450 struct arphdr *a = (struct arphdr*)buf;
451 struct rarp_map *rmap;
455 n = recvfrom(fd, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr*)&sll, &sll_len);
457 if (errno != EINTR && errno != EAGAIN)
458 syslog(LOG_ERR, "recvfrom: %s", strerror(errno));
462 /* Do not accept packets for other hosts and our own ones */
463 if (sll.sll_pkttype != PACKET_BROADCAST &&
464 sll.sll_pkttype != PACKET_MULTICAST &&
465 sll.sll_pkttype != PACKET_HOST)
468 if (ifidx && sll.sll_ifindex != ifidx)
471 if ((size_t)n<sizeof(*a)) {
472 syslog(LOG_ERR, "truncated arp packet; len=%zu", n);
476 /* Accept only RARP requests */
477 if (a->ar_op != htons(ARPOP_RREQUEST))
484 for (i=0; i<sll.sll_halen; i++) {
486 sprintf(p, ":%02x", sll.sll_addr[i]);
489 sprintf(p, "%02x", sll.sll_addr[i]);
492 syslog(LOG_INFO, "RARP request from %s on if%d", tmpbuf, sll.sll_ifindex);
497 /* 1. IP only -> pln==4 */
498 if (a->ar_pln != 4) {
499 syslog(LOG_ERR, "interesting rarp_req plen=%d", a->ar_pln);
502 /* 2. ARP protocol must be IP */
503 if (a->ar_pro != htons(ETH_P_IP)) {
504 syslog(LOG_ERR, "rarp protocol is not IP %04x", ntohs(a->ar_pro));
507 /* 3. ARP types must match */
508 if (htons(sll.sll_hatype) != a->ar_hrd) {
509 switch (sll.sll_hatype) {
511 if (a->ar_hrd == htons(ARPHRD_ETHER) ||
512 a->ar_hrd == htons(ARPHRD_IEEE802))
516 syslog(LOG_ERR, "rarp htype mismatch");
520 /* 3. LL address lengths must be equal */
521 if (a->ar_hln != sll.sll_halen) {
522 syslog(LOG_ERR, "rarp hlen mismatch");
525 /* 4. Check packet length */
526 if (sizeof(*a) + 2*4 + 2*a->ar_hln > (size_t) n) {
527 syslog(LOG_ERR, "truncated rarp request; len=%zu", n);
530 /* 5. Silly check: if this guy set different source
531 addresses in MAC header and in ARP, he is insane
533 if (memcmp(sll.sll_addr, a+1, sll.sll_halen)) {
534 syslog(LOG_ERR, "this guy set different his lladdrs in arp and header");
537 /* End of sanity checks */
539 /* Lookup requested target in our database */
540 rmap = rarp_lookup(sll.sll_ifindex, sll.sll_hatype,
541 sll.sll_halen, (unsigned char*)(a+1) + sll.sll_halen + 4);
545 /* Prepare reply. It is almost ready, we only
546 replace ARP packet type, put our lladdr and
547 IP address to source fields,
548 and fill target IP address.
550 a->ar_op = htons(ARPOP_RREPLY);
551 ptr = (unsigned char*)(a+1);
552 if (put_mylladdr(&ptr, sll.sll_ifindex, rmap->lladdr_len))
554 if (put_myipaddr(&ptr, sll.sll_ifindex, rmap->ipaddr))
556 /* It is already filled */
557 ptr += rmap->lladdr_len;
558 memcpy(ptr, &rmap->ipaddr, 4);
561 /* Update our ARP cache. Probably, this guy
562 will not able to make ARP (if it is broken)
564 arp_advise(sll.sll_ifindex, rmap->lladdr, rmap->lladdr_len, rmap->ipaddr);
566 /* Sendto is blocking, but with 5sec timeout */
568 sendto(fd, buf, ptr - buf, 0, (struct sockaddr*)&sll, sizeof(sll));
572 void catch_signal(int sig, void (*handler)(int))
576 memset(&sa, 0, sizeof(sa));
577 sa.sa_handler = handler;
578 sigaction(sig, &sa, NULL);
581 void sig_alarm(int signo __attribute__((__unused__)))
585 void sig_hup(int signo __attribute__((__unused__)))
590 int main(int argc, char **argv)
592 struct pollfd pset[2];
600 while ((opt = getopt(argc, argv, "aAb:dvoeVH")) != EOF) {
641 if (argc > optind+1) {
645 ifname = argv[optind];
649 pset[0].fd = socket(PF_PACKET, SOCK_DGRAM, 0);
653 memset(&ifr, 0, sizeof(ifr));
654 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
655 if (ioctl(pset[0].fd, SIOCGIFINDEX, &ifr)) {
656 fprintf(stderr, "%s: %s: ioctl(SIOCGIFINDEX): %s\n",
657 progname, ifname, strerror(errno));
661 ifidx = ifr.ifr_ifindex;
666 pset[1].fd = socket(PF_PACKET, SOCK_DGRAM, 0);
667 if (pset[1].fd >= 0) {
668 load_arp_bpflet(pset[1].fd);
673 if (pset[1].fd >= 0) {
674 struct sockaddr_ll sll;
675 memset(&sll, 0, sizeof(sll));
676 sll.sll_family = AF_PACKET;
677 sll.sll_protocol = htons(ETH_P_ARP);
678 sll.sll_ifindex = all_ifaces ? 0 : ifidx;
679 if (bind(pset[1].fd, (struct sockaddr*)&sll, sizeof(sll)) < 0) {
685 if (pset[0].fd >= 0) {
686 struct sockaddr_ll sll;
687 memset(&sll, 0, sizeof(sll));
688 sll.sll_family = AF_PACKET;
689 sll.sll_protocol = htons(ETH_P_RARP);
690 sll.sll_ifindex = all_ifaces ? 0 : ifidx;
691 if (bind(pset[0].fd, (struct sockaddr*)&sll, sizeof(sll)) < 0) {
696 if (pset[0].fd < 0) {
701 fprintf(stderr, "%s: error: failed to bind any socket\n", progname);
706 if (daemon(0, 0) < 0) {
707 fprintf(stderr, "%s: error: daemon() failed: %s\n",
708 progname, strerror(errno));
713 openlog("rarpd", LOG_PID | LOG_CONS, LOG_DAEMON);
714 catch_signal(SIGALRM, sig_alarm);
715 catch_signal(SIGHUP, sig_hup);
725 #define EVENTS (POLLIN|POLLPRI|POLLERR|POLLHUP)
726 pset[0].events = EVENTS;
728 pset[1].events = EVENTS;
731 i = poll(pset, psize, -1);
733 if (errno != EINTR && i<0) {
734 syslog(LOG_ERR, "poll returned some crap: %s\n", strerror(errno));
739 for (i=0; i<psize; i++) {
740 if (pset[i].revents&EVENTS)
741 serve_it(pset[i].fd);