Added tools for STM32W.

This commit is contained in:
salvopitru 2010-10-25 10:42:40 +00:00
parent ec5e3ce0d7
commit 5d8636d1f8
34 changed files with 4257 additions and 0 deletions

View 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.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

818
tools/stm32w/tapslip6.c Normal file
View 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(&eth_addr, &dev_addr, 3);
memcpy(&eth_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(&eth_addr, &eth_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(&eth_addr, &eth_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);
}
}
}
}

View 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

View 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.

View 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__ */

View 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,&eth_addr_null,6)==0){
slip_write("?M", 2);
ctimer_set(&t, 6*CLOCK_SECOND, request_mac, NULL);
}
}
/*---------------------------------------------------------------------------*/

View 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__ */

View 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);
}

View file

@ -0,0 +1,5 @@
#ifndef __RTIMER_ARCH_H__
#define __RTIMER_ARCH_H__
#endif /* __RTIMER_ARCH_H__ */

View 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 = &ETHBUF(uip_buf)->src;
eth_dest = &ETHBUF(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
/** @} */
/** @} */

View 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

View 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
}
/*---------------------------------------------------------------------------*/

View 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 $@

View 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

View 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__ */

View file

@ -0,0 +1,3 @@
set devmgr_show_nonpresent_devices=1
start devmgmt.msc

View 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,&eth_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);
}
/*---------------------------------------------------------------------------*/

View 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 *)&eth_addr.addr[0],(int *)&eth_addr.addr[1],(int *)&eth_addr.addr[2],(int *)&eth_addr.addr[3],(int *)&eth_addr.addr[4],(int *)&eth_addr.addr[5]);
if_name = wpcap_start(&eth_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
}
}
}

Binary file not shown.