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