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