2 * arpd.c ARP helper daemon.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
20 #include <sys/ioctl.h>
25 #include <sys/socket.h>
30 #include <linux/if_ether.h>
31 #include <linux/if_arp.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 #include <linux/if_packet.h>
35 #include <linux/filter.h>
37 #include "libnetlink.h"
43 char *dbname = "/var/lib/arpd/arpd.db";
55 #define IS_NEG(x) (((__u8*)(x))[0] == 0xFF)
56 #define NEG_TIME(x) (((x)[2]<<24)|((x)[3]<<16)|((x)[4]<<8)|(x)[5])
57 #define NEG_AGE(x) ((__u32)time(NULL) - NEG_TIME((__u8*)x))
58 #define NEG_VALID(x) (NEG_AGE(x) < negative_timeout)
59 #define NEG_CNT(x) (((__u8*)(x))[1])
61 struct rtnl_handle rth;
63 struct pollfd pset[2];
68 volatile int do_stats;
71 unsigned long arp_new;
72 unsigned long arp_change;
74 unsigned long app_recv;
75 unsigned long app_success;
76 unsigned long app_bad;
77 unsigned long app_neg;
78 unsigned long app_suppressed;
80 unsigned long kern_neg;
81 unsigned long kern_new;
82 unsigned long kern_change;
84 unsigned long probes_sent;
85 unsigned long probes_suppressed;
89 int negative_timeout = 60;
90 int no_kernel_broadcasts;
91 int broadcast_rate = 1000;
92 int broadcast_burst = 3000;
97 "Usage: arpd [ -lk ] [ -a N ] [ -b dbase ] [ -f file ] [ interfaces ]\n");
101 int handle_if(int ifindex)
108 for (i=0; i<ifnum; i++)
109 if (ifvec[i] == ifindex)
116 void do_sysctl_adjustments(void)
123 for (i=0; i<ifnum; i++) {
127 if (active_probing) {
128 sprintf(buf, "/proc/sys/net/ipv4/neigh/%s/mcast_solicit", ifnames[i]);
129 if ((fp = fopen(buf, "w")) != NULL) {
130 if (no_kernel_broadcasts)
133 sprintf(buf, "%d\n", active_probing>=2 ? 1 : 3-active_probing);
139 sprintf(buf, "/proc/sys/net/ipv4/neigh/%s/app_solicit", ifnames[i]);
140 if ((fp = fopen(buf, "w")) != NULL) {
141 sprintf(buf, "%d\n", active_probing<=1 ? 1 : active_probing);
149 void undo_sysctl_adjustments(void)
153 if (!sysctl_adjusted)
156 for (i=0; i<ifnum; i++) {
160 if (active_probing) {
161 sprintf(buf, "/proc/sys/net/ipv4/neigh/%s/mcast_solicit", ifnames[i]);
162 if ((fp = fopen(buf, "w")) != NULL) {
168 sprintf(buf, "/proc/sys/net/ipv4/neigh/%s/app_solicit", ifnames[i]);
169 if ((fp = fopen(buf, "w")) != NULL) {
179 int send_probe(int ifindex, __u32 addr)
182 struct sockaddr_in dst;
184 unsigned char buf[256];
185 struct arphdr *ah = (struct arphdr*)buf;
186 unsigned char *p = (unsigned char *)(ah+1);
187 struct sockaddr_ll sll;
189 memset(&ifr, 0, sizeof(ifr));
190 ifr.ifr_ifindex = ifindex;
191 if (ioctl(udp_sock, SIOCGIFNAME, &ifr))
193 if (ioctl(udp_sock, SIOCGIFHWADDR, &ifr))
195 if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)
197 if (setsockopt(udp_sock, SOL_SOCKET, SO_BINDTODEVICE, ifr.ifr_name, strlen(ifr.ifr_name)+1) < 0)
200 dst.sin_family = AF_INET;
201 dst.sin_port = htons(1025);
202 dst.sin_addr.s_addr = addr;
203 if (connect(udp_sock, (struct sockaddr*)&dst, sizeof(dst)) < 0)
206 if (getsockname(udp_sock, (struct sockaddr*)&dst, &len) < 0)
209 ah->ar_hrd = htons(ifr.ifr_hwaddr.sa_family);
210 ah->ar_pro = htons(ETH_P_IP);
213 ah->ar_op = htons(ARPOP_REQUEST);
215 memcpy(p, ifr.ifr_hwaddr.sa_data, ah->ar_hln);
218 memcpy(p, &dst.sin_addr, 4);
221 sll.sll_family = AF_PACKET;
222 memset(sll.sll_addr, 0xFF, sizeof(sll.sll_addr));
223 sll.sll_ifindex = ifindex;
224 sll.sll_protocol = htons(ETH_P_ARP);
225 memcpy(p, &sll.sll_addr, ah->ar_hln);
231 if (sendto(pset[0].fd, buf, p-buf, 0, (struct sockaddr*)&sll, sizeof(sll)) < 0)
237 /* Be very tough on sending probes: 1 per second with burst of 3. */
239 int queue_active_probe(int ifindex, __u32 addr)
241 static struct timeval prev;
245 gettimeofday(&now, NULL);
247 int diff = (now.tv_sec-prev.tv_sec)*1000+(now.tv_usec-prev.tv_usec)/1000;
250 buckets = broadcast_burst;
252 if (buckets > broadcast_burst)
253 buckets = broadcast_burst;
254 if (buckets >= broadcast_rate && !send_probe(ifindex, addr)) {
255 buckets -= broadcast_rate;
259 stats.probes_suppressed++;
263 int respond_to_kernel(int ifindex, __u32 addr, char *lla, int llalen)
271 memset(&req.n, 0, sizeof(req.n));
272 memset(&req.ndm, 0, sizeof(req.ndm));
274 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
275 req.n.nlmsg_flags = NLM_F_REQUEST;
276 req.n.nlmsg_type = RTM_NEWNEIGH;
277 req.ndm.ndm_family = AF_INET;
278 req.ndm.ndm_state = NUD_STALE;
279 req.ndm.ndm_ifindex = ifindex;
280 req.ndm.ndm_type = RTN_UNICAST;
282 addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4);
283 addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
284 return rtnl_send(&rth, (char*)&req, req.n.nlmsg_len) <= 0;
287 void prepare_neg_entry(__u8 *ndata, __u32 stamp)
291 ndata[2] = stamp>>24;
292 ndata[3] = stamp>>16;
298 int do_one_request(struct nlmsghdr *n)
300 struct ndmsg *ndm = NLMSG_DATA(n);
301 int len = n->nlmsg_len;
302 struct rtattr * tb[NDA_MAX+1];
307 if (n->nlmsg_type == NLMSG_DONE) {
308 dbase->sync(dbase, 0);
310 /* Now we have at least mirror of kernel db, so that
311 * may start real resolution.
313 do_sysctl_adjustments();
317 if (n->nlmsg_type != RTM_GETNEIGH && n->nlmsg_type != RTM_NEWNEIGH)
320 len -= NLMSG_LENGTH(sizeof(*ndm));
324 if (ndm->ndm_family != AF_INET ||
325 (ifnum && !handle_if(ndm->ndm_ifindex)) ||
327 ndm->ndm_type != RTN_UNICAST ||
328 !(ndm->ndm_state&~NUD_NOARP))
331 parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
336 key.iface = ndm->ndm_ifindex;
337 memcpy(&key.addr, RTA_DATA(tb[NDA_DST]), 4);
339 dbkey.size = sizeof(key);
341 if (dbase->get(dbase, &dbkey, &dbdat, 0) != 0) {
346 if (n->nlmsg_type == RTM_GETNEIGH) {
347 if (!(n->nlmsg_flags&NLM_F_REQUEST))
350 if (!(ndm->ndm_state&(NUD_PROBE|NUD_INCOMPLETE))) {
355 if (ndm->ndm_state&NUD_PROBE) {
356 /* If we get this, kernel still has some valid
357 * address, but unicast probing failed and host
358 * is either dead or changed its mac address.
359 * Kernel is going to initiate broadcast resolution.
360 * OK, we invalidate our information as well.
362 if (dbdat.data && !IS_NEG(dbdat.data))
365 dbase->del(dbase, &dbkey, 0);
367 /* If we get this kernel does not have any information.
368 * If we have something tell this to kernel. */
370 if (dbdat.data && !IS_NEG(dbdat.data)) {
372 respond_to_kernel(key.iface, key.addr, dbdat.data, dbdat.size);
376 /* Sheeit! We have nothing to tell. */
377 /* If we have recent negative entry, be silent. */
378 if (dbdat.data && NEG_VALID(dbdat.data)) {
379 if (NEG_CNT(dbdat.data) >= active_probing) {
380 stats.app_suppressed++;
387 if (active_probing &&
388 queue_active_probe(ndm->ndm_ifindex, key.addr) == 0 &&
390 NEG_CNT(dbdat.data)++;
391 dbase->put(dbase, &dbkey, &dbdat, 0);
393 } else if (n->nlmsg_type == RTM_NEWNEIGH) {
394 if (n->nlmsg_flags&NLM_F_REQUEST)
397 if (ndm->ndm_state&NUD_FAILED) {
398 /* Kernel was not able to resolve. Host is dead.
399 * Create negative entry if it is not present
400 * or renew it if it is too old. */
402 !IS_NEG(dbdat.data) ||
403 !NEG_VALID(dbdat.data)) {
406 prepare_neg_entry(ndata, time(NULL));
408 dbdat.size = sizeof(ndata);
409 dbase->put(dbase, &dbkey, &dbdat, 0);
411 } else if (tb[NDA_LLADDR]) {
412 if (dbdat.data && !IS_NEG(dbdat.data)) {
413 if (memcmp(RTA_DATA(tb[NDA_LLADDR]), dbdat.data, dbdat.size) == 0)
419 dbdat.data = RTA_DATA(tb[NDA_LLADDR]);
420 dbdat.size = RTA_PAYLOAD(tb[NDA_LLADDR]);
421 dbase->put(dbase, &dbkey, &dbdat, 0);
427 void load_initial_table(void)
429 rtnl_wilddump_request(&rth, AF_INET, RTM_GETNEIGH);
432 void get_kern_msg(void)
436 struct sockaddr_nl nladdr;
439 struct msghdr msg = {
440 (void*)&nladdr, sizeof(nladdr),
446 memset(&nladdr, 0, sizeof(nladdr));
449 iov.iov_len = sizeof(buf);
451 status = recvmsg(rth.fd, &msg, MSG_DONTWAIT);
456 if (msg.msg_namelen != sizeof(nladdr))
462 for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
463 int len = h->nlmsg_len;
464 int l = len - sizeof(*h);
466 if (l < 0 || len > status)
469 if (do_one_request(h) < 0)
472 status -= NLMSG_ALIGN(len);
473 h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
477 /* Receive gratuitous ARP messages and store them, that's all. */
478 void get_arp_pkt(void)
480 unsigned char buf[1024];
481 struct sockaddr_ll sll;
482 socklen_t sll_len = sizeof(sll);
483 struct arphdr *a = (struct arphdr*)buf;
488 n = recvfrom(pset[0].fd, buf, sizeof(buf), MSG_DONTWAIT,
489 (struct sockaddr*)&sll, &sll_len);
491 if (errno != EINTR && errno != EAGAIN)
492 syslog(LOG_ERR, "recvfrom: %m");
496 if (ifnum && !handle_if(sll.sll_ifindex))
501 if (n < sizeof(*a) ||
502 (a->ar_op != htons(ARPOP_REQUEST) &&
503 a->ar_op != htons(ARPOP_REPLY)) ||
505 a->ar_pro != htons(ETH_P_IP) ||
506 a->ar_hln != sll.sll_halen ||
507 sizeof(*a) + 2*4 + 2*a->ar_hln > n)
510 key.iface = sll.sll_ifindex;
511 memcpy(&key.addr, (char*)(a+1) + a->ar_hln, 4);
513 /* DAD message, ignore. */
518 dbkey.size = sizeof(key);
520 if (dbase->get(dbase, &dbkey, &dbdat, 0) == 0 && !IS_NEG(dbdat.data)) {
521 if (memcmp(dbdat.data, a+1, dbdat.size) == 0)
529 dbdat.size = a->ar_hln;
530 dbase->put(dbase, &dbkey, &dbdat, 0);
533 void catch_signal(int sig, void (*handler)(int))
537 memset(&sa, 0, sizeof(sa));
538 sa.sa_handler = handler;
540 sa.sa_flags = SA_INTERRUPT;
542 sigaction(sig, &sa, NULL);
547 volatile int in_poll;
549 void sig_exit(int signo)
556 void sig_sync(int signo)
563 void sig_stats(int signo)
571 void send_stats(void)
573 syslog(LOG_INFO, "arp_rcv: n%lu c%lu app_rcv: tot %lu hits %lu bad %lu neg %lu sup %lu",
574 stats.arp_new, stats.arp_change,
576 stats.app_recv, stats.app_success,
577 stats.app_bad, stats.app_neg, stats.app_suppressed
579 syslog(LOG_INFO, "kern: n%lu c%lu neg %lu arp_send: %lu rlim %lu",
580 stats.kern_new, stats.kern_change, stats.kern_neg,
582 stats.probes_sent, stats.probes_suppressed
588 int main(int argc, char **argv)
592 char *do_load = NULL;
594 while ((opt = getopt(argc, argv, "h?b:lf:a:n:kR:B:")) != EOF) {
601 fprintf(stderr, "Duplicate option -f\n");
610 active_probing = atoi(optarg);
613 negative_timeout = atoi(optarg);
616 no_kernel_broadcasts = 1;
619 if ((broadcast_rate = atoi(optarg)) <= 0 ||
620 (broadcast_rate = 1000/broadcast_rate) <= 0) {
621 fprintf(stderr, "Invalid ARP rate\n");
626 if ((broadcast_burst = atoi(optarg)) <= 0 ||
627 (broadcast_burst = 1000*broadcast_burst) <= 0) {
628 fprintf(stderr, "Invalid ARP burst\n");
644 ifvec = malloc(argc*sizeof(int));
651 if ((udp_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
659 memset(&ifr, 0, sizeof(ifr));
660 for (i=0; i<ifnum; i++) {
661 strncpy(ifr.ifr_name, ifnames[i], IFNAMSIZ);
662 if (ioctl(udp_sock, SIOCGIFINDEX, &ifr)) {
663 perror("ioctl(SIOCGIFINDEX)");
666 ifvec[i] = ifr.ifr_ifindex;
670 dbase = dbopen(dbname, O_CREAT|O_RDWR, 0644, DB_HASH, NULL);
683 dbkey.size = sizeof(k);
685 if (strcmp(do_load, "-") == 0 || strcmp(do_load, "--") == 0) {
687 } else if ((fp = fopen(do_load, "r")) == NULL) {
692 buf[sizeof(buf)-1] = 0;
693 while (fgets(buf, sizeof(buf)-1, fp)) {
701 if (sscanf(buf, "%u%s%s", &k.iface, ipbuf, macbuf) != 3) {
702 fprintf(stderr, "Wrong format of input file \"%s\"\n", do_load);
705 if (strncmp(macbuf, "FAILED:", 7) == 0)
707 if (!inet_aton(ipbuf, (struct in_addr*)&k.addr)) {
708 fprintf(stderr, "Invalid IP address: \"%s\"\n", ipbuf);
712 dbdat.data = hexstring_a2n(macbuf, b1, 6);
713 if (dbdat.data == NULL)
717 if (dbase->put(dbase, &dbkey, &dbdat, 0)) {
722 dbase->sync(dbase, 0);
729 printf("%-8s %-15s %s\n", "#Ifindex", "IP", "MAC");
730 while (dbase->seq(dbase, &dbkey, &dbdat, R_NEXT) == 0) {
731 struct dbkey *key = dbkey.data;
732 if (handle_if(key->iface)) {
733 if (!IS_NEG(dbdat.data)) {
735 printf("%-8d %-15s %s\n",
737 inet_ntoa(*(struct in_addr*)&key->addr),
738 hexstring_n2a(dbdat.data, 6, b1, 18));
740 printf("%-8d %-15s FAILED: %dsec ago\n",
742 inet_ntoa(*(struct in_addr*)&key->addr),
743 NEG_AGE(dbdat.data));
749 if (do_load || do_list)
752 pset[0].fd = socket(PF_PACKET, SOCK_DGRAM, 0);
753 if (pset[0].fd < 0) {
759 struct sockaddr_ll sll;
760 memset(&sll, 0, sizeof(sll));
761 sll.sll_family = AF_PACKET;
762 sll.sll_protocol = htons(ETH_P_ARP);
763 sll.sll_ifindex = (ifnum == 1 ? ifvec[0] : 0);
764 if (bind(pset[0].fd, (struct sockaddr*)&sll, sizeof(sll)) < 0) {
770 if (rtnl_open(&rth, RTMGRP_NEIGH) < 0) {
776 load_initial_table();
785 perror("arpd: fork");
790 fd = open("/dev/null", O_RDWR);
801 openlog("arpd", LOG_PID | LOG_CONS, LOG_DAEMON);
802 catch_signal(SIGINT, sig_exit);
803 catch_signal(SIGTERM, sig_exit);
804 catch_signal(SIGHUP, sig_sync);
805 catch_signal(SIGUSR1, sig_stats);
807 #define EVENTS (POLLIN|POLLPRI|POLLERR|POLLHUP)
808 pset[0].events = EVENTS;
810 pset[1].events = EVENTS;
822 dbase->sync(dbase, 0);
828 if (poll(pset, 2, 30000) > 0) {
830 if (pset[0].revents&EVENTS)
832 if (pset[1].revents&EVENTS)
839 undo_sysctl_adjustments();