Add rp_filter handling for linux 2.6.31+
[olsrd.git] / src / gateway_default_handler.c
1 /*
2  * gateway_default_handler.c
3  *
4  *  Created on: Jan 29, 2010
5  *      Author: rogge
6  */
7
8 #include "defs.h"
9 #include "gateway.h"
10 #include "gateway_default_handler.h"
11 #include "scheduler.h"
12 #include "tc_set.h"
13
14 #include "assert.h"
15
16 #ifndef WIN32
17 static uint32_t gw_def_nodecount, gw_def_stablecount;
18 static bool gw_def_finished_ipv4, gw_def_finished_ipv6;
19
20 static struct timer_entry *gw_def_timer;
21
22 static void gw_default_startup_handler(void);
23 static void gw_default_choosegw_handler(bool ipv4, bool ipv6);
24 static void gw_default_update_handler(struct gateway_entry *);
25 static void gw_default_delete_handler(struct gateway_entry *);
26
27 static struct olsr_gw_handler gw_def_handler = {
28   &gw_default_startup_handler,
29   &gw_default_choosegw_handler,
30   &gw_default_update_handler,
31   &gw_default_delete_handler
32 };
33
34 /**
35  * Look through the gateway list and select the best gateway
36  * depending on the distance to this router
37  */
38 static void gw_default_choose_gateway(void) {
39   struct tc_entry *tc;
40   struct gateway_entry *inet_ipv4, *inet_ipv6;
41   olsr_linkcost cost_ipv4, cost_ipv6;
42   struct gateway_entry *gw;
43   bool dual;
44
45   cost_ipv4 = UINT32_MAX;
46   cost_ipv6 = UINT32_MAX;
47
48   inet_ipv4 = NULL;
49   inet_ipv6 = NULL;
50
51   OLSR_FOR_ALL_GATEWAY_ENTRIES(gw) {
52     /* gateways should not exist without tc entry */
53     if ((tc = olsr_lookup_tc_entry(&gw->originator)) == NULL) {
54       continue;
55     }
56
57     if (!gw_def_finished_ipv4 && gw->ipv4 && gw->ipv4nat == olsr_cnf->smart_gw_allow_nat && tc->path_cost < cost_ipv4) {
58       inet_ipv4 = gw;
59     }
60     if (!gw_def_finished_ipv6 && gw->ipv6 && tc->path_cost < cost_ipv6) {
61       inet_ipv6 = gw;
62     }
63   } OLSR_FOR_ALL_GATEWAY_ENTRIES_END(gw)
64
65   /* found an IPv4 gateway ? */
66   gw_def_finished_ipv4 |= inet_ipv4 != NULL;
67   gw_def_finished_ipv6 |= inet_ipv6 != NULL;
68   dual = inet_ipv4 == inet_ipv6;
69   if (inet_ipv4) {
70     olsr_set_inet_gateway(&inet_ipv4->originator, true, dual, false);
71   }
72   if (inet_ipv6 && !dual) {
73     olsr_set_inet_gateway(&inet_ipv6->originator, false, true, false);
74   }
75
76   /* finished ? */
77   if (gw_def_finished_ipv4 && gw_def_finished_ipv6) {
78     olsr_stop_timer(gw_def_timer);
79     gw_def_timer = NULL;
80   }
81 }
82
83 /* timer for laze gateway selection */
84 static void gw_default_timer(void *unused __attribute__ ((unused))) {
85   if (tc_tree.count < gw_def_nodecount) {
86     gw_def_stablecount++;
87   }
88   else {
89     gw_def_nodecount = tc_tree.count;
90     gw_def_stablecount = 0;
91   }
92
93   if (gw_def_stablecount >= GW_DEFAULT_STABLE_COUNT) {
94     gw_default_choose_gateway();
95   }
96 }
97
98 /* gateway handler callbacks */
99 static void gw_default_startup_handler(void) {
100   /* reset node count */
101   gw_def_nodecount = tc_tree.count;
102   gw_def_stablecount = 0;
103
104   /* and start looking for gateway */
105   olsr_set_timer(&gw_def_timer, GW_DEFAULT_TIMER_INTERVAL, 0, true, &gw_default_timer, NULL, 0);
106 }
107
108 static void gw_default_update_handler(struct gateway_entry *gw) {
109   bool v4changed, v6changed;
110
111   v4changed = gw == olsr_get_inet_gateway(false)
112       && (!gw->ipv4 || (gw->ipv4nat && !olsr_cnf->smart_gw_allow_nat));
113   v6changed = gw == olsr_get_inet_gateway(true) && !gw->ipv6;
114
115   olsr_gw_default_lookup_gateway(v4changed, v6changed);
116 }
117
118 static void gw_default_delete_handler(struct gateway_entry *gw) {
119   bool isv4, isv6;
120
121   isv4 = gw == olsr_get_inet_gateway(false);
122   isv6 = gw == olsr_get_inet_gateway(true);
123
124   if (gw != NULL && (isv4 || isv6)) {
125     olsr_gw_default_lookup_gateway(isv4, isv6);
126   }
127 }
128
129 static void gw_default_choosegw_handler(bool ipv4, bool ipv6) {
130   olsr_gw_default_lookup_gateway(ipv4, ipv6);
131
132   if (!(gw_def_finished_ipv4 && gw_def_finished_ipv6)) {
133     gw_default_startup_handler();
134   }
135 }
136
137 /**
138  * initialization of default gateway handler
139  */
140 void olsr_gw_default_init(void) {
141   /* initialize values */
142   gw_def_timer = NULL;
143   gw_def_finished_ipv4 = false;
144   gw_def_finished_ipv6 = false;
145   gw_def_nodecount = 0;
146   gw_def_stablecount = 0;
147   gw_def_timer = NULL;
148
149   /* setup default handler */
150   olsr_set_inetgw_handler(&gw_def_handler);
151 }
152
153 /**
154  * Lookup a new gateway based on distance metric
155  *
156  * @param ipv4 lookup new v4 gateway
157  * @param ipv6 lookup new v6 gateway
158  */
159 void olsr_gw_default_lookup_gateway(bool ipv4, bool ipv6) {
160   if (ipv4) {
161     /* get new ipv4 GW if we use OLSRv4 or NIIT */
162     gw_def_finished_ipv4 = olsr_cnf->ip_version == AF_INET6 && !olsr_cnf->use_niit;
163   }
164   if (ipv6) {
165     /* get new ipv6 GW if we use OLSRv6 */
166     gw_def_finished_ipv6 = olsr_cnf->ip_version == AF_INET;
167   }
168
169   if (!(gw_def_finished_ipv4 && gw_def_finished_ipv6)) {
170     gw_default_choose_gateway();
171   }
172 }
173 #endif