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 
81 struct 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 
90 struct 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 
117 struct 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 
130 struct udp_hdr {
131  uint16_t srcport;
132  uint16_t destport;
133  uint16_t udplen;
134  uint16_t udpchksum;
135 };
136 
137 struct icmpv4_hdr {
138  uint8_t type, icode;
139  uint16_t icmpchksum;
140 };
141 
142 struct icmpv6_hdr {
143  uint8_t type, icode;
144  uint16_t icmpchksum;
145  uint16_t id, seqno;
146 };
147 
148 #define BUFSIZE UIP_BUFSIZE
149 
150 uip_buf_t ip64_packet_buffer_aligned;
151 uint8_t *ip64_packet_buffer = ip64_packet_buffer_aligned.u8;
152 
153 uint16_t ip64_packet_buffer_maxlen = BUFSIZE;
154 
155 static uip_ip4addr_t ip64_hostaddr;
156 static uip_ip4addr_t ip64_netmask;
157 static uip_ip4addr_t ip64_draddr;
158 
159 static uint16_t ipid;
160 static uint8_t ip64_hostaddr_configured = 0;
161 
162 static uip_ip6addr_t ipv6_local_address;
163 static uint8_t ipv6_local_address_configured = 0;
164 
165 static 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 /*---------------------------------------------------------------------------*/
180 void
181 ip64_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 /*---------------------------------------------------------------------------*/
209 void
210 ip64_set_hostaddr(const uip_ip4addr_t *hostaddr)
211 {
212  ip64_hostaddr_configured = 1;
213  ip64_addr_copy4(&ip64_hostaddr, hostaddr);
214 }
215 /*---------------------------------------------------------------------------*/
216 void
217 ip64_set_netmask(const uip_ip4addr_t *netmask)
218 {
219  ip64_addr_copy4(&ip64_netmask, netmask);
220 }
221 /*---------------------------------------------------------------------------*/
222 void
223 ip64_set_draddr(const uip_ip4addr_t *draddr)
224 {
225  ip64_addr_copy4(&ip64_draddr, draddr);
226 }
227 /*---------------------------------------------------------------------------*/
228 const uip_ip4addr_t *
229 ip64_get_hostaddr(void)
230 {
231  return &ip64_hostaddr;
232 }
233 /*---------------------------------------------------------------------------*/
234 const uip_ip4addr_t *
235 ip64_get_netmask(void)
236 {
237  return &ip64_netmask;
238 }
239 /*---------------------------------------------------------------------------*/
240 const uip_ip4addr_t *
241 ip64_get_draddr(void)
242 {
243  return &ip64_draddr;
244 }
245 /*---------------------------------------------------------------------------*/
246 void
247 ip64_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 /*---------------------------------------------------------------------------*/
259 void
260 ip64_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 /*---------------------------------------------------------------------------*/
271 static uint16_t
272 chksum(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 /*---------------------------------------------------------------------------*/
302 static uint16_t
303 ipv4_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 /*---------------------------------------------------------------------------*/
311 static uint16_t
312 ipv4_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 /*---------------------------------------------------------------------------*/
338 static uint16_t
339 ipv6_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 /*---------------------------------------------------------------------------*/
361 int
362 ip64_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 /*---------------------------------------------------------------------------*/
650 int
651 ip64_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 /*---------------------------------------------------------------------------*/
890 int
891 ip64_hostaddr_is_configured(void)
892 {
893  return ip64_hostaddr_configured;
894 }
895 /*---------------------------------------------------------------------------*/
896 static void
897 interface_init(void)
898 {
899  IP64_UIP_FALLBACK_INTERFACE.init();
900 }
901 /*---------------------------------------------------------------------------*/
902 static int
903 interface_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 /*---------------------------------------------------------------------------*/
911 const struct uip_fallback_interface ip64_uip_fallback_interface = {
912  interface_init, interface_output
913 };
914 
#define uip_ip4addr_cmp(addr1, addr2)
Compare two IP addresses.
Definition: uip.h:1044
uint16_t uip_len
The length of the packet in the uip_buf buffer.
Definition: uip6.c:159
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:107
#define uip_ipaddr_maskcmp(addr1, addr2, mask)
Compare two IP addresses with netmasks.
Definition: uip.h:1075
#define uip_ipaddr_to_quad(a)
Convert an IP address to four bytes separated by commas.
Definition: uip.h:916
A set of debugging macros for the IP stack
Representation of an IP address.
Definition: uip.h:95
#define uip_ipaddr(addr, addr0, addr1, addr2, addr3)
Construct an IP address from four bytes.
Definition: uip.h:944
uint16_t uip_htons(uint16_t val)
Convert a 16-bit quantity from host byte order to network byte order.
Definition: uip6.c:2347
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
Definition: uip.h:1885
#define ADDR_TENTATIVE
Possible states for the an address (RFC 4862)
Definition: uip-ds6.h:156
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
Definition: uip.h:1223
uip_ds6_netif_t uip_ds6_if
The single interface.
Definition: uip-ds6.c:75
#define ICMP6_ECHO_REPLY
Echo reply.
Definition: uip-icmp6.h:58
The uIP packet buffer.
Definition: uip.h:502