]> git.proxmox.com Git - mirror_iproute2.git/blob - misc/arpd.c
Merge branch 'master' into net-next
[mirror_iproute2.git] / misc / arpd.c
1 /*
2 * arpd.c ARP helper daemon.
3 *
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.
8 *
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10 */
11
12 #include <stdio.h>
13 #include <syslog.h>
14 #include <malloc.h>
15 #include <string.h>
16 #include <unistd.h>
17 #include <stdlib.h>
18 #include <netdb.h>
19 #include <db_185.h>
20 #include <sys/ioctl.h>
21 #include <sys/poll.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <sys/uio.h>
25 #include <sys/socket.h>
26 #include <sys/time.h>
27 #include <time.h>
28 #include <signal.h>
29 #include <linux/if.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>
36
37 #include "libnetlink.h"
38 #include "utils.h"
39 #include "rt_names.h"
40
41 int resolve_hosts;
42
43 DB *dbase;
44 char *dbname = "/var/lib/arpd/arpd.db";
45
46 int ifnum;
47 int *ifvec;
48 char **ifnames;
49
50 struct dbkey {
51 __u32 iface;
52 __u32 addr;
53 };
54
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])
60
61 struct rtnl_handle rth;
62
63 struct pollfd pset[2];
64 int udp_sock = -1;
65
66 volatile int do_exit;
67 volatile int do_sync;
68 volatile int do_stats;
69
70 struct {
71 unsigned long arp_new;
72 unsigned long arp_change;
73
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;
79
80 unsigned long kern_neg;
81 unsigned long kern_new;
82 unsigned long kern_change;
83
84 unsigned long probes_sent;
85 unsigned long probes_suppressed;
86 } stats;
87
88 int active_probing;
89 int negative_timeout = 60;
90 int no_kernel_broadcasts;
91 int broadcast_rate = 1000;
92 int broadcast_burst = 3000;
93 int poll_timeout = 30000;
94
95 static void usage(void)
96 {
97 fprintf(stderr,
98 "Usage: arpd [ -lkh? ] [ -a N ] [ -b dbase ] [ -B number ] [ -f file ] [ -n time ] [-p interval ] [ -R rate ] [ interfaces ]\n");
99 exit(1);
100 }
101
102 static int handle_if(int ifindex)
103 {
104 int i;
105
106 if (ifnum == 0)
107 return 1;
108
109 for (i = 0; i < ifnum; i++)
110 if (ifvec[i] == ifindex)
111 return 1;
112 return 0;
113 }
114
115 int sysctl_adjusted;
116
117 static void do_sysctl_adjustments(void)
118 {
119 int i;
120
121 if (!ifnum)
122 return;
123
124 for (i = 0; i < ifnum; i++) {
125 char buf[128];
126 FILE *fp;
127
128 if (active_probing) {
129 sprintf(buf, "/proc/sys/net/ipv4/neigh/%s/mcast_solicit", ifnames[i]);
130 if ((fp = fopen(buf, "w")) != NULL) {
131 if (no_kernel_broadcasts)
132 strcpy(buf, "0\n");
133 else
134 sprintf(buf, "%d\n", active_probing >= 2 ? 1 : 3-active_probing);
135 fputs(buf, fp);
136 fclose(fp);
137 }
138 }
139
140 sprintf(buf, "/proc/sys/net/ipv4/neigh/%s/app_solicit", ifnames[i]);
141 if ((fp = fopen(buf, "w")) != NULL) {
142 sprintf(buf, "%d\n", active_probing <= 1 ? 1 : active_probing);
143 fputs(buf, fp);
144 fclose(fp);
145 }
146 }
147 sysctl_adjusted = 1;
148 }
149
150 static void undo_sysctl_adjustments(void)
151 {
152 int i;
153
154 if (!sysctl_adjusted)
155 return;
156
157 for (i = 0; i < ifnum; i++) {
158 char buf[128];
159 FILE *fp;
160
161 if (active_probing) {
162 sprintf(buf, "/proc/sys/net/ipv4/neigh/%s/mcast_solicit", ifnames[i]);
163 if ((fp = fopen(buf, "w")) != NULL) {
164 strcpy(buf, "3\n");
165 fputs(buf, fp);
166 fclose(fp);
167 }
168 }
169 sprintf(buf, "/proc/sys/net/ipv4/neigh/%s/app_solicit", ifnames[i]);
170 if ((fp = fopen(buf, "w")) != NULL) {
171 strcpy(buf, "0\n");
172 fputs(buf, fp);
173 fclose(fp);
174 }
175 }
176 sysctl_adjusted = 0;
177 }
178
179
180 static int send_probe(int ifindex, __u32 addr)
181 {
182 struct ifreq ifr = { .ifr_ifindex = ifindex };
183 struct sockaddr_in dst = {
184 .sin_family = AF_INET,
185 .sin_port = htons(1025),
186 .sin_addr.s_addr = addr,
187 };
188 socklen_t len;
189 unsigned char buf[256];
190 struct arphdr *ah = (struct arphdr *)buf;
191 unsigned char *p = (unsigned char *)(ah+1);
192 struct sockaddr_ll sll = {
193 .sll_family = AF_PACKET,
194 .sll_ifindex = ifindex,
195 .sll_protocol = htons(ETH_P_ARP),
196 };
197
198 if (ioctl(udp_sock, SIOCGIFNAME, &ifr))
199 return -1;
200 if (ioctl(udp_sock, SIOCGIFHWADDR, &ifr))
201 return -1;
202 if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)
203 return -1;
204 if (setsockopt(udp_sock, SOL_SOCKET, SO_BINDTODEVICE, ifr.ifr_name, strlen(ifr.ifr_name)+1) < 0)
205 return -1;
206
207 if (connect(udp_sock, (struct sockaddr *)&dst, sizeof(dst)) < 0)
208 return -1;
209 len = sizeof(dst);
210 if (getsockname(udp_sock, (struct sockaddr *)&dst, &len) < 0)
211 return -1;
212
213 ah->ar_hrd = htons(ifr.ifr_hwaddr.sa_family);
214 ah->ar_pro = htons(ETH_P_IP);
215 ah->ar_hln = 6;
216 ah->ar_pln = 4;
217 ah->ar_op = htons(ARPOP_REQUEST);
218
219 memcpy(p, ifr.ifr_hwaddr.sa_data, ah->ar_hln);
220 p += ah->ar_hln;
221
222 memcpy(p, &dst.sin_addr, 4);
223 p += 4;
224
225 memset(sll.sll_addr, 0xFF, sizeof(sll.sll_addr));
226 memcpy(p, &sll.sll_addr, ah->ar_hln);
227 p += ah->ar_hln;
228
229 memcpy(p, &addr, 4);
230 p += 4;
231
232 if (sendto(pset[0].fd, buf, p-buf, 0, (struct sockaddr *)&sll, sizeof(sll)) < 0)
233 return -1;
234 stats.probes_sent++;
235 return 0;
236 }
237
238 /* Be very tough on sending probes: 1 per second with burst of 3. */
239
240 static int queue_active_probe(int ifindex, __u32 addr)
241 {
242 static struct timeval prev;
243 static int buckets;
244 struct timeval now;
245
246 gettimeofday(&now, NULL);
247 if (prev.tv_sec) {
248 int diff = (now.tv_sec-prev.tv_sec)*1000+(now.tv_usec-prev.tv_usec)/1000;
249
250 buckets += diff;
251 } else {
252 buckets = broadcast_burst;
253 }
254 if (buckets > broadcast_burst)
255 buckets = broadcast_burst;
256 if (buckets >= broadcast_rate && !send_probe(ifindex, addr)) {
257 buckets -= broadcast_rate;
258 prev = now;
259 return 0;
260 }
261 stats.probes_suppressed++;
262 return -1;
263 }
264
265 static int respond_to_kernel(int ifindex, __u32 addr, char *lla, int llalen)
266 {
267 struct {
268 struct nlmsghdr n;
269 struct ndmsg ndm;
270 char buf[256];
271 } req = {
272 .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)),
273 .n.nlmsg_flags = NLM_F_REQUEST,
274 .n.nlmsg_type = RTM_NEWNEIGH,
275 .ndm.ndm_family = AF_INET,
276 .ndm.ndm_state = NUD_STALE,
277 .ndm.ndm_ifindex = ifindex,
278 .ndm.ndm_type = RTN_UNICAST,
279 };
280
281 addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4);
282 addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
283 return rtnl_send(&rth, &req, req.n.nlmsg_len) <= 0;
284 }
285
286 static void prepare_neg_entry(__u8 *ndata, __u32 stamp)
287 {
288 ndata[0] = 0xFF;
289 ndata[1] = 0;
290 ndata[2] = stamp>>24;
291 ndata[3] = stamp>>16;
292 ndata[4] = stamp>>8;
293 ndata[5] = stamp;
294 }
295
296
297 static int do_one_request(struct nlmsghdr *n)
298 {
299 struct ndmsg *ndm = NLMSG_DATA(n);
300 int len = n->nlmsg_len;
301 struct rtattr *tb[NDA_MAX+1];
302 struct dbkey key;
303 DBT dbkey, dbdat;
304 int do_acct = 0;
305
306 if (n->nlmsg_type == NLMSG_DONE) {
307 dbase->sync(dbase, 0);
308
309 /* Now we have at least mirror of kernel db, so that
310 * may start real resolution.
311 */
312 do_sysctl_adjustments();
313 return 0;
314 }
315
316 if (n->nlmsg_type != RTM_GETNEIGH && n->nlmsg_type != RTM_NEWNEIGH)
317 return 0;
318
319 len -= NLMSG_LENGTH(sizeof(*ndm));
320 if (len < 0)
321 return -1;
322
323 if (ndm->ndm_family != AF_INET ||
324 (ifnum && !handle_if(ndm->ndm_ifindex)) ||
325 ndm->ndm_flags ||
326 ndm->ndm_type != RTN_UNICAST ||
327 !(ndm->ndm_state&~NUD_NOARP))
328 return 0;
329
330 parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
331
332 if (!tb[NDA_DST])
333 return 0;
334
335 key.iface = ndm->ndm_ifindex;
336 memcpy(&key.addr, RTA_DATA(tb[NDA_DST]), 4);
337 dbkey.data = &key;
338 dbkey.size = sizeof(key);
339
340 if (dbase->get(dbase, &dbkey, &dbdat, 0) != 0) {
341 dbdat.data = 0;
342 dbdat.size = 0;
343 }
344
345 if (n->nlmsg_type == RTM_GETNEIGH) {
346 if (!(n->nlmsg_flags&NLM_F_REQUEST))
347 return 0;
348
349 if (!(ndm->ndm_state&(NUD_PROBE|NUD_INCOMPLETE))) {
350 stats.app_bad++;
351 return 0;
352 }
353
354 if (ndm->ndm_state&NUD_PROBE) {
355 /* If we get this, kernel still has some valid
356 * address, but unicast probing failed and host
357 * is either dead or changed its mac address.
358 * Kernel is going to initiate broadcast resolution.
359 * OK, we invalidate our information as well.
360 */
361 if (dbdat.data && !IS_NEG(dbdat.data))
362 stats.app_neg++;
363
364 dbase->del(dbase, &dbkey, 0);
365 } else {
366 /* If we get this kernel does not have any information.
367 * If we have something tell this to kernel. */
368 stats.app_recv++;
369 if (dbdat.data && !IS_NEG(dbdat.data)) {
370 stats.app_success++;
371 respond_to_kernel(key.iface, key.addr, dbdat.data, dbdat.size);
372 return 0;
373 }
374
375 /* Sheeit! We have nothing to tell. */
376 /* If we have recent negative entry, be silent. */
377 if (dbdat.data && NEG_VALID(dbdat.data)) {
378 if (NEG_CNT(dbdat.data) >= active_probing) {
379 stats.app_suppressed++;
380 return 0;
381 }
382 do_acct = 1;
383 }
384 }
385
386 if (active_probing &&
387 queue_active_probe(ndm->ndm_ifindex, key.addr) == 0 &&
388 do_acct) {
389 NEG_CNT(dbdat.data)++;
390 dbase->put(dbase, &dbkey, &dbdat, 0);
391 }
392 } else if (n->nlmsg_type == RTM_NEWNEIGH) {
393 if (n->nlmsg_flags&NLM_F_REQUEST)
394 return 0;
395
396 if (ndm->ndm_state&NUD_FAILED) {
397 /* Kernel was not able to resolve. Host is dead.
398 * Create negative entry if it is not present
399 * or renew it if it is too old. */
400 if (!dbdat.data ||
401 !IS_NEG(dbdat.data) ||
402 !NEG_VALID(dbdat.data)) {
403 __u8 ndata[6];
404
405 stats.kern_neg++;
406 prepare_neg_entry(ndata, time(NULL));
407 dbdat.data = ndata;
408 dbdat.size = sizeof(ndata);
409 dbase->put(dbase, &dbkey, &dbdat, 0);
410 }
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)
414 return 0;
415 stats.kern_change++;
416 } else {
417 stats.kern_new++;
418 }
419 dbdat.data = RTA_DATA(tb[NDA_LLADDR]);
420 dbdat.size = RTA_PAYLOAD(tb[NDA_LLADDR]);
421 dbase->put(dbase, &dbkey, &dbdat, 0);
422 }
423 }
424 return 0;
425 }
426
427 static void load_initial_table(void)
428 {
429 if (rtnl_wilddump_request(&rth, AF_INET, RTM_GETNEIGH) < 0) {
430 perror("dump request failed");
431 exit(1);
432 }
433
434 }
435
436 static void get_kern_msg(void)
437 {
438 int status;
439 struct nlmsghdr *h;
440 struct sockaddr_nl nladdr = {};
441 struct iovec iov;
442 char buf[8192];
443 struct msghdr msg = {
444 (void *)&nladdr, sizeof(nladdr),
445 &iov, 1,
446 NULL, 0,
447 0
448 };
449
450 iov.iov_base = buf;
451 iov.iov_len = sizeof(buf);
452
453 status = recvmsg(rth.fd, &msg, MSG_DONTWAIT);
454
455 if (status <= 0)
456 return;
457
458 if (msg.msg_namelen != sizeof(nladdr))
459 return;
460
461 if (nladdr.nl_pid)
462 return;
463
464 for (h = (struct nlmsghdr *)buf; status >= sizeof(*h); ) {
465 int len = h->nlmsg_len;
466 int l = len - sizeof(*h);
467
468 if (l < 0 || len > status)
469 return;
470
471 if (do_one_request(h) < 0)
472 return;
473
474 status -= NLMSG_ALIGN(len);
475 h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len));
476 }
477 }
478
479 /* Receive gratuitous ARP messages and store them, that's all. */
480 static void get_arp_pkt(void)
481 {
482 unsigned char buf[1024];
483 struct sockaddr_ll sll;
484 socklen_t sll_len = sizeof(sll);
485 struct arphdr *a = (struct arphdr *)buf;
486 struct dbkey key;
487 DBT dbkey, dbdat;
488 int n;
489
490 n = recvfrom(pset[0].fd, buf, sizeof(buf), MSG_DONTWAIT,
491 (struct sockaddr *)&sll, &sll_len);
492 if (n < 0) {
493 if (errno != EINTR && errno != EAGAIN)
494 syslog(LOG_ERR, "recvfrom: %m");
495 return;
496 }
497
498 if (ifnum && !handle_if(sll.sll_ifindex))
499 return;
500
501 /* Sanity checks */
502
503 if (n < sizeof(*a) ||
504 (a->ar_op != htons(ARPOP_REQUEST) &&
505 a->ar_op != htons(ARPOP_REPLY)) ||
506 a->ar_pln != 4 ||
507 a->ar_pro != htons(ETH_P_IP) ||
508 a->ar_hln != sll.sll_halen ||
509 sizeof(*a) + 2*4 + 2*a->ar_hln > n)
510 return;
511
512 key.iface = sll.sll_ifindex;
513 memcpy(&key.addr, (char *)(a+1) + a->ar_hln, 4);
514
515 /* DAD message, ignore. */
516 if (key.addr == 0)
517 return;
518
519 dbkey.data = &key;
520 dbkey.size = sizeof(key);
521
522 if (dbase->get(dbase, &dbkey, &dbdat, 0) == 0 && !IS_NEG(dbdat.data)) {
523 if (memcmp(dbdat.data, a+1, dbdat.size) == 0)
524 return;
525 stats.arp_change++;
526 } else {
527 stats.arp_new++;
528 }
529
530 dbdat.data = a+1;
531 dbdat.size = a->ar_hln;
532 dbase->put(dbase, &dbkey, &dbdat, 0);
533 }
534
535 static void catch_signal(int sig, void (*handler)(int))
536 {
537 struct sigaction sa = { .sa_handler = handler };
538
539 #ifdef SA_INTERRUPT
540 sa.sa_flags = SA_INTERRUPT;
541 #endif
542 sigaction(sig, &sa, NULL);
543 }
544
545 #include <setjmp.h>
546 sigjmp_buf env;
547 volatile int in_poll;
548
549 static void sig_exit(int signo)
550 {
551 do_exit = 1;
552 if (in_poll)
553 siglongjmp(env, 1);
554 }
555
556 static void sig_sync(int signo)
557 {
558 do_sync = 1;
559 if (in_poll)
560 siglongjmp(env, 1);
561 }
562
563 static void sig_stats(int signo)
564 {
565 do_sync = 1;
566 do_stats = 1;
567 if (in_poll)
568 siglongjmp(env, 1);
569 }
570
571 static void send_stats(void)
572 {
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,
575
576 stats.app_recv, stats.app_success,
577 stats.app_bad, stats.app_neg, stats.app_suppressed
578 );
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,
581
582 stats.probes_sent, stats.probes_suppressed
583 );
584 do_stats = 0;
585 }
586
587
588 int main(int argc, char **argv)
589 {
590 int opt;
591 int do_list = 0;
592 char *do_load = NULL;
593
594 while ((opt = getopt(argc, argv, "h?b:lf:a:n:p:kR:B:")) != EOF) {
595 switch (opt) {
596 case 'b':
597 dbname = optarg;
598 break;
599 case 'f':
600 if (do_load) {
601 fprintf(stderr, "Duplicate option -f\n");
602 usage();
603 }
604 do_load = optarg;
605 break;
606 case 'l':
607 do_list = 1;
608 break;
609 case 'a':
610 active_probing = atoi(optarg);
611 break;
612 case 'n':
613 negative_timeout = atoi(optarg);
614 break;
615 case 'k':
616 no_kernel_broadcasts = 1;
617 break;
618 case 'p':
619 if ((poll_timeout = 1000 * strtod(optarg, NULL)) < 100) {
620 fprintf(stderr, "Invalid poll timeout\n");
621 exit(-1);
622 }
623 break;
624 case 'R':
625 if ((broadcast_rate = atoi(optarg)) <= 0 ||
626 (broadcast_rate = 1000/broadcast_rate) <= 0) {
627 fprintf(stderr, "Invalid ARP rate\n");
628 exit(-1);
629 }
630 break;
631 case 'B':
632 if ((broadcast_burst = atoi(optarg)) <= 0 ||
633 (broadcast_burst = 1000*broadcast_burst) <= 0) {
634 fprintf(stderr, "Invalid ARP burst\n");
635 exit(-1);
636 }
637 break;
638 case 'h':
639 case '?':
640 default:
641 usage();
642 }
643 }
644 argc -= optind;
645 argv += optind;
646
647 if (argc > 0) {
648 ifnum = argc;
649 ifnames = argv;
650 ifvec = malloc(argc*sizeof(int));
651 if (!ifvec) {
652 perror("malloc");
653 exit(-1);
654 }
655 }
656
657 if ((udp_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
658 perror("socket");
659 exit(-1);
660 }
661
662 if (ifnum) {
663 int i;
664 struct ifreq ifr = {};
665
666 for (i = 0; i < ifnum; i++) {
667 if (get_ifname(ifr.ifr_name, ifnames[i]))
668 invarg("not a valid ifname", ifnames[i]);
669 if (ioctl(udp_sock, SIOCGIFINDEX, &ifr)) {
670 perror("ioctl(SIOCGIFINDEX)");
671 exit(-1);
672 }
673 ifvec[i] = ifr.ifr_ifindex;
674 }
675 }
676
677 dbase = dbopen(dbname, O_CREAT|O_RDWR, 0644, DB_HASH, NULL);
678 if (dbase == NULL) {
679 perror("db_open");
680 exit(-1);
681 }
682
683 if (do_load) {
684 char buf[128];
685 FILE *fp;
686 struct dbkey k;
687 DBT dbkey, dbdat;
688
689 dbkey.data = &k;
690 dbkey.size = sizeof(k);
691
692 if (strcmp(do_load, "-") == 0 || strcmp(do_load, "--") == 0) {
693 fp = stdin;
694 } else if ((fp = fopen(do_load, "r")) == NULL) {
695 perror("fopen");
696 goto do_abort;
697 }
698
699 buf[sizeof(buf)-1] = 0;
700 while (fgets(buf, sizeof(buf), fp)) {
701 __u8 b1[6];
702 char ipbuf[128];
703 char macbuf[128];
704
705 if (buf[0] == '#')
706 continue;
707
708 if (sscanf(buf, "%u%s%s", &k.iface, ipbuf, macbuf) != 3) {
709 fprintf(stderr, "Wrong format of input file \"%s\"\n", do_load);
710 goto do_abort;
711 }
712 if (strncmp(macbuf, "FAILED:", 7) == 0)
713 continue;
714 if (!inet_aton(ipbuf, (struct in_addr *)&k.addr)) {
715 fprintf(stderr, "Invalid IP address: \"%s\"\n", ipbuf);
716 goto do_abort;
717 }
718
719 if (ll_addr_a2n((char *) b1, 6, macbuf) != 6)
720 goto do_abort;
721 dbdat.size = 6;
722
723 if (dbase->put(dbase, &dbkey, &dbdat, 0)) {
724 perror("hash->put");
725 goto do_abort;
726 }
727 }
728 dbase->sync(dbase, 0);
729 if (fp != stdin)
730 fclose(fp);
731 }
732
733 if (do_list) {
734 DBT dbkey, dbdat;
735
736 printf("%-8s %-15s %s\n", "#Ifindex", "IP", "MAC");
737 while (dbase->seq(dbase, &dbkey, &dbdat, R_NEXT) == 0) {
738 struct dbkey *key = dbkey.data;
739
740 if (handle_if(key->iface)) {
741 if (!IS_NEG(dbdat.data)) {
742 char b1[18];
743
744 printf("%-8d %-15s %s\n",
745 key->iface,
746 inet_ntoa(*(struct in_addr *)&key->addr),
747 ll_addr_n2a(dbdat.data, 6, ARPHRD_ETHER, b1, 18));
748 } else {
749 printf("%-8d %-15s FAILED: %dsec ago\n",
750 key->iface,
751 inet_ntoa(*(struct in_addr *)&key->addr),
752 NEG_AGE(dbdat.data));
753 }
754 }
755 }
756 }
757
758 if (do_load || do_list)
759 goto out;
760
761 pset[0].fd = socket(PF_PACKET, SOCK_DGRAM, 0);
762 if (pset[0].fd < 0) {
763 perror("socket");
764 exit(-1);
765 }
766
767 if (1) {
768 struct sockaddr_ll sll = {
769 .sll_family = AF_PACKET,
770 .sll_protocol = htons(ETH_P_ARP),
771 .sll_ifindex = (ifnum == 1 ? ifvec[0] : 0),
772 };
773
774 if (bind(pset[0].fd, (struct sockaddr *)&sll, sizeof(sll)) < 0) {
775 perror("bind");
776 goto do_abort;
777 }
778 }
779
780 if (rtnl_open(&rth, RTMGRP_NEIGH) < 0) {
781 perror("rtnl_open");
782 goto do_abort;
783 }
784 pset[1].fd = rth.fd;
785
786 load_initial_table();
787
788 if (daemon(0, 0)) {
789 perror("arpd: daemon");
790 goto do_abort;
791 }
792
793 openlog("arpd", LOG_PID | LOG_CONS, LOG_DAEMON);
794 catch_signal(SIGINT, sig_exit);
795 catch_signal(SIGTERM, sig_exit);
796 catch_signal(SIGHUP, sig_sync);
797 catch_signal(SIGUSR1, sig_stats);
798
799 #define EVENTS (POLLIN|POLLPRI|POLLERR|POLLHUP)
800 pset[0].events = EVENTS;
801 pset[0].revents = 0;
802 pset[1].events = EVENTS;
803 pset[1].revents = 0;
804
805 sigsetjmp(env, 1);
806
807 for (;;) {
808 in_poll = 1;
809
810 if (do_exit)
811 break;
812 if (do_sync) {
813 in_poll = 0;
814 dbase->sync(dbase, 0);
815 do_sync = 0;
816 in_poll = 1;
817 }
818 if (do_stats)
819 send_stats();
820 if (poll(pset, 2, poll_timeout) > 0) {
821 in_poll = 0;
822 if (pset[0].revents&EVENTS)
823 get_arp_pkt();
824 if (pset[1].revents&EVENTS)
825 get_kern_msg();
826 } else {
827 do_sync = 1;
828 }
829 }
830
831 undo_sysctl_adjustments();
832 out:
833 dbase->close(dbase);
834 exit(0);
835
836 do_abort:
837 dbase->close(dbase);
838 exit(-1);
839 }