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