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