rule: two boolean parameters with a flags field
[project/relayd.git] / main.c
1 /*
2  *   Copyright (C) 2010 Felix Fietkau <nbd@openwrt.org>
3  *
4  *   This program is free software; you can redistribute it and/or modify
5  *   it under the terms of the GNU General Public License v2 as published by
6  *   the Free Software Foundation.
7  *
8  *   This program is distributed in the hope that it will be useful,
9  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  *   GNU General Public License for more details.
12  *
13  *   You should have received a copy of the GNU General Public License
14  *   along with this program; if not, write to the Free Software
15  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
16  *
17  */
18 #include <sys/ioctl.h>
19 #include <sys/socket.h>
20
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <stddef.h>
25 #include <stdlib.h>
26 #include <stdint.h>
27 #include <stdbool.h>
28 #include <errno.h>
29 #include <signal.h>
30 #include <string.h>
31
32 #include "relayd.h"
33
34 static LIST_HEAD(pending_routes);
35 LIST_HEAD(interfaces);
36 int debug;
37
38 static int host_timeout;
39 static int inet_sock;
40 static int forward_bcast;
41 static int forward_dhcp;
42
43 struct relayd_pending_route {
44         struct relayd_route rt;
45         struct uloop_timeout timeout;
46         uint8_t gateway[4];
47 };
48
49 static struct relayd_host *find_host_by_ipaddr(struct relayd_interface *rif, const uint8_t *ipaddr)
50 {
51         struct relayd_host *host;
52
53         if (!rif) {
54                 list_for_each_entry(rif, &interfaces, list) {
55                         host = find_host_by_ipaddr(rif, ipaddr);
56                         if (!host)
57                                 continue;
58
59                         return host;
60                 }
61                 return NULL;
62         }
63
64         list_for_each_entry(host, &rif->hosts, list) {
65                 if (memcmp(ipaddr, host->ipaddr, sizeof(host->ipaddr)) != 0)
66                         continue;
67
68                 return host;
69         }
70         return NULL;
71 }
72
73 static void add_arp(struct relayd_host *host)
74 {
75         struct sockaddr_in *sin;
76         struct arpreq arp;
77
78         strncpy(arp.arp_dev, host->rif->ifname, sizeof(arp.arp_dev));
79         arp.arp_flags = ATF_COM;
80
81         arp.arp_ha.sa_family = ARPHRD_ETHER;
82         memcpy(arp.arp_ha.sa_data, host->lladdr, ETH_ALEN);
83
84         sin = (struct sockaddr_in *) &arp.arp_pa;
85         sin->sin_family = AF_INET;
86         memcpy(&sin->sin_addr, host->ipaddr, sizeof(host->ipaddr));
87
88         ioctl(inet_sock, SIOCSARP, &arp);
89 }
90
91 static void timeout_host_route(struct uloop_timeout *timeout)
92 {
93         struct relayd_pending_route *rt;
94
95         rt = container_of(timeout, struct relayd_pending_route, timeout);
96         list_del(&rt->rt.list);
97         free(rt);
98 }
99
100 void relayd_add_host_route(struct relayd_host *host, const uint8_t *dest, uint8_t mask)
101 {
102         struct relayd_route *rt;
103
104         list_for_each_entry(rt, &host->routes, list) {
105                 if (!memcmp(rt->dest, dest, sizeof(rt->dest)) && rt->mask == mask)
106                         return;
107         }
108
109         rt = calloc(1, sizeof(*rt));
110         if (!rt)
111                 return;
112
113         list_add(&rt->list, &host->routes);
114         memcpy(rt->dest, dest, sizeof(rt->dest));
115         rt->mask = mask;
116         relayd_add_route(host, rt);
117 }
118
119 static void del_host(struct relayd_host *host)
120 {
121         struct relayd_route *route, *tmp;
122
123         DPRINTF(1, "%s: deleting host "IP_FMT" ("MAC_FMT")\n", host->rif->ifname,
124                 IP_BUF(host->ipaddr), MAC_BUF(host->lladdr));
125
126         list_for_each_entry_safe(route, tmp, &host->routes, list) {
127                 relayd_del_route(host, route);
128                 list_del(&route->list);
129                 free(route);
130         }
131         if (host->rif->managed)
132                 relayd_del_route(host, NULL);
133         uloop_timeout_cancel(&host->timeout);
134         list_del(&host->list);
135         free(host);
136 }
137
138 static void fill_arp_request(struct arp_packet *pkt, struct relayd_interface *rif,
139                              const uint8_t spa[4], const uint8_t tpa[4])
140 {
141         memset(pkt, 0, sizeof(*pkt));
142
143         pkt->eth.ether_type = htons(ETHERTYPE_ARP);
144         memcpy(pkt->eth.ether_shost, rif->sll.sll_addr, ETH_ALEN);
145
146         memcpy(pkt->arp.arp_sha, rif->sll.sll_addr, ETH_ALEN);
147         memcpy(pkt->arp.arp_spa, spa, 4);
148         memcpy(pkt->arp.arp_tpa, tpa, 4);
149
150         pkt->arp.arp_hrd = htons(ARPHRD_ETHER);
151         pkt->arp.arp_pro = htons(ETH_P_IP);
152         pkt->arp.arp_hln = ETH_ALEN;
153         pkt->arp.arp_pln = 4;
154 }
155
156 static void send_arp_request(struct relayd_interface *rif, const uint8_t *ipaddr)
157 {
158         struct arp_packet pkt;
159
160         fill_arp_request(&pkt, rif, rif->src_ip, ipaddr);
161
162         pkt.arp.arp_op = htons(ARPOP_REQUEST);
163         memcpy(pkt.arp.arp_spa, rif->src_ip, ETH_ALEN);
164         memset(pkt.arp.arp_tha, 0, ETH_ALEN);
165         memset(pkt.eth.ether_dhost, 0xff, ETH_ALEN);
166
167         DPRINTF(2, "%s: sending ARP who-has "IP_FMT", tell "IP_FMT" ("MAC_FMT")\n",
168                 rif->ifname, IP_BUF(pkt.arp.arp_tpa),
169                 IP_BUF(pkt.arp.arp_spa), MAC_BUF(pkt.eth.ether_shost));
170
171         sendto(rif->fd.fd, &pkt, sizeof(pkt), 0,
172                 (struct sockaddr *) &rif->sll, sizeof(rif->sll));
173 }
174
175 void relayd_add_pending_route(const uint8_t *gateway, const uint8_t *dest, uint8_t mask, int timeout)
176 {
177         struct relayd_pending_route *rt;
178         struct relayd_interface *rif;
179         struct relayd_host *host;
180
181         host = find_host_by_ipaddr(NULL, gateway);
182         if (host) {
183                 relayd_add_host_route(host, dest, mask);
184                 return;
185         }
186
187         rt = calloc(1, sizeof(*rt));
188         if (!rt)
189                 return;
190
191         memcpy(rt->gateway, gateway, sizeof(rt->gateway));
192         memcpy(rt->rt.dest, dest, sizeof(rt->rt.dest));
193         rt->rt.mask = mask;
194         list_add(&rt->rt.list, &pending_routes);
195         if (timeout <= 0)
196                 return;
197
198         rt->timeout.cb = timeout_host_route;
199         uloop_timeout_set(&rt->timeout, 10000);
200         list_for_each_entry(rif, &interfaces, list) {
201                 send_arp_request(rif, gateway);
202         }
203 }
204
205 static void send_arp_reply(struct relayd_interface *rif, uint8_t spa[4],
206                            uint8_t tha[ETH_ALEN], uint8_t tpa[4])
207 {
208         struct arp_packet pkt;
209
210         fill_arp_request(&pkt, rif, spa, tpa);
211
212         pkt.arp.arp_op = htons(ARPOP_REPLY);
213         memcpy(pkt.eth.ether_dhost, tha, ETH_ALEN);
214         memcpy(pkt.arp.arp_tha, tha, ETH_ALEN);
215
216         DPRINTF(2, "%s: sending ARP reply to "IP_FMT", "IP_FMT" is at ("MAC_FMT")\n",
217                 rif->ifname, IP_BUF(pkt.arp.arp_tpa),
218                 IP_BUF(pkt.arp.arp_spa), MAC_BUF(pkt.eth.ether_shost));
219
220         sendto(rif->fd.fd, &pkt, sizeof(pkt), 0,
221                 (struct sockaddr *) &rif->sll, sizeof(rif->sll));
222 }
223
224 static void host_entry_timeout(struct uloop_timeout *timeout)
225 {
226         struct relayd_host *host = container_of(timeout, struct relayd_host, timeout);
227
228         /*
229          * When a host is behind a managed interface, we must not expire its host
230          * entry prematurely, as this will cause routes to the node to expire,
231          * leading to loss of connectivity from the other side.
232          * When the timeout is reached, try pinging the host a few times before
233          * giving up on it.
234          */
235         if (host->rif->managed && host->cleanup_pending < 2) {
236                 send_arp_request(host->rif, host->ipaddr);
237                 host->cleanup_pending++;
238                 uloop_timeout_set(&host->timeout, 1000);
239                 return;
240         }
241         del_host(host);
242 }
243
244 static struct relayd_host *add_host(struct relayd_interface *rif, const uint8_t *lladdr, const uint8_t *ipaddr)
245 {
246         struct relayd_host *host;
247         struct relayd_pending_route *route, *rtmp;
248
249         DPRINTF(1, "%s: adding host "IP_FMT" ("MAC_FMT")\n", rif->ifname,
250                         IP_BUF(ipaddr), MAC_BUF(lladdr));
251
252         host = calloc(1, sizeof(*host));
253         INIT_LIST_HEAD(&host->routes);
254         host->rif = rif;
255         memcpy(host->ipaddr, ipaddr, sizeof(host->ipaddr));
256         memcpy(host->lladdr, lladdr, sizeof(host->lladdr));
257         list_add(&host->list, &rif->hosts);
258         host->timeout.cb = host_entry_timeout;
259         uloop_timeout_set(&host->timeout, host_timeout * 1000);
260
261         add_arp(host);
262         if (rif->managed)
263                 relayd_add_route(host, NULL);
264
265         list_for_each_entry_safe(route, rtmp, &pending_routes, rt.list) {
266                 if (memcmp(route->gateway, ipaddr, 4) != 0)
267                         continue;
268
269                 relayd_add_host_route(host, route->rt.dest, route->rt.mask);
270                 if (!route->timeout.pending)
271                         continue;
272
273                 uloop_timeout_cancel(&route->timeout);
274                 list_del(&route->rt.list);
275                 free(route);
276         }
277
278         return host;
279 }
280
281 struct relayd_host *relayd_refresh_host(struct relayd_interface *rif, const uint8_t *lladdr, const uint8_t *ipaddr)
282 {
283         struct relayd_host *host;
284
285         host = find_host_by_ipaddr(rif, ipaddr);
286         if (!host) {
287                 host = find_host_by_ipaddr(NULL, ipaddr);
288
289                 /* 
290                  * When we suddenly see the host appearing on a different interface,
291                  * reduce the timeout to make the old entry expire faster, in case the
292                  * host has moved.
293                  * If the old entry is behind a managed interface, it will be pinged
294                  * before we expire it
295                  */
296                 if (host && !host->cleanup_pending) {
297                         uloop_timeout_set(&host->timeout, 1);
298                         return NULL;
299                 }
300
301                 host = add_host(rif, lladdr, ipaddr);
302         } else {
303                 host->cleanup_pending = false;
304                 uloop_timeout_set(&host->timeout, host_timeout * 1000);
305         }
306
307         return host;
308 }
309
310 static void relay_arp_request(struct relayd_interface *from_rif, struct arp_packet *pkt)
311 {
312         struct relayd_interface *rif;
313         struct arp_packet reqpkt;
314
315         memcpy(&reqpkt, pkt, sizeof(reqpkt));
316         list_for_each_entry(rif, &interfaces, list) {
317                 if (rif == from_rif)
318                         continue;
319
320                 memcpy(reqpkt.eth.ether_shost, rif->sll.sll_addr, ETH_ALEN);
321                 memcpy(reqpkt.arp.arp_sha, rif->sll.sll_addr, ETH_ALEN);
322
323                 DPRINTF(2, "%s: sending ARP who-has "IP_FMT", tell "IP_FMT" ("MAC_FMT")\n",
324                         rif->ifname, IP_BUF(reqpkt.arp.arp_tpa),
325                         IP_BUF(reqpkt.arp.arp_spa), MAC_BUF(reqpkt.eth.ether_shost));
326
327                 sendto(rif->fd.fd, &reqpkt, sizeof(reqpkt), 0,
328                         (struct sockaddr *) &rif->sll, sizeof(rif->sll));
329         }
330 }
331
332 static void recv_arp_request(struct relayd_interface *rif, struct arp_packet *pkt)
333 {
334         struct relayd_host *host;
335
336         DPRINTF(2, "%s: ARP who-has "IP_FMT", tell "IP_FMT" ("MAC_FMT")\n",
337                 rif->ifname,
338                 IP_BUF(pkt->arp.arp_tpa),
339                 IP_BUF(pkt->arp.arp_spa),
340                 MAC_BUF(pkt->eth.ether_shost));
341
342         if (!memcmp(pkt->arp.arp_spa, "\x00\x00\x00\x00", 4))
343                 return;
344
345         relayd_refresh_host(rif, pkt->eth.ether_shost, pkt->arp.arp_spa);
346
347         host = find_host_by_ipaddr(NULL, pkt->arp.arp_tpa);
348
349         /*
350          * If a host is being pinged because of a timeout, do not use the cached
351          * entry here. That way we can avoid giving out stale data in case the node
352          * has moved. We shouldn't relay requests here either, as we might miss our
353          * chance to create a host route.
354          */
355         if (host && host->cleanup_pending)
356                 return;
357
358         relay_arp_request(rif, pkt);
359 }
360
361
362 static void recv_arp_reply(struct relayd_interface *rif, struct arp_packet *pkt)
363 {
364         struct relayd_host *host;
365
366         DPRINTF(2, "%s: received ARP reply for "IP_FMT" from "MAC_FMT", deliver to "IP_FMT"\n",
367                 rif->ifname,
368                 IP_BUF(pkt->arp.arp_spa),
369                 MAC_BUF(pkt->eth.ether_shost),
370                 IP_BUF(pkt->arp.arp_tpa));
371
372         if (memcmp(pkt->arp.arp_sha, rif->sll.sll_addr, ETH_ALEN) != 0)
373                 relayd_refresh_host(rif, pkt->arp.arp_sha, pkt->arp.arp_spa);
374
375         if (!memcmp(pkt->arp.arp_tpa, rif->src_ip, 4))
376                 return;
377
378         host = find_host_by_ipaddr(NULL, pkt->arp.arp_tpa);
379         if (!host)
380                 return;
381
382         if (host->rif == rif)
383                 return;
384
385         send_arp_reply(host->rif, pkt->arp.arp_spa, host->lladdr, host->ipaddr);
386 }
387
388 static void recv_packet(struct uloop_fd *fd, unsigned int events)
389 {
390         struct relayd_interface *rif = container_of(fd, struct relayd_interface, fd);
391         struct arp_packet *pkt;
392         static char pktbuf[4096];
393         int pktlen;
394
395         do {
396                 if (rif->fd.error)
397                         uloop_end();
398
399                 pktlen = recv(rif->fd.fd, pktbuf, sizeof(pktbuf), 0);
400                 if (pktlen < 0) {
401                         if (errno == EINTR)
402                                 continue;
403
404                         break;
405                 }
406
407                 if (!pktlen)
408                         break;
409
410                 pkt = (void *)pktbuf;
411                 if (pkt->arp.arp_op == htons(ARPOP_REPLY))
412                         recv_arp_reply(rif, pkt);
413                 else if (pkt->arp.arp_op == htons(ARPOP_REQUEST))
414                         recv_arp_request(rif, pkt);
415                 else
416                         DPRINTF(1, "received unknown packet type: %04x\n", ntohs(pkt->arp.arp_op));
417
418         } while (1);
419 }
420
421 void relayd_forward_bcast_packet(struct relayd_interface *from_rif, void *packet, int len)
422 {
423         struct relayd_interface *rif;
424         struct ether_header *eth = packet;
425
426         list_for_each_entry(rif, &interfaces, list) {
427                 if (rif == from_rif)
428                         continue;
429
430                 DPRINTF(3, "%s: forwarding broadcast packet to %s\n", from_rif->ifname, rif->ifname);
431                 memcpy(eth->ether_shost, rif->sll.sll_addr, ETH_ALEN);
432                 send(rif->bcast_fd.fd, packet, len, 0);
433         }
434 }
435
436 static void recv_bcast_packet(struct uloop_fd *fd, unsigned int events)
437 {
438         struct relayd_interface *rif = container_of(fd, struct relayd_interface, bcast_fd);
439         static char pktbuf[4096];
440         int pktlen;
441
442         do {
443                 if (rif->fd.error)
444                         uloop_end();
445
446                 pktlen = recv(rif->bcast_fd.fd, pktbuf, sizeof(pktbuf), 0);
447                 if (pktlen < 0) {
448                         if (errno == EINTR)
449                                 continue;
450
451                         break;
452                 }
453
454                 if (!pktlen)
455                         break;
456
457                 if (!forward_bcast && !forward_dhcp)
458                         continue;
459
460                 if (relayd_handle_dhcp_packet(rif, pktbuf, pktlen, forward_dhcp))
461                         continue;
462
463                 if (forward_bcast)
464                         relayd_forward_bcast_packet(rif, pktbuf, pktlen);
465         } while (1);
466 }
467
468
469 static int init_interface(struct relayd_interface *rif)
470 {
471         struct sockaddr_ll *sll = &rif->sll;
472         struct sockaddr_in *sin;
473         struct ifreq ifr;
474         int fd = rif->fd.fd;
475 #ifdef PACKET_RECV_TYPE
476         unsigned int pkt_type;
477 #endif
478
479         fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
480         if (fd < 0)
481                 return -1;
482
483         rif->fd.fd = fd;
484
485         memset(&ifr, 0, sizeof(ifr));
486         strcpy(ifr.ifr_name, rif->ifname);
487
488         if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
489                 perror("ioctl(SIOCGIFHWADDR)");
490                 return -1;
491         }
492
493         memcpy(sll->sll_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
494         sll->sll_family = AF_PACKET;
495         sll->sll_protocol = htons(ETH_P_ARP);
496         sll->sll_pkttype = PACKET_BROADCAST;
497         sll->sll_hatype = ARPHRD_ETHER;
498         sll->sll_halen = ETH_ALEN;
499
500         if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
501                 perror("ioctl(SIOCGIFINDEX)");
502                 return -1;
503         }
504
505         sll->sll_ifindex = ifr.ifr_ifindex;
506
507         if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
508                 memcpy(rif->src_ip, DUMMY_IP, sizeof(rif->src_ip));
509         } else {
510                 sin = (struct sockaddr_in *) &ifr.ifr_addr;
511                 memcpy(rif->src_ip, &sin->sin_addr.s_addr, sizeof(rif->src_ip));
512         }
513
514         if (bind(fd, (struct sockaddr *)sll, sizeof(struct sockaddr_ll)) < 0) {
515                 perror("bind(ETH_P_ARP)");
516                 return -1;
517         }
518
519         rif->fd.cb = recv_packet;
520         uloop_fd_add(&rif->fd, ULOOP_READ | ULOOP_EDGE_TRIGGER);
521
522         if (!forward_bcast && !forward_dhcp)
523                 return 0;
524
525         fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IP));
526         if (fd < 0)
527                 return 0;
528
529         rif->bcast_fd.fd = fd;
530         rif->bcast_fd.cb = recv_bcast_packet;
531
532         memcpy(&rif->bcast_sll, &rif->sll, sizeof(rif->bcast_sll));
533         sll = &rif->bcast_sll;
534         sll->sll_protocol = htons(ETH_P_IP);
535
536         if (bind(fd, (struct sockaddr *)sll, sizeof(struct sockaddr_ll)) < 0) {
537                 perror("bind(ETH_P_IP)");
538                 return 0;
539         }
540
541 #ifdef PACKET_RECV_TYPE
542         pkt_type = (1 << PACKET_BROADCAST);
543         setsockopt(fd, SOL_PACKET, PACKET_RECV_TYPE, &pkt_type, sizeof(pkt_type));
544 #endif
545
546         uloop_fd_add(&rif->bcast_fd, ULOOP_READ | ULOOP_EDGE_TRIGGER);
547         relayd_add_interface_routes(rif);
548         return 0;
549 }
550
551 static void ping_static_routes(void)
552 {
553         struct relayd_pending_route *rt;
554         struct relayd_interface *rif;
555
556         list_for_each_entry(rt, &pending_routes, rt.list)
557                 list_for_each_entry(rif, &interfaces, list)
558                         send_arp_request(rif, rt->gateway);
559 }
560
561 static int init_interfaces(void)
562 {
563         struct relayd_interface *rif;
564         int ret;
565
566         list_for_each_entry(rif, &interfaces, list) {
567                 ret = init_interface(rif);
568                 if (ret < 0)
569                         return ret;
570         }
571
572         return 0;
573 }
574
575 static void cleanup_hosts(void)
576 {
577         struct relayd_interface *rif;
578         struct relayd_host *host, *tmp;
579
580         list_for_each_entry(rif, &interfaces, list) {
581                 list_for_each_entry_safe(host, tmp, &rif->hosts, list) {
582                         del_host(host);
583                 }
584         }
585 }
586
587 static void free_interfaces(void)
588 {
589         struct relayd_interface *rif, *rtmp;
590
591         list_for_each_entry_safe(rif, rtmp, &interfaces, list) {
592                 relayd_del_interface_routes(rif);
593                 list_del(&rif->list);
594                 free(rif);
595         }
596 }
597
598 static struct relayd_interface *alloc_interface(const char *ifname, bool managed)
599 {
600         struct relayd_interface *rif;
601
602         if (strlen(ifname) >= IFNAMSIZ)
603                 return NULL;
604
605         rif = calloc(1, sizeof(*rif));
606         if (!rif)
607                 return NULL;
608
609         INIT_LIST_HEAD(&rif->hosts);
610         strcpy(rif->ifname, ifname);
611         list_add(&rif->list, &interfaces);
612         rif->managed = managed;
613
614         return rif;
615 }
616
617 static void die(int signo)
618 {
619         /*
620          * When we hit SIGTERM, clean up interfaces directly, so that we
621          * won't leave our routing in an invalid state.
622          */
623         cleanup_hosts();
624         free_interfaces();
625         exit(1);
626 }
627
628 static int usage(const char *progname)
629 {
630         fprintf(stderr, "Usage: %s <options>\n"
631                         "\n"
632                         "Options:\n"
633                         "       -d              Enable debug messages\n"
634                         "       -i <ifname>     Add an interface for relaying\n"
635                         "       -I <ifname>     Same as -i, except with ARP cache and host route management\n"
636                         "                       You need to specify at least two interfaces\n"
637                         "       -G <ip>         Set a gateway IP for clients\n"
638                         "       -R <gateway>:<net>/<mask>\n"
639                         "                       Add a static route for <net>/<mask> via <gateway>\n"
640                         "       -t <timeout>    Host entry expiry timeout\n"
641                         "       -T <table>      Set routing table number for automatically added routes\n"
642                         "       -B              Enable broadcast forwarding\n"
643                         "       -D              Enable DHCP forwarding\n"
644                         "\n",
645                 progname);
646         return -1;
647 }
648
649 int main(int argc, char **argv)
650 {
651         struct relayd_interface *rif = NULL;
652         struct in_addr addr, addr2;
653         bool managed;
654         int ifnum = 0;
655         char *s, *s2;
656         int mask;
657         int ch;
658
659         debug = 0;
660         inet_sock = socket(AF_INET, SOCK_DGRAM, 0);
661         if (inet_sock < 0) {
662                 perror("socket(AF_INET)");
663                 return 1;
664         }
665
666         host_timeout = 60;
667         forward_bcast = 0;
668         uloop_init();
669
670         while ((ch = getopt(argc, argv, "I:i:t:BDdT:G:R:")) != -1) {
671                 switch(ch) {
672                 case 'I':
673                         managed = true;
674                         /* fall through */
675                 case 'i':
676                         ifnum++;
677                         rif = alloc_interface(optarg, managed);
678                         if (!rif)
679                                 return 1;
680
681                         managed = false;
682                         break;
683                 case 't':
684                         host_timeout = atoi(optarg);
685                         if (host_timeout <= 0)
686                                 return usage(argv[0]);
687                         break;
688                 case 'd':
689                         debug++;
690                         break;
691                 case 'B':
692                         forward_bcast = 1;
693                         break;
694                 case 'D':
695                         forward_dhcp = 1;
696                         break;
697                 case 'T':
698                         route_table = atoi(optarg);
699                         if (route_table <= 0)
700                                 return usage(argv[0]);
701                         break;
702                 case 'G':
703                         if (!inet_aton(optarg, &addr)) {
704                                 fprintf(stderr, "Address '%s' not found\n", optarg);
705                                 return 1;
706                         }
707                         relayd_add_pending_route((uint8_t *) &addr.s_addr, (const uint8_t *) "\x00\x00\x00\x00", 0, 0);
708                         break;
709                 case 'R':
710                         s = strchr(optarg, ':');
711                         if (!s)
712                                 return usage(argv[0]);
713
714                         *(s++) = 0;
715                         if (!inet_aton(optarg, &addr)) {
716                                 fprintf(stderr, "Address '%s' not found\n", optarg);
717                                 return 1;
718                         }
719
720                         s2 = strchr(s, '/');
721                         if (!s2)
722                                 return usage(argv[0]);
723
724                         *(s2++) = 0;
725                         if (!inet_aton(s, &addr2)) {
726                                 fprintf(stderr, "Address '%s' not found\n", s);
727                                 return 1;
728                         }
729
730                         mask = atoi(s2);
731                         if (mask < 0 || mask > 32)
732                                 return usage(argv[0]);
733
734                         relayd_add_pending_route((uint8_t *) &addr.s_addr, (uint8_t *) &addr2.s_addr, mask, 0);
735                         break;
736                 case '?':
737                 default:
738                         return usage(argv[0]);
739                 }
740         }
741
742         if (list_empty(&interfaces))
743                 return usage(argv[0]);
744
745         if (ifnum < 2) {
746                 fprintf(stderr, "ERROR: Need at least 2 interfaces for relaying\n");
747                 return -1;
748         }
749
750         argc -= optind;
751         argv += optind;
752
753         signal(SIGTERM, die);
754         signal(SIGHUP, die);
755         signal(SIGUSR1, die);
756         signal(SIGUSR2, die);
757
758         if (relayd_rtnl_init() < 0)
759                 return 1;
760
761         if (init_interfaces() < 0)
762                 return 1;
763
764         ping_static_routes();
765
766         uloop_run();
767         uloop_done();
768
769         cleanup_hosts();
770         free_interfaces();
771         relayd_rtnl_done();
772         close(inet_sock);
773
774         return 0;
775 }