1313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/*
2313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * rarpd.c	RARP daemon.
3313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *
4313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *		This program is free software; you can redistribute it and/or
5313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *		modify it under the terms of the GNU General Public License
6313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *		as published by the Free Software Foundation; either version
7313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *		2 of the License, or (at your option) any later version.
8313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *
9313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */
11313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
12313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <stdio.h>
13313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <syslog.h>
14313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <dirent.h>
15313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <malloc.h>
16313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <string.h>
17313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <unistd.h>
18313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <stdlib.h>
19313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <netdb.h>
20313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <arpa/inet.h>
21313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/ioctl.h>
22313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/poll.h>
23313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/errno.h>
24313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/fcntl.h>
25313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/socket.h>
26313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/signal.h>
27313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/if.h>
28313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/if_arp.h>
29313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <netinet/in.h>
30313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/if_packet.h>
31313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/filter.h>
32313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
33313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint do_reload = 1;
34313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
35313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint debug;
36313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint verbose;
37313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint ifidx;
38313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint allow_offlink;
39313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint only_ethers;
40313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint all_ifaces;
41313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint listen_arp;
42313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittichar *ifname;
43313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittichar *tftp_dir = "/etc/tftpboot";
44313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
45313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiextern int ether_ntohost(char *name, unsigned char *ea);
46313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid usage(void) __attribute__((noreturn));
47313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
48313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct iflink
49313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
50313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct iflink	*next;
51313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int	       	index;
52313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int		hatype;
53313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	unsigned char	lladdr[16];
54313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	char		name[IFNAMSIZ];
55313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct ifaddr 	*ifa_list;
56313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} *ifl_list;
57313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
58313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct ifaddr
59313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
60313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct ifaddr 	*next;
61313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	__u32		prefix;
62313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	__u32		mask;
63313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	__u32		local;
64313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti};
65313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
66313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct rarp_map
67313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
68313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct rarp_map *next;
69313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
70313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int		ifindex;
71313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int		arp_type;
72313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int		lladdr_len;
73313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	unsigned char	lladdr[16];
74313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	__u32		ipaddr;
75313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} *rarp_db;
76313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
77313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid usage()
78313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
79313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	fprintf(stderr, "Usage: rarpd [ -dveaA ] [ -b tftpdir ] [ interface]\n");
80313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	exit(1);
81313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
82313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
83313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid load_db(void)
84313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
85313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
86313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
87313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid load_if(void)
88313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
89313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int fd;
90313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct ifreq *ifrp, *ifend;
91313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct iflink *ifl;
92313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct ifaddr *ifa;
93313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct ifconf ifc;
94313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct ifreq ibuf[256];
95313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
96313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
97313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		syslog(LOG_ERR, "socket: %m");
98313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return;
99313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
100313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
101313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	ifc.ifc_len = sizeof ibuf;
102313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	ifc.ifc_buf = (caddr_t)ibuf;
103313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
104313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	    ifc.ifc_len < (int)sizeof(struct ifreq)) {
105313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		syslog(LOG_ERR, "SIOCGIFCONF: %m");
106313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		close(fd);
107313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return;
108313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
109313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
110313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	while ((ifl = ifl_list) != NULL) {
111313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		while ((ifa = ifl->ifa_list) != NULL) {
112313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ifl->ifa_list = ifa->next;
113313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			free(ifa);
114313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
115313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ifl_list = ifl->next;
116313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		free(ifl);
117313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
118313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
119313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
120313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for (ifrp = ibuf; ifrp < ifend; ifrp++) {
121313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		__u32 addr;
122313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		__u32 mask;
123313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		__u32 prefix;
124313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
125313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (ifrp->ifr_addr.sa_family != AF_INET)
126313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			continue;
127313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		addr = ((struct sockaddr_in*)&ifrp->ifr_addr)->sin_addr.s_addr;
128313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (addr == 0)
129313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			continue;
130313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (ioctl(fd, SIOCGIFINDEX, ifrp)) {
131313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			syslog(LOG_ERR, "ioctl(SIOCGIFNAME): %m");
132313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			continue;
133313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
134313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (ifidx && ifrp->ifr_ifindex != ifidx)
135313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			continue;
136313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		for (ifl = ifl_list; ifl; ifl = ifl->next)
137313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (ifl->index == ifrp->ifr_ifindex)
138313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				break;
139313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (ifl == NULL) {
140313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			char *p;
141313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			int index = ifrp->ifr_ifindex;
142313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
143313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (ioctl(fd, SIOCGIFHWADDR, ifrp)) {
144313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				syslog(LOG_ERR, "ioctl(SIOCGIFHWADDR): %m");
145313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				continue;
146313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
147313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
148313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ifl = (struct iflink*)malloc(sizeof(*ifl));
149313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (ifl == NULL)
150313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				continue;
151313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			memset(ifl, 0, sizeof(*ifl));
152313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ifl->next = ifl_list;
153313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ifl_list = ifl;
154313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ifl->index = index;
155313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ifl->hatype = ifrp->ifr_hwaddr.sa_family;
156313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			memcpy(ifl->lladdr, ifrp->ifr_hwaddr.sa_data, 14);
157313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			strncpy(ifl->name, ifrp->ifr_name, IFNAMSIZ);
158313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			p = strchr(ifl->name, ':');
159313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (p)
160313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				*p = 0;
161313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (verbose)
162313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				syslog(LOG_INFO, "link %s", ifl->name);
163313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
164313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (ioctl(fd, SIOCGIFNETMASK, ifrp)) {
165313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			syslog(LOG_ERR, "ioctl(SIOCGIFMASK): %m");
166313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			continue;
167313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
168313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		mask = ((struct sockaddr_in*)&ifrp->ifr_netmask)->sin_addr.s_addr;
169313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (ioctl(fd, SIOCGIFDSTADDR, ifrp)) {
170313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			syslog(LOG_ERR, "ioctl(SIOCGIFDSTADDR): %m");
171313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			continue;
172313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
173313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		prefix = ((struct sockaddr_in*)&ifrp->ifr_dstaddr)->sin_addr.s_addr;
174313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		for (ifa = ifl->ifa_list; ifa; ifa = ifa->next) {
175313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (ifa->local == addr &&
176313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			    ifa->prefix == prefix &&
177313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			    ifa->mask == mask)
178313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				break;
179313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
180313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (ifa == NULL) {
181313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (mask == 0 || prefix == 0)
182313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				continue;
183313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ifa = (struct ifaddr*)malloc(sizeof(*ifa));
184313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			memset(ifa, 0, sizeof(*ifa));
185313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ifa->local = addr;
186313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ifa->prefix = prefix;
187313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ifa->mask = mask;
188313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ifa->next = ifl->ifa_list;
189313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ifl->ifa_list = ifa;
190313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
191313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (verbose) {
192313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				int i;
193313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				__u32 m = ~0U;
194313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				for (i=32; i>=0; i--) {
195313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					if (htonl(m) == mask)
196313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti						break;
197313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					m <<= 1;
198313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				}
199313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (addr == prefix) {
200313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					syslog(LOG_INFO, "  addr %s/%d on %s\n",
201313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					       inet_ntoa(*(struct in_addr*)&addr), i, ifl->name);
202313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				} else {
203313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					char tmpa[64];
204313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					sprintf(tmpa, "%s", inet_ntoa(*(struct in_addr*)&addr));
205313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					syslog(LOG_INFO, "  addr %s %s/%d on %s\n", tmpa,
206313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					       inet_ntoa(*(struct in_addr*)&prefix), i, ifl->name);
207313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				}
208313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
209313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
210313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
211313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
212313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
213313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid configure(void)
214313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
215313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	load_if();
216313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	load_db();
217313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
218313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
219313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint bootable(__u32 addr)
220313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
221313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct dirent *dent;
222313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	DIR *d;
223313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	char name[9];
224313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
225313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sprintf(name, "%08X", (__u32)ntohl(addr));
226313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	d = opendir(tftp_dir);
227313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (d == NULL) {
228313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		syslog(LOG_ERR, "opendir: %m");
229313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return 0;
230313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
231313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	while ((dent = readdir(d)) != NULL) {
232313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (strncmp(dent->d_name, name, 8) == 0)
233313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
234313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
235313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	closedir(d);
236313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return dent != NULL;
237313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
238313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
239313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct ifaddr *select_ipaddr(int ifindex, __u32 *sel_addr, __u32 **alist)
240313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
241313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct iflink *ifl;
242313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct ifaddr *ifa;
243313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int retry = 0;
244313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int i;
245313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
246313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiretry:
247313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for (ifl=ifl_list; ifl; ifl=ifl->next)
248313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (ifl->index == ifindex)
249313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
250313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (ifl == NULL && !retry) {
251313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		retry++;
252313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		load_if();
253313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		goto retry;
254313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
255313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (ifl == NULL)
256313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return NULL;
257313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
258313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for (i=0; alist[i]; i++) {
259313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		__u32 addr = *(alist[i]);
260313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		for (ifa=ifl->ifa_list; ifa; ifa=ifa->next) {
261313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (!((ifa->prefix^addr)&ifa->mask)) {
262313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				*sel_addr = addr;
263313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				return ifa;
264313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
265313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
266313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (ifa == NULL && retry==0) {
267313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			retry++;
268313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			load_if();
269313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			goto retry;
270313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
271313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
272313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (i==1 && allow_offlink) {
273313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		*sel_addr = *(alist[0]);
274313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return ifl->ifa_list;
275313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
276313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	syslog(LOG_ERR, "Off-link request on %s", ifl->name);
277313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return NULL;
278313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
279313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
280313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct rarp_map *rarp_lookup(int ifindex, int hatype,
281313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			     int halen, unsigned char *lladdr)
282313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
283313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct rarp_map *r;
284313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
285313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for (r=rarp_db; r; r=r->next) {
286313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (r->arp_type != hatype && r->arp_type != -1)
287313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			continue;
288313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (r->lladdr_len != halen)
289313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			continue;
290313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (r->ifindex != ifindex && r->ifindex != 0)
291313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			continue;
292313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (memcmp(r->lladdr, lladdr, halen) == 0)
293313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
294313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
295313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
296313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (r == NULL) {
297313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (hatype == ARPHRD_ETHER && halen == 6) {
298313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			struct ifaddr *ifa;
299313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			struct hostent *hp;
300313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			char ename[256];
301313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			static struct rarp_map emap = {
302313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				NULL,
303313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				0,
304313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				ARPHRD_ETHER,
305313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				6,
306313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			};
307313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
308313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (ether_ntohost(ename, lladdr) != 0 ||
309313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			    (hp = gethostbyname(ename)) == NULL) {
310313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (verbose)
311313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					syslog(LOG_INFO, "not found in /etc/ethers");
312313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				return NULL;
313313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
314313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (hp->h_addrtype != AF_INET) {
315313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				syslog(LOG_ERR, "no IP address");
316313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				return NULL;
317313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
318313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ifa = select_ipaddr(ifindex, &emap.ipaddr, (__u32 **)hp->h_addr_list);
319313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (ifa) {
320313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				memcpy(emap.lladdr, lladdr, 6);
321313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (only_ethers || bootable(emap.ipaddr))
322313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					return &emap;
323313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (verbose)
324313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					syslog(LOG_INFO, "not bootable");
325313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
326313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
327313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
328313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return r;
329313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
330313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
331313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int load_arp_bpflet(int fd)
332313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
333313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	static struct sock_filter insns[] = {
334313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 6),
335313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, ARPOP_RREQUEST, 0, 1),
336313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		BPF_STMT(BPF_RET|BPF_K, 1024),
337313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		BPF_STMT(BPF_RET|BPF_K, 0),
338313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	};
339313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	static struct sock_fprog filter = {
340313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sizeof insns / sizeof(insns[0]),
341313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		insns
342313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	};
343313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
344313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter));
345313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
346313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
347313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint put_mylladdr(unsigned char **ptr_p, int ifindex, int alen)
348313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
349313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct iflink *ifl;
350313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
351313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for (ifl=ifl_list; ifl; ifl = ifl->next)
352313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (ifl->index == ifindex)
353313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
354313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
355313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (ifl==NULL)
356313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;
357313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
358313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memcpy(*ptr_p, ifl->lladdr, alen);
359313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	*ptr_p += alen;
360313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return 0;
361313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
362313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
363313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint put_myipaddr(unsigned char **ptr_p, int ifindex, __u32 hisipaddr)
364313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
365313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	__u32 laddr = 0;
366313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct iflink *ifl;
367313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct ifaddr *ifa;
368313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
369313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for (ifl=ifl_list; ifl; ifl = ifl->next)
370313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (ifl->index == ifindex)
371313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
372313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
373313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (ifl==NULL)
374313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;
375313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
376313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for (ifa=ifl->ifa_list; ifa; ifa=ifa->next) {
377313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (!((ifa->prefix^hisipaddr)&ifa->mask)) {
378313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			laddr = ifa->local;
379313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
380313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
381313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
382313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memcpy(*ptr_p, &laddr, 4);
383313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	*ptr_p += 4;
384313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return 0;
385313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
386313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
387313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid arp_advise(int ifindex, unsigned char *lladdr, int lllen, __u32 ipaddr)
388313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
389313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int fd;
390313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct arpreq req;
391313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct sockaddr_in *sin;
392313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct iflink *ifl;
393313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
394313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for (ifl=ifl_list; ifl; ifl = ifl->next)
395313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (ifl->index == ifindex)
396313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
397313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
398313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (ifl == NULL)
399313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return;
400313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
401313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	fd = socket(AF_INET, SOCK_DGRAM, 0);
402313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memset(&req, 0, sizeof(req));
403313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	req.arp_flags = ATF_COM;
404313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sin = (struct sockaddr_in *)&req.arp_pa;
405313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sin->sin_family = AF_INET;
406313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sin->sin_addr.s_addr = ipaddr;
407313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	req.arp_ha.sa_family = ifl->hatype;
408313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memcpy(req.arp_ha.sa_data, lladdr, lllen);
409313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memcpy(req.arp_dev, ifl->name, IFNAMSIZ);
410313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
411313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (ioctl(fd, SIOCSARP, &req))
412313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		syslog(LOG_ERR, "SIOCSARP: %m");
413313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	close(fd);
414313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
415313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
416313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid serve_it(int fd)
417313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
418313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	unsigned char buf[1024];
419313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct sockaddr_ll sll;
420313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	socklen_t sll_len = sizeof(sll);
421313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct arphdr *a = (struct arphdr*)buf;
422313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct rarp_map *rmap;
423313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	unsigned char *ptr;
424313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int n;
425313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
426313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	n = recvfrom(fd, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr*)&sll, &sll_len);
427313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (n<0) {
428313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (errno != EINTR && errno != EAGAIN)
429313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			syslog(LOG_ERR, "recvfrom: %m");
430313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return;
431313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
432313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
433313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Do not accept packets for other hosts and our own ones */
434313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (sll.sll_pkttype != PACKET_BROADCAST &&
435313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	    sll.sll_pkttype != PACKET_MULTICAST &&
436313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	    sll.sll_pkttype != PACKET_HOST)
437313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return;
438313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
439313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (ifidx && sll.sll_ifindex != ifidx)
440313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return;
441313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
442313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (n<sizeof(*a)) {
443313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		syslog(LOG_ERR, "truncated arp packet; len=%d", n);
444313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return;
445313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
446313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
447313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Accept only RARP requests */
448313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (a->ar_op != htons(ARPOP_RREQUEST))
449313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return;
450313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
451313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (verbose) {
452313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		int i;
453313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		char tmpbuf[16*3];
454313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		char *ptr = tmpbuf;
455313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		for (i=0; i<sll.sll_halen; i++) {
456313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (i) {
457313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				sprintf(ptr, ":%02x", sll.sll_addr[i]);
458313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				ptr++;
459313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			} else
460313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				sprintf(ptr, "%02x", sll.sll_addr[i]);
461313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ptr += 2;
462313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
463313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		syslog(LOG_INFO, "RARP request from %s on if%d", tmpbuf, sll.sll_ifindex);
464313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
465313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
466313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Sanity checks */
467313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
468313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* 1. IP only -> pln==4 */
469313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (a->ar_pln != 4) {
470313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		syslog(LOG_ERR, "interesting rarp_req plen=%d", a->ar_pln);
471313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return;
472313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
473313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* 2. ARP protocol must be IP */
474313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (a->ar_pro != htons(ETH_P_IP)) {
475313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		syslog(LOG_ERR, "rarp protocol is not IP %04x", ntohs(a->ar_pro));
476313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return;
477313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
478313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* 3. ARP types must match */
479313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (htons(sll.sll_hatype) != a->ar_hrd) {
480313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		switch (sll.sll_hatype) {
481313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case ARPHRD_FDDI:
482313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (a->ar_hrd == htons(ARPHRD_ETHER) ||
483313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			    a->ar_hrd == htons(ARPHRD_IEEE802))
484313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				break;
485313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		default:
486313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			syslog(LOG_ERR, "rarp htype mismatch");
487313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			return;
488313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
489313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
490313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* 3. LL address lengths must be equal */
491313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (a->ar_hln != sll.sll_halen) {
492313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		syslog(LOG_ERR, "rarp hlen mismatch");
493313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return;
494313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
495313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* 4. Check packet length */
496313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (sizeof(*a) + 2*4 + 2*a->ar_hln > n) {
497313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		syslog(LOG_ERR, "truncated rarp request; len=%d", n);
498313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return;
499313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
500313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* 5. Silly check: if this guy set different source
501313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	      addresses in MAC header and in ARP, he is insane
502313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 */
503313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (memcmp(sll.sll_addr, a+1, sll.sll_halen)) {
504313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		syslog(LOG_ERR, "this guy set different his lladdrs in arp and header");
505313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return;
506313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
507313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* End of sanity checks */
508313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
509313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Lookup requested target in our database */
510313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	rmap = rarp_lookup(sll.sll_ifindex, sll.sll_hatype,
511313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			   sll.sll_halen, (unsigned char*)(a+1) + sll.sll_halen + 4);
512313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (rmap == NULL)
513313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return;
514313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
515313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Prepare reply. It is almost ready, we only
516313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	   replace ARP packet type, put our lladdr and
517313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	   IP address to source fileds,
518313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	   and fill target IP address.
519313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 */
520313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	a->ar_op = htons(ARPOP_RREPLY);
521313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	ptr = (unsigned char*)(a+1);
522313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (put_mylladdr(&ptr, sll.sll_ifindex, rmap->lladdr_len))
523313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return;
524313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (put_myipaddr(&ptr, sll.sll_ifindex, rmap->ipaddr))
525313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return;
526313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* It is already filled */
527313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	ptr += rmap->lladdr_len;
528313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memcpy(ptr, &rmap->ipaddr, 4);
529313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	ptr += 4;
530313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
531313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Update our ARP cache. Probably, this guy
532313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	   will not able to make ARP (if it is broken)
533313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 */
534313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	arp_advise(sll.sll_ifindex, rmap->lladdr, rmap->lladdr_len, rmap->ipaddr);
535313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
536313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Sendto is blocking, but with 5sec timeout */
537313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	alarm(5);
538313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sendto(fd, buf, ptr - buf, 0, (struct sockaddr*)&sll, sizeof(sll));
539313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	alarm(0);
540313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
541313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
542313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid catch_signal(int sig, void (*handler)(int))
543313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
544313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct sigaction sa;
545313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
546313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memset(&sa, 0, sizeof(sa));
547313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sa.sa_handler = handler;
548313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef SA_INTERRUPT
549313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sa.sa_flags = SA_INTERRUPT;
550313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
551313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sigaction(sig, &sa, NULL);
552313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
553313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
554313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid sig_alarm(int signo)
555313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
556313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
557313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
558313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid sig_hup(int signo)
559313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
560313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	do_reload = 1;
561313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
562313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
563313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint main(int argc, char **argv)
564313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
565313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct pollfd pset[2];
566313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int psize;
567313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int opt;
568313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
569313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
570313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	opterr = 0;
571313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	while ((opt = getopt(argc, argv, "aAb:dvoe")) != EOF) {
572313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		switch (opt) {
573313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case 'a':
574313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			++all_ifaces;
575313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
576313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
577313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case 'A':
578313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			++listen_arp;
579313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
580313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
581313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case 'd':
582313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			++debug;
583313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
584313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
585313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case 'v':
586313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			++verbose;
587313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
588313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
589313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case 'o':
590313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			++allow_offlink;
591313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
592313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
593313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case 'e':
594313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			++only_ethers;
595313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
596313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
597313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case 'b':
598313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			tftp_dir = optarg;
599313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
600313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
601313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		default:
602313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			usage();
603313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
604313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
605313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (argc > optind) {
606313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (argc > optind+1)
607313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			usage();
608313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ifname = argv[optind];
609313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
610313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
611313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	psize = 1;
612313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	pset[0].fd = socket(PF_PACKET, SOCK_DGRAM, 0);
613313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
614313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (ifname) {
615313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		struct ifreq ifr;
616313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		memset(&ifr, 0, sizeof(ifr));
617313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
618313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (ioctl(pset[0].fd, SIOCGIFINDEX, &ifr)) {
619313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			perror("ioctl(SIOCGIFINDEX)");
620313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			usage();
621313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
622313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ifidx = ifr.ifr_ifindex;
623313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
624313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
625313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	pset[1].fd = -1;
626313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (listen_arp) {
627313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pset[1].fd = socket(PF_PACKET, SOCK_DGRAM, 0);
628313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (pset[1].fd >= 0) {
629313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			load_arp_bpflet(pset[1].fd);
630313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			psize = 1;
631313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
632313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
633313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
634313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (pset[1].fd >= 0) {
635313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		struct sockaddr_ll sll;
636313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		memset(&sll, 0, sizeof(sll));
637313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sll.sll_family = AF_PACKET;
638313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sll.sll_protocol = htons(ETH_P_ARP);
639313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sll.sll_ifindex = all_ifaces ? 0 : ifidx;
640313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (bind(pset[1].fd, (struct sockaddr*)&sll, sizeof(sll)) < 0) {
641313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			close(pset[1].fd);
642313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			pset[1].fd = -1;
643313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			psize = 1;
644313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
645313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
646313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (pset[0].fd >= 0) {
647313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		struct sockaddr_ll sll;
648313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		memset(&sll, 0, sizeof(sll));
649313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sll.sll_family = AF_PACKET;
650313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sll.sll_protocol = htons(ETH_P_RARP);
651313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sll.sll_ifindex = all_ifaces ? 0 : ifidx;
652313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (bind(pset[0].fd, (struct sockaddr*)&sll, sizeof(sll)) < 0) {
653313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			close(pset[0].fd);
654313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			pset[0].fd = -1;
655313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
656313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
657313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (pset[0].fd < 0) {
658313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pset[0] = pset[1];
659313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		psize--;
660313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
661313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (psize == 0) {
662313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		fprintf(stderr, "failed to bind any socket. Aborting.\n");
663313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(1);
664313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
665313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
666313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!debug) {
667313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		int fd;
668313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pid_t pid = fork();
669313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
670313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (pid > 0)
671313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(0);
672313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		else if (pid == -1) {
673313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			perror("rarpd: fork");
674313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(1);
675313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
676313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
677313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (chdir("/") < 0) {
678313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			perror("rarpd: chdir");
679313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(1);
680313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
681313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
682313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		fd = open("/dev/null", O_RDWR);
683313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (fd >= 0) {
684313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			dup2(fd, 0);
685313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			dup2(fd, 1);
686313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			dup2(fd, 2);
687313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (fd > 2)
688313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				close(fd);
689313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
690313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		setsid();
691313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
692313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
693313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	openlog("rarpd", LOG_PID | LOG_CONS, LOG_DAEMON);
694313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	catch_signal(SIGALRM, sig_alarm);
695313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	catch_signal(SIGHUP, sig_hup);
696313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
697313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for (;;) {
698313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		int i;
699313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
700313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (do_reload) {
701313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			configure();
702313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			do_reload = 0;
703313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
704313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
705313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define EVENTS (POLLIN|POLLPRI|POLLERR|POLLHUP)
706313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pset[0].events = EVENTS;
707313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pset[0].revents = 0;
708313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pset[1].events = EVENTS;
709313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pset[1].revents = 0;
710313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
711313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		i = poll(pset, psize, -1);
712313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (i <= 0) {
713313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (errno != EINTR && i<0) {
714313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				syslog(LOG_ERR, "poll returned some crap: %m\n");
715313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				sleep(10);
716313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
717313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			continue;
718313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
719313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		for (i=0; i<psize; i++) {
720313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (pset[i].revents&EVENTS)
721313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				serve_it(pset[i].fd);
722313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
723313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
724313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
725