1 : /*
2 : * teredo.c - Common Teredo helper functions
3 : * $Id: teredo.c 1946 2007-04-10 19:23:59Z remi $
4 : *
5 : * See "Teredo: Tunneling IPv6 over UDP through NATs"
6 : * for more information
7 : */
8 :
9 : /***********************************************************************
10 : * Copyright © 2004-2007 Rémi Denis-Courmont. *
11 : * This program is free software; you can redistribute and/or modify *
12 : * it under the terms of the GNU General Public License as published *
13 : * by the Free Software Foundation; version 2 of the license. *
14 : * *
15 : * This program is distributed in the hope that it will be useful, *
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
18 : * See the GNU General Public License for more details. *
19 : * *
20 : * You should have received a copy of the GNU General Public License *
21 : * along with this program; if not, you can get it from: *
22 : * http://www.gnu.org/copyleft/gpl.html *
23 : ***********************************************************************/
24 :
25 : #ifdef HAVE_CONFIG_H
26 : # include <config.h>
27 : #endif
28 :
29 : #include <string.h> // memcpy()
30 :
31 : #include <inttypes.h> /* for Mac OS X */
32 : #include <sys/types.h>
33 : #include <sys/uio.h>
34 : #include <netinet/in.h>
35 : #include <netinet/ip6.h>
36 :
37 : #include <fcntl.h>
38 : #include <sys/socket.h>
39 : #include <errno.h>
40 :
41 : #ifndef SOL_IP
42 : # define SOL_IP IPPROTO_IP
43 : #endif
44 :
45 : #include "teredo.h"
46 : #include "teredo-udp.h"
47 :
48 : /*
49 : * Teredo addresses
50 : */
51 : const struct in6_addr teredo_restrict =
52 : /* Vista variant */
53 : { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0,
54 : 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } };
55 :
56 : /* XP variant */
57 : // { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0,
58 : // 0, 0, 'T', 'E', 'R', 'E', 'D', 'O' } } };
59 :
60 : const struct in6_addr teredo_cone =
61 : { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0,
62 : 0x80, 0, 'T', 'E', 'R', 'E', 'D', 'O' } } };
63 :
64 : /**
65 : * Opens a Teredo UDP/IPv4 socket.
66 : * Thread-safe, not cancellation-safe.
67 : *
68 : * @return -1 on error.
69 : */
70 : int teredo_socket (uint32_t bind_ip, uint16_t port)
71 1 : {
72 : struct sockaddr_in myaddr =
73 : {
74 : .sin_family = AF_INET,
75 : #ifdef HAVE_SA_LEN
76 : .sin_len = sizeof (struct sockaddr_in),
77 : #endif
78 : .sin_port = port,
79 : .sin_addr.s_addr = bind_ip
80 1 : };
81 :
82 1 : int fd = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
83 1 : if (fd == -1)
84 0 : return -1; // failure
85 :
86 1 : fcntl (fd, F_SETFD, FD_CLOEXEC);
87 1 : setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof (int));
88 :
89 1 : if (bind (fd, (struct sockaddr *)&myaddr, sizeof (myaddr)))
90 : {
91 0 : close (fd);
92 0 : return -1;
93 : }
94 :
95 : #ifdef IP_PMTUDISC_DONT
96 : /*
97 : * This tells the (Linux) kernel not to set the Don't Fragment flags
98 : * on UDP packets we send. This is recommended by the Teredo
99 : * specifiation.
100 : */
101 1 : setsockopt (fd, SOL_IP, IP_MTU_DISCOVER, &(int){ IP_PMTUDISC_DONT },
102 : sizeof (int));
103 : #endif
104 : /*
105 : * Teredo multicast packets always have a TTL of 1.
106 : */
107 1 : setsockopt (fd, SOL_IP, IP_MULTICAST_TTL, &(int){ 1 }, sizeof (int));
108 1 : return fd;
109 : }
110 :
111 :
112 : /**
113 : * Sends an UDP/IPv4 datagram.
114 : * Thread-safe, cancellation-safe, cancellation point.
115 : *
116 : * @param fd socket from which to send.
117 : * @param iov scatter-gather array containing the datagram payload.
118 : * @param count number of entry in the scatter-gather array.
119 : * @param dest_ip destination IPv4 (network byte order).
120 : * @param dest_port destination UDP port (network byte order).
121 : *
122 : * @return number of bytes sent or -1 on error.
123 : */
124 :
125 : int teredo_sendv (int fd, const struct iovec *iov, size_t count,
126 : uint32_t dest_ip, uint16_t dest_port)
127 0 : {
128 : struct sockaddr_in addr =
129 : {
130 : .sin_family = AF_INET,
131 : #ifdef HAVE_SA_LEN
132 : .sin_len = sizeof (struct sockaddr_in),
133 : #endif
134 : .sin_port = dest_port,
135 : .sin_addr.s_addr = dest_ip
136 0 : };
137 :
138 : struct msghdr msg =
139 : {
140 : .msg_name = &addr,
141 : .msg_namelen = sizeof (addr),
142 : .msg_iov = (struct iovec *)iov,
143 : .msg_iovlen = count
144 0 : };
145 :
146 0 : for (int tries = 0; tries < 10; tries++)
147 : {
148 0 : int res = sendmsg (fd, &msg, 0);
149 0 : if (res != -1)
150 0 : return res;
151 : /*
152 : * NOTE:
153 : * We must ignore ICMP errors returned by sendto() because they are
154 : * asynchronous, so that in most case they refer to a packet which was
155 : * sent earlier already, most likely to another destination.
156 : * That means we also ignore EHOSTUNREACH when it is generated by the
157 : * kernel routing table (meaning we are not attached to the network);
158 : * while it would have been a good idea to handle that case properly.
159 : * There does not seem to be any sane solution to this issue.
160 : *
161 : * NOTE 2:
162 : * To prevent an infinite loop in case of a really unreachable
163 : * destination, we must have a limit on the number of sendto()
164 : * attempts.
165 : */
166 0 : switch (errno)
167 : {
168 : /*case EMSGSIZE:*/ /* ICMP fragmentation needed *
169 : * given we don't ensure that the length is below 65507, we
170 : * must not ignore that error */
171 : case ENETUNREACH: /* ICMP address unreachable */
172 : case EHOSTUNREACH: /* ICMP destination unreachable */
173 : case ENOPROTOOPT: /* ICMP protocol unreachable */
174 : case ECONNREFUSED: /* ICMP port unreachable */
175 : case EOPNOTSUPP: /* ICMP source route failed
176 : - should not happen */
177 : case EHOSTDOWN: /* ICMP host unknown */
178 : #ifdef ENONET
179 : case ENONET: /* ICMP host isolated */
180 : #endif
181 : continue;
182 :
183 : default:
184 0 : return -1; /* hard error */
185 : }
186 : }
187 :
188 0 : return -1;
189 : }
190 :
191 :
192 : /**
193 : * Sends an UDP/IPv4 datagram.
194 : * Thread-safe, cancellation safe, cancellation point.
195 : *
196 : * @return number of bytes sent, or -1 on error.
197 : */
198 : int teredo_send (int fd, const void *packet, size_t plen,
199 : uint32_t dest_ip, uint16_t dest_port)
200 0 : {
201 0 : struct iovec iov = { (void *)packet, plen };
202 0 : return teredo_sendv (fd, &iov, 1, dest_ip, dest_port);
203 : }
204 :
205 :
206 : static int teredo_recv_inner (int fd, struct teredo_packet *p, int flags)
207 0 : {
208 : // Receive a UDP packet
209 : struct sockaddr_in ad;
210 : int length = recvfrom (fd, p->buf, sizeof (p->buf), flags,
211 : (struct sockaddr *)&ad,
212 0 : &(socklen_t){ sizeof (ad) });
213 :
214 0 : if (length < 2) // too small or error
215 0 : return -1;
216 :
217 0 : p->source_ipv4 = ad.sin_addr.s_addr;
218 0 : p->source_port = ad.sin_port;
219 :
220 0 : uint8_t *ptr = p->buf;
221 :
222 0 : p->auth_nonce = NULL;
223 0 : p->auth_conf_byte = 0;
224 0 : p->orig_ipv4 = 0;
225 0 : p->orig_port = 0;
226 :
227 : // Teredo Authentication header
228 0 : if ((ptr[0] == 0) && (ptr[1] == teredo_auth_hdr))
229 : {
230 : uint8_t id_len, au_len;
231 :
232 0 : length -= 13;
233 0 : if (length < 0)
234 0 : return -1; // too small
235 0 : ptr += 2;
236 :
237 : /* ID and Auth */
238 0 : id_len = *ptr++;
239 0 : au_len = *ptr++;
240 :
241 : /* TODO: secure qualification */
242 0 : length -= id_len + au_len;
243 0 : if (length < 0)
244 0 : return -1;
245 0 : ptr += id_len + au_len;
246 :
247 :
248 : /* Nonce + confirmation byte */
249 0 : p->auth_nonce = ptr;
250 0 : ptr += 8;
251 0 : p->auth_conf_byte = *ptr++;
252 : }
253 :
254 : // Teredo Origin Indication
255 0 : if ((ptr[0] == 0) && (ptr[1] == teredo_orig_ind))
256 : {
257 : uint32_t addr;
258 : uint16_t port;
259 :
260 0 : length -= 8;
261 0 : if (length < 0)
262 0 : return -1; /* too small */
263 0 : ptr += 2;
264 :
265 : /* Obfuscated port */
266 0 : memcpy (&port, ptr, 2);
267 0 : ptr += 2;
268 0 : p->orig_port = ~port;
269 :
270 : /* Obfuscated IPv4 */
271 0 : memcpy (&addr, ptr, 4);
272 0 : ptr += 4;
273 0 : p->orig_ipv4 = ~addr;
274 : }
275 :
276 : /* length <= 65507 = sizeof(buf) */
277 0 : p->ip6_len = length;
278 0 : p->ip6 = ptr;
279 :
280 0 : return 0;
281 : }
282 :
283 :
284 : /**
285 : * Receives and parses a Teredo packet from a socket. Never blocks.
286 : * Thread-safe, cancellation-safe, cancellation point.
287 : *
288 : * @param fd socket file descriptor
289 : * @param p teredo_packet receive buffer
290 : *
291 : * @return 0 on success, -1 in error.
292 : * Errors might be caused by :
293 : * - lower level network I/O,
294 : * - malformatted packets,
295 : * - no data pending.
296 : */
297 : int teredo_recv (int fd, struct teredo_packet *p)
298 0 : {
299 0 : return teredo_recv_inner (fd, p, MSG_DONTWAIT);
300 : }
301 :
302 :
303 : #if defined (__FreeBSD__) || defined (__APPLE__)
304 : # define HAVE_BROKEN_RECVFROM 1
305 : # include <sys/poll.h>
306 : #endif
307 :
308 : /**
309 : * Waits for, receives and parses a Teredo packet from a socket.
310 : * Thread-safe, cancellation-safe, cancellation point.
311 : *
312 : * @param fd socket file descriptor
313 : * @param p teredo_packet receive buffer
314 : *
315 : * @return 0 on success, -1 in error.
316 : * Errors might be caused by :
317 : * - lower level network I/O,
318 : * - malformatted packets,
319 : * - a race condition if two thread are waiting on the same
320 : * non-blocking socket for receiving.
321 : */
322 : int teredo_wait_recv (int fd, struct teredo_packet *p)
323 0 : {
324 : #ifdef HAVE_BROKEN_RECVFROM
325 : // recvfrom() is not a cancellation point on FreeBSD 6.1...
326 : struct pollfd ufd = { .fd = fd, .events = POLLIN };
327 : if (poll (&ufd, 1, -1) == -1)
328 : return -1;
329 : #endif
330 :
331 0 : return teredo_recv_inner (fd, p, 0);
332 : }
333 :
334 :
335 : /* This does not fit anywhere and is needed by both relay and server */
336 : #include <stdbool.h>
337 :
338 : /**
339 : * Computes an Internet checksum over a scatter-gather array.
340 : * Buffers need not be aligned neither of even length.
341 : * Jumbograms are supported (though you probably don't care).
342 : */
343 : static uint16_t in_cksum (const struct iovec *iov, size_t n)
344 0 : {
345 0 : uint32_t sum = 0;
346 : union
347 : {
348 : uint16_t word;
349 : uint8_t bytes[2];
350 : } w;
351 0 : bool odd = false;
352 :
353 0 : while (n > 0)
354 : {
355 0 : const uint8_t *ptr = iov->iov_base;
356 :
357 0 : for (size_t len = iov->iov_len; len > 0; len--)
358 : {
359 0 : if (odd)
360 : {
361 0 : w.bytes[1] = *ptr++;
362 0 : sum += w.word;
363 0 : if (sum > 0xffff)
364 0 : sum -= 0xffff;
365 : }
366 : else
367 0 : w.bytes[0] = *ptr++;
368 0 : odd = !odd;
369 : }
370 :
371 0 : iov++;
372 0 : n--;
373 : }
374 :
375 0 : if (odd)
376 : {
377 0 : w.bytes[1] = 0;
378 0 : sum += w.word;
379 0 : if (sum > 0xffff)
380 0 : sum -= 0xffff;
381 : }
382 :
383 0 : return sum ^ 0xffff;
384 : }
385 :
386 :
387 : /**
388 : * Computes an IPv6 layer-3 checksum.
389 : * The input buffers do not need to be aligned neither of even length.
390 : * Jumbo datagrams are supported.
391 : */
392 : uint16_t
393 : teredo_cksum (const void *src, const void *dst, uint8_t protocol,
394 : const struct iovec *data, size_t n)
395 0 : {
396 0 : struct iovec iov[3 + n];
397 0 : size_t plen = 0;
398 0 : for (size_t i = 0; i < n; i++)
399 : {
400 0 : iov[3 + i].iov_base = data[i].iov_base;
401 0 : plen += (iov[3 + i].iov_len = data[i].iov_len);
402 : }
403 :
404 0 : uint32_t pseudo[4] = { htonl (plen), htonl (protocol) };
405 0 : iov[0].iov_base = (void *)src;
406 0 : iov[0].iov_len = 16;
407 0 : iov[1].iov_base = (void *)dst;
408 0 : iov[1].iov_len = 16;
409 0 : iov[2].iov_base = pseudo;
410 0 : iov[2].iov_len = 8;
411 :
412 0 : return in_cksum (iov, 3 + n);
413 : }
414 :
|