diff --git a/tools/stm32w/stm32w_flasher/linux/README b/tools/stm32w/stm32w_flasher/linux/README new file mode 100644 index 000000000..3c4a0844a --- /dev/null +++ b/tools/stm32w/stm32w_flasher/linux/README @@ -0,0 +1,22 @@ +STM32W Flasher 1.1.0b1 for Linux + +A programmer for MB851 development boards based on STM32W108 microcontroller. + +- Installation + + Installation is not required. + Hal package has to be present in your system. + + +- Usage + + Run the program with -h option for usage info. + + +- Notes + + This program may require root privileges. + In Ubuntu, if you want to flash using Make, type 'sudo -s' before that. + + This version of STM32W Flasher does not support jlink yet. + diff --git a/tools/stm32w/stm32w_flasher/linux/stm32w_flasher b/tools/stm32w/stm32w_flasher/linux/stm32w_flasher new file mode 100644 index 000000000..42d38d681 Binary files /dev/null and b/tools/stm32w/stm32w_flasher/linux/stm32w_flasher differ diff --git a/tools/stm32w/stm32w_flasher/win/FTD2XX.dll b/tools/stm32w/stm32w_flasher/win/FTD2XX.dll new file mode 100644 index 000000000..742ebfb18 Binary files /dev/null and b/tools/stm32w/stm32w_flasher/win/FTD2XX.dll differ diff --git a/tools/stm32w/stm32w_flasher/win/JlinkARM.DLL b/tools/stm32w/stm32w_flasher/win/JlinkARM.DLL new file mode 100644 index 000000000..aab92aa21 Binary files /dev/null and b/tools/stm32w/stm32w_flasher/win/JlinkARM.DLL differ diff --git a/tools/stm32w/stm32w_flasher/win/_ctypes.pyd b/tools/stm32w/stm32w_flasher/win/_ctypes.pyd new file mode 100644 index 000000000..c7743c75f Binary files /dev/null and b/tools/stm32w/stm32w_flasher/win/_ctypes.pyd differ diff --git a/tools/stm32w/stm32w_flasher/win/_socket.pyd b/tools/stm32w/stm32w_flasher/win/_socket.pyd new file mode 100644 index 000000000..4d07b365d Binary files /dev/null and b/tools/stm32w/stm32w_flasher/win/_socket.pyd differ diff --git a/tools/stm32w/stm32w_flasher/win/_ssl.pyd b/tools/stm32w/stm32w_flasher/win/_ssl.pyd new file mode 100644 index 000000000..f1c538f5e Binary files /dev/null and b/tools/stm32w/stm32w_flasher/win/_ssl.pyd differ diff --git a/tools/stm32w/stm32w_flasher/win/bz2.pyd b/tools/stm32w/stm32w_flasher/win/bz2.pyd new file mode 100644 index 000000000..7ab1cbb6e Binary files /dev/null and b/tools/stm32w/stm32w_flasher/win/bz2.pyd differ diff --git a/tools/stm32w/stm32w_flasher/win/d2xx._d2xx.pyd b/tools/stm32w/stm32w_flasher/win/d2xx._d2xx.pyd new file mode 100644 index 000000000..d3aa06e80 Binary files /dev/null and b/tools/stm32w/stm32w_flasher/win/d2xx._d2xx.pyd differ diff --git a/tools/stm32w/stm32w_flasher/win/python26.dll b/tools/stm32w/stm32w_flasher/win/python26.dll new file mode 100644 index 000000000..16b929681 Binary files /dev/null and b/tools/stm32w/stm32w_flasher/win/python26.dll differ diff --git a/tools/stm32w/stm32w_flasher/win/pywintypes26.dll b/tools/stm32w/stm32w_flasher/win/pywintypes26.dll new file mode 100644 index 000000000..17848b077 Binary files /dev/null and b/tools/stm32w/stm32w_flasher/win/pywintypes26.dll differ diff --git a/tools/stm32w/stm32w_flasher/win/select.pyd b/tools/stm32w/stm32w_flasher/win/select.pyd new file mode 100644 index 000000000..192197429 Binary files /dev/null and b/tools/stm32w/stm32w_flasher/win/select.pyd differ diff --git a/tools/stm32w/stm32w_flasher/win/stm32w_flasher.exe b/tools/stm32w/stm32w_flasher/win/stm32w_flasher.exe new file mode 100644 index 000000000..b3c5096ce Binary files /dev/null and b/tools/stm32w/stm32w_flasher/win/stm32w_flasher.exe differ diff --git a/tools/stm32w/stm32w_flasher/win/unicodedata.pyd b/tools/stm32w/stm32w_flasher/win/unicodedata.pyd new file mode 100644 index 000000000..4e4632535 Binary files /dev/null and b/tools/stm32w/stm32w_flasher/win/unicodedata.pyd differ diff --git a/tools/stm32w/stm32w_flasher/win/w9xpopen.exe b/tools/stm32w/stm32w_flasher/win/w9xpopen.exe new file mode 100644 index 000000000..139f6dd1d Binary files /dev/null and b/tools/stm32w/stm32w_flasher/win/w9xpopen.exe differ diff --git a/tools/stm32w/stm32w_flasher/win/win32api.pyd b/tools/stm32w/stm32w_flasher/win/win32api.pyd new file mode 100644 index 000000000..3018552bd Binary files /dev/null and b/tools/stm32w/stm32w_flasher/win/win32api.pyd differ diff --git a/tools/stm32w/tapslip6.c b/tools/stm32w/tapslip6.c new file mode 100644 index 000000000..31ac0ecd2 --- /dev/null +++ b/tools/stm32w/tapslip6.c @@ -0,0 +1,818 @@ +/* + * Copyright (c) 2001, Adam Dunkels. + * Copyright (c) 2009, Joakim Eriksson, Niclas Finne. + * 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: tapslip6.c,v 1.1 2010/10/25 10:42:41 salvopitru Exp $ + */ + + /** + * \file + * A driver for the uip6-bridge customized for STM32W. Thanks to + * Adam Dunkels, Joakim Eriksson, Niclas Finne for the original + * code. + * \author + * Salvatore Pitrulli + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +int ssystem(const char *fmt, ...) + __attribute__ ((__format__(__printf__, 1, 2))); +void write_to_serial(void *inbuf, int len); + +#define PRINTF(...) if(verbose)printf(__VA_ARGS__) + +//#define PROGRESS(s) fprintf(stderr, s) +#define PROGRESS(s) do { } while (0) + +#define USAGE_STRING "usage: tapslip6 [-B baudrate] [-s siodev] [-t tundev] [-a ipaddress[/prefixlen]|-p 64bit-prefix[/prefixlen]] [-c channel] [-r] [-v] [-h]" +#define HELP_STRING "usage: tapslip6 [-B baudrate] [-s siodev] [-t tundev] [-a ipaddress[/prefixlen]|-p 64bit-prefix[/prefixlen]] [-c channel] [-r] [-v] [-h]\r\n\n\ +Options:\r\n\ +-B baudrate\tBaudrate of the serial port (default:115200).\r\n\ +-s siodev\tDevice that identifies the bridge (default: the first available\r\n\ +\t\tamong ttyUSB0, cuaU0 and ucom0)\r\n\ +-t tundev\tThe virtual network interface (default: tap0)\r\n\ +-c channel\t802.15.4 radio channel.\r\n\ +-r\t\tSet sniffer mode. \r\n\ +-a ipaddress/[prefixlen] The address to be assigned to the virtual network\r\n\ +\t\tadapter.\r\n\ +-p 64bit-prefix\tAutomatic assignment of the IPv6 address from the specified\r\n\ +\t\tsubnet prefix. It may be followed by the prefix length\r\n\ +\t\tfor the on-link determination.\r\n\ +-v\t\tVerbose. Print more infos.\r\n\ +-h\t\tShow this help.\r\n" + +typedef enum { + false = 0, + true = 1, +} bool; + +char tundev[32] = { "tap0" }; + +const char *ipaddr = NULL; +char *ipprefix = NULL; +char autoconf_addr[44] = { 0 }; + +bool autoconf = false; +bool verbose = false; + +struct uip_eth_addr { + uint8_t addr[6]; +}; +struct uip_802154_longaddr { + uint8_t addr[8]; +}; + +static struct uip_eth_addr eth_addr; +const struct uip_eth_addr eth_addr_null = { {0} }; + +static int request_mac = 1; +static int send_mac = 1; +static int set_sniffer_mode = 1; +static int set_channel = 1; + +static int sniffer_mode = 0; +static int channel = 0; + + +int ssystem(const char *fmt, ...) + __attribute__ ((__format__(__printf__, 1, 2))); + +int ssystem(const char *fmt, ...) +{ + char cmd[128]; + va_list ap; + va_start(ap, fmt); + vsnprintf(cmd, sizeof(cmd), fmt, ap); + va_end(ap); + printf("%s\n", cmd); + fflush(stdout); + return system(cmd); +} + +#define SLIP_END 0300 +#define SLIP_ESC 0333 +#define SLIP_ESC_END 0334 +#define SLIP_ESC_ESC 0335 + +static void print_packet(u_int8_t * p, int len) +{ + int i; + for (i = 0; i < len; i++) { + printf("%02x", p[i]); + if ((i & 3) == 3) + printf(" "); + if ((i & 15) == 15) + printf("\n"); + } + printf("\n"); +} + +int is_sensible_string(const unsigned char *s, int len) +{ + int i; + for (i = 1; i < len; i++) { + if (s[i] == 0 || s[i] == '\r' || s[i] == '\n' || s[i] == '\t') { + continue; + } + else if (s[i] < ' ' || '~' < s[i]) { + return 0; + } + } + return 1; +} + + + +/* + * Read from serial, when we have a packet write it to tun. No output + * buffering, input buffered by stdio. + */ +void serial_to_tun(FILE * inslip, int outfd) +{ + static union { + unsigned char inbuf[2000]; + } uip; + static int inbufptr = 0; + + int ret; + unsigned char c; + +#ifdef linux + ret = fread(&c, 1, 1, inslip); + if (ret == -1 || ret == 0) + err(1, "serial_to_tun: read"); + goto after_fread; +#endif + + read_more: + if (inbufptr >= sizeof(uip.inbuf)) { + inbufptr = 0; + } + ret = fread(&c, 1, 1, inslip); +#ifdef linux + after_fread: +#endif + if (ret == -1) { + err(1, "serial_to_tun: read"); + } + if (ret == 0) { + clearerr(inslip); + return; + fprintf(stderr, "serial_to_tun: EOF\n"); + exit(1); + } + /* fprintf(stderr, "."); */ + switch (c) { + case SLIP_END: + if (inbufptr > 0) { + if (uip.inbuf[0] == '!') { + if (uip.inbuf[1] == 'M') { + /* Read gateway MAC address and autoconfigure tap0 interface */ + char macs[24]; + int i, pos; + struct uip_802154_longaddr dev_addr = { {0} }; // Bridge EUI-64. + + for (i = 0, pos = 0; i < 16; i++) { + macs[pos++] = uip.inbuf[2 + i]; + if ((i & 1) == 1 && i < 14) { + macs[pos++] = ':'; + } + } + macs[pos] = '\0'; + printf("*** Gateway's MAC address: %s\n", macs); + + { + + int addr_bytes[8]; // sscanf requires int instead of 8-bit for hexadecimal variables. + + sscanf(macs, "%2X:%2X:%2X:%2X:%2X:%2X:%2X:%2X", + &addr_bytes[0], + &addr_bytes[1], + &addr_bytes[2], + &addr_bytes[3], + &addr_bytes[4], + &addr_bytes[5], + &addr_bytes[6], + &addr_bytes[7]); + + for(i=0;i<8;i++){ + dev_addr.addr[i] = addr_bytes[i]; + } + } + + //////////////////////////////////////// + /*PRINTF("MAC:\n"); + for (i = 0; i < 8; i++) + PRINTF("%02X ", dev_addr.addr[i]); + PRINTF("\n"); */ + //////////////////////////////////////// + + // Remember what will be our MAC address (two middle bytes will be elided). + memcpy(ð_addr, &dev_addr, 3); + memcpy(ð_addr.addr[3], &dev_addr.addr[5], 3); + + if (autoconf) { + + struct in6_addr ipv6addr; + + dev_addr.addr[0] |= 0x02; + + strtok(ipprefix, "/"); + + if (inet_pton(AF_INET6, ipprefix, &ipv6addr) != 1) { + printf("Invalid IPv6 address.\n"); + exit(1); + } + + // Copy modified EUI-64 to the last 64 bits of IPv6 address. + memcpy(&ipv6addr.s6_addr[8], &dev_addr, 8); + + inet_ntop(AF_INET6, &ipv6addr, autoconf_addr, INET6_ADDRSTRLEN); // To string format. + + char *substr = strtok(NULL, "/"); + if (substr != NULL) { // Add the prefix length. + strcat(autoconf_addr, "/"); + strcat(autoconf_addr, substr); + } + ipaddr = autoconf_addr; + + } + ssystem("ifconfig %s down", tundev); + + + strcpy(&macs[9], &macs[15]); // Elide two middle bytes. + ssystem("ifconfig %s hw ether %s", tundev, macs); + ssystem("ifconfig %s inet6 up", tundev); + if(ipaddr){ + ssystem("ifconfig %s inet6 add %s", tundev, ipaddr); + ssystem("sysctl -w net.ipv6.conf.all.forwarding=1"); + } + ssystem("ifconfig %s\n", tundev); + + } +#define DEBUG_LINE_MARKER '\r' + } + else if (uip.inbuf[0] == '?') { + if (uip.inbuf[1] == 'M' + && memcmp(ð_addr, ð_addr_null, 6) != 0) { + /* Send our MAC address and other configuration options. */ + send_mac = 1; + set_sniffer_mode = 1; + set_channel = 1; + } + } + else if (uip.inbuf[0] == DEBUG_LINE_MARKER) { + fwrite(uip.inbuf + 1, inbufptr - 1, 1, stdout); + } + else if (is_sensible_string(uip.inbuf, inbufptr)) { + fwrite(uip.inbuf, inbufptr, 1, stdout); + } + else { + PRINTF("Writing to tun len: %d\n", inbufptr); + /* print_packet(uip.inbuf, inbufptr); */ + if (write(outfd, uip.inbuf, inbufptr) != inbufptr) { + err(1, "serial_to_tun: write"); + } + } + inbufptr = 0; + } + break; + + case SLIP_ESC: + if (fread(&c, 1, 1, inslip) != 1) { + clearerr(inslip); + /* Put ESC back and give up! */ + ungetc(SLIP_ESC, inslip); + return; + } + + switch (c) { + case SLIP_ESC_END: + c = SLIP_END; + break; + case SLIP_ESC_ESC: + c = SLIP_ESC; + break; + } + /* FALLTHROUGH */ + default: + uip.inbuf[inbufptr++] = c; + break; + } + + goto read_more; +} + +unsigned char slip_buf[2000]; +int slip_end, slip_begin; + + +void slip_send(unsigned char c) +{ + if (slip_end >= sizeof(slip_buf)) + err(1, "slip_send overflow"); + slip_buf[slip_end] = c; + slip_end++; +} + +int slip_empty() +{ + return slip_end == 0; +} + +void slip_flushbuf(int fd) +{ + int n; + + if (slip_empty()) + return; + + n = write(fd, slip_buf + slip_begin, (slip_end - slip_begin)); + + if (n == -1 && errno != EAGAIN) { + err(1, "slip_flushbuf write failed"); + } + else if (n == -1) { + PROGRESS("Q"); /* Outqueueis full! */ + } + else { + slip_begin += n; + if (slip_begin == slip_end) { + slip_begin = slip_end = 0; + } + } +} + +void write_to_serial(void *inbuf, int len) +{ + u_int8_t *p = inbuf; + int i; + + /* printf("Got packet of length %d - write SLIP\n", len); */ + /* print_packet(p, len); */ + + /* It would be ``nice'' to send a SLIP_END here but it's not + * really necessary. + */ + /* slip_send(outfd, SLIP_END); */ + PRINTF("Writing to serial len: %d\n", len); + for (i = 0; i < len; i++) { + switch (p[i]) { + case SLIP_END: + slip_send(SLIP_ESC); + slip_send(SLIP_ESC_END); + break; + case SLIP_ESC: + slip_send(SLIP_ESC); + slip_send(SLIP_ESC_ESC); + break; + default: + slip_send(p[i]); + break; + } + + } + slip_send(SLIP_END); + PROGRESS("t"); +} + + +/* + * Read from tun, write to slip. + */ +void tun_to_serial(int infd, int outfd) +{ + struct { + unsigned char inbuf[2000]; + } uip; + int size; + + if ((size = read(infd, uip.inbuf, 2000)) == -1) + err(1, "tun_to_serial: read"); + + write_to_serial(uip.inbuf, size); +} + +#ifndef BAUDRATE +#define BAUDRATE B115200 +#endif +speed_t b_rate = BAUDRATE; + +void stty_telos(int fd) +{ + struct termios tty; + speed_t speed = b_rate; + int i; + + if (tcflush(fd, TCIOFLUSH) == -1) + err(1, "tcflush"); + + if (tcgetattr(fd, &tty) == -1) + err(1, "tcgetattr"); + + cfmakeraw(&tty); + + /* Nonblocking read. */ + tty.c_cc[VTIME] = 0; + tty.c_cc[VMIN] = 0; + tty.c_cflag &= ~CRTSCTS; + tty.c_cflag &= ~HUPCL; + tty.c_cflag &= ~CLOCAL; + + cfsetispeed(&tty, speed); + cfsetospeed(&tty, speed); + + if (tcsetattr(fd, TCSAFLUSH, &tty) == -1) + err(1, "tcsetattr"); + +#if 1 + /* Nonblocking read and write. */ + /* if(fcntl(fd, F_SETFL, O_NONBLOCK) == -1) err(1, "fcntl"); */ + + tty.c_cflag |= CLOCAL; + if (tcsetattr(fd, TCSAFLUSH, &tty) == -1) + err(1, "tcsetattr"); + + i = TIOCM_DTR; + if (ioctl(fd, TIOCMBIS, &i) == -1) + err(1, "ioctl"); +#endif + + usleep(10 * 1000); /* Wait for hardware 10ms. */ + + /* Flush input and output buffers. */ + if (tcflush(fd, TCIOFLUSH) == -1) + err(1, "tcflush"); +} + +int devopen(const char *dev, int flags) +{ + char t[32]; + strcpy(t, "/dev/"); + strcat(t, dev); + return open(t, flags); +} + +#ifdef linux +#include +#include + +int tun_alloc(char *dev) +{ + struct ifreq ifr; + int fd, err; + + if ((fd = open("/dev/net/tun", O_RDWR)) < 0) + return -1; + + memset(&ifr, 0, sizeof(ifr)); + + /* Flags: IFF_TUN - TUN device (no Ethernet headers) + * IFF_TAP - TAP device + * + * IFF_NO_PI - Do not provide packet information + */ + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + if (*dev != 0) + strncpy(ifr.ifr_name, dev, IFNAMSIZ); + + if ((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0) { + close(fd); + return err; + } + strcpy(dev, ifr.ifr_name); + return fd; +} +#else +int tun_alloc(char *dev) +{ + return devopen(dev, O_RDWR); +} +#endif + + +void cleanup(void) +{ + ssystem("ifconfig %s down", tundev); + if(ipaddr){ + ssystem("sysctl -w net.ipv6.conf.all.forwarding=0"); + } +} + +void sigcleanup(int signo) +{ + fprintf(stderr, "signal %d\n", signo); + exit(0); /* exit(0) will call cleanup() */ +} + + +static int request_mac; +static int send_mac; + +void send_commands(void) +{ + char buf[3]; + + if (request_mac) { + slip_send('?'); + slip_send('M'); + slip_send(SLIP_END); + + request_mac = 0; + } + /* Send our mac to the device. If it knows our address, it is not needed to change + the MAC address of our local interface (this can be also unsupported, especially under + Windows). + */ + else if(send_mac && memcmp(ð_addr, ð_addr_null, 6) != 0 + && slip_empty()){ + short i; + PRINTF("Sending our MAC.\n"); + + slip_send('!'); + slip_send('M'); + + for(i=0; i < 6; i++){ + sprintf(buf,"%02X",eth_addr.addr[i]); + slip_send(buf[0]); + slip_send(buf[1]); + } + slip_send(SLIP_END); + + send_mac = 0; + } + else if(set_sniffer_mode && slip_empty()){ + + PRINTF("Setting sniffer mode to %d.\n", sniffer_mode); + + slip_send('!'); + slip_send('O'); + slip_send('S'); + + if(sniffer_mode){ + slip_send('1'); + } + else { + slip_send('0'); + } + slip_send(SLIP_END); + + set_sniffer_mode = 0; + + } + else if(set_channel && slip_empty()){ + + if(channel != 0){ + PRINTF("Setting channel %02d.\n", channel); + + slip_send('!'); + slip_send('O'); + slip_send('C'); + + sprintf(buf,"%02d",channel); + slip_send(buf[0]); + slip_send(buf[1]); + + slip_send(SLIP_END); + } + + set_channel = 0; + + } +} + + +int main(int argc, char **argv) +{ + int c; + int tunfd, slipfd, maxfd; + int ret; + fd_set rset, wset; + FILE *inslip; + const char *siodev = NULL; + int baudrate = -2; + + setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */ + + while ((c = getopt(argc, argv, "B:D:hs:c:rt:a:p:v")) != -1) { + switch (c) { + case 'B': + baudrate = atoi(optarg); + break; + + case 's': + if (strncmp("/dev/", optarg, 5) == 0) { + siodev = optarg + 5; + } + else { + siodev = optarg; + } + break; + + case 't': + if (strncmp("/dev/", optarg, 5) == 0) { + strcpy(tundev, optarg + 5); + } + else { + strcpy(tundev, optarg); + } + break; + + case 'c': + channel = atoi(optarg); + set_channel = 1; + break; + case 'r': + sniffer_mode = 1; + break; + + case 'a': + if (autoconf == true) { + errx(1, USAGE_STRING); + } + ipaddr = optarg; + break; + + case 'p': + if (ipaddr != NULL) { + errx(1, USAGE_STRING); + } + autoconf = true; + ipprefix = optarg; + break; + + case 'v': + verbose = true; + break; + + case '?': + case 'h': + default: + errx(1, HELP_STRING); + break; + } + } +#if 0 + argc -= (optind - 1); + argv += (optind - 1); + + //if(argc != 3 && argc != 4) { + //if (autoconf == false && ipaddr == NULL ) { + errx(1, USAGE_STRING); + } +#endif + + + switch (baudrate) { + case -2: + break; /* Use default. */ + case 9600: + b_rate = B9600; + break; + case 19200: + b_rate = B19200; + break; + case 38400: + b_rate = B38400; + break; + case 57600: + b_rate = B57600; + break; + case 115200: + b_rate = B115200; + break; + default: + err(1, "unknown baudrate %d", baudrate); + break; + } + + + if (siodev != NULL) { + slipfd = devopen(siodev, O_RDWR | O_NONBLOCK); + if (slipfd == -1) { + err(1, "can't open siodev ``/dev/%s''", siodev); + } + } + else { + static const char *siodevs[] = { + "ttyUSB0", "cuaU0", "ucom0" /* linux, fbsd6, fbsd5 */ + }; + int i; + for (i = 0; i < 3; i++) { + siodev = siodevs[i]; + slipfd = devopen(siodev, O_RDWR | O_NONBLOCK); + if (slipfd != -1) + break; + } + if (slipfd == -1) { + err(1, "can't open siodev"); + } + } + fprintf(stderr, "slip started on ``/dev/%s''\n", siodev); + stty_telos(slipfd); + slip_send(SLIP_END); + inslip = fdopen(slipfd, "r"); + if (inslip == NULL) + err(1, "main: fdopen"); + + tunfd = tun_alloc(tundev); + printf("opening: %s\n", tundev); + if (tunfd == -1) + err(1, "main: open"); + fprintf(stderr, "opened device ``/dev/%s''\n", tundev); + + atexit(cleanup); + signal(SIGHUP, sigcleanup); + signal(SIGTERM, sigcleanup); + signal(SIGINT, sigcleanup); + + + + while (1) { + maxfd = 0; + FD_ZERO(&rset); + FD_ZERO(&wset); + + send_commands(); + + if (!slip_empty()) { /* Anything to flush? */ + FD_SET(slipfd, &wset); + } + + FD_SET(slipfd, &rset); /* Read from slip ASAP! */ + if (slipfd > maxfd) + maxfd = slipfd; + + /* We only have one packet at a time queued for slip output. */ + if (slip_empty()) { + FD_SET(tunfd, &rset); + if (tunfd > maxfd) + maxfd = tunfd; + } + + ret = select(maxfd + 1, &rset, &wset, NULL, NULL); + if (ret == -1 && errno != EINTR) { + err(1, "select"); + } + else if (ret > 0) { + if (FD_ISSET(slipfd, &rset)) { + serial_to_tun(inslip, tunfd); + } + + if (FD_ISSET(slipfd, &wset)) { + slip_flushbuf(slipfd); + } + + if (slip_empty() && FD_ISSET(tunfd, &rset)) { + tun_to_serial(tunfd, slipfd); + slip_flushbuf(slipfd); + } + } + } +} diff --git a/tools/stm32w/uip6_bridge/Makefile b/tools/stm32w/uip6_bridge/Makefile new file mode 100644 index 000000000..eaafe7e53 --- /dev/null +++ b/tools/stm32w/uip6_bridge/Makefile @@ -0,0 +1,21 @@ +ifdef CONTIKI_HOME +CONTIKI = $(CONTIKI_HOME) +else +ifndef CONTIKI +CONTIKI=../../.. +endif +endif + +DEFINES=PROJECT_CONF_H=\"bridge-conf.h\" +UIP_CONF_IPV6=1 + +ifndef TARGET +TARGET=mb851 +endif + +PROJECTDIRS = dev +PROJECT_SOURCEFILES = fakeuip.c sicslow_ethernet.c slip.c + +all: uip6-bridge-tap + +include $(CONTIKI)/Makefile.include diff --git a/tools/stm32w/uip6_bridge/README b/tools/stm32w/uip6_bridge/README new file mode 100644 index 000000000..2b0b518ff --- /dev/null +++ b/tools/stm32w/uip6_bridge/README @@ -0,0 +1,27 @@ +See siscslow_ethernet.c for information about translation between +802.15.4 and 802.3 addresses. +Devices must have a proper EUI-64 address for this bridge to work. +If the EUI-64 address of the devices cannot be changed and they are +incompatible with the translation mechanism, you have to change the +translation rules (they are defined in mac_createSicslowpanLongAddr() +and mac_createEthernetAddr()). + +Usage example: + +run tapslip6 (source file are located in tools folder). + +./tapslip6 -p 2001:db8:bbbb:abce::/64 + +where 2001:db8:bbbb:abce:: is the network address and 64 is the the +prefix length. The remaining 64 bits will be derived from the EUI-64 (two +middle bytes will be removed). + +You can also simply create an edge router in one of the network nodes: +you have to enable routing and set the appropriate forwarding rules, as +shown in contiki-init-net.c. Then you have to add the corresponding +rule on your machine, for example: +route -A inet6 add 2001:db8:bbbb:abcd::/64 gw 2001:db8:bbbb:abce: + 280:e102::8a. + +where 2001:db8:bbbb:abce:280:e102::6c is the address of the edge +node and 2001:db8:bbbb:abcd::/64 is the lowpan address. diff --git a/tools/stm32w/uip6_bridge/bridge-conf.h b/tools/stm32w/uip6_bridge/bridge-conf.h new file mode 100644 index 000000000..2c76ab87a --- /dev/null +++ b/tools/stm32w/uip6_bridge/bridge-conf.h @@ -0,0 +1,65 @@ +/* + * 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 2010/10/25 10:42:41 salvopitru Exp $ + */ + +/** + * \file + * A brief description of what this file is + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#ifndef __BRIDGE_CONF_H__ +#define __BRIDGE_CONF_H__ + +#undef WITH_RIME +#define WITH_RIME 0 + +#undef UIP_CONF_ROUTER +#define UIP_CONF_ROUTER 0 + +#undef UIP_CONF_LLH_LEN +#define UIP_CONF_LLH_LEN 14 + +#undef UIP_CONF_BUFFER_SIZE +#define UIP_CONF_BUFFER_SIZE 512 + +#undef WITH_SERIAL_LINE_INPUT +#define WITH_SERIAL_LINE_INPUT 0 + +#undef FIXED_NET_ADDRESS +#define FIXED_NET_ADDRESS 0 + +#undef RADIO_RXBUFS +#define RADIO_RXBUFS 15 + + +#endif /* __BRIDGE_CONF_H__ */ diff --git a/tools/stm32w/uip6_bridge/dev/slip.c b/tools/stm32w/uip6_bridge/dev/slip.c new file mode 100644 index 000000000..7ae2c9626 --- /dev/null +++ b/tools/stm32w/uip6_bridge/dev/slip.c @@ -0,0 +1,501 @@ +/* -*- 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 2010/10/25 10:42:41 salvopitru Exp $ +*/ + + +#include +#include +#include "contiki.h" + +#include "net/rime/rimeaddr.h" +#include "sys/ctimer.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" + +#include "../sicslow_ethernet.h" +#include +#include "dev/stm32w-radio.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. */ + + +struct uip_eth_addr slip_eth_addr = {{0}}; +const struct uip_eth_addr eth_addr_null = {{0}}; + +static struct ctimer t; +static void request_mac(void *); + +uint8_t mac_hextoi(struct uip_eth_addr *a, const char * mac); + +//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; +} +/*---------------------------------------------------------------------------*/ +int from_slipbuffer(uint8_t *outbuf, uint16_t blen) +{ + + /* + * 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; +} + +/* 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 0 + 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; + } + } +#endif + + if(rxbuf[begin] == '?' || rxbuf[begin] == '!') { // Should this characters be escaped? + + uint8_t tmpbuf[14]; + + from_slipbuffer(tmpbuf, 14); + + + if(tmpbuf[0] == '?') { + int j; + char* hexchar = "0123456789abcdef"; + if(tmpbuf[1] == 'M') { + + /* this is just a test so far... just to see if it works */ + slip_arch_writeb('!'); + slip_arch_writeb('M'); + for(j = 0; j < RIMEADDR_SIZE; j++) { + slip_arch_writeb(hexchar[rimeaddr_node_addr.u8[j] >> 4]); + slip_arch_writeb(hexchar[rimeaddr_node_addr.u8[j] & 15]); + } + slip_arch_writeb(SLIP_END); + return 0; + } + } +#if 1 + else if(tmpbuf[0] == '!') { + + if(tmpbuf[1] == 'M') { + char * mac = (char *)tmpbuf + 2; + + if(mac_hextoi(&slip_eth_addr,mac)!=0){ + /* Error! */ + /*rxbuf_init(); + slip_arch_writeb('!'); + slip_arch_writeb('E'); + slip_arch_writeb(SLIP_END);*/ + printf("Error! Incorrect MAC format.\n"); + + } + /*for(int i=0;i<6;i++) + printf("%02X ",slip_eth_addr.addr[i]); + printf("\n"); */ + return 0; + } + else if(memcmp(&tmpbuf[1], "OS1", 3) == 0) { + + + enable_sniffer_mode(1); + + return 0; + } + else if(memcmp(&tmpbuf[1], "OS0",3) == 0) { + + enable_sniffer_mode(0); + + return 0; + } + else if(memcmp(&tmpbuf[1], "OC", 2) == 0) { + + short ch_num; + + tmpbuf[5]='\0'; + if(ch_num = atoi((char *)tmpbuf+3)){ + ST_RadioSetChannel(ch_num); + } + return 0; + } + } + } + +#endif + + return from_slipbuffer(outbuf, blen); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(slip_process, ev, data) +{ + PROCESS_BEGIN(); + + rxbuf_init(); + + ctimer_set(&t, 2*CLOCK_SECOND, request_mac, NULL); + + 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; +} +/*---------------------------------------------------------------------------*/ +uint8_t mac_hextoi(struct uip_eth_addr *a, const char * mac) +{ + int i,j; + + memset(a,0,sizeof(struct uip_eth_addr)); + + for(i = 0, j = 0; j < 12; j++){ + + if((mac[j] >= '0' && mac[j] <= '9')){ + a->addr[i] += (mac[j] - '0') * ((j & 1) ? 1 : 16); + } + else if(mac[j] >= 'A' && mac[j] <= 'F'){ + a->addr[i] += (mac[j] - 'A' + 10) * ((j & 1) ? 1 : 16); + } + else { + return 1; + } + if(j&1){ + i++; + } + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +static void request_mac(void * ptr) +{ + if(memcmp(&slip_eth_addr,ð_addr_null,6)==0){ + slip_write("?M", 2); + ctimer_set(&t, 6*CLOCK_SECOND, request_mac, NULL); + } +} +/*---------------------------------------------------------------------------*/ diff --git a/tools/stm32w/uip6_bridge/dev/slip.h b/tools/stm32w/uip6_bridge/dev/slip.h new file mode 100644 index 000000000..3130ea6f4 --- /dev/null +++ b/tools/stm32w/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 2010/10/25 10:42:41 salvopitru 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/stm32w/uip6_bridge/fakeuip.c b/tools/stm32w/uip6_bridge/fakeuip.c new file mode 100644 index 000000000..9054b2b96 --- /dev/null +++ b/tools/stm32w/uip6_bridge/fakeuip.c @@ -0,0 +1,129 @@ + +/* 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 "net/uip-ds6.h" +#include + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) + +uip_buf_t uip_aligned_buf; + +u16_t uip_len; + +struct uip_stats uip_stat; + +uip_lladdr_t uip_lladdr; + +u16_t htons(u16_t val) { return UIP_HTONS(val);} + +uip_ds6_netif_t uip_ds6_if; + +/********** UIP_DS6.c **********/ + +void +uip_ds6_set_addr_iid(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 +#error fakeuip.c cannot build interface address when UIP_LLADDR_LEN is not 6 or 8 +#endif +} + +/*---------------------------------------------------------------------------*/ +/* + * get a link local address - + * state = -1 => any address is ok. Otherwise state = desired state of addr. + * (TENTATIVE, PREFERRED, DEPRECATED) + */ +uip_ds6_addr_t * +uip_ds6_get_link_local(int8_t state) { + uip_ds6_addr_t *locaddr; + for(locaddr = uip_ds6_if.addr_list; + locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) { + if((locaddr->isused) && (state == - 1 || locaddr->state == state) + && (uip_is_addr_link_local(&locaddr->ipaddr))) { + return locaddr; + } + } + return NULL; +} + +uip_ds6_addr_t * +uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type) +{ + return NULL; +} +/********** 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/stm32w/uip6_bridge/rtimer-arch.h b/tools/stm32w/uip6_bridge/rtimer-arch.h new file mode 100644 index 000000000..1b5322b4b --- /dev/null +++ b/tools/stm32w/uip6_bridge/rtimer-arch.h @@ -0,0 +1,5 @@ +#ifndef __RTIMER_ARCH_H__ +#define __RTIMER_ARCH_H__ + + +#endif /* __RTIMER_ARCH_H__ */ diff --git a/tools/stm32w/uip6_bridge/sicslow_ethernet.c b/tools/stm32w/uip6_bridge/sicslow_ethernet.c new file mode 100644 index 000000000..e49081bd6 --- /dev/null +++ b/tools/stm32w/uip6_bridge/sicslow_ethernet.c @@ -0,0 +1,980 @@ +/** + * \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 +*/ + +/* + * For STM32W. + * Modified! 0xff and 0xfe are sobstituted by 0x02 and 0x00. +*/ + +#include "net/uip.h" +#include "net/uip_arp.h" /* For ethernet header structure */ +#include "net/rime.h" +#include "net/sicslowpan.h" +#include "sicslow_ethernet.h" +#include "dev/stm32w-radio.h" +#include "net/mac/frame802154.h" +#include "dev/slip.h" +#include "dev/leds.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; + +extern struct uip_eth_addr slip_eth_addr; + +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); */ +void mac_802154raw(const struct radio_driver *radio); +/* extern void (*sicslowmac_snifferhook)(const struct mac_driver *r); */ +void mac_ethhijack(const struct radio_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]; + +//#include "net/mac/sicslowmac.h" +/* We don't really know if this is the mac driver that we were using before */ +//#define MAC_DRIVER sicslowmac_driver + + +void enable_sniffer_mode(short on) +{ + + if(on){ +#if 0 + ST_RadioEnableReceiveCrc(FALSE); // CRC will not be checked by hardware. + ST_RadioEnableAutoAck(FALSE); + ST_RadioEnableAddressFiltering(FALSE); + stm32w_radio_driver.set_receive_function(mac_ethhijack); + usbstick_mode.raw = 1; + usbstick_mode.sendToRf = 0; +#endif + } + else { + ST_RadioEnableReceiveCrc(TRUE); // CRC will not be checked by hardware. + ST_RadioEnableAutoAck(TRUE); + ST_RadioEnableAddressFiltering(TRUE); + //MAC_DRIVER.init(&stm32w_radio_driver); + usbstick_mode.raw = 0; + usbstick_mode.sendToRf = 1; + } +} + +void mac_ethernetSetup(void) +{ + //usbstick_mode.sicslowpan = 1; + //usbstick_mode.sendToRf = 0; + usbstick_mode.translate = 1; + //usbstick_mode.raw = 1; + + enable_sniffer_mode(0); + +/* 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 != UIP_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) { */ + if(memcmp(&slip_eth_addr,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; + lowpan->addr[3] = 0x02; + lowpan->addr[4] = 0x00; + } + + //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); + /*memcpy(ethernet, &uip_lladdr.addr[0], 3); + memcpy(ethernet+3, &uip_lladdr.addr[5], 3);*/ + memcpy(ethernet,&slip_eth_addr,6); + + /* byte_reverse(ethernet, 6); */ + + return 1; + } + + + //Check if we need to do anything: + if ((lowpan->addr[3] == 0x02) && (lowpan->addr[4] == 0x00) && + ((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 1 +void mac_ethhijack(const struct radio_driver *r) +{ + if (usbstick_mode.raw) { + mac_802154raw(r); + } + +#if 0 + 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 + +} +#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. + */ +#define ETH_ENCAP +#if 1 +void mac_802154raw(const struct radio_driver *radio) +{ + uint8_t len; + frame802154_t frame; + struct uip_eth_addr * eth_src, * eth_dest; + eth_src = ÐBUF(uip_buf)->src; + eth_dest = ÐBUF(uip_buf)->dest; + +#ifndef ETH_ENCAP + len = radio->read(uip_buf, STM32W_MAX_PACKET_LEN); +#else + len = radio->read(UIP_IP_BUF, STM32W_MAX_PACKET_LEN); + if(len > 0) { + if(frame802154_parse(&uip_buf[UIP_LLH_LEN], len, &frame)) { + + struct uip_802154_longaddr * lowpan_src, * lowpan_dest; + + lowpan_src = (struct uip_802154_longaddr *)&frame.src_addr; + lowpan_dest = (struct uip_802154_longaddr *)&frame.dest_addr; + + // Fake Ethernet addresses. + + eth_src->addr[0] = lowpan_src->addr[0]; + eth_src->addr[1] = lowpan_src->addr[1]; + eth_src->addr[2] = lowpan_src->addr[2]; + eth_src->addr[3] = lowpan_src->addr[5]; + eth_src->addr[4] = lowpan_src->addr[6]; + eth_src->addr[5] = lowpan_src->addr[7]; + + + if( (frame.fcf.dest_addr_mode == FRAME802154_SHORTADDRMODE) && + (frame.dest_addr[0] == 0xff)&& + (frame.dest_addr[1] == 0xff) ) { + memset(eth_dest->addr, 0xff, 6); + } + else { + eth_dest->addr[0] = lowpan_dest->addr[0]; + eth_dest->addr[1] = lowpan_dest->addr[1]; + eth_dest->addr[2] = lowpan_dest->addr[2]; + eth_dest->addr[3] = lowpan_dest->addr[5]; + eth_dest->addr[4] = lowpan_dest->addr[6]; + eth_dest->addr[5] = lowpan_dest->addr[7]; + } + + } + else { + memset(eth_src->addr, 0xff, 6); + memset(eth_dest->addr, 0xff, 6); + } + } + + //memcpy(ETHBUF(uip_buf)->dest,&slip_eth_addr,6); + ETHBUF(uip_buf)->type = htons(UIP_ETHTYPE_802154); + + + +#if 0 + 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(); +#endif + + + +#if 0 + //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"); +#endif + + len += UIP_LLH_LEN; + +#endif + + slip_write(uip_buf, len); + leds_invert(LEDS_RED); + + //rndis_send(raw_buf, sendlen, 1); + //rndis_stat.rxok++; + + return; +} +#endif +/** @} */ +/** @} */ diff --git a/tools/stm32w/uip6_bridge/sicslow_ethernet.h b/tools/stm32w/uip6_bridge/sicslow_ethernet.h new file mode 100644 index 000000000..1ebdbb352 --- /dev/null +++ b/tools/stm32w/uip6_bridge/sicslow_ethernet.h @@ -0,0 +1,80 @@ +/** + * \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 enable_sniffer_mode(short on); +/* 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/stm32w/uip6_bridge/uip6-bridge-tap.c b/tools/stm32w/uip6_bridge/uip6-bridge-tap.c new file mode 100644 index 000000000..4a933fd1f --- /dev/null +++ b/tools/stm32w/uip6_bridge/uip6-bridge-tap.c @@ -0,0 +1,173 @@ +/* + * 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 2010/10/25 10:42:41 salvopitru 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 "net/packetbuf.h" + + +#include +#include + +void clock_wait(int i); + +#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) { + leds_on(LEDS_GREEN); + outputfunc(a); + /* printf("pppp o %u tx %u rx %u\n", UIP_IP_BUF->proto, + packetbuf_attr(PACKETBUF_ATTR_TRANSMIT_TIME), + packetbuf_attr(PACKETBUF_ATTR_LISTEN_TIME));*/ + leds_off(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) { + leds_on(LEDS_RED); + mac_LowpanToEthernet(); + if(uip_len > 0) { + /* printf("pppp i %u tx %u rx %u\n", UIP_IP_BUF->proto, + packetbuf_attr(PACKETBUF_ATTR_TRANSMIT_TIME), + packetbuf_attr(PACKETBUF_ATTR_LISTEN_TIME));*/ + slip_write(uip_buf, uip_len); + uip_len = 0; + leds_off(LEDS_RED); + } + } +} +/*---------------------------------------------------------------------------*/ +/* 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); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(uip6_bridge, ev, data) +{ + PROCESS_BEGIN(); + + printf("Setting up SLIP\n"); + + { + short i; + for(i=0;i<5;i++){ + leds_blink(); + clock_wait(100); + } + } + + + mac_ethernetSetup(); + + slip_arch_init(115200); + slip_set_tcpip_input_callback(slip_tcpip_input); + process_start(&slip_process, NULL); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ + +#ifdef __ICCARM__ +int putchar(int c) +#else +void __io_putchar(char c) +#endif +{ +#define SLIP_END 0300 + static char debug_frame = 0; + + if(!debug_frame) { /* Start of debug output */ + slip_arch_writeb(SLIP_END); + slip_arch_writeb('\r'); /* Type debug line == '\r' */ + debug_frame = 1; + } + + slip_arch_writeb((char)c); + + /* + * Line buffered output, a newline marks the end of debug output and + * implicitly flushes debug output. + */ + if(c == '\n') { + slip_arch_writeb(SLIP_END); + debug_frame = 0; + } + +#ifdef __ICCARM__ + return c; +#endif +} +/*---------------------------------------------------------------------------*/ diff --git a/tools/stm32w/wpcapslip6/Makefile b/tools/stm32w/wpcapslip6/Makefile new file mode 100644 index 000000000..a274ee8cc --- /dev/null +++ b/tools/stm32w/wpcapslip6/Makefile @@ -0,0 +1,24 @@ +CONTIKI=../../.. + + +CFLAGS=-Wall -Werror -I$(CONTIKI)/core -I. + +ifdef WITH_STDIN + CFLAGS += -DWITH_STDIN +endif + +all: clean wpcapslip6 +ifdef WITH_STDIN + mv wpcapslip6.exe wpcapslip6-stdin.exe +endif + +clean: + rm -f wpcapslip6.o wpcap6.o + + +vpath %.c $(CONTIKI)/core/net + +wpcapslip6: wpcapslip6.o wpcap6.o + +%: %.o + $(CC) $(LDFLAGS) $^ /lib/w32api/libws2_32.a /lib/w32api/libiphlpapi.a -o $@ diff --git a/tools/stm32w/wpcapslip6/README.txt b/tools/stm32w/wpcapslip6/README.txt new file mode 100644 index 000000000..4d9eec9c3 --- /dev/null +++ b/tools/stm32w/wpcapslip6/README.txt @@ -0,0 +1,7 @@ +This software needs a working network adapter. You can install a Microsoft Loopback adapter. +(Windows XP users: remeber to reboot after the installation procedure). + +In order to install this kind of device in Windows 7, use +devcon utility (you can download it from Microsoft website). + +> devcon.exe install %windir%\inf\netloop.inf *msloop \ No newline at end of file diff --git a/tools/stm32w/wpcapslip6/contiki-conf.h b/tools/stm32w/wpcapslip6/contiki-conf.h new file mode 100644 index 000000000..432dc4c22 --- /dev/null +++ b/tools/stm32w/wpcapslip6/contiki-conf.h @@ -0,0 +1,18 @@ +#ifndef __CONTIKI_CONF_H__ +#define __CONTIKI_CONF_H__ +#include +#define CCIF +#define CLIF + +typedef uint8_t u8_t; +typedef uint16_t u16_t; +typedef uint32_t u32_t; +typedef int32_t s32_t; +typedef unsigned short uip_stats_t; + +#define UIP_CONF_UIP_IP4ADDR_T_WITH_U32 1 + +typedef unsigned long clock_time_t; +#define CLOCK_CONF_SECOND 1000 + +#endif /* __CONTIKI_CONF_H__ */ diff --git a/tools/stm32w/wpcapslip6/showhiddendevices.bat b/tools/stm32w/wpcapslip6/showhiddendevices.bat new file mode 100644 index 000000000..dc6046420 --- /dev/null +++ b/tools/stm32w/wpcapslip6/showhiddendevices.bat @@ -0,0 +1,3 @@ +set devmgr_show_nonpresent_devices=1 + +start devmgmt.msc diff --git a/tools/stm32w/wpcapslip6/wpcap6.c b/tools/stm32w/wpcapslip6/wpcap6.c new file mode 100644 index 000000000..f2dd69b0f --- /dev/null +++ b/tools/stm32w/wpcapslip6/wpcap6.c @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2007, 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. + * + * Author: Oliver Schmidt + * + */ + + /** + * \file + * Functions needed by the Windows application for uip6-bridge. + * Thanks to Oliver Schmidt for the original code. + * \author + * Salvatore Pitrulli + */ + + + +#define WIN32_LEAN_AND_MEAN +#define _WIN32_WINNT 0x0501 +#include +#include +#include + +#include +#include +#include +#ifdef __CYGWIN__ +#include +#else /* __CYGWIN__ */ +#include +#endif /* __CYGWIN__ */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* Avoid 'conflicting types' errors. */ +#define htonl +#define htons + +#define PROGRESS(x) + + +struct pcap; + +struct pcap_addr { + struct pcap_addr *next; + struct sockaddr *addr; + struct sockaddr *netmask; + struct sockaddr *broadaddr; + struct sockaddr *dstaddr; +}; + +struct pcap_if { + struct pcap_if *next; + char *name; + char *description; + struct pcap_addr *addresses; + DWORD flags; +}; + +struct pcap_pkthdr { + struct timeval ts; + DWORD caplen; + DWORD len; +}; + +void wpcap_send(void *buf, int len); + +HMODULE wpcap; + +static struct pcap *pcap; + +static int (* pcap_findalldevs)(struct pcap_if **, char *); +static struct pcap *(* pcap_open_live)(char *, int, int, int, char *); +static int (* pcap_next_ex)(struct pcap *, struct pcap_pkthdr **, unsigned char **); +static int (* pcap_sendpacket)(struct pcap *, unsigned char *, int); + + +#define BUFSIZE 1514 + + +#include "net/uip.h" +#include "net/uip_arp.h" + + +static struct uip_eth_addr uip_ethaddr = {{0,0,0,0,0,0}}; + +static char interface_name[256] = ""; + +static int logging; + +static void +log_message(char *msg1, char *msg2) +{ + if(logging) { + printf("Log: %s %s\n", msg1, msg2); + } +} +/*---------------------------------------------------------------------------*/ +static void +error_exit(char *msg1) +{ + printf("error_exit: %s", msg1); + exit(EXIT_FAILURE); +} +/*---------------------------------------------------------------------------*/ +static void +setethaddr(struct uip_eth_addr *a) +{ + memcpy(&uip_ethaddr, a, sizeof(struct uip_eth_addr)); +} +/*---------------------------------------------------------------------------*/ +static void +init_pcap(struct uip_eth_addr *addr) +{ + PIP_ADAPTER_ADDRESSES adapters; + ULONG size = 0; + + if(GetAdaptersAddresses(AF_INET6, GAA_FLAG_SKIP_ANYCAST | + GAA_FLAG_SKIP_MULTICAST | + GAA_FLAG_SKIP_DNS_SERVER, + NULL, NULL, &size) != ERROR_BUFFER_OVERFLOW) { + error_exit("error on access to adapter list size\n"); + } + adapters = alloca(size); + if(GetAdaptersAddresses(AF_INET6, GAA_FLAG_SKIP_ANYCAST | + GAA_FLAG_SKIP_MULTICAST | + GAA_FLAG_SKIP_DNS_SERVER, + NULL, adapters, &size) != ERROR_SUCCESS) { + error_exit("error on access to adapter list\n"); + } + + while(adapters != NULL) { + + char buffer[256]; + WideCharToMultiByte(CP_ACP, 0, adapters->Description, -1, + buffer, sizeof(buffer), NULL, NULL); + log_message("set_ethaddr: found adapter: ", buffer); + + if (adapters->PhysicalAddressLength == 6) { + wsprintf(buffer, "%02X-%02X-%02X-%02X-%02X-%02X", + adapters->PhysicalAddress[0], adapters->PhysicalAddress[1], + adapters->PhysicalAddress[2], adapters->PhysicalAddress[3], + adapters->PhysicalAddress[4], adapters->PhysicalAddress[5]); + + log_message("Physical address: ", buffer); + + if(memcmp(addr,adapters->PhysicalAddress,sizeof(struct uip_eth_addr))==0){ + char error[256] = ""; + + WideCharToMultiByte(CP_ACP, 0, adapters->FriendlyName, -1, + interface_name, sizeof(interface_name), NULL, NULL); + printf("Using local network interface: %s\n",interface_name); + + strcpy(buffer,"\\Device\\NPF_"); + strncat(buffer,adapters->AdapterName,200); + pcap = pcap_open_live(buffer, sizeof(buffer), 0, -1, error); + if(pcap == NULL) { + error_exit(error); + } + break; + } + } + + adapters = adapters->Next; + } + + if(adapters == NULL) { + error_exit("no adapter found with Ethernet address specified on cmdline\n"); + } +} +/*---------------------------------------------------------------------------*/ +static void +print_packet(unsigned char *buf, int len) +{ + int i; + + for(i = 0; i < len; ++i) { + printf("0x%02x, ", buf[i]); + if(i % 8 == 7) { + printf("\n"); + } + } + printf("\n\n"); +} +/*---------------------------------------------------------------------------*/ +char * wpcap_start(struct uip_eth_addr *addr, int log) +{ + + logging = log; + + wpcap = LoadLibrary("wpcap.dll"); + pcap_findalldevs = (int (*)(struct pcap_if **, char *)) + GetProcAddress(wpcap, "pcap_findalldevs"); + pcap_open_live = (struct pcap *(*)(char *, int, int, int, char *)) + GetProcAddress(wpcap, "pcap_open_live"); + pcap_next_ex = (int (*)(struct pcap *, struct pcap_pkthdr **, unsigned char **)) + GetProcAddress(wpcap, "pcap_next_ex"); + pcap_sendpacket = (int (*)(struct pcap *, unsigned char *, int)) + GetProcAddress(wpcap, "pcap_sendpacket"); + + if(pcap_findalldevs == NULL || pcap_open_live == NULL || + pcap_next_ex == NULL || pcap_sendpacket == NULL) { + error_exit("error on access to winpcap library\n"); + } + + init_pcap(addr); + setethaddr(addr); + + return interface_name; + +} +/*---------------------------------------------------------------------------*/ +uint16_t +wpcap_poll(char * buf) +{ + struct pcap_pkthdr *packet_header; + unsigned char *packet; + struct uip_eth_hdr * eth_hdr; + + switch(pcap_next_ex(pcap, &packet_header, &packet)) { + case -1: + error_exit("error on poll\n"); + case 0: + return 0; + } + + if(packet_header->caplen > BUFSIZE) { + return 0; + } + + eth_hdr = (struct uip_eth_hdr *)packet; + + if(memcmp(&uip_ethaddr,ð_hdr->src,sizeof(struct uip_eth_addr))!=0){ + // It's not a packet originated from the interface itself. + return 0; + } + + CopyMemory(buf, packet, packet_header->caplen); + return packet_header->caplen; + +} +/*---------------------------------------------------------------------------*/ +void +wpcap_send(void *buf, int len) +{ + + if(pcap_sendpacket(pcap, buf, len) == -1) { + print_packet(buf, len); + error_exit("error on send\n"); + } + +} +/*---------------------------------------------------------------------------*/ +void +wpcap_exit(void) +{ + FreeLibrary(wpcap); +} +/*---------------------------------------------------------------------------*/ diff --git a/tools/stm32w/wpcapslip6/wpcapslip6.c b/tools/stm32w/wpcapslip6/wpcapslip6.c new file mode 100644 index 000000000..cf2da4717 --- /dev/null +++ b/tools/stm32w/wpcapslip6/wpcapslip6.c @@ -0,0 +1,991 @@ +/* +* Copyright (c) 2001, Adam Dunkels. +* Copyright (c) 2009, Joakim Eriksson, Niclas Finne. +* 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: wpcapslip6.c,v 1.1 2010/10/25 10:42:41 salvopitru Exp $ +*/ + + /** + * \file + * A driver for the uip6-bridge customized for STM32W that works + * under Windows (using cygwin dll). Thanks to Adam Dunkels, Joakim + * Eriksson, Niclas Finne for the original code. + * \author + * Salvatore Pitrulli + */ + + +#include +#include +#include +#include +#ifdef __CYGWIN__ +#include +#else /* __CYGWIN__ */ +#include +#endif /* __CYGWIN__ */ +#include +//#include +#include +#include +#include +#include +#include +//#include +#include +#include + +//#include +#include + + +#include + + +//#include "net/uip.h" +#include "net/uip_arp.h" + + + + + +char * wpcap_start(struct uip_eth_addr *addr, int log); + +void wpcap_send(void *buf, int len); + +uint16_t wpcap_poll(char *buf); + +void wpcap_exit(void); + +int ssystem(const char *fmt, ...) +__attribute__((__format__ (__printf__, 1, 2))); +void write_to_serial(void *inbuf, int len); + +#define PRINTF(...) if(verbose)printf(__VA_ARGS__) + +//#define PROGRESS(s) fprintf(stderr, s) +#define PROGRESS(s) do { } while (0) + +#define USAGE_STRING "usage: wcapslip6 -s siodev [-B baudrate] [-a ipaddress[/prefixlen]|-p 64bit-prefix] [-c channel] [-r] [-v] " +#define HELP_STRING "usage: wcapslip6 -s siodev [-B baudrate] [-a ipaddress[/prefixlen]|-p 64bit-prefix] [-c channel] [-r] [-v] \r\n\n\ +Options:\r\n\ +-s siodev\tDevice that identifies the bridge.\r\n\ +-B baudrate\tBaudrate of the serial port (default:115200).\r\n\ +-a ipaddress/[prefixlen] The address to be assigned to the network\r\n\ +\t\tadapter.\r\n\ +-p 64bit-prefix\tAutomatic assignment of the IPv6 address from the specified\r\n\ +\t\tsubnet prefix. It may be followed by the prefix length\r\n\ +-c channel\t 802.15.4 radio channel.\r\n\ +-r\t\t Set sniffer mode. \r\n\ +-v\t\tVerbose. Print more infos.\r\n\ +\tMAC address of the local interface that will\r\n\ +\t\tbe used by wcapslip6.\r\n" + +#define REQUEST_MAC_TIMEOUT 3 + +typedef enum { + false = 0, + true = 1, +} bool; + +//char tundev[32] = { "tap0" }; +static const char *ipaddr = NULL; +static char *ipprefix = NULL; +static char autoconf_addr[40] = {0}; +static bool autoconf = false; +static bool verbose = false; +static bool tobecleaned = false; +static struct uip_eth_addr eth_addr; +static char * if_name; +OSVERSIONINFO osVersionInfo; + +static int request_mac = 1; +static int send_mac = 1; +static int set_sniffer_mode = 1; +static int set_channel = 1; + +static int sniffer_mode = 0; +static int channel = 0; + +static bool mac_received = false; + +int +ssystem(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2))); + +void addAddress(const char * ifname, const char * ipaddr); +void delAddress(const char * ifname, const char * ipaddr); + +int +ssystem(const char *fmt, ...) +{ + char cmd[128]; + va_list ap; + va_start(ap, fmt); + vsnprintf(cmd, sizeof(cmd), fmt, ap); + va_end(ap); + printf("%s\n", cmd); + fflush(stdout); + return system(cmd); +} + +int +execProcess(LPDWORD exitCode,const char *fmt, ...) +{ + char cmd[128]; + va_list ap; + va_start(ap, fmt); + vsnprintf(cmd, sizeof(cmd), fmt, ap); + va_end(ap); + printf("%s\n", cmd); + fflush(stdout); + //return system(cmd); + + STARTUPINFO si; + PROCESS_INFORMATION pi; + + + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + ZeroMemory( &pi, sizeof(pi) ); + + // Start the child process. + if( !CreateProcess( NULL, // No module name (use command line) + cmd, // Command line + NULL, // Process handle not inheritable + NULL, // Thread handle not inheritable + FALSE, // Set handle inheritance to FALSE + 0, // No creation flags + NULL, // Use parent's environment block + NULL, // Use parent's starting directory + &si, // Pointer to STARTUPINFO structure + &pi ) // Pointer to PROCESS_INFORMATION structure + ) + { + //printf( "CreateProcess failed (%d).\n", (int)GetLastError() ); + + return -1; + } + + // Wait until child process exits. + WaitForSingleObject( pi.hProcess, INFINITE ); + + if(exitCode!=NULL){ + GetExitCodeProcess(pi.hProcess,exitCode); + } + + // Close process and thread handles. + CloseHandle( pi.hProcess ); + CloseHandle( pi.hThread ); + + return 0; + +} + + + + +#define SLIP_END 0300 +#define SLIP_ESC 0333 +#define SLIP_ESC_END 0334 +#define SLIP_ESC_ESC 0335 + +/*static void +print_packet(u_int8_t *p, int len) { +int i; +for(i = 0; i < len; i++) { +printf("%02x", p[i]); +if ((i & 3) == 3) +printf(" "); +if ((i & 15) == 15) +printf("\n"); +} +printf("\n"); +}*/ + +int +is_sensible_string(const unsigned char *s, int len) +{ + int i; + for(i = 1; i < len; i++) { + if(s[i] == 0 || s[i] == '\r' || s[i] == '\n' || s[i] == '\t') { + continue; + } else if(s[i] < ' ' || '~' < s[i]) { + return 0; + } + } + return 1; +} + + +/* +* Read from serial, when we have a packet write it to tun. No output +* buffering, input buffered by stdio. +*/ +void +serial_to_wpcap(FILE *inslip) +{ + static union { + unsigned char inbuf[2000]; + } uip; + static int inbufptr = 0; + + int ret; + unsigned char c; + +#ifdef linux + ret = fread(&c, 1, 1, inslip); + if(ret == -1 || ret == 0) err(1, "serial_to_tun: read"); + goto after_fread; +#endif + +read_more: + if(inbufptr >= sizeof(uip.inbuf)) { + inbufptr = 0; + } + ret = fread(&c, 1, 1, inslip); +#ifdef linux +after_fread: +#endif + if(ret == -1) { + err(1, "serial_to_tun: read"); + } + if(ret == 0) { + clearerr(inslip); + return; + fprintf(stderr, "serial_to_tun: EOF\n"); + exit(1); + } + /* fprintf(stderr, ".");*/ + switch(c) { + case SLIP_END: + if(inbufptr > 0) { + if(uip.inbuf[0] == '!') { + if (uip.inbuf[1] == 'M' && inbufptr == 18) { + /* Read gateway MAC address and autoconfigure tap0 interface */ + char macs[24]; + int i, pos; + for(i = 0, pos = 0; i < 16; i++) { + macs[pos++] = uip.inbuf[2 + i]; + if ((i & 1) == 1 && i < 14) { + macs[pos++] = ':'; + } + } + macs[pos] = '\0'; + printf("*** Gateway's MAC address: %s\n", macs); + mac_received = true; + + + if(autoconf){ + + struct in6_addr ipv6addr; + struct uip_802154_longaddr dev_addr; + //DWORD exitCode = -1; + + { + + int addr_bytes[8]; // sscanf requires int instead of 8-bit for hexadecimal variables. + + sscanf(macs, "%2X:%2X:%2X:%2X:%2X:%2X:%2X:%2X", + &addr_bytes[0], + &addr_bytes[1], + &addr_bytes[2], + &addr_bytes[3], + &addr_bytes[4], + &addr_bytes[5], + &addr_bytes[6], + &addr_bytes[7]); + + for(i=0;i<8;i++){ + dev_addr.addr[i] = addr_bytes[i]; + } + } + + /*int i; + PRINTF("MAC:\n"); + for(i=0; i< 8; i++) + PRINTF("%02X ",dev_addr.addr[i]); + PRINTF("\n");*/ + + dev_addr.addr[0] |= 0x02; + + strtok(ipprefix,"/"); + + if(inet_pton(AF_INET6, ipprefix, &ipv6addr)!=1){ + printf("Invalid IPv6 address.\n"); + exit(1); + } + + // Copy modified EUI-64 to the last 64 bits of IPv6 address. + memcpy(&ipv6addr.s6_addr[8],&dev_addr,8); + + inet_ntop(AF_INET6,&ipv6addr,autoconf_addr,INET6_ADDRSTRLEN); // To string format. + + char * substr = strtok(NULL,"/"); + if(substr!=NULL){ // Add the prefix length. + strcat(autoconf_addr,"/"); + strcat(autoconf_addr,substr); + } + ipaddr = autoconf_addr; + + addAddress(if_name,ipaddr); + + + } + + } +#define DEBUG_LINE_MARKER '\r' + } + else if(uip.inbuf[0] == '?') { + if (uip.inbuf[1] == 'M') { + /* Send our MAC address. */ + + send_mac = 1; + set_sniffer_mode = 1; + set_channel = 1; + } + } + else if(uip.inbuf[0] == DEBUG_LINE_MARKER) { + fwrite(uip.inbuf + 1, inbufptr - 1, 1, stderr); + } + else if(is_sensible_string(uip.inbuf, inbufptr)) { + fwrite(uip.inbuf, inbufptr, 1, stderr); + } + else { + //PRINTF("Writing to tun len: %d\n", inbufptr); + /* print_packet(uip.inbuf, inbufptr);*/ + /*if(write(outfd, uip.inbuf, inbufptr) != inbufptr) { + err(1, "serial_to_tun: write"); + }*/ + + PRINTF("Sending to wpcap\n"); + /*print_packet(uip.inbuf, inbufptr);*/ + wpcap_send(uip.inbuf, inbufptr); + /* printf("After sending to wpcap\n");*/ + } + inbufptr = 0; + } + break; + + case SLIP_ESC: + if(fread(&c, 1, 1, inslip) != 1) { + clearerr(inslip); + /* Put ESC back and give up! */ + ungetc(SLIP_ESC, inslip); + return; + } + + switch(c) { + case SLIP_ESC_END: + c = SLIP_END; + break; + case SLIP_ESC_ESC: + c = SLIP_ESC; + break; + } + /* FALLTHROUGH */ + default: + uip.inbuf[inbufptr++] = c; + break; + } + + goto read_more; +} +/*---------------------------------------------------------------------------*/ +unsigned char slip_buf[2000]; +int slip_end, slip_begin; +/*---------------------------------------------------------------------------*/ + +void +slip_send(unsigned char c) +{ + if(slip_end >= sizeof(slip_buf)) { + err(1, "slip_send overflow"); + } + slip_buf[slip_end] = c; + slip_end++; +} +/*---------------------------------------------------------------------------*/ +int +slip_empty() +{ + return slip_end == 0; +} +/*---------------------------------------------------------------------------*/ +void +slip_flushbuf(int fd) +{ + int n; + + if (slip_empty()) + return; + + n = write(fd, slip_buf + slip_begin, (slip_end - slip_begin)); + + if(n == -1 && errno != EAGAIN) { + err(1, "slip_flushbuf write failed"); + } else if(n == -1) { + PROGRESS("Q"); /* Outqueueis full! */ + } else { + slip_begin += n; + if(slip_begin == slip_end) { + slip_begin = slip_end = 0; + } + } +} +/*---------------------------------------------------------------------------*/ +void +write_to_serial(void *inbuf, int len) +{ + u_int8_t *p = inbuf; + int i; /*, ecode;*/ + + /* printf("Got packet of length %d - write SLIP\n", len);*/ + /* print_packet(p, len);*/ + + /* It would be ``nice'' to send a SLIP_END here but it's not + * really necessary. + */ + /* slip_send(outfd, SLIP_END); */ + PRINTF("Writing to serial len: %d\n", len); + for(i = 0; i < len; i++) { + switch(p[i]) { + case SLIP_END: + slip_send(SLIP_ESC); + slip_send(SLIP_ESC_END); + break; + case SLIP_ESC: + slip_send(SLIP_ESC); + slip_send(SLIP_ESC_ESC); + break; + default: + slip_send(p[i]); + break; + } + + } + slip_send(SLIP_END); + PROGRESS("t"); +} +/*---------------------------------------------------------------------------*/ + +/* +* Read from tun, write to slip. +*/ +#if 0 +void +tun_to_serial(int infd, int outfd) +{ + struct { + unsigned char inbuf[2000]; + } uip; + int size; + + if((size = read(infd, uip.inbuf, 2000)) == -1) { + err(1, "tun_to_serial: read"); + } + + write_to_serial(uip.inbuf, size); +} +#endif /* 0 */ +/*---------------------------------------------------------------------------*/ +#ifndef BAUDRATE +#define BAUDRATE B115200 +#endif +speed_t b_rate = BAUDRATE; + +void +stty_telos(int fd) +{ + struct termios tty; + speed_t speed = b_rate; + int i; + + if(tcflush(fd, TCIOFLUSH) == -1) err(1, "tcflush"); + + if(tcgetattr(fd, &tty) == -1) err(1, "tcgetattr"); + + cfmakeraw(&tty); + + /* Nonblocking read. */ + tty.c_cc[VTIME] = 0; + tty.c_cc[VMIN] = 0; + tty.c_cflag &= ~CRTSCTS; + tty.c_cflag &= ~HUPCL; + tty.c_cflag &= ~CLOCAL; + + cfsetispeed(&tty, speed); + cfsetospeed(&tty, speed); + + if(tcsetattr(fd, TCSAFLUSH, &tty) == -1) err(1, "tcsetattr"); + +#if 1 + /* Nonblocking read and write. */ + /* if(fcntl(fd, F_SETFL, O_NONBLOCK) == -1) err(1, "fcntl"); */ + + tty.c_cflag |= CLOCAL; + if(tcsetattr(fd, TCSAFLUSH, &tty) == -1) err(1, "tcsetattr"); + + i = TIOCM_DTR; + if(ioctl(fd, TIOCMBIS, &i) == -1) err(1, "ioctl"); +#endif + + usleep(10*1000); /* Wait for hardware 10ms. */ + + /* Flush input and output buffers. */ + if(tcflush(fd, TCIOFLUSH) == -1) err(1, "tcflush"); +} + +int +devopen(const char *dev, int flags) +{ + char t[32]; + strcpy(t, "/dev/"); + strcat(t, dev); + return open(t, flags); +} + +#ifdef linux +#include +#include + +int +tun_alloc(char *dev) +{ + struct ifreq ifr; + int fd, err; + + if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) + return -1; + + memset(&ifr, 0, sizeof(ifr)); + + /* Flags: IFF_TUN - TUN device (no Ethernet headers) + * IFF_TAP - TAP device + * + * IFF_NO_PI - Do not provide packet information + */ + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + if(*dev != 0) + strncpy(ifr.ifr_name, dev, IFNAMSIZ); + + if((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){ + close(fd); + return err; + } + strcpy(dev, ifr.ifr_name); + return fd; +} +#else +int +tun_alloc(char *dev) +{ + return devopen(dev, O_RDWR); +} +#endif + +//const char *netmask; + +void +cleanup(void) +{ + wpcap_exit(); + if(tobecleaned){ + delAddress(if_name,ipaddr); + } +} + +void +sigcleanup(int signo) +{ + fprintf(stderr, "signal %d\n", signo); + exit(0); /* exit(0) will call cleanup() */ +} + +void +sigalarm(int signo) +{ + if(!mac_received){ + fprintf(stderr, "Bridge not found!\n"); + exit(2); + } +} + + +void send_commands(void) +{ + char buf[3]; + + if (request_mac) { + slip_send('?'); + slip_send('M'); + slip_send(SLIP_END); + + request_mac = 0; + alarm(REQUEST_MAC_TIMEOUT); + } + /* Send our mac to the device. If it knows our address, it is not needed to change + the MAC address of our local interface (this can be also unsupported, especially under + Windows). + */ + else if(send_mac && slip_empty()){ + short i; + PRINTF("Sending our MAC.\n"); + + slip_send('!'); + slip_send('M'); + + for(i=0; i < 6; i++){ + sprintf(buf,"%02X",eth_addr.addr[i]); + slip_send(buf[0]); + slip_send(buf[1]); + } + slip_send(SLIP_END); + + send_mac = 0; + } + else if(set_sniffer_mode && slip_empty()){ + + PRINTF("Setting sniffer mode to %d.\n", sniffer_mode); + + slip_send('!'); + slip_send('O'); + slip_send('S'); + + if(sniffer_mode){ + slip_send('1'); + } + else { + slip_send('0'); + } + slip_send(SLIP_END); + + set_sniffer_mode = 0; + + } + else if(set_channel && slip_empty()){ + + if(channel != 0){ + PRINTF("Setting channel %02d.\n", channel); + + slip_send('!'); + slip_send('O'); + slip_send('C'); + + sprintf(buf,"%02d",channel); + slip_send(buf[0]); + slip_send(buf[1]); + + slip_send(SLIP_END); + } + + set_channel = 0; + + } +} + +void addAddress(const char * ifname, const char * ipaddr) +{ + DWORD exitCode = -1; + + if(osVersionInfo.dwMajorVersion < 6){ // < Windows Vista (i.e., Windows XP; check if this command is ok for Windows Server 2003 too). + char * substr; + char tmpaddr[44]; + + strncpy(tmpaddr,ipaddr,sizeof(tmpaddr)); + + strtok(tmpaddr,"/"); // Remove possible prefix length. + execProcess(&exitCode,"netsh interface ipv6 add address \"%s\" %s",if_name,tmpaddr); + substr = strtok(NULL,"/"); + if(substr == NULL){ // A prefix length is not specified. + // Use a 64 bit prefix + strcat(tmpaddr,"/64"); + execProcess(NULL,"netsh interface ipv6 add route %s \"%s\"",tmpaddr,if_name); + } + else { + execProcess(NULL,"netsh interface ipv6 add route %s \"%s\"",ipaddr,if_name); + } + + } + else{ + execProcess(&exitCode,"netsh interface ipv6 add address \"%s\" %s",if_name,ipaddr); + } + if(exitCode==0) + tobecleaned = true; +} + +void delAddress(const char * ifname, const char * ipaddr) +{ + char tmpaddr[42]; + + strncpy(tmpaddr,ipaddr,sizeof(tmpaddr)); + strtok(tmpaddr,"/"); // Remove possible prefix length. + + if(osVersionInfo.dwMajorVersion < 6){ // < Windows Vista (i.e., Windows XP; check if this command is ok for Windows Server 2003 too). + char * substr; + + execProcess(NULL,"netsh interface ipv6 delete address \"%s\" %s",if_name,tmpaddr); + substr = strtok(NULL,"/"); + if(substr == NULL){ // A prefix length is not specified. + // Use a 64 bit prefix + strcat(tmpaddr,"/64"); + execProcess(NULL,"netsh interface ipv6 delete route %s \"%s\"",tmpaddr,if_name); + } + else { + execProcess(NULL,"netsh interface ipv6 delete route %s \"%s\"",ipaddr,if_name); + } + + } + else{ + strtok(tmpaddr,"/"); // Remove possible prefix length. + execProcess(NULL,"netsh interface ipv6 delete address \"%s\" %s",if_name,tmpaddr); + } + +} + +int +main(int argc, char **argv) +{ + int c; + int slipfd, maxfd; + int ret; + fd_set rset, wset; + FILE *inslip; + char siodev[10] = ""; + int baudrate = -2; + + char buf[4000]; + + setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */ + + memset(&osVersionInfo,0,sizeof(OSVERSIONINFO)); + osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osVersionInfo); + + while((c = getopt(argc, argv, "B:D:hs:c:ra:p:v")) != -1) { + switch (c) { + case 'B': + baudrate = atoi(optarg); + break; + + case 's': + if(strncmp("/dev/", optarg, 5) == 0) { + strncpy(siodev,optarg + 5,sizeof(siodev)-1); + } + else if(strncmp("COM", optarg, 3) == 0) { + + int portnum; + + portnum = atoi(optarg+3); + + if(portnum == 0){ + err(1,"port number is invalid"); + } + sprintf(siodev,"ttyS%d",portnum-1); + + /*int i = 0; + + while(optarg[i] && i < sizeof(siodev) - 1){ + siodev[i] = tolower((int)optarg[i]); + i++; + } + siodev[i] = '\0';*/ + } + else { + strncpy(siodev,optarg,sizeof(siodev)-1); + } + break; + + case 'c': + channel = atoi(optarg); + set_channel = 1; + break; + case 'r': + sniffer_mode = 1; + break; + + case 'a': + if(autoconf == true){ + errx(1, USAGE_STRING); + } + ipaddr = optarg; + break; + + case 'p': + if(ipaddr !=NULL){ + errx(1, USAGE_STRING); + } + autoconf = true; + ipprefix = optarg; + break; + + case 'v': + verbose = true; + break; + + case '?': + case 'h': + default: + errx(1,HELP_STRING); + break; + } + } + argc -= (optind - 1); + argv += (optind - 1); + + if(argc != 2 || *siodev == '\0') { + errx(1, USAGE_STRING); + } + + sscanf(argv[1],"%2X-%2X-%2X-%2X-%2X-%2X", + (int *)ð_addr.addr[0],(int *)ð_addr.addr[1],(int *)ð_addr.addr[2],(int *)ð_addr.addr[3],(int *)ð_addr.addr[4],(int *)ð_addr.addr[5]); + if_name = wpcap_start(ð_addr, verbose); + + + if(ipaddr!=NULL){ + addAddress(if_name, ipaddr); + } + + + switch(baudrate) { + case -2: + break; /* Use default. */ + case 9600: + b_rate = B9600; + break; + case 19200: + b_rate = B19200; + break; + case 38400: + b_rate = B38400; + break; + case 57600: + b_rate = B57600; + break; + case 115200: + b_rate = B115200; + break; + default: + err(1, "unknown baudrate %d", baudrate); + break; + } + + + //if(siodev != NULL) { + slipfd = devopen(siodev, O_RDWR | O_NONBLOCK | O_NOCTTY | O_NDELAY | O_DIRECT | O_SYNC ); + if(slipfd == -1) { + err(1, "can't open siodev ``/dev/%s''", siodev); + } + /*} else { + + err(1, "can't open siodev"); + }*/ + fprintf(stderr, "slip started on ``/dev/%s''\n", siodev); + stty_telos(slipfd); + slip_send(SLIP_END); + inslip = fdopen(slipfd, "r"); + if(inslip == NULL) err(1, "main: fdopen"); + + + atexit(cleanup); + signal(SIGHUP, sigcleanup); + signal(SIGTERM, sigcleanup); + signal(SIGINT, sigcleanup); + signal(SIGALRM, sigalarm); + + /* Request mac address from gateway. It may be useful for setting the best + IPv6 address of the local interface. */ + + + while(1) { + maxfd = 0; + FD_ZERO(&rset); + FD_ZERO(&wset); + + send_commands(); + + if(!slip_empty()) { /* Anything to flush? */ + FD_SET(slipfd, &wset); + } + + FD_SET(slipfd, &rset); /* Read from slip ASAP! */ + if(slipfd > maxfd) maxfd = slipfd; +#ifdef WITH_STDIN + FD_SET(STDIN_FILENO, &rset); /* Read from stdin too. */ + if(STDIN_FILENO > maxfd) maxfd = STDIN_FILENO; /* This would not be necessary, since we know STDIN_FILENO is 0. */ +#endif + + if(slip_empty()) { + char *pbuf = buf; + + ret = wpcap_poll(pbuf); + if( ret > 0 ){ + struct uip_eth_hdr * eth_hdr = (struct uip_eth_hdr *)pbuf; + + if(eth_hdr->type == htons(UIP_ETHTYPE_IPV6)){ + // We forward only IPv6 packet. + write_to_serial(pbuf, ret); + /*print_packet(pbuf, ret);*/ + slip_flushbuf(slipfd); + } + } + } + { + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 10; + ret = select(maxfd + 1, &rset, &wset, NULL, &tv); + } + if(ret == -1 && errno != EINTR) { + err(1, "select"); + } + else if(ret > 0) { + if(FD_ISSET(slipfd, &rset)) { + /* printf("serial_to_wpcap\n"); */ + /*serial_to_tun(inslip, tunfd);*/ + serial_to_wpcap(inslip); + /* printf("End of serial_to_wpcap\n");*/ + } + + if(FD_ISSET(slipfd, &wset)) { + slip_flushbuf(slipfd); + } +#ifdef WITH_STDIN + if(FD_ISSET(STDIN_FILENO, &rset)) { + char inbuf; + if(fread(&inbuf,1,1,stdin)){ + if(inbuf=='q'){ + exit(0); + } + } + } +#endif + } + } +} diff --git a/tools/stm32w/wpcapslip6/wpcapslip6.exe b/tools/stm32w/wpcapslip6/wpcapslip6.exe new file mode 100644 index 000000000..ddd618111 Binary files /dev/null and b/tools/stm32w/wpcapslip6/wpcapslip6.exe differ