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