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