From 890eb830e80cd54e68f4718a61dcd1d87ecbd29a Mon Sep 17 00:00:00 2001 From: joxe Date: Fri, 8 May 2009 12:49:36 +0000 Subject: [PATCH] ipv6 bridge between 802.15.4 and ethernet - over USB/SLIP - use with sliptap6 --- tools/sky/uip6-bridge/Makefile | 21 + tools/sky/uip6-bridge/bridge-conf.h | 56 ++ tools/sky/uip6-bridge/dev/slip.c | 392 ++++++++++ tools/sky/uip6-bridge/dev/slip.h | 93 +++ tools/sky/uip6-bridge/fakeuip.c | 108 +++ tools/sky/uip6-bridge/sicslow_ethernet.c | 881 +++++++++++++++++++++++ tools/sky/uip6-bridge/sicslow_ethernet.h | 78 ++ tools/sky/uip6-bridge/uip6-bridge-tap.c | 126 ++++ 8 files changed, 1755 insertions(+) create mode 100644 tools/sky/uip6-bridge/Makefile create mode 100644 tools/sky/uip6-bridge/bridge-conf.h create mode 100644 tools/sky/uip6-bridge/dev/slip.c create mode 100644 tools/sky/uip6-bridge/dev/slip.h create mode 100644 tools/sky/uip6-bridge/fakeuip.c create mode 100644 tools/sky/uip6-bridge/sicslow_ethernet.c create mode 100644 tools/sky/uip6-bridge/sicslow_ethernet.h create mode 100644 tools/sky/uip6-bridge/uip6-bridge-tap.c diff --git a/tools/sky/uip6-bridge/Makefile b/tools/sky/uip6-bridge/Makefile new file mode 100644 index 000000000..3ba8650c1 --- /dev/null +++ b/tools/sky/uip6-bridge/Makefile @@ -0,0 +1,21 @@ +ifdef CONTIKI_HOME +CONTIKI = $(CONTIKI_HOME) +else +ifndef CONTIKI +CONTIKI=../../../../contiki-2.x +endif +endif + +DEFINES=WITH_UIP6=1,WITH_SLIP=1,PROJECT_CONF_H=\"bridge-conf.h\" +UIP_CONF_IPV6=1 + +ifndef TARGET +TARGET=sky +endif + +PROJECTDIRS = dev +PROJECT_SOURCEFILES = fakeuip.c sicslow_ethernet.c + +all: uip6-bridge-tap.sky + +include $(CONTIKI)/Makefile.include diff --git a/tools/sky/uip6-bridge/bridge-conf.h b/tools/sky/uip6-bridge/bridge-conf.h new file mode 100644 index 000000000..5f622df99 --- /dev/null +++ b/tools/sky/uip6-bridge/bridge-conf.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2009, 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. + * + * $Id: bridge-conf.h,v 1.1 2009/05/08 12:49:36 joxe Exp $ + */ + +/** + * \file + * A brief description of what this file is + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#ifndef __BRIDGE_CONF_H__ +#define __BRIDGE_CONF_H__ + +#undef UIP_CONF_ROUTER + +#undef UIP_CONF_LLH_LEN +#define UIP_CONF_LLH_LEN 14 + +#undef XMAC_CONF_COMPOWER +#define XMAC_CONF_COMPOWER 0 +#undef XMAC_CONF_ANNOUNCEMENTS +#define XMAC_CONF_ANNOUNCEMENTS 0 + +#undef RF_CHANNEL +#define RF_CHANNEL 24 + +#endif /* __BRIDGE_CONF_H__ */ diff --git a/tools/sky/uip6-bridge/dev/slip.c b/tools/sky/uip6-bridge/dev/slip.c new file mode 100644 index 000000000..931cf50d0 --- /dev/null +++ b/tools/sky/uip6-bridge/dev/slip.c @@ -0,0 +1,392 @@ +/* -*- C -*- */ +/* + * 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: slip.c,v 1.1 2009/05/08 12:49:36 joxe Exp $ + */ + + +#include +#include +#include "dev/ds2411.h" +#include "contiki.h" + +#include "net/uip.h" +#include "net/uip-fw.h" +#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) + +#include "dev/slip.h" + +#define SLIP_END 0300 +#define SLIP_ESC 0333 +#define SLIP_ESC_END 0334 +#define SLIP_ESC_ESC 0335 + +PROCESS(slip_process, "SLIP driver"); + +uint8_t slip_active; + +#if 1 +#define SLIP_STATISTICS(statement) +#else +uint16_t slip_rubbish, slip_twopackets, slip_overflow, slip_ip_drop; +#define SLIP_STATISTICS(statement) statement +#endif + +/* Must be at least one byte larger than UIP_BUFSIZE! */ +#define RX_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN + 16) + +enum { + STATE_TWOPACKETS = 0, /* We have 2 packets and drop incoming data. */ + STATE_OK = 1, + STATE_ESC = 2, + STATE_RUBBISH = 3, +}; + +/* + * Variables begin and end manage the buffer space in a cyclic + * fashion. The first used byte is at begin and end is one byte past + * the last. I.e. [begin, end) is the actively used space. + * + * If begin != pkt_end we have a packet at [begin, pkt_end), + * furthermore, if state == STATE_TWOPACKETS we have one more packet at + * [pkt_end, end). If more bytes arrive in state STATE_TWOPACKETS + * they are discarded. + */ + +static uint8_t state = STATE_TWOPACKETS; +static uint16_t begin, end; +static uint8_t rxbuf[RX_BUFSIZE]; +static uint16_t pkt_end; /* SLIP_END tracker. */ + +static void (* input_callback)(void) = NULL; +static void (* tcpip_input_callback)(void) = NULL; +/*---------------------------------------------------------------------------*/ +void +slip_set_input_callback(void (*c)(void)) +{ + input_callback = c; +} +/*---------------------------------------------------------------------------*/ +void +slip_set_tcpip_input_callback(void (*c)(void)) +{ + tcpip_input_callback = c; +} +/*---------------------------------------------------------------------------*/ +#if WITH_UIP +uint8_t +slip_send(void) +{ + uint16_t i; + uint8_t *ptr; + uint8_t c; + + slip_arch_writeb(SLIP_END); + + ptr = &uip_buf[UIP_LLH_LEN]; + for(i = 0; i < uip_len; ++i) { + if(i == UIP_TCPIP_HLEN) { + ptr = (uint8_t *)uip_appdata; + } + c = *ptr++; + if(c == SLIP_END) { + slip_arch_writeb(SLIP_ESC); + c = SLIP_ESC_END; + } else if(c == SLIP_ESC) { + slip_arch_writeb(SLIP_ESC); + c = SLIP_ESC_ESC; + } + slip_arch_writeb(c); + } + slip_arch_writeb(SLIP_END); + + return UIP_FW_OK; +} +#endif /* WITH_UIP */ +/*---------------------------------------------------------------------------*/ +uint8_t +slip_write(const void *_ptr, int len) +{ + const uint8_t *ptr = _ptr; + uint16_t i; + uint8_t c; + + slip_arch_writeb(SLIP_END); + + for(i = 0; i < len; ++i) { + c = *ptr++; + if(c == SLIP_END) { + slip_arch_writeb(SLIP_ESC); + c = SLIP_ESC_END; + } else if(c == SLIP_ESC) { + slip_arch_writeb(SLIP_ESC); + c = SLIP_ESC_ESC; + } + slip_arch_writeb(c); + } + slip_arch_writeb(SLIP_END); + + return len; +} +/*---------------------------------------------------------------------------*/ +static void +rxbuf_init(void) +{ + begin = end = pkt_end = 0; + state = STATE_OK; +} +/*---------------------------------------------------------------------------*/ +/* Upper half does the polling. */ +static uint16_t +slip_poll_handler(uint8_t *outbuf, uint16_t blen) +{ + /* This is a hack and won't work across buffer edge! */ + if(rxbuf[begin] == 'C') { + int i; + if(begin < end && (end - begin) >= 6 + && memcmp(&rxbuf[begin], "CLIENT", 6) == 0) { + state = STATE_TWOPACKETS; /* Interrupts do nothing. */ + memset(&rxbuf[begin], 0x0, 6); + + rxbuf_init(); + + for(i = 0; i < 13; i++) { + slip_arch_writeb("CLIENTSERVER\300"[i]); + } + return 0; + } + } else if(rxbuf[begin] == '?') { + int i, j; + char* hexchar = "0123456789abcdef"; + if(begin < end && (end - begin) >= 2 + && rxbuf[begin + 1] == 'M') { + state = STATE_TWOPACKETS; /* Interrupts do nothing. */ + rxbuf[begin] = 0; + rxbuf[begin + 1] = 0; + + rxbuf_init(); + + /* this is just a test so far... just to see if it works */ + slip_arch_writeb('!'); + slip_arch_writeb('M'); + for(j = 0; j < 8; j++) { + slip_arch_writeb(hexchar[ds2411_id[j] >> 4]); + slip_arch_writeb(hexchar[ds2411_id[j] & 15]); + } + slip_arch_writeb(SLIP_END); + return 0; + } + } + + /* + * Interrupt can not change begin but may change pkt_end. + * If pkt_end != begin it will not change again. + */ + if(begin != pkt_end) { + uint16_t len; + + if(begin < pkt_end) { + len = pkt_end - begin; + if(len > blen) { + len = 0; + } else { + memcpy(outbuf, &rxbuf[begin], len); + } + } else { + len = (RX_BUFSIZE - begin) + (pkt_end - 0); + if(len > blen) { + len = 0; + } else { + unsigned i; + for(i = begin; i < RX_BUFSIZE; i++) { + *outbuf++ = rxbuf[i]; + } + for(i = 0; i < pkt_end; i++) { + *outbuf++ = rxbuf[i]; + } + } + } + + /* Remove data from buffer together with the copied packet. */ + begin = pkt_end; + if(state == STATE_TWOPACKETS) { + pkt_end = end; + state = STATE_OK; /* Assume no bytes where lost! */ + + /* One more packet is buffered, need to be polled again! */ + process_poll(&slip_process); + } + return len; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(slip_process, ev, data) +{ + PROCESS_BEGIN(); + + rxbuf_init(); + + while(1) { + PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL); + + slip_active = 1; + + /* Move packet from rxbuf to buffer provided by uIP. */ + uip_len = slip_poll_handler(&uip_buf[UIP_LLH_LEN], + UIP_BUFSIZE - UIP_LLH_LEN); +#if !UIP_CONF_IPV6 + if(uip_len == 4 && strncmp((char*)&uip_buf[UIP_LLH_LEN], "?IPA", 4) == 0) { + char buf[8]; + memcpy(&buf[0], "=IPA", 4); + memcpy(&buf[4], &uip_hostaddr, 4); + if(input_callback) { + input_callback(); + } + slip_write(buf, 8); + } else if(uip_len > 0 + && uip_len == (((uint16_t)(BUF->len[0]) << 8) + BUF->len[1]) + && uip_ipchksum() == 0xffff) { +#define IP_DF 0x40 + if(BUF->ipid[0] == 0 && BUF->ipid[1] == 0 && BUF->ipoffset[0] & IP_DF) { + static uint16_t ip_id; + uint16_t nid = ip_id++; + BUF->ipid[0] = nid >> 8; + BUF->ipid[1] = nid; + nid = htons(nid); + nid = ~nid; /* negate */ + BUF->ipchksum += nid; /* add */ + if(BUF->ipchksum < nid) { /* 1-complement overflow? */ + BUF->ipchksum++; + } + } + if(tcpip_input_callback) { + tcpip_input_callback(); + } else { + tcpip_input(); + } + } else { + uip_len = 0; + SLIP_STATISTICS(slip_ip_drop++); + } +#else /* UIP_CONF_IPV6 */ + if(uip_len > 0) { + if(tcpip_input_callback) { + tcpip_input_callback(); + } else { + tcpip_input(); + } + } +#endif /* UIP_CONF_IPV6 */ + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +int +slip_input_byte(unsigned char c) +{ + switch(state) { + case STATE_RUBBISH: + if(c == SLIP_END) { + state = STATE_OK; + } + return 0; + + case STATE_TWOPACKETS: /* Two packets are already buffered! */ + return 0; + + case STATE_ESC: + if(c == SLIP_ESC_END) { + c = SLIP_END; + } else if(c == SLIP_ESC_ESC) { + c = SLIP_ESC; + } else { + state = STATE_RUBBISH; + SLIP_STATISTICS(slip_rubbish++); + end = pkt_end; /* remove rubbish */ + return 0; + } + state = STATE_OK; + break; + + case STATE_OK: + if(c == SLIP_ESC) { + state = STATE_ESC; + return 0; + } else if(c == SLIP_END) { + /* + * We have a new packet, possibly of zero length. + * + * There may already be one packet buffered. + */ + if(end != pkt_end) { /* Non zero length. */ + if(begin == pkt_end) { /* None buffered. */ + pkt_end = end; + } else { + state = STATE_TWOPACKETS; + SLIP_STATISTICS(slip_twopackets++); + } + process_poll(&slip_process); + return 1; + } + return 0; + } + break; + } + + /* add_char: */ + { + unsigned next; + next = end + 1; + if(next == RX_BUFSIZE) { + next = 0; + } + if(next == begin) { /* rxbuf is full */ + state = STATE_RUBBISH; + SLIP_STATISTICS(slip_overflow++); + end = pkt_end; /* remove rubbish */ + return 0; + } + rxbuf[end] = c; + end = next; + } + + /* There could be a separate poll routine for this. */ + if(c == 'T' && rxbuf[begin] == 'C') { + process_poll(&slip_process); + return 1; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ diff --git a/tools/sky/uip6-bridge/dev/slip.h b/tools/sky/uip6-bridge/dev/slip.h new file mode 100644 index 000000000..16beadd32 --- /dev/null +++ b/tools/sky/uip6-bridge/dev/slip.h @@ -0,0 +1,93 @@ +/* -*- C -*- */ +/* + * 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: slip.h,v 1.1 2009/05/08 12:49:36 joxe Exp $ + */ + +#ifndef __SLIP_H__ +#define __SLIP_H__ + +#include "contiki.h" + +PROCESS_NAME(slip_process); + +/** + * Send an IP packet from the uIP buffer with SLIP. + */ +uint8_t slip_send(void); + +/** + * Input a SLIP byte. + * + * This function is called by the RS232/SIO device driver to pass + * incoming bytes to the SLIP driver. The function can be called from + * an interrupt context. + * + * For systems using low-power CPU modes, the return value of the + * function can be used to determine if the CPU should be woken up or + * not. If the function returns non-zero, the CPU should be powered + * up. If the function returns zero, the CPU can continue to be + * powered down. + * + * \param c The data that is to be passed to the SLIP driver + * + * \return Non-zero if the CPU should be powered up, zero otherwise. + */ +int slip_input_byte(unsigned char c); + +uint8_t slip_write(const void *ptr, int len); + +/* Did we receive any bytes lately? */ +extern uint8_t slip_active; + +/* Statistics. */ +extern uint16_t slip_rubbish, slip_twopackets, slip_overflow, slip_ip_drop; + +/** + * Set a function to be called when there is activity on the SLIP + * interface; used for detecting if a node is a gateway node. + */ +void slip_set_input_callback(void (*callback)(void)); + +/** + * Set a function to be called when a packet has been received. + * Default is tcpip_input(). + */ +void slip_set_tcpip_input_callback(void (*callback)(void)); + +/* + * These machine dependent functions and an interrupt service routine + * must be provided externally (slip_arch.c). + */ +void slip_arch_init(unsigned long ubr); +void slip_arch_writeb(unsigned char c); + +#endif /* __SLIP_H__ */ diff --git a/tools/sky/uip6-bridge/fakeuip.c b/tools/sky/uip6-bridge/fakeuip.c new file mode 100644 index 000000000..57a9c54f6 --- /dev/null +++ b/tools/sky/uip6-bridge/fakeuip.c @@ -0,0 +1,108 @@ + +/* Various stub functions and uIP variables other code might need to + * compile. Allows you to save needing to compile all of uIP in just + * to get a few things */ + + +#include "net/uip.h" +#include + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) + +u8_t uip_buf[UIP_BUFSIZE + 2]; + +u16_t uip_len; + +struct uip_stats uip_stat; + +uip_lladdr_t uip_lladdr; + +u16_t htons(u16_t val) { return HTONS(val);} + + +/********** UIP_NETIF.c **********/ + +void +uip_netif_addr_autoconf_set(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr) +{ + /* We consider only links with IEEE EUI-64 identifier or + IEEE 48-bit MAC addresses */ +#if (UIP_LLADDR_LEN == 8) + memcpy(ipaddr->u8 + 8, lladdr, UIP_LLADDR_LEN); + ipaddr->u8[8] ^= 0x02; +#elif (UIP_LLADDR_LEN == 6) + memcpy(ipaddr->u8 + 8, lladdr, 3); + ipaddr->u8[11] = 0xff; + ipaddr->u8[12] = 0xfe; + memcpy(ipaddr->u8 + 13, lladdr + 3, 3); + ipaddr->u8[8] ^= 0x02; +#else + /* + UIP_LOG("CAN NOT BUIL INTERFACE IDENTIFIER"); + UIP_LOG("THE STACK IS GOING TO SHUT DOWN"); + UIP_LOG("THE HOST WILL BE UNREACHABLE"); + */ + exit(-1); +#endif +} + +/********** UIP.c ****************/ + +static u16_t +chksum(u16_t sum, const u8_t *data, u16_t len) +{ + u16_t t; + const u8_t *dataptr; + const u8_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 u16_t +upper_layer_chksum(u8_t proto) +{ + u16_t upper_layer_len; + u16_t sum; + + upper_layer_len = (((u16_t)(UIP_IP_BUF->len[0]) << 8) + UIP_IP_BUF->len[1]) ; + + /* First sum pseudoheader. */ + /* IP protocol and length fields. This addition cannot carry. */ + sum = upper_layer_len + proto; + /* Sum IP source and destination addresses. */ + sum = chksum(sum, (u8_t *)&UIP_IP_BUF->srcipaddr, 2 * sizeof(uip_ipaddr_t)); + + /* Sum TCP header and data. */ + sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], + upper_layer_len); + + return (sum == 0) ? 0xffff : htons(sum); +} + +/*---------------------------------------------------------------------------*/ +u16_t +uip_icmp6chksum(void) +{ + return upper_layer_chksum(UIP_PROTO_ICMP6); +} diff --git a/tools/sky/uip6-bridge/sicslow_ethernet.c b/tools/sky/uip6-bridge/sicslow_ethernet.c new file mode 100644 index 000000000..15ffbd63b --- /dev/null +++ b/tools/sky/uip6-bridge/sicslow_ethernet.c @@ -0,0 +1,881 @@ +/** + * \file sicslow_ethernet.c + * Routines to interface between Ethernet and 6LowPan + * + * \author + * Colin O'Flynn + * + * \addtogroup usbstick + */ + +/* Copyright (c) 2008 by: + * Colin O'Flynn coflynn@newae.com + * Eric Gnoske egnoske@gmail.com + * Blake Leverett bleverett@gmail.com + * Mike Vidales mavida404@gmail.com + * Kevin Brown kbrown3@uccs.edu + * Nate Bohlmann nate@elfwerks.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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the copyright holders nor the names of + * 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 OWNER 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. + */ + +/** + \ingroup usbstick + \defgroup sicslowinterop 6LowPan Ethernet Interop + @{ +*/ + + +/** + \par Ethernet to 6LowPan Address Translation + + It should be obvious that since 802.15.4 addresses are 8 + bytes, and 802.3 addresses are 6 bytes, some form of + address translation is needed. These routines provide this + + \par 802.3 Address Formats + + 802.3 MAC addresses used here have this form: + + \verbatim + +----+----+----+----+----+----+----+----+ + + + + + + + TR + GL + MU + + +----+----+----+----+----+----+----+----+ + \endverbatim + + + It can be seen this is like a normal ethernet MAC address, + with GL being the Global/Local bit, and MU being the + Multicast/Unicast bit. + + The addition is the 'TR' bit, which if set indicates that + the address must be translated when going between 802.15.4 + and 802.3. + + \par Address Translation + + If the TRANSLATE (TR) bit is CLEAR, this means the 5th and + 4th LSBytes of the 802.15.4 address are fffe, aka the address + has the hexidecial form: + + xxxxxxfffexxxxxx + + \note + You should always aim to set the 802.15.4 addresses + of the devices on your network to ones that will + satisfy this requirement. Some examples are: + \note + 0x02 23 42 ff fe 73 92 28 + \note + 0x82 00 82 ff fe cd ee 22 + + \note + So the most significant octets MUST + have bit 0 CLEAR, bit 1 SET, and bit 2 CLEAR. The remaining + bits in this octet can be anything. + + If the TRANSLATE bit is SET, this means the address on the + 802.3 side does not directly convert to an 802.15.4 address. + To translate it, the remainder of the octet is used as an + index in a look-up table. This look-up table simply stores + the 4th, 5th, and 8th octet of the 802.15.4 address, and attaches + them to the remaining 5 bytes of the 802.3 address. + + In this way there can be 32 different 802.15.4 'prefixes', + requiring only 96 bytes of RAM in a storage table on the + 802.3 to 802.15.4 bridge. + + Mulitcast addresses on 802.3 are mapped to broadcast addresses on + 802.15.4 and vis-versa. Since IPv6 does not use 802.3 broadcast, + this code will drop all 802.3 broadcast packets. They are most + likely something unwanted, such as IPv4 packets that snuck in. + + \par Notes on how addresses are stored + + An 802.15.4 address will be reported for example as: + + 0x8877665544332211 + + Stored in the array as passed to these functions, it will be: + \verbatim + array[0] = 0x88; + array[1] = 0x77; + array[2] = 0x66; + etc. + \endverbatim + + An 802.3 address will be reported for example as: + 02:43:53:35:45:45 + + Stored in the array as passed to these functions, it will be: + \verbatim + array[0] = 0x02; + array[1] = 0x43; + array[2] = 0x53; + array[3] = 0x35 + etc. + \endverbatim +*/ + +#include "uip.h" +#include "uip_arp.h" /* For ethernet header structure */ +#include "net/rime.h" +#include "net/sicslowpan.h" +#include "sicslow_ethernet.h" + +#include +#include +#include + +//#define PRINTF printf +#define PRINTF(...) + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define ETHBUF(x) ((struct uip_eth_hdr *)x) + +//For little endian, such as our friend mr. AVR +#ifndef LSB +#define LSB(u16) (((uint8_t *)&(u16))[0]) //!< Least significant byte of \a u16. +#define MSB(u16) (((uint8_t *)&(u16))[1]) //!< Most significant byte of \a u16. +#endif + +usbstick_mode_t usbstick_mode; + +uint8_t mac_createSicslowpanLongAddr(uint8_t * ethernet, uip_lladdr_t * lowpan); +uint8_t mac_createEthernetAddr(uint8_t * ethernet, uip_lladdr_t * lowpan); +/* uint8_t memcmp_reverse(uint8_t * a, uint8_t * b, uint8_t num); */ +/* void mac_ethhijack_nondata(const struct mac_driver *r); */ +/* void mac_ethhijack(const struct mac_driver *r); */ + +/* extern void (*sicslowmac_snifferhook)(const struct mac_driver *r); */ + + +//! Location of TRANSLATE (TR) bit in Ethernet address +#define TRANSLATE_BIT_MASK (1<<2) +//! Location of LOCAL (GL) bit in Ethernet address +#define LOCAL_BIT_MASK (1<<1) +//! Location of MULTICAST (MU) bit in Ethernet address +#define MULTICAST_BIT_MASK (1<<0) + +#define PREFIX_BUFFER_SIZE 32 + +uint8_t prefixCounter; +uint8_t prefixBuffer[PREFIX_BUFFER_SIZE][3]; + +/* 6lowpan max size + ethernet header size + 1 */ +uint8_t raw_buf[127+ UIP_LLH_LEN +1]; + + +/* void tcpip_input( void ) */ +/* { */ +/* mac_LowpanToEthernet(); */ +/* } */ + +/** + * \brief Perform any setup needed + */ +/* struct mac_driver * pmac; */ +void mac_ethernetSetup(void) +{ + usbstick_mode.sicslowpan = 1; + usbstick_mode.sendToRf = 1; + usbstick_mode.translate = 1; + usbstick_mode.raw = 1; + +/* sicslowinput = pinput; */ + + +/* pmac = sicslowmac_get_driver(); */ +/* pmac->set_receive_function(mac_ethhijack); */ +/* sicslowmac_snifferhook = mac_ethhijack_nondata; */ +} + + +/** + * \brief Take a packet received over the ethernet link, and send it + * out over 802.15.4 + */ +void mac_ethernetToLowpan(uint8_t * ethHeader) +{ + //Dest address + uip_lladdr_t destAddr; + uip_lladdr_t *destAddrPtr = NULL; + + PRINTF("Packet type: %x\n", ((struct uip_eth_hdr *) ethHeader)->type); + + //RUM doesn't support sending data + #if UIP_CONF_USE_RUM + return; + #endif + + //If not IPv6 we don't do anything + if (((struct uip_eth_hdr *) ethHeader)->type != HTONS(UIP_ETHTYPE_IPV6)) { + PRINTF("eth2low: Packet is not IPv6, dropping\n"); +/* rndis_stat.txbad++; */ + uip_len = 0; + return; + } + + // In sniffer mode we don't ever send anything + if (usbstick_mode.sendToRf == 0) { + uip_len = 0; + return; + } + + /* IPv6 uses 33-33-xx-xx-xx-xx prefix for multicast ND stuff */ + if ( (((struct uip_eth_hdr *) ethHeader)->dest.addr[0] == 0x33) && + (((struct uip_eth_hdr *) ethHeader)->dest.addr[1] == 0x33) ) + { + PRINTF("eth2low: Ethernet multicast packet received\n"); + ;//Do Nothing + } else if ( (((struct uip_eth_hdr *) ethHeader)->dest.addr[0] == 0xFF) && + (((struct uip_eth_hdr *) ethHeader)->dest.addr[1] == 0xFF) && + (((struct uip_eth_hdr *) ethHeader)->dest.addr[2] == 0xFF) && + (((struct uip_eth_hdr *) ethHeader)->dest.addr[3] == 0xFF) && + (((struct uip_eth_hdr *) ethHeader)->dest.addr[4] == 0xFF) && + (((struct uip_eth_hdr *) ethHeader)->dest.addr[5] == 0xFF) ) { + /* IPv6 does not use broadcast addresses, hence this should not happen */ + PRINTF("eth2low: Ethernet broadcast address received, should not happen?\n"); +/* rndis_stat.txbad++; */ + uip_len = 0; + return; + } else { + PRINTF("eth2low: Addressed packet received... "); + //Check this returns OK + if (mac_createSicslowpanLongAddr( &(((struct uip_eth_hdr *) ethHeader)->dest.addr[0]), &destAddr) == 0) { + PRINTF(" translation failed\n"); +/* rndis_stat.txbad++; */ + uip_len = 0; + return; + } + PRINTF(" translated OK\n"); + destAddrPtr = &destAddr; + } + + //Remove header from length before passing onward + uip_len -= UIP_LLH_LEN; + + //Some IP packets have link layer in them, need to change them around! + if (usbstick_mode.translate) { +/* uint8_t transReturn = */ + mac_translateIPLinkLayer(ll_802154_type); + PRINTF("IPTranslation: returns %d\n", transReturn); + } + + if (usbstick_mode.sendToRf){ + tcpip_output(destAddrPtr); +/* rndis_stat.txok++; */ + } + + uip_len = 0; + +} + + +/** + * \brief Take a packet received over the 802.15.4 link, and send it + * out over ethernet, performing any translations needed. + */ +void mac_LowpanToEthernet(void) +{ +/* parsed_frame = sicslowmac_get_frame(); */ + + //Setup generic ethernet stuff + ETHBUF(uip_buf)->type = htons(UIP_ETHTYPE_IPV6); + + //Check for broadcast message + if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) { +/* if( ( parsed_frame->fcf->destAddrMode == SHORTADDRMODE) && */ +/* ( parsed_frame->dest_addr->addr16 == 0xffff) ) { */ + ETHBUF(uip_buf)->dest.addr[0] = 0x33; + ETHBUF(uip_buf)->dest.addr[1] = 0x33; + ETHBUF(uip_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12]; + ETHBUF(uip_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13]; + ETHBUF(uip_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14]; + ETHBUF(uip_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15]; + } else { + //Otherwise we have a real address + mac_createEthernetAddr((uint8_t *) &(ETHBUF(uip_buf)->dest.addr[0]), + (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); + } + + + mac_createEthernetAddr((uint8_t *) &(ETHBUF(uip_buf)->src.addr[0]), + (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); + + //We only do address translation in network mode! + if (usbstick_mode.translate) { + //Some IP packets have link layer in them, need to change them around! + mac_translateIPLinkLayer(ll_8023_type); + } + + PRINTF("Low2Eth: Sending packet to ethernet\n"); + + uip_len += UIP_LLH_LEN; + +/* rndis_send(uip_buf, uip_len, 1); */ +/* rndis_stat.rxok++; */ +/* uip_len = 0; */ +} + +/** + * \brief Translate IP packet's possible link-layer addresses, passing + * the message to the appropriate higher level function for this + * packet (aka: ICMP) + * \param target The target we want to end up with - either ll_8023_type + * for ethernet, or ll_802154_type for 802.15.4 + * \return Returns how successful the translation was + * \retval 0 Addresses, if present, were translated. + * \retval <0 Negative return values indicate various errors, as defined + * by the higher level function. + */ +int8_t mac_translateIPLinkLayer(lltype_t target) +{ + +#if UIP_LLADDR_LEN == 8 + if (UIP_IP_BUF->proto == UIP_PROTO_ICMP6) { + PRINTF("eth2low: ICMP Message detected\n"); + return mac_translateIcmpLinkLayer(target); + } + return 0; +#else + return 1; +#endif + +} + +#include "net/uip-icmp6.h" +#include "net/uip-nd6.h" + +typedef struct { + uint8_t type; + uint8_t length; + uint8_t data[16]; +} icmp_opts_t; + +#define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN]) +#define UIP_ICMP_OPTS(x) ((icmp_opts_t *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN + x]) + +void slide(uint8_t * data, uint8_t length, int16_t slide); + +/** + * \brief Translate the link-layer (L2) addresses in an ICMP packet. + * This will just be NA/NS/RA/RS packets currently. + * \param target The target we want to end up with - either ll_8023_type + * for ethernet, or ll_802154_type for 802.15.4 + * \return Returns how successful the translation was + * \retval 0 Addresses, if present, were translated. + * \retval -1 ICMP message was unknown type, nothing done. + * \retval -2 ICMP Length does not make sense? + * \retval -3 Unknown 'target' type + */ +int8_t mac_translateIcmpLinkLayer(lltype_t target) +{ + uint16_t icmp_opt_offset = 0; + int16_t len = UIP_IP_BUF->len[1] | (UIP_IP_BUF->len[0] << 8); + + uint16_t iplen; + + uint8_t i; + + int16_t sizechange; + + uint8_t llbuf[16]; + + //Figure out offset to start of options + switch(UIP_ICMP_BUF->type) { + case ICMP6_NS: + case ICMP6_NA: + icmp_opt_offset = 24; + break; + + case ICMP6_RS: + icmp_opt_offset = 8; + break; + + case ICMP6_RA: + icmp_opt_offset = 16; + break; + + case ICMP6_REDIRECT: + icmp_opt_offset = 40; + break; + + /** Things without link-layer */ + case ICMP6_DST_UNREACH: + case ICMP6_PACKET_TOO_BIG: + case ICMP6_TIME_EXCEEDED: + case ICMP6_PARAM_PROB: + case ICMP6_ECHO_REQUEST: + case ICMP6_ECHO_REPLY: + return 0; + break; + + default: + return -1; + } + + //Figure out length of options + len -= icmp_opt_offset; + + //Sanity check + if (len < 8) return -2; + + //While we have options to do... + while (len >= 8){ + + //If we have one of these, we have something useful! + if (((UIP_ICMP_OPTS(icmp_opt_offset)->type) == UIP_ND6_OPT_SLLAO) || + ((UIP_ICMP_OPTS(icmp_opt_offset)->type) == UIP_ND6_OPT_TLLAO) ) { + + /* Shrinking the buffer may thrash things, so we store the old + link-layer address */ + for(i = 0; i < (UIP_ICMP_OPTS(icmp_opt_offset)->length*8 - 2); i++) { + llbuf[i] = UIP_ICMP_OPTS(icmp_opt_offset)->data[i]; + } + + //Shrink/grow buffer as needed + if (target == ll_802154_type) { + //Current is 802.3, Hence current link-layer option is 6 extra bytes + sizechange = 8; + slide(UIP_ICMP_OPTS(icmp_opt_offset)->data + 6, len - 6, sizechange); + } else if (target == ll_8023_type) { + /* Current is 802.15.4, Hence current link-layer option is 14 extra + * bytes. + * (Actual LL is 8 bytes, but total option length is in multiples of + * 8 Bytes, hence 8 + 2 = 10. Closest is 16 bytes, then 16 bytes for + * total optional length - 2 bytes for type + length leaves 14 ) + */ + sizechange = -8; + slide(UIP_ICMP_OPTS(icmp_opt_offset)->data + 14, len - 14, sizechange); + } else { + return -3; //Uh-oh! + } + + //Translate addresses + if (target == ll_802154_type) { + mac_createSicslowpanLongAddr(llbuf, (uip_lladdr_t *)UIP_ICMP_OPTS(icmp_opt_offset)->data); + } else { + mac_createEthernetAddr(UIP_ICMP_OPTS(icmp_opt_offset)->data, (uip_lladdr_t *)llbuf); + } + + //Adjust the length + if (target == ll_802154_type) { + UIP_ICMP_OPTS(icmp_opt_offset)->length = 2; + } else { + UIP_ICMP_OPTS(icmp_opt_offset)->length = 1; + } + + //Adjust the IP header length, as well as uIP length + iplen = UIP_IP_BUF->len[1] | (UIP_IP_BUF->len[0]<<8); + iplen += sizechange; + len += sizechange; + + UIP_IP_BUF->len[1] = (uint8_t)iplen; + UIP_IP_BUF->len[0] = (uint8_t)(iplen >> 8); + + uip_len += sizechange; + + //We broke ICMP checksum, be sure to fix that + UIP_ICMP_BUF->icmpchksum = 0; + UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); + + //Finally set up next run in while loop + len -= 8 * UIP_ICMP_OPTS(icmp_opt_offset)->length; + icmp_opt_offset += 8 * UIP_ICMP_OPTS(icmp_opt_offset)->length; + } else { + + //Not an option we care about, ignore it + len -= 8 * UIP_ICMP_OPTS(icmp_opt_offset)->length; + + //This shouldn't happen! + if (UIP_ICMP_OPTS(icmp_opt_offset)->length == 0) { + PRINTF("Option in ND packet has length zero, error?\n"); + len = 0; + } + + icmp_opt_offset += 8 * UIP_ICMP_OPTS(icmp_opt_offset)->length; + + } //If ICMP_OPT is one we care about + + } //while(len >= 8) + + return 0; + +} + + +/** + * \brief Create a 802.15.4 long address from a 802.3 address + * \param ethernet Pointer to ethernet address + * \param lowpan Pointer to 802.15.4 address + */ +uint8_t mac_createSicslowpanLongAddr(uint8_t * ethernet, uip_lladdr_t * lowpan) +{ + uint8_t index; + +#if UIP_LLADDR_LEN == 8 + //Special case - if the address is our address, we just copy over what we know to be + //our 802.15.4 address + +/* if (memcmp_reverse((uint8_t *)&rndis_ethernet_addr, ethernet, 6) == 0) { */ + if (memcmp((uint8_t *)&uip_lladdr.addr[2], ethernet, 6) == 0) { + memcpy((uint8_t *)lowpan, uip_lladdr.addr, 8); +/* byte_reverse((uint8_t *)lowpan, 8); */ + + return 1; + } + + //Check if translate bit is set, hence we have to look up the prefix + if (ethernet[0] & TRANSLATE_BIT_MASK) { + + //Get top bits + index = ethernet[0] >> 3; + + //Check this is plausible... + if (index >= prefixCounter) { + return 0; + } + + //Copy over prefix + lowpan->addr[0] = prefixBuffer[index][0]; + lowpan->addr[3] = prefixBuffer[index][1]; + lowpan->addr[4] = prefixBuffer[index][2]; + + //Bit is clear + //so we copy all six + } else { + lowpan->addr[0] = ethernet[0]; + lowpan->addr[3] = 0xff; + lowpan->addr[4] = 0xfe; + } + + //Copy over reamining five bytes + lowpan->addr[1] = ethernet[1]; + lowpan->addr[2] = ethernet[2]; + lowpan->addr[5] = ethernet[3]; + lowpan->addr[6] = ethernet[4]; + lowpan->addr[7] = ethernet[5]; + +#else + uint8_t i; + + for(i = 0; i < UIP_LLADDR_LEN; i++) { + lowpan->addr[i] = ethernet[i]; + } +#endif + + return 1; +} + + +/** + * \brief Create a 802.3 address from a 802.15.4 long address + * \param ethernet Pointer to ethernet address + * \param lowpan Pointer to 802.15.4 address + */ +uint8_t mac_createEthernetAddr(uint8_t * ethernet, uip_lladdr_t * lowpan) +{ + uint8_t index = 0; + uint8_t i; +/* uint8_t j, match; */ + +#if UIP_LLADDR_LEN == 8 + + //Special case - if the address is our address, we just copy over what we know to be + //our 802.3 address +/* if (memcmp_reverse(uip_lladdr.addr, (uint8_t *)lowpan, 8) == 0) { */ + if (memcmp(uip_lladdr.addr, (uint8_t *)lowpan, 8) == 0) { + memcpy(ethernet, &uip_lladdr.addr[2], 6); +/* byte_reverse(ethernet, 6); */ + + return 1; + } + + + //Check if we need to do anything: + if ((lowpan->addr[3] == 0xff) && (lowpan->addr[4] == 0xfe) && + ((lowpan->addr[0] & TRANSLATE_BIT_MASK) == 0) && + ((lowpan->addr[0] & MULTICAST_BIT_MASK) == 0) && + (lowpan->addr[0] & LOCAL_BIT_MASK)) { + + /** Nope: just copy over 6 bytes **/ + ethernet[0] = lowpan->addr[0]; + ethernet[1] = lowpan->addr[1]; + ethernet[2] = lowpan->addr[2]; + ethernet[3] = lowpan->addr[5]; + ethernet[4] = lowpan->addr[6]; + ethernet[5] = lowpan->addr[7]; + + + } else { + + /** Yes: need to store prefix **/ + for (i = 0; i < prefixCounter; i++) { + //Check the current prefix - if it fails, check next one + + + if ((lowpan->addr[0] == prefixBuffer[i][0]) && + (lowpan->addr[3] == prefixBuffer[i][1]) && + (lowpan->addr[4] == prefixBuffer[i][2])) { + break; + } + + } + + index = i; + + //Deal with overflow, iron-fist style + if (index >= PREFIX_BUFFER_SIZE) { + index = 0; + prefixCounter = PREFIX_BUFFER_SIZE; + } else { + //Are we making a new one? + if (index == prefixCounter) { + prefixCounter++; + } + } + + //Copy the prefix over, no matter if we have a new or old one + prefixBuffer[index][0] = lowpan->addr[0]; + prefixBuffer[index][1] = lowpan->addr[3]; + prefixBuffer[index][2] = lowpan->addr[4]; + + //Create ethernet MAC address now + ethernet[1] = lowpan->addr[1]; + ethernet[2] = lowpan->addr[2]; + ethernet[3] = lowpan->addr[5]; + ethernet[4] = lowpan->addr[6]; + ethernet[5] = lowpan->addr[7]; + + + ethernet[0] = TRANSLATE_BIT_MASK | LOCAL_BIT_MASK | (index << 3); + } + +#else + + //Create ethernet MAC address now + for(i = 0; i < UIP_LLADDR_LEN; i++) { + ethernet[i] = lowpan->addr[i]; + } +#endif + + return 1; +} + + +/** + * \brief Slide the pointed to memory up a certain amount, + * growing/shrinking a buffer + * \param data Pointer to start of data buffer + * \param length Length of the data buffer + * \param slide How many bytes to slide the buffer up in memory (if +) or + * down in memory (if -) + */ +void slide(uint8_t * data, uint8_t length, int16_t slide) +{ + //Sanity checks + if (!length) return; + if (!slide) return; + + uint8_t i = 0; + + while(length) { + length--; + + //If we are sliding up, we do from the top of the buffer down + if (slide > 0) { + *(data + length + slide) = *(data + length); + + //If we are sliding down, we do from the bottom of the buffer up + } else { + *(data + slide + i) = *(data + i); + } + + i++; + } +} + +/*--------------------------------------------------------------------*/ +/** \brief Process a received 6lowpan packet. Hijack function. + * \param r The MAC layer + * + * The 6lowpan packet is put in packetbuf by the MAC. This routine calls + * any other needed layers (either 6lowpan, or just raw ethernet dump) + */ +#if 0 +void mac_ethhijack(const struct mac_driver *r) +{ + if (usbstick_mode.raw) { + mac_802154raw(r); + } + + if (usbstick_mode.sicslowpan) { + +#if UIP_CONF_USE_RUM + if (parsed_frame->payload[4]) { /* RUM 6lowpan frame type */ +#endif + sicslowinput(r); +#if UIP_CONF_USE_RUM + } +#endif + + + } + +} +#endif + +#if 0 +void mac_ethhijack_nondata(const struct mac_driver *r) +{ + if (usbstick_mode.raw) + mac_802154raw(r); +} +#endif + +/*--------------------------------------------------------------------*/ +/*--------------------------------------------------------------------*/ +/** \brief Logs a sent 6lowpan frame + * + * This routine passes a frame + * directly to the ethernet layer without decompressing. + */ +#if 0 +void mac_logTXtoEthernet(frame_create_params_t *p,frame_result_t *frame_result) +{ + uint8_t sendlen; + + /* Make sure we are supposed to do this */ + if (usbstick_mode.raw == 0) return; + +/* Get the raw frame */ + memcpy(&raw_buf[UIP_LLH_LEN], frame_result->frame, frame_result->length); + sendlen = frame_result->length; + + //Setup generic ethernet stuff + ETHBUF(raw_buf)->type = htons(UIP_ETHTYPE_802154); + + uint64_t tempaddr; + + + //Check for broadcast message + //if(rimeaddr_cmp((const rimeaddr_t *)destAddr, &rimeaddr_null)) { + if( ( p->fcf.destAddrMode == SHORTADDRMODE) && + ( p->dest_addr.addr16 == 0xffff) ) { + ETHBUF(raw_buf)->dest.addr[0] = 0x33; + ETHBUF(raw_buf)->dest.addr[1] = 0x33; + ETHBUF(raw_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12]; + ETHBUF(raw_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13]; + ETHBUF(raw_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14]; + ETHBUF(raw_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15]; + } else { + + tempaddr = p->dest_addr.addr64; + + byte_reverse((uint8_t *)&tempaddr, 8); + + //Otherwise we have a real address + mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->dest.addr[0]), + (uip_lladdr_t *)&tempaddr); + + } + + tempaddr = p->src_addr.addr64; + + byte_reverse((uint8_t *)&tempaddr, 8); + + mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]), + (uip_lladdr_t *)&tempaddr); + + PRINTF("Low2Eth: Sending 802.15.4 packet to ethernet\n"); + + sendlen += UIP_LLH_LEN; + + rndis_send(raw_buf, sendlen, 0); + rndis_stat.rxok++; + return; +} +#endif + +/*--------------------------------------------------------------------*/ +/** \brief Process a received 6lowpan packet. + * \param r The MAC layer + * + * The 6lowpan packet is put in packetbuf by the MAC. This routine passes + * it directly to the ethernet layer without decompressing. + */ +#if 0 +void mac_802154raw(const struct mac_driver *r) +{ + uint8_t sendlen; + + parsed_frame = sicslowmac_get_frame(); + + /* Get the raw frame */ + memcpy(&raw_buf[UIP_LLH_LEN], radio_frame_data(), radio_frame_length()); + sendlen = radio_frame_length(); + + //Setup generic ethernet stuff + ETHBUF(raw_buf)->type = htons(UIP_ETHTYPE_802154); + + + //Check for broadcast message + //if(rimeaddr_cmp((const rimeaddr_t *)destAddr, &rimeaddr_null)) { + if( ( parsed_frame->fcf->destAddrMode == SHORTADDRMODE) && + ( parsed_frame->dest_addr->addr16 == 0xffff) ) { + ETHBUF(raw_buf)->dest.addr[0] = 0x33; + ETHBUF(raw_buf)->dest.addr[1] = 0x33; + ETHBUF(raw_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12]; + ETHBUF(raw_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13]; + ETHBUF(raw_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14]; + ETHBUF(raw_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15]; + } else { + + //Otherwise we have a real address + mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->dest.addr[0]), + (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); + + } + + mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]), + (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); + + PRINTF("Low2Eth: Sending 802.15.4 packet to ethernet\n"); + + sendlen += UIP_LLH_LEN; + + rndis_send(raw_buf, sendlen, 1); + rndis_stat.rxok++; + + return; +} +#endif +/** @} */ +/** @} */ diff --git a/tools/sky/uip6-bridge/sicslow_ethernet.h b/tools/sky/uip6-bridge/sicslow_ethernet.h new file mode 100644 index 000000000..2e48c188e --- /dev/null +++ b/tools/sky/uip6-bridge/sicslow_ethernet.h @@ -0,0 +1,78 @@ +/** + * \file sicslow_ethernet.c + * Routines to interface between Ethernet and 6LowPan + * + * \author + * Colin O'Flynn + * + * \addtogroup usbstick + */ + +/* Copyright (c) 2008 by: + + Colin O'Flynn coflynn@newae.com + Eric Gnoske egnoske@gmail.com + Blake Leverett bleverett@gmail.com + Mike Vidales mavida404@gmail.com + Kevin Brown kbrown3@uccs.edu + Nate Bohlmann nate@elfwerks.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: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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 OWNER 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 SICSLOW_ETHERNET_H +#define SICSLOW_ETHERNET_H + +typedef enum { + ll_802154_type, + ll_8023_type +} lltype_t; + + +typedef struct { + uint8_t sicslowpan :1; + uint8_t sendToRf :1; + uint8_t translate :1; + uint8_t raw :1; +} usbstick_mode_t; + + +#define UIP_ETHTYPE_802154 0x809A + +extern usbstick_mode_t usbstick_mode; + + +int8_t mac_translateIcmpLinkLayer(lltype_t target); +int8_t mac_translateIPLinkLayer(lltype_t target); +void mac_LowpanToEthernet(void); +void mac_ethernetToLowpan(uint8_t * ethHeader); +void mac_ethernetSetup(void); +/* void mac_802154raw(const struct mac_driver *r); */ +/* void mac_logTXtoEthernet(frame_create_params_t *p,frame_result_t *frame_result); */ + +#endif diff --git a/tools/sky/uip6-bridge/uip6-bridge-tap.c b/tools/sky/uip6-bridge/uip6-bridge-tap.c new file mode 100644 index 000000000..735fab9ce --- /dev/null +++ b/tools/sky/uip6-bridge/uip6-bridge-tap.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2009, 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. + * + * $Id: uip6-bridge-tap.c,v 1.1 2009/05/08 12:49:36 joxe Exp $ + * + */ + +/** + * \file + * A brief description of what this file is + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#include "contiki.h" +#include "net/uip.h" +#include "dev/slip.h" +#include "dev/leds.h" +#include "sicslow_ethernet.h" +#include +#include + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) + +PROCESS(uip6_bridge, "IPv6/6lowpan TAP bridge"); +PROCESS(tcpip_process, "tcpip dummy"); +AUTOSTART_PROCESSES(&uip6_bridge); + +/*---------------------------------------------------------------------------*/ +static uint8_t (* outputfunc)(uip_lladdr_t *a); +uint8_t +tcpip_output(uip_lladdr_t *a) +{ + if(outputfunc != NULL) { + outputfunc(a); + leds_invert(LEDS_GREEN); + } + return 0; +} +void +tcpip_ipv6_output(void) +{ +} +void +tcpip_set_outputfunc(uint8_t (*f)(uip_lladdr_t *)) +{ + outputfunc = f; +} +PROCESS_THREAD(tcpip_process, ev, data) +{ + PROCESS_BEGIN(); + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/* Packet from SICSLoWPAN */ +void +tcpip_input(void) +{ + if(uip_len > 0) { + mac_LowpanToEthernet(); + if(uip_len > 0) { +/* slip_write(UIP_IP_BUF, uip_len); */ + slip_write(uip_buf, uip_len); + leds_invert(LEDS_RED); + uip_len = 0; + } + } +} +/*---------------------------------------------------------------------------*/ +/* Packet from SLIP */ +static void +slip_tcpip_input(void) +{ + /* TODO Should fix this in slip configuration */ + memmove(uip_buf, &uip_buf[UIP_LLH_LEN], uip_len); + mac_ethernetToLowpan(uip_buf); +} +/*---------------------------------------------------------------------------*/ +static void +slip_activity(void) +{ + leds_invert(LEDS_BLUE); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(uip6_bridge, ev, data) +{ + PROCESS_BEGIN(); + + printf("Setting up SLIP\n"); + + mac_ethernetSetup(); + + slip_arch_init(BAUD2UBR(115200)); + slip_set_input_callback(slip_activity); + slip_set_tcpip_input_callback(slip_tcpip_input); + process_start(&slip_process, NULL); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/