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