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