346cd801271b7b4c0f0876a5318460602863b946
[olsrd.git] / src / gateway.c
1 /*
2  * gateway.c
3  *
4  *  Created on: 05.01.2010
5  *      Author: henning
6  */
7
8 #ifdef __linux__
9
10 #include "common/avl.h"
11 #include "defs.h"
12 #include "ipcalc.h"
13 #include "olsr.h"
14 #include "olsr_cfg.h"
15 #include "olsr_cookie.h"
16 #include "scheduler.h"
17 #include "kernel_routes.h"
18 #include "kernel_tunnel.h"
19 #include "net_os.h"
20 #include "duplicate_set.h"
21 #include "log.h"
22 #include "gateway_default_handler.h"
23 #include "gateway_list.h"
24 #include "gateway.h"
25 #include "egressTypes.h"
26 #include "egressFile.h"
27
28 #include <assert.h>
29 #include <net/if.h>
30 #include <linux/rtnetlink.h>
31
32 /*
33  * Defines for the multi-gateway script
34  */
35
36 #define SCRIPT_MODE_GENERIC   "generic"
37 #define SCRIPT_MODE_OLSRIF    "olsrif"
38 #define SCRIPT_MODE_SGWSRVTUN "sgwsrvtun"
39 #define SCRIPT_MODE_EGRESSIF  "egressif"
40 #define SCRIPT_MODE_SGWTUN    "sgwtun"
41
42 /* ipv4 prefix 0.0.0.0/0 */
43 static struct olsr_ip_prefix ipv4_slash_0_route;
44
45 /* ipv4 prefixes 0.0.0.0/1 and 128.0.0.0/1 */
46 static struct olsr_ip_prefix ipv4_slash_1_routes[2];
47
48 /** structure that holds an interface name, mark and a pointer to the gateway that uses it */
49 struct interfaceName {
50   char name[IFNAMSIZ]; /**< interface name */
51   uint8_t tableNr; /**< routing table number */
52   uint8_t ruleNr; /**< IP rule number */
53   uint8_t bypassRuleNr; /**< bypass IP rule number */
54   struct gateway_entry *gw; /**< gateway that uses this interface name */
55 };
56
57 /** the gateway tree */
58 struct avl_tree gateway_tree;
59
60 /** gateway cookie */
61 static struct olsr_cookie_info *gateway_entry_mem_cookie = NULL;
62
63 /** gateway container cookie */
64 static struct olsr_cookie_info *gw_container_entry_mem_cookie = NULL;
65
66 /** the gateway netmask for the HNA */
67 static uint8_t smart_gateway_netmask[sizeof(union olsr_ip_addr)];
68
69 /** the gateway handler/plugin */
70 static struct olsr_gw_handler *gw_handler;
71
72 /** the IPv4 gateway list */
73 struct gw_list gw_list_ipv4;
74
75 /** the IPv6 gateway list */
76 struct gw_list gw_list_ipv6;
77
78 /** the current IPv4 gateway */
79 static struct gw_container_entry *current_ipv4_gw;
80
81 /** the current IPv6 gateway */
82 static struct gw_container_entry *current_ipv6_gw;
83
84 /** interface names for smart gateway tunnel interfaces, IPv4 */
85 struct interfaceName * sgwTunnel4InterfaceNames;
86
87 /** interface names for smart gateway tunnel interfaces, IPv6 */
88 struct interfaceName * sgwTunnel6InterfaceNames;
89
90 /** the timer for proactive takedown */
91 static struct timer_entry *gw_takedown_timer;
92
93 struct BestOverallLink {
94   bool valid;
95   bool isOlsr;
96   union {
97     struct sgw_egress_if * egress;
98     struct gateway_entry * olsr;
99   } link;
100   int olsrTunnelIfIndex;
101 };
102
103 static struct sgw_egress_if * bestEgressLinkPrevious = NULL;
104 static struct sgw_egress_if * bestEgressLink = NULL;
105
106 struct sgw_route_info bestEgressLinkPreviousRoute = {0};
107 struct sgw_route_info bestEgressLinkRoute = {0};
108
109 struct sgw_route_info bestOverallLinkPreviousRoutes[2] = {{0}};
110 struct sgw_route_info bestOverallLinkRoutes[2] = {{0}};
111
112 static struct BestOverallLink bestOverallLinkPrevious;
113 static struct BestOverallLink bestOverallLink;
114
115 /*
116  * Forward Declarations
117  */
118
119 static void olsr_delete_gateway_tree_entry(struct gateway_entry * gw, uint8_t prefixlen, bool immediate);
120
121 /*
122  * Helper Functions
123  */
124
125 /**
126  * @return the gateway 'server' tunnel name to use
127  */
128 static inline const char * server_tunnel_name(void) {
129   return (olsr_cnf->ip_version == AF_INET ? TUNNEL_ENDPOINT_IF : TUNNEL_ENDPOINT_IF6);
130 }
131
132 /**
133  * Convert the netmask of the HNA (in the form of an IP address) to a HNA
134  * pointer.
135  *
136  * @param mask the netmask of the HNA (in the form of an IP address)
137  * @param prefixlen the prefix length
138  * @return a pointer to the HNA
139  */
140 static inline uint8_t * hna_mask_to_hna_pointer(union olsr_ip_addr *mask, int prefixlen) {
141   return (((uint8_t *)mask) + ((prefixlen+7)/8));
142 }
143
144 /**
145  * Convert an encoded 1 byte transport value (5 bits mantissa, 3 bits exponent)
146  * to an uplink/downlink speed value
147  *
148  * @param value the encoded 1 byte transport value
149  * @return the uplink/downlink speed value (in kbit/s)
150  */
151 static uint32_t deserialize_gw_speed(uint8_t value) {
152   uint32_t speed;
153   uint32_t exp;
154
155   if (!value) {
156     /* 0 and 1 alias onto 0 during serialisation. We take 0 here to mean 0 and
157      * not 1 (since a bandwidth of 1 is no bandwidth at all really) */
158     return 0;
159   }
160
161   if (value == UINT8_MAX) {
162     /* maximum value: also return maximum value */
163     return 320000000;
164   }
165
166   speed = (value >> 3) + 1;
167   exp = value & 7;
168
169   while (exp-- > 0) {
170     speed *= 10;
171   }
172   return speed;
173 }
174
175 /**
176  * Convert an uplink/downlink speed value into an encoded 1 byte transport
177  * value (5 bits mantissa, 3 bits exponent)
178  *
179  * @param speed the uplink/downlink speed value (in kbit/s)
180  * @return value the encoded 1 byte transport value
181  */
182 static uint8_t serialize_gw_speed(uint32_t speed) {
183   uint8_t exp = 0;
184
185   if (speed == 0) {
186     return 0;
187   }
188
189   if (speed > 320000000) {
190     return UINT8_MAX;
191   }
192
193   while ((speed > 32 || (speed % 10) == 0) && exp < 7) {
194     speed /= 10;
195     exp++;
196   }
197   return ((speed - 1) << 3) | exp;
198 }
199
200 /**
201  * Find an interfaceName struct corresponding to a certain gateway
202  * (when gw != NULL) or to an empty interfaceName struct (when gw == NULL).
203  *
204  * @param gw the gateway to find (when not NULL), or the empty struct to find (when NULL)
205  * @return a pointer to the struct, or NULL when not found
206  */
207 static struct interfaceName * find_interfaceName(struct gateway_entry *gw) {
208   struct interfaceName * sgwTunnelInterfaceNames;
209   uint8_t i = 0;
210
211   if (!multi_gateway_mode()) {
212     return NULL;
213   }
214
215   assert(sgwTunnel4InterfaceNames);
216   assert(sgwTunnel6InterfaceNames);
217
218   sgwTunnelInterfaceNames = (olsr_cnf->ip_version == AF_INET) ? sgwTunnel4InterfaceNames : sgwTunnel6InterfaceNames;
219   while (i < olsr_cnf->smart_gw_use_count) {
220     struct interfaceName * ifn = &sgwTunnelInterfaceNames[i];
221     if (ifn->gw == gw) {
222       return ifn;
223     }
224     i++;
225   }
226
227   return NULL;
228 }
229
230 /**
231  * Get an unused olsr ipip tunnel name for a certain gateway and store it in name.
232  *
233  * @param gw pointer to the gateway
234  * @param name pointer to output buffer (length IFNAMSIZ)
235  * @param interfaceName a pointer to the location where to store a pointer to the interfaceName struct
236  */
237 static void get_unused_iptunnel_name(struct gateway_entry *gw, char * name, struct interfaceName ** interfaceName) {
238   static uint32_t counter = 0;
239
240   assert(gw);
241   assert(name);
242   assert(interfaceName);
243
244   memset(name, 0, IFNAMSIZ);
245
246   if (multi_gateway_mode()) {
247     struct interfaceName * ifn = find_interfaceName(NULL);
248
249     if (ifn) {
250       strncpy(&name[0], &ifn->name[0], sizeof(ifn->name));
251       *interfaceName = ifn;
252       ifn->gw = gw;
253       return;
254     }
255
256     /* do not return, fall-through to classic naming as fallback */
257   }
258
259   snprintf(name, IFNAMSIZ, "tnl_%08x", (olsr_cnf->ip_version == AF_INET) ? gw->originator.v4.s_addr : ++counter);
260   *interfaceName = NULL;
261 }
262
263 /**
264  * Set an olsr ipip tunnel name that is used by a certain gateway as unused
265  *
266  * @param gw pointer to the gateway
267  */
268 static void set_unused_iptunnel_name(struct gateway_entry *gw) {
269   struct interfaceName * ifn;
270
271   if (!multi_gateway_mode()) {
272     return;
273   }
274
275   assert(gw);
276
277   ifn = find_interfaceName(gw);
278   if (ifn) {
279     ifn->gw = NULL;
280     return;
281   }
282 }
283
284 /**
285  * Run the multi-gateway script/
286  *
287  * @param mode the mode (see SCRIPT_MODE_* defines)
288  * @param addMode true to add policy routing, false to remove it
289  * @param ifname the interface name (optional)
290  * @param tableNr the routing table number (optional)
291  * @param ruleNr the IP rule number/priority (optional)
292  * @param bypassRuleNr the bypass IP rule number/priority (optional)
293  * @return true when successful
294  */
295 static bool multiGwRunScript(const char * mode, bool addMode, const char * ifName, uint32_t tableNr, uint32_t ruleNr, uint32_t bypassRuleNr) {
296   struct autobuf buf;
297   int r;
298
299   assert(!strcmp(mode, SCRIPT_MODE_GENERIC) //
300       || !strcmp(mode, SCRIPT_MODE_OLSRIF)//
301       || !strcmp(mode, SCRIPT_MODE_SGWSRVTUN)//
302       || !strcmp(mode, SCRIPT_MODE_EGRESSIF)//
303       || !strcmp(mode, SCRIPT_MODE_SGWTUN)//
304       );
305
306   assert(strcmp(mode, SCRIPT_MODE_GENERIC) //
307       || (!strcmp(mode, SCRIPT_MODE_GENERIC) && !ifName && !tableNr && !ruleNr && !bypassRuleNr));
308
309   assert(strcmp(mode, SCRIPT_MODE_OLSRIF) //
310       || (!strcmp(mode, SCRIPT_MODE_OLSRIF) && ifName && !tableNr && !ruleNr && bypassRuleNr));
311
312   assert(strcmp(mode, SCRIPT_MODE_SGWSRVTUN) //
313       || (!strcmp(mode, SCRIPT_MODE_SGWSRVTUN) && ifName && tableNr&& ruleNr && !bypassRuleNr));
314
315   assert(strcmp(mode, SCRIPT_MODE_EGRESSIF) //
316       || (!strcmp(mode, SCRIPT_MODE_EGRESSIF) && ifName && tableNr && ruleNr && bypassRuleNr));
317
318   assert(strcmp(mode, SCRIPT_MODE_SGWTUN) //
319       || (!strcmp(mode, SCRIPT_MODE_SGWTUN) && ifName && tableNr && ruleNr && !bypassRuleNr));
320
321   abuf_init(&buf, 1024);
322
323   abuf_appendf(&buf, "\"%s\"", olsr_cnf->smart_gw_policyrouting_script);
324
325   abuf_appendf(&buf, " \"%s\"", (olsr_cnf->ip_version == AF_INET) ? "ipv4" : "ipv6");
326
327   abuf_appendf(&buf, " \"%s\"", mode);
328
329   abuf_appendf(&buf, " \"%s\"", addMode ? "add" : "del");
330
331   if (ifName) {
332     abuf_appendf(&buf, " \"%s\"", ifName);
333   }
334
335   if (tableNr) {
336     abuf_appendf(&buf, " \"%u\"", tableNr);
337   }
338
339   if (ruleNr) {
340     abuf_appendf(&buf, " \"%u\"", ruleNr);
341   }
342
343   if (bypassRuleNr) {
344     abuf_appendf(&buf, " \"%u\"", bypassRuleNr);
345   }
346
347   r = system(buf.buf);
348
349   abuf_free(&buf);
350
351   return (r == 0);
352 }
353
354 /**
355  * Setup generic multi-gateway iptables and ip rules
356  *
357  * @param add true to add policy routing, false to remove it
358  * @return true when successful
359  */
360 static bool multiGwRulesGeneric(bool add) {
361   return multiGwRunScript(SCRIPT_MODE_GENERIC, add, NULL, 0, 0, 0);
362 }
363
364 /**
365  * Setup multi-gateway iptables and ip rules for all OLSR interfaces.
366  *
367  * @param add true to add policy routing, false to remove it
368  * @return true when successful
369  */
370 static bool multiGwRulesOlsrInterfaces(bool add) {
371   bool ok = true;
372   struct olsr_if * ifn;
373   unsigned int i = 0;
374
375   for (ifn = olsr_cnf->interfaces; ifn; ifn = ifn->next, i++) {
376     if (!multiGwRunScript( //
377         SCRIPT_MODE_OLSRIF,//
378         add, //
379         ifn->name, //
380         0, //
381         0, //
382         olsr_cnf->smart_gw_offset_rules + olsr_cnf->smart_gw_egress_interfaces_count + i //
383             )) {
384       ok = false;
385       if (add) {
386         return ok;
387       }
388     }
389   }
390
391   return ok;
392 }
393
394 /**
395  * Setup multi-gateway iptables and ip rules for the smart gateway server tunnel.
396  *
397  * @param add true to add policy routing, false to remove it
398  * @return true when successful
399  */
400 static bool multiGwRulesSgwServerTunnel(bool add) {
401   return multiGwRunScript( //
402       SCRIPT_MODE_SGWSRVTUN,//
403       add, //
404       server_tunnel_name(), //
405       olsr_cnf->smart_gw_offset_tables, //
406       olsr_cnf->smart_gw_offset_rules + olsr_cnf->smart_gw_egress_interfaces_count + getNrOfOlsrInterfaces(olsr_cnf), //
407       0 //
408       );
409 }
410
411 /**
412  * Setup multi-gateway iptables and ip rules for all egress interfaces.
413  *
414  * @param add true to add policy routing, false to remove it
415  * @return true when successful
416  */
417 static bool multiGwRulesEgressInterfaces(bool add) {
418   bool ok = true;
419   unsigned int i = 0;
420
421   struct sgw_egress_if * egress_if = olsr_cnf->smart_gw_egress_interfaces;
422   while (egress_if) {
423     if (!multiGwRunScript(SCRIPT_MODE_EGRESSIF, add, egress_if->name, egress_if->tableNr, egress_if->ruleNr, egress_if->bypassRuleNr)) {
424       ok = false;
425       if (add) {
426         return ok;
427       }
428     }
429
430     egress_if = egress_if->next;
431   }
432
433   return ok;
434 }
435
436 /**
437  * Setup multi-gateway iptables and ip rules for the smart gateway client tunnels.
438  *
439  * @param add true to add policy routing, false to remove it
440  * @return true when successful
441  */
442 static bool multiGwRulesSgwTunnels(bool add) {
443   bool ok = true;
444   unsigned int i = 0;
445
446   while (i < olsr_cnf->smart_gw_use_count) {
447     struct interfaceName * ifn = (olsr_cnf->ip_version == AF_INET) ? &sgwTunnel4InterfaceNames[i] : &sgwTunnel6InterfaceNames[i];
448     if (!multiGwRunScript(SCRIPT_MODE_SGWTUN, add, ifn->name, ifn->tableNr, ifn->ruleNr, ifn->bypassRuleNr)) {
449       ok = false;
450       if (add) {
451         return ok;
452       }
453     }
454
455     i++;
456   }
457
458   return ok;
459 }
460
461 /**
462  * Process interface up/down events for non-olsr interfaces, which are egress
463  * interfaces
464  *
465  * @param if_index the index of the interface
466  * @param flag the up/down event
467  */
468 static void doEgressInterface(int if_index, enum olsr_ifchg_flag flag) {
469   switch (flag) {
470     case IFCHG_IF_ADD: {
471       char ifname[IF_NAMESIZE];
472       struct sgw_egress_if * egress_if;
473
474       /*
475        * we need to get the name of the interface first because the interface
476        * might be hot-plugged _after_ olsrd has started
477        */
478       if (!if_indextoname(if_index, ifname)) {
479         /* not a known OS interface */
480         return;
481       }
482
483       egress_if = findEgressInterface(ifname);
484       if (!egress_if) {
485         /* not a known egress interface */
486         return;
487       }
488
489       egress_if->if_index = if_index;
490
491       if (egress_if->upCurrent) {
492         /* interface is already up: no change */
493         return;
494       }
495
496       egress_if->upPrevious = egress_if->upCurrent;
497       egress_if->upCurrent = true;
498       egress_if->upChanged = true;
499
500       egress_if->bwCostsChanged = egressBwCalculateCosts(&egress_if->bwCurrent, egress_if->upCurrent);
501     }
502       break;
503
504     case IFCHG_IF_REMOVE: {
505       /*
506        * we need to find the egress interface by if_index because we might
507        * be too late; the kernel could already have removed the interface
508        * in which case we'd get a NULL ifname here if we'd try to call
509        * if_indextoname
510        */
511       struct sgw_egress_if * egress_if = findEgressInterfaceByIndex(if_index);
512       if (!egress_if) {
513         /* not a known egress interface */
514         return;
515       }
516
517       if (!egress_if->upCurrent) {
518         /* interface is already down: no change */
519         return;
520       }
521
522       egress_if->upPrevious = egress_if->upCurrent;
523       egress_if->upCurrent = false;
524       egress_if->upChanged = true;
525
526       egress_if->bwCostsChanged = egressBwCalculateCosts(&egress_if->bwCurrent, egress_if->upCurrent);
527     }
528       break;
529
530     case IFCHG_IF_UPDATE:
531     default:
532       return;
533   }
534
535   doRoutesMultiGw(true, false, GW_MULTI_CHANGE_PHASE_RUNTIME);
536 }
537
538 /*
539  * Callback Functions
540  */
541
542 /**
543  * Callback for tunnel interface monitoring which will set the route into the tunnel
544  * when the interface comes up again.
545  *
546  * @param if_index the interface index
547  * @param ifh the interface (NULL when not an olsr interface)
548  * @param flag interface change flags
549  */
550 static void smartgw_tunnel_monitor(int if_index, struct interface *ifh, enum olsr_ifchg_flag flag) {
551   if (!ifh && multi_gateway_mode()) {
552     /* non-olsr interface in multi-sgw mode */
553     doEgressInterface(if_index, flag);
554   }
555
556   return;
557 }
558
559 /**
560  * Timer callback to remove and cleanup a gateway entry
561  *
562  * @param ptr
563  */
564 static void cleanup_gateway_handler(void *ptr) {
565   struct gateway_entry *gw = ptr;
566
567   if (gw->ipv4 || gw->ipv6) {
568     /* do not clean it up when it is in use */
569     return;
570   }
571
572   /* remove gateway entry */
573   avl_delete(&gateway_tree, &gw->node);
574   olsr_cookie_free(gateway_entry_mem_cookie, gw);
575 }
576
577 /**
578  * Remove a gateway from a gateway list.
579  *
580  * @param gw_list a pointer to the gateway list
581  * @param ipv4 true when dealing with an IPv4 gateway / gateway list
582  * @param gw a pointer to the gateway to remove from the list
583  */
584 static void removeGatewayFromList(struct gw_list * gw_list, bool ipv4, struct gw_container_entry * gw) {
585   if (gw->tunnel) {
586     struct interfaceName * ifn = find_interfaceName(gw->gw);
587     if (ifn) {
588       olsr_os_inetgw_tunnel_route(gw->tunnel->if_index, ipv4, false, ifn->tableNr);
589     }
590     olsr_os_del_ipip_tunnel(gw->tunnel);
591     set_unused_iptunnel_name(gw->gw);
592     gw->tunnel = NULL;
593   }
594   gw->gw = NULL;
595   olsr_cookie_free(gw_container_entry_mem_cookie, olsr_gw_list_remove(gw_list, gw));
596 }
597
598 /**
599  * Remove expensive gateways from the gateway list.
600  * It uses the smart_gw_takedown_percentage configuration parameter
601  *
602  * @param gw_list a pointer to the gateway list
603  * @param ipv4 true when dealing with an IPv4 gateway / gateway list
604  * @param current_gw the current gateway
605  */
606 static void takeDownExpensiveGateways(struct gw_list * gw_list, bool ipv4, struct gw_container_entry * current_gw) {
607   int64_t current_gw_cost_boundary;
608
609   /*
610    * exit immediately when takedown is disabled, there is no current gateway, or
611    * when there is only a single gateway
612    */
613   if ((olsr_cnf->smart_gw_takedown_percentage == 0) || (current_gw == NULL ) || (gw_list->count <= 1)) {
614     return;
615   }
616
617   /* get the cost boundary */
618   current_gw_cost_boundary = current_gw->gw->path_cost;
619   if (olsr_cnf->smart_gw_takedown_percentage < 100) {
620     if (current_gw_cost_boundary <= (INT64_MAX / 100)) {
621       current_gw_cost_boundary =  ((current_gw_cost_boundary * 100) / olsr_cnf->smart_gw_takedown_percentage);
622     } else {
623       /* perform scaling because otherwise the percentage calculation can overflow */
624       current_gw_cost_boundary = (((current_gw_cost_boundary      ) / olsr_cnf->smart_gw_takedown_percentage) * 100) + 99;
625     }
626   }
627
628   /* loop while we still have gateways */
629   while (gw_list->count > 1) {
630     /* get the worst gateway */
631     struct gw_container_entry * worst_gw = olsr_gw_list_get_worst_entry(gw_list);
632
633     /* exit when it's the current gateway */
634     if (worst_gw == current_gw) {
635       return;
636     }
637
638     /*
639      * exit when it (and further ones; the list is sorted on costs) has lower
640      * costs than the boundary costs
641      */
642     if (worst_gw->gw->path_cost < current_gw_cost_boundary) {
643       return;
644     }
645
646     /* it's too expensive: take it down */
647     removeGatewayFromList(gw_list, ipv4, worst_gw);
648   }
649 }
650
651 /**
652  * Timer callback for proactive gateway takedown
653  *
654  * @param unused unused
655  */
656 static void gw_takedown_timer_callback(void *unused __attribute__ ((unused))) {
657   takeDownExpensiveGateways(&gw_list_ipv4, true, current_ipv4_gw);
658   takeDownExpensiveGateways(&gw_list_ipv6, false, current_ipv6_gw);
659 }
660
661 /*
662  * Main Interface
663  */
664
665 /**
666  * Initialize gateway system
667  */
668 int olsr_init_gateways(void) {
669   int retries = 5;
670
671   /* ipv4 prefix 0.0.0.0/0 */
672   memset(&ipv4_slash_0_route, 0, sizeof(ipv4_slash_0_route));
673
674   /* ipv4 prefixes 0.0.0.0/1 and 128.0.0.0/1 */
675   memset(&ipv4_slash_1_routes, 0, sizeof(ipv4_slash_1_routes));
676   ipv4_slash_1_routes[0].prefix.v4.s_addr = htonl(0x00000000);
677   ipv4_slash_1_routes[0].prefix_len = 1;
678   ipv4_slash_1_routes[1].prefix.v4.s_addr = htonl(0x80000000);
679   ipv4_slash_1_routes[1].prefix_len = 1;
680
681   gateway_entry_mem_cookie = olsr_alloc_cookie("gateway_entry_mem_cookie", OLSR_COOKIE_TYPE_MEMORY);
682   olsr_cookie_set_memory_size(gateway_entry_mem_cookie, sizeof(struct gateway_entry));
683
684   gw_container_entry_mem_cookie = olsr_alloc_cookie("gw_container_entry_mem_cookie", OLSR_COOKIE_TYPE_MEMORY);
685   olsr_cookie_set_memory_size(gw_container_entry_mem_cookie, sizeof(struct gw_container_entry));
686
687   avl_init(&gateway_tree, avl_comp_default);
688
689   olsr_gw_list_init(&gw_list_ipv4, olsr_cnf->smart_gw_use_count);
690   olsr_gw_list_init(&gw_list_ipv6, olsr_cnf->smart_gw_use_count);
691
692   sgwTunnel4InterfaceNames = NULL;
693   sgwTunnel6InterfaceNames = NULL;
694   memset(&bestOverallLinkPrevious, 0, sizeof(bestOverallLinkPrevious));
695   memset(&bestOverallLink, 0, sizeof(bestOverallLink));
696
697   if (multi_gateway_mode()) {
698     uint8_t i;
699     struct sgw_egress_if * egressif;
700     unsigned int nrOlsrIfs = getNrOfOlsrInterfaces(olsr_cnf);
701
702     /* setup the egress interface name/mark pairs */
703     i = 0;
704     egressif = olsr_cnf->smart_gw_egress_interfaces;
705     while (egressif) {
706       egressif->tableNr = olsr_cnf->smart_gw_offset_tables + 1 + i;
707       egressif->ruleNr = olsr_cnf->smart_gw_offset_rules + olsr_cnf->smart_gw_egress_interfaces_count + nrOlsrIfs + 1 + i;
708       egressif->bypassRuleNr = olsr_cnf->smart_gw_offset_rules + i;
709
710       egressif = egressif->next;
711       i++;
712     }
713     assert(i == olsr_cnf->smart_gw_egress_interfaces_count);
714
715     /* setup the SGW tunnel name/mark pairs */
716     sgwTunnel4InterfaceNames = olsr_malloc(sizeof(struct interfaceName) * olsr_cnf->smart_gw_use_count, "sgwTunnel4InterfaceNames");
717     sgwTunnel6InterfaceNames = olsr_malloc(sizeof(struct interfaceName) * olsr_cnf->smart_gw_use_count, "sgwTunnel6InterfaceNames");
718     for (i = 0; i < olsr_cnf->smart_gw_use_count; i++) {
719       struct interfaceName * ifn = &sgwTunnel4InterfaceNames[i];
720       uint32_t tableNr = olsr_cnf->smart_gw_offset_tables + 1 + olsr_cnf->smart_gw_egress_interfaces_count + i;
721       uint32_t ruleNr = olsr_cnf->smart_gw_offset_rules + olsr_cnf->smart_gw_egress_interfaces_count + nrOlsrIfs + 1 + olsr_cnf->smart_gw_egress_interfaces_count + i;
722
723       ifn->gw = NULL;
724       ifn->tableNr = tableNr;
725       ifn->ruleNr = ruleNr;
726       ifn->bypassRuleNr = 0;
727       snprintf(&ifn->name[0], sizeof(ifn->name), "tnl_4%03u", ifn->tableNr);
728
729       ifn = &sgwTunnel6InterfaceNames[i];
730       ifn->gw = NULL;
731       ifn->tableNr = tableNr;
732       ifn->ruleNr = ruleNr;
733       ifn->bypassRuleNr = 0;
734       snprintf(&ifn->name[0], sizeof(ifn->name), "tnl_6%03u", ifn->tableNr);
735     }
736   }
737
738   current_ipv4_gw = NULL;
739   current_ipv6_gw = NULL;
740
741   gw_handler = NULL;
742
743   refresh_smartgw_netmask();
744
745   /* initialize default gateway handler */
746   gw_handler = &gw_def_handler;
747   gw_handler->init();
748
749
750   /*
751    * There appears to be a kernel bug in some kernels (at least in the 3.0
752    * Debian Squeeze kernel, but not in the Fedora 17 kernels) around
753    * initialising the IPIP server tunnel (loading the IPIP module), so we retry
754    * a few times before giving up
755    */
756   while (retries-- > 0) {
757     if (!olsr_os_init_iptunnel(server_tunnel_name())) {
758       retries = 5;
759       break;
760     }
761
762     olsr_printf(0, "Could not initialise the IPIP server tunnel, retrying %d more times\n", retries);
763   }
764   if (retries <= 0) {
765     return 1;
766   }
767
768   return 0;
769 }
770
771 /**
772  * Startup gateway system
773  */
774 int olsr_startup_gateways(void) {
775   bool ok = true;
776
777   if (!multi_gateway_mode()) {
778     olsr_add_ifchange_handler(smartgw_tunnel_monitor);
779     return 0;
780   }
781
782   /* Initialise the egress interfaces */
783   {
784     struct sgw_egress_if * egress_if = olsr_cnf->smart_gw_egress_interfaces;
785     while (egress_if) {
786       egress_if->if_index = if_nametoindex(egress_if->name);
787
788       egress_if->upPrevious = egress_if->upCurrent = olsr_if_isup(egress_if->name);
789       egress_if->upChanged = (egress_if->upPrevious != egress_if->upCurrent);
790
791       egressBwClear(&egress_if->bwPrevious, egress_if->upPrevious);
792       egressBwClear(&egress_if->bwCurrent, egress_if->upCurrent);
793       egress_if->bwCostsChanged = egressBwCostsChanged(egress_if);
794       egress_if->bwNetworkChanged = egressBwNetworkChanged(egress_if);
795       egress_if->bwGatewayChanged = egressBwGatewayChanged(egress_if);
796       egress_if->bwChanged = egressBwChanged(egress_if);
797
798       egress_if->inEgressFile = false;
799
800       egress_if = egress_if->next;
801     }
802   }
803
804   ok = ok && multiGwRulesGeneric(true);
805   ok = ok && multiGwRulesSgwServerTunnel(true);
806   ok = ok && multiGwRulesOlsrInterfaces(true);
807   ok = ok && multiGwRulesEgressInterfaces(true);
808   ok = ok && multiGwRulesSgwTunnels(true);
809   if (!ok) {
810     olsr_printf(0, "Could not setup multi-gateway iptables and ip rules\n");
811     olsr_shutdown_gateways();
812     return 1;
813   }
814
815   startEgressFile();
816   doRoutesMultiGw(true, false, GW_MULTI_CHANGE_PHASE_STARTUP);
817
818   olsr_add_ifchange_handler(smartgw_tunnel_monitor);
819
820   /* Check egress interfaces up status to compensate for a race: the interfaces
821    * can change status between initialising their data structures and
822    * registering the tunnel monitor */
823   {
824     struct sgw_egress_if * egress_if = olsr_cnf->smart_gw_egress_interfaces;
825     while (egress_if) {
826       bool upCurrent = olsr_if_isup(egress_if->name);
827
828       if (upCurrent != egress_if->upCurrent) {
829         int index = upCurrent ? (int) if_nametoindex(egress_if->name) : egress_if->if_index;
830         enum olsr_ifchg_flag flag = upCurrent ? IFCHG_IF_ADD : IFCHG_IF_REMOVE;
831         smartgw_tunnel_monitor(index, NULL, flag);
832       }
833
834       egress_if = egress_if->next;
835     }
836   }
837
838   if (olsr_cnf->smart_gw_takedown_percentage > 0) {
839     /* start gateway takedown timer */
840     olsr_set_timer(&gw_takedown_timer, olsr_cnf->smart_gw_period, 0, true, &gw_takedown_timer_callback, NULL, 0);
841   }
842
843   return 0;
844 }
845
846 /**
847  * Shutdown gateway tunnel system
848  */
849 void olsr_shutdown_gateways(void) {
850   if (!multi_gateway_mode()) {
851     olsr_remove_ifchange_handler(smartgw_tunnel_monitor);
852     return;
853   }
854
855   if (olsr_cnf->smart_gw_takedown_percentage > 0) {
856     /* stop gateway takedown timer */
857     olsr_stop_timer(gw_takedown_timer);
858     gw_takedown_timer = NULL;
859   }
860
861   olsr_remove_ifchange_handler(smartgw_tunnel_monitor);
862
863   stopEgressFile();
864   {
865     struct sgw_egress_if * egress_if = olsr_cnf->smart_gw_egress_interfaces;
866     while (egress_if) {
867       egress_if->upPrevious = egress_if->upCurrent;
868       egress_if->upCurrent = false;
869       egress_if->upChanged = (egress_if->upPrevious != egress_if->upCurrent);
870
871       egress_if->bwPrevious = egress_if->bwCurrent;
872       egressBwClear(&egress_if->bwCurrent, egress_if->upCurrent);
873       egress_if->bwCostsChanged = egressBwCostsChanged(egress_if);
874       egress_if->bwNetworkChanged = egressBwNetworkChanged(egress_if);
875       egress_if->bwGatewayChanged = egressBwGatewayChanged(egress_if);
876       egress_if->bwChanged = egressBwChanged(egress_if);
877
878       egress_if->inEgressFile = false;
879
880       egress_if = egress_if->next;
881     }
882   }
883   doRoutesMultiGw(true, false, GW_MULTI_CHANGE_PHASE_SHUTDOWN);
884
885   (void)multiGwRulesSgwTunnels(false);
886   (void)multiGwRulesEgressInterfaces(false);
887   (void)multiGwRulesOlsrInterfaces(false);
888   (void)multiGwRulesSgwServerTunnel(false);
889   (void)multiGwRulesGeneric(false);
890 }
891
892 /**
893  * Cleanup gateway tunnel system
894  */
895 void olsr_cleanup_gateways(void) {
896   struct gateway_entry * tree_gw;
897   struct gw_container_entry * gw;
898
899   /* remove all gateways in the gateway tree that are not the active gateway */
900   OLSR_FOR_ALL_GATEWAY_ENTRIES(tree_gw) {
901     if ((tree_gw != olsr_get_inet_gateway(false)) && (tree_gw != olsr_get_inet_gateway(true))) {
902       olsr_delete_gateway_tree_entry(tree_gw, FORCE_DELETE_GW_ENTRY, true);
903     }
904   } OLSR_FOR_ALL_GATEWAY_ENTRIES_END(tree_gw)
905
906   /* remove all active IPv4 gateways (should be at most 1 now) */
907   OLSR_FOR_ALL_GWS(&gw_list_ipv4.head, gw) {
908     if (gw && gw->gw) {
909       olsr_delete_gateway_entry(&gw->gw->originator, FORCE_DELETE_GW_ENTRY, true);
910     }
911   }
912   OLSR_FOR_ALL_GWS_END(gw);
913
914   /* remove all active IPv6 gateways (should be at most 1 now) */
915   OLSR_FOR_ALL_GWS(&gw_list_ipv6.head, gw) {
916     if (gw && gw->gw) {
917       olsr_delete_gateway_entry(&gw->gw->originator, FORCE_DELETE_GW_ENTRY, true);
918     }
919   }
920   OLSR_FOR_ALL_GWS_END(gw);
921
922   /* there should be no more gateways */
923   assert(!avl_walk_first(&gateway_tree));
924   assert(!current_ipv4_gw);
925   assert(!current_ipv6_gw);
926
927   olsr_os_cleanup_iptunnel(server_tunnel_name());
928
929   assert(gw_handler);
930   gw_handler->cleanup();
931   gw_handler = NULL;
932
933   if (sgwTunnel4InterfaceNames) {
934     free(sgwTunnel4InterfaceNames);
935     sgwTunnel4InterfaceNames = NULL;
936   }
937   if (sgwTunnel6InterfaceNames) {
938     free(sgwTunnel6InterfaceNames);
939     sgwTunnel6InterfaceNames = NULL;
940   }
941
942   olsr_gw_list_cleanup(&gw_list_ipv6);
943   olsr_gw_list_cleanup(&gw_list_ipv4);
944   olsr_free_cookie(gw_container_entry_mem_cookie);
945   olsr_free_cookie(gateway_entry_mem_cookie);
946 }
947
948 /**
949  * Triggers the first lookup of a gateway.
950  */
951 void olsr_trigger_inetgw_startup(void) {
952   assert(gw_handler);
953   gw_handler->startup();
954 }
955
956 /**
957  * Print debug information about gateway entries
958  */
959 #ifndef NODEBUG
960 void olsr_print_gateway_entries(void) {
961   struct ipaddr_str buf;
962   struct gateway_entry *gw;
963   const int addrsize = olsr_cnf->ip_version == AF_INET ? (INET_ADDRSTRLEN - 1) : (INET6_ADDRSTRLEN - 1);
964
965   OLSR_PRINTF(0, "\n--- %s ---------------------------------------------------- GATEWAYS\n\n", olsr_wallclock_string());
966   OLSR_PRINTF(0, "%-*s %-6s %-9s %-9s %s\n",
967       addrsize, "IP address", "Type", "Uplink", "Downlink", olsr_cnf->ip_version == AF_INET ? "" : "External Prefix");
968
969   OLSR_FOR_ALL_GATEWAY_ENTRIES(gw) {
970     OLSR_PRINTF(0, "%-*s %s%c%s%c%c %-9u %-9u %s\n",
971         addrsize,
972         olsr_ip_to_string(&buf, &gw->originator),
973         gw->ipv4nat ? "" : "   ",
974         gw->ipv4 ? '4' : ' ',
975         gw->ipv4nat ? "(N)" : "",
976         (gw->ipv4 && gw->ipv6) ? ',' : ' ',
977         gw->ipv6 ? '6' : ' ',
978         gw->uplink,
979         gw->downlink,
980         gw->external_prefix.prefix_len == 0 ? "" : olsr_ip_prefix_to_string(&gw->external_prefix));
981   } OLSR_FOR_ALL_GATEWAY_ENTRIES_END(gw)
982 }
983 #endif /* NODEBUG */
984
985 /*
986  * Tx Path Interface
987  */
988
989 /**
990  * Apply the smart gateway modifications to an outgoing HNA
991  *
992  * @param mask pointer to netmask of the HNA
993  * @param prefixlen of the HNA
994  */
995 void olsr_modifiy_inetgw_netmask(union olsr_ip_addr *mask, int prefixlen) {
996   uint8_t *ptr = hna_mask_to_hna_pointer(mask, prefixlen);
997
998   /* copy the current settings for uplink/downlink into the mask */
999   memcpy(ptr, &smart_gateway_netmask, sizeof(smart_gateway_netmask) - prefixlen / 8);
1000   if (olsr_cnf->has_ipv4_gateway) {
1001     ptr[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV4;
1002
1003     if (olsr_cnf->smart_gw_uplink_nat) {
1004       ptr[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV4_NAT;
1005     }
1006   }
1007   if (olsr_cnf->has_ipv6_gateway) {
1008     ptr[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV6;
1009   }
1010   if (!olsr_cnf->has_ipv6_gateway || prefixlen != ipv6_internet_route.prefix_len) {
1011     ptr[GW_HNA_FLAGS] &= ~GW_HNA_FLAG_IPV6PREFIX;
1012   }
1013 }
1014
1015 /*
1016  * SgwDynSpeed Plugin Interface
1017  */
1018
1019 /**
1020  * Setup the gateway netmask
1021  */
1022 void refresh_smartgw_netmask(void) {
1023   uint8_t *ip;
1024
1025   /* clear the mask */
1026   memset(&smart_gateway_netmask, 0, sizeof(smart_gateway_netmask));
1027
1028   if (olsr_cnf->smart_gw_active) {
1029     ip = (uint8_t *) &smart_gateway_netmask;
1030
1031     ip[GW_HNA_FLAGS] |= GW_HNA_FLAG_LINKSPEED;
1032     ip[GW_HNA_DOWNLINK] = serialize_gw_speed(olsr_cnf->smart_gw_downlink);
1033     ip[GW_HNA_UPLINK] = serialize_gw_speed(olsr_cnf->smart_gw_uplink);
1034
1035     if (olsr_cnf->ip_version == AF_INET6 && olsr_cnf->smart_gw_prefix.prefix_len > 0) {
1036       ip[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV6PREFIX;
1037       ip[GW_HNA_V6PREFIXLEN] = olsr_cnf->smart_gw_prefix.prefix_len;
1038       memcpy(&ip[GW_HNA_V6PREFIX], &olsr_cnf->smart_gw_prefix.prefix, 8);
1039     }
1040   }
1041 }
1042
1043 /*
1044  * TC/SPF/HNA Interface
1045  */
1046
1047 /**
1048  * Checks if a HNA prefix/netmask combination is a smart gateway
1049  *
1050  * @param prefix
1051  * @param mask
1052  * @return true if is a valid smart gateway HNA, false otherwise
1053  */
1054 bool olsr_is_smart_gateway(struct olsr_ip_prefix *prefix, union olsr_ip_addr *mask) {
1055   uint8_t *ptr;
1056
1057   if (!is_prefix_inetgw(prefix)) {
1058     return false;
1059   }
1060
1061   ptr = hna_mask_to_hna_pointer(mask, prefix->prefix_len);
1062   return ptr[GW_HNA_PAD] == 0 && ptr[GW_HNA_FLAGS] != 0;
1063 }
1064
1065 /**
1066  * Update a gateway_entry based on a HNA
1067  *
1068  * @param originator ip of the source of the HNA
1069  * @param mask netmask of the HNA
1070  * @param prefixlen of the HNA
1071  * @param seqno the sequence number of the HNA
1072  */
1073 void olsr_update_gateway_entry(union olsr_ip_addr *originator, union olsr_ip_addr *mask, int prefixlen, uint16_t seqno) {
1074   struct gw_container_entry * new_gw_in_list;
1075   uint8_t *ptr;
1076   int64_t prev_path_cost = 0;
1077   struct gateway_entry *gw = node2gateway(avl_find(&gateway_tree, originator));
1078
1079   if (!gw) {
1080     gw = olsr_cookie_malloc(gateway_entry_mem_cookie);
1081     gw->originator = *originator;
1082     gw->node.key = &gw->originator;
1083
1084     avl_insert(&gateway_tree, &gw->node, AVL_DUP_NO);
1085   } else if (olsr_seqno_diff(seqno, gw->seqno) <= 0) {
1086     /* ignore older HNAs */
1087     return;
1088   }
1089
1090   /* keep new HNA seqno */
1091   gw->seqno = seqno;
1092
1093   ptr = hna_mask_to_hna_pointer(mask, prefixlen);
1094   if ((ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_LINKSPEED) != 0) {
1095     gw->uplink = deserialize_gw_speed(ptr[GW_HNA_UPLINK]);
1096     gw->downlink = deserialize_gw_speed(ptr[GW_HNA_DOWNLINK]);
1097   } else {
1098     gw->uplink = 0;
1099     gw->downlink = 0;
1100   }
1101
1102   gw->ipv4 = (ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV4) != 0;
1103   gw->ipv4nat = (ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV4_NAT) != 0;
1104   gw->ipv6 = false;
1105
1106   if (olsr_cnf->ip_version == AF_INET6) {
1107     gw->ipv6 = (ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV6) != 0;
1108
1109     /* do not reset prefixlength for ::ffff:0:0 HNAs */
1110     if (prefixlen == ipv6_internet_route.prefix_len) {
1111       memset(&gw->external_prefix, 0, sizeof(gw->external_prefix));
1112
1113       if ((ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV6PREFIX) != 0
1114           && memcmp(mask->v6.s6_addr, &ipv6_internet_route.prefix, olsr_cnf->ipsize) == 0) {
1115         /* this is the right prefix (2000::/3), so we can copy the prefix */
1116         gw->external_prefix.prefix_len = ptr[GW_HNA_V6PREFIXLEN];
1117         memcpy(&gw->external_prefix.prefix, &ptr[GW_HNA_V6PREFIX], 8);
1118       }
1119     }
1120   }
1121
1122   /* stop cleanup timer if necessary */
1123   if (gw->cleanup_timer) {
1124     olsr_stop_timer(gw->cleanup_timer);
1125     gw->cleanup_timer = NULL;
1126   }
1127
1128   assert(gw_handler);
1129   prev_path_cost = gw->path_cost;
1130   gw->path_cost = gw_handler->getcosts(gw);
1131
1132   if (prev_path_cost != gw->path_cost) {
1133     /* re-sort the gateway list when costs have changed and when it is an active gateway */
1134     new_gw_in_list = olsr_gw_list_find(&gw_list_ipv4, gw);
1135     if (new_gw_in_list) {
1136       new_gw_in_list = olsr_gw_list_update(&gw_list_ipv4, new_gw_in_list);
1137       assert(new_gw_in_list);
1138     }
1139
1140     new_gw_in_list = olsr_gw_list_find(&gw_list_ipv6, gw);
1141     if (new_gw_in_list) {
1142       new_gw_in_list = olsr_gw_list_update(&gw_list_ipv6, new_gw_in_list);
1143       assert(new_gw_in_list);
1144     }
1145
1146     if (multi_gateway_mode() && //
1147         ((!gw->ipv6 && current_ipv4_gw && current_ipv4_gw->gw == gw) || //
1148          (gw->ipv6 && current_ipv6_gw && current_ipv6_gw->gw == gw)) //
1149         ) {
1150       /* the active gw has changed its costs: re-evaluate egress routes */
1151       doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
1152     }
1153   }
1154
1155   /* call update handler */
1156   assert(gw_handler);
1157   gw_handler->update(gw);
1158 }
1159
1160 /**
1161  * Delete a gateway based on the originator IP and the prefixlength of a HNA.
1162  * Should only be called if prefix is a smart_gw prefix or if node is removed
1163  * from TC set.
1164  *
1165  * @param originator
1166  * @param prefixlen
1167  * @param immediate when set to true then the gateway is removed from the
1168  * gateway tree immediately, else it is removed on a delayed schedule.
1169  */
1170 void olsr_delete_gateway_entry(union olsr_ip_addr *originator, uint8_t prefixlen, bool immediate) {
1171   olsr_delete_gateway_tree_entry(node2gateway(avl_find(&gateway_tree, originator)), prefixlen, immediate);
1172 }
1173
1174 /**
1175  * Delete a gateway entry .
1176  *
1177  * @param gw a gateway entry from the gateway tree
1178  * @param prefixlen
1179  * @param immediate when set to true then the gateway is removed from the
1180  * gateway tree immediately, else it is removed on a delayed schedule.
1181  */
1182 static void olsr_delete_gateway_tree_entry(struct gateway_entry * gw, uint8_t prefixlen, bool immediate) {
1183   bool change = false;
1184
1185   if (!gw) {
1186     return;
1187   }
1188
1189   if (immediate && gw->cleanup_timer) {
1190     /* stop timer if we have to remove immediately */
1191     olsr_stop_timer(gw->cleanup_timer);
1192     gw->cleanup_timer = NULL;
1193   }
1194
1195   if (gw->cleanup_timer == NULL || gw->ipv4 || gw->ipv6) {
1196     /* the gw  is not scheduled for deletion */
1197
1198     if (olsr_cnf->ip_version == AF_INET && prefixlen == 0) {
1199       change = gw->ipv4;
1200       gw->ipv4 = false;
1201       gw->ipv4nat = false;
1202     } else if (olsr_cnf->ip_version == AF_INET6 && prefixlen == ipv6_internet_route.prefix_len) {
1203       change = gw->ipv6;
1204       gw->ipv6 = false;
1205     } else if (olsr_cnf->ip_version == AF_INET6 && prefixlen == ipv6_mappedv4_route.prefix_len) {
1206       change = gw->ipv4;
1207       gw->ipv4 = false;
1208       gw->ipv4nat = false;
1209     }
1210
1211     if (prefixlen == FORCE_DELETE_GW_ENTRY || !(gw->ipv4 || gw->ipv6)) {
1212       struct gw_container_entry * gw_in_list;
1213
1214       /* prevent this gateway from being chosen as the new gateway */
1215       gw->ipv4 = false;
1216       gw->ipv4nat = false;
1217       gw->ipv6 = false;
1218
1219       /* handle gateway loss */
1220       assert(gw_handler);
1221       gw_handler->delete(gw);
1222
1223       /* cleanup gateway if necessary */
1224       gw_in_list = olsr_gw_list_find(&gw_list_ipv4, gw);
1225       if (gw_in_list) {
1226         if (current_ipv4_gw && current_ipv4_gw->gw == gw) {
1227           olsr_os_inetgw_tunnel_route(current_ipv4_gw->tunnel->if_index, true, false, olsr_cnf->rt_table_tunnel);
1228           current_ipv4_gw = NULL;
1229         }
1230
1231         if (gw_in_list->tunnel) {
1232           struct interfaceName * ifn = find_interfaceName(gw_in_list->gw);
1233           if (ifn) {
1234             olsr_os_inetgw_tunnel_route(gw_in_list->tunnel->if_index, true, false, ifn->tableNr);
1235           }
1236           olsr_os_del_ipip_tunnel(gw_in_list->tunnel);
1237           set_unused_iptunnel_name(gw_in_list->gw);
1238           gw_in_list->tunnel = NULL;
1239         }
1240
1241         gw_in_list->gw = NULL;
1242         gw_in_list = olsr_gw_list_remove(&gw_list_ipv4, gw_in_list);
1243         olsr_cookie_free(gw_container_entry_mem_cookie, gw_in_list);
1244       }
1245
1246       gw_in_list = olsr_gw_list_find(&gw_list_ipv6, gw);
1247       if (gw_in_list) {
1248         if (current_ipv6_gw && current_ipv6_gw->gw == gw) {
1249           olsr_os_inetgw_tunnel_route(current_ipv6_gw->tunnel->if_index, false, false, olsr_cnf->rt_table_tunnel);
1250           current_ipv6_gw = NULL;
1251         }
1252
1253         if (gw_in_list->tunnel) {
1254           struct interfaceName * ifn = find_interfaceName(gw_in_list->gw);
1255           if (ifn) {
1256             olsr_os_inetgw_tunnel_route(gw_in_list->tunnel->if_index, false, false, ifn->tableNr);
1257           }
1258           olsr_os_del_ipip_tunnel(gw_in_list->tunnel);
1259           set_unused_iptunnel_name(gw_in_list->gw);
1260           gw_in_list->tunnel = NULL;
1261         }
1262
1263         gw_in_list->gw = NULL;
1264         gw_in_list = olsr_gw_list_remove(&gw_list_ipv6, gw_in_list);
1265         olsr_cookie_free(gw_container_entry_mem_cookie, gw_in_list);
1266       }
1267
1268       if (!immediate) {
1269         /* remove gateway entry on a delayed schedule */
1270         olsr_set_timer(&gw->cleanup_timer, GW_CLEANUP_INTERVAL, 0, false, cleanup_gateway_handler, gw, NULL);
1271       } else {
1272         cleanup_gateway_handler(gw);
1273       }
1274
1275       /* when the current gateway was deleted, then immediately choose a new gateway */
1276       if (!current_ipv4_gw || !current_ipv6_gw) {
1277         assert(gw_handler);
1278         gw_handler->choose(!current_ipv4_gw, !current_ipv6_gw);
1279       }
1280
1281     } else if (change) {
1282       assert(gw_handler);
1283       gw_handler->update(gw);
1284     }
1285   }
1286 }
1287
1288 /**
1289  * Triggers a check if the one of the gateways have been lost or has an
1290  * ETX = infinity
1291  */
1292 void olsr_trigger_gatewayloss_check(void) {
1293   bool ipv4 = false;
1294   bool ipv6 = false;
1295
1296   if (current_ipv4_gw && current_ipv4_gw->gw) {
1297     struct tc_entry *tc = olsr_lookup_tc_entry(&current_ipv4_gw->gw->originator);
1298     ipv4 = (tc == NULL || tc->path_cost == ROUTE_COST_BROKEN);
1299   }
1300   if (current_ipv6_gw && current_ipv6_gw->gw) {
1301     struct tc_entry *tc = olsr_lookup_tc_entry(&current_ipv6_gw->gw->originator);
1302     ipv6 = (tc == NULL || tc->path_cost == ROUTE_COST_BROKEN);
1303   }
1304
1305   if (ipv4 || ipv6) {
1306     assert(gw_handler);
1307     gw_handler->choose(ipv4, ipv6);
1308   }
1309 }
1310
1311 /*
1312  * Gateway Plugin Functions
1313  */
1314
1315 /**
1316  * Sets a new internet gateway.
1317  *
1318  * @param the chosen gateway
1319  * @param ipv4 set ipv4 gateway
1320  * @param ipv6 set ipv6 gateway
1321  * @return true if an error happened, false otherwise
1322  */
1323 bool olsr_set_inet_gateway(struct gateway_entry * chosen_gw, bool ipv4, bool ipv6) {
1324   struct gateway_entry *new_gw;
1325
1326   ipv4 = ipv4 && (olsr_cnf->ip_version == AF_INET || olsr_cnf->use_niit);
1327   ipv6 = ipv6 && (olsr_cnf->ip_version == AF_INET6);
1328   if (!ipv4 && !ipv6) {
1329     return true;
1330   }
1331
1332   new_gw = node2gateway(avl_find(&gateway_tree, &chosen_gw->originator));
1333   if (!new_gw) {
1334     /* the originator is not in the gateway tree, we can't set it as gateway */
1335     return true;
1336   }
1337
1338   /* handle IPv4 */
1339   if (ipv4 &&
1340       new_gw->ipv4 &&
1341       (!new_gw->ipv4nat || olsr_cnf->smart_gw_allow_nat) &&
1342       (!current_ipv4_gw || current_ipv4_gw->gw != new_gw)) {
1343     /* new gw is different than the current gw */
1344
1345     struct gw_container_entry * new_gw_in_list = olsr_gw_list_find(&gw_list_ipv4, new_gw);
1346     if (new_gw_in_list) {
1347       /* new gw is already in the gw list */
1348       assert(new_gw_in_list->tunnel);
1349       olsr_os_inetgw_tunnel_route(new_gw_in_list->tunnel->if_index, true, true, olsr_cnf->rt_table_tunnel);
1350       current_ipv4_gw = new_gw_in_list;
1351
1352       if (multi_gateway_mode()) {
1353         doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
1354       }
1355     } else {
1356       /* new gw is not yet in the gw list */
1357       char name[IFNAMSIZ];
1358       struct olsr_iptunnel_entry *new_v4gw_tunnel;
1359       struct interfaceName * interfaceName;
1360
1361       if (olsr_gw_list_full(&gw_list_ipv4)) {
1362         /* the list is full: remove the worst active gateway */
1363         struct gw_container_entry* worst = olsr_gw_list_get_worst_entry(&gw_list_ipv4);
1364         assert(worst);
1365
1366         removeGatewayFromList(&gw_list_ipv4, true, worst);
1367       }
1368
1369       get_unused_iptunnel_name(new_gw, name, &interfaceName);
1370       new_v4gw_tunnel = olsr_os_add_ipip_tunnel(&new_gw->originator, true, name);
1371       if (new_v4gw_tunnel) {
1372         if (interfaceName) {
1373           olsr_os_inetgw_tunnel_route(new_v4gw_tunnel->if_index, true, true, interfaceName->tableNr);
1374         }
1375         olsr_os_inetgw_tunnel_route(new_v4gw_tunnel->if_index, true, true, olsr_cnf->rt_table_tunnel);
1376
1377         new_gw_in_list = olsr_cookie_malloc(gw_container_entry_mem_cookie);
1378         new_gw_in_list->gw = new_gw;
1379         new_gw_in_list->tunnel = new_v4gw_tunnel;
1380         current_ipv4_gw = olsr_gw_list_add(&gw_list_ipv4, new_gw_in_list);
1381
1382         if (multi_gateway_mode()) {
1383           doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
1384         }
1385       } else {
1386         /* adding the tunnel failed, we try again in the next cycle */
1387         set_unused_iptunnel_name(new_gw);
1388         ipv4 = false;
1389       }
1390     }
1391   }
1392
1393   /* handle IPv6 */
1394   if (ipv6 &&
1395       new_gw->ipv6 &&
1396       (!current_ipv6_gw || current_ipv6_gw->gw != new_gw)) {
1397     /* new gw is different than the current gw */
1398
1399         struct gw_container_entry * new_gw_in_list = olsr_gw_list_find(&gw_list_ipv6, new_gw);
1400     if (new_gw_in_list) {
1401       /* new gw is already in the gw list */
1402       assert(new_gw_in_list->tunnel);
1403       olsr_os_inetgw_tunnel_route(new_gw_in_list->tunnel->if_index, true, true, olsr_cnf->rt_table_tunnel);
1404       current_ipv6_gw = new_gw_in_list;
1405
1406       if (multi_gateway_mode()) {
1407         doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
1408       }
1409     } else {
1410       /* new gw is not yet in the gw list */
1411       char name[IFNAMSIZ];
1412       struct olsr_iptunnel_entry *new_v6gw_tunnel;
1413       struct interfaceName * interfaceName;
1414
1415       if (olsr_gw_list_full(&gw_list_ipv6)) {
1416         /* the list is full: remove the worst active gateway */
1417         struct gw_container_entry* worst = olsr_gw_list_get_worst_entry(&gw_list_ipv6);
1418         assert(worst);
1419
1420         removeGatewayFromList(&gw_list_ipv6, false, worst);
1421       }
1422
1423       get_unused_iptunnel_name(new_gw, name, &interfaceName);
1424       new_v6gw_tunnel = olsr_os_add_ipip_tunnel(&new_gw->originator, false, name);
1425       if (new_v6gw_tunnel) {
1426         if (interfaceName) {
1427           olsr_os_inetgw_tunnel_route(new_v6gw_tunnel->if_index, false, true, interfaceName->tableNr);
1428         }
1429         olsr_os_inetgw_tunnel_route(new_v6gw_tunnel->if_index, false, true, olsr_cnf->rt_table_tunnel);
1430
1431         new_gw_in_list = olsr_cookie_malloc(gw_container_entry_mem_cookie);
1432         new_gw_in_list->gw = new_gw;
1433         new_gw_in_list->tunnel = new_v6gw_tunnel;
1434         current_ipv6_gw = olsr_gw_list_add(&gw_list_ipv6, new_gw_in_list);
1435
1436         if (multi_gateway_mode()) {
1437           doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
1438         }
1439       } else {
1440         /* adding the tunnel failed, we try again in the next cycle */
1441         set_unused_iptunnel_name(new_gw);
1442         ipv6 = false;
1443       }
1444     }
1445   }
1446
1447   return !ipv4 && !ipv6;
1448 }
1449
1450 /**
1451  * @param ipv6 if set to true then the IPv6 gateway is returned, otherwise the IPv4
1452  * gateway is returned
1453  * @return a pointer to the gateway_entry of the current ipv4 internet gw or
1454  * NULL if not set.
1455  */
1456 struct gateway_entry *olsr_get_inet_gateway(bool ipv6) {
1457         if (ipv6) {
1458                 return current_ipv6_gw ? current_ipv6_gw->gw : NULL;
1459         }
1460
1461         return current_ipv4_gw ? current_ipv4_gw->gw : NULL;
1462 }
1463
1464 /*
1465  * Process Egress Changes
1466  */
1467
1468 #define MSGW_ROUTE_ADD_ALLOWED(phase)   ((phase == GW_MULTI_CHANGE_PHASE_STARTUP ) || (phase == GW_MULTI_CHANGE_PHASE_RUNTIME ))
1469 #define MSGW_ROUTE_ADD_FORCED(phase)    ( phase == GW_MULTI_CHANGE_PHASE_STARTUP )
1470 #define MSGW_ROUTE_DEL_ALLOWED(phase)   ((phase == GW_MULTI_CHANGE_PHASE_RUNTIME ) || (phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN))
1471 #define MSGW_ROUTE_DEL_FORCED(phase)    ( phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN)
1472 #define MSGW_ROUTE_FORCED(phase)        ((phase == GW_MULTI_CHANGE_PHASE_STARTUP ) || (phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN))
1473
1474 /**
1475  * Determine best egress link.
1476  * The list of egress interface is ordered on priority (the declaration order),
1477  * so the function will - for multiple egress links with the same costs - set the
1478  * best egress interface to the first declared one of those.
1479  * When there is no best egress interface (that is up) then the function will
1480  * set the best egress interface to NULL.
1481  *
1482  * @param phase the phase of the change (startup/runtime/shutdown)
1483  * @return true when the best egress link changed or when any of its relevant
1484  * parameters has changed
1485  */
1486 static bool determineBestEgressLink(enum sgw_multi_change_phase phase) {
1487   struct sgw_egress_if * bestEgress = olsr_cnf->smart_gw_egress_interfaces;
1488
1489   if (phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN) {
1490     bestEgress = NULL;
1491   } else {
1492     struct sgw_egress_if * egress_if = bestEgress;
1493     if (egress_if) {
1494       egress_if = egress_if->next;
1495     }
1496     while (egress_if) {
1497       if (egress_if->upCurrent && (egress_if->bwCurrent.costs < bestEgress->bwCurrent.costs)) {
1498         bestEgress = egress_if;
1499       }
1500
1501       egress_if = egress_if->next;
1502     }
1503
1504     if (bestEgress && (!bestEgress->upCurrent || (bestEgress->bwCurrent.costs == INT64_MAX))) {
1505       bestEgress = NULL;
1506     }
1507   }
1508
1509   bestEgressLinkPrevious = bestEgressLink;
1510   bestEgressLink = bestEgress;
1511
1512   return ((bestEgressLinkPrevious != bestEgressLink) || //
1513       (bestEgressLink && (bestEgressLink->upChanged || bestEgressLink->bwChanged)));
1514 }
1515
1516 /**
1517  * Determine best overall link (choose egress interface over olsrd).
1518  *
1519  * When there is no best overall link, the best overall link will be set to a
1520  * NULL egress interface.
1521  *
1522  * @param phase the phase of the change (startup/runtime/shutdown)
1523  * @return true when the best egress link changed or when any of its relevant
1524  * parameters has changed
1525  */
1526 static bool determineBestOverallLink(enum sgw_multi_change_phase phase) {
1527   struct gw_container_entry * gwContainer = (olsr_cnf->ip_version == AF_INET) ? current_ipv4_gw : current_ipv6_gw;
1528   struct gateway_entry * olsrGw = !gwContainer ? NULL : gwContainer->gw;
1529
1530   int64_t egressCosts = !bestEgressLink ? INT64_MAX : bestEgressLink->bwCurrent.costs;
1531   int64_t olsrCosts = !olsrGw ? INT64_MAX : olsrGw->path_cost;
1532   int64_t bestOverallCosts = MIN(egressCosts, olsrCosts);
1533
1534   bestOverallLinkPrevious = bestOverallLink;
1535   if ((bestOverallCosts == INT64_MAX) || (phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN)) {
1536     bestOverallLink.valid = false;
1537     bestOverallLink.isOlsr = false;
1538     bestOverallLink.link.egress = NULL;
1539     bestOverallLink.olsrTunnelIfIndex = 0;
1540   } else if (egressCosts <= olsrCosts) {
1541     bestOverallLink.valid = bestEgressLink;
1542     bestOverallLink.isOlsr = false;
1543     bestOverallLink.link.egress = bestEgressLink;
1544     bestOverallLink.olsrTunnelIfIndex = 0;
1545   } else {
1546     struct olsr_iptunnel_entry * tunnel = !gwContainer ? NULL : gwContainer->tunnel;
1547
1548     bestOverallLink.valid = olsrGw;
1549     bestOverallLink.isOlsr = true;
1550     bestOverallLink.link.olsr = olsrGw;
1551     bestOverallLink.olsrTunnelIfIndex = !tunnel ? 0 : tunnel->if_index;
1552   }
1553
1554   return memcmp(&bestOverallLink, &bestOverallLinkPrevious, sizeof(bestOverallLink));
1555 }
1556
1557 /**
1558  * Program a route (add or remove) through netlink
1559  *
1560  * @param add true to add the route, false to remove it
1561  * @param route the route
1562  * @param linkName the human readable id of the route, used in error reports in
1563  * the syslog
1564  */
1565 static void programRoute(bool add, struct sgw_route_info * route, const char * linkName) {
1566   if (!route || !route->active) {
1567     return;
1568   }
1569
1570   if (olsr_new_netlink_route( //
1571       route->route.family, //
1572       route->route.rttable, //
1573       route->route.flags, //
1574       route->route.scope, //
1575       route->route.if_index, //
1576       route->route.metric, //
1577       route->route.protocol, //
1578       !route->route.srcSet ? NULL : &route->route.srcStore, //
1579       !route->route.gwSet ? NULL : &route->route.gwStore, //
1580       !route->route.dstSet ? NULL : &route->route.dstStore, //
1581       add, //
1582       route->route.del_similar, //
1583       route->route.blackhole //
1584       )) {
1585     olsr_syslog(OLSR_LOG_ERR, "Could not %s a route for the %s %s", !add ? "remove" : "add", !add ? "previous" : "current", linkName);
1586     route->active = false;
1587   } else {
1588     route->active = add;
1589   }
1590 }
1591
1592 /**
1593  * Determine the best overall egress/olsr interface routes.
1594  *
1595  * These are a set of 2 /1 routes to override any default gateway
1596  * routes that are setup through other means such as a DHCP client.
1597  *
1598  * @param routes a pointer to the array of 2 /1 routes where to store the
1599  * newly determined routes
1600  */
1601 static void determineBestOverallLinkRoutes(struct sgw_route_info * routes) {
1602   int ifIndex = 0;
1603   union olsr_ip_addr * gw = NULL;
1604   int i;
1605   if (!bestOverallLink.valid) {
1606     /* there is no current best overall link */
1607   } else if (!bestOverallLink.isOlsr) {
1608     /* current best overall link is an egress interface */
1609     struct sgw_egress_if * egress = bestOverallLink.link.egress;
1610     if (egress) {
1611       ifIndex = egress->if_index;
1612       if (egress->bwCurrent.gatewaySet) {
1613         gw = &egress->bwCurrent.gateway;
1614       }
1615     }
1616   } else {
1617     /* current best overall link is an olsr tunnel interface */
1618     struct gw_container_entry * gwContainer = current_ipv4_gw;
1619     struct olsr_iptunnel_entry * tunnel = !gwContainer ? NULL : gwContainer->tunnel;
1620
1621     if (tunnel) {
1622       ifIndex = tunnel->if_index;
1623     }
1624   }
1625
1626   if (!ifIndex) {
1627     for (i = 0; i < 2; i++) {
1628       routes[i].active = false;
1629     }
1630     return;
1631   }
1632
1633   for (i = 0; i < 2; i++) {
1634     memset(&routes[i], 0, sizeof(routes[i]));
1635     routes[i].active = true;
1636     routes[i].route.family = AF_INET;
1637     routes[i].route.rttable = olsr_cnf->rt_table;
1638     routes[i].route.flags = 0;
1639     routes[i].route.scope = !gw ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
1640     routes[i].route.if_index = ifIndex;
1641     routes[i].route.metric = 0;
1642     routes[i].route.protocol = RTPROT_STATIC;
1643     routes[i].route.srcSet = false;
1644     routes[i].route.gwSet = false;
1645     if (gw) {
1646       routes[i].route.gwSet = true;
1647       routes[i].route.gwStore = *gw;
1648     }
1649     routes[i].route.dstSet = true;
1650     routes[i].route.dstStore = ipv4_slash_1_routes[i];
1651     routes[i].route.del_similar = false;
1652     routes[i].route.blackhole = false;
1653   }
1654 }
1655
1656 /**
1657  * Setup default gateway override routes: a set of 2 /1 routes for the best
1658  * overall link
1659  *
1660  * @param phase the phase of the change (startup/runtime/shutdown)
1661  */
1662 static void setupDefaultGatewayOverrideRoutes(enum sgw_multi_change_phase phase) {
1663   bool force = MSGW_ROUTE_FORCED(phase);
1664   int i;
1665
1666   if (!bestOverallLinkPrevious.valid && !bestOverallLink.valid && !force) {
1667     return;
1668   }
1669
1670   memcpy(&bestOverallLinkPreviousRoutes, &bestOverallLinkRoutes, sizeof(bestOverallLinkPreviousRoutes));
1671
1672   determineBestOverallLinkRoutes(bestOverallLinkRoutes);
1673
1674   for (i = 0; i < 2; i++) {
1675     bool routeChanged = //
1676         (bestOverallLinkPreviousRoutes[i].active != bestOverallLinkRoutes[i].active) || //
1677         memcmp(&bestOverallLinkPreviousRoutes[i].route, &bestOverallLinkRoutes[i].route, sizeof(bestOverallLinkRoutes[i].route));
1678
1679     if ((routeChanged || MSGW_ROUTE_DEL_FORCED(phase)) && MSGW_ROUTE_DEL_ALLOWED(phase)) {
1680       programRoute(false, &bestOverallLinkPreviousRoutes[i], "overall best gateway");
1681     }
1682
1683     if ((routeChanged || MSGW_ROUTE_ADD_FORCED(phase)) && MSGW_ROUTE_ADD_ALLOWED(phase)) {
1684       programRoute(true, &bestOverallLinkRoutes[i], "overall best gateway");
1685     }
1686   }
1687 }
1688
1689 /**
1690  * Determine the best egress interface route.
1691  *
1692  * @param route a pointer to the an route where to store the
1693  * newly determined route
1694  * @param networkRoute true when the route is a network route (not an internet
1695  * route)
1696  * @param if_index the index of the interface that the route is for
1697  * @param gw the gateway for the route
1698  * @param dst the destination for the route
1699  * @param table the routing table for the route
1700  */
1701 static void determineEgressLinkRoute( //
1702     struct sgw_route_info * route, //
1703     bool networkRoute, //
1704     int if_index, //
1705     union olsr_ip_addr * gw, //
1706     struct olsr_ip_prefix * dst, //
1707     int table) {
1708   // default route
1709   // ----: ip route replace|delete blackhole default                          table 90: !egress_if               (1)
1710   // ppp0: ip route replace|delete           default                 dev ppp0 table 90:  egress_if && dst && !gw (2)
1711   // eth1: ip route replace|delete           default via 192.168.0.1 dev eth1 table 90:  egress_if && dst &&  gw (3)
1712
1713   // network route
1714   // eth1: ip route replace|delete to 192.168.0.0/24                 dev eth1 table 90:  egress_if && dst && !gw (2*)
1715
1716   memset(route, 0, sizeof(*route));
1717   if (if_index <= 0) { /* 1 */
1718     route->active = true;
1719     route->route.family = AF_INET;
1720     route->route.rttable = table;
1721     route->route.flags = RTNH_F_ONLINK;
1722     route->route.scope = RT_SCOPE_UNIVERSE;
1723     route->route.if_index = 0;
1724     route->route.metric = 0;
1725     route->route.protocol = RTPROT_STATIC;
1726     route->route.srcSet = false;
1727     route->route.gwSet = false;
1728     route->route.dstSet = false;
1729     if (dst) {
1730       route->route.dstSet = true;
1731       route->route.dstStore = *dst;
1732     }
1733     route->route.del_similar = false;
1734     route->route.blackhole = true;
1735   } else if (dst && !gw) { /* 2 */
1736     route->active = true;
1737     route->route.family = AF_INET;
1738     route->route.rttable = table;
1739     route->route.flags = !networkRoute ? RTNH_F_ONLINK /* 2 */ : 0 /* 2* */;
1740     route->route.scope = RT_SCOPE_LINK;
1741     route->route.if_index = if_index;
1742     route->route.metric = 0;
1743     route->route.protocol = RTPROT_STATIC;
1744     route->route.srcSet = false;
1745     route->route.gwSet = false;
1746     route->route.dstSet = true;
1747     route->route.dstStore = *dst;
1748     route->route.del_similar = false;
1749     route->route.blackhole = false;
1750   } else if (dst && gw) { /* 3 */
1751     route->active = true;
1752     route->route.family = AF_INET;
1753     route->route.rttable = table;
1754     route->route.flags = 0;
1755     route->route.scope = RT_SCOPE_UNIVERSE;
1756     route->route.if_index = if_index;
1757     route->route.metric = 0;
1758     route->route.protocol = RTPROT_STATIC;
1759     route->route.srcSet = false;
1760     route->route.gwSet = true;
1761     route->route.gwStore = *gw;
1762     route->route.dstSet = true;
1763     route->route.dstStore = *dst;
1764     route->route.del_similar = false;
1765     route->route.blackhole = false;
1766   } else {
1767     /* no destination set */
1768     route->active = false;
1769     olsr_syslog(OLSR_LOG_ERR, "No route destination specified in %s", __FUNCTION__);
1770     return;
1771   }
1772 }
1773
1774 /**
1775  * Setup default route for the best egress interface
1776  *
1777  * When there is no best egress link, then a blackhole route is setup to prevent
1778  * looping smart gateway tunnel traffic.
1779  *
1780  * @param phase the phase of the change (startup/runtime/shutdown)
1781  */
1782 static void configureBestEgressLinkRoute(enum sgw_multi_change_phase phase) {
1783   bool force = MSGW_ROUTE_FORCED(phase);
1784
1785   /*
1786    * bestEgressLinkPrevious  bestEgressLink  Action
1787    *                   NULL            NULL  -
1788    *                   NULL               x  add new route
1789    *                      x            NULL  remove old route
1790    *                      x               x  remove old route && add new routes
1791    */
1792
1793   if (!bestEgressLinkPrevious && !bestEgressLink && !force) {
1794     return;
1795   }
1796
1797   memcpy(&bestEgressLinkPreviousRoute, &bestEgressLinkRoute, sizeof(bestEgressLinkPreviousRoute));
1798
1799   determineEgressLinkRoute( //
1800       &bestEgressLinkRoute, // route
1801       false, // networkRoute
1802       !bestEgressLink ? 0 : bestEgressLink->if_index, // if_index
1803       (!bestEgressLink || !bestEgressLink->bwCurrent.gatewaySet) ? NULL : &bestEgressLink->bwCurrent.gateway, // gw
1804       &ipv4_slash_0_route, // dst
1805       olsr_cnf->smart_gw_offset_tables // table
1806       );
1807
1808   {
1809     bool routeChanged = //
1810         (bestEgressLinkPreviousRoute.active != bestEgressLinkRoute.active) || //
1811         memcmp(&bestEgressLinkPreviousRoute.route, &bestEgressLinkRoute.route, sizeof(bestEgressLinkRoute.route));
1812
1813     if ((routeChanged || MSGW_ROUTE_DEL_FORCED(phase)) && MSGW_ROUTE_DEL_ALLOWED(phase)) {
1814       programRoute(false, &bestEgressLinkPreviousRoute, "best egress link");
1815     }
1816
1817     if ((routeChanged || MSGW_ROUTE_ADD_FORCED(phase)) && MSGW_ROUTE_ADD_ALLOWED(phase)) {
1818       programRoute(true, &bestEgressLinkRoute, "best egress link");
1819     }
1820   }
1821 }
1822
1823 /**
1824  * Setup network (when relevant) and default routes for the every egress
1825  * interface
1826  *
1827  * @param phase the phase of the change (startup/runtime/shutdown)
1828  */
1829 static void configureEgressLinkRoutes(enum sgw_multi_change_phase phase) {
1830   bool force = MSGW_ROUTE_FORCED(phase);
1831
1832   /* egress interfaces */
1833   struct sgw_egress_if * egress_if = olsr_cnf->smart_gw_egress_interfaces;
1834   while (egress_if) {
1835     if (!egress_if->bwNetworkChanged && !egress_if->bwGatewayChanged && !egress_if->upChanged && !force) {
1836       /* no relevant change */
1837       goto next;
1838     }
1839
1840     /* network route */
1841     if (egress_if->bwNetworkChanged || force) {
1842       bool routeChanged;
1843
1844       struct sgw_route_info networkRoutePrevious = egress_if->networkRouteCurrent;
1845
1846       if (!egress_if->bwCurrent.networkSet || !egress_if->upCurrent || (egress_if->bwCurrent.costs == INT64_MAX)) {
1847         memset(&egress_if->networkRouteCurrent, 0, sizeof(egress_if->networkRouteCurrent));
1848         egress_if->networkRouteCurrent.active = false;
1849       } else {
1850         determineEgressLinkRoute( //
1851             &egress_if->networkRouteCurrent, // route
1852             true,// networkRoute
1853             egress_if->if_index, // if_index
1854             NULL, // gw
1855             &egress_if->bwCurrent.network, // dst
1856             egress_if->tableNr // table
1857             );
1858       }
1859
1860       routeChanged = //
1861           (networkRoutePrevious.active != egress_if->networkRouteCurrent.active) || //
1862           memcmp(&networkRoutePrevious.route, &egress_if->networkRouteCurrent.route, sizeof(egress_if->networkRouteCurrent.route));
1863
1864       if ((routeChanged || MSGW_ROUTE_DEL_FORCED(phase)) && MSGW_ROUTE_DEL_ALLOWED(phase)) {
1865         programRoute(false, &networkRoutePrevious, egress_if->name);
1866       }
1867
1868       if ((routeChanged || MSGW_ROUTE_ADD_FORCED(phase)) && MSGW_ROUTE_ADD_ALLOWED(phase)) {
1869         programRoute(true, &egress_if->networkRouteCurrent, egress_if->name);
1870       }
1871     }
1872
1873     /* default route */
1874     if (egress_if->bwGatewayChanged || force) {
1875       bool routeChanged;
1876
1877       struct sgw_route_info egressRoutePrevious = egress_if->egressRouteCurrent;
1878
1879       if (!egress_if->upCurrent || (egress_if->bwCurrent.costs == INT64_MAX)) {
1880         memset(&egress_if->egressRouteCurrent, 0, sizeof(egress_if->egressRouteCurrent));
1881         egress_if->egressRouteCurrent.active = false;
1882       } else {
1883         determineEgressLinkRoute( //
1884             &egress_if->egressRouteCurrent, // route
1885             false,// networkRoute
1886             egress_if->if_index, // if_index
1887             !egress_if->bwCurrent.gatewaySet ? NULL : &egress_if->bwCurrent.gateway, // gw
1888             &ipv4_slash_0_route, // dst
1889             egress_if->tableNr // table
1890             );
1891       }
1892
1893       routeChanged = //
1894           (egressRoutePrevious.active != egress_if->egressRouteCurrent.active) || //
1895           memcmp(&egressRoutePrevious, &egress_if->egressRouteCurrent, sizeof(egress_if->egressRouteCurrent));
1896
1897        if ((routeChanged || MSGW_ROUTE_DEL_FORCED(phase)) && MSGW_ROUTE_DEL_ALLOWED(phase)) {
1898          programRoute(false, &egressRoutePrevious, egress_if->name);
1899        }
1900
1901        if ((routeChanged || MSGW_ROUTE_ADD_FORCED(phase)) && MSGW_ROUTE_ADD_ALLOWED(phase)) {
1902          programRoute(true, &egress_if->egressRouteCurrent, egress_if->name);
1903        }
1904     }
1905
1906     next: egress_if = egress_if->next;
1907   }
1908 }
1909
1910 /*
1911  * Multi-Smart-Gateway Status Overview
1912  */
1913
1914 #define IPNONE    ((olsr_cnf->ip_version == AF_INET) ? "0.0.0.0"     : "::")
1915 #define MASKNONE  ((olsr_cnf->ip_version == AF_INET) ? "0.0.0.0/0"   : "::/0")
1916 #define IPLOCAL   ((olsr_cnf->ip_version == AF_INET) ? "127.0.0.1"   : "::1")
1917 #define MASKLOCAL ((olsr_cnf->ip_version == AF_INET) ? "127.0.0.0/8" : "::1/128")
1918
1919 /**
1920  * Print a timestamp to a file
1921  *
1922  * @param f the file
1923  */
1924 static void printDate(FILE * f) {
1925   time_t timer;
1926   struct tm* tm_info;
1927   char buffer[64];
1928
1929   time(&timer);
1930   tm_info = localtime(&timer);
1931
1932   strftime(buffer, sizeof(buffer), "%B %d, %Y at %H:%M:%S", tm_info);
1933   fprintf(f, "%s", buffer);
1934 }
1935
1936 /**
1937  * Write multi-smart-gateway status file
1938  *
1939  * <pre>
1940  * # multi-smart-gateway status overview, generated on October 10, 2014 at 08:27:15
1941  *
1942  * #Originator Prefix      Uplink Downlink PathCost   Type   Interface Gateway     Cost
1943  *  127.0.0.1  127.0.0.0/8 0      0        4294967295 egress ppp0      0.0.0.0     9223372036854775807
1944  *  127.0.0.1  127.0.0.0/8 0      0        4294967295 egress eth1      192.168.0.1 9223372036854775807
1945  * *0.0.0.0    0.0.0.0/0   290    1500     1024       olsr   tnl_4094  0.0.0.0     2182002287
1946  * </pre>
1947  *
1948  * @param phase the phase of the change (startup/runtime/shutdown)
1949  */
1950 static void writeProgramStatusFile(enum sgw_multi_change_phase phase) {
1951              /*                     #  Orig Prefx Upl   Dwn PathC Type  Intfc Gw    Cost */
1952   static const char * fmt_header = "%s%-16s %-33s %-8s %-8s %-10s %-16s %-16s %-16s %s\n";
1953   static const char * fmt_values = "%s%-16s %-33s %-8u %-8u %-10u %-16s %-16s %-16s %llu\n";
1954
1955   char * fileName = olsr_cnf->smart_gw_status_file;
1956   FILE * fp = NULL;
1957
1958   if (!fileName || (fileName[0] == '\0')) {
1959     return;
1960   }
1961
1962   if (phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN) {
1963     remove(fileName);
1964     return;
1965   }
1966
1967   fp = fopen(fileName, "w");
1968   if (!fp) {
1969     olsr_syslog(OLSR_LOG_ERR, "Could not write to %s", fileName);
1970     return;
1971   }
1972
1973   fprintf(fp, "# OLSRd Multi-Smart-Gateway Status Overview\n");
1974   fprintf(fp, "# Generated on ");
1975   printDate(fp);
1976   fprintf(fp, "\n\n");
1977
1978   /* header */
1979   fprintf(fp, fmt_header, "#", "Originator", "Prefix", "Uplink", "Downlink", "PathCost", "Type", "Interface", "Gateway", "Cost");
1980
1981   /* egress interfaces */
1982   {
1983     struct sgw_egress_if * egress_if = olsr_cnf->smart_gw_egress_interfaces;
1984     while (egress_if) {
1985       struct ipaddr_str gwStr;
1986       const char * gw = !egress_if->bwCurrent.gatewaySet ? IPNONE : olsr_ip_to_string(&gwStr, &egress_if->bwCurrent.gateway);
1987       bool selected = bestOverallLink.valid && !bestOverallLink.isOlsr && (bestOverallLink.link.egress == egress_if);
1988
1989       fprintf(fp, fmt_values, //
1990           selected ? "*" : " ", //selected
1991           IPLOCAL, // Originator
1992           MASKLOCAL, // Prefix
1993           egress_if->bwCurrent.egressUk, // Uplink
1994           egress_if->bwCurrent.egressDk, // Downlink
1995           egress_if->bwCurrent.path_cost, // PathCost
1996           "egress", // Type
1997           egress_if->name, // Interface
1998           gw, // Gateway
1999           egress_if->bwCurrent.costs // Cost
2000           );
2001
2002       egress_if = egress_if->next;
2003     }
2004   }
2005
2006   /* olsr */
2007   {
2008     struct gw_container_entry * gwContainer = (olsr_cnf->ip_version == AF_INET) ? current_ipv4_gw : current_ipv6_gw;
2009     struct gateway_entry * gw = !gwContainer ? NULL : gwContainer->gw;
2010     struct olsr_iptunnel_entry * tunnel = !gwContainer ? NULL : gwContainer->tunnel;
2011     struct tc_entry* tc = !gw ? NULL : olsr_lookup_tc_entry(&gw->originator);
2012
2013     struct ipaddr_str originatorStr;
2014     const char * originator = !gw ? IPNONE : olsr_ip_to_string(&originatorStr, &gw->originator);
2015     struct ipaddr_str prefixIpStr;
2016     const char * prefixIPStr = !gw ? IPNONE : olsr_ip_to_string(&prefixIpStr, &gw->external_prefix.prefix);
2017     uint8_t prefix_len = !gw ? 0 : gw->external_prefix.prefix_len;
2018     struct interfaceName * tunnelName = !gw ? NULL : find_interfaceName(gw);
2019     struct ipaddr_str tunnelGwStr;
2020     const char * tunnelGw = !tunnel ? IPNONE : olsr_ip_to_string(&tunnelGwStr, &tunnel->target);
2021     bool selected = bestOverallLink.valid && bestOverallLink.isOlsr;
2022
2023     char prefix[strlen(prefixIPStr) + 1 + 3 + 1];
2024     snprintf(prefix, sizeof(prefix), "%s/%d", prefixIPStr, prefix_len);
2025
2026     fprintf(fp, fmt_values, //
2027         selected ? "*" : " ", // selected
2028         originator, // Originator
2029         !gw ? MASKNONE : prefix, // Prefix IP
2030         !gw ? 0 : gw->uplink, // Uplink
2031         !gw ? 0 : gw->downlink, // Downlink
2032         (!gw || !tc) ? ROUTE_COST_BROKEN : tc->path_cost, // PathCost
2033         "olsr", // Type
2034         !tunnelName ? "none" : tunnelName->name, // Interface
2035         tunnelGw, // Gateway
2036         !gw ? INT64_MAX : gw->path_cost // Cost
2037       );
2038   }
2039
2040   fclose(fp);
2041 }
2042
2043 /**
2044  * Report a new gateway with its most relevant parameters in the syslog
2045  */
2046 static void reportNewGateway(void) {
2047   if (!bestOverallLink.valid) {
2048     /* best overall link is invalid (none) */
2049     olsr_syslog(OLSR_LOG_INFO, "New gateway selected: none");
2050     return;
2051   }
2052
2053   if (!bestOverallLink.isOlsr) {
2054     /* best overall link is an egress interface */
2055     struct ipaddr_str gwStr;
2056     const char * gw = !bestOverallLink.link.egress->bwCurrent.gatewaySet ? //
2057         NULL : //
2058         olsr_ip_to_string(&gwStr, &bestOverallLink.link.egress->bwCurrent.gateway);
2059
2060     olsr_syslog(OLSR_LOG_INFO, "New gateway selected: %s %s%s%swith uplink/downlink/pathcost = %u/%u/%u", //
2061         bestOverallLink.link.egress->name, //
2062         !gw ? "" : "via ", //
2063         !gw ? "" : gwStr.buf, //
2064         !gw ? "" : " ", //
2065         bestOverallLink.link.egress->bwCurrent.egressUk, //
2066         bestOverallLink.link.egress->bwCurrent.egressDk, //
2067         bestOverallLink.link.egress->bwCurrent.path_cost);
2068     return;
2069   }
2070
2071   /* best overall link is an olsr (tunnel) interface */
2072   {
2073     struct tc_entry* tc = olsr_lookup_tc_entry(&bestOverallLink.link.olsr->originator);
2074
2075     char ifNameBuf[IFNAMSIZ];
2076     const char * ifName = if_indextoname(bestOverallLink.olsrTunnelIfIndex, ifNameBuf);
2077
2078     struct ipaddr_str gwStr;
2079     const char * gw = olsr_ip_to_string(&gwStr, &bestOverallLink.link.olsr->originator);
2080
2081     olsr_syslog(OLSR_LOG_INFO, "New gateway selected: %s %s%s%swith uplink/downlink/pathcost = %u/%u/%u", //
2082         !ifName ? "none" : ifName, //
2083         !gw ? "" : "via ", //
2084         !gw ? "" : gwStr.buf, //
2085         !gw ? "" : " ", //
2086         bestOverallLink.link.olsr->uplink, //
2087         bestOverallLink.link.olsr->downlink, //
2088         !tc ? ROUTE_COST_BROKEN : tc->path_cost);
2089   }
2090 }
2091
2092 /**
2093  * Process changes that are relevant to egress interface: changes to the
2094  * egress interfaces themselves and to the smart gateway that is chosen by olsrd
2095  *
2096  * @param egressChanged true when an egress interface changed
2097  * @param olsrChanged true when the smart gateway changed
2098  * @param phase the phase of the change (startup/runtime/shutdown)
2099  */
2100 void doRoutesMultiGw(bool egressChanged, bool olsrChanged, enum sgw_multi_change_phase phase) {
2101   bool bestEgressChanged = false;
2102   bool bestOverallChanged = false;
2103   bool force = MSGW_ROUTE_FORCED(phase);
2104
2105   assert( //
2106       (phase == GW_MULTI_CHANGE_PHASE_STARTUP) || //
2107       (phase == GW_MULTI_CHANGE_PHASE_RUNTIME) || //
2108       (phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN));
2109
2110   if (!egressChanged && !olsrChanged && !force) {
2111     goto out;
2112   }
2113
2114   assert(multi_gateway_mode());
2115
2116   if (egressChanged || force) {
2117     bestEgressChanged = determineBestEgressLink(phase);
2118     configureEgressLinkRoutes(phase);
2119   }
2120
2121   if (olsrChanged || bestEgressChanged || force) {
2122     bestOverallChanged = determineBestOverallLink(phase);
2123   }
2124
2125   if (!bestEgressChanged && !bestOverallChanged && !force) {
2126     goto out;
2127   }
2128
2129   if (bestOverallChanged || force) {
2130     setupDefaultGatewayOverrideRoutes(phase);
2131   }
2132
2133   if (bestEgressChanged || force) {
2134     configureBestEgressLinkRoute(phase);
2135   }
2136
2137   if (bestOverallChanged || force) {
2138     reportNewGateway();
2139   }
2140
2141   writeProgramStatusFile(phase);
2142
2143   out: if (egressChanged) {
2144     /* clear the 'changed' flags of egress interfaces */
2145     struct sgw_egress_if * egress_if = olsr_cnf->smart_gw_egress_interfaces;
2146     while (egress_if) {
2147       egress_if->upChanged = false;
2148
2149       egress_if->bwCostsChanged = false;
2150       egress_if->bwNetworkChanged = false;
2151       egress_if->bwGatewayChanged = false;
2152       egress_if->bwChanged = false;
2153
2154       egress_if = egress_if->next;
2155     }
2156   }
2157 }
2158
2159 #endif /* __linux__ */