Merge pull request #804 from adamdunkels/pr/ip64

NAT64 for Contiki (RFC6164, RFC6147)
This commit is contained in:
Nicolas Tsiftes 2014-10-08 19:41:09 +02:00
commit 0a88764185
24 changed files with 3279 additions and 0 deletions

29
core/net/ip64/README.md Normal file
View file

@ -0,0 +1,29 @@
The `ip64` module lets an IPv6 Contiki network be connected to an IPv4
network without any additional configuration or outside software. The
`ip64` module runs on the RPL root node and translates outgoing IPv6
packets into IPv4 packets nd incoming IPv4 packets to IPv6 packets.
The `ip64` module uses stateful NAT64 (RFC6164) to do the packet
translation and DNS64 (RFC6147) to catch DNS requests for IPv6
addresses, turn them into requests for IPv4 addresses, and turn the
replies into responses for IPv6 addresses. This allows devices on the
inside IPv6 network to connect to named servers on the outside IPv4
network.
The `ip64` module hooks into the IPv6 stack via a fallback
interface. Any packet that can not be routed into the local RPL mesh
will be sent over the fallback interface, where `ip64` picks it up,
translates it into an IPv4 packet, and sends it over its outgoing
interface.
In addition to providing NAT64 and DNS64 services, the `ip64` module
also performs DHCPv4 to request IPv4 address for devices connected to
a medium such as Ethernet. The `ip64` module also performs ARP
processing to communicate over the Ethernet.
The `ip64` module uses a configuration file called `ip64-conf.h` that
specifies what device to use for the IPv4 network. This file is
intended to be placed in the platform directory. An example
configuration file called `ip64-conf-example.h` is provided in this
directory.

View file

