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" 64 #include "ip64/ip64-ipv4-dhcp.h" 65 #include "contiki-net.h" 76 #define PRINTF(...) printf(__VA_ARGS__) 86 uint8_t nxthdr, hoplim;
87 uip_ip6addr_t srcipaddr, destipaddr;
102 #define EPHEMERAL_PORTRANGE 1024 104 #define IPV6_HDRLEN 40 105 #define IPV4_HDRLEN 20 107 #define IP_PROTO_ICMPV4 1 108 #define IP_PROTO_TCP 6 109 #define IP_PROTO_UDP 17 110 #define IP_PROTO_ICMPV6 58 112 #define ICMP_ECHO_REPLY 0 114 #define ICMP6_ECHO_REPLY 129 115 #define ICMP6_ECHO 128 148 #define BUFSIZE UIP_BUFSIZE 151 uint8_t *ip64_packet_buffer = ip64_packet_buffer_aligned.u8;
153 uint16_t ip64_packet_buffer_maxlen = BUFSIZE;
159 static uint16_t ipid;
160 static uint8_t ip64_hostaddr_configured = 0;
162 static uip_ip6addr_t ipv6_local_address;
163 static uint8_t ipv6_local_address_configured = 0;
168 #define SYN_LIFETIME (CLOCK_SECOND * 20) 169 #define RST_LIFETIME (CLOCK_SECOND * 30) 170 #define DEFAULT_LIFETIME (CLOCK_SECOND * 60 * 5) 186 uip_ipaddr(&ipv4_broadcast_addr, 255,255,255,255);
187 ip64_hostaddr_configured = 0;
189 PRINTF(
"ip64_init\n");
190 IP64_ETH_DRIVER.init();
192 ip64_ipv4_dhcp_init();
197 for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
199 PRINTF(
"i %d used %d\n", i,
uip_ds6_if.addr_list[i].isused);
202 ip64_set_ipv6_address(&
uip_ds6_if.addr_list[i].ipaddr);
212 ip64_hostaddr_configured = 1;
213 ip64_addr_copy4(&ip64_hostaddr, hostaddr);
219 ip64_addr_copy4(&ip64_netmask, netmask);
225 ip64_addr_copy4(&ip64_draddr, draddr);
229 ip64_get_hostaddr(
void)
231 return &ip64_hostaddr;
235 ip64_get_netmask(
void)
237 return &ip64_netmask;
241 ip64_get_draddr(
void)
249 ip64_set_hostaddr(addr);
250 ip64_set_netmask(netmask);
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]);
260 ip64_set_ipv6_address(
const uip_ip6addr_t *
addr)
262 ip64_addr_copy6(&ipv6_local_address, (
const uip_ip6addr_t *)addr);
263 ipv6_local_address_configured = 1;
265 PRINTF(
"ip64_set_ipv6_address: configuring address ");
266 uip_debug_ipaddr_print(addr);
272 chksum(uint16_t sum,
const uint8_t *data, uint16_t len)
275 const uint8_t *dataptr;
276 const uint8_t *last_byte;
279 last_byte = data + len - 1;
281 while(dataptr < last_byte) {
282 t = (dataptr[0] << 8) + dataptr[1];
290 if(dataptr == last_byte) {
291 t = (dataptr[0] << 8) + 0;
303 ipv4_checksum(
struct ipv4_hdr *hdr)
307 sum = chksum(0, (uint8_t *)hdr, IPV4_HDRLEN);
308 return (sum == 0) ? 0xffff :
uip_htons(sum);
312 ipv4_transport_checksum(
const uint8_t *packet, uint16_t len, uint8_t proto)
314 uint16_t transport_layer_len;
316 struct ipv4_hdr *v4hdr = (
struct ipv4_hdr *)packet;
318 transport_layer_len = len - IPV4_HDRLEN;
322 if(proto != IP_PROTO_ICMPV4) {
324 sum = transport_layer_len + proto;
326 sum = chksum(sum, (uint8_t *)&v4hdr->srcipaddr, 2 *
sizeof(
uip_ip4addr_t));
333 sum = chksum(sum, &packet[IPV4_HDRLEN], transport_layer_len);
335 return (sum == 0) ? 0xffff :
uip_htons(sum);
339 ipv6_transport_checksum(
const uint8_t *packet, uint16_t len, uint8_t proto)
341 uint16_t transport_layer_len;
343 struct ipv6_hdr *v6hdr = (
struct ipv6_hdr *)packet;
345 transport_layer_len = len - IPV6_HDRLEN;
350 sum = transport_layer_len + proto;
352 sum = chksum(sum, (uint8_t *)&v6hdr->srcipaddr,
sizeof(uip_ip6addr_t));
353 sum = chksum(sum, (uint8_t *)&v6hdr->destipaddr,
sizeof(uip_ip6addr_t));
356 sum = chksum(sum, &packet[IPV6_HDRLEN], transport_layer_len);
358 return (sum == 0) ? 0xffff :
uip_htons(sum);
362 ip64_6to4(
const uint8_t *ipv6packet,
const uint16_t ipv6packet_len,
363 uint8_t *resultpacket)
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;
374 v6hdr = (
struct ipv6_hdr *)ipv6packet;
375 v4hdr = (
struct ipv4_hdr *)resultpacket;
377 if((v6hdr->len[0] << 8) + v6hdr->len[1] <= ipv6packet_len) {
378 ipv6len = (v6hdr->len[0] << 8) + v6hdr->len[1] + IPV6_HDRLEN;
380 PRINTF(
"ip64_6to4: packet smaller than reported in IPv6 header, dropping\n");
386 memcpy(&resultpacket[IPV4_HDRLEN],
387 &ipv6packet[IPV6_HDRLEN],
388 ipv6len - IPV6_HDRLEN);
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];
403 v4hdr->ipoffset[0] = v4hdr->ipoffset[1] = 0;
408 ipv4len = ipv6len - IPV6_HDRLEN + IPV4_HDRLEN;
409 v4hdr->len[0] = ipv4len >> 8;
410 v4hdr->len[1] = ipv4len & 0xff;
415 v4hdr->ipid[0] = ipid >> 8;
416 v4hdr->ipid[1] = ipid & 0xff;
423 switch(v6hdr->nxthdr) {
425 PRINTF(
"ip64_6to4: TCP header\n");
426 v4hdr->proto = IP_PROTO_TCP;
431 if(ipv6_transport_checksum(ipv6packet, ipv6len,
432 IP_PROTO_TCP) != 0xffff) {
433 PRINTF(
"Bad TCP checksum, dropping packet\n");
439 PRINTF(
"ip64_6to4: UDP header\n");
440 v4hdr->proto = IP_PROTO_UDP;
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));
453 if(ipv6_transport_checksum(ipv6packet, ipv6len,
454 IP_PROTO_UDP) != 0xffff) {
455 PRINTF(
"Bad UDP checksum, dropping packet\n");
459 case IP_PROTO_ICMPV6:
460 PRINTF(
"ip64_6to4: ICMPv6 header\n");
461 v4hdr->proto = IP_PROTO_ICMPV4;
464 icmpv4hdr->type = ICMP_ECHO_REPLY;
466 PRINTF(
"ip64_6to4: ICMPv6 mapping for type %d not implemented.\n",
476 PRINTF(
"ip64_6to4: Could not convert IPv6 next hop %d to an IPv4 protocol number.\n",
484 v4hdr->ttl = v6hdr->hoplim;
490 if(ip64_addr_6to4(&v6hdr->destipaddr,
491 &v4hdr->destipaddr) == 0) {
493 PRINTF(
"ip64_6to4: Could not convert IPv6 destination address.\n");
494 uip_debug_ipaddr_print(&v6hdr->destipaddr);
503 if(!ip64_hostaddr_configured &&
505 PRINTF(
"ip64_6to4: no IPv4 address configured.\n");
508 ip64_addr_copy4(&v4hdr->srcipaddr, &ip64_hostaddr);
524 if((v4hdr->proto == IP_PROTO_UDP || v4hdr->proto == IP_PROTO_TCP)) {
526 if(ip64_special_ports_outgoing_is_special(uip_ntohs(udphdr->srcport))) {
528 if(ip64_special_ports_translate_outgoing(uip_ntohs(udphdr->srcport),
533 }
else if(uip_ntohs(udphdr->srcport) >= EPHEMERAL_PORTRANGE) {
534 m = ip64_addrmap_lookup(&v6hdr->srcipaddr,
535 uip_ntohs(udphdr->srcport),
537 uip_ntohs(udphdr->destport),
540 PRINTF(
"Lookup failed\n");
541 m = ip64_addrmap_create(&v6hdr->srcipaddr,
542 uip_ntohs(udphdr->srcport),
544 uip_ntohs(udphdr->destport),
547 PRINTF(
"Could not create new map\n");
550 PRINTF(
"Could create new local port %d\n", m->mapped_port);
553 PRINTF(
"Lookup: found local port %d (%d)\n", m->mapped_port,
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);
575 ip64_addrmap_set_lifetime(m, DEFAULT_LIFETIME);
581 if((tcphdr->flags & TCP_FIN) ||
582 (tcphdr->flags & TCP_RST)) {
583 ip64_addrmap_set_recycleble(m);
586 ip64_addrmap_set_lifetime(m, DEFAULT_LIFETIME);
593 if(v4hdr->destipaddr.u8[0] == 224) {
594 ip64_addrmap_set_recycleble(m);
599 if(udphdr->destport ==
UIP_HTONS(DNS_PORT)) {
600 ip64_addrmap_set_recycleble(m);
606 udphdr->srcport =
uip_htons(m->mapped_port);
613 v4hdr->ipchksum = ~(ipv4_checksum(v4hdr));
620 switch(v4hdr->proto) {
622 tcphdr->tcpchksum = 0;
623 tcphdr->tcpchksum = ~(ipv4_transport_checksum(resultpacket, ipv4len,
627 udphdr->udpchksum = 0;
628 udphdr->udpchksum = ~(ipv4_transport_checksum(resultpacket, ipv4len,
630 if(udphdr->udpchksum == 0) {
631 udphdr->udpchksum = 0xffff;
634 case IP_PROTO_ICMPV4:
635 icmpv4hdr->icmpchksum = 0;
636 icmpv4hdr->icmpchksum = ~(ipv4_transport_checksum(resultpacket, ipv4len,
641 PRINTF(
"ip64_6to4: transport protocol %d not implemented\n", v4hdr->proto);
646 PRINTF(
"ip64_6to4: ipv4len %d\n", ipv4len);
651 ip64_4to6(
const uint8_t *ipv4packet,
const uint16_t ipv4packet_len,
652 uint8_t *resultpacket)
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;
663 v6hdr = (
struct ipv6_hdr *)resultpacket;
664 v4hdr = (
struct ipv4_hdr *)ipv4packet;
666 if((v4hdr->len[0] << 8) + v4hdr->len[1] <= ipv4packet_len) {
667 ipv4len = (v4hdr->len[0] << 8) + v4hdr->len[1];
669 PRINTF(
"ip64_4to6: packet smaller than reported in IPv4 header, dropping\n");
673 if(ipv4len <= IPV4_HDRLEN) {
679 if(ipv4len - IPV4_HDRLEN + IPV6_HDRLEN > BUFSIZE) {
680 PRINTF(
"ip64_4to6: packet too big to fit in buffer, dropping\n");
684 memcpy(&resultpacket[IPV6_HDRLEN],
685 &ipv4packet[IPV4_HDRLEN],
686 ipv4len - IPV4_HDRLEN);
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];
693 ipv6len = ipv4len - IPV4_HDRLEN + IPV6_HDRLEN;
694 ipv6_packet_len = ipv6len - IPV6_HDRLEN;
703 v6hdr->len[0] = ipv6_packet_len >> 8;
704 v6hdr->len[1] = ipv6_packet_len & 0xff;
707 v6hdr->hoplim = v4hdr->ttl;
721 if(ip64_addr_4to6(&v4hdr->srcipaddr, &v6hdr->srcipaddr) == 0) {
722 PRINTF(
"ip64_packet_4to6: failed to convert source IP address\n");
728 switch(v4hdr->proto) {
730 v6hdr->nxthdr = IP_PROTO_UDP;
733 if(udphdr->srcport ==
UIP_HTONS(DNS_PORT)) {
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;
749 v6hdr->nxthdr = IP_PROTO_TCP;
752 case IP_PROTO_ICMPV4:
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);
761 PRINTF(
"ip64_packet_4to6: ICMPv4 packet type %d not supported\n",
771 PRINTF(
"ip64_packet_4to6: protocol type %d not supported\n",
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]))))) {
787 if(!ip64_hostaddr_configured) {
788 PRINTF(
"ip64_packet_4to6: no local IPv4 address configured, dropping incoming packet.\n");
793 PRINTF(
"ip64_packet_4to6: the IPv4 destination address %d.%d.%d.%d did not match our IPv4 address %d.%d.%d.%d\n",
812 if((v4hdr->proto == IP_PROTO_TCP || v4hdr->proto == IP_PROTO_UDP)) {
813 if(
uip_htons(tcphdr->destport) < EPHEMERAL_PORTRANGE) {
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;
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);
827 PRINTF(
"New port %d (%d)\n",
828 tcphdr->destport,
uip_htons(tcphdr->destport));
830 ip64_addr_copy6(&v6hdr->destipaddr, &ipv6_local_address);
831 PRINTF(
"No new port\n");
838 m = ip64_addrmap_lookup_port(uip_ntohs(udphdr->destport),
841 PRINTF(
"Inbound lookup failed\n");
844 PRINTF(
"Inbound lookup did not fail\n");
846 ip64_addr_copy6(&v6hdr->destipaddr, &m->ip6addr);
847 udphdr->destport =
uip_htons(m->ip6port);
855 switch(v6hdr->nxthdr) {
857 tcphdr->tcpchksum = 0;
858 tcphdr->tcpchksum = ~(ipv6_transport_checksum(resultpacket,
863 udphdr->udpchksum = 0;
865 udphdr->udplen =
uip_htons(ipv6_packet_len);
866 udphdr->udpchksum = ~(ipv6_transport_checksum(resultpacket,
869 if(udphdr->udpchksum == 0) {
870 udphdr->udpchksum = 0xffff;
874 case IP_PROTO_ICMPV6:
875 icmpv6hdr->icmpchksum = 0;
876 icmpv6hdr->icmpchksum = ~(ipv6_transport_checksum(resultpacket,
881 PRINTF(
"ip64_4to6: transport protocol %d not implemented\n", v4hdr->proto);
886 PRINTF(
"ip64_4to6: ipv6len %d\n", ipv6len);
891 ip64_hostaddr_is_configured(
void)
893 return ip64_hostaddr_configured;
899 IP64_UIP_FALLBACK_INTERFACE.init();
903 interface_output(
void)
905 PRINTF(
"ip64: interface_output len %d\n",
uip_len);
906 IP64_UIP_FALLBACK_INTERFACE.output();
911 const struct uip_fallback_interface ip64_uip_fallback_interface = {
912 interface_init, interface_output
#define uip_ip4addr_cmp(addr1, addr2)
Compare two IP addresses.
uint16_t uip_len
The length of the packet in the uip_buf buffer.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
#define uip_ipaddr_maskcmp(addr1, addr2, mask)
Compare two IP addresses with netmasks.
#define uip_ipaddr_to_quad(a)
Convert an IP address to four bytes separated by commas.
A set of debugging macros for the IP stack
Representation of an IP address.
#define uip_ipaddr(addr, addr0, addr1, addr2, addr3)
Construct an IP address from four bytes.
uint16_t uip_htons(uint16_t val)
Convert a 16-bit quantity from host byte order to network byte order.
Header file for IPv6-related data structures.
#define uip_create_linklocal_allnodes_mcast(a)
set IP address a to the link local all-nodes multicast address
#define ADDR_TENTATIVE
Possible states for the an address (RFC 4862)
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
uip_ds6_netif_t uip_ds6_if
The single interface.
#define ICMP6_ECHO_REPLY
Echo reply.