7e39e2fe4e410771d69ae39263645814d0a96fe0
[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
1137     new_gw_in_list = olsr_gw_list_find(&gw_list_ipv6, gw);
1138     if (new_gw_in_list) {
1139       new_gw_in_list = olsr_gw_list_update(&gw_list_ipv6, new_gw_in_list);
1140       assert(new_gw_in_list);
1141     }
1142
1143     if (multi_gateway_mode() && //
1144         ((!gw->ipv6 && current_ipv4_gw && current_ipv4_gw->gw == gw) || //
1145          (gw->ipv6 && current_ipv6_gw && current_ipv6_gw->gw == gw)) //
1146         ) {
1147       /* the active gw has changed its costs: re-evaluate egress routes */
1148       doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
1149     }
1150   }
1151
1152   /* call update handler */
1153   assert(gw_handler);
1154   gw_handler->update(gw);
1155 }
1156
1157 /**
1158  * Delete a gateway based on the originator IP and the prefixlength of a HNA.
1159  * Should only be called if prefix is a smart_gw prefix or if node is removed
1160  * from TC set.
1161  *
1162  * @param originator
1163  * @param prefixlen
1164  * @param immediate when set to true then the gateway is removed from the
1165  * gateway tree immediately, else it is removed on a delayed schedule.
1166  */
1167 void olsr_delete_gateway_entry(union olsr_ip_addr *originator, uint8_t prefixlen, bool immediate) {
1168   olsr_delete_gateway_tree_entry(node2gateway(avl_find(&gateway_tree, originator)), prefixlen, immediate);
1169 }
1170
1171 /**
1172  * Delete a gateway entry .
1173  *
1174  * @param gw a gateway entry from the gateway tree
1175  * @param prefixlen
1176  * @param immediate when set to true then the gateway is removed from the
1177  * gateway tree immediately, else it is removed on a delayed schedule.
1178  */
1179 static void olsr_delete_gateway_tree_entry(struct gateway_entry * gw, uint8_t prefixlen, bool immediate) {
1180   bool change = false;
1181
1182   if (!gw) {
1183     return;
1184   }
1185
1186   if (immediate && gw->cleanup_timer) {
1187     /* stop timer if we have to remove immediately */
1188     olsr_stop_timer(gw->cleanup_timer);
1189     gw->cleanup_timer = NULL;
1190   }
1191
1192   if (gw->cleanup_timer == NULL || gw->ipv4 || gw->ipv6) {
1193     /* the gw  is not scheduled for deletion */
1194
1195     if (olsr_cnf->ip_version == AF_INET && prefixlen == 0) {
1196       change = gw->ipv4;
1197       gw->ipv4 = false;
1198       gw->ipv4nat = false;
1199     } else if (olsr_cnf->ip_version == AF_INET6 && prefixlen == ipv6_internet_route.prefix_len) {
1200       change = gw->ipv6;
1201       gw->ipv6 = false;
1202     } else if (olsr_cnf->ip_version == AF_INET6 && prefixlen == ipv6_mappedv4_route.prefix_len) {
1203       change = gw->ipv4;
1204       gw->ipv4 = false;
1205       gw->ipv4nat = false;
1206     }
1207
1208     if (prefixlen == FORCE_DELETE_GW_ENTRY || !(gw->ipv4 || gw->ipv6)) {
1209       struct gw_container_entry * gw_in_list;
1210
1211       /* prevent this gateway from being chosen as the new gateway */
1212       gw->ipv4 = false;
1213       gw->ipv4nat = false;
1214       gw->ipv6 = false;
1215
1216       /* handle gateway loss */
1217       assert(gw_handler);
1218       gw_handler->delete(gw);
1219
1220       /* cleanup gateway if necessary */
1221       gw_in_list = olsr_gw_list_find(&gw_list_ipv4, gw);
1222       if (gw_in_list) {
1223         if (current_ipv4_gw && current_ipv4_gw->gw == gw) {
1224           olsr_os_inetgw_tunnel_route(current_ipv4_gw->tunnel->if_index, true, false, olsr_cnf->rt_table_tunnel);
1225           current_ipv4_gw = NULL;
1226         }
1227
1228         if (gw_in_list->tunnel) {
1229           struct interfaceName * ifn = find_interfaceName(gw_in_list->gw);
1230           if (ifn) {
1231             olsr_os_inetgw_tunnel_route(gw_in_list->tunnel->if_index, true, false, ifn->tableNr);
1232           }
1233           olsr_os_del_ipip_tunnel(gw_in_list->tunnel);
1234           set_unused_iptunnel_name(gw_in_list->gw);
1235           gw_in_list->tunnel = NULL;
1236         }
1237
1238         gw_in_list->gw = NULL;
1239         gw_in_list = olsr_gw_list_remove(&gw_list_ipv4, gw_in_list);
1240         olsr_cookie_free(gw_container_entry_mem_cookie, gw_in_list);
1241       }
1242
1243       gw_in_list = olsr_gw_list_find(&gw_list_ipv6, gw);
1244       if (gw_in_list) {
1245         if (current_ipv6_gw && current_ipv6_gw->gw == gw) {
1246           olsr_os_inetgw_tunnel_route(current_ipv6_gw->tunnel->if_index, false, false, olsr_cnf->rt_table_tunnel);
1247           current_ipv6_gw = NULL;
1248         }
1249
1250         if (gw_in_list->tunnel) {
1251           struct interfaceName * ifn = find_interfaceName(gw_in_list->gw);
1252           if (ifn) {
1253             olsr_os_inetgw_tunnel_route(gw_in_list->tunnel->if_index, false, false, ifn->tableNr);
1254           }
1255           olsr_os_del_ipip_tunnel(gw_in_list->tunnel);
1256           set_unused_iptunnel_name(gw_in_list->gw);
1257           gw_in_list->tunnel = NULL;
1258         }
1259
1260         gw_in_list->gw = NULL;
1261         gw_in_list = olsr_gw_list_remove(&gw_list_ipv6, gw_in_list);
1262         olsr_cookie_free(gw_container_entry_mem_cookie, gw_in_list);
1263       }
1264
1265       if (!immediate) {
1266         /* remove gateway entry on a delayed schedule */
1267         olsr_set_timer(&gw->cleanup_timer, GW_CLEANUP_INTERVAL, 0, false, cleanup_gateway_handler, gw, NULL);
1268       } else {
1269         cleanup_gateway_handler(gw);
1270       }
1271
1272       /* when the current gateway was deleted, then immediately choose a new gateway */
1273       if (!current_ipv4_gw || !current_ipv6_gw) {
1274         assert(gw_handler);
1275         gw_handler->choose(!current_ipv4_gw, !current_ipv6_gw);
1276       }
1277
1278     } else if (change) {
1279       assert(gw_handler);
1280       gw_handler->update(gw);
1281     }
1282   }
1283 }
1284
1285 /**
1286  * Triggers a check if the one of the gateways have been lost or has an
1287  * ETX = infinity
1288  */
1289 void olsr_trigger_gatewayloss_check(void) {
1290   bool ipv4 = false;
1291   bool ipv6 = false;
1292
1293   if (current_ipv4_gw && current_ipv4_gw->gw) {
1294     struct tc_entry *tc = olsr_lookup_tc_entry(&current_ipv4_gw->gw->originator);
1295     ipv4 = (tc == NULL || tc->path_cost == ROUTE_COST_BROKEN);
1296   }
1297   if (current_ipv6_gw && current_ipv6_gw->gw) {
1298     struct tc_entry *tc = olsr_lookup_tc_entry(&current_ipv6_gw->gw->originator);
1299     ipv6 = (tc == NULL || tc->path_cost == ROUTE_COST_BROKEN);
1300   }
1301
1302   if (ipv4 || ipv6) {
1303     assert(gw_handler);
1304     gw_handler->choose(ipv4, ipv6);
1305   }
1306 }
1307
1308 /*
1309  * Gateway Plugin Functions
1310  */
1311
1312 /**
1313  * Sets a new internet gateway.
1314  *
1315  * @param the chosen gateway
1316  * @param ipv4 set ipv4 gateway
1317  * @param ipv6 set ipv6 gateway
1318  * @return true if an error happened, false otherwise
1319  */
1320 bool olsr_set_inet_gateway(struct gateway_entry * chosen_gw, bool ipv4, bool ipv6) {
1321   struct gateway_entry *new_gw;
1322
1323   ipv4 = ipv4 && (olsr_cnf->ip_version == AF_INET || olsr_cnf->use_niit);
1324   ipv6 = ipv6 && (olsr_cnf->ip_version == AF_INET6);
1325   if (!ipv4 && !ipv6) {
1326     return true;
1327   }
1328
1329   new_gw = node2gateway(avl_find(&gateway_tree, &chosen_gw->originator));
1330   if (!new_gw) {
1331     /* the originator is not in the gateway tree, we can't set it as gateway */
1332     return true;
1333   }
1334
1335   /* handle IPv4 */
1336   if (ipv4 &&
1337       new_gw->ipv4 &&
1338       (!new_gw->ipv4nat || olsr_cnf->smart_gw_allow_nat) &&
1339       (!current_ipv4_gw || current_ipv4_gw->gw != new_gw)) {
1340     /* new gw is different than the current gw */
1341
1342     struct gw_container_entry * new_gw_in_list = olsr_gw_list_find(&gw_list_ipv4, new_gw);
1343     if (new_gw_in_list) {
1344       /* new gw is already in the gw list */
1345       assert(new_gw_in_list->tunnel);
1346       olsr_os_inetgw_tunnel_route(new_gw_in_list->tunnel->if_index, true, true, olsr_cnf->rt_table_tunnel);
1347       current_ipv4_gw = new_gw_in_list;
1348
1349       if (multi_gateway_mode()) {
1350         doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
1351       }
1352     } else {
1353       /* new gw is not yet in the gw list */
1354       char name[IFNAMSIZ];
1355       struct olsr_iptunnel_entry *new_v4gw_tunnel;
1356       struct interfaceName * interfaceName;
1357
1358       if (olsr_gw_list_full(&gw_list_ipv4)) {
1359         /* the list is full: remove the worst active gateway */
1360         struct gw_container_entry* worst = olsr_gw_list_get_worst_entry(&gw_list_ipv4);
1361         assert(worst);
1362
1363         removeGatewayFromList(&gw_list_ipv4, true, worst);
1364       }
1365
1366       get_unused_iptunnel_name(new_gw, name, &interfaceName);
1367       new_v4gw_tunnel = olsr_os_add_ipip_tunnel(&new_gw->originator, true, name);
1368       if (new_v4gw_tunnel) {
1369         if (interfaceName) {
1370           olsr_os_inetgw_tunnel_route(new_v4gw_tunnel->if_index, true, true, interfaceName->tableNr);
1371         }
1372         olsr_os_inetgw_tunnel_route(new_v4gw_tunnel->if_index, true, true, olsr_cnf->rt_table_tunnel);
1373
1374         new_gw_in_list = olsr_cookie_malloc(gw_container_entry_mem_cookie);
1375         new_gw_in_list->gw = new_gw;
1376         new_gw_in_list->tunnel = new_v4gw_tunnel;
1377         current_ipv4_gw = olsr_gw_list_add(&gw_list_ipv4, new_gw_in_list);
1378
1379         if (multi_gateway_mode()) {
1380           doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
1381         }
1382       } else {
1383         /* adding the tunnel failed, we try again in the next cycle */
1384         set_unused_iptunnel_name(new_gw);
1385         ipv4 = false;
1386       }
1387     }
1388   }
1389
1390   /* handle IPv6 */
1391   if (ipv6 &&
1392       new_gw->ipv6 &&
1393       (!current_ipv6_gw || current_ipv6_gw->gw != new_gw)) {
1394     /* new gw is different than the current gw */
1395
1396         struct gw_container_entry * new_gw_in_list = olsr_gw_list_find(&gw_list_ipv6, new_gw);
1397     if (new_gw_in_list) {
1398       /* new gw is already in the gw list */
1399       assert(new_gw_in_list->tunnel);
1400       olsr_os_inetgw_tunnel_route(new_gw_in_list->tunnel->if_index, true, true, olsr_cnf->rt_table_tunnel);
1401       current_ipv6_gw = new_gw_in_list;
1402
1403       if (multi_gateway_mode()) {
1404         doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
1405       }
1406     } else {
1407       /* new gw is not yet in the gw list */
1408       char name[IFNAMSIZ];
1409       struct olsr_iptunnel_entry *new_v6gw_tunnel;
1410       struct interfaceName * interfaceName;
1411
1412       if (olsr_gw_list_full(&gw_list_ipv6)) {
1413         /* the list is full: remove the worst active gateway */
1414         struct gw_container_entry* worst = olsr_gw_list_get_worst_entry(&gw_list_ipv6);
1415         assert(worst);
1416
1417         removeGatewayFromList(&gw_list_ipv6, false, worst);
1418       }
1419
1420       get_unused_iptunnel_name(new_gw, name, &interfaceName);
1421       new_v6gw_tunnel = olsr_os_add_ipip_tunnel(&new_gw->originator, false, name);
1422       if (new_v6gw_tunnel) {
1423         if (interfaceName) {
1424           olsr_os_inetgw_tunnel_route(new_v6gw_tunnel->if_index, false, true, interfaceName->tableNr);
1425         }
1426         olsr_os_inetgw_tunnel_route(new_v6gw_tunnel->if_index, false, true, olsr_cnf->rt_table_tunnel);
1427
1428         new_gw_in_list = olsr_cookie_malloc(gw_container_entry_mem_cookie);
1429         new_gw_in_list->gw = new_gw;
1430         new_gw_in_list->tunnel = new_v6gw_tunnel;
1431         current_ipv6_gw = olsr_gw_list_add(&gw_list_ipv6, new_gw_in_list);
1432
1433         if (multi_gateway_mode()) {
1434           doRoutesMultiGw(false, true, GW_MULTI_CHANGE_PHASE_RUNTIME);
1435         }
1436       } else {
1437         /* adding the tunnel failed, we try again in the next cycle */
1438         set_unused_iptunnel_name(new_gw);
1439         ipv6 = false;
1440       }
1441     }
1442   }
1443
1444   return !ipv4 && !ipv6;
1445 }
1446
1447 /**
1448  * @param ipv6 if set to true then the IPv6 gateway is returned, otherwise the IPv4
1449  * gateway is returned
1450  * @return a pointer to the gateway_entry of the current ipv4 internet gw or
1451  * NULL if not set.
1452  */
1453 struct gateway_entry *olsr_get_inet_gateway(bool ipv6) {
1454         if (ipv6) {
1455                 return current_ipv6_gw ? current_ipv6_gw->gw : NULL;
1456         }
1457
1458         return current_ipv4_gw ? current_ipv4_gw->gw : NULL;
1459 }
1460
1461 /*
1462  * Process Egress Changes
1463  */
1464
1465 #define MSGW_ROUTE_ADD_ALLOWED(phase)   ((phase == GW_MULTI_CHANGE_PHASE_STARTUP ) || (phase == GW_MULTI_CHANGE_PHASE_RUNTIME ))
1466 #define MSGW_ROUTE_ADD_FORCED(phase)    ( phase == GW_MULTI_CHANGE_PHASE_STARTUP )
1467 #define MSGW_ROUTE_DEL_ALLOWED(phase)   ((phase == GW_MULTI_CHANGE_PHASE_RUNTIME ) || (phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN))
1468 #define MSGW_ROUTE_DEL_FORCED(phase)    ( phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN)
1469 #define MSGW_ROUTE_FORCED(phase)        ((phase == GW_MULTI_CHANGE_PHASE_STARTUP ) || (phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN))
1470
1471 /**
1472  * Determine best egress link.
1473  * The list of egress interface is ordered on priority (the declaration order),
1474  * so the function will - for multiple egress links with the same costs - set the
1475  * best egress interface to the first declared one of those.
1476  * When there is no best egress interface (that is up) then the function will
1477  * set the best egress interface to NULL.
1478  *
1479  * @param phase the phase of the change (startup/runtime/shutdown)
1480  * @return true when the best egress link changed or when any of its relevant
1481  * parameters has changed
1482  */
1483 static bool determineBestEgressLink(enum sgw_multi_change_phase phase) {
1484   bool changed = false;
1485   struct sgw_egress_if * bestEgress = olsr_cnf->smart_gw_egress_interfaces;
1486
1487   if (phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN) {
1488     bestEgress = NULL;
1489   } else {
1490     struct sgw_egress_if * egress_if = bestEgress;
1491     if (egress_if) {
1492       egress_if = egress_if->next;
1493     }
1494     while (egress_if) {
1495       if (egress_if->upCurrent && (egress_if->bwCurrent.costs < bestEgress->bwCurrent.costs)) {
1496         bestEgress = egress_if;
1497       }
1498
1499       egress_if = egress_if->next;
1500     }
1501
1502     if (bestEgress && (!bestEgress->upCurrent || (bestEgress->bwCurrent.costs == INT64_MAX))) {
1503       bestEgress = NULL;
1504     }
1505   }
1506
1507   bestEgressLinkPrevious = bestEgressLink;
1508   bestEgressLink = bestEgress;
1509
1510   changed = (bestEgressLinkPrevious != bestEgressLink) || //
1511       (bestEgressLink && (bestEgressLink->upChanged || bestEgressLink->bwChanged));
1512
1513   if (changed || MSGW_ROUTE_FORCED(phase)) {
1514     if (!bestEgressLink || !bestEgressLink->upCurrent) {
1515       olsr_cnf->smart_gw_uplink = 0;
1516       olsr_cnf->smart_gw_downlink = 0;
1517     } else {
1518       olsr_cnf->smart_gw_uplink = bestEgressLink->bwCurrent.egressUk;
1519       olsr_cnf->smart_gw_downlink = bestEgressLink->bwCurrent.egressDk;
1520     }
1521     refresh_smartgw_netmask();
1522   }
1523
1524   return changed;
1525 }
1526
1527 /**
1528  * Determine best overall link (choose egress interface over olsrd).
1529  *
1530  * When there is no best overall link, the best overall link will be set to a
1531  * NULL egress interface.
1532  *
1533  * @param phase the phase of the change (startup/runtime/shutdown)
1534  * @return true when the best egress link changed or when any of its relevant
1535  * parameters has changed
1536  */
1537 static bool determineBestOverallLink(enum sgw_multi_change_phase phase) {
1538   struct gw_container_entry * gwContainer = (olsr_cnf->ip_version == AF_INET) ? current_ipv4_gw : current_ipv6_gw;
1539   struct gateway_entry * olsrGw = !gwContainer ? NULL : gwContainer->gw;
1540
1541   int64_t egressCosts = !bestEgressLink ? INT64_MAX : bestEgressLink->bwCurrent.costs;
1542   int64_t olsrCosts = !olsrGw ? INT64_MAX : olsrGw->path_cost;
1543   int64_t bestOverallCosts = MIN(egressCosts, olsrCosts);
1544
1545   bestOverallLinkPrevious = bestOverallLink;
1546   if ((bestOverallCosts == INT64_MAX) || (phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN)) {
1547     bestOverallLink.valid = false;
1548     bestOverallLink.isOlsr = false;
1549     bestOverallLink.link.egress = NULL;
1550     bestOverallLink.olsrTunnelIfIndex = 0;
1551   } else if (egressCosts <= olsrCosts) {
1552     bestOverallLink.valid = bestEgressLink;
1553     bestOverallLink.isOlsr = false;
1554     bestOverallLink.link.egress = bestEgressLink;
1555     bestOverallLink.olsrTunnelIfIndex = 0;
1556   } else {
1557     struct olsr_iptunnel_entry * tunnel = !gwContainer ? NULL : gwContainer->tunnel;
1558
1559     bestOverallLink.valid = olsrGw;
1560     bestOverallLink.isOlsr = true;
1561     bestOverallLink.link.olsr = olsrGw;
1562     bestOverallLink.olsrTunnelIfIndex = !tunnel ? 0 : tunnel->if_index;
1563   }
1564
1565   return memcmp(&bestOverallLink, &bestOverallLinkPrevious, sizeof(bestOverallLink));
1566 }
1567
1568 /**
1569  * Program a route (add or remove) through netlink
1570  *
1571  * @param add true to add the route, false to remove it
1572  * @param route the route
1573  * @param linkName the human readable id of the route, used in error reports in
1574  * the syslog
1575  */
1576 static void programRoute(bool add, struct sgw_route_info * route, const char * linkName) {
1577   if (!route || !route->active) {
1578     return;
1579   }
1580
1581   if (olsr_new_netlink_route( //
1582       route->route.family, //
1583       route->route.rttable, //
1584       route->route.flags, //
1585       route->route.scope, //
1586       route->route.if_index, //
1587       route->route.metric, //
1588       route->route.protocol, //
1589       !route->route.srcSet ? NULL : &route->route.srcStore, //
1590       !route->route.gwSet ? NULL : &route->route.gwStore, //
1591       !route->route.dstSet ? NULL : &route->route.dstStore, //
1592       add, //
1593       route->route.del_similar, //
1594       route->route.blackhole //
1595       )) {
1596     olsr_syslog(OLSR_LOG_ERR, "Could not %s a route for the %s %s", !add ? "remove" : "add", !add ? "previous" : "current", linkName);
1597     route->active = false;
1598   } else {
1599     route->active = add;
1600   }
1601 }
1602
1603 /**
1604  * Determine the best overall egress/olsr interface routes.
1605  *
1606  * These are a set of 2 /1 routes to override any default gateway
1607  * routes that are setup through other means such as a DHCP client.
1608  *
1609  * @param routes a pointer to the array of 2 /1 routes where to store the
1610  * newly determined routes
1611  */
1612 static void determineBestOverallLinkRoutes(struct sgw_route_info * routes) {
1613   int ifIndex = 0;
1614   union olsr_ip_addr * gw = NULL;
1615   int i;
1616   if (!bestOverallLink.valid) {
1617     /* there is no current best overall link */
1618   } else if (!bestOverallLink.isOlsr) {
1619     /* current best overall link is an egress interface */
1620     struct sgw_egress_if * egress = bestOverallLink.link.egress;
1621     if (egress) {
1622       ifIndex = egress->if_index;
1623       if (egress->bwCurrent.gatewaySet) {
1624         gw = &egress->bwCurrent.gateway;
1625       }
1626     }
1627   } else {
1628     /* current best overall link is an olsr tunnel interface */
1629     struct gw_container_entry * gwContainer = current_ipv4_gw;
1630     struct olsr_iptunnel_entry * tunnel = !gwContainer ? NULL : gwContainer->tunnel;
1631
1632     if (tunnel) {
1633       ifIndex = tunnel->if_index;
1634     }
1635   }
1636
1637   if (!ifIndex) {
1638     for (i = 0; i < 2; i++) {
1639       routes[i].active = false;
1640     }
1641     return;
1642   }
1643
1644   for (i = 0; i < 2; i++) {
1645     memset(&routes[i], 0, sizeof(routes[i]));
1646     routes[i].active = true;
1647     routes[i].route.family = AF_INET;
1648     routes[i].route.rttable = olsr_cnf->rt_table;
1649     routes[i].route.flags = 0;
1650     routes[i].route.scope = !gw ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
1651     routes[i].route.if_index = ifIndex;
1652     routes[i].route.metric = 0;
1653     routes[i].route.protocol = RTPROT_STATIC;
1654     routes[i].route.srcSet = false;
1655     routes[i].route.gwSet = false;
1656     if (gw) {
1657       routes[i].route.gwSet = true;
1658       routes[i].route.gwStore = *gw;
1659     }
1660     routes[i].route.dstSet = true;
1661     routes[i].route.dstStore = ipv4_slash_1_routes[i];
1662     routes[i].route.del_similar = false;
1663     routes[i].route.blackhole = false;
1664   }
1665 }
1666
1667 /**
1668  * Setup default gateway override routes: a set of 2 /1 routes for the best
1669  * overall link
1670  *
1671  * @param phase the phase of the change (startup/runtime/shutdown)
1672  */
1673 static void setupDefaultGatewayOverrideRoutes(enum sgw_multi_change_phase phase) {
1674   bool force = MSGW_ROUTE_FORCED(phase);
1675   int i;
1676
1677   if (!bestOverallLinkPrevious.valid && !bestOverallLink.valid && !force) {
1678     return;
1679   }
1680
1681   memcpy(&bestOverallLinkPreviousRoutes, &bestOverallLinkRoutes, sizeof(bestOverallLinkPreviousRoutes));
1682
1683   determineBestOverallLinkRoutes(bestOverallLinkRoutes);
1684
1685   for (i = 0; i < 2; i++) {
1686     bool routeChanged = //
1687         (bestOverallLinkPreviousRoutes[i].active != bestOverallLinkRoutes[i].active) || //
1688         memcmp(&bestOverallLinkPreviousRoutes[i].route, &bestOverallLinkRoutes[i].route, sizeof(bestOverallLinkRoutes[i].route));
1689
1690     if ((routeChanged || MSGW_ROUTE_DEL_FORCED(phase)) && MSGW_ROUTE_DEL_ALLOWED(phase)) {
1691       programRoute(false, &bestOverallLinkPreviousRoutes[i], "overall best gateway");
1692     }
1693
1694     if ((routeChanged || MSGW_ROUTE_ADD_FORCED(phase)) && MSGW_ROUTE_ADD_ALLOWED(phase)) {
1695       programRoute(true, &bestOverallLinkRoutes[i], "overall best gateway");
1696     }
1697   }
1698 }
1699
1700 /**
1701  * Determine the best egress interface route.
1702  *
1703  * @param route a pointer to the an route where to store the
1704  * newly determined route
1705  * @param networkRoute true when the route is a network route (not an internet
1706  * route)
1707  * @param if_index the index of the interface that the route is for
1708  * @param gw the gateway for the route
1709  * @param dst the destination for the route
1710  * @param table the routing table for the route
1711  */
1712 static void determineEgressLinkRoute( //
1713     struct sgw_route_info * route, //
1714     bool networkRoute, //
1715     int if_index, //
1716     union olsr_ip_addr * gw, //
1717     struct olsr_ip_prefix * dst, //
1718     int table) {
1719   // default route
1720   // ----: ip route replace|delete blackhole default                          table 90: !egress_if               (1)
1721   // ppp0: ip route replace|delete           default                 dev ppp0 table 90:  egress_if && dst && !gw (2)
1722   // eth1: ip route replace|delete           default via 192.168.0.1 dev eth1 table 90:  egress_if && dst &&  gw (3)
1723
1724   // network route
1725   // eth1: ip route replace|delete to 192.168.0.0/24                 dev eth1 table 90:  egress_if && dst && !gw (2*)
1726
1727   memset(route, 0, sizeof(*route));
1728   if (if_index <= 0) { /* 1 */
1729     route->active = true;
1730     route->route.family = AF_INET;
1731     route->route.rttable = table;
1732     route->route.flags = RTNH_F_ONLINK;
1733     route->route.scope = RT_SCOPE_UNIVERSE;
1734     route->route.if_index = 0;
1735     route->route.metric = 0;
1736     route->route.protocol = RTPROT_STATIC;
1737     route->route.srcSet = false;
1738     route->route.gwSet = false;
1739     route->route.dstSet = false;
1740     if (dst) {
1741       route->route.dstSet = true;
1742       route->route.dstStore = *dst;
1743     }
1744     route->route.del_similar = false;
1745     route->route.blackhole = true;
1746   } else if (dst && !gw) { /* 2 */
1747     route->active = true;
1748     route->route.family = AF_INET;
1749     route->route.rttable = table;
1750     route->route.flags = !networkRoute ? RTNH_F_ONLINK /* 2 */ : 0 /* 2* */;
1751     route->route.scope = RT_SCOPE_LINK;
1752     route->route.if_index = if_index;
1753     route->route.metric = 0;
1754     route->route.protocol = RTPROT_STATIC;
1755     route->route.srcSet = false;
1756     route->route.gwSet = false;
1757     route->route.dstSet = true;
1758     route->route.dstStore = *dst;
1759     route->route.del_similar = false;
1760     route->route.blackhole = false;
1761   } else if (dst && gw) { /* 3 */
1762     route->active = true;
1763     route->route.family = AF_INET;
1764     route->route.rttable = table;
1765     route->route.flags = 0;
1766     route->route.scope = RT_SCOPE_UNIVERSE;
1767     route->route.if_index = if_index;
1768     route->route.metric = 0;
1769     route->route.protocol = RTPROT_STATIC;
1770     route->route.srcSet = false;
1771     route->route.gwSet = true;
1772     route->route.gwStore = *gw;
1773     route->route.dstSet = true;
1774     route->route.dstStore = *dst;
1775     route->route.del_similar = false;
1776     route->route.blackhole = false;
1777   } else {
1778     /* no destination set */
1779     route->active = false;
1780     olsr_syslog(OLSR_LOG_ERR, "No route destination specified in %s", __FUNCTION__);
1781     return;
1782   }
1783 }
1784
1785 /**
1786  * Setup default route for the best egress interface
1787  *
1788  * When there is no best egress link, then a blackhole route is setup to prevent
1789  * looping smart gateway tunnel traffic.
1790  *
1791  * @param phase the phase of the change (startup/runtime/shutdown)
1792  */
1793 static void configureBestEgressLinkRoute(enum sgw_multi_change_phase phase) {
1794   bool force = MSGW_ROUTE_FORCED(phase);
1795
1796   /*
1797    * bestEgressLinkPrevious  bestEgressLink  Action
1798    *                   NULL            NULL  -
1799    *                   NULL               x  add new route
1800    *                      x            NULL  remove old route
1801    *                      x               x  remove old route && add new routes
1802    */
1803
1804   if (!bestEgressLinkPrevious && !bestEgressLink && !force) {
1805     return;
1806   }
1807
1808   memcpy(&bestEgressLinkPreviousRoute, &bestEgressLinkRoute, sizeof(bestEgressLinkPreviousRoute));
1809
1810   determineEgressLinkRoute( //
1811       &bestEgressLinkRoute, // route
1812       false, // networkRoute
1813       !bestEgressLink ? 0 : bestEgressLink->if_index, // if_index
1814       (!bestEgressLink || !bestEgressLink->bwCurrent.gatewaySet) ? NULL : &bestEgressLink->bwCurrent.gateway, // gw
1815       &ipv4_slash_0_route, // dst
1816       olsr_cnf->smart_gw_offset_tables // table
1817       );
1818
1819   {
1820     bool routeChanged = //
1821         (bestEgressLinkPreviousRoute.active != bestEgressLinkRoute.active) || //
1822         memcmp(&bestEgressLinkPreviousRoute.route, &bestEgressLinkRoute.route, sizeof(bestEgressLinkRoute.route));
1823
1824     if ((routeChanged || MSGW_ROUTE_DEL_FORCED(phase)) && MSGW_ROUTE_DEL_ALLOWED(phase)) {
1825       programRoute(false, &bestEgressLinkPreviousRoute, "best egress link");
1826     }
1827
1828     if ((routeChanged || MSGW_ROUTE_ADD_FORCED(phase)) && MSGW_ROUTE_ADD_ALLOWED(phase)) {
1829       programRoute(true, &bestEgressLinkRoute, "best egress link");
1830     }
1831   }
1832 }
1833
1834 /**
1835  * Setup network (when relevant) and default routes for the every egress
1836  * interface
1837  *
1838  * @param phase the phase of the change (startup/runtime/shutdown)
1839  */
1840 static void configureEgressLinkRoutes(enum sgw_multi_change_phase phase) {
1841   bool force = MSGW_ROUTE_FORCED(phase);
1842
1843   /* egress interfaces */
1844   struct sgw_egress_if * egress_if = olsr_cnf->smart_gw_egress_interfaces;
1845   while (egress_if) {
1846     if (!egress_if->bwNetworkChanged && !egress_if->bwGatewayChanged && !egress_if->upChanged && !force) {
1847       /* no relevant change */
1848       goto next;
1849     }
1850
1851     /* network route */
1852     if (egress_if->bwNetworkChanged || force) {
1853       bool routeChanged;
1854
1855       struct sgw_route_info networkRoutePrevious = egress_if->networkRouteCurrent;
1856
1857       if (!egress_if->bwCurrent.networkSet || !egress_if->upCurrent || (egress_if->bwCurrent.costs == INT64_MAX)) {
1858         memset(&egress_if->networkRouteCurrent, 0, sizeof(egress_if->networkRouteCurrent));
1859         egress_if->networkRouteCurrent.active = false;
1860       } else {
1861         determineEgressLinkRoute( //
1862             &egress_if->networkRouteCurrent, // route
1863             true,// networkRoute
1864             egress_if->if_index, // if_index
1865             NULL, // gw
1866             &egress_if->bwCurrent.network, // dst
1867             egress_if->tableNr // table
1868             );
1869       }
1870
1871       routeChanged = //
1872           (networkRoutePrevious.active != egress_if->networkRouteCurrent.active) || //
1873           memcmp(&networkRoutePrevious.route, &egress_if->networkRouteCurrent.route, sizeof(egress_if->networkRouteCurrent.route));
1874
1875       if ((routeChanged || MSGW_ROUTE_DEL_FORCED(phase)) && MSGW_ROUTE_DEL_ALLOWED(phase)) {
1876         programRoute(false, &networkRoutePrevious, egress_if->name);
1877       }
1878
1879       if ((routeChanged || MSGW_ROUTE_ADD_FORCED(phase)) && MSGW_ROUTE_ADD_ALLOWED(phase)) {
1880         programRoute(true, &egress_if->networkRouteCurrent, egress_if->name);
1881       }
1882     }
1883
1884     /* default route */
1885     if (egress_if->bwGatewayChanged || force) {
1886       bool routeChanged;
1887
1888       struct sgw_route_info egressRoutePrevious = egress_if->egressRouteCurrent;
1889
1890       if (!egress_if->upCurrent || (egress_if->bwCurrent.costs == INT64_MAX)) {
1891         memset(&egress_if->egressRouteCurrent, 0, sizeof(egress_if->egressRouteCurrent));
1892         egress_if->egressRouteCurrent.active = false;
1893       } else {
1894         determineEgressLinkRoute( //
1895             &egress_if->egressRouteCurrent, // route
1896             false,// networkRoute
1897             egress_if->if_index, // if_index
1898             !egress_if->bwCurrent.gatewaySet ? NULL : &egress_if->bwCurrent.gateway, // gw
1899             &ipv4_slash_0_route, // dst
1900             egress_if->tableNr // table
1901             );
1902       }
1903
1904       routeChanged = //
1905           (egressRoutePrevious.active != egress_if->egressRouteCurrent.active) || //
1906           memcmp(&egressRoutePrevious, &egress_if->egressRouteCurrent, sizeof(egress_if->egressRouteCurrent));
1907
1908        if ((routeChanged || MSGW_ROUTE_DEL_FORCED(phase)) && MSGW_ROUTE_DEL_ALLOWED(phase)) {
1909          programRoute(false, &egressRoutePrevious, egress_if->name);
1910        }
1911
1912        if ((routeChanged || MSGW_ROUTE_ADD_FORCED(phase)) && MSGW_ROUTE_ADD_ALLOWED(phase)) {
1913          programRoute(true, &egress_if->egressRouteCurrent, egress_if->name);
1914        }
1915     }
1916
1917     next: egress_if = egress_if->next;
1918   }
1919 }
1920
1921 /*
1922  * Multi-Smart-Gateway Status Overview
1923  */
1924
1925 #define IPNONE    ((olsr_cnf->ip_version == AF_INET) ? "0.0.0.0"     : "::")
1926 #define MASKNONE  ((olsr_cnf->ip_version == AF_INET) ? "0.0.0.0/0"   : "::/0")
1927 #define IPLOCAL   ((olsr_cnf->ip_version == AF_INET) ? "127.0.0.1"   : "::1")
1928 #define MASKLOCAL ((olsr_cnf->ip_version == AF_INET) ? "127.0.0.0/8" : "::1/128")
1929
1930 /**
1931  * Print a timestamp to a file
1932  *
1933  * @param f the file
1934  */
1935 static void printDate(FILE * f) {
1936   time_t timer;
1937   struct tm* tm_info;
1938   char buffer[64];
1939
1940   time(&timer);
1941   tm_info = localtime(&timer);
1942
1943   strftime(buffer, sizeof(buffer), "%B %d, %Y at %H:%M:%S", tm_info);
1944   fprintf(f, "%s", buffer);
1945 }
1946
1947 /**
1948  * Write multi-smart-gateway status file
1949  *
1950  * <pre>
1951  * # multi-smart-gateway status overview, generated on October 10, 2014 at 08:27:15
1952  *
1953  * #Originator Prefix      Uplink Downlink PathCost   Type   Interface Gateway     Cost
1954  *  127.0.0.1  127.0.0.0/8 0      0        4294967295 egress ppp0      0.0.0.0     9223372036854775807
1955  *  127.0.0.1  127.0.0.0/8 0      0        4294967295 egress eth1      192.168.0.1 9223372036854775807
1956  * *0.0.0.0    0.0.0.0/0   290    1500     1024       olsr   tnl_4094  0.0.0.0     2182002287
1957  * </pre>
1958  *
1959  * @param phase the phase of the change (startup/runtime/shutdown)
1960  */
1961 static void writeProgramStatusFile(enum sgw_multi_change_phase phase) {
1962   /*                                # Origi Prefx Upln Dwnl PathC Type Intfc Gtway Cost */
1963   static const char * fmt_header = "%s%-15s %-18s %-9s %-9s %-10s %-6s %-16s %-15s %s\n";
1964   static const char * fmt_values = "%s%-15s %-18s %-9u %-9u %-10u %-6s %-16s %-15s %llu\n";
1965
1966   char * fileName = olsr_cnf->smart_gw_status_file;
1967   FILE * fp = NULL;
1968
1969   if (!fileName || (fileName[0] == '\0')) {
1970     return;
1971   }
1972
1973   if (phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN) {
1974     remove(fileName);
1975     return;
1976   }
1977
1978   fp = fopen(fileName, "w");
1979   if (!fp) {
1980     olsr_syslog(OLSR_LOG_ERR, "Could not write to %s", fileName);
1981     return;
1982   }
1983
1984   fprintf(fp, "# OLSRd Multi-Smart-Gateway Status Overview\n");
1985   fprintf(fp, "# Generated on ");
1986   printDate(fp);
1987   fprintf(fp, "\n\n");
1988
1989   /* header */
1990   fprintf(fp, fmt_header, "#", "Originator", "Prefix", "Uplink", "Downlink", "PathCost", "Type", "Interface", "Gateway", "Cost");
1991
1992   /* egress interfaces */
1993   {
1994     struct sgw_egress_if * egress_if = olsr_cnf->smart_gw_egress_interfaces;
1995     while (egress_if) {
1996       struct ipaddr_str gwStr;
1997       const char * gw = !egress_if->bwCurrent.gatewaySet ? IPNONE : olsr_ip_to_string(&gwStr, &egress_if->bwCurrent.gateway);
1998       bool selected = bestOverallLink.valid && !bestOverallLink.isOlsr && (bestOverallLink.link.egress == egress_if);
1999
2000       fprintf(fp, fmt_values, //
2001           selected ? "*" : " ", //selected
2002           IPLOCAL, // Originator
2003           MASKLOCAL, // Prefix
2004           egress_if->bwCurrent.egressUk, // Uplink
2005           egress_if->bwCurrent.egressDk, // Downlink
2006           egress_if->bwCurrent.path_cost, // PathCost
2007           "egress", // Type
2008           egress_if->name, // Interface
2009           gw, // Gateway
2010           egress_if->bwCurrent.costs // Cost
2011           );
2012
2013       egress_if = egress_if->next;
2014     }
2015   }
2016
2017   /* olsr */
2018   {
2019     struct gateway_entry * current_gw = olsr_get_inet_gateway((olsr_cnf->ip_version == AF_INET) ? false : true);
2020     struct interfaceName * sgwTunnelInterfaceNames = (olsr_cnf->ip_version == AF_INET) ? sgwTunnel4InterfaceNames : sgwTunnel6InterfaceNames;
2021
2022     int i = 0;
2023     for (i = 0; i < olsr_cnf->smart_gw_use_count; i++) {
2024       struct interfaceName * node = &sgwTunnelInterfaceNames[i];
2025       struct gateway_entry * gw = node->gw;
2026       struct tc_entry* tc = !gw ? NULL : olsr_lookup_tc_entry(&gw->originator);
2027
2028       struct ipaddr_str originatorStr;
2029       const char * originator = !gw ? IPNONE : olsr_ip_to_string(&originatorStr, &gw->originator);
2030       struct ipaddr_str prefixIpStr;
2031       const char * prefixIPStr = !gw ? IPNONE : olsr_ip_to_string(&prefixIpStr, &gw->external_prefix.prefix);
2032       uint8_t prefix_len = !gw ? 0 : gw->external_prefix.prefix_len;
2033       struct ipaddr_str tunnelGwStr;
2034       const char * tunnelGw = !gw ? IPNONE : olsr_ip_to_string(&tunnelGwStr, &gw->originator);
2035       bool selected = bestOverallLink.valid && bestOverallLink.isOlsr && current_gw && (current_gw == gw);
2036
2037       char prefix[strlen(prefixIPStr) + 1 + 3 + 1];
2038       snprintf(prefix, sizeof(prefix), "%s/%d", prefixIPStr, prefix_len);
2039
2040       fprintf(fp, fmt_values, //
2041           selected ? "*" : " ", // selected
2042           originator, // Originator
2043           !gw ? MASKNONE : prefix, // Prefix IP
2044           !gw ? 0 : gw->uplink, // Uplink
2045           !gw ? 0 : gw->downlink, // Downlink
2046           (!gw || !tc) ? ROUTE_COST_BROKEN : tc->path_cost, // PathCost
2047           "olsr", // Type
2048           node->name, // Interface
2049           tunnelGw, // Gateway
2050           !gw ? INT64_MAX : gw->path_cost // Cost
2051       );
2052     }
2053   }
2054
2055   fclose(fp);
2056 }
2057
2058 /**
2059  * Report a new gateway with its most relevant parameters in the syslog
2060  */
2061 static void reportNewGateway(void) {
2062   if (!bestOverallLink.valid) {
2063     /* best overall link is invalid (none) */
2064     olsr_syslog(OLSR_LOG_INFO, "New gateway selected: none");
2065     return;
2066   }
2067
2068   if (!bestOverallLink.isOlsr) {
2069     /* best overall link is an egress interface */
2070     struct ipaddr_str gwStr;
2071     const char * gw = !bestOverallLink.link.egress->bwCurrent.gatewaySet ? //
2072         NULL : //
2073         olsr_ip_to_string(&gwStr, &bestOverallLink.link.egress->bwCurrent.gateway);
2074
2075     olsr_syslog(OLSR_LOG_INFO, "New gateway selected: %s %s%s%swith uplink/downlink/pathcost = %u/%u/%u", //
2076         bestOverallLink.link.egress->name, //
2077         !gw ? "" : "via ", //
2078         !gw ? "" : gwStr.buf, //
2079         !gw ? "" : " ", //
2080         bestOverallLink.link.egress->bwCurrent.egressUk, //
2081         bestOverallLink.link.egress->bwCurrent.egressDk, //
2082         bestOverallLink.link.egress->bwCurrent.path_cost);
2083     return;
2084   }
2085
2086   /* best overall link is an olsr (tunnel) interface */
2087   {
2088     struct tc_entry* tc = olsr_lookup_tc_entry(&bestOverallLink.link.olsr->originator);
2089
2090     char ifNameBuf[IFNAMSIZ];
2091     const char * ifName = if_indextoname(bestOverallLink.olsrTunnelIfIndex, ifNameBuf);
2092
2093     struct ipaddr_str gwStr;
2094     const char * gw = olsr_ip_to_string(&gwStr, &bestOverallLink.link.olsr->originator);
2095
2096     olsr_syslog(OLSR_LOG_INFO, "New gateway selected: %s %s%s%swith uplink/downlink/pathcost = %u/%u/%u", //
2097         !ifName ? "none" : ifName, //
2098         !gw ? "" : "via ", //
2099         !gw ? "" : gwStr.buf, //
2100         !gw ? "" : " ", //
2101         bestOverallLink.link.olsr->uplink, //
2102         bestOverallLink.link.olsr->downlink, //
2103         !tc ? ROUTE_COST_BROKEN : tc->path_cost);
2104   }
2105 }
2106
2107 /**
2108  * Process changes that are relevant to egress interface: changes to the
2109  * egress interfaces themselves and to the smart gateway that is chosen by olsrd
2110  *
2111  * @param egressChanged true when an egress interface changed
2112  * @param olsrChanged true when the smart gateway changed
2113  * @param phase the phase of the change (startup/runtime/shutdown)
2114  */
2115 void doRoutesMultiGw(bool egressChanged, bool olsrChanged, enum sgw_multi_change_phase phase) {
2116   bool bestEgressChanged = false;
2117   bool bestOverallChanged = false;
2118   bool force = MSGW_ROUTE_FORCED(phase);
2119
2120   assert( //
2121       (phase == GW_MULTI_CHANGE_PHASE_STARTUP) || //
2122       (phase == GW_MULTI_CHANGE_PHASE_RUNTIME) || //
2123       (phase == GW_MULTI_CHANGE_PHASE_SHUTDOWN));
2124
2125   if (!egressChanged && !olsrChanged && !force) {
2126     goto out;
2127   }
2128
2129   assert(multi_gateway_mode());
2130
2131   if (egressChanged || force) {
2132     bestEgressChanged = determineBestEgressLink(phase);
2133     configureEgressLinkRoutes(phase);
2134   }
2135
2136   if (olsrChanged || bestEgressChanged || force) {
2137     bestOverallChanged = determineBestOverallLink(phase);
2138   }
2139
2140   if (bestOverallChanged || force) {
2141     setupDefaultGatewayOverrideRoutes(phase);
2142   }
2143
2144   if (bestEgressChanged || force) {
2145     configureBestEgressLinkRoute(phase);
2146   }
2147
2148   if (bestOverallChanged || force) {
2149     reportNewGateway();
2150   }
2151
2152   writeProgramStatusFile(phase);
2153
2154   out: if (egressChanged) {
2155     /* clear the 'changed' flags of egress interfaces */
2156     struct sgw_egress_if * egress_if = olsr_cnf->smart_gw_egress_interfaces;
2157     while (egress_if) {
2158       egress_if->upChanged = false;
2159
2160       egress_if->bwCostsChanged = false;
2161       egress_if->bwNetworkChanged = false;
2162       egress_if->bwGatewayChanged = false;
2163       egress_if->bwChanged = false;
2164
2165       egress_if = egress_if->next;
2166     }
2167   }
2168 }
2169
2170 #endif /* __linux__ */