Contiki-NG
ip64.c
1/*
2 * Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29 * OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 */
32
33/* The ip64 module is a translator between IPv6 and IPv4 packets. The
34 IPv6 packets come from an IPv6 network and are translated into a
35 single IPv4 host, as shown in the ASCII graphics below. The IPv6
36 network typically is a low-power RF network and the IPv4 network
37 typically is an Ethernet.
38
39 +----------------+
40 | |
41 | | +------+
42 | IPv6 network |---| ip64 |-- IPv4 network
43 | | +------+
44 | |
45 +----------------+
46
47 ip64 maps all IPv6 addresses from inside the IPv6 network to its
48 own IPv4 address. This IPv4 address would typically have been
49 obtained with DHCP from the IPv4 network, but the exact way this
50 has been obtained is outside the scope of the ip64 module. The IPv4
51 address is given to the ip64 module through the
52 ip64_set_ipv4_address() function.
53*/
54
55#include "ip64/ip64.h"
56#include "ipv6/ip64-addr.h"
57#include "ip64/ip64-addrmap.h"
58#include "ip64-conf.h"
59#include "ip64/ip64-special-ports.h"
60#include "ip64/ip64-eth-interface.h"
61#include "ip64/ip64-slip-interface.h"
62#include "ip64/ip64-dns64.h"
63#include "net/ipv6/uip-ds6.h"
64#include "ip64/ip64-ipv4-dhcp.h"
65#include "contiki-net.h"
66
67#include "net/ipv6/uip-debug.h"
68
69#include <string.h> /* for memcpy() */
70#include <stdio.h> /* for printf() */
71
72#define DEBUG 0
73
74#if DEBUG
75#undef PRINTF
76#define PRINTF(...) printf(__VA_ARGS__)
77#else /* DEBUG */
78#define PRINTF(...)
79#endif /* DEBUG */
80
81struct ipv6_hdr {
82 uint8_t vtc;
83 uint8_t tcflow;
84 uint16_t flow;
85 uint8_t len[2];
86 uint8_t nxthdr, hoplim;
87 uip_ip6addr_t srcipaddr, destipaddr;
88};
89
90struct ipv4_hdr {
91 uint8_t vhl,
92 tos,
93 len[2],
94 ipid[2],
95 ipoffset[2],
96 ttl,
97 proto;
98 uint16_t ipchksum;
99 uip_ip4addr_t srcipaddr, destipaddr;
100};
101
102#define EPHEMERAL_PORTRANGE 1024
103
104#define IPV6_HDRLEN 40
105#define IPV4_HDRLEN 20
106
107#define IP_PROTO_ICMPV4 1
108#define IP_PROTO_TCP 6
109#define IP_PROTO_UDP 17
110#define IP_PROTO_ICMPV6 58
111
112#define ICMP_ECHO_REPLY 0
113#define ICMP_ECHO 8
114#define ICMP6_ECHO_REPLY 129
115#define ICMP6_ECHO 128
116
117struct tcp_hdr {
118 uint16_t srcport;
119 uint16_t destport;
120 uint8_t seqno[4];
121 uint8_t ackno[4];
122 uint8_t tcpoffset;
123 uint8_t flags;
124 uint8_t wnd[2];
125 uint16_t tcpchksum;
126 uint8_t urgp[2];
127 uint8_t optdata[4];
128};
129
130struct udp_hdr {
131 uint16_t srcport;
132 uint16_t destport;
133 uint16_t udplen;
134 uint16_t udpchksum;
135};
136
137struct icmpv4_hdr {
138 uint8_t type, icode;
139 uint16_t icmpchksum;
140};
141
142struct icmpv6_hdr {
143 uint8_t type, icode;
144 uint16_t icmpchksum;
145 uint16_t id, seqno;
146};
147
148#define BUFSIZE UIP_BUFSIZE
149
150uip_buf_t ip64_packet_buffer_aligned;
151uint8_t *ip64_packet_buffer = ip64_packet_buffer_aligned.u8;
152
153uint16_t ip64_packet_buffer_maxlen = BUFSIZE;
154
155static uip_ip4addr_t ip64_hostaddr;
156static uip_ip4addr_t ip64_netmask;
157static uip_ip4addr_t ip64_draddr;
158
159static uint16_t ipid;
160static uint8_t ip64_hostaddr_configured = 0;
161
162static uip_ip6addr_t ipv6_local_address;
163static uint8_t ipv6_local_address_configured = 0;
164
165static uip_ip4addr_t ipv4_broadcast_addr;
166
167/* Lifetimes for address mappings. */
168#define SYN_LIFETIME (CLOCK_SECOND * 20)
169#define RST_LIFETIME (CLOCK_SECOND * 30)
170#define DEFAULT_LIFETIME (CLOCK_SECOND * 60 * 5)
171
172/* TCP flag defines */
173#define TCP_FIN 0x01
174#define TCP_SYN 0x02
175#define TCP_RST 0x04
176
177#define DNS_PORT 53
178
179/*---------------------------------------------------------------------------*/
180void
181ip64_init(void)
182{
183 int i;
184 uint8_t state;
185
186 uip_ipaddr(&ipv4_broadcast_addr, 255,255,255,255);
187 ip64_hostaddr_configured = 0;
188
189 PRINTF("ip64_init\n");
190 IP64_ETH_DRIVER.init();
191#if IP64_DHCP
192 ip64_ipv4_dhcp_init();
193#endif /* IP64_CONF_DHCP */
194
195 /* Specify an IPv6 address for local communication to the
196 host. We'll just pick the first one we find in our list. */
197 for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
198 state = uip_ds6_if.addr_list[i].state;
199 PRINTF("i %d used %d\n", i, uip_ds6_if.addr_list[i].isused);
200 if(uip_ds6_if.addr_list[i].isused &&
201 (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) {
202 ip64_set_ipv6_address(&uip_ds6_if.addr_list[i].ipaddr);
203 break;
204 }
205 }
206
207}
208/*---------------------------------------------------------------------------*/
209void
210ip64_set_hostaddr(const uip_ip4addr_t *hostaddr)
211{
212 ip64_hostaddr_configured = 1;
213 ip64_addr_copy4(&ip64_hostaddr, hostaddr);
214}
215/*---------------------------------------------------------------------------*/
216void
217ip64_set_netmask(const uip_ip4addr_t *netmask)
218{
219 ip64_addr_copy4(&ip64_netmask, netmask);
220}
221/*---------------------------------------------------------------------------*/
222void
223ip64_set_draddr(const uip_ip4addr_t *draddr)
224{
225 ip64_addr_copy4(&ip64_draddr, draddr);
226}
227/*---------------------------------------------------------------------------*/
228const uip_ip4addr_t *
229ip64_get_hostaddr(void)
230{
231 return &ip64_hostaddr;
232}
233/*---------------------------------------------------------------------------*/
234const uip_ip4addr_t *
235ip64_get_netmask(void)
236{
237 return &ip64_netmask;
238}
239/*---------------------------------------------------------------------------*/
240const uip_ip4addr_t *
241ip64_get_draddr(void)
242{
243 return &ip64_draddr;
244}
245/*---------------------------------------------------------------------------*/
246void
247ip64_set_ipv4_address(const uip_ip4addr_t *addr, const uip_ip4addr_t *netmask)
248{
249 ip64_set_hostaddr(addr);
250 ip64_set_netmask(netmask);
251
252 PRINTF("ip64_set_ipv4_address: configuring address %d.%d.%d.%d/%d.%d.%d.%d\n",
253 ip64_hostaddr.u8[0], ip64_hostaddr.u8[1],
254 ip64_hostaddr.u8[2], ip64_hostaddr.u8[3],
255 ip64_netmask.u8[0], ip64_netmask.u8[1],
256 ip64_netmask.u8[2], ip64_netmask.u8[3]);
257}
258/*---------------------------------------------------------------------------*/
259void
260ip64_set_ipv6_address(const uip_ip6addr_t *addr)
261{
262 ip64_addr_copy6(&ipv6_local_address, (const uip_ip6addr_t *)addr);
263 ipv6_local_address_configured = 1;
264#if DEBUG
265 PRINTF("ip64_set_ipv6_address: configuring address ");
266 uip_debug_ipaddr_print(addr);
267 PRINTF("\n");
268#endif /* DEBUG */
269}
270/*---------------------------------------------------------------------------*/
271static uint16_t
272chksum(uint16_t sum, const uint8_t *data, uint16_t len)
273{
274 uint16_t t;
275 const uint8_t *dataptr;
276 const uint8_t *last_byte;
277
278 dataptr = data;
279 last_byte = data + len - 1;
280
281 while(dataptr < last_byte) { /* At least two more bytes */
282 t = (dataptr[0] << 8) + dataptr[1];
283 sum += t;
284 if(sum < t) {
285 sum++; /* carry */
286 }
287 dataptr += 2;
288 }
289
290 if(dataptr == last_byte) {
291 t = (dataptr[0] << 8) + 0;
292 sum += t;
293 if(sum < t) {
294 sum++; /* carry */
295 }
296 }
297
298 /* Return sum in host byte order. */
299 return sum;
300}
301/*---------------------------------------------------------------------------*/
302static uint16_t
303ipv4_checksum(struct ipv4_hdr *hdr)
304{
305 uint16_t sum;
306
307 sum = chksum(0, (uint8_t *)hdr, IPV4_HDRLEN);
308 return (sum == 0) ? 0xffff : uip_htons(sum);
309}
310/*---------------------------------------------------------------------------*/
311static uint16_t
312ipv4_transport_checksum(const uint8_t *packet, uint16_t len, uint8_t proto)
313{
314 uint16_t transport_layer_len;
315 uint16_t sum;
316 struct ipv4_hdr *v4hdr = (struct ipv4_hdr *)packet;
317
318 transport_layer_len = len - IPV4_HDRLEN;
319
320 /* First sum pseudoheader. */
321
322 if(proto != IP_PROTO_ICMPV4) {
323 /* IP protocol and length fields. This addition cannot carry. */
324 sum = transport_layer_len + proto;
325 /* Sum IP source and destination addresses. */
326 sum = chksum(sum, (uint8_t *)&v4hdr->srcipaddr, 2 * sizeof(uip_ip4addr_t));
327 } else {
328 /* ping replies' checksums are calculated over the icmp-part only */
329 sum = 0;
330 }
331
332 /* Sum transport layer header and data. */
333 sum = chksum(sum, &packet[IPV4_HDRLEN], transport_layer_len);
334
335 return (sum == 0) ? 0xffff : uip_htons(sum);
336}
337/*---------------------------------------------------------------------------*/
338static uint16_t
339ipv6_transport_checksum(const uint8_t *packet, uint16_t len, uint8_t proto)
340{
341 uint16_t transport_layer_len;
342 uint16_t sum;
343 struct ipv6_hdr *v6hdr = (struct ipv6_hdr *)packet;
344
345 transport_layer_len = len - IPV6_HDRLEN;
346
347 /* First sum pseudoheader. */
348
349 /* IP protocol and length fields. This addition cannot carry. */
350 sum = transport_layer_len + proto;
351 /* Sum IP source and destination addresses. */
352 sum = chksum(sum, (uint8_t *)&v6hdr->srcipaddr, sizeof(uip_ip6addr_t));
353 sum = chksum(sum, (uint8_t *)&v6hdr->destipaddr, sizeof(uip_ip6addr_t));
354
355 /* Sum transport layer header and data. */
356 sum = chksum(sum, &packet[IPV6_HDRLEN], transport_layer_len);
357
358 return (sum == 0) ? 0xffff : uip_htons(sum);
359}
360/*---------------------------------------------------------------------------*/
361int
362ip64_6to4(const uint8_t *ipv6packet, const uint16_t ipv6packet_len,
363 uint8_t *resultpacket)
364{
365 struct ipv4_hdr *v4hdr;
366 struct ipv6_hdr *v6hdr;
367 struct udp_hdr *udphdr;
368 struct tcp_hdr *tcphdr;
369 struct icmpv4_hdr *icmpv4hdr;
370 struct icmpv6_hdr *icmpv6hdr;
371 uint16_t ipv6len, ipv4len;
372 struct ip64_addrmap_entry *m;
373
374 v6hdr = (struct ipv6_hdr *)ipv6packet;
375 v4hdr = (struct ipv4_hdr *)resultpacket;
376
377 if((v6hdr->len[0] << 8) + v6hdr->len[1] <= ipv6packet_len) {
378 ipv6len = (v6hdr->len[0] << 8) + v6hdr->len[1] + IPV6_HDRLEN;
379 } else {
380 PRINTF("ip64_6to4: packet smaller than reported in IPv6 header, dropping\n");
381 return 0;
382 }
383
384 /* We copy the data from the IPv6 packet into the IPv4 packet. We do
385 not modify the data in any way. */
386 memcpy(&resultpacket[IPV4_HDRLEN],
387 &ipv6packet[IPV6_HDRLEN],
388 ipv6len - IPV6_HDRLEN);
389
390 udphdr = (struct udp_hdr *)&resultpacket[IPV4_HDRLEN];
391 tcphdr = (struct tcp_hdr *)&resultpacket[IPV4_HDRLEN];
392 icmpv4hdr = (struct icmpv4_hdr *)&resultpacket[IPV4_HDRLEN];
393 icmpv6hdr = (struct icmpv6_hdr *)&ipv6packet[IPV6_HDRLEN];
394
395 /* Translate the IPv6 header into an IPv4 header. */
396
397 /* First the basics: the IPv4 version, header length, type of
398 service, and offset fields. Those are the same for all IPv4
399 packets we send, regardless of the values found in the IPv6
400 packet. */
401 v4hdr->vhl = 0x45;
402 v4hdr->tos = 0;
403 v4hdr->ipoffset[0] = v4hdr->ipoffset[1] = 0;
404
405 /* We assume that the IPv6 packet has a fixed size header with no
406 extension headers, and compute the length of the IPv4 packet and
407 place the resulting value in the IPv4 packet header. */
408 ipv4len = ipv6len - IPV6_HDRLEN + IPV4_HDRLEN;
409 v4hdr->len[0] = ipv4len >> 8;
410 v4hdr->len[1] = ipv4len & 0xff;
411
412 /* For simplicity, we set a unique IP id for each outgoing IPv4
413 packet. */
414 ipid++;
415 v4hdr->ipid[0] = ipid >> 8;
416 v4hdr->ipid[1] = ipid & 0xff;
417
418 /* Set the IPv4 protocol. We only support TCP, UDP, and ICMP at this
419 point. While the IPv4 header protocol numbers are the same as the
420 IPv6 next header numbers, the ICMPv4 and ICMPv6 numbers are
421 different so we cannot simply copy the contents of the IPv6 next
422 header field. */
423 switch(v6hdr->nxthdr) {
424 case IP_PROTO_TCP:
425 PRINTF("ip64_6to4: TCP header\n");
426 v4hdr->proto = IP_PROTO_TCP;
427
428 /* Compute and check the TCP checksum - since we're going to
429 recompute it ourselves, we must ensure that it was correct in
430 the first place. */
431 if(ipv6_transport_checksum(ipv6packet, ipv6len,
432 IP_PROTO_TCP) != 0xffff) {
433 PRINTF("Bad TCP checksum, dropping packet\n");
434 }
435
436 break;
437
438 case IP_PROTO_UDP:
439 PRINTF("ip64_6to4: UDP header\n");
440 v4hdr->proto = IP_PROTO_UDP;
441
442 /* Check if this is a DNS request. If so, we should rewrite it
443 with the DNS64 module. */
444 if(udphdr->destport == UIP_HTONS(DNS_PORT)) {
445 ip64_dns64_6to4((uint8_t *)v6hdr + IPV6_HDRLEN + sizeof(struct udp_hdr),
446 ipv6len - IPV6_HDRLEN - sizeof(struct udp_hdr),
447 (uint8_t *)udphdr + sizeof(struct udp_hdr),
448 BUFSIZE - IPV4_HDRLEN - sizeof(struct udp_hdr));
449 }
450 /* Compute and check the UDP checksum - since we're going to
451 recompute it ourselves, we must ensure that it was correct in
452 the first place. */
453 if(ipv6_transport_checksum(ipv6packet, ipv6len,
454 IP_PROTO_UDP) != 0xffff) {
455 PRINTF("Bad UDP checksum, dropping packet\n");
456 }
457 break;
458
459 case IP_PROTO_ICMPV6:
460 PRINTF("ip64_6to4: ICMPv6 header\n");
461 v4hdr->proto = IP_PROTO_ICMPV4;
462 /* Translate only ECHO_REPLY messages. */
463 if(icmpv6hdr->type == ICMP6_ECHO_REPLY) {
464 icmpv4hdr->type = ICMP_ECHO_REPLY;
465 } else {
466 PRINTF("ip64_6to4: ICMPv6 mapping for type %d not implemented.\n",
467 icmpv6hdr->type);
468 return 0;
469 }
470 break;
471
472 default:
473 /* We did not recognize the next header, and we do not attempt to
474 translate something we do not understand, so we return 0 to
475 indicate that no successful translation could be made. */
476 PRINTF("ip64_6to4: Could not convert IPv6 next hop %d to an IPv4 protocol number.\n",
477 v6hdr->nxthdr);
478 return 0;
479 }
480
481 /* We set the IPv4 ttl value to the hoplim number from the IPv6
482 header. This means that information about the IPv6 topology is
483 transported into to the IPv4 network. */
484 v4hdr->ttl = v6hdr->hoplim;
485
486 /* We next convert the destination address. We make this conversion
487 with the ip64_addr_6to4() function. If the conversion
488 fails, ip64_addr_6to4() returns 0. If so, we also return 0 to
489 indicate failure. */
490 if(ip64_addr_6to4(&v6hdr->destipaddr,
491 &v4hdr->destipaddr) == 0) {
492#if DEBUG
493 PRINTF("ip64_6to4: Could not convert IPv6 destination address.\n");
494 uip_debug_ipaddr_print(&v6hdr->destipaddr);
495 PRINTF("\n");
496#endif /* DEBUG */
497 return 0;
498 }
499
500 /* We set the source address in the IPv4 packet to be the IPv4
501 address that we have been configured with through the
502 ip64_set_ipv4_address() function. Only let broadcasts through. */
503 if(!ip64_hostaddr_configured &&
504 !uip_ip4addr_cmp(&v4hdr->destipaddr, &ipv4_broadcast_addr)) {
505 PRINTF("ip64_6to4: no IPv4 address configured.\n");
506 return 0;
507 }
508 ip64_addr_copy4(&v4hdr->srcipaddr, &ip64_hostaddr);
509
510
511 /* Next we update the transport layer header. This must be updated
512 in two ways: the source port number is changed and the transport
513 layer checksum must be recomputed. The reason why we change the
514 source port number is so that we can remember what IPv6 address
515 this packet came from, in case the packet will result in a reply
516 from the host on the IPv4 network. If a reply would be sent, it
517 would be sent to the port number that we chose, and we will be
518 able to map this back to the IPv6 address of the original sender
519 of the packet.
520 */
521
522 /* We check to see if we already have an existing IP address mapping
523 for this connection. If not, we create a new one. */
524 if((v4hdr->proto == IP_PROTO_UDP || v4hdr->proto == IP_PROTO_TCP)) {
525
526 if(ip64_special_ports_outgoing_is_special(uip_ntohs(udphdr->srcport))) {
527 uint16_t newport;
528 if(ip64_special_ports_translate_outgoing(uip_ntohs(udphdr->srcport),
529 &v6hdr->srcipaddr,
530 &newport)) {
531 udphdr->srcport = uip_htons(newport);
532 }
533 } else if(uip_ntohs(udphdr->srcport) >= EPHEMERAL_PORTRANGE) {
534 m = ip64_addrmap_lookup(&v6hdr->srcipaddr,
535 uip_ntohs(udphdr->srcport),
536 &v4hdr->destipaddr,
537 uip_ntohs(udphdr->destport),
538 v4hdr->proto);
539 if(m == NULL) {
540 PRINTF("Lookup failed\n");
541 m = ip64_addrmap_create(&v6hdr->srcipaddr,
542 uip_ntohs(udphdr->srcport),
543 &v4hdr->destipaddr,
544 uip_ntohs(udphdr->destport),
545 v4hdr->proto);
546 if(m == NULL) {
547 PRINTF("Could not create new map\n");
548 return 0;
549 } else {
550 PRINTF("Could create new local port %d\n", m->mapped_port);
551 }
552 } else {
553 PRINTF("Lookup: found local port %d (%d)\n", m->mapped_port,
554 uip_htons(m->mapped_port));
555 }
556
557 /* Update the lifetime of the address mapping. We need to be
558 frugal with address mapping table entries, so we assign
559 different lifetimes depending on the type of packet we see.
560
561 For TCP connections, we don't want to have a lot of failed
562 connection attmpts lingering around, so we assign mappings
563 with TCP SYN segments a short lifetime. If we see a RST
564 segment, this indicates that the connection might be dead,
565 and we'll assign a shorter lifetime.
566
567 For UDP packets and for non-SYN/non-RST segments, we assign
568 the default lifetime. */
569 if(v4hdr->proto == IP_PROTO_TCP) {
570 if((tcphdr->flags & TCP_SYN)) {
571 ip64_addrmap_set_lifetime(m, SYN_LIFETIME);
572 } else if((tcphdr->flags & TCP_RST)) {
573 ip64_addrmap_set_lifetime(m, RST_LIFETIME);
574 } else {
575 ip64_addrmap_set_lifetime(m, DEFAULT_LIFETIME);
576 }
577
578 /* Also check if we see a FIN segment. If so, we'll mark the
579 address mapping as being candidate for recycling. Same for
580 RST segments. */
581 if((tcphdr->flags & TCP_FIN) ||
582 (tcphdr->flags & TCP_RST)) {
583 ip64_addrmap_set_recycleble(m);
584 }
585 } else {
586 ip64_addrmap_set_lifetime(m, DEFAULT_LIFETIME);
587
588 /* Treat UDP packets from the IPv6 network to a multicast
589 address on the IPv4 network differently: since there is
590 no way for packets from the IPv4 network to go back to
591 the IPv6 network on these mappings, we'll mark them as
592 recyclable. */
593 if(v4hdr->destipaddr.u8[0] == 224) {
594 ip64_addrmap_set_recycleble(m);
595 }
596
597 /* Treat DNS requests differently: since the are one-shot, we
598 mark them as recyclable. */
599 if(udphdr->destport == UIP_HTONS(DNS_PORT)) {
600 ip64_addrmap_set_recycleble(m);
601 }
602 }
603
604 /* Set the source port of the packet to be the mapped port
605 number. */
606 udphdr->srcport = uip_htons(m->mapped_port);
607 }
608 }
609
610 /* The IPv4 header is now complete, so we can compute the IPv4
611 header checksum. */
612 v4hdr->ipchksum = 0;
613 v4hdr->ipchksum = ~(ipv4_checksum(v4hdr));
614
615
616
617 /* The checksum is in different places in the different protocol
618 headers, so we need to be sure that we update the correct
619 field. */
620 switch(v4hdr->proto) {
621 case IP_PROTO_TCP:
622 tcphdr->tcpchksum = 0;
623 tcphdr->tcpchksum = ~(ipv4_transport_checksum(resultpacket, ipv4len,
624 IP_PROTO_TCP));
625 break;
626 case IP_PROTO_UDP:
627 udphdr->udpchksum = 0;
628 udphdr->udpchksum = ~(ipv4_transport_checksum(resultpacket, ipv4len,
629 IP_PROTO_UDP));
630 if(udphdr->udpchksum == 0) {
631 udphdr->udpchksum = 0xffff;
632 }
633 break;
634 case IP_PROTO_ICMPV4:
635 icmpv4hdr->icmpchksum = 0;
636 icmpv4hdr->icmpchksum = ~(ipv4_transport_checksum(resultpacket, ipv4len,
637 IP_PROTO_ICMPV4));
638 break;
639
640 default:
641 PRINTF("ip64_6to4: transport protocol %d not implemented\n", v4hdr->proto);
642 return 0;
643 }
644
645 /* Finally, we return the length of the resulting IPv4 packet. */
646 PRINTF("ip64_6to4: ipv4len %d\n", ipv4len);
647 return ipv4len;
648}
649/*---------------------------------------------------------------------------*/
650int
651ip64_4to6(const uint8_t *ipv4packet, const uint16_t ipv4packet_len,
652 uint8_t *resultpacket)
653{
654 struct ipv4_hdr *v4hdr;
655 struct ipv6_hdr *v6hdr;
656 struct udp_hdr *udphdr;
657 struct tcp_hdr *tcphdr;
658 struct icmpv4_hdr *icmpv4hdr;
659 struct icmpv6_hdr *icmpv6hdr;
660 uint16_t ipv4len, ipv6len, ipv6_packet_len;
661 struct ip64_addrmap_entry *m;
662
663 v6hdr = (struct ipv6_hdr *)resultpacket;
664 v4hdr = (struct ipv4_hdr *)ipv4packet;
665
666 if((v4hdr->len[0] << 8) + v4hdr->len[1] <= ipv4packet_len) {
667 ipv4len = (v4hdr->len[0] << 8) + v4hdr->len[1];
668 } else {
669 PRINTF("ip64_4to6: packet smaller than reported in IPv4 header, dropping\n");
670 return 0;
671 }
672
673 if(ipv4len <= IPV4_HDRLEN) {
674 return 0;
675 }
676
677 /* Make sure that the resulting packet fits in the ip64 packet
678 buffer. If not, we drop it. */
679 if(ipv4len - IPV4_HDRLEN + IPV6_HDRLEN > BUFSIZE) {
680 PRINTF("ip64_4to6: packet too big to fit in buffer, dropping\n");
681 return 0;
682 }
683 /* We copy the data from the IPv4 packet into the IPv6 packet. */
684 memcpy(&resultpacket[IPV6_HDRLEN],
685 &ipv4packet[IPV4_HDRLEN],
686 ipv4len - IPV4_HDRLEN);
687
688 udphdr = (struct udp_hdr *)&resultpacket[IPV6_HDRLEN];
689 tcphdr = (struct tcp_hdr *)&resultpacket[IPV6_HDRLEN];
690 icmpv4hdr = (struct icmpv4_hdr *)&ipv4packet[IPV4_HDRLEN];
691 icmpv6hdr = (struct icmpv6_hdr *)&resultpacket[IPV6_HDRLEN];
692
693 ipv6len = ipv4len - IPV4_HDRLEN + IPV6_HDRLEN;
694 ipv6_packet_len = ipv6len - IPV6_HDRLEN;
695
696 /* Translate the IPv4 header into an IPv6 header. */
697
698 /* We first fill in the simple fields: IP header version, traffic
699 class and flow label, and length fields. */
700 v6hdr->vtc = 0x60;
701 v6hdr->tcflow = 0;
702 v6hdr->flow = 0;
703 v6hdr->len[0] = ipv6_packet_len >> 8;
704 v6hdr->len[1] = ipv6_packet_len & 0xff;
705
706 /* We use the IPv4 TTL field as the IPv6 hop limit field. */
707 v6hdr->hoplim = v4hdr->ttl;
708
709
710 /* We now translate the IPv4 source and destination addresses to
711 IPv6 source and destination addresses. We translate the IPv4
712 source address into an IPv6-encoded IPv4 address. The IPv4
713 destination address will be the address with which we have
714 previously been configured, through the ip64_set_ipv4_address()
715 function. We use the mapping table to look up the new IPv6
716 destination address. As we assume that the IPv4 packet is a
717 response to a previously sent IPv6 packet, we should have a
718 mapping between the (protocol, destport, srcport, srcaddress)
719 tuple. If not, we'll return 0 to indicate that we failed to
720 translate the packet. */
721 if(ip64_addr_4to6(&v4hdr->srcipaddr, &v6hdr->srcipaddr) == 0) {
722 PRINTF("ip64_packet_4to6: failed to convert source IP address\n");
723 return 0;
724 }
725
726 /* For the next header field, we simply use the IPv4 protocol
727 field. We only support UDP and TCP packets. */
728 switch(v4hdr->proto) {
729 case IP_PROTO_UDP:
730 v6hdr->nxthdr = IP_PROTO_UDP;
731 /* Check if this is a DNS request. If so, we should rewrite it
732 with the DNS64 module. */
733 if(udphdr->srcport == UIP_HTONS(DNS_PORT)) {
734 int len;
735
736 len = ip64_dns64_4to6((uint8_t *)v4hdr + IPV4_HDRLEN + sizeof(struct udp_hdr),
737 ipv4len - IPV4_HDRLEN - sizeof(struct udp_hdr),
738 (uint8_t *)v6hdr + IPV6_HDRLEN + sizeof(struct udp_hdr),
739 ipv6_packet_len - sizeof(struct udp_hdr));
740 ipv6_packet_len = len + sizeof(struct udp_hdr);
741 v6hdr->len[0] = ipv6_packet_len >> 8;
742 v6hdr->len[1] = ipv6_packet_len & 0xff;
743 ipv6len = ipv6_packet_len + IPV6_HDRLEN;
744
745 }
746 break;
747
748 case IP_PROTO_TCP:
749 v6hdr->nxthdr = IP_PROTO_TCP;
750 break;
751
752 case IP_PROTO_ICMPV4:
753 /* Allow only ICMPv4 ECHO_REQUESTS (ping packets) through to the
754 local IPv6 host. */
755 if(icmpv4hdr->type == ICMP_ECHO) {
756 PRINTF("ip64_4to6: translating ICMPv4 ECHO packet\n");
757 v6hdr->nxthdr = IP_PROTO_ICMPV6;
758 icmpv6hdr->type = ICMP6_ECHO;
759 ip64_addr_copy6(&v6hdr->destipaddr, &ipv6_local_address);
760 } else {
761 PRINTF("ip64_packet_4to6: ICMPv4 packet type %d not supported\n",
762 icmpv4hdr->type);
763 return 0;
764 }
765 break;
766
767 default:
768 /* For protocol types that we do not support, we return 0 to
769 indicate that we failed to translate the packet to an IPv6
770 packet. */
771 PRINTF("ip64_packet_4to6: protocol type %d not supported\n",
772 v4hdr->proto);
773 return 0;
774 }
775
776 /* Translate IPv4 broadcasts to IPv6 all-nodes multicasts. */
777 if(uip_ip4addr_cmp(&v4hdr->destipaddr, &ipv4_broadcast_addr) ||
778 (uip_ipaddr_maskcmp(&v4hdr->destipaddr, &ip64_hostaddr,
779 &ip64_netmask) &&
780 ((v4hdr->destipaddr.u16[0] & (~ip64_netmask.u16[0])) ==
781 (ipv4_broadcast_addr.u16[0] & (~ip64_netmask.u16[0]))) &&
782 ((v4hdr->destipaddr.u16[1] & (~ip64_netmask.u16[1])) ==
783 (ipv4_broadcast_addr.u16[1] & (~ip64_netmask.u16[1]))))) {
784 uip_create_linklocal_allnodes_mcast(&v6hdr->destipaddr);
785 } else {
786
787 if(!ip64_hostaddr_configured) {
788 PRINTF("ip64_packet_4to6: no local IPv4 address configured, dropping incoming packet.\n");
789 return 0;
790 }
791
792 if(!uip_ip4addr_cmp(&v4hdr->destipaddr, &ip64_hostaddr)) {
793 PRINTF("ip64_packet_4to6: the IPv4 destination address %d.%d.%d.%d did not match our IPv4 address %d.%d.%d.%d\n",
794 uip_ipaddr_to_quad(&v4hdr->destipaddr),
795 uip_ipaddr_to_quad(&ip64_hostaddr));
796 return 0;
797 }
798
799
800 /* Now we translate the transport layer port numbers. We assume that
801 the IPv4 packet is a response to a packet that has previously
802 been translated from IPv6 to IPv4. If this is the case, the tuple
803 (protocol, destport, srcport, srcaddress) corresponds to an address/port
804 pair in our mapping table. If we do not find a mapping, we return
805 0 to indicate that we could not translate the IPv4 packet to an
806 IPv6 packet. */
807
808 /* XXX treat a few ports differently: those ports should be let
809 through to the local host. For those ports, we set up an address
810 mapping that ensures that the local port number is retained. */
811
812 if((v4hdr->proto == IP_PROTO_TCP || v4hdr->proto == IP_PROTO_UDP)) {
813 if(uip_htons(tcphdr->destport) < EPHEMERAL_PORTRANGE) {
814 /* This packet should go to the local host. */
815 PRINTF("Port is in the non-ephemeral port range %d (%d)\n",
816 tcphdr->destport, uip_htons(tcphdr->destport));
817 ip64_addr_copy6(&v6hdr->destipaddr, &ipv6_local_address);
818 } else if(ip64_special_ports_incoming_is_special(uip_htons(tcphdr->destport))) {
819 uip_ip6addr_t newip6addr;
820 uint16_t newport;
821 PRINTF("ip64 port %d (%d) is special, treating it differently\n",
822 tcphdr->destport, uip_htons(tcphdr->destport));
823 if(ip64_special_ports_translate_incoming(uip_htons(tcphdr->destport),
824 &newip6addr, &newport)) {
825 ip64_addr_copy6(&v6hdr->destipaddr, &newip6addr);
826 tcphdr->destport = uip_htons(newport);
827 PRINTF("New port %d (%d)\n",
828 tcphdr->destport, uip_htons(tcphdr->destport));
829 } else {
830 ip64_addr_copy6(&v6hdr->destipaddr, &ipv6_local_address);
831 PRINTF("No new port\n");
832 }
833 } else {
834 /* The TCP or UDP port numbers were not non-ephemeral and not
835 special, so we map the port number according to the address
836 mapping table. */
837
838 m = ip64_addrmap_lookup_port(uip_ntohs(udphdr->destport),
839 v4hdr->proto);
840 if(m == NULL) {
841 PRINTF("Inbound lookup failed\n");
842 return 0;
843 } else {
844 PRINTF("Inbound lookup did not fail\n");
845 }
846 ip64_addr_copy6(&v6hdr->destipaddr, &m->ip6addr);
847 udphdr->destport = uip_htons(m->ip6port);
848 }
849 }
850 }
851
852 /* The checksum is in different places in the different protocol
853 headers, so we need to be sure that we update the correct
854 field. */
855 switch(v6hdr->nxthdr) {
856 case IP_PROTO_TCP:
857 tcphdr->tcpchksum = 0;
858 tcphdr->tcpchksum = ~(ipv6_transport_checksum(resultpacket,
859 ipv6len,
860 IP_PROTO_TCP));
861 break;
862 case IP_PROTO_UDP:
863 udphdr->udpchksum = 0;
864 /* As the udplen might have changed (DNS) we need to update it also */
865 udphdr->udplen = uip_htons(ipv6_packet_len);
866 udphdr->udpchksum = ~(ipv6_transport_checksum(resultpacket,
867 ipv6len,
868 IP_PROTO_UDP));
869 if(udphdr->udpchksum == 0) {
870 udphdr->udpchksum = 0xffff;
871 }
872 break;
873
874 case IP_PROTO_ICMPV6:
875 icmpv6hdr->icmpchksum = 0;
876 icmpv6hdr->icmpchksum = ~(ipv6_transport_checksum(resultpacket,
877 ipv6len,
878 IP_PROTO_ICMPV6));
879 break;
880 default:
881 PRINTF("ip64_4to6: transport protocol %d not implemented\n", v4hdr->proto);
882 return 0;
883 }
884
885 /* Finally, we return the length of the resulting IPv6 packet. */
886 PRINTF("ip64_4to6: ipv6len %d\n", ipv6len);
887 return ipv6len;
888}
889/*---------------------------------------------------------------------------*/
890int
891ip64_hostaddr_is_configured(void)
892{
893 return ip64_hostaddr_configured;
894}
895/*---------------------------------------------------------------------------*/
896static void
897interface_init(void)
898{
899 IP64_UIP_FALLBACK_INTERFACE.init();
900}
901/*---------------------------------------------------------------------------*/
902static int
903interface_output(void)
904{
905 PRINTF("ip64: interface_output len %d\n", uip_len);
906 IP64_UIP_FALLBACK_INTERFACE.output();
907
908 return 0;
909}
910/*---------------------------------------------------------------------------*/
911const struct uip_fallback_interface ip64_uip_fallback_interface = {
912 interface_init, interface_output
913};
914
#define ICMP6_ECHO_REPLY
Echo reply.
Definition: uip-icmp6.h:58
#define ADDR_TENTATIVE
Possible states for the an address (RFC 4862)
Definition: uip-ds6.h:156
uip_ds6_netif_t uip_ds6_if
The single interface.
Definition: uip-ds6.c:75
#define uip_create_linklocal_allnodes_mcast(a)
set IP address a to the link local all-nodes multicast address
Definition: uip.h:1783
#define uip_ip4addr_cmp(addr1, addr2)
Compare two IP addresses.
Definition: uip.h:998
#define uip_ipaddr_maskcmp(addr1, addr2, mask)
Compare two IP addresses with netmasks.
Definition: uip.h:1029
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
Definition: uip.h:1157
#define uip_ipaddr(addr, addr0, addr1, addr2, addr3)
Construct an IP address from four bytes.
Definition: uip.h:898
#define uip_ipaddr_to_quad(a)
Convert an IP address to four bytes separated by commas.
Definition: uip.h:870
uint16_t uip_htons(uint16_t val)
Convert a 16-bit quantity from host byte order to network byte order.
Definition: uip6.c:2347
uint16_t uip_len
The length of the packet in the uip_buf buffer.
Definition: uip6.c:159
A set of debugging macros for the IP stack.
Header file for IPv6-related data structures.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:107
The uIP packet buffer.
Definition: uip.h:457
Representation of an IP address.
Definition: uip.h:95