@ -0,0 +1,249 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "ip64-addrmap.h"
#include "lib/memb.h"
#include "lib/list.h"
#include "ip64-conf.h"
#include <string.h>
#ifdef IP64_ADDRMAP_CONF_ENTRIES
#define NUM_ENTRIES IP64_ADDRMAP_CONF_ENTRIES
#else /* IP64_ADDRMAP_CONF_ENTRIES */
#define NUM_ENTRIES 32
#endif /* IP64_ADDRMAP_CONF_ENTRIES */
MEMB(entrymemb, struct ip64_addrmap_entry, NUM_ENTRIES);
LIST(entrylist);
#define FIRST_MAPPED_PORT 10000
#define LAST_MAPPED_PORT 20000
static uint16_t mapped_port = FIRST_MAPPED_PORT;
#define printf(...)
/*---------------------------------------------------------------------------*/
struct ip64_addrmap_entry *
ip64_addrmap_list(void)
{
return list_head(entrylist);
}
/*---------------------------------------------------------------------------*/
void
ip64_addrmap_init(void)
{
memb_init(&entrymemb);
list_init(entrylist);
mapped_port = FIRST_MAPPED_PORT;
}
/*---------------------------------------------------------------------------*/
static void
check_age(void)
{
struct ip64_addrmap_entry *m;
/* Walk through the list of address mappings, throw away the ones
that are too old. */
m = list_head(entrylist);
while(m != NULL) {
if(timer_expired(&m->timer)) {
list_remove(entrylist, m);
memb_free(&entrymemb, m);
m = list_head(entrylist);
} else {
m = list_item_next(m);
}
}
}
/*---------------------------------------------------------------------------*/
static int
recycle(void)
{
/* Find the oldest recyclable mapping and remove it. */
struct ip64_addrmap_entry *m, *oldest;
/* Walk through the list of address mappings, throw away the ones
that are too old. */
oldest = NULL;
for(m = list_head(entrylist);
m != NULL;
m = list_item_next(m)) {
if(m->flags & FLAGS_RECYCLABLE) {
if(oldest == NULL) {
oldest = m;
} else {
if(timer_remaining(&m->timer) <
timer_remaining(&oldest->timer)) {
oldest = m;
}
}
}
}
/* If we found an oldest recyclable entry, remove it and return
non-zero. */
if(oldest != NULL) {
list_remove(entrylist, oldest);
memb_free(&entrymemb, oldest);
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------*/
struct ip64_addrmap_entry *
ip64_addrmap_lookup(const uip_ip6addr_t *ip6addr,
uint16_t ip6port,
const uip_ip4addr_t *ip4addr,
uint16_t ip4port,
uint8_t protocol)
{
struct ip64_addrmap_entry *m;
printf("lookup ip4port %d ip6port %d\n", uip_htons(ip4port),
uip_htons(ip6port));
check_age();
for(m = list_head(entrylist); m != NULL; m = list_item_next(m)) {
printf("protocol %d %d, ip4port %d %d, ip6port %d %d, ip4 %d ip6 %d\n",
m->protocol, protocol,
m->ip4port, ip4port,
m->ip6port, ip6port,
uip_ip4addr_cmp(&m->ip4addr, ip4addr),
uip_ip6addr_cmp(&m->ip6addr, ip6addr));
if(m->protocol == protocol &&
m->ip4port == ip4port &&
m->ip6port == ip6port &&
uip_ip4addr_cmp(&m->ip4addr, ip4addr) &&
uip_ip6addr_cmp(&m->ip6addr, ip6addr)) {
return m;
}
}
return NULL;
}
/*---------------------------------------------------------------------------*/
struct ip64_addrmap_entry *
ip64_addrmap_lookup_port(uint16_t mapped_port, uint8_t protocol)
{
struct ip64_addrmap_entry *m;
check_age();
for(m = list_head(entrylist); m != NULL; m = list_item_next(m)) {
printf("mapped port %d %d, protocol %d %d\n",
m->mapped_port, mapped_port,
m->protocol, protocol);
if(m->mapped_port == mapped_port &&
m->protocol == protocol) {
return m;
}
}
return NULL;
}
/*---------------------------------------------------------------------------*/
static void
increase_mapped_port(void)
{
mapped_port++;
if(mapped_port >= LAST_MAPPED_PORT) {
mapped_port = FIRST_MAPPED_PORT;
}
}
/*---------------------------------------------------------------------------*/
struct ip64_addrmap_entry *
ip64_addrmap_create(const uip_ip6addr_t *ip6addr,
uint16_t ip6port,
const uip_ip4addr_t *ip4addr,
uint16_t ip4port,
uint8_t protocol)
{
struct ip64_addrmap_entry *m;
check_age();
m = memb_alloc(&entrymemb);
if(m == NULL) {
/* We could not allocate an entry, try to recycle one and try to
allocate again. */
if(recycle()) {
m = memb_alloc(&entrymemb);
}
}
if(m != NULL) {
uip_ip4addr_copy(&m->ip4addr, ip4addr);
m->ip4port = ip4port;
uip_ip6addr_copy(&m->ip6addr, ip6addr);
m->ip6port = ip6port;
m->protocol = protocol;
m->flags = FLAGS_NONE;
timer_set(&m->timer, 0);
/* Pick a new, unused local port. First make sure that the
mapped_port number does not belong to any active connection. If
so, we keep increasing the mapped_port until we're free. */
{
struct ip64_addrmap_entry *n;
n = list_head(entrylist);
while(n != NULL) {
if(n->mapped_port == mapped_port) {
increase_mapped_port();
n = list_head(entrylist);
} else {
n = list_item_next(m);
}
}
}
m->mapped_port = mapped_port;
increase_mapped_port();
list_add(entrylist, m);
return m;
}
return NULL;
}
/*---------------------------------------------------------------------------*/
void
ip64_addrmap_set_lifetime(struct ip64_addrmap_entry *e,
clock_time_t time)
{
if(e != NULL) {
timer_set(&e->timer, time);
}
}
/*---------------------------------------------------------------------------*/
void
ip64_addrmap_set_recycleble(struct ip64_addrmap_entry *e)
{
if(e != NULL) {
e->flags |= FLAGS_RECYCLABLE;
}
}
/*---------------------------------------------------------------------------*/

View file

@ -0,0 +1,101 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef IP64_ADDRMAP_H
#define IP64_ADDRMAP_H
#include "sys/timer.h"
#include "net/ip/uip.h"
struct ip64_addrmap_entry {
struct ip64_addrmap_entry *next;
struct timer timer;
uip_ip6addr_t ip6addr;
uip_ip4addr_t ip4addr;
uint16_t mapped_port;
uint16_t ip6port;
uint16_t ip4port;
uint8_t protocol;
uint8_t flags;
};
#define FLAGS_NONE 0
#define FLAGS_RECYCLABLE 1
/**
* Initialize the ip64_addrmap module.
*/
void ip64_addrmap_init(void);
/**
* Look up an address mapping from inside the IPv6 network, given the
* IPv6 address/port, the IPv4 address/port, and the protocol.
*/
struct ip64_addrmap_entry *ip64_addrmap_lookup(const uip_ip6addr_t *ip6addr,
uint16_t ip6port,
const uip_ip4addr_t *ip4addr,
uint16_t ip4port,
uint8_t protocol);
/**
* Look up an address mapping from the outside IPv4 network, given the
* mapped port number and protocol.
*/
struct ip64_addrmap_entry *ip64_addrmap_lookup_port(uint16_t mappedport,
uint8_t protocol);
/**
* Create a new address mapping from an IPv6 address/port, an IPv4
* address/port, and a protocol number.
*/
struct ip64_addrmap_entry *ip64_addrmap_create(const uip_ip6addr_t *ip6addr,
uint16_t ip6port,
const uip_ip4addr_t *ip4addr,
uint16_t ip4port,
uint8_t protocol);
/**
* Set the lifetime of an address mapping.
*/
void ip64_addrmap_set_lifetime(struct ip64_addrmap_entry *e,
clock_time_t lifetime);
/**
* Mark an address mapping to be recyclable.
*/
void ip64_addrmap_set_recycleble(struct ip64_addrmap_entry *e);
/**
* Obtain the list of all address mappings.
*/
struct ip64_addrmap_entry *ip64_addrmap_list(void);
#endif /* IP64_ADDRMAP_H */

417
core/net/ip64/ip64-arp.c Normal file
View file

@ -0,0 +1,417 @@
/*
* Copyright (c) 2001-2003, Adam Dunkels.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This file is part of the uIP TCP/IP stack.
*
* $Id: uip_arp.c,v 1.8 2010/12/14 22:45:22 dak664 Exp $
*
*/
#include "ip64.h"
#include "ip64-eth.h"
#include "ip64-arp.h"
#include <string.h>
#include <stdio.h>
#define printf(...)
struct arp_hdr {
struct ip64_eth_hdr ethhdr;
uint16_t hwtype;
uint16_t protocol;
uint8_t hwlen;
uint8_t protolen;
uint16_t opcode;
struct uip_eth_addr shwaddr;
uip_ip4addr_t sipaddr;
struct uip_eth_addr dhwaddr;
uip_ip4addr_t dipaddr;
};
struct ethip_hdr {
struct ip64_eth_hdr ethhdr;
/* IP header. */
uint8_t vhl,
tos,
len[2],
ipid[2],
ipoffset[2],
ttl,
proto;
uint16_t ipchksum;
uip_ip4addr_t srcipaddr, destipaddr;
};
struct ipv4_hdr {
/* IP header. */
uint8_t vhl,
tos,
len[2],
ipid[2],
ipoffset[2],
ttl,
proto;
uint16_t ipchksum;
uip_ip4addr_t srcipaddr, destipaddr;
};
#define ARP_REQUEST 1
#define ARP_REPLY 2
#define ARP_HWTYPE_ETH 1
struct arp_entry {
uip_ip4addr_t ipaddr;
struct uip_eth_addr ethaddr;
uint8_t time;
};
static const struct ip64_eth_addr broadcast_ethaddr =
{{0xff,0xff,0xff,0xff,0xff,0xff}};
static const uint16_t broadcast_ipaddr[2] = {0xffff,0xffff};
static struct arp_entry arp_table[UIP_ARPTAB_SIZE];
static uint8_t arptime;
static uint8_t tmpage;
#define DEBUG 0
#if DEBUG
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PRINTF(...)
#endif
const uip_ipaddr_t uip_all_zeroes_addr;
/*---------------------------------------------------------------------------*/
/**
* Initialize the ARP module.
*
*/
/*---------------------------------------------------------------------------*/
void
ip64_arp_init(void)
{
int i;
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
memset(&arp_table[i].ipaddr, 0, 4);
}
}
/*---------------------------------------------------------------------------*/
/**
* Periodic ARP processing function.
*
* This function performs periodic timer processing in the ARP module
* and should be called at regular intervals. The recommended interval
* is 10 seconds between the calls.
*
*/
/*---------------------------------------------------------------------------*/
void
ip64_arp_timer(void)
{
struct arp_entry *tabptr;
int i;
++arptime;
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
tabptr = &arp_table[i];
if(uip_ip4addr_cmp(&tabptr->ipaddr, &uip_all_zeroes_addr) &&
arptime - tabptr->time >= UIP_ARP_MAXAGE) {
memset(&tabptr->ipaddr, 0, 4);
}
}
}
/*---------------------------------------------------------------------------*/
static void
arp_update(uip_ip4addr_t *ipaddr, struct uip_eth_addr *ethaddr)
{
register struct arp_entry *tabptr = arp_table;
int i, c;
/* Walk through the ARP mapping table and try to find an entry to
update. If none is found, the IP -> MAC address mapping is
inserted in the ARP table. */
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
tabptr = &arp_table[i];
/* Only check those entries that are actually in use. */
if(!uip_ip4addr_cmp(&tabptr->ipaddr, &uip_all_zeroes_addr)) {
/* Check if the source IP address of the incoming packet matches
the IP address in this ARP table entry. */
if(uip_ip4addr_cmp(ipaddr, &tabptr->ipaddr)) {
/* An old entry found, update this and return. */
memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
tabptr->time = arptime;
return;
}
}
tabptr++;
}
/* If we get here, no existing ARP table entry was found, so we
create one. */
/* First, we try to find an unused entry in the ARP table. */
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
tabptr = &arp_table[i];
if(uip_ip4addr_cmp(&tabptr->ipaddr, &uip_all_zeroes_addr)) {
break;
}
}
/* If no unused entry is found, we try to find the oldest entry and
throw it away. */
if(i == UIP_ARPTAB_SIZE) {
tmpage = 0;
c = 0;
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
tabptr = &arp_table[i];
if(arptime - tabptr->time > tmpage) {
tmpage = arptime - tabptr->time;
c = i;
}
}
i = c;
tabptr = &arp_table[i];
}
/* Now, i is the ARP table entry which we will fill with the new
information. */
uip_ip4addr_copy(&tabptr->ipaddr, ipaddr);
memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
tabptr->time = arptime;
}
/*---------------------------------------------------------------------------*/
uint16_t
ip64_arp_arp_input(const uint8_t *packet, uint16_t packet_len)
{
struct arp_hdr *arphdr = (struct arp_hdr *)packet;
if(packet_len < sizeof(struct arp_hdr)) {
printf("ip64_arp_arp_input: len too small %d\n", packet_len);
return 0;
}
switch(arphdr->opcode) {
case UIP_HTONS(ARP_REQUEST):
/* ARP request. If it asked for our address, we send out a
reply. */
printf("ip64_arp_arp_input: request for %d.%d.%d.%d (we are %d.%d.%d.%d)\n",
arphdr->dipaddr.u8[0], arphdr->dipaddr.u8[1],
arphdr->dipaddr.u8[2], arphdr->dipaddr.u8[3],
ip64_get_hostaddr()->u8[0], ip64_get_hostaddr()->u8[1],
ip64_get_hostaddr()->u8[2], ip64_get_hostaddr()->u8[3]);
if(uip_ip4addr_cmp(&arphdr->dipaddr, ip64_get_hostaddr())) {
/* First, we register the one who made the request in our ARP
table, since it is likely that we will do more communication
with this host in the future. */
arp_update(&arphdr->sipaddr, &arphdr->shwaddr);
arphdr->opcode = UIP_HTONS(ARP_REPLY);
memcpy(arphdr->dhwaddr.addr, arphdr->shwaddr.addr, 6);
memcpy(arphdr->shwaddr.addr, ip64_eth_addr.addr, 6);
memcpy(arphdr->ethhdr.src.addr, ip64_eth_addr.addr, 6);
memcpy(arphdr->ethhdr.dest.addr, arphdr->dhwaddr.addr, 6);
uip_ip4addr_copy(&arphdr->dipaddr, &arphdr->sipaddr);
uip_ip4addr_copy(&arphdr->sipaddr, ip64_get_hostaddr());
arphdr->ethhdr.type = UIP_HTONS(IP64_ETH_TYPE_ARP);
return sizeof(struct arp_hdr);
}
break;
case UIP_HTONS(ARP_REPLY):
/* ARP reply. We insert or update the ARP table if it was meant
for us. */
if(uip_ip4addr_cmp(&arphdr->dipaddr, ip64_get_hostaddr())) {
arp_update(&arphdr->sipaddr, &arphdr->shwaddr);
}
break;
}
return 0;
}
/*---------------------------------------------------------------------------*/
int
ip64_arp_check_cache(const uint8_t *nlhdr)
{
struct ipv4_hdr *ipv4_hdr = (struct ipv4_hdr *)nlhdr;
uip_ip4addr_t broadcast_addr;
struct arp_entry *tabptr = arp_table;
printf("check cache %d.%d.%d.%d\n",
uip_ipaddr_to_quad(&ipv4_hdr->destipaddr));
/* First check if destination is a local broadcast. */
uip_ipaddr(&broadcast_addr, 255,255,255,255);
if(uip_ip4addr_cmp(&ipv4_hdr->destipaddr, &broadcast_addr)) {
printf("Return 1\n");
return 1;
} else if(ipv4_hdr->destipaddr.u8[0] == 224) {
/* Multicast. */
return 1;
} else {
uip_ip4addr_t ipaddr;
int i;
/* Check if the destination address is on the local network. */
if(!uip_ipaddr_maskcmp(&ipv4_hdr->destipaddr,
ip64_get_hostaddr(),
ip64_get_netmask())) {
/* Destination address was not on the local network, so we need to
use the default router's IP address instead of the destination
address when determining the MAC address. */
uip_ip4addr_copy(&ipaddr, ip64_get_draddr());
} else {
/* Else, we use the destination IP address. */
uip_ip4addr_copy(&ipaddr, &ipv4_hdr->destipaddr);
}
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
if(uip_ip4addr_cmp(&ipaddr, &tabptr->ipaddr)) {
break;
}
tabptr++;
}
if(i == UIP_ARPTAB_SIZE) {
return 0;
}
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------*/
int
ip64_arp_create_ethhdr(uint8_t *llhdr, const uint8_t *nlhdr)
{
struct arp_entry *tabptr = arp_table;
struct ipv4_hdr *ipv4_hdr = (struct ipv4_hdr *)nlhdr;
struct ip64_eth_hdr *ethhdr = (struct ip64_eth_hdr *)llhdr;
uip_ip4addr_t broadcast_addr;
/* Find the destination IP address in the ARP table and construct
the Ethernet header. If the destination IP addres isn't on the
local network, we use the default router's IP address instead.
If not ARP table entry is found, we overwrite the original IP
packet with an ARP request for the IP address. */
/* First check if destination is a local broadcast. */
uip_ipaddr(&broadcast_addr, 255,255,255,255);
if(uip_ip4addr_cmp(&ipv4_hdr->destipaddr, &broadcast_addr)) {
memcpy(&ethhdr->dest.addr, &broadcast_ethaddr.addr, 6);
} else if(ipv4_hdr->destipaddr.u8[0] == 224) {
/* Multicast. */
ethhdr->dest.addr[0] = 0x01;
ethhdr->dest.addr[1] = 0x00;
ethhdr->dest.addr[2] = 0x5e;
ethhdr->dest.addr[3] = ipv4_hdr->destipaddr.u8[1];
ethhdr->dest.addr[4] = ipv4_hdr->destipaddr.u8[2];
ethhdr->dest.addr[5] = ipv4_hdr->destipaddr.u8[3];
} else {
uip_ip4addr_t ipaddr;
int i;
/* Check if the destination address is on the local network. */
if(!uip_ipaddr_maskcmp(&ipv4_hdr->destipaddr,
ip64_get_hostaddr(),
ip64_get_netmask())) {
/* Destination address was not on the local network, so we need to
use the default router's IP address instead of the destination
address when determining the MAC address. */
uip_ip4addr_copy(&ipaddr, ip64_get_draddr());
} else {
/* Else, we use the destination IP address. */
uip_ip4addr_copy(&ipaddr, &ipv4_hdr->destipaddr);
}
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
if(uip_ip4addr_cmp(&ipaddr, &tabptr->ipaddr)) {
break;
}
tabptr++;
}
if(i == UIP_ARPTAB_SIZE) {
return 0;
}
memcpy(ethhdr->dest.addr, tabptr->ethaddr.addr, 6);
}
memcpy(ethhdr->src.addr, ip64_eth_addr.addr, 6);
ethhdr->type = UIP_HTONS(IP64_ETH_TYPE_IP);
return sizeof(struct ip64_eth_hdr);
}
/*---------------------------------------------------------------------------*/
int
ip64_arp_create_arp_request(uint8_t *llhdr, const uint8_t *nlhdr)
{
struct ipv4_hdr *ipv4_hdr = (struct ipv4_hdr *)nlhdr;
struct arp_hdr *arp_hdr = (struct arp_hdr *)llhdr;
uip_ip4addr_t ipaddr;
if(!uip_ipaddr_maskcmp(&ipv4_hdr->destipaddr,
ip64_get_hostaddr(),
ip64_get_netmask())) {
/* Destination address was not on the local network, so we need to
use the default router's IP address instead of the destination
address when determining the MAC address. */
uip_ip4addr_copy(&ipaddr, ip64_get_draddr());
} else {
/* Else, we use the destination IP address. */
uip_ip4addr_copy(&ipaddr, &ipv4_hdr->destipaddr);
}
memset(arp_hdr->ethhdr.dest.addr, 0xff, 6);
memset(arp_hdr->dhwaddr.addr, 0x00, 6);
memcpy(arp_hdr->ethhdr.src.addr, ip64_eth_addr.addr, 6);
memcpy(arp_hdr->shwaddr.addr, ip64_eth_addr.addr, 6);
uip_ip4addr_copy(&arp_hdr->dipaddr, &ipaddr);
uip_ip4addr_copy(&arp_hdr->sipaddr, ip64_get_hostaddr());
arp_hdr->opcode = UIP_HTONS(ARP_REQUEST);
arp_hdr->hwtype = UIP_HTONS(ARP_HWTYPE_ETH);
arp_hdr->protocol = UIP_HTONS(IP64_ETH_TYPE_IP);
arp_hdr->hwlen = 6;
arp_hdr->protolen = 4;
arp_hdr->ethhdr.type = UIP_HTONS(IP64_ETH_TYPE_ARP);
uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN];
return sizeof(struct arp_hdr);
}
/*---------------------------------------------------------------------------*/

