Merge branch 'release-0.6.5'
[olsrd.git] / src / olsr_niit.c
1 /*
2  * olsr_niit.c
3  *
4  *  Created on: 02.02.2010
5  *      Author: henning
6  */
7
8 #include "defs.h"
9 #include "kernel_routes.h"
10 #include "net_os.h"
11 #include "olsr_niit.h"
12
13 #include <net/if.h>
14
15 #ifdef __linux__
16 static void handle_niit_ifchange (int if_index, struct interface *iface, enum olsr_ifchg_flag);
17
18 static bool niit4to6_active, niit6to4_active;
19
20 void olsr_init_niit(void) {
21   if (olsr_cnf->ip_version == AF_INET) {
22     olsr_cnf->use_niit = false;
23     return;
24   }
25
26   olsr_cnf->niit4to6_if_index = if_nametoindex(DEF_NIIT4TO6_IFNAME);
27   if (olsr_cnf->niit4to6_if_index <= 0) {
28     OLSR_PRINTF(1, "Warning, %s device is not available, deactivating NIIT\n", DEF_NIIT4TO6_IFNAME);
29     olsr_cnf->use_niit = false;
30     return;
31   }
32   olsr_cnf->niit6to4_if_index = if_nametoindex(DEF_NIIT6TO4_IFNAME);
33   if (olsr_cnf->niit6to4_if_index <= 0) {
34     OLSR_PRINTF(1, "Warning, %s device is not available, deactivating NIIT\n", DEF_NIIT6TO4_IFNAME);
35     olsr_cnf->use_niit = false;
36     return;
37   }
38
39   niit4to6_active = olsr_if_isup(DEF_NIIT4TO6_IFNAME);
40   niit6to4_active = olsr_if_isup(DEF_NIIT6TO4_IFNAME);
41
42   olsr_add_ifchange_handler(&handle_niit_ifchange);
43   olsr_add_ifchange_handler(&handle_niit_ifchange);
44   return;
45 }
46
47 void olsr_setup_niit_routes(void) {
48   struct ip_prefix_list *h;
49
50   if (!niit4to6_active || !niit6to4_active) {
51     return;
52   }
53   for (h = olsr_cnf->hna_entries; h != NULL; h = h->next) {
54     if (ip_prefix_is_mappedv4(&h->net)) {
55       olsr_os_niit_6to4_route(&h->net, true);
56     }
57   }
58 }
59
60 void olsr_cleanup_niit_routes(void) {
61   struct ip_prefix_list *h;
62
63   if (!niit6to4_active) {
64     return;
65   }
66   for (h = olsr_cnf->hna_entries; h != NULL; h = h->next) {
67     if (ip_prefix_is_mappedv4(&h->net)) {
68       olsr_os_niit_6to4_route(&h->net, false);
69     }
70   }
71 }
72
73 void olsr_niit_handle_route(const struct rt_entry *rt, bool set) {
74   if (olsr_cnf->ip_version == AF_INET6 && olsr_cnf->use_niit
75       && niit4to6_active && niit6to4_active && is_prefix_niit_ipv6(&rt->rt_dst)) {
76     struct olsr_ip_prefix dst_v4;
77
78     prefix_mappedv4_to_v4(&dst_v4, &rt->rt_dst);
79     olsr_os_niit_4to6_route(&dst_v4, set);
80   }
81 }
82
83 static void refresh_niit4to6_routes(bool set) {
84   struct rt_entry *rt;
85
86   if (set && (!niit4to6_active || !niit6to4_active)) {
87     return;
88   }
89   if (!set && !niit4to6_active) {
90     return;
91   }
92
93   OLSR_FOR_ALL_RT_ENTRIES(rt) {
94     if (is_prefix_niit_ipv6(&rt->rt_dst)) {
95       struct olsr_ip_prefix dst_v4;
96
97       prefix_mappedv4_to_v4(&dst_v4, &rt->rt_dst);
98       olsr_os_niit_4to6_route(&dst_v4, set);
99     }
100   } OLSR_FOR_ALL_RT_ENTRIES_END(rt)
101 }
102
103 static void handle_niit_ifchange (int if_index, struct interface *iface __attribute__ ((unused)),
104     enum olsr_ifchg_flag flag) {
105   bool active;
106
107   active = niit4to6_active && niit6to4_active;
108   if (if_index == olsr_cnf->niit4to6_if_index) {
109     niit4to6_active = flag != IFCHG_IF_REMOVE;
110   }
111   if (if_index == olsr_cnf->niit6to4_if_index) {
112     niit6to4_active = flag != IFCHG_IF_REMOVE;
113   }
114
115   if (active != (niit4to6_active && niit6to4_active)) {
116     /* niit status change */
117     if (!active) {
118       /* from inactive to active */
119       olsr_setup_niit_routes();
120       refresh_niit4to6_routes(true);
121     }
122     else {
123       /* the other way around */
124       olsr_cleanup_niit_routes();
125       refresh_niit4to6_routes(false);
126     }
127   }
128
129 }
130 #endif /* __linux__ */