1*bd1f8aebSAndroid Build Coastguard Worker /*
2*bd1f8aebSAndroid Build Coastguard Worker * rarpd.c RARP daemon.
3*bd1f8aebSAndroid Build Coastguard Worker *
4*bd1f8aebSAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or
5*bd1f8aebSAndroid Build Coastguard Worker * modify it under the terms of the GNU General Public License
6*bd1f8aebSAndroid Build Coastguard Worker * as published by the Free Software Foundation; either version
7*bd1f8aebSAndroid Build Coastguard Worker * 2 of the License, or (at your option) any later version.
8*bd1f8aebSAndroid Build Coastguard Worker *
9*bd1f8aebSAndroid Build Coastguard Worker * Authors: Alexey Kuznetsov, <[email protected]>
10*bd1f8aebSAndroid Build Coastguard Worker */
11*bd1f8aebSAndroid Build Coastguard Worker
12*bd1f8aebSAndroid Build Coastguard Worker #include <stdio.h>
13*bd1f8aebSAndroid Build Coastguard Worker #include <syslog.h>
14*bd1f8aebSAndroid Build Coastguard Worker #include <dirent.h>
15*bd1f8aebSAndroid Build Coastguard Worker #include <malloc.h>
16*bd1f8aebSAndroid Build Coastguard Worker #include <string.h>
17*bd1f8aebSAndroid Build Coastguard Worker #include <unistd.h>
18*bd1f8aebSAndroid Build Coastguard Worker #include <stdlib.h>
19*bd1f8aebSAndroid Build Coastguard Worker #include <netdb.h>
20*bd1f8aebSAndroid Build Coastguard Worker #include <arpa/inet.h>
21*bd1f8aebSAndroid Build Coastguard Worker #include <sys/ioctl.h>
22*bd1f8aebSAndroid Build Coastguard Worker #include <sys/poll.h>
23*bd1f8aebSAndroid Build Coastguard Worker #include <sys/errno.h>
24*bd1f8aebSAndroid Build Coastguard Worker #include <sys/fcntl.h>
25*bd1f8aebSAndroid Build Coastguard Worker #include <sys/socket.h>
26*bd1f8aebSAndroid Build Coastguard Worker #include <sys/signal.h>
27*bd1f8aebSAndroid Build Coastguard Worker #include <linux/if.h>
28*bd1f8aebSAndroid Build Coastguard Worker #include <linux/if_arp.h>
29*bd1f8aebSAndroid Build Coastguard Worker #include <netinet/in.h>
30*bd1f8aebSAndroid Build Coastguard Worker #include <linux/if_packet.h>
31*bd1f8aebSAndroid Build Coastguard Worker #include <linux/filter.h>
32*bd1f8aebSAndroid Build Coastguard Worker
33*bd1f8aebSAndroid Build Coastguard Worker int do_reload = 1;
34*bd1f8aebSAndroid Build Coastguard Worker
35*bd1f8aebSAndroid Build Coastguard Worker int debug;
36*bd1f8aebSAndroid Build Coastguard Worker int verbose;
37*bd1f8aebSAndroid Build Coastguard Worker int ifidx;
38*bd1f8aebSAndroid Build Coastguard Worker int allow_offlink;
39*bd1f8aebSAndroid Build Coastguard Worker int only_ethers;
40*bd1f8aebSAndroid Build Coastguard Worker int all_ifaces;
41*bd1f8aebSAndroid Build Coastguard Worker int listen_arp;
42*bd1f8aebSAndroid Build Coastguard Worker char *ifname;
43*bd1f8aebSAndroid Build Coastguard Worker char *tftp_dir = "/etc/tftpboot";
44*bd1f8aebSAndroid Build Coastguard Worker
45*bd1f8aebSAndroid Build Coastguard Worker extern int ether_ntohost(char *name, unsigned char *ea);
46*bd1f8aebSAndroid Build Coastguard Worker void usage(void) __attribute__((noreturn));
47*bd1f8aebSAndroid Build Coastguard Worker
48*bd1f8aebSAndroid Build Coastguard Worker struct iflink
49*bd1f8aebSAndroid Build Coastguard Worker {
50*bd1f8aebSAndroid Build Coastguard Worker struct iflink *next;
51*bd1f8aebSAndroid Build Coastguard Worker int index;
52*bd1f8aebSAndroid Build Coastguard Worker int hatype;
53*bd1f8aebSAndroid Build Coastguard Worker unsigned char lladdr[16];
54*bd1f8aebSAndroid Build Coastguard Worker char name[IFNAMSIZ];
55*bd1f8aebSAndroid Build Coastguard Worker struct ifaddr *ifa_list;
56*bd1f8aebSAndroid Build Coastguard Worker } *ifl_list;
57*bd1f8aebSAndroid Build Coastguard Worker
58*bd1f8aebSAndroid Build Coastguard Worker struct ifaddr
59*bd1f8aebSAndroid Build Coastguard Worker {
60*bd1f8aebSAndroid Build Coastguard Worker struct ifaddr *next;
61*bd1f8aebSAndroid Build Coastguard Worker __u32 prefix;
62*bd1f8aebSAndroid Build Coastguard Worker __u32 mask;
63*bd1f8aebSAndroid Build Coastguard Worker __u32 local;
64*bd1f8aebSAndroid Build Coastguard Worker };
65*bd1f8aebSAndroid Build Coastguard Worker
66*bd1f8aebSAndroid Build Coastguard Worker struct rarp_map
67*bd1f8aebSAndroid Build Coastguard Worker {
68*bd1f8aebSAndroid Build Coastguard Worker struct rarp_map *next;
69*bd1f8aebSAndroid Build Coastguard Worker
70*bd1f8aebSAndroid Build Coastguard Worker int ifindex;
71*bd1f8aebSAndroid Build Coastguard Worker int arp_type;
72*bd1f8aebSAndroid Build Coastguard Worker int lladdr_len;
73*bd1f8aebSAndroid Build Coastguard Worker unsigned char lladdr[16];
74*bd1f8aebSAndroid Build Coastguard Worker __u32 ipaddr;
75*bd1f8aebSAndroid Build Coastguard Worker } *rarp_db;
76*bd1f8aebSAndroid Build Coastguard Worker
usage()77*bd1f8aebSAndroid Build Coastguard Worker void usage()
78*bd1f8aebSAndroid Build Coastguard Worker {
79*bd1f8aebSAndroid Build Coastguard Worker fprintf(stderr, "Usage: rarpd [ -dveaA ] [ -b tftpdir ] [ interface]\n");
80*bd1f8aebSAndroid Build Coastguard Worker exit(1);
81*bd1f8aebSAndroid Build Coastguard Worker }
82*bd1f8aebSAndroid Build Coastguard Worker
load_db(void)83*bd1f8aebSAndroid Build Coastguard Worker void load_db(void)
84*bd1f8aebSAndroid Build Coastguard Worker {
85*bd1f8aebSAndroid Build Coastguard Worker }
86*bd1f8aebSAndroid Build Coastguard Worker
load_if(void)87*bd1f8aebSAndroid Build Coastguard Worker void load_if(void)
88*bd1f8aebSAndroid Build Coastguard Worker {
89*bd1f8aebSAndroid Build Coastguard Worker int fd;
90*bd1f8aebSAndroid Build Coastguard Worker struct ifreq *ifrp, *ifend;
91*bd1f8aebSAndroid Build Coastguard Worker struct iflink *ifl;
92*bd1f8aebSAndroid Build Coastguard Worker struct ifaddr *ifa;
93*bd1f8aebSAndroid Build Coastguard Worker struct ifconf ifc;
94*bd1f8aebSAndroid Build Coastguard Worker struct ifreq ibuf[256];
95*bd1f8aebSAndroid Build Coastguard Worker
96*bd1f8aebSAndroid Build Coastguard Worker if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
97*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_ERR, "socket: %m");
98*bd1f8aebSAndroid Build Coastguard Worker return;
99*bd1f8aebSAndroid Build Coastguard Worker }
100*bd1f8aebSAndroid Build Coastguard Worker
101*bd1f8aebSAndroid Build Coastguard Worker ifc.ifc_len = sizeof ibuf;
102*bd1f8aebSAndroid Build Coastguard Worker ifc.ifc_buf = (caddr_t)ibuf;
103*bd1f8aebSAndroid Build Coastguard Worker if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
104*bd1f8aebSAndroid Build Coastguard Worker ifc.ifc_len < (int)sizeof(struct ifreq)) {
105*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_ERR, "SIOCGIFCONF: %m");
106*bd1f8aebSAndroid Build Coastguard Worker close(fd);
107*bd1f8aebSAndroid Build Coastguard Worker return;
108*bd1f8aebSAndroid Build Coastguard Worker }
109*bd1f8aebSAndroid Build Coastguard Worker
110*bd1f8aebSAndroid Build Coastguard Worker while ((ifl = ifl_list) != NULL) {
111*bd1f8aebSAndroid Build Coastguard Worker while ((ifa = ifl->ifa_list) != NULL) {
112*bd1f8aebSAndroid Build Coastguard Worker ifl->ifa_list = ifa->next;
113*bd1f8aebSAndroid Build Coastguard Worker free(ifa);
114*bd1f8aebSAndroid Build Coastguard Worker }
115*bd1f8aebSAndroid Build Coastguard Worker ifl_list = ifl->next;
116*bd1f8aebSAndroid Build Coastguard Worker free(ifl);
117*bd1f8aebSAndroid Build Coastguard Worker }
118*bd1f8aebSAndroid Build Coastguard Worker
119*bd1f8aebSAndroid Build Coastguard Worker ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
120*bd1f8aebSAndroid Build Coastguard Worker for (ifrp = ibuf; ifrp < ifend; ifrp++) {
121*bd1f8aebSAndroid Build Coastguard Worker __u32 addr;
122*bd1f8aebSAndroid Build Coastguard Worker __u32 mask;
123*bd1f8aebSAndroid Build Coastguard Worker __u32 prefix;
124*bd1f8aebSAndroid Build Coastguard Worker
125*bd1f8aebSAndroid Build Coastguard Worker if (ifrp->ifr_addr.sa_family != AF_INET)
126*bd1f8aebSAndroid Build Coastguard Worker continue;
127*bd1f8aebSAndroid Build Coastguard Worker addr = ((struct sockaddr_in*)&ifrp->ifr_addr)->sin_addr.s_addr;
128*bd1f8aebSAndroid Build Coastguard Worker if (addr == 0)
129*bd1f8aebSAndroid Build Coastguard Worker continue;
130*bd1f8aebSAndroid Build Coastguard Worker if (ioctl(fd, SIOCGIFINDEX, ifrp)) {
131*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_ERR, "ioctl(SIOCGIFNAME): %m");
132*bd1f8aebSAndroid Build Coastguard Worker continue;
133*bd1f8aebSAndroid Build Coastguard Worker }
134*bd1f8aebSAndroid Build Coastguard Worker if (ifidx && ifrp->ifr_ifindex != ifidx)
135*bd1f8aebSAndroid Build Coastguard Worker continue;
136*bd1f8aebSAndroid Build Coastguard Worker for (ifl = ifl_list; ifl; ifl = ifl->next)
137*bd1f8aebSAndroid Build Coastguard Worker if (ifl->index == ifrp->ifr_ifindex)
138*bd1f8aebSAndroid Build Coastguard Worker break;
139*bd1f8aebSAndroid Build Coastguard Worker if (ifl == NULL) {
140*bd1f8aebSAndroid Build Coastguard Worker char *p;
141*bd1f8aebSAndroid Build Coastguard Worker int index = ifrp->ifr_ifindex;
142*bd1f8aebSAndroid Build Coastguard Worker
143*bd1f8aebSAndroid Build Coastguard Worker if (ioctl(fd, SIOCGIFHWADDR, ifrp)) {
144*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_ERR, "ioctl(SIOCGIFHWADDR): %m");
145*bd1f8aebSAndroid Build Coastguard Worker continue;
146*bd1f8aebSAndroid Build Coastguard Worker }
147*bd1f8aebSAndroid Build Coastguard Worker
148*bd1f8aebSAndroid Build Coastguard Worker ifl = (struct iflink*)malloc(sizeof(*ifl));
149*bd1f8aebSAndroid Build Coastguard Worker if (ifl == NULL)
150*bd1f8aebSAndroid Build Coastguard Worker continue;
151*bd1f8aebSAndroid Build Coastguard Worker memset(ifl, 0, sizeof(*ifl));
152*bd1f8aebSAndroid Build Coastguard Worker ifl->next = ifl_list;
153*bd1f8aebSAndroid Build Coastguard Worker ifl_list = ifl;
154*bd1f8aebSAndroid Build Coastguard Worker ifl->index = index;
155*bd1f8aebSAndroid Build Coastguard Worker ifl->hatype = ifrp->ifr_hwaddr.sa_family;
156*bd1f8aebSAndroid Build Coastguard Worker memcpy(ifl->lladdr, ifrp->ifr_hwaddr.sa_data, 14);
157*bd1f8aebSAndroid Build Coastguard Worker strncpy(ifl->name, ifrp->ifr_name, IFNAMSIZ);
158*bd1f8aebSAndroid Build Coastguard Worker p = strchr(ifl->name, ':');
159*bd1f8aebSAndroid Build Coastguard Worker if (p)
160*bd1f8aebSAndroid Build Coastguard Worker *p = 0;
161*bd1f8aebSAndroid Build Coastguard Worker if (verbose)
162*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_INFO, "link %s", ifl->name);
163*bd1f8aebSAndroid Build Coastguard Worker }
164*bd1f8aebSAndroid Build Coastguard Worker if (ioctl(fd, SIOCGIFNETMASK, ifrp)) {
165*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_ERR, "ioctl(SIOCGIFMASK): %m");
166*bd1f8aebSAndroid Build Coastguard Worker continue;
167*bd1f8aebSAndroid Build Coastguard Worker }
168*bd1f8aebSAndroid Build Coastguard Worker mask = ((struct sockaddr_in*)&ifrp->ifr_netmask)->sin_addr.s_addr;
169*bd1f8aebSAndroid Build Coastguard Worker if (ioctl(fd, SIOCGIFDSTADDR, ifrp)) {
170*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_ERR, "ioctl(SIOCGIFDSTADDR): %m");
171*bd1f8aebSAndroid Build Coastguard Worker continue;
172*bd1f8aebSAndroid Build Coastguard Worker }
173*bd1f8aebSAndroid Build Coastguard Worker prefix = ((struct sockaddr_in*)&ifrp->ifr_dstaddr)->sin_addr.s_addr;
174*bd1f8aebSAndroid Build Coastguard Worker for (ifa = ifl->ifa_list; ifa; ifa = ifa->next) {
175*bd1f8aebSAndroid Build Coastguard Worker if (ifa->local == addr &&
176*bd1f8aebSAndroid Build Coastguard Worker ifa->prefix == prefix &&
177*bd1f8aebSAndroid Build Coastguard Worker ifa->mask == mask)
178*bd1f8aebSAndroid Build Coastguard Worker break;
179*bd1f8aebSAndroid Build Coastguard Worker }
180*bd1f8aebSAndroid Build Coastguard Worker if (ifa == NULL) {
181*bd1f8aebSAndroid Build Coastguard Worker if (mask == 0 || prefix == 0)
182*bd1f8aebSAndroid Build Coastguard Worker continue;
183*bd1f8aebSAndroid Build Coastguard Worker ifa = (struct ifaddr*)malloc(sizeof(*ifa));
184*bd1f8aebSAndroid Build Coastguard Worker memset(ifa, 0, sizeof(*ifa));
185*bd1f8aebSAndroid Build Coastguard Worker ifa->local = addr;
186*bd1f8aebSAndroid Build Coastguard Worker ifa->prefix = prefix;
187*bd1f8aebSAndroid Build Coastguard Worker ifa->mask = mask;
188*bd1f8aebSAndroid Build Coastguard Worker ifa->next = ifl->ifa_list;
189*bd1f8aebSAndroid Build Coastguard Worker ifl->ifa_list = ifa;
190*bd1f8aebSAndroid Build Coastguard Worker
191*bd1f8aebSAndroid Build Coastguard Worker if (verbose) {
192*bd1f8aebSAndroid Build Coastguard Worker int i;
193*bd1f8aebSAndroid Build Coastguard Worker __u32 m = ~0U;
194*bd1f8aebSAndroid Build Coastguard Worker for (i=32; i>=0; i--) {
195*bd1f8aebSAndroid Build Coastguard Worker if (htonl(m) == mask)
196*bd1f8aebSAndroid Build Coastguard Worker break;
197*bd1f8aebSAndroid Build Coastguard Worker m <<= 1;
198*bd1f8aebSAndroid Build Coastguard Worker }
199*bd1f8aebSAndroid Build Coastguard Worker if (addr == prefix) {
200*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_INFO, " addr %s/%d on %s\n",
201*bd1f8aebSAndroid Build Coastguard Worker inet_ntoa(*(struct in_addr*)&addr), i, ifl->name);
202*bd1f8aebSAndroid Build Coastguard Worker } else {
203*bd1f8aebSAndroid Build Coastguard Worker char tmpa[64];
204*bd1f8aebSAndroid Build Coastguard Worker sprintf(tmpa, "%s", inet_ntoa(*(struct in_addr*)&addr));
205*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_INFO, " addr %s %s/%d on %s\n", tmpa,
206*bd1f8aebSAndroid Build Coastguard Worker inet_ntoa(*(struct in_addr*)&prefix), i, ifl->name);
207*bd1f8aebSAndroid Build Coastguard Worker }
208*bd1f8aebSAndroid Build Coastguard Worker }
209*bd1f8aebSAndroid Build Coastguard Worker }
210*bd1f8aebSAndroid Build Coastguard Worker }
211*bd1f8aebSAndroid Build Coastguard Worker }
212*bd1f8aebSAndroid Build Coastguard Worker
configure(void)213*bd1f8aebSAndroid Build Coastguard Worker void configure(void)
214*bd1f8aebSAndroid Build Coastguard Worker {
215*bd1f8aebSAndroid Build Coastguard Worker load_if();
216*bd1f8aebSAndroid Build Coastguard Worker load_db();
217*bd1f8aebSAndroid Build Coastguard Worker }
218*bd1f8aebSAndroid Build Coastguard Worker
bootable(__u32 addr)219*bd1f8aebSAndroid Build Coastguard Worker int bootable(__u32 addr)
220*bd1f8aebSAndroid Build Coastguard Worker {
221*bd1f8aebSAndroid Build Coastguard Worker struct dirent *dent;
222*bd1f8aebSAndroid Build Coastguard Worker DIR *d;
223*bd1f8aebSAndroid Build Coastguard Worker char name[9];
224*bd1f8aebSAndroid Build Coastguard Worker
225*bd1f8aebSAndroid Build Coastguard Worker sprintf(name, "%08X", (__u32)ntohl(addr));
226*bd1f8aebSAndroid Build Coastguard Worker d = opendir(tftp_dir);
227*bd1f8aebSAndroid Build Coastguard Worker if (d == NULL) {
228*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_ERR, "opendir: %m");
229*bd1f8aebSAndroid Build Coastguard Worker return 0;
230*bd1f8aebSAndroid Build Coastguard Worker }
231*bd1f8aebSAndroid Build Coastguard Worker while ((dent = readdir(d)) != NULL) {
232*bd1f8aebSAndroid Build Coastguard Worker if (strncmp(dent->d_name, name, 8) == 0)
233*bd1f8aebSAndroid Build Coastguard Worker break;
234*bd1f8aebSAndroid Build Coastguard Worker }
235*bd1f8aebSAndroid Build Coastguard Worker closedir(d);
236*bd1f8aebSAndroid Build Coastguard Worker return dent != NULL;
237*bd1f8aebSAndroid Build Coastguard Worker }
238*bd1f8aebSAndroid Build Coastguard Worker
select_ipaddr(int ifindex,__u32 * sel_addr,__u32 ** alist)239*bd1f8aebSAndroid Build Coastguard Worker struct ifaddr *select_ipaddr(int ifindex, __u32 *sel_addr, __u32 **alist)
240*bd1f8aebSAndroid Build Coastguard Worker {
241*bd1f8aebSAndroid Build Coastguard Worker struct iflink *ifl;
242*bd1f8aebSAndroid Build Coastguard Worker struct ifaddr *ifa;
243*bd1f8aebSAndroid Build Coastguard Worker int retry = 0;
244*bd1f8aebSAndroid Build Coastguard Worker int i;
245*bd1f8aebSAndroid Build Coastguard Worker
246*bd1f8aebSAndroid Build Coastguard Worker retry:
247*bd1f8aebSAndroid Build Coastguard Worker for (ifl=ifl_list; ifl; ifl=ifl->next)
248*bd1f8aebSAndroid Build Coastguard Worker if (ifl->index == ifindex)
249*bd1f8aebSAndroid Build Coastguard Worker break;
250*bd1f8aebSAndroid Build Coastguard Worker if (ifl == NULL && !retry) {
251*bd1f8aebSAndroid Build Coastguard Worker retry++;
252*bd1f8aebSAndroid Build Coastguard Worker load_if();
253*bd1f8aebSAndroid Build Coastguard Worker goto retry;
254*bd1f8aebSAndroid Build Coastguard Worker }
255*bd1f8aebSAndroid Build Coastguard Worker if (ifl == NULL)
256*bd1f8aebSAndroid Build Coastguard Worker return NULL;
257*bd1f8aebSAndroid Build Coastguard Worker
258*bd1f8aebSAndroid Build Coastguard Worker for (i=0; alist[i]; i++) {
259*bd1f8aebSAndroid Build Coastguard Worker __u32 addr = *(alist[i]);
260*bd1f8aebSAndroid Build Coastguard Worker for (ifa=ifl->ifa_list; ifa; ifa=ifa->next) {
261*bd1f8aebSAndroid Build Coastguard Worker if (!((ifa->prefix^addr)&ifa->mask)) {
262*bd1f8aebSAndroid Build Coastguard Worker *sel_addr = addr;
263*bd1f8aebSAndroid Build Coastguard Worker return ifa;
264*bd1f8aebSAndroid Build Coastguard Worker }
265*bd1f8aebSAndroid Build Coastguard Worker }
266*bd1f8aebSAndroid Build Coastguard Worker if (ifa == NULL && retry==0) {
267*bd1f8aebSAndroid Build Coastguard Worker retry++;
268*bd1f8aebSAndroid Build Coastguard Worker load_if();
269*bd1f8aebSAndroid Build Coastguard Worker goto retry;
270*bd1f8aebSAndroid Build Coastguard Worker }
271*bd1f8aebSAndroid Build Coastguard Worker }
272*bd1f8aebSAndroid Build Coastguard Worker if (i==1 && allow_offlink) {
273*bd1f8aebSAndroid Build Coastguard Worker *sel_addr = *(alist[0]);
274*bd1f8aebSAndroid Build Coastguard Worker return ifl->ifa_list;
275*bd1f8aebSAndroid Build Coastguard Worker }
276*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_ERR, "Off-link request on %s", ifl->name);
277*bd1f8aebSAndroid Build Coastguard Worker return NULL;
278*bd1f8aebSAndroid Build Coastguard Worker }
279*bd1f8aebSAndroid Build Coastguard Worker
rarp_lookup(int ifindex,int hatype,int halen,unsigned char * lladdr)280*bd1f8aebSAndroid Build Coastguard Worker struct rarp_map *rarp_lookup(int ifindex, int hatype,
281*bd1f8aebSAndroid Build Coastguard Worker int halen, unsigned char *lladdr)
282*bd1f8aebSAndroid Build Coastguard Worker {
283*bd1f8aebSAndroid Build Coastguard Worker struct rarp_map *r;
284*bd1f8aebSAndroid Build Coastguard Worker
285*bd1f8aebSAndroid Build Coastguard Worker for (r=rarp_db; r; r=r->next) {
286*bd1f8aebSAndroid Build Coastguard Worker if (r->arp_type != hatype && r->arp_type != -1)
287*bd1f8aebSAndroid Build Coastguard Worker continue;
288*bd1f8aebSAndroid Build Coastguard Worker if (r->lladdr_len != halen)
289*bd1f8aebSAndroid Build Coastguard Worker continue;
290*bd1f8aebSAndroid Build Coastguard Worker if (r->ifindex != ifindex && r->ifindex != 0)
291*bd1f8aebSAndroid Build Coastguard Worker continue;
292*bd1f8aebSAndroid Build Coastguard Worker if (memcmp(r->lladdr, lladdr, halen) == 0)
293*bd1f8aebSAndroid Build Coastguard Worker break;
294*bd1f8aebSAndroid Build Coastguard Worker }
295*bd1f8aebSAndroid Build Coastguard Worker
296*bd1f8aebSAndroid Build Coastguard Worker if (r == NULL) {
297*bd1f8aebSAndroid Build Coastguard Worker if (hatype == ARPHRD_ETHER && halen == 6) {
298*bd1f8aebSAndroid Build Coastguard Worker struct ifaddr *ifa;
299*bd1f8aebSAndroid Build Coastguard Worker struct hostent *hp;
300*bd1f8aebSAndroid Build Coastguard Worker char ename[256];
301*bd1f8aebSAndroid Build Coastguard Worker static struct rarp_map emap = {
302*bd1f8aebSAndroid Build Coastguard Worker NULL,
303*bd1f8aebSAndroid Build Coastguard Worker 0,
304*bd1f8aebSAndroid Build Coastguard Worker ARPHRD_ETHER,
305*bd1f8aebSAndroid Build Coastguard Worker 6,
306*bd1f8aebSAndroid Build Coastguard Worker };
307*bd1f8aebSAndroid Build Coastguard Worker
308*bd1f8aebSAndroid Build Coastguard Worker if (ether_ntohost(ename, lladdr) != 0 ||
309*bd1f8aebSAndroid Build Coastguard Worker (hp = gethostbyname(ename)) == NULL) {
310*bd1f8aebSAndroid Build Coastguard Worker if (verbose)
311*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_INFO, "not found in /etc/ethers");
312*bd1f8aebSAndroid Build Coastguard Worker return NULL;
313*bd1f8aebSAndroid Build Coastguard Worker }
314*bd1f8aebSAndroid Build Coastguard Worker if (hp->h_addrtype != AF_INET) {
315*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_ERR, "no IP address");
316*bd1f8aebSAndroid Build Coastguard Worker return NULL;
317*bd1f8aebSAndroid Build Coastguard Worker }
318*bd1f8aebSAndroid Build Coastguard Worker ifa = select_ipaddr(ifindex, &emap.ipaddr, (__u32 **)hp->h_addr_list);
319*bd1f8aebSAndroid Build Coastguard Worker if (ifa) {
320*bd1f8aebSAndroid Build Coastguard Worker memcpy(emap.lladdr, lladdr, 6);
321*bd1f8aebSAndroid Build Coastguard Worker if (only_ethers || bootable(emap.ipaddr))
322*bd1f8aebSAndroid Build Coastguard Worker return &emap;
323*bd1f8aebSAndroid Build Coastguard Worker if (verbose)
324*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_INFO, "not bootable");
325*bd1f8aebSAndroid Build Coastguard Worker }
326*bd1f8aebSAndroid Build Coastguard Worker }
327*bd1f8aebSAndroid Build Coastguard Worker }
328*bd1f8aebSAndroid Build Coastguard Worker return r;
329*bd1f8aebSAndroid Build Coastguard Worker }
330*bd1f8aebSAndroid Build Coastguard Worker
load_arp_bpflet(int fd)331*bd1f8aebSAndroid Build Coastguard Worker static int load_arp_bpflet(int fd)
332*bd1f8aebSAndroid Build Coastguard Worker {
333*bd1f8aebSAndroid Build Coastguard Worker static struct sock_filter insns[] = {
334*bd1f8aebSAndroid Build Coastguard Worker BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 6),
335*bd1f8aebSAndroid Build Coastguard Worker BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, ARPOP_RREQUEST, 0, 1),
336*bd1f8aebSAndroid Build Coastguard Worker BPF_STMT(BPF_RET|BPF_K, 1024),
337*bd1f8aebSAndroid Build Coastguard Worker BPF_STMT(BPF_RET|BPF_K, 0),
338*bd1f8aebSAndroid Build Coastguard Worker };
339*bd1f8aebSAndroid Build Coastguard Worker static struct sock_fprog filter = {
340*bd1f8aebSAndroid Build Coastguard Worker sizeof insns / sizeof(insns[0]),
341*bd1f8aebSAndroid Build Coastguard Worker insns
342*bd1f8aebSAndroid Build Coastguard Worker };
343*bd1f8aebSAndroid Build Coastguard Worker
344*bd1f8aebSAndroid Build Coastguard Worker return setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter));
345*bd1f8aebSAndroid Build Coastguard Worker }
346*bd1f8aebSAndroid Build Coastguard Worker
put_mylladdr(unsigned char ** ptr_p,int ifindex,int alen)347*bd1f8aebSAndroid Build Coastguard Worker int put_mylladdr(unsigned char **ptr_p, int ifindex, int alen)
348*bd1f8aebSAndroid Build Coastguard Worker {
349*bd1f8aebSAndroid Build Coastguard Worker struct iflink *ifl;
350*bd1f8aebSAndroid Build Coastguard Worker
351*bd1f8aebSAndroid Build Coastguard Worker for (ifl=ifl_list; ifl; ifl = ifl->next)
352*bd1f8aebSAndroid Build Coastguard Worker if (ifl->index == ifindex)
353*bd1f8aebSAndroid Build Coastguard Worker break;
354*bd1f8aebSAndroid Build Coastguard Worker
355*bd1f8aebSAndroid Build Coastguard Worker if (ifl==NULL)
356*bd1f8aebSAndroid Build Coastguard Worker return -1;
357*bd1f8aebSAndroid Build Coastguard Worker
358*bd1f8aebSAndroid Build Coastguard Worker memcpy(*ptr_p, ifl->lladdr, alen);
359*bd1f8aebSAndroid Build Coastguard Worker *ptr_p += alen;
360*bd1f8aebSAndroid Build Coastguard Worker return 0;
361*bd1f8aebSAndroid Build Coastguard Worker }
362*bd1f8aebSAndroid Build Coastguard Worker
put_myipaddr(unsigned char ** ptr_p,int ifindex,__u32 hisipaddr)363*bd1f8aebSAndroid Build Coastguard Worker int put_myipaddr(unsigned char **ptr_p, int ifindex, __u32 hisipaddr)
364*bd1f8aebSAndroid Build Coastguard Worker {
365*bd1f8aebSAndroid Build Coastguard Worker __u32 laddr = 0;
366*bd1f8aebSAndroid Build Coastguard Worker struct iflink *ifl;
367*bd1f8aebSAndroid Build Coastguard Worker struct ifaddr *ifa;
368*bd1f8aebSAndroid Build Coastguard Worker
369*bd1f8aebSAndroid Build Coastguard Worker for (ifl=ifl_list; ifl; ifl = ifl->next)
370*bd1f8aebSAndroid Build Coastguard Worker if (ifl->index == ifindex)
371*bd1f8aebSAndroid Build Coastguard Worker break;
372*bd1f8aebSAndroid Build Coastguard Worker
373*bd1f8aebSAndroid Build Coastguard Worker if (ifl==NULL)
374*bd1f8aebSAndroid Build Coastguard Worker return -1;
375*bd1f8aebSAndroid Build Coastguard Worker
376*bd1f8aebSAndroid Build Coastguard Worker for (ifa=ifl->ifa_list; ifa; ifa=ifa->next) {
377*bd1f8aebSAndroid Build Coastguard Worker if (!((ifa->prefix^hisipaddr)&ifa->mask)) {
378*bd1f8aebSAndroid Build Coastguard Worker laddr = ifa->local;
379*bd1f8aebSAndroid Build Coastguard Worker break;
380*bd1f8aebSAndroid Build Coastguard Worker }
381*bd1f8aebSAndroid Build Coastguard Worker }
382*bd1f8aebSAndroid Build Coastguard Worker memcpy(*ptr_p, &laddr, 4);
383*bd1f8aebSAndroid Build Coastguard Worker *ptr_p += 4;
384*bd1f8aebSAndroid Build Coastguard Worker return 0;
385*bd1f8aebSAndroid Build Coastguard Worker }
386*bd1f8aebSAndroid Build Coastguard Worker
arp_advise(int ifindex,unsigned char * lladdr,int lllen,__u32 ipaddr)387*bd1f8aebSAndroid Build Coastguard Worker void arp_advise(int ifindex, unsigned char *lladdr, int lllen, __u32 ipaddr)
388*bd1f8aebSAndroid Build Coastguard Worker {
389*bd1f8aebSAndroid Build Coastguard Worker int fd;
390*bd1f8aebSAndroid Build Coastguard Worker struct arpreq req;
391*bd1f8aebSAndroid Build Coastguard Worker struct sockaddr_in *sin;
392*bd1f8aebSAndroid Build Coastguard Worker struct iflink *ifl;
393*bd1f8aebSAndroid Build Coastguard Worker
394*bd1f8aebSAndroid Build Coastguard Worker for (ifl=ifl_list; ifl; ifl = ifl->next)
395*bd1f8aebSAndroid Build Coastguard Worker if (ifl->index == ifindex)
396*bd1f8aebSAndroid Build Coastguard Worker break;
397*bd1f8aebSAndroid Build Coastguard Worker
398*bd1f8aebSAndroid Build Coastguard Worker if (ifl == NULL)
399*bd1f8aebSAndroid Build Coastguard Worker return;
400*bd1f8aebSAndroid Build Coastguard Worker
401*bd1f8aebSAndroid Build Coastguard Worker fd = socket(AF_INET, SOCK_DGRAM, 0);
402*bd1f8aebSAndroid Build Coastguard Worker memset(&req, 0, sizeof(req));
403*bd1f8aebSAndroid Build Coastguard Worker req.arp_flags = ATF_COM;
404*bd1f8aebSAndroid Build Coastguard Worker sin = (struct sockaddr_in *)&req.arp_pa;
405*bd1f8aebSAndroid Build Coastguard Worker sin->sin_family = AF_INET;
406*bd1f8aebSAndroid Build Coastguard Worker sin->sin_addr.s_addr = ipaddr;
407*bd1f8aebSAndroid Build Coastguard Worker req.arp_ha.sa_family = ifl->hatype;
408*bd1f8aebSAndroid Build Coastguard Worker memcpy(req.arp_ha.sa_data, lladdr, lllen);
409*bd1f8aebSAndroid Build Coastguard Worker memcpy(req.arp_dev, ifl->name, IFNAMSIZ);
410*bd1f8aebSAndroid Build Coastguard Worker
411*bd1f8aebSAndroid Build Coastguard Worker if (ioctl(fd, SIOCSARP, &req))
412*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_ERR, "SIOCSARP: %m");
413*bd1f8aebSAndroid Build Coastguard Worker close(fd);
414*bd1f8aebSAndroid Build Coastguard Worker }
415*bd1f8aebSAndroid Build Coastguard Worker
serve_it(int fd)416*bd1f8aebSAndroid Build Coastguard Worker void serve_it(int fd)
417*bd1f8aebSAndroid Build Coastguard Worker {
418*bd1f8aebSAndroid Build Coastguard Worker unsigned char buf[1024];
419*bd1f8aebSAndroid Build Coastguard Worker struct sockaddr_ll sll;
420*bd1f8aebSAndroid Build Coastguard Worker socklen_t sll_len = sizeof(sll);
421*bd1f8aebSAndroid Build Coastguard Worker struct arphdr *a = (struct arphdr*)buf;
422*bd1f8aebSAndroid Build Coastguard Worker struct rarp_map *rmap;
423*bd1f8aebSAndroid Build Coastguard Worker unsigned char *ptr;
424*bd1f8aebSAndroid Build Coastguard Worker int n;
425*bd1f8aebSAndroid Build Coastguard Worker
426*bd1f8aebSAndroid Build Coastguard Worker n = recvfrom(fd, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr*)&sll, &sll_len);
427*bd1f8aebSAndroid Build Coastguard Worker if (n<0) {
428*bd1f8aebSAndroid Build Coastguard Worker if (errno != EINTR && errno != EAGAIN)
429*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_ERR, "recvfrom: %m");
430*bd1f8aebSAndroid Build Coastguard Worker return;
431*bd1f8aebSAndroid Build Coastguard Worker }
432*bd1f8aebSAndroid Build Coastguard Worker
433*bd1f8aebSAndroid Build Coastguard Worker /* Do not accept packets for other hosts and our own ones */
434*bd1f8aebSAndroid Build Coastguard Worker if (sll.sll_pkttype != PACKET_BROADCAST &&
435*bd1f8aebSAndroid Build Coastguard Worker sll.sll_pkttype != PACKET_MULTICAST &&
436*bd1f8aebSAndroid Build Coastguard Worker sll.sll_pkttype != PACKET_HOST)
437*bd1f8aebSAndroid Build Coastguard Worker return;
438*bd1f8aebSAndroid Build Coastguard Worker
439*bd1f8aebSAndroid Build Coastguard Worker if (ifidx && sll.sll_ifindex != ifidx)
440*bd1f8aebSAndroid Build Coastguard Worker return;
441*bd1f8aebSAndroid Build Coastguard Worker
442*bd1f8aebSAndroid Build Coastguard Worker if (n<sizeof(*a)) {
443*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_ERR, "truncated arp packet; len=%d", n);
444*bd1f8aebSAndroid Build Coastguard Worker return;
445*bd1f8aebSAndroid Build Coastguard Worker }
446*bd1f8aebSAndroid Build Coastguard Worker
447*bd1f8aebSAndroid Build Coastguard Worker /* Accept only RARP requests */
448*bd1f8aebSAndroid Build Coastguard Worker if (a->ar_op != htons(ARPOP_RREQUEST))
449*bd1f8aebSAndroid Build Coastguard Worker return;
450*bd1f8aebSAndroid Build Coastguard Worker
451*bd1f8aebSAndroid Build Coastguard Worker if (verbose) {
452*bd1f8aebSAndroid Build Coastguard Worker int i;
453*bd1f8aebSAndroid Build Coastguard Worker char tmpbuf[16*3];
454*bd1f8aebSAndroid Build Coastguard Worker char *ptr = tmpbuf;
455*bd1f8aebSAndroid Build Coastguard Worker for (i=0; i<sll.sll_halen; i++) {
456*bd1f8aebSAndroid Build Coastguard Worker if (i) {
457*bd1f8aebSAndroid Build Coastguard Worker sprintf(ptr, ":%02x", sll.sll_addr[i]);
458*bd1f8aebSAndroid Build Coastguard Worker ptr++;
459*bd1f8aebSAndroid Build Coastguard Worker } else
460*bd1f8aebSAndroid Build Coastguard Worker sprintf(ptr, "%02x", sll.sll_addr[i]);
461*bd1f8aebSAndroid Build Coastguard Worker ptr += 2;
462*bd1f8aebSAndroid Build Coastguard Worker }
463*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_INFO, "RARP request from %s on if%d", tmpbuf, sll.sll_ifindex);
464*bd1f8aebSAndroid Build Coastguard Worker }
465*bd1f8aebSAndroid Build Coastguard Worker
466*bd1f8aebSAndroid Build Coastguard Worker /* Sanity checks */
467*bd1f8aebSAndroid Build Coastguard Worker
468*bd1f8aebSAndroid Build Coastguard Worker /* 1. IP only -> pln==4 */
469*bd1f8aebSAndroid Build Coastguard Worker if (a->ar_pln != 4) {
470*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_ERR, "interesting rarp_req plen=%d", a->ar_pln);
471*bd1f8aebSAndroid Build Coastguard Worker return;
472*bd1f8aebSAndroid Build Coastguard Worker }
473*bd1f8aebSAndroid Build Coastguard Worker /* 2. ARP protocol must be IP */
474*bd1f8aebSAndroid Build Coastguard Worker if (a->ar_pro != htons(ETH_P_IP)) {
475*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_ERR, "rarp protocol is not IP %04x", ntohs(a->ar_pro));
476*bd1f8aebSAndroid Build Coastguard Worker return;
477*bd1f8aebSAndroid Build Coastguard Worker }
478*bd1f8aebSAndroid Build Coastguard Worker /* 3. ARP types must match */
479*bd1f8aebSAndroid Build Coastguard Worker if (htons(sll.sll_hatype) != a->ar_hrd) {
480*bd1f8aebSAndroid Build Coastguard Worker switch (sll.sll_hatype) {
481*bd1f8aebSAndroid Build Coastguard Worker case ARPHRD_FDDI:
482*bd1f8aebSAndroid Build Coastguard Worker if (a->ar_hrd == htons(ARPHRD_ETHER) ||
483*bd1f8aebSAndroid Build Coastguard Worker a->ar_hrd == htons(ARPHRD_IEEE802))
484*bd1f8aebSAndroid Build Coastguard Worker break;
485*bd1f8aebSAndroid Build Coastguard Worker default:
486*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_ERR, "rarp htype mismatch");
487*bd1f8aebSAndroid Build Coastguard Worker return;
488*bd1f8aebSAndroid Build Coastguard Worker }
489*bd1f8aebSAndroid Build Coastguard Worker }
490*bd1f8aebSAndroid Build Coastguard Worker /* 3. LL address lengths must be equal */
491*bd1f8aebSAndroid Build Coastguard Worker if (a->ar_hln != sll.sll_halen) {
492*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_ERR, "rarp hlen mismatch");
493*bd1f8aebSAndroid Build Coastguard Worker return;
494*bd1f8aebSAndroid Build Coastguard Worker }
495*bd1f8aebSAndroid Build Coastguard Worker /* 4. Check packet length */
496*bd1f8aebSAndroid Build Coastguard Worker if (sizeof(*a) + 2*4 + 2*a->ar_hln > n) {
497*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_ERR, "truncated rarp request; len=%d", n);
498*bd1f8aebSAndroid Build Coastguard Worker return;
499*bd1f8aebSAndroid Build Coastguard Worker }
500*bd1f8aebSAndroid Build Coastguard Worker /* 5. Silly check: if this guy set different source
501*bd1f8aebSAndroid Build Coastguard Worker addresses in MAC header and in ARP, he is insane
502*bd1f8aebSAndroid Build Coastguard Worker */
503*bd1f8aebSAndroid Build Coastguard Worker if (memcmp(sll.sll_addr, a+1, sll.sll_halen)) {
504*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_ERR, "this guy set different his lladdrs in arp and header");
505*bd1f8aebSAndroid Build Coastguard Worker return;
506*bd1f8aebSAndroid Build Coastguard Worker }
507*bd1f8aebSAndroid Build Coastguard Worker /* End of sanity checks */
508*bd1f8aebSAndroid Build Coastguard Worker
509*bd1f8aebSAndroid Build Coastguard Worker /* Lookup requested target in our database */
510*bd1f8aebSAndroid Build Coastguard Worker rmap = rarp_lookup(sll.sll_ifindex, sll.sll_hatype,
511*bd1f8aebSAndroid Build Coastguard Worker sll.sll_halen, (unsigned char*)(a+1) + sll.sll_halen + 4);
512*bd1f8aebSAndroid Build Coastguard Worker if (rmap == NULL)
513*bd1f8aebSAndroid Build Coastguard Worker return;
514*bd1f8aebSAndroid Build Coastguard Worker
515*bd1f8aebSAndroid Build Coastguard Worker /* Prepare reply. It is almost ready, we only
516*bd1f8aebSAndroid Build Coastguard Worker replace ARP packet type, put our lladdr and
517*bd1f8aebSAndroid Build Coastguard Worker IP address to source fileds,
518*bd1f8aebSAndroid Build Coastguard Worker and fill target IP address.
519*bd1f8aebSAndroid Build Coastguard Worker */
520*bd1f8aebSAndroid Build Coastguard Worker a->ar_op = htons(ARPOP_RREPLY);
521*bd1f8aebSAndroid Build Coastguard Worker ptr = (unsigned char*)(a+1);
522*bd1f8aebSAndroid Build Coastguard Worker if (put_mylladdr(&ptr, sll.sll_ifindex, rmap->lladdr_len))
523*bd1f8aebSAndroid Build Coastguard Worker return;
524*bd1f8aebSAndroid Build Coastguard Worker if (put_myipaddr(&ptr, sll.sll_ifindex, rmap->ipaddr))
525*bd1f8aebSAndroid Build Coastguard Worker return;
526*bd1f8aebSAndroid Build Coastguard Worker /* It is already filled */
527*bd1f8aebSAndroid Build Coastguard Worker ptr += rmap->lladdr_len;
528*bd1f8aebSAndroid Build Coastguard Worker memcpy(ptr, &rmap->ipaddr, 4);
529*bd1f8aebSAndroid Build Coastguard Worker ptr += 4;
530*bd1f8aebSAndroid Build Coastguard Worker
531*bd1f8aebSAndroid Build Coastguard Worker /* Update our ARP cache. Probably, this guy
532*bd1f8aebSAndroid Build Coastguard Worker will not able to make ARP (if it is broken)
533*bd1f8aebSAndroid Build Coastguard Worker */
534*bd1f8aebSAndroid Build Coastguard Worker arp_advise(sll.sll_ifindex, rmap->lladdr, rmap->lladdr_len, rmap->ipaddr);
535*bd1f8aebSAndroid Build Coastguard Worker
536*bd1f8aebSAndroid Build Coastguard Worker /* Sendto is blocking, but with 5sec timeout */
537*bd1f8aebSAndroid Build Coastguard Worker alarm(5);
538*bd1f8aebSAndroid Build Coastguard Worker sendto(fd, buf, ptr - buf, 0, (struct sockaddr*)&sll, sizeof(sll));
539*bd1f8aebSAndroid Build Coastguard Worker alarm(0);
540*bd1f8aebSAndroid Build Coastguard Worker }
541*bd1f8aebSAndroid Build Coastguard Worker
catch_signal(int sig,void (* handler)(int))542*bd1f8aebSAndroid Build Coastguard Worker void catch_signal(int sig, void (*handler)(int))
543*bd1f8aebSAndroid Build Coastguard Worker {
544*bd1f8aebSAndroid Build Coastguard Worker struct sigaction sa;
545*bd1f8aebSAndroid Build Coastguard Worker
546*bd1f8aebSAndroid Build Coastguard Worker memset(&sa, 0, sizeof(sa));
547*bd1f8aebSAndroid Build Coastguard Worker sa.sa_handler = handler;
548*bd1f8aebSAndroid Build Coastguard Worker #ifdef SA_INTERRUPT
549*bd1f8aebSAndroid Build Coastguard Worker sa.sa_flags = SA_INTERRUPT;
550*bd1f8aebSAndroid Build Coastguard Worker #endif
551*bd1f8aebSAndroid Build Coastguard Worker sigaction(sig, &sa, NULL);
552*bd1f8aebSAndroid Build Coastguard Worker }
553*bd1f8aebSAndroid Build Coastguard Worker
sig_alarm(int signo)554*bd1f8aebSAndroid Build Coastguard Worker void sig_alarm(int signo)
555*bd1f8aebSAndroid Build Coastguard Worker {
556*bd1f8aebSAndroid Build Coastguard Worker }
557*bd1f8aebSAndroid Build Coastguard Worker
sig_hup(int signo)558*bd1f8aebSAndroid Build Coastguard Worker void sig_hup(int signo)
559*bd1f8aebSAndroid Build Coastguard Worker {
560*bd1f8aebSAndroid Build Coastguard Worker do_reload = 1;
561*bd1f8aebSAndroid Build Coastguard Worker }
562*bd1f8aebSAndroid Build Coastguard Worker
main(int argc,char ** argv)563*bd1f8aebSAndroid Build Coastguard Worker int main(int argc, char **argv)
564*bd1f8aebSAndroid Build Coastguard Worker {
565*bd1f8aebSAndroid Build Coastguard Worker struct pollfd pset[2];
566*bd1f8aebSAndroid Build Coastguard Worker int psize;
567*bd1f8aebSAndroid Build Coastguard Worker int opt;
568*bd1f8aebSAndroid Build Coastguard Worker
569*bd1f8aebSAndroid Build Coastguard Worker
570*bd1f8aebSAndroid Build Coastguard Worker opterr = 0;
571*bd1f8aebSAndroid Build Coastguard Worker while ((opt = getopt(argc, argv, "aAb:dvoe")) != EOF) {
572*bd1f8aebSAndroid Build Coastguard Worker switch (opt) {
573*bd1f8aebSAndroid Build Coastguard Worker case 'a':
574*bd1f8aebSAndroid Build Coastguard Worker ++all_ifaces;
575*bd1f8aebSAndroid Build Coastguard Worker break;
576*bd1f8aebSAndroid Build Coastguard Worker
577*bd1f8aebSAndroid Build Coastguard Worker case 'A':
578*bd1f8aebSAndroid Build Coastguard Worker ++listen_arp;
579*bd1f8aebSAndroid Build Coastguard Worker break;
580*bd1f8aebSAndroid Build Coastguard Worker
581*bd1f8aebSAndroid Build Coastguard Worker case 'd':
582*bd1f8aebSAndroid Build Coastguard Worker ++debug;
583*bd1f8aebSAndroid Build Coastguard Worker break;
584*bd1f8aebSAndroid Build Coastguard Worker
585*bd1f8aebSAndroid Build Coastguard Worker case 'v':
586*bd1f8aebSAndroid Build Coastguard Worker ++verbose;
587*bd1f8aebSAndroid Build Coastguard Worker break;
588*bd1f8aebSAndroid Build Coastguard Worker
589*bd1f8aebSAndroid Build Coastguard Worker case 'o':
590*bd1f8aebSAndroid Build Coastguard Worker ++allow_offlink;
591*bd1f8aebSAndroid Build Coastguard Worker break;
592*bd1f8aebSAndroid Build Coastguard Worker
593*bd1f8aebSAndroid Build Coastguard Worker case 'e':
594*bd1f8aebSAndroid Build Coastguard Worker ++only_ethers;
595*bd1f8aebSAndroid Build Coastguard Worker break;
596*bd1f8aebSAndroid Build Coastguard Worker
597*bd1f8aebSAndroid Build Coastguard Worker case 'b':
598*bd1f8aebSAndroid Build Coastguard Worker tftp_dir = optarg;
599*bd1f8aebSAndroid Build Coastguard Worker break;
600*bd1f8aebSAndroid Build Coastguard Worker
601*bd1f8aebSAndroid Build Coastguard Worker default:
602*bd1f8aebSAndroid Build Coastguard Worker usage();
603*bd1f8aebSAndroid Build Coastguard Worker }
604*bd1f8aebSAndroid Build Coastguard Worker }
605*bd1f8aebSAndroid Build Coastguard Worker if (argc > optind) {
606*bd1f8aebSAndroid Build Coastguard Worker if (argc > optind+1)
607*bd1f8aebSAndroid Build Coastguard Worker usage();
608*bd1f8aebSAndroid Build Coastguard Worker ifname = argv[optind];
609*bd1f8aebSAndroid Build Coastguard Worker }
610*bd1f8aebSAndroid Build Coastguard Worker
611*bd1f8aebSAndroid Build Coastguard Worker psize = 1;
612*bd1f8aebSAndroid Build Coastguard Worker pset[0].fd = socket(PF_PACKET, SOCK_DGRAM, 0);
613*bd1f8aebSAndroid Build Coastguard Worker
614*bd1f8aebSAndroid Build Coastguard Worker if (ifname) {
615*bd1f8aebSAndroid Build Coastguard Worker struct ifreq ifr;
616*bd1f8aebSAndroid Build Coastguard Worker memset(&ifr, 0, sizeof(ifr));
617*bd1f8aebSAndroid Build Coastguard Worker strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
618*bd1f8aebSAndroid Build Coastguard Worker if (ioctl(pset[0].fd, SIOCGIFINDEX, &ifr)) {
619*bd1f8aebSAndroid Build Coastguard Worker perror("ioctl(SIOCGIFINDEX)");
620*bd1f8aebSAndroid Build Coastguard Worker usage();
621*bd1f8aebSAndroid Build Coastguard Worker }
622*bd1f8aebSAndroid Build Coastguard Worker ifidx = ifr.ifr_ifindex;
623*bd1f8aebSAndroid Build Coastguard Worker }
624*bd1f8aebSAndroid Build Coastguard Worker
625*bd1f8aebSAndroid Build Coastguard Worker pset[1].fd = -1;
626*bd1f8aebSAndroid Build Coastguard Worker if (listen_arp) {
627*bd1f8aebSAndroid Build Coastguard Worker pset[1].fd = socket(PF_PACKET, SOCK_DGRAM, 0);
628*bd1f8aebSAndroid Build Coastguard Worker if (pset[1].fd >= 0) {
629*bd1f8aebSAndroid Build Coastguard Worker load_arp_bpflet(pset[1].fd);
630*bd1f8aebSAndroid Build Coastguard Worker psize = 1;
631*bd1f8aebSAndroid Build Coastguard Worker }
632*bd1f8aebSAndroid Build Coastguard Worker }
633*bd1f8aebSAndroid Build Coastguard Worker
634*bd1f8aebSAndroid Build Coastguard Worker if (pset[1].fd >= 0) {
635*bd1f8aebSAndroid Build Coastguard Worker struct sockaddr_ll sll;
636*bd1f8aebSAndroid Build Coastguard Worker memset(&sll, 0, sizeof(sll));
637*bd1f8aebSAndroid Build Coastguard Worker sll.sll_family = AF_PACKET;
638*bd1f8aebSAndroid Build Coastguard Worker sll.sll_protocol = htons(ETH_P_ARP);
639*bd1f8aebSAndroid Build Coastguard Worker sll.sll_ifindex = all_ifaces ? 0 : ifidx;
640*bd1f8aebSAndroid Build Coastguard Worker if (bind(pset[1].fd, (struct sockaddr*)&sll, sizeof(sll)) < 0) {
641*bd1f8aebSAndroid Build Coastguard Worker close(pset[1].fd);
642*bd1f8aebSAndroid Build Coastguard Worker pset[1].fd = -1;
643*bd1f8aebSAndroid Build Coastguard Worker psize = 1;
644*bd1f8aebSAndroid Build Coastguard Worker }
645*bd1f8aebSAndroid Build Coastguard Worker }
646*bd1f8aebSAndroid Build Coastguard Worker if (pset[0].fd >= 0) {
647*bd1f8aebSAndroid Build Coastguard Worker struct sockaddr_ll sll;
648*bd1f8aebSAndroid Build Coastguard Worker memset(&sll, 0, sizeof(sll));
649*bd1f8aebSAndroid Build Coastguard Worker sll.sll_family = AF_PACKET;
650*bd1f8aebSAndroid Build Coastguard Worker sll.sll_protocol = htons(ETH_P_RARP);
651*bd1f8aebSAndroid Build Coastguard Worker sll.sll_ifindex = all_ifaces ? 0 : ifidx;
652*bd1f8aebSAndroid Build Coastguard Worker if (bind(pset[0].fd, (struct sockaddr*)&sll, sizeof(sll)) < 0) {
653*bd1f8aebSAndroid Build Coastguard Worker close(pset[0].fd);
654*bd1f8aebSAndroid Build Coastguard Worker pset[0].fd = -1;
655*bd1f8aebSAndroid Build Coastguard Worker }
656*bd1f8aebSAndroid Build Coastguard Worker }
657*bd1f8aebSAndroid Build Coastguard Worker if (pset[0].fd < 0) {
658*bd1f8aebSAndroid Build Coastguard Worker pset[0] = pset[1];
659*bd1f8aebSAndroid Build Coastguard Worker psize--;
660*bd1f8aebSAndroid Build Coastguard Worker }
661*bd1f8aebSAndroid Build Coastguard Worker if (psize == 0) {
662*bd1f8aebSAndroid Build Coastguard Worker fprintf(stderr, "failed to bind any socket. Aborting.\n");
663*bd1f8aebSAndroid Build Coastguard Worker exit(1);
664*bd1f8aebSAndroid Build Coastguard Worker }
665*bd1f8aebSAndroid Build Coastguard Worker
666*bd1f8aebSAndroid Build Coastguard Worker if (!debug) {
667*bd1f8aebSAndroid Build Coastguard Worker int fd;
668*bd1f8aebSAndroid Build Coastguard Worker pid_t pid = fork();
669*bd1f8aebSAndroid Build Coastguard Worker
670*bd1f8aebSAndroid Build Coastguard Worker if (pid > 0)
671*bd1f8aebSAndroid Build Coastguard Worker exit(0);
672*bd1f8aebSAndroid Build Coastguard Worker else if (pid == -1) {
673*bd1f8aebSAndroid Build Coastguard Worker perror("rarpd: fork");
674*bd1f8aebSAndroid Build Coastguard Worker exit(1);
675*bd1f8aebSAndroid Build Coastguard Worker }
676*bd1f8aebSAndroid Build Coastguard Worker
677*bd1f8aebSAndroid Build Coastguard Worker if (chdir("/") < 0) {
678*bd1f8aebSAndroid Build Coastguard Worker perror("rarpd: chdir");
679*bd1f8aebSAndroid Build Coastguard Worker exit(1);
680*bd1f8aebSAndroid Build Coastguard Worker }
681*bd1f8aebSAndroid Build Coastguard Worker
682*bd1f8aebSAndroid Build Coastguard Worker fd = open("/dev/null", O_RDWR);
683*bd1f8aebSAndroid Build Coastguard Worker if (fd >= 0) {
684*bd1f8aebSAndroid Build Coastguard Worker dup2(fd, 0);
685*bd1f8aebSAndroid Build Coastguard Worker dup2(fd, 1);
686*bd1f8aebSAndroid Build Coastguard Worker dup2(fd, 2);
687*bd1f8aebSAndroid Build Coastguard Worker if (fd > 2)
688*bd1f8aebSAndroid Build Coastguard Worker close(fd);
689*bd1f8aebSAndroid Build Coastguard Worker }
690*bd1f8aebSAndroid Build Coastguard Worker setsid();
691*bd1f8aebSAndroid Build Coastguard Worker }
692*bd1f8aebSAndroid Build Coastguard Worker
693*bd1f8aebSAndroid Build Coastguard Worker openlog("rarpd", LOG_PID | LOG_CONS, LOG_DAEMON);
694*bd1f8aebSAndroid Build Coastguard Worker catch_signal(SIGALRM, sig_alarm);
695*bd1f8aebSAndroid Build Coastguard Worker catch_signal(SIGHUP, sig_hup);
696*bd1f8aebSAndroid Build Coastguard Worker
697*bd1f8aebSAndroid Build Coastguard Worker for (;;) {
698*bd1f8aebSAndroid Build Coastguard Worker int i;
699*bd1f8aebSAndroid Build Coastguard Worker
700*bd1f8aebSAndroid Build Coastguard Worker if (do_reload) {
701*bd1f8aebSAndroid Build Coastguard Worker configure();
702*bd1f8aebSAndroid Build Coastguard Worker do_reload = 0;
703*bd1f8aebSAndroid Build Coastguard Worker }
704*bd1f8aebSAndroid Build Coastguard Worker
705*bd1f8aebSAndroid Build Coastguard Worker #define EVENTS (POLLIN|POLLPRI|POLLERR|POLLHUP)
706*bd1f8aebSAndroid Build Coastguard Worker pset[0].events = EVENTS;
707*bd1f8aebSAndroid Build Coastguard Worker pset[0].revents = 0;
708*bd1f8aebSAndroid Build Coastguard Worker pset[1].events = EVENTS;
709*bd1f8aebSAndroid Build Coastguard Worker pset[1].revents = 0;
710*bd1f8aebSAndroid Build Coastguard Worker
711*bd1f8aebSAndroid Build Coastguard Worker i = poll(pset, psize, -1);
712*bd1f8aebSAndroid Build Coastguard Worker if (i <= 0) {
713*bd1f8aebSAndroid Build Coastguard Worker if (errno != EINTR && i<0) {
714*bd1f8aebSAndroid Build Coastguard Worker syslog(LOG_ERR, "poll returned some crap: %m\n");
715*bd1f8aebSAndroid Build Coastguard Worker sleep(10);
716*bd1f8aebSAndroid Build Coastguard Worker }
717*bd1f8aebSAndroid Build Coastguard Worker continue;
718*bd1f8aebSAndroid Build Coastguard Worker }
719*bd1f8aebSAndroid Build Coastguard Worker for (i=0; i<psize; i++) {
720*bd1f8aebSAndroid Build Coastguard Worker if (pset[i].revents&EVENTS)
721*bd1f8aebSAndroid Build Coastguard Worker serve_it(pset[i].fd);
722*bd1f8aebSAndroid Build Coastguard Worker }
723*bd1f8aebSAndroid Build Coastguard Worker }
724*bd1f8aebSAndroid Build Coastguard Worker }
725