84
core/net/ip64/ip64-arp.h Normal file
View file

@ -0,0 +1,84 @@
/*
* Copyright (c) 2001-2003, Adam Dunkels.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This file is part of the uIP TCP/IP stack.
*
* $Id: uip_arp.h,v 1.2 2006/08/26 23:58:45 oliverschmidt Exp $
*
*/
#ifndef IP64_ARP_H
#define IP64_ARP_H
#include "net/ip/uip.h"
#include "ip64-eth.h"
/* The uip_arp_init() function must be called before any of the other
ARP functions. */
void ip64_arp_init(void);
/* The uip_arp_ipin() function should be called whenever an IP packet
arrives from the Ethernet. This function refreshes the ARP table or
inserts a new mapping if none exists. The function assumes that an
IP packet with an Ethernet header is present in the uip_buf buffer
and that the length of the packet is in the uip_len variable. */
void ip64_arp_ip_input(const uint8_t *packet, uint16_t packet_len);
/* The uip_arp_arpin() should be called when an ARP packet is received
by the Ethernet driver. This function also assumes that the
Ethernet frame is present in the uip_buf buffer. When the
uip_arp_arpin() function returns, the contents of the uip_buf
buffer should be sent out on the Ethernet if the uip_len variable
is > 0. */
uint16_t ip64_arp_arp_input(const uint8_t *packet, uint16_t packet_len);
/* The uip_arp_out() function should be called when an IP packet
should be sent out on the Ethernet. This function creates an
Ethernet header before the IP header in the uip_buf buffer. The
Ethernet header will have the correct Ethernet MAC destination
address filled in if an ARP table entry for the destination IP
address (or the IP address of the default router) is present. If no
such table entry is found, the IP packet is overwritten with an ARP
request and we rely on TCP to retransmit the packet that was
overwritten. In any case, the uip_len variable holds the length of
the Ethernet frame that should be transmitted. */
void ip64_arp_ip_output(uint8_t *packet, uint16_t packet_len);
int ip64_arp_create_ethhdr(uint8_t *link_header,
const uint8_t *network_header);
int ip64_arp_create_arp_request(uint8_t *link_header,
const uint8_t *network_header);
int ip64_arp_check_cache(const uint8_t *nlhdr);
#endif /* IP64_ARP_H */

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef IP64_CONF_H
#define IP64_CONF_H
#include "ip64-tap-driver.h"
#include "ip64-eth-interface.h"
#define IP64_CONF_UIP_FALLBACK_INTERFACE ip64_eth_interface
#define IP64_CONF_INPUT ip64_eth_interface_input
#define IP64_CONF_ETH_DRIVER ip64_tap_driver
#endif /* IP64_CONF_H */

450
core/net/ip64/ip64-dhcpc.c Normal file
View file

