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