Split SmartGatewayNAT into SmartGatewayAllowNAT and SmartGatewayUplinkNAT
[olsrd.git] / src / gateway.c
1 /*
2  * gateway.c
3  *
4  *  Created on: 05.01.2010
5  *      Author: henning
6  */
7
8 #include "common/avl.h"
9 #include "defs.h"
10 #include "ipcalc.h"
11 #include "olsr.h"
12 #include "olsr_cfg.h"
13 #include "olsr_cookie.h"
14 #include "scheduler.h"
15 #include "gateway.h"
16
17 struct avl_tree gateway_tree;
18 static struct olsr_cookie_info *gw_mem_cookie = NULL;
19 static uint8_t smart_gateway_netmask[sizeof(union olsr_ip_addr)];
20
21 static uint32_t deserialize_gw_speed(uint8_t value) {
22   uint32_t speed, exp;
23
24   speed = (value >> 3)+1;
25   exp = value & 7;
26   while (exp-- > 0) {
27     speed *= 10;
28   }
29   return speed;
30 }
31
32 static uint8_t serialize_gw_speed(uint32_t speed) {
33   uint8_t exp = 0;
34
35   if (speed == 0 || speed > 320000000) {
36     return 0;
37   }
38
39   while (speed > 32 || (speed % 10) == 0) {
40     speed /= 10;
41     exp ++;
42   }
43   return ((speed-1) << 3) | exp;
44 }
45
46 void
47 olsr_init_gateways(void) {
48   uint8_t *ip;
49   gw_mem_cookie = olsr_alloc_cookie("Gateway cookie", OLSR_COOKIE_TYPE_MEMORY);
50   olsr_cookie_set_memory_size(gw_mem_cookie, sizeof(struct gateway_entry));
51
52   avl_init(&gateway_tree, avl_comp_default);
53
54   memset(&smart_gateway_netmask, 0, sizeof(smart_gateway_netmask));
55
56   if (olsr_cnf->smart_gw_active) {
57     union olsr_ip_addr gw_net;
58     int prefix;
59
60     memset(&gw_net, 0, sizeof(gw_net));
61
62     /*
63      * hack for Vienna network to remove 0.0.0.0/128.0.0.0 and 128.0.0.0/128.0.0.0 routes
64      * just set MAXIMUM_GATEWAY_PREFIX_LENGTH to 1
65      */
66     for (prefix = 1; prefix <= MAXIMUM_GATEWAY_PREFIX_LENGTH; prefix++) {
67       while (ip_prefix_list_remove(&olsr_cnf->hna_entries, &gw_net, prefix));
68     }
69
70     ip = (uint8_t *) &smart_gateway_netmask;
71
72     if (olsr_cnf->smart_gw_uplink > 0 || olsr_cnf->smart_gw_downlink > 0) {
73       ip[GW_HNA_FLAGS] |= GW_HNA_FLAG_LINKSPEED;
74       ip[GW_HNA_DOWNLINK] = serialize_gw_speed(olsr_cnf->smart_gw_downlink);
75       ip[GW_HNA_UPLINK] = serialize_gw_speed(olsr_cnf->smart_gw_uplink);
76     }
77     if (olsr_cnf->ip_version == AF_INET6 && olsr_cnf->smart_gw_prefix.prefix_len > 0) {
78       ip[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV6PREFIX;
79       ip[GW_HNA_V6PREFIXLEN] = olsr_cnf->smart_gw_prefix.prefix_len;
80       memcpy(&ip[GW_HNA_V6PREFIX], &olsr_cnf->smart_gw_prefix.prefix, 8);
81     }
82   }
83 }
84
85 struct gateway_entry *
86 olsr_find_gateway(union olsr_ip_addr *originator) {
87   struct avl_node *node = avl_find(&gateway_tree, originator);
88
89   return node == NULL ? NULL : node2gateway(node);
90 }
91
92 void
93 olsr_set_gateway(union olsr_ip_addr *originator, union olsr_ip_addr *mask, int prefixlen) {
94   struct gateway_entry *gw;
95   uint8_t *ptr = ((uint8_t *)mask) + ((prefixlen+7)/8);
96
97   gw = olsr_find_gateway(originator);
98   if (!gw) {
99     gw = olsr_cookie_malloc(gw_mem_cookie);
100
101     gw->originator = *originator;
102     gw->node.key = &gw->originator;
103
104     avl_insert(&gateway_tree, &gw->node, AVL_DUP_NO);
105   }
106
107   if ((ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_LINKSPEED) != 0) {
108     gw->uplink = deserialize_gw_speed(ptr[GW_HNA_UPLINK]);
109     gw->downlink = deserialize_gw_speed(ptr[GW_HNA_DOWNLINK]);
110   }
111   else {
112     gw->uplink = 1;
113     gw->downlink = 1;
114   }
115
116   gw->ipv4 = (ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV4) != 0;
117   gw->ipv4nat = (ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV4_NAT) != 0;
118
119   if (olsr_cnf->ip_version == AF_INET6) {
120     gw->ipv6 = (ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV6) != 0;
121
122     /* do not reset prefixlength for ::ffff:0:0 HNAs */
123     if (prefixlen == ipv6_internet_route.prefix_len) {
124       memset(&gw->external_prefix, 0, sizeof(gw->external_prefix));
125
126       if ((ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV6PREFIX) != 0
127           && memcmp(mask->v6.s6_addr, &ipv6_internet_route.prefix, olsr_cnf->ipsize) == 0) {
128         /* this is the right prefix (2000::/3), so we can copy the prefix */
129         gw->external_prefix.prefix_len = ptr[GW_HNA_V6PREFIXLEN];
130         memcpy(&gw->external_prefix.prefix, &ptr[GW_HNA_V6PREFIX], 8);
131       }
132     }
133   }
134 }
135
136 void
137 olsr_delete_gateway(union olsr_ip_addr *originator) {
138   struct gateway_entry *gw;
139
140   gw = olsr_find_gateway(originator);
141   if (gw) {
142     avl_delete(&gateway_tree, &gw->node);
143
144     olsr_cookie_free(gw_mem_cookie, gw);
145   }
146 }
147
148 bool olsr_is_smart_gateway(struct olsr_ip_prefix *prefix, union olsr_ip_addr *mask) {
149   uint8_t *ptr;
150
151   if (!ip_is_inetgw_prefix(prefix)) {
152     return false;
153   }
154
155   ptr = ((uint8_t *)mask) + ((prefix->prefix_len+7)/8);
156   return ptr[GW_HNA_PAD] == 0 && ptr[GW_HNA_FLAGS] != 0;
157 }
158
159 void olsr_modifiy_inetgw_netmask(union olsr_ip_addr *mask, int prefixlen) {
160   uint8_t *ptr = ((uint8_t *)mask) + ((prefixlen+7)/8);
161
162   memcpy(ptr, &smart_gateway_netmask, sizeof(smart_gateway_netmask) - prefixlen/8);
163   if (olsr_cnf->has_ipv4_gateway) {
164     ptr[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV4;
165
166     if (olsr_cnf->smart_gw_uplink_nat) {
167       ptr[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV4_NAT;
168     }
169   }
170   if (olsr_cnf->has_ipv6_gateway) {
171     ptr[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV6;
172   }
173   if (!olsr_cnf->has_ipv6_gateway || prefixlen != ipv6_internet_route.prefix_len){
174     ptr[GW_HNA_FLAGS] &= ~GW_HNA_FLAG_IPV6PREFIX;
175   }
176 }
177
178 void
179 olsr_print_gateway(void) {
180 #ifndef NODEBUG
181   struct ipaddr_str buf;
182   struct gateway_entry *gw;
183   const int addrsize = olsr_cnf->ip_version == AF_INET ? 15 : 39;
184
185   OLSR_PRINTF(0, "\n--- %s ---------------------------------------------------- GATEWAYS\n\n",
186       olsr_wallclock_string());
187   OLSR_PRINTF(0, "%-*s %-6s %-9s %-9s %s\n", addrsize, "IP address", "Type", "Uplink", "Downlink",
188       olsr_cnf->ip_version == AF_INET ? "" : "External Prefix");
189
190   OLSR_FOR_ALL_GATEWAY_ENTRIES(gw) {
191     OLSR_PRINTF(0, "%-*s %s%c%s%c%c %-9u %-9u %s\n", addrsize, olsr_ip_to_string(&buf, &gw->originator),
192         gw->ipv4nat ? "" : "   ",
193         gw->ipv4 ? '4' : ' ',
194         gw->ipv4nat ? "(N)" : "",
195         (gw->ipv4 && gw->ipv6) ? ',' : ' ',
196         gw->ipv6 ? '6' : ' ',
197         gw->uplink, gw->downlink,
198         gw->external_prefix.prefix_len == 0 ? "" : olsr_ip_prefix_to_string(&gw->external_prefix));
199   } OLSR_FOR_ALL_GATEWAY_ENTRIES_END(gw)
200 #endif
201 }