Changes to p2pd for duplicate packet filter
[olsrd.git] / src / gateway.c
1 /*
2  * gateway.c
3  *
4  *  Created on: 05.01.2010
5  *      Author: henning
6  */
7
8 #include "common/avl.h"
9 #include "defs.h"
10 #include "ipcalc.h"
11 #include "olsr.h"
12 #include "olsr_cfg.h"
13 #include "olsr_cookie.h"
14 #include "scheduler.h"
15 #include "kernel_routes.h"
16 #include "kernel_tunnel.h"
17 #include "net_os.h"
18 #include "duplicate_set.h"
19 #include "log.h"
20 #include "gateway_default_handler.h"
21 #include "gateway.h"
22
23 #include <assert.h>
24 #include <net/if.h>
25
26 #ifdef LINUX_NETLINK_ROUTING
27 struct avl_tree gateway_tree;
28
29 static struct olsr_cookie_info *gw_mem_cookie = NULL;
30 static uint8_t smart_gateway_netmask[sizeof(union olsr_ip_addr)];
31 static struct gateway_entry *current_ipv4_gw, *current_ipv6_gw;
32 static struct olsr_gw_handler *gw_handler;
33
34 static struct olsr_iptunnel_entry *v4gw_tunnel, *v6gw_tunnel;
35 static bool v4gw_choosen_external, v6gw_choosen_external;
36
37 /**
38  * Reconstructs an uplink/downlink speed value from the encoded
39  * 1 byte transport value (3 bit mantissa, 5 bit exponent)
40  * @param value
41  * @return
42  */
43 static uint32_t
44 deserialize_gw_speed(uint8_t value) {
45   uint32_t speed, exp;
46
47   speed = (value >> 3)+1;
48   exp = value & 7;
49   while (exp-- > 0) {
50     speed *= 10;
51   }
52   return speed;
53 }
54
55 /**
56  * Convert an uplink/downlink speed into an exponential encoded
57  * transport value (1 byte, 3 bit mantissa and 5 bit exponent)
58  * @param value uplink/downlink speed in kbit/s
59  * @return encoded byte value
60  */
61 static uint8_t
62 serialize_gw_speed(uint32_t speed) {
63   uint8_t exp = 0;
64
65   if (speed == 0 || speed > 320000000) {
66     return 0;
67   }
68
69   while (speed > 32 || (speed % 10) == 0) {
70     speed /= 10;
71     exp ++;
72   }
73   return ((speed-1) << 3) | exp;
74 }
75
76 /**
77  * Callback for tunnel interface monitoring which will set the route into the tunnel
78  * when the interface comes up again.
79  * @param if_index
80  * @param ifh
81  * @param flag
82  */
83 static void smartgw_tunnel_monitor (int if_index,
84     struct interface *ifh __attribute__ ((unused)), enum olsr_ifchg_flag flag) {
85   if (current_ipv4_gw != NULL && if_index == v4gw_tunnel->if_index && flag == IFCHG_IF_ADD) {
86     /* v4 tunnel up again, set route */
87     olsr_os_inetgw_tunnel_route(v4gw_tunnel->if_index, true, true);
88   }
89   if (current_ipv6_gw != NULL && if_index == v6gw_tunnel->if_index && flag == IFCHG_IF_ADD) {
90     /* v6 status changed, set route */
91     olsr_os_inetgw_tunnel_route(v6gw_tunnel->if_index, false, true);
92   }
93 }
94
95 /**
96  * Initialize gateway system
97  */
98 int
99 olsr_init_gateways(void) {
100   gw_mem_cookie = olsr_alloc_cookie("Gateway cookie", OLSR_COOKIE_TYPE_MEMORY);
101   olsr_cookie_set_memory_size(gw_mem_cookie, sizeof(struct gateway_entry));
102
103   avl_init(&gateway_tree, avl_comp_default);
104   current_ipv4_gw = NULL;
105   current_ipv6_gw = NULL;
106
107   v4gw_tunnel = NULL;
108   v6gw_tunnel = NULL;
109
110   refresh_smartgw_netmask();
111
112   if (olsr_os_init_iptunnel()) {
113     return 1;
114   }
115
116   olsr_add_ifchange_handler(smartgw_tunnel_monitor);
117
118   /*
119    * initialize default gateway handler,
120    * can be overwritten with olsr_set_inetgw_handler
121    */
122   olsr_gw_default_init();
123   return 0;
124 }
125
126 void refresh_smartgw_netmask(void) {
127   uint8_t *ip;
128   memset(&smart_gateway_netmask, 0, sizeof(smart_gateway_netmask));
129
130   if (olsr_cnf->smart_gw_active) {
131     union olsr_ip_addr gw_net;
132     memset(&gw_net, 0, sizeof(gw_net));
133
134     ip = (uint8_t *) &smart_gateway_netmask;
135
136     if (olsr_cnf->smart_gw_uplink > 0 || olsr_cnf->smart_gw_downlink > 0) {
137       ip[GW_HNA_FLAGS] |= GW_HNA_FLAG_LINKSPEED;
138       ip[GW_HNA_DOWNLINK] = serialize_gw_speed(olsr_cnf->smart_gw_downlink);
139       ip[GW_HNA_UPLINK] = serialize_gw_speed(olsr_cnf->smart_gw_uplink);
140     }
141     if (olsr_cnf->ip_version == AF_INET6 && olsr_cnf->smart_gw_prefix.prefix_len > 0) {
142       ip[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV6PREFIX;
143       ip[GW_HNA_V6PREFIXLEN] = olsr_cnf->smart_gw_prefix.prefix_len;
144       memcpy(&ip[GW_HNA_V6PREFIX], &olsr_cnf->smart_gw_prefix.prefix, 8);
145     }
146   }
147 }
148
149 /**
150  * Cleanup gateway tunnel system
151  */
152 void olsr_cleanup_gateways(void) {
153   if (current_ipv4_gw) {
154     olsr_os_del_ipip_tunnel(v4gw_tunnel);
155   }
156   if (current_ipv6_gw) {
157     olsr_os_del_ipip_tunnel(v6gw_tunnel);
158   }
159
160   olsr_remove_ifchange_handler(smartgw_tunnel_monitor);
161   olsr_os_cleanup_iptunnel();
162 }
163
164 /**
165  * Triggers the first lookup of an gateway. This lookup might
166  * take some time to wait for routing/gateway information.
167  */
168 void
169 olsr_trigger_inetgw_startup(void) {
170   gw_handler->handle_startup();
171 }
172
173 /**
174  * Triggers an instant gateway selection based on the current data
175  * @param ipv4 trigger a ipv4 gateway lookup
176  * @param ipv6 trigger a ipv6 gateway lookup
177  * @return 0 if successful, -1 otherwise
178  */
179 int
180 olsr_trigger_inetgw_selection(bool ipv4, bool ipv6) {
181   gw_handler->select_gateway(ipv4, ipv6);
182   return ((ipv4 && current_ipv4_gw == NULL) || (ipv6 && current_ipv6_gw == NULL)) ? -1 : 0;
183 }
184
185 /**
186  * Triggers a check if the one of the gateways have been lost
187  * through ETX = infinity
188  */
189 void olsr_trigger_gatewayloss_check(void) {
190   struct tc_entry *tc;
191   bool ipv4 = false, ipv6 = false;
192   if (current_ipv4_gw) {
193     tc = olsr_lookup_tc_entry(&current_ipv4_gw->originator);
194     if (tc == NULL || tc->path_cost == ROUTE_COST_BROKEN) {
195       ipv4 = true;
196     }
197   }
198   if (current_ipv6_gw) {
199     tc = olsr_lookup_tc_entry(&current_ipv6_gw->originator);
200     if (tc == NULL || tc->path_cost == ROUTE_COST_BROKEN) {
201       ipv6 = true;
202     }
203   }
204   if (ipv4 || ipv6) {
205     olsr_trigger_inetgw_selection(ipv4, ipv6);
206   }
207 }
208 /**
209  * Set a new gateway handler. Do only call this once during startup from
210  * a plugin to overwrite the default handler.
211  * @param h pointer to gateway handler struct
212  */
213 void
214 olsr_set_inetgw_handler(struct olsr_gw_handler *h) {
215   gw_handler = h;
216 }
217
218 /**
219  * Sets a new internet gateway.
220  * An external set command might trigger an internal one if
221  * address is not a legal gateway.
222  *
223  * @param originator ip address of the node with the new gateway
224  * @param ipv4 set ipv4 gateway
225  * @param ipv6 set ipv6 gateway
226  * @param external true if change was triggered directly by an user,
227  *   false if triggered by automatic lookup.
228  * @return true if an error happened, false otherwise
229  */
230 bool
231 olsr_set_inet_gateway(union olsr_ip_addr *originator, bool ipv4, bool ipv6, bool external) {
232   struct gateway_entry *entry, *oldV4, *oldV6;
233   struct olsr_iptunnel_entry *tunnelV4, *tunnelV6;
234
235   oldV4 = current_ipv4_gw;
236   oldV6 = current_ipv6_gw;
237   tunnelV4 = v4gw_tunnel;
238   tunnelV6 = v6gw_tunnel;
239
240   ipv4 = ipv4 && (olsr_cnf->ip_version == AF_INET || olsr_cnf->use_niit);
241   ipv6 = ipv6 && (olsr_cnf->ip_version == AF_INET6);
242
243   if (ipv4) {
244     current_ipv4_gw = NULL;
245   }
246   if (ipv6) {
247     current_ipv6_gw = NULL;
248   }
249
250   entry = olsr_find_gateway_entry(originator);
251   if (entry != NULL) {
252     if (ipv4 && entry != current_ipv4_gw && entry->ipv4
253         && (!entry->ipv4nat || olsr_cnf->smart_gw_allow_nat)) {
254       /* valid ipv4 gateway */
255       current_ipv4_gw = entry;
256     }
257     if (ipv6 && entry != current_ipv6_gw && entry->ipv6) {
258       /* valid ipv6 gateway */
259       current_ipv6_gw = entry;
260     }
261   }
262
263   /* handle IPv4 */
264   if (oldV4 != current_ipv4_gw) {
265     if ((v4gw_tunnel = olsr_os_add_ipip_tunnel(&current_ipv4_gw->originator, true)) != NULL) {
266       olsr_os_inetgw_tunnel_route(v4gw_tunnel->if_index, true, true);
267       v4gw_choosen_external = external;
268     }
269     else {
270       // TODO: what to do now ? Choose another one ? Fire up a timer ?
271       current_ipv4_gw = NULL;
272     }
273     if (oldV4 != NULL) {
274       olsr_os_del_ipip_tunnel(tunnelV4);
275     }
276   }
277   /* handle IPv6 */
278   if (oldV6 != current_ipv6_gw) {
279     if ((v6gw_tunnel = olsr_os_add_ipip_tunnel(&current_ipv6_gw->originator, false)) != NULL) {
280       olsr_os_inetgw_tunnel_route(v6gw_tunnel->if_index, false, true);
281       v6gw_choosen_external = external;
282     }
283     else {
284       // TODO: what to do now ? Choose another one ? Fire up a timer ?
285       current_ipv6_gw = NULL;
286     }
287     if (oldV6 != NULL) {
288       olsr_os_del_ipip_tunnel(tunnelV6);
289     }
290   }
291   return (ipv4 && current_ipv4_gw == NULL) || (ipv6 && current_ipv6_gw == NULL);
292 }
293
294 /**
295  * returns the gateway_entry of the current ipv4 internet gw.
296  * @return pointer to gateway_entry or NULL if not set
297  */
298 struct gateway_entry *olsr_get_ipv4_inet_gateway(bool *ext) {
299   if (ext) {
300     *ext = v4gw_choosen_external;
301   }
302   return current_ipv4_gw;
303 }
304
305 /**
306  * returns the gateway_entry of the current ipv6 internet gw.
307  * @return pointer to gateway_entry or NULL if not set
308  */
309 struct gateway_entry *olsr_get_ipv6_inet_gateway(bool *ext) {
310   if (ext) {
311     *ext = v6gw_choosen_external;
312   }
313   return current_ipv6_gw;
314 }
315
316 /**
317  * @param originator
318  * @return gateway_entry for corresponding router
319  */
320 struct gateway_entry *
321 olsr_find_gateway_entry(union olsr_ip_addr *originator) {
322   struct avl_node *node = avl_find(&gateway_tree, originator);
323
324   return node == NULL ? NULL : node2gateway(node);
325 }
326
327 /**
328  * update a gateway_entry based on data received from a HNA
329  * @param originator ip of the source of the HNA
330  * @param mask netmask of the HNA
331  * @param prefixlen of the HNA
332  */
333 void
334 olsr_update_gateway_entry(union olsr_ip_addr *originator, union olsr_ip_addr *mask, int prefixlen, uint16_t seqno) {
335   struct gateway_entry *gw;
336   uint8_t *ptr;
337
338   ptr = ((uint8_t *)mask) + ((prefixlen+7)/8);
339
340   gw = olsr_find_gateway_entry(originator);
341   if (!gw) {
342     struct ipaddr_str buf;
343     gw = olsr_cookie_malloc(gw_mem_cookie);
344
345     gw->originator = *originator;
346     gw->node.key = &gw->originator;
347
348     avl_insert(&gateway_tree, &gw->node, AVL_DUP_NO);
349   }
350   else if (olsr_seqno_diff(seqno, gw->seqno) <= 0) {
351     /* ignore older HNAs */
352     return;
353   }
354
355   /* keep new HNA seqno */
356   gw->seqno = seqno;
357
358   if ((ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_LINKSPEED) != 0) {
359     gw->uplink = deserialize_gw_speed(ptr[GW_HNA_UPLINK]);
360     gw->downlink = deserialize_gw_speed(ptr[GW_HNA_DOWNLINK]);
361   }
362   else {
363     gw->uplink = 1;
364     gw->downlink = 1;
365   }
366
367   gw->ipv4 = (ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV4) != 0;
368   gw->ipv4nat = (ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV4_NAT) != 0;
369
370   if (olsr_cnf->ip_version == AF_INET6) {
371     gw->ipv6 = (ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV6) != 0;
372
373     /* do not reset prefixlength for ::ffff:0:0 HNAs */
374     if (prefixlen == ipv6_internet_route.prefix_len) {
375       memset(&gw->external_prefix, 0, sizeof(gw->external_prefix));
376
377       if ((ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV6PREFIX) != 0
378           && memcmp(mask->v6.s6_addr, &ipv6_internet_route.prefix, olsr_cnf->ipsize) == 0) {
379         /* this is the right prefix (2000::/3), so we can copy the prefix */
380         gw->external_prefix.prefix_len = ptr[GW_HNA_V6PREFIXLEN];
381         memcpy(&gw->external_prefix.prefix, &ptr[GW_HNA_V6PREFIX], 8);
382       }
383     }
384   }
385
386   /* stop cleanup timer if necessary */
387   if (gw->cleanup_timer) {
388     olsr_stop_timer(gw->cleanup_timer);
389     gw->cleanup_timer = NULL;
390   }
391
392   /* call update handler */
393   gw_handler->handle_update_gw(gw);
394 }
395
396 static void cleanup_gateway_handler(void *ptr) {
397   struct gateway_entry *gw = ptr;
398
399   if (gw->ipv4 || gw->ipv6) {
400     return;
401   }
402
403   /* remove gateway entry */
404   avl_delete(&gateway_tree, &gw->node);
405   olsr_cookie_free(gw_mem_cookie, gw);
406 }
407
408 /**
409  * Delete a gateway based on the originator IP and the prefixlength of a HNA.
410  * Should only be called if prefix is a smart_gw prefix or if node is removed
411  * from TC set.
412  * @param originator
413  * @param prefixlen
414  */
415 void
416 olsr_delete_gateway_entry(union olsr_ip_addr *originator, uint8_t prefixlen) {
417   struct gateway_entry *gw;
418   bool change = false;
419   gw = olsr_find_gateway_entry(originator);
420   if (gw && (gw->cleanup_timer == NULL || gw->ipv4 || gw->ipv6)) {
421     if (olsr_cnf->ip_version == AF_INET && prefixlen == 0) {
422       change = gw->ipv4;
423       gw->ipv4 = false;
424       gw->ipv4nat = false;
425     }
426     else if (olsr_cnf->ip_version == AF_INET6 && prefixlen == ipv6_internet_route.prefix_len) {
427       change = gw->ipv6;
428       gw->ipv6 = false;
429     }
430     else if (olsr_cnf->ip_version == AF_INET6 && prefixlen == ipv6_mappedv4_route.prefix_len) {
431       change = gw->ipv4;
432       gw->ipv4 = false;
433       gw->ipv4nat = false;
434     }
435
436     if (prefixlen == FORCE_DELETE_GW_ENTRY || !(gw->ipv4 || gw->ipv6)) {
437       /* prevent this gateway from being choosen as the new gateway */
438       gw->ipv4 = false;
439       gw->ipv4nat = false;
440       gw->ipv6 = false;
441
442       /* handle gateway loss */
443       gw_handler->handle_delete_gw(gw);
444
445       /* cleanup gateway if necessary */
446       if (current_ipv4_gw == gw) {
447         olsr_os_inetgw_tunnel_route(v4gw_tunnel->if_index, true, false);
448         olsr_os_del_ipip_tunnel(v4gw_tunnel);
449
450         current_ipv4_gw = NULL;
451         v4gw_tunnel = NULL;
452       }
453       if (current_ipv6_gw == gw) {
454         olsr_os_inetgw_tunnel_route(v6gw_tunnel->if_index, false, false);
455         olsr_os_del_ipip_tunnel(v6gw_tunnel);
456
457         current_ipv6_gw = NULL;
458         v6gw_tunnel = NULL;
459       }
460
461       /* remove gateway entry */
462       olsr_set_timer(&gw->cleanup_timer, GW_CLEANUP_INTERVAL, 0, false, cleanup_gateway_handler, gw, NULL);
463     }
464     else if (change) {
465       gw_handler->handle_update_gw(gw);
466     }
467   }
468 }
469
470 /**
471  * Checks if a prefix/netmask combination is a smart gateway
472  * @param prefix
473  * @param mask
474  * @return true if is a valid smart gateway HNA, false otherwise
475  */
476 bool
477 olsr_is_smart_gateway(struct olsr_ip_prefix *prefix, union olsr_ip_addr *mask) {
478   uint8_t *ptr;
479
480   if (!is_prefix_inetgw(prefix)) {
481     return false;
482   }
483
484   ptr = ((uint8_t *)mask) + ((prefix->prefix_len+7)/8);
485   return ptr[GW_HNA_PAD] == 0 && ptr[GW_HNA_FLAGS] != 0;
486 }
487
488 /**
489  * Apply the smart gateway modifications to an outgoing HNA
490  * @param mask pointer to netmask of the HNA
491  * @param prefixlen of the HNA
492  */
493 void
494 olsr_modifiy_inetgw_netmask(union olsr_ip_addr *mask, int prefixlen) {
495   uint8_t *ptr = ((uint8_t *)mask) + ((prefixlen+7)/8);
496
497   memcpy(ptr, &smart_gateway_netmask, sizeof(smart_gateway_netmask) - prefixlen/8);
498   if (olsr_cnf->has_ipv4_gateway) {
499     ptr[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV4;
500
501     if (olsr_cnf->smart_gw_uplink_nat) {
502       ptr[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV4_NAT;
503     }
504   }
505   if (olsr_cnf->has_ipv6_gateway) {
506     ptr[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV6;
507   }
508   if (!olsr_cnf->has_ipv6_gateway || prefixlen != ipv6_internet_route.prefix_len){
509     ptr[GW_HNA_FLAGS] &= ~GW_HNA_FLAG_IPV6PREFIX;
510   }
511 }
512
513 /**
514  * Print debug information about gateway entries
515  */
516 void
517 olsr_print_gateway_entries(void) {
518 #ifndef NODEBUG
519   struct ipaddr_str buf;
520   struct gateway_entry *gw;
521   const int addrsize = olsr_cnf->ip_version == AF_INET ? 15 : 39;
522
523   OLSR_PRINTF(0, "\n--- %s ---------------------------------------------------- GATEWAYS\n\n",
524       olsr_wallclock_string());
525   OLSR_PRINTF(0, "%-*s %-6s %-9s %-9s %s\n", addrsize, "IP address", "Type", "Uplink", "Downlink",
526       olsr_cnf->ip_version == AF_INET ? "" : "External Prefix");
527
528   OLSR_FOR_ALL_GATEWAY_ENTRIES(gw) {
529     OLSR_PRINTF(0, "%-*s %s%c%s%c%c %-9u %-9u %s\n", addrsize, olsr_ip_to_string(&buf, &gw->originator),
530         gw->ipv4nat ? "" : "   ",
531         gw->ipv4 ? '4' : ' ',
532         gw->ipv4nat ? "(N)" : "",
533         (gw->ipv4 && gw->ipv6) ? ',' : ' ',
534         gw->ipv6 ? '6' : ' ',
535         gw->uplink, gw->downlink,
536         gw->external_prefix.prefix_len == 0 ? "" : olsr_ip_prefix_to_string(&gw->external_prefix));
537   } OLSR_FOR_ALL_GATEWAY_ENTRIES_END(gw)
538 #endif
539 }
540
541 #endif /* !WIN32 */