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