@ -0,0 +1,450 @@
/*
* Copyright (c) 2005, Swedish Institute of Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
* @(#)$Id: dhcpc.c,v 1.9 2010/10/19 18:29:04 adamdunkels Exp $
*/
#include <stdio.h>
#include <string.h>
#include "contiki.h"
#include "contiki-net.h"
#include "ip64-dhcpc.h"
#include "ip64-addr.h"
#define STATE_INITIAL 0
#define STATE_SENDING 1
#define STATE_OFFER_RECEIVED 2
#define STATE_CONFIG_RECEIVED 3
static struct ip64_dhcpc_state s;
struct dhcp_msg {
uint8_t op, htype, hlen, hops;
uint8_t xid[4];
uint16_t secs, flags;
uint8_t ciaddr[4];
uint8_t yiaddr[4];
uint8_t siaddr[4];
uint8_t giaddr[4];
uint8_t chaddr[16];
uint8_t sname[64];
uint8_t file[128];
uint8_t options[312];
};
#if (UIP_BUFSIZE - UIP_UDPIP_HLEN) < 548
#error UIP_CONF_BUFFER_SIZE may be too small to accomodate DHCPv4 packets
#error Increase UIP_CONF_BUFFER_SIZE in your project-conf.h, platform-conf.h, or contiki-conf.h
#error A good size is 600 bytes
#endif
#define BOOTP_BROADCAST 0x8000
#define DHCP_REQUEST 1
#define DHCP_REPLY 2
#define DHCP_HTYPE_ETHERNET 1
#define DHCP_HLEN_ETHERNET 6
#define DHCP_MSG_LEN 236
#define IP64_DHCPC_SERVER_PORT 67
#define IP64_DHCPC_CLIENT_PORT 68
#define DHCPDISCOVER 1
#define DHCPOFFER 2
#define DHCPREQUEST 3
#define DHCPDECLINE 4
#define DHCPACK 5
#define DHCPNAK 6
#define DHCPRELEASE 7
#define DHCP_OPTION_SUBNET_MASK 1
#define DHCP_OPTION_ROUTER 3
#define DHCP_OPTION_DNS_SERVER 6
#define DHCP_OPTION_REQ_IPADDR 50
#define DHCP_OPTION_LEASE_TIME 51
#define DHCP_OPTION_MSG_TYPE 53
#define DHCP_OPTION_SERVER_ID 54
#define DHCP_OPTION_REQ_LIST 55
#define DHCP_OPTION_END 255
static uint32_t xid;
static const uint8_t magic_cookie[4] = {99, 130, 83, 99};
/*---------------------------------------------------------------------------*/
static uint8_t *
add_msg_type(uint8_t *optptr, uint8_t type)
{
*optptr++ = DHCP_OPTION_MSG_TYPE;
*optptr++ = 1;
*optptr++ = type;
return optptr;
}
/*---------------------------------------------------------------------------*/
static uint8_t *
add_server_id(uint8_t *optptr)
{
*optptr++ = DHCP_OPTION_SERVER_ID;
*optptr++ = 4;
memcpy(optptr, s.serverid, 4);
return optptr + 4;
}
/*---------------------------------------------------------------------------*/
static uint8_t *
add_req_ipaddr(uint8_t *optptr)
{
*optptr++ = DHCP_OPTION_REQ_IPADDR;
*optptr++ = 4;
memcpy(optptr, s.ipaddr.u16, 4);
return optptr + 4;
}
/*---------------------------------------------------------------------------*/
static uint8_t *
add_req_options(uint8_t *optptr)
{
*optptr++ = DHCP_OPTION_REQ_LIST;
*optptr++ = 3;
*optptr++ = DHCP_OPTION_SUBNET_MASK;
*optptr++ = DHCP_OPTION_ROUTER;
*optptr++ = DHCP_OPTION_DNS_SERVER;
return optptr;
}
/*---------------------------------------------------------------------------*/
static uint8_t *
add_end(uint8_t *optptr)
{
*optptr++ = DHCP_OPTION_END;
return optptr;
}
/*---------------------------------------------------------------------------*/
static void
create_msg(CC_REGISTER_ARG struct dhcp_msg *m)
{
m->op = DHCP_REQUEST;
m->htype = DHCP_HTYPE_ETHERNET;
m->hlen = s.mac_len;
m->hops = 0;
memcpy(m->xid, &xid, sizeof(m->xid));
m->secs = 0;
m->flags = UIP_HTONS(BOOTP_BROADCAST); /* Broadcast bit. */
/* uip_ipaddr_copy(m->ciaddr, uip_hostaddr);*/
memcpy(m->ciaddr, uip_hostaddr.u16, sizeof(m->ciaddr));
memset(m->yiaddr, 0, sizeof(m->yiaddr));
memset(m->siaddr, 0, sizeof(m->siaddr));
memset(m->giaddr, 0, sizeof(m->giaddr));
memcpy(m->chaddr, s.mac_addr, s.mac_len);
memset(&m->chaddr[s.mac_len], 0, sizeof(m->chaddr) - s.mac_len);
memset(m->sname, 0, sizeof(m->sname));
strcpy((char *)m->sname, "Thingsquare");
memset(m->file, 0, sizeof(m->file));
memcpy(m->options, magic_cookie, sizeof(magic_cookie));
}
/*---------------------------------------------------------------------------*/
static void
send_discover(void)
{
uint8_t *end;
struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
create_msg(m);
end = add_msg_type(&m->options[4], DHCPDISCOVER);
end = add_req_options(end);
end = add_end(end);
uip_send(uip_appdata, (int)(end - (uint8_t *)uip_appdata));
}
/*---------------------------------------------------------------------------*/
static void
send_request(void)
{
uint8_t *end;
struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
create_msg(m);
end = add_msg_type(&m->options[4], DHCPREQUEST);
end = add_server_id(end);
end = add_req_ipaddr(end);
end = add_end(end);
uip_send(uip_appdata, (int)(end - (uint8_t *)uip_appdata));
}
/*---------------------------------------------------------------------------*/
static uint8_t
parse_options(uint8_t *optptr, int len)
{
uint8_t *end = optptr + len;
uint8_t type = 0;
while(optptr < end) {
switch(*optptr) {
case DHCP_OPTION_SUBNET_MASK:
memcpy(s.netmask.u16, optptr + 2, 4);
break;
case DHCP_OPTION_ROUTER:
memcpy(s.default_router.u16, optptr + 2, 4);
break;
case DHCP_OPTION_DNS_SERVER:
memcpy(s.dnsaddr.u16, optptr + 2, 4);
break;
case DHCP_OPTION_MSG_TYPE:
type = *(optptr + 2);
break;
case DHCP_OPTION_SERVER_ID:
memcpy(s.serverid, optptr + 2, 4);
break;
case DHCP_OPTION_LEASE_TIME:
memcpy(s.lease_time, optptr + 2, 4);
break;
case DHCP_OPTION_END:
return type;
}
optptr += optptr[1] + 2;
}
return type;
}
/*---------------------------------------------------------------------------*/
static uint8_t
parse_msg(void)
{
struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
if(m->op == DHCP_REPLY &&
memcmp(m->xid, &xid, sizeof(xid)) == 0 &&
memcmp(m->chaddr, s.mac_addr, s.mac_len) == 0) {
memcpy(s.ipaddr.u16, m->yiaddr, 4);
return parse_options(&m->options[4], uip_datalen());
}
return 0;
}
/*---------------------------------------------------------------------------*/
/*
* Is this a "fresh" reply for me? If it is, return the type.
*/
static int
msg_for_me(void)
{
struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
uint8_t *optptr = &m->options[4];
uint8_t *end = (uint8_t*)uip_appdata + uip_datalen();
if(m->op == DHCP_REPLY &&
memcmp(m->xid, &xid, sizeof(xid)) == 0 &&
memcmp(m->chaddr, s.mac_addr, s.mac_len) == 0) {
while(optptr < end) {
if(*optptr == DHCP_OPTION_MSG_TYPE) {
return *(optptr + 2);
} else if (*optptr == DHCP_OPTION_END) {
return -1;
}
optptr += optptr[1] + 2;
}
}
return -1;
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(handle_dhcp(process_event_t ev, void *data))
{
clock_time_t ticks;
PT_BEGIN(&s.pt);
init:
xid++;
s.state = STATE_SENDING;
s.ticks = CLOCK_SECOND * 4;
while(1) {
while(ev != tcpip_event) {
tcpip_poll_udp(s.conn);
PT_YIELD(&s.pt);
}
send_discover();
etimer_set(&s.etimer, s.ticks);
do {
PT_YIELD(&s.pt);
if(ev == tcpip_event && uip_newdata() && msg_for_me() == DHCPOFFER) {
parse_msg();
s.state = STATE_OFFER_RECEIVED;
goto selecting;
}
} while(!etimer_expired(&s.etimer));
if(s.ticks < CLOCK_SECOND * 60) {
s.ticks *= 2;
}
}
selecting:
xid++;
s.ticks = CLOCK_SECOND;
do {
while(ev != tcpip_event) {
tcpip_poll_udp(s.conn);
PT_YIELD(&s.pt);
}
send_request();
etimer_set(&s.etimer, s.ticks);
do {
PT_YIELD(&s.pt);
if(ev == tcpip_event && uip_newdata() && msg_for_me() == DHCPACK) {
parse_msg();
s.state = STATE_CONFIG_RECEIVED;
goto bound;
}
} while (!etimer_expired(&s.etimer));
if(s.ticks <= CLOCK_SECOND * 10) {
s.ticks += CLOCK_SECOND;
} else {
goto init;
}
} while(s.state != STATE_CONFIG_RECEIVED);
bound:
#if 0
printf("Got IP address %d.%d.%d.%d\n", uip_ipaddr_to_quad(&s.ipaddr));
printf("Got netmask %d.%d.%d.%d\n", uip_ipaddr_to_quad(&s.netmask));
printf("Got DNS server %d.%d.%d.%d\n", uip_ipaddr_to_quad(&s.dnsaddr));
printf("Got default router %d.%d.%d.%d\n",
uip_ipaddr_to_quad(&s.default_router));
printf("Lease expires in %ld seconds\n",
uip_ntohs(s.lease_time[0])*65536ul + uip_ntohs(s.lease_time[1]));
#endif
ip64_dhcpc_configured(&s);
#define MAX_TICKS (~((clock_time_t)0) / 2)
#define MAX_TICKS32 (~((uint32_t)0))
#define IMIN(a, b) ((a) < (b) ? (a) : (b))
if((uip_ntohs(s.lease_time[0])*65536ul + uip_ntohs(s.lease_time[1]))*CLOCK_SECOND/2
<= MAX_TICKS32) {
s.ticks = (uip_ntohs(s.lease_time[0])*65536ul + uip_ntohs(s.lease_time[1])
)*CLOCK_SECOND/2;
} else {
s.ticks = MAX_TICKS32;
}
while(s.ticks > 0) {
ticks = IMIN(s.ticks, MAX_TICKS);
s.ticks -= ticks;
etimer_set(&s.etimer, ticks);
PT_YIELD_UNTIL(&s.pt, etimer_expired(&s.etimer));
}
if((uip_ntohs(s.lease_time[0])*65536ul + uip_ntohs(s.lease_time[1]))*CLOCK_SECOND/2
<= MAX_TICKS32) {
s.ticks = (uip_ntohs(s.lease_time[0])*65536ul + uip_ntohs(s.lease_time[1])
)*CLOCK_SECOND/2;
} else {
s.ticks = MAX_TICKS32;
}
/* renewing: */
xid++;
do {
while(ev != tcpip_event) {
tcpip_poll_udp(s.conn);
PT_YIELD(&s.pt);
}
send_request();
ticks = IMIN(s.ticks / 2, MAX_TICKS);
s.ticks -= ticks;
etimer_set(&s.etimer, ticks);
do {
PT_YIELD(&s.pt);
if(ev == tcpip_event && uip_newdata() && msg_for_me() == DHCPACK) {
parse_msg();
goto bound;
}
} while(!etimer_expired(&s.etimer));
} while(s.ticks >= CLOCK_SECOND*3);
/* rebinding: */
/* lease_expired: */
ip64_dhcpc_unconfigured(&s);
goto init;
PT_END(&s.pt);
}
/*---------------------------------------------------------------------------*/
void
ip64_dhcpc_init(const void *mac_addr, int mac_len)
{
/* Although this is DHCPv4, we explicitly bind the socket to an IPv6
address so that it can operate over the ip64 bridge. */
uip_ip6addr_t v6addr;
uip_ip4addr_t v4addr;
struct uip_udp_conn *conn2;
s.mac_addr = mac_addr;
s.mac_len = mac_len;
s.state = STATE_INITIAL;
uip_ipaddr(&v4addr, 255,255,255,255);
ip64_addr_4to6(&v4addr, &v6addr);
s.conn = udp_new(&v6addr, UIP_HTONS(IP64_DHCPC_SERVER_PORT), NULL);
conn2 = udp_new(NULL, UIP_HTONS(IP64_DHCPC_SERVER_PORT), NULL);
if(s.conn != NULL) {
udp_bind(s.conn, UIP_HTONS(IP64_DHCPC_CLIENT_PORT));
}
if(conn2 != NULL) {
udp_bind(conn2, UIP_HTONS(IP64_DHCPC_CLIENT_PORT));
}
PT_INIT(&s.pt);
}
/*---------------------------------------------------------------------------*/
void
ip64_dhcpc_appcall(process_event_t ev, void *data)
{
if(ev == tcpip_event || ev == PROCESS_EVENT_TIMER) {
handle_dhcp(ev, data);
}
}
/*---------------------------------------------------------------------------*/
void
ip64_dhcpc_request(void)
{
uip_ipaddr_t ipaddr;
if(s.state == STATE_INITIAL) {
uip_ipaddr(&ipaddr, 0,0,0,0);
uip_sethostaddr(&ipaddr);
handle_dhcp(PROCESS_EVENT_NONE, NULL);
}
}
/*---------------------------------------------------------------------------*/

View file

@ -0,0 +1,62 @@
/*
* Copyright (c) 2005, Swedish Institute of Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*/
#ifndef __IP64_DHCPC_H__
#define __IP64_DHCPC_H__
struct ip64_dhcpc_state {
struct pt pt;
char state;
struct uip_udp_conn *conn;
struct etimer etimer;
uint32_t ticks;
const void *mac_addr;
int mac_len;
uint8_t serverid[4];
uint16_t lease_time[2];
uip_ipaddr_t ipaddr;
uip_ipaddr_t netmask;
uip_ipaddr_t dnsaddr;
uip_ipaddr_t default_router;
};
void ip64_dhcpc_init(const void *mac_addr, int mac_len);
void ip64_dhcpc_request(void);
void ip64_dhcpc_appcall(process_event_t ev, void *data);
/* Mandatory callbacks provided by the user. */
void ip64_dhcpc_configured(const struct ip64_dhcpc_state *s);
void ip64_dhcpc_unconfigured(const struct ip64_dhcpc_state *s);
#endif /* __IP64_DHCPC_H__ */

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef IP64_DRIVER_H
#define IP64_DRIVER_H
struct ip64_driver {
void (* init)(void);
int (* output)(uint8_t *packet, uint16_t packet_len);
};
#endif /* IP64_DRIVER_H */

View file

@ -0,0 +1,125 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "net/ip/uip.h"
#include "net/ipv6/uip-ds6.h"
#include "dev/slip.h"
#include "ip64.h"
#include "ip64-arp.h"
#include "ip64-eth-interface.h"
#include <string.h>
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
#define DEBUG DEBUG_NONE
#include "net/ip/uip-debug.h"
#define printf(...)
/*---------------------------------------------------------------------------*/
void
ip64_eth_interface_input(uint8_t *packet, uint16_t len)
{
struct ip64_eth_hdr *ethhdr;
ethhdr = (struct ip64_eth_hdr *)packet;
if(ethhdr->type == UIP_HTONS(IP64_ETH_TYPE_ARP)) {
len = ip64_arp_arp_input(packet, len);
if(len > 0) {
IP64_ETH_DRIVER.output(packet, len);
}
} else if(ethhdr->type == UIP_HTONS(IP64_ETH_TYPE_IP) &&
len > sizeof(struct ip64_eth_hdr)) {
printf("-------------->\n");
uip_len = ip64_4to6(&packet[sizeof(struct ip64_eth_hdr)],
len - sizeof(struct ip64_eth_hdr),
&uip_buf[UIP_LLH_LEN]);
if(uip_len > 0) {
printf("ip64_interface_process: converted %d bytes\n", uip_len);
printf("ip64-interface: input source ");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF(" destination ");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("\n");
tcpip_input();
printf("Done\n");
}
}
}
/*---------------------------------------------------------------------------*/
static void
init(void)
{
printf("ip64-eth-interface: init\n");
}
/*---------------------------------------------------------------------------*/
static void
output(void)
{
int len, ret;
printf("ip64-interface: output source ");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF(" destination ");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("\n");
printf("<--------------\n");
len = ip64_6to4(&uip_buf[UIP_LLH_LEN], uip_len,
&ip64_packet_buffer[sizeof(struct ip64_eth_hdr)]);
printf("ip64-interface: output len %d\n", len);
if(len > 0) {
if(ip64_arp_check_cache(&ip64_packet_buffer[sizeof(struct ip64_eth_hdr)])) {
printf("Create header\n");
ret = ip64_arp_create_ethhdr(ip64_packet_buffer,
&ip64_packet_buffer[sizeof(struct ip64_eth_hdr)]);
if(ret > 0) {
len += ret;
IP64_ETH_DRIVER.output(ip64_packet_buffer, len);
}
} else {
printf("Create request\n");
len = ip64_arp_create_arp_request(ip64_packet_buffer,
&ip64_packet_buffer[sizeof(struct ip64_eth_hdr)]);
IP64_ETH_DRIVER.output(ip64_packet_buffer, len);
}
}
}
/*---------------------------------------------------------------------------*/
const struct uip_fallback_interface ip64_eth_interface = {
init,
output
};
/*---------------------------------------------------------------------------*/

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef IP64_ETH_INTERFACE_H
#define IP64_ETH_INTERFACE_H
#include "net/ip/uip.h"
void ip64_eth_interface_input(uint8_t *packet, uint16_t len);
extern const struct uip_fallback_interface ip64_eth_interface;
#endif /* IP64_ETH_INTERFACE_H */

43
core/net/ip64/ip64-eth.c Normal file
View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "ip64-eth.h"
#include <string.h>
struct ip64_eth_addr ip64_eth_addr;
/*---------------------------------------------------------------------------*/
void
ip64_eth_addr_set(struct ip64_eth_addr *addr)
{
memcpy(&ip64_eth_addr, addr, sizeof(struct ip64_eth_addr));
}
/*---------------------------------------------------------------------------*/

61
core/net/ip64/ip64-eth.h Normal file
View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef IP64_ETH_H
#define IP64_ETH_H
#include "contiki-conf.h"
/**
* The Ethernet address.
*/
struct ip64_eth_addr {
uint8_t addr[6];
};
extern struct ip64_eth_addr ip64_eth_addr;
void ip64_eth_addr_set(struct ip64_eth_addr *addr);
/**
* The Ethernet header.
*/
struct ip64_eth_hdr {
struct ip64_eth_addr dest;
struct ip64_eth_addr src;
uint16_t type;
};
#define IP64_ETH_TYPE_ARP 0x0806
#define IP64_ETH_TYPE_IP 0x0800
#define IP64_ETH_TYPE_IPV6 0x86dd
#endif /* IP64_ETH_H */

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef IP64_INTERFACE_H
#define IP64_INTERFACE_H
struct ip64_interface {
void (* init)(void);
int (* input)(uint8_t *packet, uint16_t packet_len);
int (* output)(uint8_t *packet, uint16_t packet_len);
};
#endif /* IP64_INTERFACE_H */

View file

@ -0,0 +1,95 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "contiki.h"
#include "contiki-net.h"
#include "ip64-dhcpc.h"
#include "ip64.h"
#include "ip64-eth.h"
#include "ip64-addr.h"
#include <stdio.h>
PROCESS(ip64_ipv4_dhcp_process, "IPv4 DHCP");
uip_ipaddr_t uip_hostaddr; /* Needed because it is referenced by dhcpc.c */
/*---------------------------------------------------------------------------*/
void
ip64_ipv4_dhcp_init(void)
{
printf("Starting DHCPv4\n");
process_start(&ip64_ipv4_dhcp_process, NULL);
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(ip64_ipv4_dhcp_process, ev, data)
{
PROCESS_BEGIN();
ip64_dhcpc_init(&ip64_eth_addr, sizeof(ip64_eth_addr));
printf("Inited\n");
ip64_dhcpc_request();
printf("Requested\n");
while(1) {
PROCESS_WAIT_EVENT();
if(ev == tcpip_event ||
ev == PROCESS_EVENT_TIMER) {
ip64_dhcpc_appcall(ev, data);
}
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
void
ip64_dhcpc_configured(const struct ip64_dhcpc_state *s)
{
uip_ip6addr_t ip6dnsaddr;
printf("DHCP Configured with %d.%d.%d.%d\n",
s->ipaddr.u8[0], s->ipaddr.u8[1],
s->ipaddr.u8[2], s->ipaddr.u8[3]);
ip64_set_hostaddr((uip_ip4addr_t *)&s->ipaddr);
ip64_set_netmask((uip_ip4addr_t *)&s->netmask);
ip64_set_draddr((uip_ip4addr_t *)&s->default_router);
ip64_addr_4to6((uip_ip4addr_t *)&s->dnsaddr, &ip6dnsaddr);
// mdns_conf(&ip6dnsaddr);
}
/*---------------------------------------------------------------------------*/
void
ip64_dhcpc_unconfigured(const struct ip64_dhcpc_state *s)
{
}
/*---------------------------------------------------------------------------*/

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef IP64_IPV4_DHCP_H
#define IP64_IPV4_DHCP_H
void ip64_ipv4_dhcp_init(void);
#endif /* IP64_IPV4_DHCP_H */

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "contiki-net.h"
#include "ip64-driver.h"
/*---------------------------------------------------------------------------*/
static void
init(void)
{
}
/*---------------------------------------------------------------------------*/
static int
output(uint8_t *packet, uint16_t len)
{
return 0;
}
/*---------------------------------------------------------------------------*/
const struct ip64_driver ip64_null_driver = {
init,
output
};

View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef IP64_NULL_DRIVER_H
#define IP64_NULL_DRIVER_H
#include "ip64-driver.h"
extern const struct ip64_driver ip64_null_driver;
#endif /* IP64_NULL_DRIVER_H */

View file

@ -0,0 +1,150 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "net/ip/uip.h"
#include "net/ipv6/uip-ds6.h"
#include "dev/slip.h"
#include "ip64.h"
#include <string.h>
#include <stdio.h>
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
#define DEBUG DEBUG_NONE
#include "net/ip/uip-debug.h"
static uip_ipaddr_t last_sender;
/*---------------------------------------------------------------------------*/
void
ip64_slip_interface_input(uint8_t *packet, uint16_t len)
{
/* Dummy definition: this function is not actually called, but must
be here to conform to the ip65-interface.h structure. */
}
/*---------------------------------------------------------------------------*/
static void
input_callback(void)
{
/*PRINTF("SIN: %u\n", uip_len);*/
if(uip_buf[0] == '!') {
PRINTF("Got configuration message of type %c\n", uip_buf[1]);
uip_len = 0;
#if 0
if(uip_buf[1] == 'P') {
uip_ipaddr_t prefix;
/* Here we set a prefix !!! */
memset(&prefix, 0, 16);
memcpy(&prefix, &uip_buf[2], 8);
PRINTF("Setting prefix ");
PRINT6ADDR(&prefix);
PRINTF("\n");
set_prefix_64(&prefix);
}
#endif
} else if(uip_buf[0] == '?') {
PRINTF("Got request message of type %c\n", uip_buf[1]);
if(uip_buf[1] == 'M') {
const char *hexchar = "0123456789abcdef";
int j;
/* this is just a test so far... just to see if it works */
uip_buf[0] = '!';
for(j = 0; j < 8; j++) {
uip_buf[2 + j * 2] = hexchar[uip_lladdr.addr[j] >> 4];
uip_buf[3 + j * 2] = hexchar[uip_lladdr.addr[j] & 15];
}
uip_len = 18;
slip_send();
}
uip_len = 0;
} else {
/* Save the last sender received over SLIP to avoid bouncing the
packet back if no route is found */
uip_ipaddr_copy(&last_sender, &UIP_IP_BUF->srcipaddr);
uint16_t len = ip64_4to6(&uip_buf[UIP_LLH_LEN], uip_len,
ip64_packet_buffer);
if(len > 0) {
memcpy(&uip_buf[UIP_LLH_LEN], ip64_packet_buffer, len);
uip_len = len;
/* PRINTF("send len %d\n", len); */
} else {
uip_len = 0;
}
}
}
/*---------------------------------------------------------------------------*/
static void
init(void)
{
PRINTF("ip64-slip-interface: init\n");
// slip_arch_init(BAUD2UBR(115200));
process_start(&slip_process, NULL);
slip_set_input_callback(input_callback);
}
/*---------------------------------------------------------------------------*/
static void
output(void)
{
int len;
PRINTF("ip64-slip-interface: output source ");
/*
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF(" destination ");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("\n");
*/
if(uip_ipaddr_cmp(&last_sender, &UIP_IP_BUF->srcipaddr)) {
PRINTF("ip64-interface: output, not sending bounced message\n");
} else {
len = ip64_6to4(&uip_buf[UIP_LLH_LEN], uip_len,
ip64_packet_buffer);
PRINTF("ip64-interface: output len %d\n", len);
if(len > 0) {
memcpy(&uip_buf[UIP_LLH_LEN], ip64_packet_buffer, len);
uip_len = len;
slip_send();
}
}
}
/*---------------------------------------------------------------------------*/
const struct uip_fallback_interface ip64_slip_interface = {
init, output
};
/*---------------------------------------------------------------------------*/

View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef IP64_SLIP_INTERFACE_H
#define IP64_SLIP_INTERFACE_H
void ip64_slip_interface_input(uint8_t *packet, uint16_t len);
extern const struct uip_fallback_interface ip64_slip_interface;
#endif /* IP64_SLIP_INTERFACE_H */

View file

@ -0,0 +1,76 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "ip64.h"
#include "ip64-special-ports.h"
#ifndef IP64_SPECIAL_PORTS_CONF_ENABLE
#define EMPTY_DEFINITIONS 1
#else
#if IP64_SPECIAL_PORTS_CONF_ENABLE == 0
#define EMPTY_DEFINITIONS 1
#endif /* IP64_SPECIAL_PORTS_CONF_ENABLE */
#endif /* IP64_SPECIAL_PORTS_CONF_ENABLE */
#if EMPTY_DEFINITIONS
/*---------------------------------------------------------------------------*/
int
ip64_special_ports_translate_incoming(uint16_t incoming_port,
uip_ip6addr_t *newaddr,
uint16_t *newport)
{
return 0;
}
/*---------------------------------------------------------------------------*/
int
ip64_special_ports_translate_outgoing(uint16_t incoming_port,
const uip_ip6addr_t *ip6addr,
uint16_t *newport)
{
return 0;
}
/*---------------------------------------------------------------------------*/
int
ip64_special_ports_incoming_is_special(uint16_t port)
{
/* Default is to have no special ports. */
return 0;
}
/*---------------------------------------------------------------------------*/
int
ip64_special_ports_outgoing_is_special(uint16_t port)
{
/* Default is to have no special ports. */
return 0;
}
/*---------------------------------------------------------------------------*/
#endif /* EMPTY_DEFINITIONS */

View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef IP64_SPECIAL_PORTS_H
#define IP64_SPECIAL_PORTS_H
/* The IP64 special ports module allows specific ports on the IP64
translator to be mapped to specific address in the IPv6
network. The module provides three function prototypes that must be
implemented by the user.
The IP64 special ports module must be enabled by
#define IP64_SPECIAL_PORTS_CONF_ENABLE 1
Otherwise, the functions are replaced by empty default definitions
in the ip64-special-ports.c module.
Port numbers are always in network byte order. */
/* Translate the special port to an IPv6 address for inbound
packets. */
int ip64_special_ports_translate_incoming(uint16_t incoming_port,
uip_ip6addr_t *newaddr,
uint16_t *newport);
int ip64_special_ports_translate_outgoing(uint16_t incoming_port,
const uip_ip6addr_t *ip6addr,
uint16_t *newport);
/* Check if an incoming (destination) port is special. */
int ip64_special_ports_incoming_is_special(uint16_t port);
/* Check if an outgoing (source) port is special. */
int ip64_special_ports_outgoing_is_special(uint16_t port);
#endif /* IP64_SPECIAL_PORTS_H */

873
core/net/ip64/ip64.c Normal file
View file

@ -0,0 +1,873 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* The ip64 module is a translator between IPv6 and IPv4 packets. The
IPv6 packets come from an IPv6 network and are translated into a
single IPv4 host, as shown in the ASCII graphics below. The IPv6
network typically is a low-power RF network and the IPv4 network
typically is an Ethernet.
+----------------+
| |
| | +------+
| IPv6 network |---| ip64 |-- IPv4 network
| | +------+
| |
+----------------+
ip64 maps all IPv6 addresses from inside the IPv6 network to its
own IPv4 address. This IPv4 address would typically have been
obtained with DHCP from the IPv4 network, but the exact way this
has been obtained is outside the scope of the ip64 module. The IPv4
address is given to the ip64 module through the
ip64_set_ipv4_address() function.
*/
#include "ip64.h"
#include "ip64-addr.h"
#include "ip64-addrmap.h"
#include "ip64-conf.h"
#include "ip64-special-ports.h"
#include "ip64-eth-interface.h"
#include "ip64-slip-interface.h"
#include "ip64-ipv4-dhcp.h"
#include "contiki-net.h"
#include "net/ip/uip-debug.h"
#include <string.h> /* for memcpy() */
#include <stdio.h> /* for printf() */
#define DEBUG 0
#if DEBUG
#undef PRINTF
#define PRINTF(...) printf(__VA_ARGS__)
#else /* DEBUG */
#define PRINTF(...)
#endif /* DEBUG */
struct ipv6_hdr {
uint8_t vtc;
uint8_t tcflow;
uint16_t flow;
uint8_t len[2];
uint8_t nxthdr, hoplim;
uip_ip6addr_t srcipaddr, destipaddr;
};
struct ipv4_hdr {
uint8_t vhl,
tos,
len[2],
ipid[2],
ipoffset[2],
ttl,
proto;
uint16_t ipchksum;
uip_ip4addr_t srcipaddr, destipaddr;
};
#define EPHEMERAL_PORTRANGE 1024
#define IPV6_HDRLEN 40
#define IPV4_HDRLEN 20
#define IP_PROTO_ICMPV4 1
#define IP_PROTO_TCP 6
#define IP_PROTO_UDP 17
#define IP_PROTO_ICMPV6 58
#define ICMP_ECHO_REPLY 0
#define ICMP_ECHO 8
#define ICMP6_ECHO_REPLY 129
#define ICMP6_ECHO 128
struct tcp_hdr {
uint16_t srcport;
uint16_t destport;
uint8_t seqno[4];
uint8_t ackno[4];
uint8_t tcpoffset;
uint8_t flags;
uint8_t wnd[2];
uint16_t tcpchksum;
uint8_t urgp[2];
uint8_t optdata[4];
};
struct udp_hdr {
uint16_t srcport;
uint16_t destport;
uint16_t udplen;
uint16_t udpchksum;
};
struct icmpv4_hdr {
uint8_t type, icode;
uint16_t icmpchksum;
};
struct icmpv6_hdr {
uint8_t type, icode;
uint16_t icmpchksum;
uint16_t id, seqno;
};
#define BUFSIZE UIP_BUFSIZE
uip_buf_t ip64_packet_buffer_aligned;
uint8_t *ip64_packet_buffer = ip64_packet_buffer_aligned.u8;
uint16_t ip64_packet_buffer_maxlen = BUFSIZE;
static uip_ip4addr_t ip64_hostaddr;
static uip_ip4addr_t ip64_netmask;
static uip_ip4addr_t ip64_draddr;
static uint16_t ipid;
static uint8_t ip64_hostaddr_configured = 0;
static uip_ip6addr_t ipv6_local_address;
static uint8_t ipv6_local_address_configured = 0;
static uip_ip4addr_t ipv4_broadcast_addr;
/* Lifetimes for address mappings. */
#define SYN_LIFETIME (CLOCK_SECOND * 20)
#define RST_LIFETIME (CLOCK_SECOND * 30)
#define DEFAULT_LIFETIME (CLOCK_SECOND * 60 * 5)
/* TCP flag defines */
#define TCP_FIN 0x01
#define TCP_SYN 0x02
#define TCP_RST 0x04
/*---------------------------------------------------------------------------*/
void
ip64_init(void)
{
int i;
uint8_t state;
uip_ipaddr(&ipv4_broadcast_addr, 255,255,255,255);
ip64_hostaddr_configured = 0;
PRINTF("ip64_init\n");
IP64_ETH_DRIVER.init();
#if IP64_CONF_DHCP
ip64_ipv4_dhcp_init();
#endif /* IP64_CONF_DHCP */
/* Specify an IPv6 address for local communication to the
host. We'll just pick the first one we find in our list. */
for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
state = uip_ds6_if.addr_list[i].state;
PRINTF("i %d used %d\n", i, uip_ds6_if.addr_list[i].isused);
if(uip_ds6_if.addr_list[i].isused &&
(state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) {
ip64_set_ipv6_address(&uip_ds6_if.addr_list[i].ipaddr);
break;
}
}
}
/*---------------------------------------------------------------------------*/
void
ip64_set_hostaddr(const uip_ip4addr_t *hostaddr)
{
ip64_hostaddr_configured = 1;
ip64_addr_copy4(&ip64_hostaddr, hostaddr);
}
/*---------------------------------------------------------------------------*/
void
ip64_set_netmask(const uip_ip4addr_t *netmask)
{
ip64_addr_copy4(&ip64_netmask, netmask);
}
/*---------------------------------------------------------------------------*/
void
ip64_set_draddr(const uip_ip4addr_t *draddr)
{
ip64_addr_copy4(&ip64_draddr, draddr);
}
/*---------------------------------------------------------------------------*/
const uip_ip4addr_t *
ip64_get_hostaddr(void)
{
return &ip64_hostaddr;
}
/*---------------------------------------------------------------------------*/
const uip_ip4addr_t *
ip64_get_netmask(void)
{
return &ip64_netmask;
}
/*---------------------------------------------------------------------------*/
const uip_ip4addr_t *
ip64_get_draddr(void)
{
return &ip64_draddr;
}
/*---------------------------------------------------------------------------*/
void
ip64_set_ipv4_address(const uip_ip4addr_t *addr, const uip_ip4addr_t *netmask)
{
ip64_set_hostaddr(addr);
ip64_set_netmask(netmask);
PRINTF("ip64_set_ipv4_address: configuring address %d.%d.%d.%d/%d.%d.%d.%d\n",
ip64_hostaddr.u8[0], ip64_hostaddr.u8[1],
ip64_hostaddr.u8[2], ip64_hostaddr.u8[3],
ip64_netmask.u8[0], ip64_netmask.u8[1],
ip64_netmask.u8[2], ip64_netmask.u8[3]);
}
/*---------------------------------------------------------------------------*/
void
ip64_set_ipv6_address(const uip_ip6addr_t *addr)
{
ip64_addr_copy6(&ipv6_local_address, (const uip_ip6addr_t *)addr);
ipv6_local_address_configured = 1;
#if DEBUG
PRINTF("ip64_set_ipv6_address: configuring address ");
uip_debug_ipaddr_print(addr);
PRINTF("\n");
#endif /* DEBUG */
}
/*---------------------------------------------------------------------------*/
static uint16_t
chksum(uint16_t sum, const uint8_t *data, uint16_t len)
{
uint16_t t;
const uint8_t *dataptr;
const uint8_t *last_byte;
dataptr = data;
last_byte = data + len - 1;
while(dataptr < last_byte) { /* At least two more bytes */
t = (dataptr[0] << 8) + dataptr[1];
sum += t;
if(sum < t) {
sum++; /* carry */
}
dataptr += 2;
}
if(dataptr == last_byte) {
t = (dataptr[0] << 8) + 0;
sum += t;
if(sum < t) {
sum++; /* carry */
}
}
/* Return sum in host byte order. */
return sum;
}
/*---------------------------------------------------------------------------*/
static uint16_t
ipv4_checksum(struct ipv4_hdr *hdr)
{
uint16_t sum;
sum = chksum(0, (uint8_t *)hdr, IPV4_HDRLEN);
return (sum == 0) ? 0xffff : uip_htons(sum);
}
/*---------------------------------------------------------------------------*/
static uint16_t
ipv4_transport_checksum(const uint8_t *packet, uint16_t len, uint8_t proto)
{
uint16_t transport_layer_len;
uint16_t sum;
struct ipv4_hdr *v4hdr = (struct ipv4_hdr *)packet;
transport_layer_len = len - IPV4_HDRLEN;
/* First sum pseudoheader. */
if(proto != IP_PROTO_ICMPV4) {
/* IP protocol and length fields. This addition cannot carry. */
sum = transport_layer_len + proto;
/* Sum IP source and destination addresses. */
sum = chksum(sum, (uint8_t *)&v4hdr->srcipaddr, 2 * sizeof(uip_ip4addr_t));
} else {
/* ping replies' checksums are calculated over the icmp-part only */
sum = 0;
}
/* Sum transport layer header and data. */
sum = chksum(sum, &packet[IPV4_HDRLEN], transport_layer_len);
return (sum == 0) ? 0xffff : uip_htons(sum);
}
/*---------------------------------------------------------------------------*/
static uint16_t
ipv6_transport_checksum(const uint8_t *packet, uint16_t len, uint8_t proto)
{
uint16_t transport_layer_len;
uint16_t sum;
struct ipv6_hdr *v6hdr = (struct ipv6_hdr *)packet;
transport_layer_len = len - IPV6_HDRLEN;
/* First sum pseudoheader. */
/* IP protocol and length fields. This addition cannot carry. */
sum = transport_layer_len + proto;
/* Sum IP source and destination addresses. */
sum = chksum(sum, (uint8_t *)&v6hdr->srcipaddr, sizeof(uip_ip6addr_t));
sum = chksum(sum, (uint8_t *)&v6hdr->destipaddr, sizeof(uip_ip6addr_t));
/* Sum transport layer header and data. */
sum = chksum(sum, &packet[IPV6_HDRLEN], transport_layer_len);
return (sum == 0) ? 0xffff : uip_htons(sum);
}
/*---------------------------------------------------------------------------*/
int
ip64_6to4(const uint8_t *ipv6packet, const uint16_t ipv6packet_len,
uint8_t *resultpacket)
{
struct ipv4_hdr *v4hdr;
struct ipv6_hdr *v6hdr;
struct udp_hdr *udphdr;
struct tcp_hdr *tcphdr;
struct icmpv4_hdr *icmpv4hdr;
struct icmpv6_hdr *icmpv6hdr;
uint16_t ipv6len, ipv4len;
struct ip64_addrmap_entry *m;
v6hdr = (struct ipv6_hdr *)ipv6packet;
v4hdr = (struct ipv4_hdr *)resultpacket;
if((v6hdr->len[0] << 8) + v6hdr->len[1] <= ipv6packet_len) {
ipv6len = (v6hdr->len[0] << 8) + v6hdr->len[1] + IPV6_HDRLEN;
} else {
PRINTF("ip64_6to4: packet smaller than reported in IPv6 header, dropping\n");
return 0;
}
/* We copy the data from the IPv6 packet into the IPv4 packet. We do
not modify the data in any way. */
memcpy(&resultpacket[IPV4_HDRLEN],
&ipv6packet[IPV6_HDRLEN],
ipv6len - IPV6_HDRLEN);
udphdr = (struct udp_hdr *)&resultpacket[IPV4_HDRLEN];
tcphdr = (struct tcp_hdr *)&resultpacket[IPV4_HDRLEN];
icmpv4hdr = (struct icmpv4_hdr *)&resultpacket[IPV4_HDRLEN];
icmpv6hdr = (struct icmpv6_hdr *)&ipv6packet[IPV6_HDRLEN];
/* Translate the IPv6 header into an IPv4 header. */
/* First the basics: the IPv4 version, header length, type of
service, and offset fields. Those are the same for all IPv4
packets we send, regardless of the values found in the IPv6
packet. */
v4hdr->vhl = 0x45;
v4hdr->tos = 0;
v4hdr->ipoffset[0] = v4hdr->ipoffset[1] = 0;
/* We assume that the IPv6 packet has a fixed size header with no
extension headers, and compute the length of the IPv4 packet and
place the resulting value in the IPv4 packet header. */
ipv4len = ipv6len - IPV6_HDRLEN + IPV4_HDRLEN;
v4hdr->len[0] = ipv4len >> 8;
v4hdr->len[1] = ipv4len & 0xff;
/* For simplicity, we set a unique IP id for each outgoing IPv4
packet. */
ipid++;
v4hdr->ipid[0] = ipid >> 8;
v4hdr->ipid[1] = ipid & 0xff;
/* Set the IPv4 protocol. We only support TCP, UDP, and ICMP at this
point. While the IPv4 header protocol numbers are the same as the
IPv6 next header numbers, the ICMPv4 and ICMPv6 numbers are
different so we cannot simply copy the contents of the IPv6 next
header field. */
switch(v6hdr->nxthdr) {
case IP_PROTO_TCP:
PRINTF("ip64_6to4: TCP header\n");
v4hdr->proto = IP_PROTO_TCP;
/* Compute and check the TCP checksum - since we're going to
recompute it ourselves, we must ensure that it was correct in
the first place. */
if(ipv6_transport_checksum(ipv6packet, ipv6len,
IP_PROTO_TCP) != 0xffff) {
PRINTF("Bad TCP checksum, dropping packet\n");
}
break;
case IP_PROTO_UDP:
PRINTF("ip64_6to4: UDP header\n");
v4hdr->proto = IP_PROTO_UDP;
/* Compute and check the UDP checksum - since we're going to
recompute it ourselves, we must ensure that it was correct in
the first place. */
if(ipv6_transport_checksum(ipv6packet, ipv6len,
IP_PROTO_UDP) != 0xffff) {
PRINTF("Bad UDP checksum, dropping packet\n");
}
break;
case IP_PROTO_ICMPV6:
PRINTF("ip64_6to4: ICMPv6 header\n");
v4hdr->proto = IP_PROTO_ICMPV4;
/* Translate only ECHO_REPLY messages. */
if(icmpv6hdr->type == ICMP6_ECHO_REPLY) {
icmpv4hdr->type = ICMP_ECHO_REPLY;
} else {
PRINTF("ip64_6to4: ICMPv6 mapping for type %d not implemented.\n",
icmpv6hdr->type);
return 0;
}
break;
default:
/* We did not recognize the next header, and we do not attempt to
translate something we do not understand, so we return 0 to
indicate that no successful translation could be made. */
PRINTF("ip64_6to4: Could not convert IPv6 next hop %d to an IPv4 protocol number.\n",
v6hdr->nxthdr);
return 0;
}
/* We set the IPv4 ttl value to the hoplim number from the IPv6
header. This means that information about the IPv6 topology is
transported into to the IPv4 network. */
v4hdr->ttl = v6hdr->hoplim;
/* We next convert the destination address. We make this conversion
with the ip64_addr_6to4() function. If the conversion
fails, ip64_addr_6to4() returns 0. If so, we also return 0 to
indicate failure. */
if(ip64_addr_6to4(&v6hdr->destipaddr,
&v4hdr->destipaddr) == 0) {
#if DEBUG
PRINTF("ip64_6to4: Could not convert IPv6 destination address.\n");
uip_debug_ipaddr_print(&v6hdr->destipaddr);
PRINTF("\n");
#endif /* DEBUG */
return 0;
}
/* We set the source address in the IPv4 packet to be the IPv4
address that we have been configured with through the
ip64_set_ipv4_address() function. Only let broadcasts through. */
if(!ip64_hostaddr_configured &&
!uip_ip4addr_cmp(&v4hdr->destipaddr, &ipv4_broadcast_addr)) {
PRINTF("ip64_6to4: no IPv4 address configured.\n");
return 0;
}
ip64_addr_copy4(&v4hdr->srcipaddr, &ip64_hostaddr);
/* Next we update the transport layer header. This must be updated
in two ways: the source port number is changed and the transport
layer checksum must be recomputed. The reason why we change the
source port number is so that we can remember what IPv6 address
this packet came from, in case the packet will result in a reply
from the host on the IPv4 network. If a reply would be sent, it
would be sent to the port number that we chose, and we will be
able to map this back to the IPv6 address of the original sender
of the packet.
*/
/* We check to see if we already have an existing IP address mapping
for this connection. If not, we create a new one. */
if((v4hdr->proto == IP_PROTO_UDP || v4hdr->proto == IP_PROTO_TCP)) {
if(ip64_special_ports_outgoing_is_special(uip_ntohs(udphdr->srcport))) {
uint16_t newport;
if(ip64_special_ports_translate_outgoing(uip_ntohs(udphdr->srcport),
&v6hdr->srcipaddr,
&newport)) {
udphdr->srcport = uip_htons(newport);
}
} else if(uip_ntohs(udphdr->srcport) >= EPHEMERAL_PORTRANGE) {
m = ip64_addrmap_lookup(&v6hdr->srcipaddr,
uip_ntohs(udphdr->srcport),
&v4hdr->destipaddr,
uip_ntohs(udphdr->destport),
v4hdr->proto);
if(m == NULL) {
PRINTF("Lookup failed\n");
m = ip64_addrmap_create(&v6hdr->srcipaddr,
uip_ntohs(udphdr->srcport),
&v4hdr->destipaddr,
uip_ntohs(udphdr->destport),
v4hdr->proto);
if(m == NULL) {
PRINTF("Could not create new map\n");
return 0;
} else {
PRINTF("Could create new local port %d\n", m->mapped_port);
}
} else {
PRINTF("Lookup: found local port %d (%d)\n", m->mapped_port,
uip_htons(m->mapped_port));
}
/* Update the lifetime of the address mapping. We need to be
frugal with address mapping table entries, so we assign
different lifetimes depending on the type of packet we see.
For TCP connections, we don't want to have a lot of failed
connection attmpts lingering around, so we assign mappings
with TCP SYN segments a short lifetime. If we see a RST
segment, this indicates that the connection might be dead,
and we'll assign a shorter lifetime.
For UDP packets and for non-SYN/non-RST segments, we assign
the default lifetime. */
if(v4hdr->proto == IP_PROTO_TCP) {
if((tcphdr->flags & TCP_SYN)) {
ip64_addrmap_set_lifetime(m, SYN_LIFETIME);
} else if((tcphdr->flags & TCP_RST)) {
ip64_addrmap_set_lifetime(m, RST_LIFETIME);
} else {
ip64_addrmap_set_lifetime(m, DEFAULT_LIFETIME);
}
/* Also check if we see a FIN segment. If so, we'll mark the
address mapping as being candidate for recycling. Same for
RST segments. */
if((tcphdr->flags & TCP_FIN) ||
(tcphdr->flags & TCP_RST)) {
ip64_addrmap_set_recycleble(m);
}
} else {
ip64_addrmap_set_lifetime(m, DEFAULT_LIFETIME);
/* Treat DNS requests specially: since the are one-shot, we
mark them as recyclable. */
if(udphdr->destport == UIP_HTONS(53)) {
ip64_addrmap_set_recycleble(m);
}
}
/* Set the source port of the packet to be the mapped port
number. */
udphdr->srcport = uip_htons(m->mapped_port);
}
}
/* The IPv4 header is now complete, so we can compute the IPv4
header checksum. */
v4hdr->ipchksum = 0;
v4hdr->ipchksum = ~(ipv4_checksum(v4hdr));
/* The checksum is in different places in the different protocol
headers, so we need to be sure that we update the correct
field. */
switch(v4hdr->proto) {
case IP_PROTO_TCP:
tcphdr->tcpchksum = 0;
tcphdr->tcpchksum = ~(ipv4_transport_checksum(resultpacket, ipv4len,
IP_PROTO_TCP));
break;
case IP_PROTO_UDP:
udphdr->udpchksum = 0;
udphdr->udpchksum = ~(ipv4_transport_checksum(resultpacket, ipv4len,
IP_PROTO_UDP));
if(udphdr->udpchksum == 0) {
udphdr->udpchksum = 0xffff;
}
break;
case IP_PROTO_ICMPV4:
icmpv4hdr->icmpchksum = 0;
icmpv4hdr->icmpchksum = ~(ipv4_transport_checksum(resultpacket, ipv4len,
IP_PROTO_ICMPV4));
break;
default:
PRINTF("ip64_6to4: transport protocol %d not implemented\n", v4hdr->proto);
return 0;
}
/* Finally, we return the length of the resulting IPv4 packet. */
PRINTF("ip64_6to4: ipv4len %d\n", ipv4len);
return ipv4len;
}
/*---------------------------------------------------------------------------*/
int
ip64_4to6(const uint8_t *ipv4packet, const uint16_t ipv4packet_len,
uint8_t *resultpacket)
{
struct ipv4_hdr *v4hdr;
struct ipv6_hdr *v6hdr;
struct udp_hdr *udphdr;
struct tcp_hdr *tcphdr;
struct icmpv4_hdr *icmpv4hdr;
struct icmpv6_hdr *icmpv6hdr;
uint16_t ipv4len, ipv6len, ipv6_packet_len;
struct ip64_addrmap_entry *m;
v6hdr = (struct ipv6_hdr *)resultpacket;
v4hdr = (struct ipv4_hdr *)ipv4packet;
if((v4hdr->len[0] << 8) + v4hdr->len[1] <= ipv4packet_len) {
ipv4len = (v4hdr->len[0] << 8) + v4hdr->len[1];
} else {
PRINTF("ip64_4to6: packet smaller than reported in IPv4 header, dropping\n");
return 0;
}
if(ipv4len <= IPV4_HDRLEN) {
return 0;
}
/* Make sure that the resulting packet fits in the ip64 packet
buffer. If not, we drop it. */
if(ipv4len - IPV4_HDRLEN + IPV6_HDRLEN > BUFSIZE) {
PRINTF("ip64_4to6: packet too big to fit in buffer, dropping\n");
return 0;
}
/* We copy the data from the IPv4 packet into the IPv6 packet. */
memcpy(&resultpacket[IPV6_HDRLEN],
&ipv4packet[IPV4_HDRLEN],
ipv4len - IPV4_HDRLEN);
udphdr = (struct udp_hdr *)&resultpacket[IPV6_HDRLEN];
tcphdr = (struct tcp_hdr *)&resultpacket[IPV6_HDRLEN];
icmpv4hdr = (struct icmpv4_hdr *)&ipv4packet[IPV4_HDRLEN];
icmpv6hdr = (struct icmpv6_hdr *)&resultpacket[IPV6_HDRLEN];
ipv6len = ipv4len - IPV4_HDRLEN + IPV6_HDRLEN;
ipv6_packet_len = ipv6len - IPV6_HDRLEN;
/* Translate the IPv4 header into an IPv6 header. */
/* We first fill in the simple fields: IP header version, traffic
class and flow label, and length fields. */
v6hdr->vtc = 0x60;
v6hdr->tcflow = 0;
v6hdr->flow = 0;
v6hdr->len[0] = ipv6_packet_len >> 8;
v6hdr->len[1] = ipv6_packet_len & 0xff;
/* We use the IPv4 TTL field as the IPv6 hop limit field. */
v6hdr->hoplim = v4hdr->ttl;
/* We now translate the IPv4 source and destination addresses to
IPv6 source and destination addresses. We translate the IPv4
source address into an IPv6-encoded IPv4 address. The IPv4
destination address will be the address with which we have
previously been configured, through the ip64_set_ipv4_address()
function. We use the mapping table to look up the new IPv6
destination address. As we assume that the IPv4 packet is a
response to a previously sent IPv6 packet, we should have a
mapping between the (protocol, destport, srcport, srcaddress)
tuple. If not, we'll return 0 to indicate that we failed to
translate the packet. */
if(ip64_addr_4to6(&v4hdr->srcipaddr, &v6hdr->srcipaddr) == 0) {
PRINTF("ip64_packet_4to6: failed to convert source IP address\n");
return 0;
}
/* For the next header field, we simply use the IPv4 protocol
field. We only support UDP and TCP packets. */
switch(v4hdr->proto) {
case IP_PROTO_UDP:
v6hdr->nxthdr = IP_PROTO_UDP;
break;
case IP_PROTO_TCP:
v6hdr->nxthdr = IP_PROTO_TCP;
break;
case IP_PROTO_ICMPV4:
/* Allow only ICMPv4 ECHO_REQUESTS (ping packets) through to the
local IPv6 host. */
if(icmpv4hdr->type == ICMP_ECHO) {
PRINTF("ip64_4to6: translating ICMPv4 ECHO packet\n");
v6hdr->nxthdr = IP_PROTO_ICMPV6;
icmpv6hdr->type = ICMP6_ECHO;
ip64_addr_copy6(&v6hdr->destipaddr, &ipv6_local_address);
} else {
PRINTF("ip64_packet_4to6: ICMPv4 packet type %d not supported\n",
icmpv4hdr->type);
return 0;
}
break;
default:
/* For protocol types that we do not support, we return 0 to
indicate that we failed to translate the packet to an IPv6
packet. */
PRINTF("ip64_packet_4to6: protocol type %d not supported\n",
v4hdr->proto);
return 0;
}
/* Translate IPv4 broadcasts to IPv6 all-nodes multicasts. */
if(uip_ip4addr_cmp(&v4hdr->destipaddr, &ipv4_broadcast_addr) ||
(uip_ipaddr_maskcmp(&v4hdr->destipaddr, &ip64_hostaddr,
&ip64_netmask) &&
((v4hdr->destipaddr.u16[0] & (~ip64_netmask.u16[0])) ==
(ipv4_broadcast_addr.u16[0] & (~ip64_netmask.u16[0]))) &&
((v4hdr->destipaddr.u16[1] & (~ip64_netmask.u16[1])) ==
(ipv4_broadcast_addr.u16[1] & (~ip64_netmask.u16[1]))))) {
uip_create_linklocal_allnodes_mcast(&v6hdr->destipaddr);
} else {
if(!ip64_hostaddr_configured) {
PRINTF("ip64_packet_4to6: no local IPv4 address configured, dropping incoming packet.\n");
return 0;
}
if(!uip_ip4addr_cmp(&v4hdr->destipaddr, &ip64_hostaddr)) {
PRINTF("ip64_packet_4to6: the IPv4 destination address %d.%d.%d.%d did not match our IPv4 address %d.%d.%d.%d\n",
uip_ipaddr_to_quad(&v4hdr->destipaddr),
uip_ipaddr_to_quad(&ip64_hostaddr));
return 0;
}
/* Now we translate the transport layer port numbers. We assume that
the IPv4 packet is a response to a packet that has previously
been translated from IPv6 to IPv4. If this is the case, the tuple
(protocol, destport, srcport, srcaddress) corresponds to an address/port
pair in our mapping table. If we do not find a mapping, we return
0 to indicate that we could not translate the IPv4 packet to an
IPv6 packet. */
/* XXX treat a few ports differently: those ports should be let
through to the local host. For those ports, we set up an address
mapping that ensures that the local port number is retained. */
if((v4hdr->proto == IP_PROTO_TCP || v4hdr->proto == IP_PROTO_UDP)) {
if(uip_htons(tcphdr->destport) < EPHEMERAL_PORTRANGE) {
/* This packet should go to the local host. */
PRINTF("Port is in the non-ephemeral port range %d (%d)\n",
tcphdr->destport, uip_htons(tcphdr->destport));
ip64_addr_copy6(&v6hdr->destipaddr, &ipv6_local_address);
} else if(ip64_special_ports_incoming_is_special(uip_htons(tcphdr->destport))) {
uip_ip6addr_t newip6addr;
uint16_t newport;
PRINTF("ip64 port %d (%d) is special, treating it differently\n",
tcphdr->destport, uip_htons(tcphdr->destport));
if(ip64_special_ports_translate_incoming(uip_htons(tcphdr->destport),
&newip6addr, &newport)) {
ip64_addr_copy6(&v6hdr->destipaddr, &newip6addr);
tcphdr->destport = uip_htons(newport);
PRINTF("New port %d (%d)\n",
tcphdr->destport, uip_htons(tcphdr->destport));
} else {
ip64_addr_copy6(&v6hdr->destipaddr, &ipv6_local_address);
PRINTF("No new port\n");
}
} else {
/* The TCP or UDP port numbers were not non-ephemeral and not
special, so we map the port number according to the address
mapping table. */
m = ip64_addrmap_lookup_port(uip_ntohs(udphdr->destport),
v4hdr->proto);
if(m == NULL) {
PRINTF("Inbound lookup failed\n");
return 0;
} else {
PRINTF("Inbound lookup did not fail\n");
}
ip64_addr_copy6(&v6hdr->destipaddr, &m->ip6addr);
udphdr->destport = uip_htons(m->ip6port);
}
}
}
/* The checksum is in different places in the different protocol
headers, so we need to be sure that we update the correct
field. */
switch(v6hdr->nxthdr) {
case IP_PROTO_TCP:
tcphdr->tcpchksum = 0;
tcphdr->tcpchksum = ~(ipv6_transport_checksum(resultpacket,
ipv6len,
IP_PROTO_TCP));
break;
case IP_PROTO_UDP:
udphdr->udpchksum = 0;
udphdr->udpchksum = ~(ipv6_transport_checksum(resultpacket,
ipv6len,
IP_PROTO_UDP));
if(udphdr->udpchksum == 0) {
udphdr->udpchksum = 0xffff;
}
break;
case IP_PROTO_ICMPV6:
icmpv6hdr->icmpchksum = 0;
icmpv6hdr->icmpchksum = ~(ipv6_transport_checksum(resultpacket,
ipv6len,
IP_PROTO_ICMPV6));
break;
default:
PRINTF("ip64_4to6: transport protocol %d not implemented\n", v4hdr->proto);
return 0;
}
/* Finally, we return the length of the resulting IPv6 packet. */
PRINTF("ip64_4to6: ipv6len %d\n", ipv6len);
return ipv6len;
}
/*---------------------------------------------------------------------------*/
int
ip64_hostaddr_is_configured(void)
{
return ip64_hostaddr_configured;
}
/*---------------------------------------------------------------------------*/
static void
interface_init(void)
{
IP64_CONF_UIP_FALLBACK_INTERFACE.init();
}
/*---------------------------------------------------------------------------*/
static void
interface_output(void)
{
PRINTF("ip64: interface_output len %d\n", uip_len);
IP64_CONF_UIP_FALLBACK_INTERFACE.output();
}
/*---------------------------------------------------------------------------*/
const struct uip_fallback_interface ip64_uip_fallback_interface = {
interface_init, interface_output
};

76
core/net/ip64/ip64.h Normal file
View file

@ -0,0 +1,76 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef IP64_H
#define IP64_H
#include "net/ip/uip.h"
void ip64_init(void);
int ip64_6to4(const uint8_t *ipv6packet, const uint16_t ipv6len,
uint8_t *resultpacket);
int ip64_4to6(const uint8_t *ipv4packet, const uint16_t ipv4len,
uint8_t *resultpacket);
void ip64_set_ipv4_address(const uip_ip4addr_t *ipv4addr,
const uip_ip4addr_t *netmask);
void ip64_set_ipv6_address(const uip_ip6addr_t *ipv6addr);
const uip_ip4addr_t *ip64_get_hostaddr(void);
const uip_ip4addr_t *ip64_get_netmask(void);
const uip_ip4addr_t *ip64_get_draddr(void);
void ip64_set_hostaddr(const uip_ip4addr_t *hostaddr);
void ip64_set_netmask(const uip_ip4addr_t *netmask);
void ip64_set_draddr(const uip_ip4addr_t *draddr);
int ip64_hostaddr_is_configured(void);
extern uint8_t *ip64_packet_buffer;
extern uint16_t ip64_packet_buffer_maxlen;
#include "ip64-conf.h"
#ifndef IP64_CONF_ETH_DRIVER
#error IP64_CONF_ETH_DRIVER must be #defined in ip64-conf.h
#else /* IP64_CONF_ETH_DRIVER */
#define IP64_ETH_DRIVER IP64_CONF_ETH_DRIVER
#endif /* IP64_CONF_ETH_DRIVER */
#ifndef IP64_CONF_INPUT
#error IP64_CONF_INPUT must be #defined in ip64-conf.h
#else /* IP64_CONF_INPUT */
#define IP64_INPUT IP64_CONF_INPUT
#endif /* IP64_CONF_INPUT */
#endif /* IP64_H */