sgw: do not prematurely exit doRoutesMultiGw
[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     /* Initialise the egress interfaces */
703     /* setup the egress interface name/mark pairs */
704     i = 0;
705     egressif = olsr_cnf->smart_gw_egress_interfaces;
706     while (egressif) {
707       egressif->if_index = if_nametoindex(egressif->name);
708
709       egressif->tableNr = olsr_cnf->smart_gw_offset_tables + 1 + i;
710       egressif->ruleNr = olsr_cnf->smart_gw_offset_rules + olsr_cnf->smart_gw_egress_interfaces_count + nrOlsrIfs + 1 + i;
711       egressif->bypassRuleNr = olsr_cnf->smart_gw_offset_rules + i;
712
713       egressif->upPrevious = egressif->upCurrent = olsr_if_isup(egressif->name);
714       egressif->upChanged = (egressif->upPrevious != egressif->upCurrent);
715
716       egressBwClear(&egressif->bwPrevious, egressif->upPrevious);
717       egressBwClear(&egressif->bwCurrent, egressif->upCurrent);
718       egressif->bwCostsChanged = egressBwCostsChanged(egressif);
719       egressif->bwNetworkChanged = egressBwNetworkChanged(egressif);
720       egressif->bwGatewayChanged = egressBwGatewayChanged(egressif);
721       egressif->bwChanged = egressBwChanged(egressif);
722
723       egressif->inEgressFile = false;
724
725       egressif = egressif->next;
726       i++;
727     }
728     assert(i == olsr_cnf->smart_gw_egress_interfaces_count);
729
730     /* setup the SGW tunnel name/mark pairs */
731     sgwTunnel4InterfaceNames = olsr_malloc(sizeof(struct interfaceName) * olsr_cnf->smart_gw_use_count, "sgwTunnel4InterfaceNames");
732     sgwTunnel6InterfaceNames = olsr_malloc(sizeof(struct interfaceName) * olsr_cnf->smart_gw_use_count, "sgwTunnel6InterfaceNames");
733     for (i = 0; i < olsr_cnf->smart_gw_use_count; i++) {
734       struct interfaceName * ifn = &sgwTunnel4InterfaceNames[i];
735       uint32_t tableNr = olsr_cnf->smart_gw_offset_tables + 1 + olsr_cnf->smart_gw_egress_interfaces_count + i;
736       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;
737
738       ifn->gw = NULL;
739       ifn->tableNr = tableNr;
740       ifn->ruleNr = ruleNr;
741       ifn->bypassRuleNr = 0;
742       snprintf(&ifn->name[0], sizeof(ifn->name), "tnl_4%03u", ifn->tableNr);
743
744       ifn = &sgwTunnel6InterfaceNames[i];
745       ifn->gw = NULL;
746       ifn->tableNr = tableNr;
747       ifn->ruleNr = ruleNr;
748       ifn->bypassRuleNr = 0;
749       snprintf(&ifn->name[0], sizeof(ifn->name), "tnl_6%03u", ifn->tableNr);
750     }
751   }
752
753   current_ipv4_gw = NULL;
754   current_ipv6_gw = NULL;
755
756   gw_handler = NULL;
757
758   refresh_smartgw_netmask();
759
760   /* initialize default gateway handler */
761   gw_handler = &gw_def_handler;
762   gw_handler->init();
763
764
765   /*
766    * There appears to be a kernel bug in some kernels (at least in the 3.0
767    * Debian Squeeze kernel, but not in the Fedora 17 kernels) around
768    * initialising the IPIP server tunnel (loading the IPIP module), so we retry
769    * a few times before giving up
770    */
771   while (retries-- > 0) {
772     if (!olsr_os_init_iptunnel(server_tunnel_name())) {
773       retries = 5;
774       break;
775     }
776
777     olsr_printf(0, "Could not initialise the IPIP server tunnel, retrying %d more times\n", retries);
778   }
779   if (retries <= 0) {
780     return 1;
781   }
782
783   return 0;
784 }
785
786 /**
787  * Startup gateway system
788  */
789 int olsr_startup_gateways(void) {
790   bool ok = true;
791
792   if (!multi_gateway_mode()) {
793     olsr_add_ifchange_handler(smartgw_tunnel_monitor);
794     return 0;
795   }
796
797   ok = ok && multiGwRulesGeneric(true);
798   ok = ok && multiGwRulesSgwServerTunnel(true);
799   ok = ok && multiGwRulesOlsrInterfaces(true);
800   ok = ok && multiGwRulesEgressInterfaces(true);
801   ok = ok && multiGwRulesSgwTunnels(true);
802   if (!ok) {
803     olsr_printf(0, "Could not setup multi-gateway iptables and ip rules\n");
804     olsr_shutdown_gateways();
805     return 1;
806   }
807
808   startEgressFile();
809   doRoutesMultiGw(true, false, GW_MULTI_CHANGE_PHASE_STARTUP);
810
811   olsr_add_ifchange_handler(smartgw_tunnel_monitor);
812
813   /* Check egress interfaces up status to compensate for a race: the interfaces
814    * can change status between initialising their data structures and
815    * registering the tunnel monitor */
816   {
817     struct sgw_egress_if * egress_if = olsr_cnf->smart_gw_egress_interfaces;
818     while (egress_if) {
819       bool upCurrent = olsr_if_isup(egress_if->name);
820
821       if (upCurrent != egress_if->upCurrent) {
822         int index = upCurrent ? (int) if_nametoindex(egress_if->name) : egress_if->if_index;
823         enum olsr_ifchg_flag flag = upCurrent ? IFCHG_IF_ADD : IFCHG_IF_REMOVE;
824         smartgw_tunnel_monitor(index, NULL, flag);
825       }
826
827       egress_if = egress_if->next;
828     }
829   }
830
831   if (olsr_cnf->smart_gw_takedown_percentage > 0) {
832     /* start gateway takedown timer */
833     olsr_set_timer(&gw_takedown_timer, olsr_cnf->smart_gw_period, 0, true, &gw_takedown_timer_callback, NULL, 0);
834   }
835
836   return 0;
837 }
838
839 /**
840  * Shutdown gateway tunnel system
841  */
842 void olsr_shutdown_gateways(void) {
843   if (!multi_gateway_mode()) {
844     olsr_remove_ifchange_handler(smartgw_tunnel_monitor);
845     return;
846   }
847
848   if (olsr_cnf->smart_gw_takedown_percentage > 0) {
849     /* stop gateway takedown timer */
850     olsr_stop_timer(gw_takedown_timer);
851     gw_takedown_timer = NULL;
852   }
853
854   olsr_remove_ifchange_handler(smartgw_tunnel_monitor);
855
856   stopEgressFile();
857   {
858     struct sgw_egress_if * egress_if = olsr_cnf->smart_gw_egress_interfaces;
859     while (egress_if) {
860       egress_if->upPrevious = egress_if->upCurrent;
861       egress_if->upCurrent = false;
862       egress_if->upChanged = (egress_if->upPrevious != egress_if->upCurrent);
863
864       egress_if->bwPrevious = egress_if->bwCurrent;
865       egressBwClear(&egress_if->bwCurrent, egress_if->upCurrent);
866       egress_if->bwCostsChanged = egressBwCostsChanged(egress_if);
867       egress_if->bwNetworkChanged = egressBwNetworkChanged(egress_if);
868       egress_if->bwGatewayChanged = egressBwGatewayChanged(egress_if);
869       egress_if->bwChanged = egressBwChanged(egress_if);
870
871       egress_if->inEgressFile = false;
872
873       egress_if = egress_if->next;
874     }
875   }
876   doRoutesMultiGw(true, false, GW_MULTI_CHANGE_PHASE_SHUTDOWN);
877
878   (void)multiGwRulesSgwTunnels(false);
879   (void)multiGwRulesEgressInterfaces(false);
880   (void)multiGwRulesOlsrInterfaces(false);
881   (void)multiGwRulesSgwServerTunnel(false);
882   (void)multiGwRulesGeneric(false);
883 }
884
885 /**
886  * Cleanup gateway tunnel system
887  */
888 void olsr_cleanup_gateways(void) {
889   struct gateway_entry * tree_gw;
890   struct gw_container_entry * gw;
891
892   /* remove all gateways in the gateway tree that are not the active gateway */
893   OLSR_FOR_ALL_GATEWAY_ENTRIES(tree_gw) {
894     if ((tree_gw != olsr_get_inet_gateway(false)) && (tree_gw != olsr_get_inet_gateway(true))) {
895       olsr_delete_gateway_tree_entry(tree_gw, FORCE_DELETE_GW_ENTRY, true);
896     }
897   } OLSR_FOR_ALL_GATEWAY_ENTRIES_END(tree_gw)
898
899   /* remove all active IPv4 gateways (should be at most 1 now) */
900   OLSR_FOR_ALL_GWS(&gw_list_ipv4.head, gw) {
901     if (gw && gw->gw) {
902       olsr_delete_gateway_entry(&gw->gw->originator, FORCE_DELETE_GW_ENTRY, true);
903     }
904   }
905   OLSR_FOR_ALL_GWS_END(gw);
906
907   /* remove all active IPv6 gateways (should be at most 1 now) */
908   OLSR_FOR_ALL_GWS(&gw_list_ipv6.head, gw) {
909     if (gw && gw->gw) {
910       olsr_delete_gateway_entry(&gw->gw->originator, FORCE_DELETE_GW_ENTRY, true);
911     }
912   }
913   OLSR_FOR_ALL_GWS_END(gw);
914
915   /* there should be no more gateways */
916   assert(!avl_walk_first(&gateway_tree));
917   assert(!current_ipv4_gw);
918   assert(!current_ipv6_gw);
919
920   olsr_os_cleanup_iptunnel(server_tunnel_name());
921
922   assert(gw_handler);
923   gw_handler->cleanup();
924   gw_handler = NULL;
925
926   if (sgwTunnel4InterfaceNames) {
927     free(sgwTunnel4InterfaceNames);
928     sgwTunnel4InterfaceNames = NULL;
929   }
930   if (sgwTunnel6InterfaceNames) {
931     free(sgwTunnel6InterfaceNames);
932     sgwTunnel6InterfaceNames = NULL;
933   }
934
935   olsr_gw_list_cleanup(&gw_list_ipv6);
936   olsr_gw_list_cleanup(&gw_list_ipv4);
937   olsr_free_cookie(gw_container_entry_mem_cookie);
938   olsr_free_cookie(gateway_entry_mem_cookie);
939 }
940
941 /**
942  * Triggers the first lookup of a gateway.
943  */
944 void olsr_trigger_inetgw_startup(void) {
945   assert(gw_handler);
946   gw_handler->startup();
947 }
948
949 /**
950  * Print debug information about gateway entries
951  */
952 #ifndef NODEBUG
953 void olsr_print_gateway_entries(void) {
954   struct ipaddr_str buf;
955   struct gateway_entry *gw;
956   const int addrsize = olsr_cnf->ip_version == AF_INET ? (INET_ADDRSTRLEN - 1) : (INET6_ADDRSTRLEN - 1);
957
958   OLSR_PRINTF(0, "\n--- %s ---------------------------------------------------- GATEWAYS\n\n", olsr_wallclock_string());
959   OLSR_PRINTF(0, "%-*s %-6s %-9s %-9s %s\n",
960       addrsize, "IP address", "Type", "Uplink", "Downlink", olsr_cnf->ip_version == AF_INET ? "" : "External Prefix");
961
962   OLSR_FOR_ALL_GATEWAY_ENTRIES(gw) {
963     OLSR_PRINTF(0, "%-*s %s%c%s%c%c %-9u %-9u %s\n",
964         addrsize,
965         olsr_ip_to_string(&buf, &gw->originator),
966         gw->ipv4nat ? "" : "   ",
967         gw->ipv4 ? '4' : ' ',
968         gw->ipv4nat ? "(N)" : "",
969         (gw->ipv4 && gw->ipv6) ? ',' : ' ',
970         gw->ipv6 ? '6' : ' ',
971         gw->uplink,
972         gw->downlink,
973         gw->external_prefix.prefix_len == 0 ? "" : olsr_ip_prefix_to_string(&gw->external_prefix));
974   } OLSR_FOR_ALL_GATEWAY_ENTRIES_END(gw)
975 }
976 #endif /* NODEBUG */
977
978 /*
979  * Tx Path Interface
980  */
981
982 /**
983  * Apply the smart gateway modifications to an outgoing HNA
984  *
985  * @param mask pointer to netmask of the HNA
986  * @param prefixlen of the HNA
987  */
988 void olsr_modifiy_inetgw_netmask(union olsr_ip_addr *mask, int prefixlen) {
989   uint8_t *ptr = hna_mask_to_hna_pointer(mask, prefixlen);
990
991   /* copy the current settings for uplink/downlink into the mask */
992   memcpy(ptr, &smart_gateway_netmask, sizeof(smart_gateway_netmask) - prefixlen / 8);
993   if (olsr_cnf->has_ipv4_gateway) {
994     ptr[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV4;
995
996     if (olsr_cnf->smart_gw_uplink_nat) {
997       ptr[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV4_NAT;
998     }
999   }
1000   if (olsr_cnf->has_ipv6_gateway) {
1001     ptr[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV6;
1002   }
1003   if (!olsr_cnf->has_ipv6_gateway || prefixlen != ipv6_internet_route.prefix_len) {
1004     ptr[GW_HNA_FLAGS] &= ~GW_HNA_FLAG_IPV6PREFIX;
1005   }
1006 }
1007
1008 /*
1009  * SgwDynSpeed Plugin Interface
1010  */
1011
1012 /**
1013  * Setup the gateway netmask
1014  */
1015 void refresh_smartgw_netmask(void) {
1016   uint8_t *ip;
1017
1018   /* clear the mask */
1019   memset(&smart_gateway_netmask, 0, sizeof(smart_gateway_netmask));
1020
1021   if (olsr_cnf->smart_gw_active) {
1022     ip = (uint8_t *) &smart_gateway_netmask;
1023
1024     ip[GW_HNA_FLAGS] |= GW_HNA_FLAG_LINKSPEED;
1025     ip[GW_HNA_DOWNLINK] = serialize_gw_speed(olsr_cnf->smart_gw_downlink);
1026     ip[GW_HNA_UPLINK] = serialize_gw_speed(olsr_cnf->smart_gw_uplink);
1027
1028     if (olsr_cnf->ip_version == AF_INET6 && olsr_cnf->smart_gw_prefix.prefix_len > 0) {
1029       ip[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV6PREFIX;
1030       ip[GW_HNA_V6PREFIXLEN] = olsr_cnf->smart_gw_prefix.prefix_len;
1031       memcpy(&ip[GW_HNA_V6PREFIX], &olsr_cnf->smart_gw_prefix.prefix, 8);
1032     }
1033   }
1034 }
1035
1036 /*
1037  * TC/SPF/HNA Interface
1038  */
1039
1040 /**
1041  * Checks if a HNA prefix/netmask combination is a smart gateway
1042  *
1043  * @param prefix
1044  * @param mask
1045  * @return true if is a valid smart gateway HNA, false otherwise
1046  */
1047 bool olsr_is_smart_gateway(struct olsr_ip_prefix *prefix, union olsr_ip_addr *mask) {
1048   uint8_t *ptr;
1049
1050   if (!is_prefix_inetgw(prefix)) {
1051     return false;
1052   }
1053
1054   ptr = hna_mask_to_hna_pointer(mask, prefix->prefix_len);
1055   return ptr[GW_HNA_PAD] == 0 && ptr[GW_HNA_FLAGS] != 0;
1056 }
1057
1058 /**
1059  * Update a gateway_entry based on a HNA
1060  *
1061  * @param originator ip of the source of the HNA
1062  * @param mask netmask of the HNA
1063  * @param prefixlen of the HNA
1064  * @param seqno the sequence number of the HNA
1065  */
1066 void olsr_update_gateway_entry(union olsr_ip_addr *originator, union olsr_ip_addr *mask, int prefixlen, uint16_t seqno) {
1067   struct gw_container_entry * new_gw_in_list;
1068   uint8_t *ptr;
1069   int64_t prev_path_cost = 0;
1070   struct gateway_entry *gw = node2gateway(avl_find(&gateway_tree, originator));
1071
1072   if (!gw) {
1073     gw = olsr_cookie_malloc(gateway_entry_mem_cookie);
1074     gw->originator = *originator;
1075     gw->node.key = &gw->originator;
1076
1077     avl_insert(&gateway_tree, &gw->node, AVL_DUP_NO);
1078   } else if (olsr_seqno_diff(seqno, gw->seqno) <= 0) {
1079     /* ignore older HNAs */
1080     return;
1081   }
1082
1083   /* keep new HNA seqno */
1084   gw->seqno = seqno;
1085
1086   ptr = hna_mask_to_hna_pointer(mask, prefixlen);
1087   if ((ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_LINKSPEED) != 0) {
1088     gw->uplink = deserialize_gw_speed(ptr[GW_HNA_UPLINK]);
1089     gw->downlink = deserialize_gw_speed(ptr[GW_HNA_DOWNLINK]);
1090   } else {
1091     gw->uplink = 0;
1092     gw->downlink = 0;
1093   }
1094
1095   gw->ipv4 = (ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV4) != 0;
1096   gw->ipv4nat = (ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV4_NAT) != 0;
1097   gw->ipv6 = false;
1098
1099   if (olsr_cnf->ip_version == AF_INET6) {
1100     gw->ipv6 = (ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV6) != 0;
1101
1102     /* do not reset prefixlength for ::ffff:0:0 HNAs */
1103     if (prefixlen == ipv6_internet_route.prefix_len) {
1104       memset(&gw->external_prefix, 0, sizeof(gw->external_prefix));
1105
1106       if ((ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV6PREFIX) != 0
1107           && memcmp(mask->v6.s6_addr, &ipv6_internet_route.prefix, olsr_cnf->ipsize) == 0) {
1108         /* this is the right prefix (2000::/3), so we can copy the prefix */
1109         gw->external_prefix.prefix_len = ptr[GW_HNA_V6PREFIXLEN];
1110         memcpy(&gw->external_prefix.prefix, &ptr[GW_HNA_V6PREFIX], 8);
1111       }
1112     }
1113   }
1114
1115   /* stop cleanup timer if necessary */
1116   if (gw->cleanup_timer) {
1117     olsr_stop_timer(gw->cleanup_timer);
1118     gw->cleanup_timer = NULL;
1119   }
1120
1121   assert(gw_handler);
1122   prev_path_cost = gw->path_cost;
1123   gw->path_cost = gw_handler->getcosts(gw);
1124
1125   if (prev_path_cost != gw->path_cost) {
1126     /* re-sort the gateway list when costs have changed and when it is an active gateway */
1127     new_gw_in_list = olsr_gw_list_find(&gw_list_ipv4, gw);
1128     if (new_gw_in_list) {
1129       new_gw_in_list = olsr_gw_list_update(&gw_list_ipv4, new_gw_in_list);
1130       assert(new_gw_in_list);
1131     }
1132
1133     new_gw_in_list = olsr_gw_list_find(&gw_list_ipv6, gw);
1134     if (new_gw_in_list) {
1135       new_gw_in_list = olsr_gw_list_update(&gw_list_ipv6, new_gw_in_list);
1136       assert(new_gw_in_list);
1137     }
1138
1139     if (multi_gateway_mode() && //
1140         ((!gw->ipv6 && current_ipv4_gw && current_ipv4_gw->gw == gw) || //
1141          (gw->ipv6 && current_ipv6_gw && current_ipv6_gw->gw == gw)) //
1142         ) {
1143       /* the active gw has changed its costs: re-evaluate egress routes */
1144       doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
1145     }
1146   }
1147
1148   /* call update handler */
1149   assert(gw_handler);
1150   gw_handler->update(gw);
1151 }
1152
1153 /**
1154  * Delete a gateway based on the originator IP and the prefixlength of a HNA.
1155  * Should only be called if prefix is a smart_gw prefix or if node is removed
1156  * from TC set.
1157  *
1158  * @param originator
1159  * @param prefixlen
1160  * @param immediate when set to true then the gateway is removed from the
1161  * gateway tree immediately, else it is removed on a delayed schedule.
1162  */
1163 void olsr_delete_gateway_entry(union olsr_ip_addr *originator, uint8_t prefixlen, bool immediate) {
1164   olsr_delete_gateway_tree_entry(node2gateway(avl_find(&gateway_tree, originator)), prefixlen, immediate);
1165 }
1166
1167 /**
1168  * Delete a gateway entry .
1169  *
1170  * @param gw a gateway entry from the gateway tree
1171  * @param prefixlen
1172  * @param immediate when set to true then the gateway is removed from the
1173  * gateway tree immediately, else it is removed on a delayed schedule.
1174  */
1175 static void olsr_delete_gateway_tree_entry(struct gateway_entry * gw, uint8_t prefixlen, bool immediate) {
1176   bool change = false;
1177
1178   if (!gw) {
1179     return;
1180   }
1181
1182   if (immediate && gw->cleanup_timer) {
1183     /* stop timer if we have to remove immediately */
1184     olsr_stop_timer(gw->cleanup_timer);
1185     gw->cleanup_timer = NULL;
1186   }
1187
1188   if (gw->cleanup_timer == NULL || gw->ipv4 || gw->ipv6) {
1189     /* the gw  is not scheduled for deletion */
1190
1191     if (olsr_cnf->ip_version == AF_INET && prefixlen == 0) {
1192       change = gw->ipv4;
1193       gw->ipv4 = false;
1194       gw->ipv4nat = false;
1195     } else if (olsr_cnf->ip_version == AF_INET6 && prefixlen == ipv6_internet_route.prefix_len) {
1196       change = gw->ipv6;
1197       gw->ipv6 = false;
1198     } else if (olsr_cnf->ip_version == AF_INET6 && prefixlen == ipv6_mappedv4_route.prefix_len) {
1199       change = gw->ipv4;
1200       gw->ipv4 = false;
1201       gw->ipv4nat = false;
1202     }
1203
1204     if (prefixlen == FORCE_DELETE_GW_ENTRY || !(gw->ipv4 || gw->ipv6)) {
1205       struct gw_container_entry * gw_in_list;
1206
1207       /* prevent this gateway from being chosen as the new gateway */
1208       gw->ipv4 = false;
1209       gw->ipv4nat = false;
1210       gw->ipv6 = false;
1211
1212       /* handle gateway loss */
1213       assert(gw_handler);
1214       gw_handler->delete(gw);
1215
1216       /* cleanup gateway if necessary */
1217       gw_in_list = olsr_gw_list_find(&gw_list_ipv4, gw);
1218       if (gw_in_list) {
1219         if (current_ipv4_gw && current_ipv4_gw->gw == gw) {
1220           olsr_os_inetgw_tunnel_route(current_ipv4_gw->tunnel->if_index, true, false, olsr_cnf->rt_table_tunnel);
1221           current_ipv4_gw = NULL;
1222         }
1223
1224         if (gw_in_list->tunnel) {
1225           struct interfaceName * ifn = find_interfaceName(gw_in_list->gw);
1226           if (ifn) {
1227             olsr_os_inetgw_tunnel_route(gw_in_list->tunnel->if_index, true, false, ifn->tableNr);
1228           }
1229           olsr_os_del_ipip_tunnel(gw_in_list->tunnel);
1230           set_unused_iptunnel_name(gw_in_list->gw);
1231           gw_in_list->tunnel = NULL;
1232         }
1233
1234         gw_in_list->gw = NULL;
1235         gw_in_list = olsr_gw_list_remove(&gw_list_ipv4, gw_in_list);
1236         olsr_cookie_free(gw_container_entry_mem_cookie, gw_in_list);
1237       }
1238
1239       gw_in_list = olsr_gw_list_find(&gw_list_ipv6, gw);
1240       if (gw_in_list) {
1241         if (current_ipv6_gw && current_ipv6_gw->gw == gw) {
1242           olsr_os_inetgw_tunnel_route(current_ipv6_gw->tunnel->if_index, false, false, olsr_cnf->rt_table_tunnel);
1243           current_ipv6_gw = NULL;
1244         }
1245
1246         if (gw_in_list->tunnel) {
1247           struct interfaceName * ifn = find_interfaceName(gw_in_list->gw);
1248           if (ifn) {
1249             olsr_os_inetgw_tunnel_route(gw_in_list->tunnel->if_index, false, false, ifn->tableNr);
1250           }
1251           olsr_os_del_ipip_tunnel(gw_in_list->tunnel);
1252           set_unused_iptunnel_name(gw_in_list->gw);
1253           gw_in_list->tunnel = NULL;
1254         }
1255
1256         gw_in_list->gw = NULL;
1257         gw_in_list = olsr_gw_list_remove(&gw_list_ipv6, gw_in_list);
1258         olsr_cookie_free(gw_container_entry_mem_cookie, gw_in_list);
1259       }
1260
1261       if (!immediate) {
1262         /* remove gateway entry on a delayed schedule */
1263         olsr_set_timer(&gw->cleanup_timer, GW_CLEANUP_INTERVAL, 0, false, cleanup_gateway_handler, gw, NULL);
1264       } else {
1265         cleanup_gateway_handler(gw);
1266       }
1267
1268       /* when the current gateway was deleted, then immediately choose a new gateway */
1269       if (!current_ipv4_gw || !current_ipv6_gw) {
1270         assert(gw_handler);
1271         gw_handler->choose(!current_ipv4_gw, !current_ipv6_gw);
1272       }
1273
1274     } else if (change) {
1275       assert(gw_handler);
1276       gw_handler->update(gw);
1277     }
1278   }
1279 }
1280
1281 /**
1282  * Triggers a check if the one of the gateways have been lost or has an
1283  * ETX = infinity
1284  */
1285 void olsr_trigger_gatewayloss_check(void) {
1286   bool ipv4 = false;
1287   bool ipv6 = false;
1288
1289   if (current_ipv4_gw && current_ipv4_gw->gw) {
1290     struct tc_entry *tc = olsr_lookup_tc_entry(&current_ipv4_gw->gw->originator);
1291     ipv4 = (tc == NULL || tc->path_cost == ROUTE_COST_BROKEN);
1292   }
1293   if (current_ipv6_gw && current_ipv6_gw->gw) {
1294     struct tc_entry *tc = olsr_lookup_tc_entry(&current_ipv6_gw->gw->originator);
1295     ipv6 = (tc == NULL || tc->path_cost == ROUTE_COST_BROKEN);
1296   }
1297
1298   if (ipv4 || ipv6) {
1299     assert(gw_handler);
1300     gw_handler->choose(ipv4, ipv6);
1301   }
1302 }
1303
1304 /*
1305  * Gateway Plugin Functions
1306  */
1307
1308 /**
1309  * Sets a new internet gateway.
1310  *
1311  * @param the chosen gateway
1312  * @param ipv4 set ipv4 gateway
1313  * @param ipv6 set ipv6 gateway
1314  * @return true if an error happened, false otherwise
1315  */
1316 bool olsr_set_inet_gateway(struct gateway_entry * chosen_gw, bool ipv4, bool ipv6) {
1317   struct gateway_entry *new_gw;
1318
1319   ipv4 = ipv4 && (olsr_cnf->ip_version == AF_INET || olsr_cnf->use_niit);
1320   ipv6 = ipv6 && (olsr_cnf->ip_version == AF_INET6);
1321   if (!ipv4 && !ipv6) {
1322     return true;
1323   }
1324
1325   new_gw = node2gateway(avl_find(&gateway_tree, &chosen_gw->originator));
1326   if (!new_gw) {
1327     /* the originator is not in the gateway tree, we can't set it as gateway */
1328     return true;
1329   }
1330
1331   /* handle IPv4 */
1332   if (ipv4 &&
1333       new_gw->ipv4 &&
1334       (!new_gw->ipv4nat || olsr_cnf->smart_gw_allow_nat) &&
1335       (!current_ipv4_gw || current_ipv4_gw->gw != new_gw)) {
1336     /* new gw is different than the current gw */
1337
1338     struct gw_container_entry * new_gw_in_list = olsr_gw_list_find(&gw_list_ipv4, new_gw);
1339     if (new_gw_in_list) {
1340       /* new gw is already in the gw list */
1341       assert(new_gw_in_list->tunnel);
1342       olsr_os_inetgw_tunnel_route(new_gw_in_list->tunnel->if_index, true, true, olsr_cnf->rt_table_tunnel);
1343       current_ipv4_gw = new_gw_in_list;
1344
1345       if (multi_gateway_mode()) {
1346         doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
1347       }
1348     } else {
1349       /* new gw is not yet in the gw list */
1350       char name[IFNAMSIZ];
1351       struct olsr_iptunnel_entry *new_v4gw_tunnel;
1352       struct interfaceName * interfaceName;
1353
1354       if (olsr_gw_list_full(&gw_list_ipv4)) {
1355         /* the list is full: remove the worst active gateway */
1356         struct gw_container_entry* worst = olsr_gw_list_get_worst_entry(&gw_list_ipv4);
1357         assert(worst);
1358
1359         removeGatewayFromList(&gw_list_ipv4, true, worst);
1360       }
1361
1362       get_unused_iptunnel_name(new_gw, name, &interfaceName);
1363       new_v4gw_tunnel = olsr_os_add_ipip_tunnel(&new_gw->originator, true, name);
1364       if (new_v4gw_tunnel) {
1365         if (interfaceName) {
1366           olsr_os_inetgw_tunnel_route(new_v4gw_tunnel->if_index, true, true, interfaceName->tableNr);
1367         }
1368         olsr_os_inetgw_tunnel_route(new_v4gw_tunnel->if_index, true, true, olsr_cnf->rt_table_tunnel);
1369
1370         new_gw_in_list = olsr_cookie_malloc(gw_container_entry_mem_cookie);
1371         new_gw_in_list->gw = new_gw;
1372         new_gw_in_list->tunnel = new_v4gw_tunnel;
1373         current_ipv4_gw = olsr_gw_list_add(&gw_list_ipv4, new_gw_in_list);
1374
1375         if (multi_gateway_mode()) {
1376           doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
1377         }
1378       } else {
1379         /* adding the tunnel failed, we try again in the next cycle */
1380         set_unused_iptunnel_name(new_gw);
1381         ipv4 = false;
1382       }
1383     }
1384   }
1385
1386   /* handle IPv6 */
1387   if (ipv6 &&
1388       new_gw->ipv6 &&
1389       (!current_ipv6_gw || current_ipv6_gw->gw != new_gw)) {
1390     /* new gw is different than the current gw */
1391
1392         struct gw_container_entry * new_gw_in_list = olsr_gw_list_find(&gw_list_ipv6, new_gw);
1393     if (new_gw_in_list) {
1394       /* new gw is already in the gw list */
1395       assert(new_gw_in_list->tunnel);
1396       olsr_os_inetgw_tunnel_route(new_gw_in_list->tunnel->if_index, true, true, olsr_cnf->rt_table_tunnel);
1397       current_ipv6_gw = new_gw_in_list;
1398
1399       if (multi_gateway_mode()) {
1400         doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
1401       }
1402     } else {
1403       /* new gw is not yet in the gw list */
1404       char name[IFNAMSIZ];
1405       struct olsr_iptunnel_entry *new_v6gw_tunnel;
1406       struct interfaceName * interfaceName;
1407
1408       if (olsr_gw_list_full(&gw_list_ipv6)) {
1409         /* the list is full: remove the worst active gateway */
1410         struct gw_container_entry* worst = olsr_gw_list_get_worst_entry(&gw_list_ipv6);
1411         assert(worst);
1412
1413         removeGatewayFromList(&gw_list_ipv6, false, worst);
1414       }
1415
1416       get_unused_iptunnel_name(new_gw, name, &interfaceName);
1417       new_v6gw_tunnel = olsr_os_add_ipip_tunnel(&new_gw->originator, false, name);
1418       if (new_v6gw_tunnel) {
1419         if (interfaceName) {
1420           olsr_os_inetgw_tunnel_route(new_v6gw_tunnel->if_index, false, true, interfaceName->tableNr);
1421         }
1422         olsr_os_inetgw_tunnel_route(new_v6gw_tunnel->if_index, false, true, olsr_cnf->rt_table_tunnel);
1423
1424         new_gw_in_list = olsr_cookie_malloc(gw_container_entry_mem_cookie);
1425         new_gw_in_list->gw = new_gw;
1426         new_gw_in_list->tunnel = new_v6gw_tunnel;
1427         current_ipv6_gw = olsr_gw_list_add(&gw_list_ipv6, new_gw_in_list);
1428
1429         if (multi_gateway_mode()) {
1430           doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
1431         }
1432       } else {
1433         /* adding the tunnel failed, we try again in the next cycle */
1434         set_unused_iptunnel_name(new_gw);
1435         ipv6 = false;
1436       }
1437     }
1438   }
1439
1440   return !ipv4 && !ipv6;
1441 }
1442
1443 /**
1444  * @param ipv6 if set to true then the IPv6 gateway is returned, otherwise the IPv4
1445  * gateway is returned
1446  * @return a pointer to the gateway_entry of the current ipv4 internet gw or
1447  * NULL if not set.
1448  */
1449 struct gateway_entry *olsr_get_inet_gateway(bool ipv6) {
1450         if (ipv6) {
1451                 return current_ipv6_gw ? current_ipv6_gw->gw : NULL;
1452         }
1453
1454         return current_ipv4_gw ? current_ipv4_gw->gw : NULL;
1455 }
1456
1457 /*
1458  * Process Egress Changes
1459  */
1460
1461 #define MSGW_ROUTE_ADD_ALLOWED(phase)   ((phase == GW_MULTI_CHANGE_PHASE_STARTUP ) || (phase == GW_MULTI_CHANGE_PHASE_RUNTIME ))
1462 #define MSGW_ROUTE_ADD_FORCED(phase)    ( phase == GW_MULTI_CHANGE_PHASE_STARTUP )
1463 #define MSGW_ROUTE_DEL_ALLOWED(phase)   ((phase == GW_MULTI_CHANGE_PHASE_RUNTIME ) || (phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN))
1464 #define MSGW_ROUTE_DEL_FORCED(phase)    ( phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN)
1465 #define MSGW_ROUTE_FORCED(phase)        ((phase == GW_MULTI_CHANGE_PHASE_STARTUP ) || (phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN))
1466
1467 /**
1468  * Determine best egress link.
1469  * The list of egress interface is ordered on priority (the declaration order),
1470  * so the function will - for multiple egress links with the same costs - set the
1471  * best egress interface to the first declared one of those.
1472  * When there is no best egress interface (that is up) then the function will
1473  * set the best egress interface to NULL.
1474  *
1475  * @param phase the phase of the change (startup/runtime/shutdown)
1476  * @return true when the best egress link changed or when any of its relevant
1477  * parameters has changed
1478  */
1479 static bool determineBestEgressLink(enum sgw_multi_change_phase phase) {
1480   struct sgw_egress_if * bestEgress = olsr_cnf->smart_gw_egress_interfaces;
1481
1482   if (phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN) {
1483     bestEgress = NULL;
1484   } else {
1485     struct sgw_egress_if * egress_if = bestEgress;
1486     if (egress_if) {
1487       egress_if = egress_if->next;
1488     }
1489     while (egress_if) {
1490       if (egress_if->upCurrent && (egress_if->bwCurrent.costs < bestEgress->bwCurrent.costs)) {
1491         bestEgress = egress_if;
1492       }
1493
1494       egress_if = egress_if->next;
1495     }
1496
1497     if (bestEgress && (!bestEgress->upCurrent || (bestEgress->bwCurrent.costs == INT64_MAX))) {
1498       bestEgress = NULL;
1499     }
1500   }
1501
1502   bestEgressLinkPrevious = bestEgressLink;
1503   bestEgressLink = bestEgress;
1504
1505   return ((bestEgressLinkPrevious != bestEgressLink) || //
1506       (bestEgressLink && (bestEgressLink->upChanged || bestEgressLink->bwChanged)));
1507 }
1508
1509 /**
1510  * Determine best overall link (choose egress interface over olsrd).
1511  *
1512  * When there is no best overall link, the best overall link will be set to a
1513  * NULL egress interface.
1514  *
1515  * @param phase the phase of the change (startup/runtime/shutdown)
1516  * @return true when the best egress link changed or when any of its relevant
1517  * parameters has changed
1518  */
1519 static bool determineBestOverallLink(enum sgw_multi_change_phase phase) {
1520   struct gw_container_entry * gwContainer = (olsr_cnf->ip_version == AF_INET) ? current_ipv4_gw : current_ipv6_gw;
1521   struct gateway_entry * olsrGw = !gwContainer ? NULL : gwContainer->gw;
1522
1523   int64_t egressCosts = !bestEgressLink ? INT64_MAX : bestEgressLink->bwCurrent.costs;
1524   int64_t olsrCosts = !olsrGw ? INT64_MAX : olsrGw->path_cost;
1525   int64_t bestOverallCosts = MIN(egressCosts, olsrCosts);
1526
1527   bestOverallLinkPrevious = bestOverallLink;
1528   if ((bestOverallCosts == INT64_MAX) || (phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN)) {
1529     bestOverallLink.valid = false;
1530     bestOverallLink.isOlsr = false;
1531     bestOverallLink.link.egress = NULL;
1532     bestOverallLink.olsrTunnelIfIndex = 0;
1533   } else if (egressCosts <= olsrCosts) {
1534     bestOverallLink.valid = bestEgressLink;
1535     bestOverallLink.isOlsr = false;
1536     bestOverallLink.link.egress = bestEgressLink;
1537     bestOverallLink.olsrTunnelIfIndex = 0;
1538   } else {
1539     struct olsr_iptunnel_entry * tunnel = !gwContainer ? NULL : gwContainer->tunnel;
1540
1541     bestOverallLink.valid = olsrGw;
1542     bestOverallLink.isOlsr = true;
1543     bestOverallLink.link.olsr = olsrGw;
1544     bestOverallLink.olsrTunnelIfIndex = !tunnel ? 0 : tunnel->if_index;
1545   }
1546
1547   return memcmp(&bestOverallLink, &bestOverallLinkPrevious, sizeof(bestOverallLink));
1548 }
1549
1550 /**
1551  * Program a route (add or remove) through netlink
1552  *
1553  * @param add true to add the route, false to remove it
1554  * @param route the route
1555  * @param linkName the human readable id of the route, used in error reports in
1556  * the syslog
1557  */
1558 static void programRoute(bool add, struct sgw_route_info * route, const char * linkName) {
1559   if (!route || !route->active) {
1560     return;
1561   }
1562
1563   if (olsr_new_netlink_route( //
1564       route->route.family, //
1565       route->route.rttable, //
1566       route->route.flags, //
1567       route->route.scope, //
1568       route->route.if_index, //
1569       route->route.metric, //
1570       route->route.protocol, //
1571       !route->route.srcSet ? NULL : &route->route.srcStore, //
1572       !route->route.gwSet ? NULL : &route->route.gwStore, //
1573       !route->route.dstSet ? NULL : &route->route.dstStore, //
1574       add, //
1575       route->route.del_similar, //
1576       route->route.blackhole //
1577       )) {
1578     olsr_syslog(OLSR_LOG_ERR, "Could not %s a route for the %s %s", !add ? "remove" : "add", !add ? "previous" : "current", linkName);
1579     route->active = false;
1580   } else {
1581     route->active = add;
1582   }
1583 }
1584
1585 /**
1586  * Determine the best overall egress/olsr interface routes.
1587  *
1588  * These are a set of 2 /1 routes to override any default gateway
1589  * routes that are setup through other means such as a DHCP client.
1590  *
1591  * @param routes a pointer to the array of 2 /1 routes where to store the
1592  * newly determined routes
1593  */
1594 static void determineBestOverallLinkRoutes(struct sgw_route_info * routes) {
1595   int ifIndex = 0;
1596   union olsr_ip_addr * gw = NULL;
1597   int i;
1598   if (!bestOverallLink.valid) {
1599     /* there is no current best overall link */
1600   } else if (!bestOverallLink.isOlsr) {
1601     /* current best overall link is an egress interface */
1602     struct sgw_egress_if * egress = bestOverallLink.link.egress;
1603     if (egress) {
1604       ifIndex = egress->if_index;
1605       if (egress->bwCurrent.gatewaySet) {
1606         gw = &egress->bwCurrent.gateway;
1607       }
1608     }
1609   } else {
1610     /* current best overall link is an olsr tunnel interface */
1611     struct gw_container_entry * gwContainer = current_ipv4_gw;
1612     struct olsr_iptunnel_entry * tunnel = !gwContainer ? NULL : gwContainer->tunnel;
1613
1614     if (tunnel) {
1615       ifIndex = tunnel->if_index;
1616     }
1617   }
1618
1619   if (!ifIndex) {
1620     for (i = 0; i < 2; i++) {
1621       routes[i].active = false;
1622     }
1623     return;
1624   }
1625
1626   for (i = 0; i < 2; i++) {
1627     memset(&routes[i], 0, sizeof(routes[i]));
1628     routes[i].active = true;
1629     routes[i].route.family = AF_INET;
1630     routes[i].route.rttable = olsr_cnf->rt_table;
1631     routes[i].route.flags = 0;
1632     routes[i].route.scope = !gw ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
1633     routes[i].route.if_index = ifIndex;
1634     routes[i].route.metric = 0;
1635     routes[i].route.protocol = RTPROT_STATIC;
1636     routes[i].route.srcSet = false;
1637     routes[i].route.gwSet = false;
1638     if (gw) {
1639       routes[i].route.gwSet = true;
1640       routes[i].route.gwStore = *gw;
1641     }
1642     routes[i].route.dstSet = true;
1643     routes[i].route.dstStore = ipv4_slash_1_routes[i];
1644     routes[i].route.del_similar = false;
1645     routes[i].route.blackhole = false;
1646   }
1647 }
1648
1649 /**
1650  * Setup default gateway override routes: a set of 2 /1 routes for the best
1651  * overall link
1652  *
1653  * @param phase the phase of the change (startup/runtime/shutdown)
1654  */
1655 static void setupDefaultGatewayOverrideRoutes(enum sgw_multi_change_phase phase) {
1656   bool force = MSGW_ROUTE_FORCED(phase);
1657   int i;
1658
1659   if (!bestOverallLinkPrevious.valid && !bestOverallLink.valid && !force) {
1660     return;
1661   }
1662
1663   memcpy(&bestOverallLinkPreviousRoutes, &bestOverallLinkRoutes, sizeof(bestOverallLinkPreviousRoutes));
1664
1665   determineBestOverallLinkRoutes(bestOverallLinkRoutes);
1666
1667   for (i = 0; i < 2; i++) {
1668     bool routeChanged = //
1669         (bestOverallLinkPreviousRoutes[i].active != bestOverallLinkRoutes[i].active) || //
1670         memcmp(&bestOverallLinkPreviousRoutes[i].route, &bestOverallLinkRoutes[i].route, sizeof(bestOverallLinkRoutes[i].route));
1671
1672     if ((routeChanged || MSGW_ROUTE_DEL_FORCED(phase)) && MSGW_ROUTE_DEL_ALLOWED(phase)) {
1673       programRoute(false, &bestOverallLinkPreviousRoutes[i], "overall best gateway");
1674     }
1675
1676     if ((routeChanged || MSGW_ROUTE_ADD_FORCED(phase)) && MSGW_ROUTE_ADD_ALLOWED(phase)) {
1677       programRoute(true, &bestOverallLinkRoutes[i], "overall best gateway");
1678     }
1679   }
1680 }
1681
1682 /**
1683  * Determine the best egress interface route.
1684  *
1685  * @param route a pointer to the an route where to store the
1686  * newly determined route
1687  * @param networkRoute true when the route is a network route (not an internet
1688  * route)
1689  * @param if_index the index of the interface that the route is for
1690  * @param gw the gateway for the route
1691  * @param dst the destination for the route
1692  * @param table the routing table for the route
1693  */
1694 static void determineEgressLinkRoute( //
1695     struct sgw_route_info * route, //
1696     bool networkRoute, //
1697     int if_index, //
1698     union olsr_ip_addr * gw, //
1699     struct olsr_ip_prefix * dst, //
1700     int table) {
1701   // default route
1702   // ----: ip route replace|delete blackhole default                          table 90: !egress_if               (1)
1703   // ppp0: ip route replace|delete           default                 dev ppp0 table 90:  egress_if && dst && !gw (2)
1704   // eth1: ip route replace|delete           default via 192.168.0.1 dev eth1 table 90:  egress_if && dst &&  gw (3)
1705
1706   // network route
1707   // eth1: ip route replace|delete to 192.168.0.0/24                 dev eth1 table 90:  egress_if && dst && !gw (2*)
1708
1709   memset(route, 0, sizeof(*route));
1710   if (if_index <= 0) { /* 1 */
1711     route->active = true;
1712     route->route.family = AF_INET;
1713     route->route.rttable = table;
1714     route->route.flags = RTNH_F_ONLINK;
1715     route->route.scope = RT_SCOPE_UNIVERSE;
1716     route->route.if_index = 0;
1717     route->route.metric = 0;
1718     route->route.protocol = RTPROT_STATIC;
1719     route->route.srcSet = false;
1720     route->route.gwSet = false;
1721     route->route.dstSet = false;
1722     if (dst) {
1723       route->route.dstSet = true;
1724       route->route.dstStore = *dst;
1725     }
1726     route->route.del_similar = false;
1727     route->route.blackhole = true;
1728   } else if (dst && !gw) { /* 2 */
1729     route->active = true;
1730     route->route.family = AF_INET;
1731     route->route.rttable = table;
1732     route->route.flags = !networkRoute ? RTNH_F_ONLINK /* 2 */ : 0 /* 2* */;
1733     route->route.scope = RT_SCOPE_LINK;
1734     route->route.if_index = if_index;
1735     route->route.metric = 0;
1736     route->route.protocol = RTPROT_STATIC;
1737     route->route.srcSet = false;
1738     route->route.gwSet = false;
1739     route->route.dstSet = true;
1740     route->route.dstStore = *dst;
1741     route->route.del_similar = false;
1742     route->route.blackhole = false;
1743   } else if (dst && gw) { /* 3 */
1744     route->active = true;
1745     route->route.family = AF_INET;
1746     route->route.rttable = table;
1747     route->route.flags = 0;
1748     route->route.scope = RT_SCOPE_UNIVERSE;
1749     route->route.if_index = if_index;
1750     route->route.metric = 0;
1751     route->route.protocol = RTPROT_STATIC;
1752     route->route.srcSet = false;
1753     route->route.gwSet = true;
1754     route->route.gwStore = *gw;
1755     route->route.dstSet = true;
1756     route->route.dstStore = *dst;
1757     route->route.del_similar = false;
1758     route->route.blackhole = false;
1759   } else {
1760     /* no destination set */
1761     route->active = false;
1762     olsr_syslog(OLSR_LOG_ERR, "No route destination specified in %s", __FUNCTION__);
1763     return;
1764   }
1765 }
1766
1767 /**
1768  * Setup default route for the best egress interface
1769  *
1770  * When there is no best egress link, then a blackhole route is setup to prevent
1771  * looping smart gateway tunnel traffic.
1772  *
1773  * @param phase the phase of the change (startup/runtime/shutdown)
1774  */
1775 static void configureBestEgressLinkRoute(enum sgw_multi_change_phase phase) {
1776   bool force = MSGW_ROUTE_FORCED(phase);
1777
1778   /*
1779    * bestEgressLinkPrevious  bestEgressLink  Action
1780    *                   NULL            NULL  -
1781    *                   NULL               x  add new route
1782    *                      x            NULL  remove old route
1783    *                      x               x  remove old route && add new routes
1784    */
1785
1786   if (!bestEgressLinkPrevious && !bestEgressLink && !force) {
1787     return;
1788   }
1789
1790   memcpy(&bestEgressLinkPreviousRoute, &bestEgressLinkRoute, sizeof(bestEgressLinkPreviousRoute));
1791
1792   determineEgressLinkRoute( //
1793       &bestEgressLinkRoute, // route
1794       false, // networkRoute
1795       !bestEgressLink ? 0 : bestEgressLink->if_index, // if_index
1796       (!bestEgressLink || !bestEgressLink->bwCurrent.gatewaySet) ? NULL : &bestEgressLink->bwCurrent.gateway, // gw
1797       &ipv4_slash_0_route, // dst
1798       olsr_cnf->smart_gw_offset_tables // table
1799       );
1800
1801   {
1802     bool routeChanged = //
1803         (bestEgressLinkPreviousRoute.active != bestEgressLinkRoute.active) || //
1804         memcmp(&bestEgressLinkPreviousRoute.route, &bestEgressLinkRoute.route, sizeof(bestEgressLinkRoute.route));
1805
1806     if ((routeChanged || MSGW_ROUTE_DEL_FORCED(phase)) && MSGW_ROUTE_DEL_ALLOWED(phase)) {
1807       programRoute(false, &bestEgressLinkPreviousRoute, "best egress link");
1808     }
1809
1810     if ((routeChanged || MSGW_ROUTE_ADD_FORCED(phase)) && MSGW_ROUTE_ADD_ALLOWED(phase)) {
1811       programRoute(true, &bestEgressLinkRoute, "best egress link");
1812     }
1813   }
1814 }
1815
1816 /**
1817  * Setup network (when relevant) and default routes for the every egress
1818  * interface
1819  *
1820  * @param phase the phase of the change (startup/runtime/shutdown)
1821  */
1822 static void configureEgressLinkRoutes(enum sgw_multi_change_phase phase) {
1823   bool force = MSGW_ROUTE_FORCED(phase);
1824
1825   /* egress interfaces */
1826   struct sgw_egress_if * egress_if = olsr_cnf->smart_gw_egress_interfaces;
1827   while (egress_if) {
1828     if (!egress_if->bwNetworkChanged && !egress_if->bwGatewayChanged && !egress_if->upChanged && !force) {
1829       /* no relevant change */
1830       goto next;
1831     }
1832
1833     /* network route */
1834     if (egress_if->bwNetworkChanged || force) {
1835       bool routeChanged;
1836
1837       struct sgw_route_info networkRoutePrevious = egress_if->networkRouteCurrent;
1838
1839       if (!egress_if->bwCurrent.networkSet || !egress_if->upCurrent || (egress_if->bwCurrent.costs == INT64_MAX)) {
1840         memset(&egress_if->networkRouteCurrent, 0, sizeof(egress_if->networkRouteCurrent));
1841         egress_if->networkRouteCurrent.active = false;
1842       } else {
1843         determineEgressLinkRoute( //
1844             &egress_if->networkRouteCurrent, // route
1845             true,// networkRoute
1846             egress_if->if_index, // if_index
1847             NULL, // gw
1848             &egress_if->bwCurrent.network, // dst
1849             egress_if->tableNr // table
1850             );
1851       }
1852
1853       routeChanged = //
1854           (networkRoutePrevious.active != egress_if->networkRouteCurrent.active) || //
1855           memcmp(&networkRoutePrevious.route, &egress_if->networkRouteCurrent.route, sizeof(egress_if->networkRouteCurrent.route));
1856
1857       if ((routeChanged || MSGW_ROUTE_DEL_FORCED(phase)) && MSGW_ROUTE_DEL_ALLOWED(phase)) {
1858         programRoute(false, &networkRoutePrevious, egress_if->name);
1859       }
1860
1861       if ((routeChanged || MSGW_ROUTE_ADD_FORCED(phase)) && MSGW_ROUTE_ADD_ALLOWED(phase)) {
1862         programRoute(true, &egress_if->networkRouteCurrent, egress_if->name);
1863       }
1864     }
1865
1866     /* default route */
1867     if (egress_if->bwGatewayChanged || force) {
1868       bool routeChanged;
1869
1870       struct sgw_route_info egressRoutePrevious = egress_if->egressRouteCurrent;
1871
1872       if (!egress_if->upCurrent || (egress_if->bwCurrent.costs == INT64_MAX)) {
1873         memset(&egress_if->egressRouteCurrent, 0, sizeof(egress_if->egressRouteCurrent));
1874         egress_if->egressRouteCurrent.active = false;
1875       } else {
1876         determineEgressLinkRoute( //
1877             &egress_if->egressRouteCurrent, // route
1878             false,// networkRoute
1879             egress_if->if_index, // if_index
1880             !egress_if->bwCurrent.gatewaySet ? NULL : &egress_if->bwCurrent.gateway, // gw
1881             &ipv4_slash_0_route, // dst
1882             egress_if->tableNr // table
1883             );
1884       }
1885
1886       routeChanged = //
1887           (egressRoutePrevious.active != egress_if->egressRouteCurrent.active) || //
1888           memcmp(&egressRoutePrevious, &egress_if->egressRouteCurrent, sizeof(egress_if->egressRouteCurrent));
1889
1890        if ((routeChanged || MSGW_ROUTE_DEL_FORCED(phase)) && MSGW_ROUTE_DEL_ALLOWED(phase)) {
1891          programRoute(false, &egressRoutePrevious, egress_if->name);
1892        }
1893
1894        if ((routeChanged || MSGW_ROUTE_ADD_FORCED(phase)) && MSGW_ROUTE_ADD_ALLOWED(phase)) {
1895          programRoute(true, &egress_if->egressRouteCurrent, egress_if->name);
1896        }
1897     }
1898
1899     next: egress_if = egress_if->next;
1900   }
1901 }
1902
1903 /*
1904  * Multi-Smart-Gateway Status Overview
1905  */
1906
1907 #define IPNONE    ((olsr_cnf->ip_version == AF_INET) ? "0.0.0.0"     : "::")
1908 #define MASKNONE  ((olsr_cnf->ip_version == AF_INET) ? "0.0.0.0/0"   : "::/0")
1909 #define IPLOCAL   ((olsr_cnf->ip_version == AF_INET) ? "127.0.0.1"   : "::1")
1910 #define MASKLOCAL ((olsr_cnf->ip_version == AF_INET) ? "127.0.0.0/8" : "::1/128")
1911
1912 /**
1913  * Print a timestamp to a file
1914  *
1915  * @param f the file
1916  */
1917 static void printDate(FILE * f) {
1918   time_t timer;
1919   struct tm* tm_info;
1920   char buffer[64];
1921
1922   time(&timer);
1923   tm_info = localtime(&timer);
1924
1925   strftime(buffer, sizeof(buffer), "%B %d, %Y at %H:%M:%S", tm_info);
1926   fprintf(f, "%s", buffer);
1927 }
1928
1929 /**
1930  * Write multi-smart-gateway status file
1931  *
1932  * <pre>
1933  * # multi-smart-gateway status overview, generated on October 10, 2014 at 08:27:15
1934  *
1935  * #Originator Prefix      Uplink Downlink PathCost   Type   Interface Gateway     Cost
1936  *  127.0.0.1  127.0.0.0/8 0      0        4294967295 egress ppp0      0.0.0.0     9223372036854775807
1937  *  127.0.0.1  127.0.0.0/8 0      0        4294967295 egress eth1      192.168.0.1 9223372036854775807
1938  * *0.0.0.0    0.0.0.0/0   290    1500     1024       olsr   tnl_4094  0.0.0.0     2182002287
1939  * </pre>
1940  *
1941  * @param phase the phase of the change (startup/runtime/shutdown)
1942  */
1943 static void writeProgramStatusFile(enum sgw_multi_change_phase phase) {
1944              /*                     #  Orig Prefx Upl   Dwn PathC Type  Intfc Gw    Cost */
1945   static const char * fmt_header = "%s%-16s %-33s %-8s %-8s %-10s %-16s %-16s %-16s %s\n";
1946   static const char * fmt_values = "%s%-16s %-33s %-8u %-8u %-10u %-16s %-16s %-16s %llu\n";
1947
1948   char * fileName = olsr_cnf->smart_gw_status_file;
1949   FILE * fp = NULL;
1950
1951   if (!fileName || (fileName[0] == '\0')) {
1952     return;
1953   }
1954
1955   if (phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN) {
1956     remove(fileName);
1957     return;
1958   }
1959
1960   fp = fopen(fileName, "w");
1961   if (!fp) {
1962     olsr_syslog(OLSR_LOG_ERR, "Could not write to %s", fileName);
1963     return;
1964   }
1965
1966   fprintf(fp, "# OLSRd Multi-Smart-Gateway Status Overview\n");
1967   fprintf(fp, "# Generated on ");
1968   printDate(fp);
1969   fprintf(fp, "\n\n");
1970
1971   /* header */
1972   fprintf(fp, fmt_header, "#", "Originator", "Prefix", "Uplink", "Downlink", "PathCost", "Type", "Interface", "Gateway", "Cost");
1973
1974   /* egress interfaces */
1975   {
1976     struct sgw_egress_if * egress_if = olsr_cnf->smart_gw_egress_interfaces;
1977     while (egress_if) {
1978       struct ipaddr_str gwStr;
1979       const char * gw = !egress_if->bwCurrent.gatewaySet ? IPNONE : olsr_ip_to_string(&gwStr, &egress_if->bwCurrent.gateway);
1980       bool selected = bestOverallLink.valid && !bestOverallLink.isOlsr && (bestOverallLink.link.egress == egress_if);
1981
1982       fprintf(fp, fmt_values, //
1983           selected ? "*" : " ", //selected
1984           IPLOCAL, // Originator
1985           MASKLOCAL, // Prefix
1986           egress_if->bwCurrent.egressUk, // Uplink
1987           egress_if->bwCurrent.egressDk, // Downlink
1988           egress_if->bwCurrent.path_cost, // PathCost
1989           "egress", // Type
1990           egress_if->name, // Interface
1991           gw, // Gateway
1992           egress_if->bwCurrent.costs // Cost
1993           );
1994
1995       egress_if = egress_if->next;
1996     }
1997   }
1998
1999   /* olsr */
2000   {
2001     struct gateway_entry * current_gw = olsr_get_inet_gateway((olsr_cnf->ip_version == AF_INET) ? false : true);
2002     struct interfaceName * sgwTunnelInterfaceNames = (olsr_cnf->ip_version == AF_INET) ? sgwTunnel4InterfaceNames : sgwTunnel6InterfaceNames;
2003
2004     int i = 0;
2005     for (i = 0; i < olsr_cnf->smart_gw_use_count; i++) {
2006       struct interfaceName * node = &sgwTunnelInterfaceNames[i];
2007       struct gateway_entry * gw = node->gw;
2008       struct tc_entry* tc = !gw ? NULL : olsr_lookup_tc_entry(&gw->originator);
2009
2010       struct ipaddr_str originatorStr;
2011       const char * originator = !gw ? IPNONE : olsr_ip_to_string(&originatorStr, &gw->originator);
2012       struct ipaddr_str prefixIpStr;
2013       const char * prefixIPStr = !gw ? IPNONE : olsr_ip_to_string(&prefixIpStr, &gw->external_prefix.prefix);
2014       uint8_t prefix_len = !gw ? 0 : gw->external_prefix.prefix_len;
2015       struct ipaddr_str tunnelGwStr;
2016       const char * tunnelGw = !gw ? IPNONE : olsr_ip_to_string(&tunnelGwStr, &gw->originator);
2017       bool selected = bestOverallLink.valid && bestOverallLink.isOlsr && current_gw && (current_gw == gw);
2018
2019       char prefix[strlen(prefixIPStr) + 1 + 3 + 1];
2020       snprintf(prefix, sizeof(prefix), "%s/%d", prefixIPStr, prefix_len);
2021
2022       fprintf(fp, fmt_values, //
2023           selected ? "*" : " ", // selected
2024           originator, // Originator
2025           !gw ? MASKNONE : prefix, // Prefix IP
2026           !gw ? 0 : gw->uplink, // Uplink
2027           !gw ? 0 : gw->downlink, // Downlink
2028           (!gw || !tc) ? ROUTE_COST_BROKEN : tc->path_cost, // PathCost
2029           "olsr", // Type
2030           node->name, // Interface
2031           tunnelGw, // Gateway
2032           !gw ? INT64_MAX : gw->path_cost // Cost
2033       );
2034     }
2035   }
2036
2037   fclose(fp);
2038 }
2039
2040 /**
2041  * Report a new gateway with its most relevant parameters in the syslog
2042  */
2043 static void reportNewGateway(void) {
2044   if (!bestOverallLink.valid) {
2045     /* best overall link is invalid (none) */
2046     olsr_syslog(OLSR_LOG_INFO, "New gateway selected: none");
2047     return;
2048   }
2049
2050   if (!bestOverallLink.isOlsr) {
2051     /* best overall link is an egress interface */
2052     struct ipaddr_str gwStr;
2053     const char * gw = !bestOverallLink.link.egress->bwCurrent.gatewaySet ? //
2054         NULL : //
2055         olsr_ip_to_string(&gwStr, &bestOverallLink.link.egress->bwCurrent.gateway);
2056
2057     olsr_syslog(OLSR_LOG_INFO, "New gateway selected: %s %s%s%swith uplink/downlink/pathcost = %u/%u/%u", //
2058         bestOverallLink.link.egress->name, //
2059         !gw ? "" : "via ", //
2060         !gw ? "" : gwStr.buf, //
2061         !gw ? "" : " ", //
2062         bestOverallLink.link.egress->bwCurrent.egressUk, //
2063         bestOverallLink.link.egress->bwCurrent.egressDk, //
2064         bestOverallLink.link.egress->bwCurrent.path_cost);
2065     return;
2066   }
2067
2068   /* best overall link is an olsr (tunnel) interface */
2069   {
2070     struct tc_entry* tc = olsr_lookup_tc_entry(&bestOverallLink.link.olsr->originator);
2071
2072     char ifNameBuf[IFNAMSIZ];
2073     const char * ifName = if_indextoname(bestOverallLink.olsrTunnelIfIndex, ifNameBuf);
2074
2075     struct ipaddr_str gwStr;
2076     const char * gw = olsr_ip_to_string(&gwStr, &bestOverallLink.link.olsr->originator);
2077
2078     olsr_syslog(OLSR_LOG_INFO, "New gateway selected: %s %s%s%swith uplink/downlink/pathcost = %u/%u/%u", //
2079         !ifName ? "none" : ifName, //
2080         !gw ? "" : "via ", //
2081         !gw ? "" : gwStr.buf, //
2082         !gw ? "" : " ", //
2083         bestOverallLink.link.olsr->uplink, //
2084         bestOverallLink.link.olsr->downlink, //
2085         !tc ? ROUTE_COST_BROKEN : tc->path_cost);
2086   }
2087 }
2088
2089 /**
2090  * Process changes that are relevant to egress interface: changes to the
2091  * egress interfaces themselves and to the smart gateway that is chosen by olsrd
2092  *
2093  * @param egressChanged true when an egress interface changed
2094  * @param olsrChanged true when the smart gateway changed
2095  * @param phase the phase of the change (startup/runtime/shutdown)
2096  */
2097 void doRoutesMultiGw(bool egressChanged, bool olsrChanged, enum sgw_multi_change_phase phase) {
2098   bool bestEgressChanged = false;
2099   bool bestOverallChanged = false;
2100   bool force = MSGW_ROUTE_FORCED(phase);
2101
2102   assert( //
2103       (phase == GW_MULTI_CHANGE_PHASE_STARTUP) || //
2104       (phase == GW_MULTI_CHANGE_PHASE_RUNTIME) || //
2105       (phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN));
2106
2107   if (!egressChanged && !olsrChanged && !force) {
2108     goto out;
2109   }
2110
2111   assert(multi_gateway_mode());
2112
2113   if (egressChanged || force) {
2114     bestEgressChanged = determineBestEgressLink(phase);
2115     configureEgressLinkRoutes(phase);
2116   }
2117
2118   if (olsrChanged || bestEgressChanged || force) {
2119     bestOverallChanged = determineBestOverallLink(phase);
2120   }
2121
2122   if (bestOverallChanged || force) {
2123     setupDefaultGatewayOverrideRoutes(phase);
2124   }
2125
2126   if (bestEgressChanged || force) {
2127     configureBestEgressLinkRoute(phase);
2128   }
2129
2130   if (bestOverallChanged || force) {
2131     reportNewGateway();
2132   }
2133
2134   writeProgramStatusFile(phase);
2135
2136   out: if (egressChanged) {
2137     /* clear the 'changed' flags of egress interfaces */
2138     struct sgw_egress_if * egress_if = olsr_cnf->smart_gw_egress_interfaces;
2139     while (egress_if) {
2140       egress_if->upChanged = false;
2141
2142       egress_if->bwCostsChanged = false;
2143       egress_if->bwNetworkChanged = false;
2144       egress_if->bwGatewayChanged = false;
2145       egress_if->bwChanged = false;
2146
2147       egress_if = egress_if->next;
2148     }
2149   }
2150 }
2151
2152 #endif /* __linux__ */