Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 955 lines (716 sloc) 26.784 kb
c46e848 Guus Sliepen - route.c will contain the routing logic.
authored
1 /*
2 route.c -- routing
de78d79 Guus Sliepen Update copyright notices, remove Ivo's email address.
authored
3 Copyright (C) 2000-2005 Ivo Timmermans,
4712d8f Guus Sliepen Update copyright notices.
authored
4 2000-2012 Guus Sliepen <guus@tinc-vpn.org>
c46e848 Guus Sliepen - route.c will contain the routing logic.
authored
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
ab7c61b Guus Sliepen Update the address of the Free Software Foundation in all copyright head...
authored
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
c46e848 Guus Sliepen - route.c will contain the routing logic.
authored
19 */
20
e449d94 Guus Sliepen Big header file cleanup: everything that has to do with standard system
authored
21 #include "system.h"
c46e848 Guus Sliepen - route.c will contain the routing logic.
authored
22
e449d94 Guus Sliepen Big header file cleanup: everything that has to do with standard system
authored
23 #include "avl_tree.h"
408ca91 Guus Sliepen - Integrate rbl trees into tinc.
authored
24 #include "connection.h"
b0a4f7b Guus Sliepen Even more missing definitions.
authored
25 #include "ethernet.h"
26 #include "ipv4.h"
27 #include "ipv6.h"
0b9175e Guus Sliepen Define logger(), cleans up source code and allows us to write log entrie...
authored
28 #include "logger.h"
e449d94 Guus Sliepen Big header file cleanup: everything that has to do with standard system
authored
29 #include "net.h"
30 #include "protocol.h"
31 #include "route.h"
32 #include "subnet.h"
33 #include "utils.h"
c46e848 Guus Sliepen - route.c will contain the routing logic.
authored
34
eefa280 Guus Sliepen Use bools and enums where appropriate.
authored
35 rmode_t routing_mode = RMODE_ROUTER;
95a6974 Guus Sliepen Add the Forwarding option.
authored
36 fmode_t forwarding_mode = FMODE_INTERNAL;
84531fb Guus Sliepen Allow broadcast packets to be sent directly instead of via the MST.
authored
37 bmode_t broadcast_mode = BMODE_MST;
b5e3bf1 Guus Sliepen Set default value of DecrementTTL to "no".
authored
38 bool decrement_ttl = false;
3e4829e Guus Sliepen Add the DirectOnly option.
authored
39 bool directonly = false;
eefa280 Guus Sliepen Use bools and enums where appropriate.
authored
40 bool priorityinheritance = false;
14979f8 Guus Sliepen - Global time_t now, so that we don't have to call time() too often.
authored
41 int macexpire = 600;
eefa280 Guus Sliepen Use bools and enums where appropriate.
authored
42 bool overwrite_mac = false;
d26a4af Guus Sliepen Export mymac.
authored
43 mac_t mymac = {{0xFE, 0xFD, 0, 0, 0, 0}};
c46e848 Guus Sliepen - route.c will contain the routing logic.
authored
44
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
45 /* Sizes of various headers */
46
c97b882 Guus Sliepen const
authored
47 static const size_t ether_size = sizeof(struct ether_header);
48 static const size_t arp_size = sizeof(struct ether_arp);
49 static const size_t ip_size = sizeof(struct ip);
50 static const size_t icmp_size = sizeof(struct icmp) - sizeof(struct ip);
51 static const size_t ip6_size = sizeof(struct ip6_hdr);
52 static const size_t icmp6_size = sizeof(struct icmp6_hdr);
53 static const size_t ns_size = sizeof(struct nd_neighbor_solicit);
54 static const size_t opt_size = sizeof(struct nd_opt_hdr);
0ddce63 Guus Sliepen Don't redefine MAX if it already exists.
authored
55
56 #ifndef MAX
a9bbb33 Guus Sliepen Fixes for definitions under Windows.
authored
57 #define MAX(a, b) ((a) > (b) ? (a) : (b))
0ddce63 Guus Sliepen Don't redefine MAX if it already exists.
authored
58 #endif
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
59
7d21a8d Guus Sliepen - Speed up checksumming
authored
60 /* RFC 1071 */
61
5dde646 Guus Sliepen K&R style braces.
authored
62 static uint16_t inet_checksum(void *data, int len, uint16_t prevsum) {
7d21a8d Guus Sliepen - Speed up checksumming
authored
63 uint16_t *p = data;
64 uint32_t checksum = prevsum ^ 0xFFFF;
65
8285827 Guus Sliepen Checksums must also work for uneven number of bytes.
authored
66 while(len >= 2) {
7d21a8d Guus Sliepen - Speed up checksumming
authored
67 checksum += *p++;
8285827 Guus Sliepen Checksums must also work for uneven number of bytes.
authored
68 len -= 2;
69 }
70
71 if(len)
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
72 checksum += *(uint8_t *)p;
7d21a8d Guus Sliepen - Speed up checksumming
authored
73
74 while(checksum >> 16)
75 checksum = (checksum & 0xFFFF) + (checksum >> 16);
76
77 return ~checksum;
78 }
79
d02d81f Guus Sliepen Let compiler decide when to inline.
authored
80 static bool ratelimit(int frequency) {
7d21a8d Guus Sliepen - Speed up checksumming
authored
81 static time_t lasttime = 0;
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
82 static int count = 0;
7d21a8d Guus Sliepen - Speed up checksumming
authored
83
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
84 if(lasttime == now) {
f1d5eae Guus Sliepen Don't send ICMP Time Exceeded messages for other Time Exceeded messages.
authored
85 if(count >= frequency)
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
86 return true;
87 } else {
88 lasttime = now;
89 count = 0;
90 }
7d21a8d Guus Sliepen - Speed up checksumming
authored
91
f1d5eae Guus Sliepen Don't send ICMP Time Exceeded messages for other Time Exceeded messages.
authored
92 count++;
eefa280 Guus Sliepen Use bools and enums where appropriate.
authored
93 return false;
7d21a8d Guus Sliepen - Speed up checksumming
authored
94 }
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
95
d02d81f Guus Sliepen Let compiler decide when to inline.
authored
96 static bool checklength(node_t *source, vpn_packet_t *packet, length_t length) {
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
97 if(packet->len < length) {
4c85542 Guus Sliepen Drop support for localisation.
authored
98 ifdebug(TRAFFIC) logger(LOG_WARNING, "Got too short packet from %s (%s)", source->name, source->hostname);
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
99 return false;
100 } else
101 return true;
102 }
9915f2a Guus Sliepen Handle unicast packets larger than PMTU in switch mode.
authored
103
95928f7 Guus Sliepen Also clamp MSS of TCP over IPv6 packets.
authored
104 static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *packet) {
3cb91d7 Guus Sliepen Clamp MSS to miminum MTU in both directions.
authored
105 if(!source || !via || !(via->options & OPTION_CLAMP_MSS))
95928f7 Guus Sliepen Also clamp MSS of TCP over IPv6 packets.
authored
106 return;
107
3cb91d7 Guus Sliepen Clamp MSS to miminum MTU in both directions.
authored
108 uint16_t mtu = source->mtu;
109 if(via != myself && via->mtu < mtu)
110 mtu = via->mtu;
111
95928f7 Guus Sliepen Also clamp MSS of TCP over IPv6 packets.
authored
112 /* Find TCP header */
113 int start = 0;
114 uint16_t type = packet->data[12] << 8 | packet->data[13];
2a538ed Guus Sliepen Clamp MSS of IPv4 SYN packets.
authored
115
95928f7 Guus Sliepen Also clamp MSS of TCP over IPv6 packets.
authored
116 if(type == ETH_P_IP && packet->data[23] == 6)
117 start = 14 + (packet->data[14] & 0xf) * 4;
118 else if(type == ETH_P_IPV6 && packet->data[20] == 6)
119 start = 14 + 40;
120
121 if(!start || packet->len <= start + 20)
122 return;
123
124 /* Use data offset field to calculate length of options field */
125 int len = ((packet->data[start + 12] >> 4) - 5) * 4;
126
b455111 Guus Sliepen Make MSS clamping configurable, but enabled by default.
authored
127 if(packet->len < start + 20 + len)
128 return;
129
95928f7 Guus Sliepen Also clamp MSS of TCP over IPv6 packets.
authored
130 /* Search for MSS option header */
2a538ed Guus Sliepen Clamp MSS of IPv4 SYN packets.
authored
131 for(int i = 0; i < len;) {
95928f7 Guus Sliepen Also clamp MSS of TCP over IPv6 packets.
authored
132 if(packet->data[start + 20 + i] == 0)
2a538ed Guus Sliepen Clamp MSS of IPv4 SYN packets.
authored
133 break;
134
95928f7 Guus Sliepen Also clamp MSS of TCP over IPv6 packets.
authored
135 if(packet->data[start + 20 + i] == 1) {
2a538ed Guus Sliepen Clamp MSS of IPv4 SYN packets.
authored
136 i++;
137 continue;
138 }
139
95928f7 Guus Sliepen Also clamp MSS of TCP over IPv6 packets.
authored
140 if(i > len - 2 || i > len - packet->data[start + 21 + i])
2a538ed Guus Sliepen Clamp MSS of IPv4 SYN packets.
authored
141 break;
142
95928f7 Guus Sliepen Also clamp MSS of TCP over IPv6 packets.
authored
143 if(packet->data[start + 20 + i] != 2) {
144 if(packet->data[start + 21 + i] < 2)
2a538ed Guus Sliepen Clamp MSS of IPv4 SYN packets.
authored
145 break;
95928f7 Guus Sliepen Also clamp MSS of TCP over IPv6 packets.
authored
146 i += packet->data[start + 21 + i];
2a538ed Guus Sliepen Clamp MSS of IPv4 SYN packets.
authored
147 continue;
148 }
149
95928f7 Guus Sliepen Also clamp MSS of TCP over IPv6 packets.
authored
150 if(packet->data[start + 21] != 4)
2a538ed Guus Sliepen Clamp MSS of IPv4 SYN packets.
authored
151 break;
152
95928f7 Guus Sliepen Also clamp MSS of TCP over IPv6 packets.
authored
153 /* Found it */
154 uint16_t oldmss = packet->data[start + 22 + i] << 8 | packet->data[start + 23 + i];
3cb91d7 Guus Sliepen Clamp MSS to miminum MTU in both directions.
authored
155 uint16_t newmss = mtu - start - 20;
95928f7 Guus Sliepen Also clamp MSS of TCP over IPv6 packets.
authored
156 uint16_t csum = packet->data[start + 16] << 8 | packet->data[start + 17];
2a538ed Guus Sliepen Clamp MSS of IPv4 SYN packets.
authored
157
158 if(oldmss <= newmss)
159 break;
160
161 ifdebug(TRAFFIC) logger(LOG_INFO, "Clamping MSS of packet from %s to %s to %d", source->name, via->name, newmss);
162
95928f7 Guus Sliepen Also clamp MSS of TCP over IPv6 packets.
authored
163 /* Update the MSS value and the checksum */
164 packet->data[start + 22 + i] = newmss >> 8;
165 packet->data[start + 23 + i] = newmss & 0xff;
2a538ed Guus Sliepen Clamp MSS of IPv4 SYN packets.
authored
166 csum ^= 0xffff;
167 csum -= oldmss;
168 csum += newmss;
169 csum ^= 0xffff;
95928f7 Guus Sliepen Also clamp MSS of TCP over IPv6 packets.
authored
170 packet->data[start + 16] = csum >> 8;
171 packet->data[start + 17] = csum & 0xff;
2a538ed Guus Sliepen Clamp MSS of IPv4 SYN packets.
authored
172 break;
173 }
174 }
175
9915f2a Guus Sliepen Handle unicast packets larger than PMTU in switch mode.
authored
176 static void swap_mac_addresses(vpn_packet_t *packet) {
177 mac_t tmp;
178 memcpy(&tmp, &packet->data[0], sizeof tmp);
179 memcpy(&packet->data[0], &packet->data[6], sizeof tmp);
180 memcpy(&packet->data[6], &tmp, sizeof tmp);
181 }
7d21a8d Guus Sliepen - Speed up checksumming
authored
182
5dde646 Guus Sliepen K&R style braces.
authored
183 static void learn_mac(mac_t *address) {
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
184 subnet_t *subnet;
185 avl_node_t *node;
186 connection_t *c;
187
92aefd2 Guus Sliepen When learning MAC addresses, only check our own Subnets for previous ent...
authored
188 subnet = lookup_subnet_mac(myself, address);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
189
190 /* If we don't know this MAC address yet, store it */
191
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
192 if(!subnet) {
4c85542 Guus Sliepen Drop support for localisation.
authored
193 ifdebug(TRAFFIC) logger(LOG_INFO, "Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx",
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
194 address->x[0], address->x[1], address->x[2], address->x[3],
195 address->x[4], address->x[5]);
196
197 subnet = new_subnet();
198 subnet->type = SUBNET_MAC;
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
199 subnet->expires = now + macexpire;
200 subnet->net.mac.address = *address;
43a6e78 Guus Sliepen Handle weighted Subnets in switch and hub modes.
authored
201 subnet->weight = 10;
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
202 subnet_add(myself, subnet);
469fa31 Guus Sliepen Run subnet-up/down scripts for local MAC addresses as well.
authored
203 subnet_update(myself, subnet, true);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
204
205 /* And tell all other tinc daemons it's our MAC */
206
207 for(node = connection_tree->head; node; node = node->next) {
6c5f3d8 Guus Sliepen We don't have to tell GCC how to cast.
authored
208 c = node->data;
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
209 if(c->status.active)
210 send_add_subnet(c, subnet);
211 }
212 }
213
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
214 if(subnet->expires)
215 subnet->expires = now + macexpire;
14979f8 Guus Sliepen - Global time_t now, so that we don't have to call time() too often.
authored
216 }
217
5dde646 Guus Sliepen K&R style braces.
authored
218 void age_subnets(void) {
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
219 subnet_t *s;
220 connection_t *c;
221 avl_node_t *node, *next, *node2;
222
223 for(node = myself->subnet_tree->head; node; node = next) {
224 next = node->next;
6c5f3d8 Guus Sliepen We don't have to tell GCC how to cast.
authored
225 s = node->data;
50af33d loicco Nearly tickless tinc.
loicco authored
226 if(s->expires && s->expires <= now) {
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
227 ifdebug(TRAFFIC) {
228 char netstr[MAXNETSTR];
229 if(net2str(netstr, sizeof netstr, s))
4c85542 Guus Sliepen Drop support for localisation.
authored
230 logger(LOG_INFO, "Subnet %s expired", netstr);
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
231 }
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
232
233 for(node2 = connection_tree->head; node2; node2 = node2->next) {
6c5f3d8 Guus Sliepen We don't have to tell GCC how to cast.
authored
234 c = node2->data;
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
235 if(c->status.active)
236 send_del_subnet(c, s);
237 }
238
469fa31 Guus Sliepen Run subnet-up/down scripts for local MAC addresses as well.
authored
239 subnet_update(myself, s, false);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
240 subnet_del(myself, s);
241 }
14979f8 Guus Sliepen - Global time_t now, so that we don't have to call time() too often.
authored
242 }
07a08f5 Guus Sliepen - Reinstated a queue for outgoing packets.
authored
243 }
244
7d21a8d Guus Sliepen - Speed up checksumming
authored
245 /* RFC 792 */
246
5dde646 Guus Sliepen K&R style braces.
authored
247 static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, uint8_t type, uint8_t code) {
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
248 struct ip ip = {0};
249 struct icmp icmp = {0};
7d21a8d Guus Sliepen - Speed up checksumming
authored
250
251 struct in_addr ip_src;
252 struct in_addr ip_dst;
253 uint32_t oldlen;
254
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
255 if(ratelimit(3))
7d21a8d Guus Sliepen - Speed up checksumming
authored
256 return;
257
9915f2a Guus Sliepen Handle unicast packets larger than PMTU in switch mode.
authored
258 /* Swap Ethernet source and destination addresses */
259
260 swap_mac_addresses(packet);
261
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
262 /* Copy headers from packet into properly aligned structs on the stack */
263
264 memcpy(&ip, packet->data + ether_size, ip_size);
7d21a8d Guus Sliepen - Speed up checksumming
authored
265
266 /* Remember original source and destination */
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
267
268 ip_src = ip.ip_src;
269 ip_dst = ip.ip_dst;
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
270
271 oldlen = packet->len - ether_size;
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
272
6b12bea Guus Sliepen Let tinc figure out the exact MTU of the link.
authored
273 if(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
274 icmp.icmp_nextmtu = htons(packet->len - ether_size);
275
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
276 if(oldlen >= IP_MSS - ip_size - icmp_size)
277 oldlen = IP_MSS - ip_size - icmp_size;
7d21a8d Guus Sliepen - Speed up checksumming
authored
278
279 /* Copy first part of original contents to ICMP message */
280
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
281 memmove(packet->data + ether_size + ip_size + icmp_size, packet->data + ether_size, oldlen);
7d21a8d Guus Sliepen - Speed up checksumming
authored
282
283 /* Fill in IPv4 header */
284
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
285 ip.ip_v = 4;
286 ip.ip_hl = ip_size / 4;
287 ip.ip_tos = 0;
288 ip.ip_len = htons(ip_size + icmp_size + oldlen);
289 ip.ip_id = 0;
290 ip.ip_off = 0;
291 ip.ip_ttl = 255;
292 ip.ip_p = IPPROTO_ICMP;
293 ip.ip_sum = 0;
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
294 ip.ip_src = ip_dst;
295 ip.ip_dst = ip_src;
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
296
297 ip.ip_sum = inet_checksum(&ip, ip_size, ~0);
7d21a8d Guus Sliepen - Speed up checksumming
authored
298
299 /* Fill in ICMP header */
300
6b12bea Guus Sliepen Let tinc figure out the exact MTU of the link.
authored
301 icmp.icmp_type = type;
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
302 icmp.icmp_code = code;
303 icmp.icmp_cksum = 0;
7d21a8d Guus Sliepen - Speed up checksumming
authored
304
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
305 icmp.icmp_cksum = inet_checksum(&icmp, icmp_size, ~0);
306 icmp.icmp_cksum = inet_checksum(packet->data + ether_size + ip_size + icmp_size, oldlen, icmp.icmp_cksum);
307
308 /* Copy structs on stack back to packet */
309
310 memcpy(packet->data + ether_size, &ip, ip_size);
311 memcpy(packet->data + ether_size + ip_size, &icmp, icmp_size);
7d21a8d Guus Sliepen - Speed up checksumming
authored
312
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
313 packet->len = ether_size + ip_size + icmp_size + oldlen;
6b12bea Guus Sliepen Let tinc figure out the exact MTU of the link.
authored
314
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
315 send_packet(source, packet);
7d21a8d Guus Sliepen - Speed up checksumming
authored
316 }
317
3539978 Guus Sliepen Improvements for PMTU discovery and IPv4 packet fragmentation.
authored
318 /* RFC 791 */
319
d02d81f Guus Sliepen Let compiler decide when to inline.
authored
320 static void fragment_ipv4_packet(node_t *dest, vpn_packet_t *packet) {
3539978 Guus Sliepen Improvements for PMTU discovery and IPv4 packet fragmentation.
authored
321 struct ip ip;
322 vpn_packet_t fragment;
323 int len, maxlen, todo;
324 uint8_t *offset;
325 uint16_t ip_off, origf;
326
327 memcpy(&ip, packet->data + ether_size, ip_size);
328 fragment.priority = packet->priority;
329
330 if(ip.ip_hl != ip_size / 4)
331 return;
332
333 todo = ntohs(ip.ip_len) - ip_size;
334
335 if(ether_size + ip_size + todo != packet->len) {
4c85542 Guus Sliepen Drop support for localisation.
authored
336 ifdebug(TRAFFIC) logger(LOG_WARNING, "Length of packet (%d) doesn't match length in IPv4 header (%zd)", packet->len, ether_size + ip_size + todo);
3539978 Guus Sliepen Improvements for PMTU discovery and IPv4 packet fragmentation.
authored
337 return;
338 }
339
4c85542 Guus Sliepen Drop support for localisation.
authored
340 ifdebug(TRAFFIC) logger(LOG_INFO, "Fragmenting packet of %d bytes to %s (%s)", packet->len, dest->name, dest->hostname);
3539978 Guus Sliepen Improvements for PMTU discovery and IPv4 packet fragmentation.
authored
341
342 offset = packet->data + ether_size + ip_size;
343 maxlen = (dest->mtu - ether_size - ip_size) & ~0x7;
344 ip_off = ntohs(ip.ip_off);
345 origf = ip_off & ~IP_OFFMASK;
346 ip_off &= IP_OFFMASK;
347
348 while(todo) {
349 len = todo > maxlen ? maxlen : todo;
350 memcpy(fragment.data + ether_size + ip_size, offset, len);
351 todo -= len;
352 offset += len;
353
354 ip.ip_len = htons(ip_size + len);
355 ip.ip_off = htons(ip_off | origf | (todo ? IP_MF : 0));
356 ip.ip_sum = 0;
357 ip.ip_sum = inet_checksum(&ip, ip_size, ~0);
358 memcpy(fragment.data, packet->data, ether_size);
359 memcpy(fragment.data + ether_size, &ip, ip_size);
360 fragment.len = ether_size + ip_size + len;
361
362 send_packet(dest, &fragment);
363
364 ip_off += len / 8;
365 }
366 }
367
5dde646 Guus Sliepen K&R style braces.
authored
368 static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
369 subnet_t *subnet;
aebc97a Guus Sliepen Small fixes for PMTU discovery.
authored
370 node_t *via;
134dc89 Guus Sliepen memcpy() addresses from packet headers before calling the lookup functio...
authored
371 ipv4_t dest;
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
372
134dc89 Guus Sliepen memcpy() addresses from packet headers before calling the lookup functio...
authored
373 memcpy(&dest, &packet->data[30], sizeof dest);
374 subnet = lookup_subnet_ipv4(&dest);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
375
376 if(!subnet) {
4c85542 Guus Sliepen Drop support for localisation.
authored
377 ifdebug(TRAFFIC) logger(LOG_WARNING, "Cannot route packet from %s (%s): unknown IPv4 destination address %d.%d.%d.%d",
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
378 source->name, source->hostname,
134dc89 Guus Sliepen memcpy() addresses from packet headers before calling the lookup functio...
authored
379 dest.x[0],
380 dest.x[1],
381 dest.x[2],
382 dest.x[3]);
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
383
6b12bea Guus Sliepen Let tinc figure out the exact MTU of the link.
authored
384 route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_UNKNOWN);
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
385 return;
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
386 }
7d21a8d Guus Sliepen - Speed up checksumming
authored
387
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
388 if(subnet->owner == source) {
4c85542 Guus Sliepen Drop support for localisation.
authored
389 ifdebug(TRAFFIC) logger(LOG_WARNING, "Packet looping back to %s (%s)!", source->name, source->hostname);
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
390 return;
391 }
392
7d21a8d Guus Sliepen - Speed up checksumming
authored
393 if(!subnet->owner->status.reachable)
95a6974 Guus Sliepen Add the Forwarding option.
authored
394 return route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_UNREACH);
395
396 if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
397 return route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_ANO);
6b12bea Guus Sliepen Let tinc figure out the exact MTU of the link.
authored
398
3539978 Guus Sliepen Improvements for PMTU discovery and IPv4 packet fragmentation.
authored
399 if(priorityinheritance)
400 packet->priority = packet->data[15];
401
aebc97a Guus Sliepen Small fixes for PMTU discovery.
authored
402 via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
5140656 Guus Sliepen Stricter checks against routing loops.
authored
403
404 if(via == source) {
405 ifdebug(TRAFFIC) logger(LOG_ERR, "Routing loop for packet from %s (%s)!", source->name, source->hostname);
406 return;
407 }
aebc97a Guus Sliepen Small fixes for PMTU discovery.
authored
408
3e4829e Guus Sliepen Add the DirectOnly option.
authored
409 if(directonly && subnet->owner != via)
410 return route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_ANO);
411
a9bbb33 Guus Sliepen Fixes for definitions under Windows.
authored
412 if(via && packet->len > MAX(via->mtu, 590) && via != myself) {
4c85542 Guus Sliepen Drop support for localisation.
authored
413 ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
3539978 Guus Sliepen Improvements for PMTU discovery and IPv4 packet fragmentation.
authored
414 if(packet->data[20] & 0x40) {
a9bbb33 Guus Sliepen Fixes for definitions under Windows.
authored
415 packet->len = MAX(via->mtu, 590);
3539978 Guus Sliepen Improvements for PMTU discovery and IPv4 packet fragmentation.
authored
416 route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
417 } else {
aebc97a Guus Sliepen Small fixes for PMTU discovery.
authored
418 fragment_ipv4_packet(via, packet);
3539978 Guus Sliepen Improvements for PMTU discovery and IPv4 packet fragmentation.
authored
419 }
420
6b12bea Guus Sliepen Let tinc figure out the exact MTU of the link.
authored
421 return;
422 }
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
423
95928f7 Guus Sliepen Also clamp MSS of TCP over IPv6 packets.
authored
424 clamp_mss(source, via, packet);
2a538ed Guus Sliepen Clamp MSS of IPv4 SYN packets.
authored
425
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
426 send_packet(subnet->owner, packet);
427 }
428
5dde646 Guus Sliepen K&R style braces.
authored
429 static void route_ipv4(node_t *source, vpn_packet_t *packet) {
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
430 if(!checklength(source, packet, ether_size + ip_size))
431 return;
432
84531fb Guus Sliepen Allow broadcast packets to be sent directly instead of via the MST.
authored
433 if(broadcast_mode && (((packet->data[30] & 0xf0) == 0xe0) || (
de03205 Guus Sliepen Handle broadcast and multicast packets in router mode.
authored
434 packet->data[30] == 255 &&
435 packet->data[31] == 255 &&
436 packet->data[32] == 255 &&
8420a0c Guus Sliepen Allow disabling of broadcast packets.
authored
437 packet->data[33] == 255)))
de03205 Guus Sliepen Handle broadcast and multicast packets in router mode.
authored
438 broadcast_packet(source, packet);
439 else
440 route_ipv4_unicast(source, packet);
c46e848 Guus Sliepen - route.c will contain the routing logic.
authored
441 }
442
7d21a8d Guus Sliepen - Speed up checksumming
authored
443 /* RFC 2463 */
444
5dde646 Guus Sliepen K&R style braces.
authored
445 static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, uint8_t type, uint8_t code) {
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
446 struct ip6_hdr ip6;
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
447 struct icmp6_hdr icmp6 = {0};
7d21a8d Guus Sliepen - Speed up checksumming
authored
448 uint16_t checksum;
449
450 struct {
451 struct in6_addr ip6_src; /* source address */
452 struct in6_addr ip6_dst; /* destination address */
453 uint32_t length;
454 uint32_t next;
455 } pseudo;
456
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
457 if(ratelimit(3))
7d21a8d Guus Sliepen - Speed up checksumming
authored
458 return;
459
9915f2a Guus Sliepen Handle unicast packets larger than PMTU in switch mode.
authored
460 /* Swap Ethernet source and destination addresses */
461
462 swap_mac_addresses(packet);
463
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
464 /* Copy headers from packet to structs on the stack */
465
466 memcpy(&ip6, packet->data + ether_size, ip6_size);
7d21a8d Guus Sliepen - Speed up checksumming
authored
467
468 /* Remember original source and destination */
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
469
470 pseudo.ip6_src = ip6.ip6_dst;
471 pseudo.ip6_dst = ip6.ip6_src;
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
472
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
473 pseudo.length = packet->len - ether_size;
6b12bea Guus Sliepen Let tinc figure out the exact MTU of the link.
authored
474
475 if(type == ICMP6_PACKET_TOO_BIG)
476 icmp6.icmp6_mtu = htonl(pseudo.length);
7d21a8d Guus Sliepen - Speed up checksumming
authored
477
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
478 if(pseudo.length >= IP_MSS - ip6_size - icmp6_size)
479 pseudo.length = IP_MSS - ip6_size - icmp6_size;
7d21a8d Guus Sliepen - Speed up checksumming
authored
480
481 /* Copy first part of original contents to ICMP message */
482
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
483 memmove(packet->data + ether_size + ip6_size + icmp6_size, packet->data + ether_size, pseudo.length);
7d21a8d Guus Sliepen - Speed up checksumming
authored
484
485 /* Fill in IPv6 header */
486
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
487 ip6.ip6_flow = htonl(0x60000000UL);
488 ip6.ip6_plen = htons(icmp6_size + pseudo.length);
489 ip6.ip6_nxt = IPPROTO_ICMPV6;
490 ip6.ip6_hlim = 255;
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
491 ip6.ip6_src = pseudo.ip6_src;
492 ip6.ip6_dst = pseudo.ip6_dst;
7d21a8d Guus Sliepen - Speed up checksumming
authored
493
494 /* Fill in ICMP header */
495
6b12bea Guus Sliepen Let tinc figure out the exact MTU of the link.
authored
496 icmp6.icmp6_type = type;
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
497 icmp6.icmp6_code = code;
498 icmp6.icmp6_cksum = 0;
7d21a8d Guus Sliepen - Speed up checksumming
authored
499
500 /* Create pseudo header */
501
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
502 pseudo.length = htonl(icmp6_size + pseudo.length);
7d21a8d Guus Sliepen - Speed up checksumming
authored
503 pseudo.next = htonl(IPPROTO_ICMPV6);
504
505 /* Generate checksum */
506
507 checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
508 checksum = inet_checksum(&icmp6, icmp6_size, checksum);
509 checksum = inet_checksum(packet->data + ether_size + ip6_size + icmp6_size, ntohl(pseudo.length) - icmp6_size, checksum);
7d21a8d Guus Sliepen - Speed up checksumming
authored
510
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
511 icmp6.icmp6_cksum = checksum;
512
513 /* Copy structs on stack back to packet */
514
515 memcpy(packet->data + ether_size, &ip6, ip6_size);
516 memcpy(packet->data + ether_size + ip6_size, &icmp6, icmp6_size);
7d21a8d Guus Sliepen - Speed up checksumming
authored
517
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
518 packet->len = ether_size + ip6_size + ntohl(pseudo.length);
7d21a8d Guus Sliepen - Speed up checksumming
authored
519
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
520 send_packet(source, packet);
7d21a8d Guus Sliepen - Speed up checksumming
authored
521 }
522
5dde646 Guus Sliepen K&R style braces.
authored
523 static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) {
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
524 subnet_t *subnet;
aebc97a Guus Sliepen Small fixes for PMTU discovery.
authored
525 node_t *via;
134dc89 Guus Sliepen memcpy() addresses from packet headers before calling the lookup functio...
authored
526 ipv6_t dest;
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
527
134dc89 Guus Sliepen memcpy() addresses from packet headers before calling the lookup functio...
authored
528 memcpy(&dest, &packet->data[38], sizeof dest);
529 subnet = lookup_subnet_ipv6(&dest);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
530
531 if(!subnet) {
4c85542 Guus Sliepen Drop support for localisation.
authored
532 ifdebug(TRAFFIC) logger(LOG_WARNING, "Cannot route packet from %s (%s): unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
533 source->name, source->hostname,
134dc89 Guus Sliepen memcpy() addresses from packet headers before calling the lookup functio...
authored
534 ntohs(dest.x[0]),
535 ntohs(dest.x[1]),
536 ntohs(dest.x[2]),
537 ntohs(dest.x[3]),
538 ntohs(dest.x[4]),
539 ntohs(dest.x[5]),
540 ntohs(dest.x[6]),
541 ntohs(dest.x[7]));
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
542
6b12bea Guus Sliepen Let tinc figure out the exact MTU of the link.
authored
543 route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR);
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
544 return;
545 }
546
547 if(subnet->owner == source) {
4c85542 Guus Sliepen Drop support for localisation.
authored
548 ifdebug(TRAFFIC) logger(LOG_WARNING, "Packet looping back to %s (%s)!", source->name, source->hostname);
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
549 return;
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
550 }
551
7d21a8d Guus Sliepen - Speed up checksumming
authored
552 if(!subnet->owner->status.reachable)
95a6974 Guus Sliepen Add the Forwarding option.
authored
553 return route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE);
554
555 if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
556 return route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
aebc97a Guus Sliepen Small fixes for PMTU discovery.
authored
557
558 via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
8681047 Guus Sliepen Check for IPv6 header files.
authored
559
5140656 Guus Sliepen Stricter checks against routing loops.
authored
560 if(via == source) {
561 ifdebug(TRAFFIC) logger(LOG_ERR, "Routing loop for packet from %s (%s)!", source->name, source->hostname);
562 return;
563 }
564
3e4829e Guus Sliepen Add the DirectOnly option.
authored
565 if(directonly && subnet->owner != via)
566 return route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
567
a9bbb33 Guus Sliepen Fixes for definitions under Windows.
authored
568 if(via && packet->len > MAX(via->mtu, 1294) && via != myself) {
4c85542 Guus Sliepen Drop support for localisation.
authored
569 ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
a9bbb33 Guus Sliepen Fixes for definitions under Windows.
authored
570 packet->len = MAX(via->mtu, 1294);
6b12bea Guus Sliepen Let tinc figure out the exact MTU of the link.
authored
571 route_ipv6_unreachable(source, packet, ICMP6_PACKET_TOO_BIG, 0);
572 return;
573 }
574
95928f7 Guus Sliepen Also clamp MSS of TCP over IPv6 packets.
authored
575 clamp_mss(source, via, packet);
576
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
577 send_packet(subnet->owner, packet);
578 }
579
7d21a8d Guus Sliepen - Speed up checksumming
authored
580 /* RFC 2461 */
f219f15 Guus Sliepen Put #ifdef NEIGHBORSOL around corresponding code.
authored
581
5dde646 Guus Sliepen K&R style braces.
authored
582 static void route_neighborsol(node_t *source, vpn_packet_t *packet) {
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
583 struct ip6_hdr ip6;
584 struct nd_neighbor_solicit ns;
585 struct nd_opt_hdr opt;
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
586 subnet_t *subnet;
587 uint16_t checksum;
1c1a67f Guus Sliepen Handle neighbor solicitation requests without link layer addresses.
authored
588 bool has_opt;
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
589
590 struct {
591 struct in6_addr ip6_src; /* source address */
592 struct in6_addr ip6_dst; /* destination address */
593 uint32_t length;
7d21a8d Guus Sliepen - Speed up checksumming
authored
594 uint32_t next;
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
595 } pseudo;
596
1c1a67f Guus Sliepen Handle neighbor solicitation requests without link layer addresses.
authored
597 if(!checklength(source, packet, ether_size + ip6_size + ns_size))
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
598 return;
599
1c1a67f Guus Sliepen Handle neighbor solicitation requests without link layer addresses.
authored
600 has_opt = packet->len >= ether_size + ip6_size + ns_size + opt_size + ETH_ALEN;
601
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
602 if(source != myself) {
4c85542 Guus Sliepen Drop support for localisation.
authored
603 ifdebug(TRAFFIC) logger(LOG_WARNING, "Got neighbor solicitation request from %s (%s) while in router mode!", source->name, source->hostname);
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
604 return;
605 }
606
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
607 /* Copy headers from packet to structs on the stack */
608
609 memcpy(&ip6, packet->data + ether_size, ip6_size);
610 memcpy(&ns, packet->data + ether_size + ip6_size, ns_size);
1c1a67f Guus Sliepen Handle neighbor solicitation requests without link layer addresses.
authored
611 if(has_opt)
612 memcpy(&opt, packet->data + ether_size + ip6_size + ns_size, opt_size);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
613
614 /* First, snatch the source address from the neighbor solicitation packet */
615
12de5a8 Guus Sliepen Remove mymac stuff from device.c.
authored
616 if(overwrite_mac)
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
617 memcpy(mymac.x, packet->data + ETH_ALEN, ETH_ALEN);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
618
619 /* Check if this is a valid neighbor solicitation request */
620
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
621 if(ns.nd_ns_hdr.icmp6_type != ND_NEIGHBOR_SOLICIT ||
1c1a67f Guus Sliepen Handle neighbor solicitation requests without link layer addresses.
authored
622 (has_opt && opt.nd_opt_type != ND_OPT_SOURCE_LINKADDR)) {
4c85542 Guus Sliepen Drop support for localisation.
authored
623 ifdebug(TRAFFIC) logger(LOG_WARNING, "Cannot route packet: received unknown type neighbor solicitation request");
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
624 return;
625 }
626
627 /* Create pseudo header */
628
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
629 pseudo.ip6_src = ip6.ip6_src;
630 pseudo.ip6_dst = ip6.ip6_dst;
1c1a67f Guus Sliepen Handle neighbor solicitation requests without link layer addresses.
authored
631 if(has_opt)
632 pseudo.length = htonl(ns_size + opt_size + ETH_ALEN);
633 else
634 pseudo.length = htonl(ns_size);
7d21a8d Guus Sliepen - Speed up checksumming
authored
635 pseudo.next = htonl(IPPROTO_ICMPV6);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
636
637 /* Generate checksum */
638
7d21a8d Guus Sliepen - Speed up checksumming
authored
639 checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
640 checksum = inet_checksum(&ns, ns_size, checksum);
1c1a67f Guus Sliepen Handle neighbor solicitation requests without link layer addresses.
authored
641 if(has_opt) {
642 checksum = inet_checksum(&opt, opt_size, checksum);
643 checksum = inet_checksum(packet->data + ether_size + ip6_size + ns_size + opt_size, ETH_ALEN, checksum);
644 }
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
645
646 if(checksum) {
4c85542 Guus Sliepen Drop support for localisation.
authored
647 ifdebug(TRAFFIC) logger(LOG_WARNING, "Cannot route packet: checksum error for neighbor solicitation request");
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
648 return;
649 }
650
651 /* Check if the IPv6 address exists on the VPN */
652
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
653 subnet = lookup_subnet_ipv6((ipv6_t *) &ns.nd_ns_target);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
654
655 if(!subnet) {
4c85542 Guus Sliepen Drop support for localisation.
authored
656 ifdebug(TRAFFIC) logger(LOG_WARNING, "Cannot route packet: neighbor solicitation request for unknown address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
657 ntohs(((uint16_t *) &ns.nd_ns_target)[0]),
658 ntohs(((uint16_t *) &ns.nd_ns_target)[1]),
659 ntohs(((uint16_t *) &ns.nd_ns_target)[2]),
660 ntohs(((uint16_t *) &ns.nd_ns_target)[3]),
661 ntohs(((uint16_t *) &ns.nd_ns_target)[4]),
662 ntohs(((uint16_t *) &ns.nd_ns_target)[5]),
663 ntohs(((uint16_t *) &ns.nd_ns_target)[6]),
664 ntohs(((uint16_t *) &ns.nd_ns_target)[7]));
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
665
666 return;
667 }
668
669 /* Check if it is for our own subnet */
670
671 if(subnet->owner == myself)
672 return; /* silently ignore */
673
674 /* Create neighbor advertation reply */
675
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
676 memcpy(packet->data, packet->data + ETH_ALEN, ETH_ALEN); /* copy destination address */
677 packet->data[ETH_ALEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
678
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
679 ip6.ip6_dst = ip6.ip6_src; /* swap destination and source protocoll address */
680 ip6.ip6_src = ns.nd_ns_target;
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
681
1c1a67f Guus Sliepen Handle neighbor solicitation requests without link layer addresses.
authored
682 if(has_opt)
683 memcpy(packet->data + ether_size + ip6_size + ns_size + opt_size, packet->data + ETH_ALEN, ETH_ALEN); /* add fake source hard addr */
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
684
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
685 ns.nd_ns_cksum = 0;
686 ns.nd_ns_type = ND_NEIGHBOR_ADVERT;
687 ns.nd_ns_reserved = htonl(0x40000000UL); /* Set solicited flag */
688 opt.nd_opt_type = ND_OPT_TARGET_LINKADDR;
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
689
690 /* Create pseudo header */
691
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
692 pseudo.ip6_src = ip6.ip6_src;
693 pseudo.ip6_dst = ip6.ip6_dst;
1c1a67f Guus Sliepen Handle neighbor solicitation requests without link layer addresses.
authored
694 if(has_opt)
695 pseudo.length = htonl(ns_size + opt_size + ETH_ALEN);
696 else
697 pseudo.length = htonl(ns_size);
7d21a8d Guus Sliepen - Speed up checksumming
authored
698 pseudo.next = htonl(IPPROTO_ICMPV6);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
699
700 /* Generate checksum */
701
7d21a8d Guus Sliepen - Speed up checksumming
authored
702 checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
703 checksum = inet_checksum(&ns, ns_size, checksum);
1c1a67f Guus Sliepen Handle neighbor solicitation requests without link layer addresses.
authored
704 if(has_opt) {
705 checksum = inet_checksum(&opt, opt_size, checksum);
706 checksum = inet_checksum(packet->data + ether_size + ip6_size + ns_size + opt_size, ETH_ALEN, checksum);
707 }
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
708
709 ns.nd_ns_hdr.icmp6_cksum = checksum;
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
710
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
711 /* Copy structs on stack back to packet */
712
713 memcpy(packet->data + ether_size, &ip6, ip6_size);
714 memcpy(packet->data + ether_size + ip6_size, &ns, ns_size);
1c1a67f Guus Sliepen Handle neighbor solicitation requests without link layer addresses.
authored
715 if(has_opt)
716 memcpy(packet->data + ether_size + ip6_size + ns_size, &opt, opt_size);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
717
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
718 send_packet(source, packet);
719 }
720
5dde646 Guus Sliepen K&R style braces.
authored
721 static void route_ipv6(node_t *source, vpn_packet_t *packet) {
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
722 if(!checklength(source, packet, ether_size + ip6_size))
723 return;
724
725 if(packet->data[20] == IPPROTO_ICMPV6 && checklength(source, packet, ether_size + ip6_size + icmp6_size) && packet->data[54] == ND_NEIGHBOR_SOLICIT) {
726 route_neighborsol(source, packet);
727 return;
728 }
729
84531fb Guus Sliepen Allow broadcast packets to be sent directly instead of via the MST.
authored
730 if(broadcast_mode && packet->data[38] == 255)
de03205 Guus Sliepen Handle broadcast and multicast packets in router mode.
authored
731 broadcast_packet(source, packet);
732 else
733 route_ipv6_unicast(source, packet);
46fa10c Guus Sliepen Try to reply to neighbor solicitation requests.
authored
734 }
735
7d21a8d Guus Sliepen - Speed up checksumming
authored
736 /* RFC 826 */
737
5dde646 Guus Sliepen K&R style braces.
authored
738 static void route_arp(node_t *source, vpn_packet_t *packet) {
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
739 struct ether_arp arp;
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
740 subnet_t *subnet;
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
741 struct in_addr addr;
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
742
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
743 if(!checklength(source, packet, ether_size + arp_size))
744 return;
745
746 if(source != myself) {
4c85542 Guus Sliepen Drop support for localisation.
authored
747 ifdebug(TRAFFIC) logger(LOG_WARNING, "Got ARP request from %s (%s) while in router mode!", source->name, source->hostname);
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
748 return;
749 }
750
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
751 /* First, snatch the source address from the ARP packet */
752
12de5a8 Guus Sliepen Remove mymac stuff from device.c.
authored
753 if(overwrite_mac)
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
754 memcpy(mymac.x, packet->data + ETH_ALEN, ETH_ALEN);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
755
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
756 /* Copy headers from packet to structs on the stack */
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
757
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
758 memcpy(&arp, packet->data + ether_size, arp_size);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
759
760 /* Check if this is a valid ARP request */
761
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
762 if(ntohs(arp.arp_hrd) != ARPHRD_ETHER || ntohs(arp.arp_pro) != ETH_P_IP ||
763 arp.arp_hln != ETH_ALEN || arp.arp_pln != sizeof(addr) || ntohs(arp.arp_op) != ARPOP_REQUEST) {
4c85542 Guus Sliepen Drop support for localisation.
authored
764 ifdebug(TRAFFIC) logger(LOG_WARNING, "Cannot route packet: received unknown type ARP request");
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
765 return;
766 }
767
768 /* Check if the IPv4 address exists on the VPN */
769
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
770 subnet = lookup_subnet_ipv4((ipv4_t *) &arp.arp_tpa);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
771
772 if(!subnet) {
4c85542 Guus Sliepen Drop support for localisation.
authored
773 ifdebug(TRAFFIC) logger(LOG_WARNING, "Cannot route packet: ARP request for unknown address %d.%d.%d.%d",
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
774 arp.arp_tpa[0], arp.arp_tpa[1], arp.arp_tpa[2],
775 arp.arp_tpa[3]);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
776 return;
777 }
778
779 /* Check if it is for our own subnet */
780
781 if(subnet->owner == myself)
782 return; /* silently ignore */
783
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
784 memcpy(packet->data, packet->data + ETH_ALEN, ETH_ALEN); /* copy destination address */
785 packet->data[ETH_ALEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
786
787 memcpy(&addr, arp.arp_tpa, sizeof(addr)); /* save protocol addr */
788 memcpy(arp.arp_tpa, arp.arp_spa, sizeof(addr)); /* swap destination and source protocol address */
789 memcpy(arp.arp_spa, &addr, sizeof(addr)); /* ... */
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
790
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
791 memcpy(arp.arp_tha, arp.arp_sha, ETH_ALEN); /* set target hard/proto addr */
792 memcpy(arp.arp_sha, packet->data + ETH_ALEN, ETH_ALEN); /* add fake source hard addr */
793 arp.arp_op = htons(ARPOP_REPLY);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
794
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
795 /* Copy structs on stack back to packet */
796
797 memcpy(packet->data + ether_size, &arp, arp_size);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
798
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
799 send_packet(source, packet);
428482d Guus Sliepen Added proxy-arp support. No more ifconfig -arp needed. Works like a char...
authored
800 }
801
5dde646 Guus Sliepen K&R style braces.
authored
802 static void route_mac(node_t *source, vpn_packet_t *packet) {
9915f2a Guus Sliepen Handle unicast packets larger than PMTU in switch mode.
authored
803 subnet_t *subnet;
804 mac_t dest;
805
806 /* Learn source address */
807
808 if(source == myself) {
809 mac_t src;
810 memcpy(&src, &packet->data[6], sizeof src);
811 learn_mac(&src);
812 }
813
814 /* Lookup destination address */
815
816 memcpy(&dest, &packet->data[0], sizeof dest);
92aefd2 Guus Sliepen When learning MAC addresses, only check our own Subnets for previous ent...
authored
817 subnet = lookup_subnet_mac(NULL, &dest);
9915f2a Guus Sliepen Handle unicast packets larger than PMTU in switch mode.
authored
818
819 if(!subnet) {
84531fb Guus Sliepen Allow broadcast packets to be sent directly instead of via the MST.
authored
820 broadcast_packet(source, packet);
9915f2a Guus Sliepen Handle unicast packets larger than PMTU in switch mode.
authored
821 return;
822 }
823
824 if(subnet->owner == source) {
4c85542 Guus Sliepen Drop support for localisation.
authored
825 ifdebug(TRAFFIC) logger(LOG_WARNING, "Packet looping back to %s (%s)!", source->name, source->hostname);
9915f2a Guus Sliepen Handle unicast packets larger than PMTU in switch mode.
authored
826 return;
827 }
828
95a6974 Guus Sliepen Add the Forwarding option.
authored
829 if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
830 return;
831
9915f2a Guus Sliepen Handle unicast packets larger than PMTU in switch mode.
authored
832 // Handle packets larger than PMTU
833
834 node_t *via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
3e4829e Guus Sliepen Add the DirectOnly option.
authored
835
836 if(directonly && subnet->owner != via)
837 return;
9915f2a Guus Sliepen Handle unicast packets larger than PMTU in switch mode.
authored
838
839 if(via && packet->len > via->mtu && via != myself) {
4c85542 Guus Sliepen Drop support for localisation.
authored
840 ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
9915f2a Guus Sliepen Handle unicast packets larger than PMTU in switch mode.
authored
841 uint16_t type = packet->data[12] << 8 | packet->data[13];
43e34d8 Guus Sliepen Do not fragment packets smaller than RFC defined minimum MTUs.
authored
842 if(type == ETH_P_IP && packet->len > 590) {
9915f2a Guus Sliepen Handle unicast packets larger than PMTU in switch mode.
authored
843 if(packet->data[20] & 0x40) {
844 packet->len = via->mtu;
845 route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
846 } else {
847 fragment_ipv4_packet(via, packet);
848 }
b5ccce2 Guus Sliepen Send large packets we cannot handle properly via TCP.
authored
849 return;
43e34d8 Guus Sliepen Do not fragment packets smaller than RFC defined minimum MTUs.
authored
850 } else if(type == ETH_P_IPV6 && packet->len > 1294) {
9915f2a Guus Sliepen Handle unicast packets larger than PMTU in switch mode.
authored
851 packet->len = via->mtu;
852 route_ipv6_unreachable(source, packet, ICMP6_PACKET_TOO_BIG, 0);
b5ccce2 Guus Sliepen Send large packets we cannot handle properly via TCP.
authored
853 return;
854 }
9915f2a Guus Sliepen Handle unicast packets larger than PMTU in switch mode.
authored
855 }
856
95928f7 Guus Sliepen Also clamp MSS of TCP over IPv6 packets.
authored
857 clamp_mss(source, via, packet);
2a538ed Guus Sliepen Clamp MSS of IPv4 SYN packets.
authored
858
9915f2a Guus Sliepen Handle unicast packets larger than PMTU in switch mode.
authored
859 send_packet(subnet->owner, packet);
860 }
861
0233b1d Guus Sliepen Decrement TTL of incoming packets.
authored
862 static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) {
863 uint16_t type = packet->data[12] << 8 | packet->data[13];
864
865 switch (type) {
866 case ETH_P_IP:
867 if(!checklength(source, packet, 14 + 32))
868 return false;
869
870 if(packet->data[22] < 1) {
f1d5eae Guus Sliepen Don't send ICMP Time Exceeded messages for other Time Exceeded messages.
authored
871 if(packet->data[25] != IPPROTO_ICMP || packet->data[46] != ICMP_TIME_EXCEEDED)
872 route_ipv4_unreachable(source, packet, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL);
0233b1d Guus Sliepen Decrement TTL of incoming packets.
authored
873 return false;
874 }
875
876 uint16_t old = packet->data[22] << 8 | packet->data[23];
877 packet->data[22]--;
878 uint16_t new = packet->data[22] << 8 | packet->data[23];
879
880 uint32_t checksum = packet->data[24] << 8 | packet->data[25];
881 checksum += old + (~new & 0xFFFF);
882 while(checksum >> 16)
883 checksum = (checksum & 0xFFFF) + (checksum >> 16);
884 packet->data[24] = checksum >> 8;
885 packet->data[25] = checksum & 0xff;
886
887 return true;
888
889 case ETH_P_IPV6:
890 if(!checklength(source, packet, 14 + 40))
891 return false;
892
893 if(packet->data[21] < 1) {
f1d5eae Guus Sliepen Don't send ICMP Time Exceeded messages for other Time Exceeded messages.
authored
894 if(packet->data[20] != IPPROTO_ICMPV6 || packet->data[54] != ICMP6_TIME_EXCEEDED)
895 route_ipv6_unreachable(source, packet, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT);
0233b1d Guus Sliepen Decrement TTL of incoming packets.
authored
896 return false;
897 }
898
899 packet->data[21]--;
900
901 return true;
902
903 default:
904 return true;
905 }
906 }
907
5dde646 Guus Sliepen K&R style braces.
authored
908 void route(node_t *source, vpn_packet_t *packet) {
8ae54dc Guus Sliepen Fixes for the Forwarding option.
authored
909 if(forwarding_mode == FMODE_KERNEL && source != myself) {
95a6974 Guus Sliepen Add the Forwarding option.
authored
910 send_packet(myself, packet);
911 return;
912 }
913
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
914 if(!checklength(source, packet, ether_size))
288d956 Guus Sliepen Check for short packets from the tun/tap device and from other tinc daem...
authored
915 return;
916
0233b1d Guus Sliepen Decrement TTL of incoming packets.
authored
917 if(decrement_ttl && source != myself)
918 if(!do_decrement_ttl(source, packet))
919 return;
920
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
921 switch (routing_mode) {
922 case RMODE_ROUTER:
923 {
9915f2a Guus Sliepen Handle unicast packets larger than PMTU in switch mode.
authored
924 uint16_t type = packet->data[12] << 8 | packet->data[13];
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
925
926 switch (type) {
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
927 case ETH_P_ARP:
928 route_arp(source, packet);
929 break;
acbb9d6 Guus Sliepen Better length checks.
authored
930
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
931 case ETH_P_IP:
932 route_ipv4(source, packet);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
933 break;
934
6094312 Guus Sliepen Copy structs from packets to the stack before using them, to prevent
authored
935 case ETH_P_IPV6:
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
936 route_ipv6(source, packet);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
937 break;
938
939 default:
4c85542 Guus Sliepen Drop support for localisation.
authored
940 ifdebug(TRAFFIC) logger(LOG_WARNING, "Cannot route packet from %s (%s): unknown type %hx", source->name, source->hostname, type);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
941 break;
942 }
943 }
944 break;
945
946 case RMODE_SWITCH:
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
947 route_mac(source, packet);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
948 break;
949
950 case RMODE_HUB:
5a1406a Guus Sliepen Code beautification, start of multicast support.
authored
951 broadcast_packet(source, packet);
f75dcef Guus Sliepen Switch to K&R style indentation.
authored
952 break;
953 }
07a08f5 Guus Sliepen - Reinstated a queue for outgoing packets.
authored
954 }
Something went wrong with that request. Please try again.