Added tools for STM32W.
This commit is contained in:
parent
ec5e3ce0d7
commit
5d8636d1f8
22
tools/stm32w/stm32w_flasher/linux/README
Normal file
22
tools/stm32w/stm32w_flasher/linux/README
Normal file
|
@ -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.
|
||||||
|
|
BIN
tools/stm32w/stm32w_flasher/linux/stm32w_flasher
Normal file
BIN
tools/stm32w/stm32w_flasher/linux/stm32w_flasher
Normal file
Binary file not shown.
BIN
tools/stm32w/stm32w_flasher/win/FTD2XX.dll
Normal file
BIN
tools/stm32w/stm32w_flasher/win/FTD2XX.dll
Normal file
Binary file not shown.
BIN
tools/stm32w/stm32w_flasher/win/JlinkARM.DLL
Normal file
BIN
tools/stm32w/stm32w_flasher/win/JlinkARM.DLL
Normal file
Binary file not shown.
BIN
tools/stm32w/stm32w_flasher/win/_ctypes.pyd
Normal file
BIN
tools/stm32w/stm32w_flasher/win/_ctypes.pyd
Normal file
Binary file not shown.
BIN
tools/stm32w/stm32w_flasher/win/_socket.pyd
Normal file
BIN
tools/stm32w/stm32w_flasher/win/_socket.pyd
Normal file
Binary file not shown.
BIN
tools/stm32w/stm32w_flasher/win/_ssl.pyd
Normal file
BIN
tools/stm32w/stm32w_flasher/win/_ssl.pyd
Normal file
Binary file not shown.
BIN
tools/stm32w/stm32w_flasher/win/bz2.pyd
Normal file
BIN
tools/stm32w/stm32w_flasher/win/bz2.pyd
Normal file
Binary file not shown.
BIN
tools/stm32w/stm32w_flasher/win/d2xx._d2xx.pyd
Normal file
BIN
tools/stm32w/stm32w_flasher/win/d2xx._d2xx.pyd
Normal file
Binary file not shown.
BIN
tools/stm32w/stm32w_flasher/win/python26.dll
Normal file
BIN
tools/stm32w/stm32w_flasher/win/python26.dll
Normal file
Binary file not shown.
BIN
tools/stm32w/stm32w_flasher/win/pywintypes26.dll
Normal file
BIN
tools/stm32w/stm32w_flasher/win/pywintypes26.dll
Normal file
Binary file not shown.
BIN
tools/stm32w/stm32w_flasher/win/select.pyd
Normal file
BIN
tools/stm32w/stm32w_flasher/win/select.pyd
Normal file
Binary file not shown.
BIN
tools/stm32w/stm32w_flasher/win/stm32w_flasher.exe
Normal file
BIN
tools/stm32w/stm32w_flasher/win/stm32w_flasher.exe
Normal file
Binary file not shown.
BIN
tools/stm32w/stm32w_flasher/win/unicodedata.pyd
Normal file
BIN
tools/stm32w/stm32w_flasher/win/unicodedata.pyd
Normal file
Binary file not shown.
BIN
tools/stm32w/stm32w_flasher/win/w9xpopen.exe
Normal file
BIN
tools/stm32w/stm32w_flasher/win/w9xpopen.exe
Normal file
Binary file not shown.
BIN
tools/stm32w/stm32w_flasher/win/win32api.pyd
Normal file
BIN
tools/stm32w/stm32w_flasher/win/win32api.pyd
Normal file
Binary file not shown.
818
tools/stm32w/tapslip6.c
Normal file
818
tools/stm32w/tapslip6.c
Normal file
|
@ -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 <salvopitru@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
|
||||||
|
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 <linux/if.h>
|
||||||
|
#include <linux/if_tun.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
tools/stm32w/uip6_bridge/Makefile
Normal file
21
tools/stm32w/uip6_bridge/Makefile
Normal file
|
@ -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
|
27
tools/stm32w/uip6_bridge/README
Normal file
27
tools/stm32w/uip6_bridge/README
Normal file
|
@ -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.
|
65
tools/stm32w/uip6_bridge/bridge-conf.h
Normal file
65
tools/stm32w/uip6_bridge/bridge-conf.h
Normal file
|
@ -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 <nfi@sics.se>
|
||||||
|
* Joakim Eriksson <joakime@sics.se>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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__ */
|
501
tools/stm32w/uip6_bridge/dev/slip.c
Normal file
501
tools/stm32w/uip6_bridge/dev/slip.c
Normal file
|
@ -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 <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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 <stdlib.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
93
tools/stm32w/uip6_bridge/dev/slip.h
Normal file
93
tools/stm32w/uip6_bridge/dev/slip.h
Normal file
|
@ -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__ */
|
129
tools/stm32w/uip6_bridge/fakeuip.c
Normal file
129
tools/stm32w/uip6_bridge/fakeuip.c
Normal file
|
@ -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 <string.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
5
tools/stm32w/uip6_bridge/rtimer-arch.h
Normal file
5
tools/stm32w/uip6_bridge/rtimer-arch.h
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#ifndef __RTIMER_ARCH_H__
|
||||||
|
#define __RTIMER_ARCH_H__
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __RTIMER_ARCH_H__ */
|
980
tools/stm32w/uip6_bridge/sicslow_ethernet.c
Normal file
980
tools/stm32w/uip6_bridge/sicslow_ethernet.c
Normal file
|
@ -0,0 +1,980 @@
|
||||||
|
/**
|
||||||
|
* \file sicslow_ethernet.c
|
||||||
|
* Routines to interface between Ethernet and 6LowPan
|
||||||
|
*
|
||||||
|
* \author
|
||||||
|
* Colin O'Flynn <coflynn@newae.com>
|
||||||
|
*
|
||||||
|
* \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 <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
//#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
|
||||||
|
/** @} */
|
||||||
|
/** @} */
|
80
tools/stm32w/uip6_bridge/sicslow_ethernet.h
Normal file
80
tools/stm32w/uip6_bridge/sicslow_ethernet.h
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/**
|
||||||
|
* \file sicslow_ethernet.c
|
||||||
|
* Routines to interface between Ethernet and 6LowPan
|
||||||
|
*
|
||||||
|
* \author
|
||||||
|
* Colin O'Flynn <coflynn@newae.com>
|
||||||
|
*
|
||||||
|
* \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
|
173
tools/stm32w/uip6_bridge/uip6-bridge-tap.c
Normal file
173
tools/stm32w/uip6_bridge/uip6-bridge-tap.c
Normal file
|
@ -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 <nfi@sics.se>
|
||||||
|
* Joakim Eriksson <joakime@sics.se>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "contiki.h"
|
||||||
|
#include "net/uip.h"
|
||||||
|
#include "dev/slip.h"
|
||||||
|
#include "dev/leds.h"
|
||||||
|
#include "sicslow_ethernet.h"
|
||||||
|
|
||||||
|
#include "net/packetbuf.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
24
tools/stm32w/wpcapslip6/Makefile
Normal file
24
tools/stm32w/wpcapslip6/Makefile
Normal file
|
@ -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 $@
|
7
tools/stm32w/wpcapslip6/README.txt
Normal file
7
tools/stm32w/wpcapslip6/README.txt
Normal file
|
@ -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
|
18
tools/stm32w/wpcapslip6/contiki-conf.h
Normal file
18
tools/stm32w/wpcapslip6/contiki-conf.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef __CONTIKI_CONF_H__
|
||||||
|
#define __CONTIKI_CONF_H__
|
||||||
|
#include <stdint.h>
|
||||||
|
#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__ */
|
3
tools/stm32w/wpcapslip6/showhiddendevices.bat
Normal file
3
tools/stm32w/wpcapslip6/showhiddendevices.bat
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
set devmgr_show_nonpresent_devices=1
|
||||||
|
|
||||||
|
start devmgmt.msc
|
300
tools/stm32w/wpcapslip6/wpcap6.c
Normal file
300
tools/stm32w/wpcapslip6/wpcap6.c
Normal file
|
@ -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 <ol.sc@web.de>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* Functions needed by the Windows application for uip6-bridge.
|
||||||
|
* Thanks to Oliver Schmidt for the original code.
|
||||||
|
* \author
|
||||||
|
* Salvatore Pitrulli <salvopitru@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#define _WIN32_WINNT 0x0501
|
||||||
|
#include <windows.h>
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <iphlpapi.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
#include <alloca.h>
|
||||||
|
#else /* __CYGWIN__ */
|
||||||
|
#include <malloc.h>
|
||||||
|
#endif /* __CYGWIN__ */
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
991
tools/stm32w/wpcapslip6/wpcapslip6.c
Normal file
991
tools/stm32w/wpcapslip6/wpcapslip6.c
Normal file
|
@ -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 <salvopitru@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
#include <alloca.h>
|
||||||
|
#else /* __CYGWIN__ */
|
||||||
|
#include <malloc.h>
|
||||||
|
#endif /* __CYGWIN__ */
|
||||||
|
#include <signal.h>
|
||||||
|
//#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
//#include <termios.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <err.h>
|
||||||
|
|
||||||
|
//#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
|
||||||
|
//#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] <local interface mac address>"
|
||||||
|
#define HELP_STRING "usage: wcapslip6 -s siodev [-B baudrate] [-a ipaddress[/prefixlen]|-p 64bit-prefix] [-c channel] [-r] [-v] <local interface mac address>\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\
|
||||||
|
<local interface mac address>\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 <linux/if.h>
|
||||||
|
#include <linux/if_tun.h>
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
BIN
tools/stm32w/wpcapslip6/wpcapslip6.exe
Normal file
BIN
tools/stm32w/wpcapslip6/wpcapslip6.exe
Normal file
Binary file not shown.
Loading…
Reference in a new issue