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