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