NAT64 / DNS64 code for Contiki that makes connecting an IPv6 Contiki network to IPv4 networks really easy
This commit is contained in:
parent
af5dcc628a
commit
c77bc6d3f1
23 changed files with 3250 additions and 0 deletions
249
core/net/ip64/ip64-addrmap.c
Normal file
249
core/net/ip64/ip64-addrmap.c
Normal 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;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
101
core/net/ip64/ip64-addrmap.h
Normal file
101
core/net/ip64/ip64-addrmap.h
Normal 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
417
core/net/ip64/ip64-arp.c
Normal 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(ðhdr->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
84
core/net/ip64/ip64-arp.h
Normal 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 */
|
42
core/net/ip64/ip64-conf-example.h
Normal file
42
core/net/ip64/ip64-conf-example.h
Normal 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
450
core/net/ip64/ip64-dhcpc.c
Normal 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);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
62
core/net/ip64/ip64-dhcpc.h
Normal file
62
core/net/ip64/ip64-dhcpc.h
Normal 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__ */
|
40
core/net/ip64/ip64-driver.h
Normal file
40
core/net/ip64/ip64-driver.h
Normal 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 */
|
125
core/net/ip64/ip64-eth-interface.c
Normal file
125
core/net/ip64/ip64-eth-interface.c
Normal 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
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
40
core/net/ip64/ip64-eth-interface.h
Normal file
40
core/net/ip64/ip64-eth-interface.h
Normal 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
43
core/net/ip64/ip64-eth.c
Normal 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
61
core/net/ip64/ip64-eth.h
Normal 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 */
|
41
core/net/ip64/ip64-interface.h
Normal file
41
core/net/ip64/ip64-interface.h
Normal 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 */
|
95
core/net/ip64/ip64-ipv4-dhcp.c
Normal file
95
core/net/ip64/ip64-ipv4-dhcp.c
Normal 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)
|
||||
{
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
36
core/net/ip64/ip64-ipv4-dhcp.h
Normal file
36
core/net/ip64/ip64-ipv4-dhcp.h
Normal 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 */
|
49
core/net/ip64/ip64-null-driver.c
Normal file
49
core/net/ip64/ip64-null-driver.c
Normal 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
|
||||
};
|
38
core/net/ip64/ip64-null-driver.h
Normal file
38
core/net/ip64/ip64-null-driver.h
Normal 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 */
|
150
core/net/ip64/ip64-slip-interface.c
Normal file
150
core/net/ip64/ip64-slip-interface.c
Normal 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
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
38
core/net/ip64/ip64-slip-interface.h
Normal file
38
core/net/ip64/ip64-slip-interface.h
Normal 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 */
|
76
core/net/ip64/ip64-special-ports.c
Normal file
76
core/net/ip64/ip64-special-ports.c
Normal 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 */
|
64
core/net/ip64/ip64-special-ports.h
Normal file
64
core/net/ip64/ip64-special-ports.h
Normal 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
873
core/net/ip64/ip64.c
Normal 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
76
core/net/ip64/ip64.h
Normal 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 */
|
||||
|
Loading…
Reference in a new issue