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