56#include "ipv6/ip64-addr.h"
57#include "ip64/ip64-addrmap.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"
64#include "ip64/ip64-ipv4-dhcp.h"
65#include "contiki-net.h"
72#define LOG_MODULE "IP64"
73#define LOG_LEVEL LOG_LEVEL_IP64
82 uint8_t nxthdr, hoplim;
83 uip_ip6addr_t srcipaddr, destipaddr;
98#define EPHEMERAL_PORTRANGE 1024
100#define IPV6_HDRLEN 40
101#define IPV4_HDRLEN 20
103#define IP_PROTO_ICMPV4 1
104#define IP_PROTO_TCP 6
105#define IP_PROTO_UDP 17
106#define IP_PROTO_ICMPV6 58
108#define ICMP_ECHO_REPLY 0
110#define ICMP6_ECHO_REPLY 129
111#define ICMP6_ECHO 128
144#define BUFSIZE UIP_BUFSIZE
147uint8_t *ip64_packet_buffer = ip64_packet_buffer_aligned.u8;
149uint16_t ip64_packet_buffer_maxlen = BUFSIZE;
156static uint8_t ip64_hostaddr_configured = 0;
158static uip_ip6addr_t ipv6_local_address;
159static uint8_t ipv6_local_address_configured = 0;
164#define SYN_LIFETIME (CLOCK_SECOND * 20)
165#define RST_LIFETIME (CLOCK_SECOND * 30)
166#define DEFAULT_LIFETIME (CLOCK_SECOND * 60 * 5)
182 uip_ipaddr(&ipv4_broadcast_addr, 255,255,255,255);
183 ip64_hostaddr_configured = 0;
186 IP64_ETH_DRIVER.init();
188 ip64_ipv4_dhcp_init();
193 for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
195 LOG_DBG(
"i %d used %d\n", i,
uip_ds6_if.addr_list[i].isused);
198 ip64_set_ipv6_address(&
uip_ds6_if.addr_list[i].ipaddr);
208 ip64_hostaddr_configured = 1;
209 ip64_addr_copy4(&ip64_hostaddr, hostaddr);
215 ip64_addr_copy4(&ip64_netmask, netmask);
221 ip64_addr_copy4(&ip64_draddr, draddr);
225ip64_get_hostaddr(
void)
227 return &ip64_hostaddr;
231ip64_get_netmask(
void)
233 return &ip64_netmask;
245 ip64_set_hostaddr(
addr);
246 ip64_set_netmask(netmask);
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]);
256ip64_set_ipv6_address(
const uip_ip6addr_t *
addr)
258 ip64_addr_copy6(&ipv6_local_address, (
const uip_ip6addr_t *)
addr);
259 ipv6_local_address_configured = 1;
261 LOG_INFO(
"Configuring IPv6 address ");
262 LOG_INFO_6ADDR(
addr);
268chksum(uint16_t sum,
const uint8_t *data, uint16_t len)
271 const uint8_t *dataptr;
272 const uint8_t *last_byte;
275 last_byte = data + len - 1;
277 while(dataptr < last_byte) {
278 t = (dataptr[0] << 8) + dataptr[1];
286 if(dataptr == last_byte) {
287 t = (dataptr[0] << 8) + 0;
299ipv4_checksum(
struct ipv4_hdr *hdr)
303 sum = chksum(0, (uint8_t *)hdr, IPV4_HDRLEN);
304 return (sum == 0) ? 0xffff :
uip_htons(sum);
308ipv4_transport_checksum(
const uint8_t *packet, uint16_t len, uint8_t proto)
310 uint16_t transport_layer_len;
312 struct ipv4_hdr *v4hdr = (
struct ipv4_hdr *)packet;
314 transport_layer_len = len - IPV4_HDRLEN;
318 if(proto != IP_PROTO_ICMPV4) {
320 sum = transport_layer_len + proto;
322 sum = chksum(sum, (uint8_t *)&v4hdr->srcipaddr, 2 *
sizeof(
uip_ip4addr_t));
329 sum = chksum(sum, &packet[IPV4_HDRLEN], transport_layer_len);
331 return (sum == 0) ? 0xffff :
uip_htons(sum);
335ipv6_transport_checksum(
const uint8_t *packet, uint16_t len, uint8_t proto)
337 uint16_t transport_layer_len;
339 struct ipv6_hdr *v6hdr = (
struct ipv6_hdr *)packet;
341 transport_layer_len = len - IPV6_HDRLEN;
346 sum = transport_layer_len + proto;
348 sum = chksum(sum, (uint8_t *)&v6hdr->srcipaddr,
sizeof(uip_ip6addr_t));
349 sum = chksum(sum, (uint8_t *)&v6hdr->destipaddr,
sizeof(uip_ip6addr_t));
352 sum = chksum(sum, &packet[IPV6_HDRLEN], transport_layer_len);
354 return (sum == 0) ? 0xffff :
uip_htons(sum);
358ip64_6to4(
const uint8_t *ipv6packet,
const uint16_t ipv6packet_len,
359 uint8_t *resultpacket)
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;
370 v6hdr = (
struct ipv6_hdr *)ipv6packet;
371 v4hdr = (
struct ipv4_hdr *)resultpacket;
373 if((v6hdr->len[0] << 8) + v6hdr->len[1] <= ipv6packet_len) {
374 ipv6len = (v6hdr->len[0] << 8) + v6hdr->len[1] + IPV6_HDRLEN;
376 LOG_WARN(
"6to4: Packet smaller (%u) than in IPv6 header (%u), dropping\n",
377 ipv6packet_len, (v6hdr->len[0] << 8) + v6hdr->len[1]);
383 memcpy(&resultpacket[IPV4_HDRLEN],
384 &ipv6packet[IPV6_HDRLEN],
385 ipv6len - IPV6_HDRLEN);
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];
400 v4hdr->ipoffset[0] = v4hdr->ipoffset[1] = 0;
405 ipv4len = ipv6len - IPV6_HDRLEN + IPV4_HDRLEN;
406 v4hdr->len[0] = ipv4len >> 8;
407 v4hdr->len[1] = ipv4len & 0xff;
412 v4hdr->ipid[0] = ipid >> 8;
413 v4hdr->ipid[1] = ipid & 0xff;
420 switch(v6hdr->nxthdr) {
422 LOG_DBG(
"6to4: TCP header\n");
423 v4hdr->proto = IP_PROTO_TCP;
428 if(ipv6_transport_checksum(ipv6packet, ipv6len,
429 IP_PROTO_TCP) != 0xffff) {
430 LOG_WARN(
"Bad TCP checksum, dropping\n");
436 LOG_DBG(
"6to4: UDP header\n");
437 v4hdr->proto = IP_PROTO_UDP;
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));
450 if(ipv6_transport_checksum(ipv6packet, ipv6len,
451 IP_PROTO_UDP) != 0xffff) {
452 LOG_WARN(
"Bad UDP checksum, dropping\n");
456 case IP_PROTO_ICMPV6:
457 LOG_DBG(
"6to4: ICMPv6 header\n");
458 v4hdr->proto = IP_PROTO_ICMPV4;
460 if(icmpv6hdr->type == ICMP6_ECHO_REPLY) {
461 icmpv4hdr->type = ICMP_ECHO_REPLY;
463 LOG_WARN(
"6to4: ICMPv6 type %u not supported\n", icmpv6hdr->type);
472 LOG_WARN(
"6to4: Unrecognized IPv6 next header %u\n", v6hdr->nxthdr);
479 v4hdr->ttl = v6hdr->hoplim;
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);
496 if(!ip64_hostaddr_configured &&
498 LOG_ERR(
"6to4: No IPv4 address configured\n");
501 ip64_addr_copy4(&v4hdr->srcipaddr, &ip64_hostaddr);
517 if((v4hdr->proto == IP_PROTO_UDP || v4hdr->proto == IP_PROTO_TCP)) {
519 if(ip64_special_ports_outgoing_is_special(uip_ntohs(udphdr->srcport))) {
521 if(ip64_special_ports_translate_outgoing(uip_ntohs(udphdr->srcport),
526 }
else if(uip_ntohs(udphdr->srcport) >= EPHEMERAL_PORTRANGE) {
527 m = ip64_addrmap_lookup(&v6hdr->srcipaddr,
528 uip_ntohs(udphdr->srcport),
530 uip_ntohs(udphdr->destport),
533 LOG_DBG(
"6to4: Lookup failed\n");
534 m = ip64_addrmap_create(&v6hdr->srcipaddr,
535 uip_ntohs(udphdr->srcport),
537 uip_ntohs(udphdr->destport),
540 LOG_ERR(
"6to4: Could not create new map\n");
543 LOG_DBG(
"6to4: Could create new local port %d\n", m->mapped_port);
546 LOG_DBG(
"6to4: Found local port %d (%d)\n", m->mapped_port,
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);
568 ip64_addrmap_set_lifetime(m, DEFAULT_LIFETIME);
574 if((tcphdr->flags & TCP_FIN) ||
575 (tcphdr->flags & TCP_RST)) {
576 ip64_addrmap_set_recycleble(m);
579 ip64_addrmap_set_lifetime(m, DEFAULT_LIFETIME);
586 if(v4hdr->destipaddr.u8[0] == 224) {
587 ip64_addrmap_set_recycleble(m);
592 if(udphdr->destport ==
UIP_HTONS(DNS_PORT)) {
593 ip64_addrmap_set_recycleble(m);
599 udphdr->srcport =
uip_htons(m->mapped_port);
606 v4hdr->ipchksum = ~(ipv4_checksum(v4hdr));
613 switch(v4hdr->proto) {
615 tcphdr->tcpchksum = 0;
616 tcphdr->tcpchksum = ~(ipv4_transport_checksum(resultpacket, ipv4len,
620 udphdr->udpchksum = 0;
621 udphdr->udpchksum = ~(ipv4_transport_checksum(resultpacket, ipv4len,
623 if(udphdr->udpchksum == 0) {
624 udphdr->udpchksum = 0xffff;
627 case IP_PROTO_ICMPV4:
628 icmpv4hdr->icmpchksum = 0;
629 icmpv4hdr->icmpchksum = ~(ipv4_transport_checksum(resultpacket, ipv4len,
634 LOG_WARN(
"6to4: Protocol %d not supported\n", v4hdr->proto);
639 LOG_DBG(
"6to4: IPv4 len %d\n", ipv4len);
644ip64_4to6(
const uint8_t *ipv4packet,
const uint16_t ipv4packet_len,
645 uint8_t *resultpacket)
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;
656 v6hdr = (
struct ipv6_hdr *)resultpacket;
657 v4hdr = (
struct ipv4_hdr *)ipv4packet;
659 if((v4hdr->len[0] << 8) + v4hdr->len[1] <= ipv4packet_len) {
660 ipv4len = (v4hdr->len[0] << 8) + v4hdr->len[1];
662 LOG_WARN(
"4to6: Packet smaller (%u) than in IPv4 header (%u), dropping\n",
663 ipv4packet_len, (v4hdr->len[0] << 8) + v4hdr->len[1]);
667 if(ipv4len <= IPV4_HDRLEN) {
673 if(ipv4len - IPV4_HDRLEN + IPV6_HDRLEN > BUFSIZE) {
674 LOG_WARN(
"4to6: Packet too big, dropping\n");
678 memcpy(&resultpacket[IPV6_HDRLEN],
679 &ipv4packet[IPV4_HDRLEN],
680 ipv4len - IPV4_HDRLEN);
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];
687 ipv6len = ipv4len - IPV4_HDRLEN + IPV6_HDRLEN;
688 ipv6_packet_len = ipv6len - IPV6_HDRLEN;
697 v6hdr->len[0] = ipv6_packet_len >> 8;
698 v6hdr->len[1] = ipv6_packet_len & 0xff;
701 v6hdr->hoplim = v4hdr->ttl;
715 if(ip64_addr_4to6(&v4hdr->srcipaddr, &v6hdr->srcipaddr) == 0) {
716 LOG_WARN(
"4to6: Failed to convert source IPv4 address\n");
722 switch(v4hdr->proto) {
724 v6hdr->nxthdr = IP_PROTO_UDP;
727 if(udphdr->srcport ==
UIP_HTONS(DNS_PORT)) {
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;
743 v6hdr->nxthdr = IP_PROTO_TCP;
746 case IP_PROTO_ICMPV4:
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);
755 LOG_WARN(
"4to6: ICMPv4 type %d not supported\n",
765 LOG_WARN(
"4to6: Protocol type %d not supported\n", v4hdr->proto);
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]))))) {
780 if(!ip64_hostaddr_configured) {
781 LOG_ERR(
"4to6: No IPv4 address configured, dropping\n");
786 LOG_WARN(
"4to6: Dest. addr. %d.%d.%d.%d not matching our: %d.%d.%d.%d\n",
805 if((v4hdr->proto == IP_PROTO_TCP || v4hdr->proto == IP_PROTO_UDP)) {
806 if(
uip_htons(tcphdr->destport) < EPHEMERAL_PORTRANGE) {
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;
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);
820 LOG_DBG(
"4to6: New port %d (%d)\n",
821 tcphdr->destport,
uip_htons(tcphdr->destport));
823 ip64_addr_copy6(&v6hdr->destipaddr, &ipv6_local_address);
824 LOG_DBG(
"4to6: No new port\n");
831 m = ip64_addrmap_lookup_port(uip_ntohs(udphdr->destport),
834 LOG_WARN(
"4to6: Lookup failed\n");
837 LOG_DBG(
"4to6: Lookup did not fail\n");
839 ip64_addr_copy6(&v6hdr->destipaddr, &m->ip6addr);
840 udphdr->destport =
uip_htons(m->ip6port);
848 switch(v6hdr->nxthdr) {
850 tcphdr->tcpchksum = 0;
851 tcphdr->tcpchksum = ~(ipv6_transport_checksum(resultpacket,
856 udphdr->udpchksum = 0;
858 udphdr->udplen =
uip_htons(ipv6_packet_len);
859 udphdr->udpchksum = ~(ipv6_transport_checksum(resultpacket,
862 if(udphdr->udpchksum == 0) {
863 udphdr->udpchksum = 0xffff;
867 case IP_PROTO_ICMPV6:
868 icmpv6hdr->icmpchksum = 0;
869 icmpv6hdr->icmpchksum = ~(ipv6_transport_checksum(resultpacket,
874 LOG_WARN(
"4to6: Protocol type %d not supported\n", v4hdr->proto);
879 LOG_DBG(
"4to6: IPv6 len %d\n", ipv6len);
884ip64_hostaddr_is_configured(
void)
886 return ip64_hostaddr_configured;
892 IP64_UIP_FALLBACK_INTERFACE.init();
896interface_output(
void)
898 LOG_DBG(
"Interface output len %d\n",
uip_len);
899 IP64_UIP_FALLBACK_INTERFACE.output();
904const struct uip_fallback_interface ip64_uip_fallback_interface = {
905 interface_init, interface_output
#define ADDR_TENTATIVE
Possible states for the an address (RFC 4862)
uip_ds6_netif_t uip_ds6_if
The single interface.
#define uip_create_linklocal_allnodes_mcast(a)
set IP address a to the link local all-nodes multicast address
#define uip_ip4addr_cmp(addr1, addr2)
Compare two IP addresses.
#define uip_ipaddr_maskcmp(addr1, addr2, mask)
Compare two IP addresses with netmasks.
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
#define uip_ipaddr(addr, addr0, addr1, addr2, addr3)
Construct an IP address from four bytes.
#define uip_ipaddr_to_quad(a)
Convert an IP address to four bytes separated by commas.
uint16_t uip_htons(uint16_t val)
Convert a 16-bit quantity from host byte order to network byte order.
uint16_t uip_len
The length of the packet in the uip_buf buffer.
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.
Representation of an IP address.