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