From 8e0bcaee5054cd386eed6215491fba5b83f4bb52 Mon Sep 17 00:00:00 2001 From: salvopitru Date: Mon, 17 Jan 2011 09:16:55 +0000 Subject: [PATCH] Added new options that make wpcapslip6 work also with the rpl-border-router. --- tools/stm32w/wpcapslip6/README.txt | 16 +- tools/stm32w/wpcapslip6/wpcapslip6.c | 504 ++++++++++++++++--------- tools/stm32w/wpcapslip6/wpcapslip6.exe | Bin 40356 -> 43214 bytes 3 files changed, 341 insertions(+), 179 deletions(-) diff --git a/tools/stm32w/wpcapslip6/README.txt b/tools/stm32w/wpcapslip6/README.txt index 4d9eec9c3..7dab62e80 100644 --- a/tools/stm32w/wpcapslip6/README.txt +++ b/tools/stm32w/wpcapslip6/README.txt @@ -1,7 +1,19 @@ This software needs a working network adapter. You can install a Microsoft Loopback adapter. -(Windows XP users: remeber to reboot after the installation procedure). +(remeber to reboot after the installation procedure). In order to install this kind of device in Windows 7, use devcon utility (you can download it from Microsoft website). -> devcon.exe install %windir%\inf\netloop.inf *msloop \ No newline at end of file +> devcon.exe install %windir%\inf\netloop.inf *msloop + + +This utility can be used in conjunction with the uip6-bridge or the rpl-border-router +(the latter on Windows Vista and later only). + + +An example of usage with the RPL border router: +wpcapslip6 -s COMXX -b aaaa:: -a aaaa:1::1/128 02-00-00-00-00-01 + +where 02-00-00-00-00-01 is the MAC address of the local network adapter. +-a aaaa:1::1/128 can be omitted if an IP address is already set +to the network adapter. diff --git a/tools/stm32w/wpcapslip6/wpcapslip6.c b/tools/stm32w/wpcapslip6/wpcapslip6.c index cf2da4717..3b10ac1bc 100644 --- a/tools/stm32w/wpcapslip6/wpcapslip6.c +++ b/tools/stm32w/wpcapslip6/wpcapslip6.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2001, Adam Dunkels. * Copyright (c) 2009, Joakim Eriksson, Niclas Finne. +* Copyright (c) 2011, STMicroelectronics. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +30,7 @@ * * This file is part of the uIP TCP/IP stack. * -* $Id: wpcapslip6.c,v 1.1 2010/10/25 10:42:41 salvopitru Exp $ +* $Id: wpcapslip6.c,v 1.2 2011/01/17 09:16:55 salvopitru Exp $ */ /** @@ -93,21 +94,6 @@ void write_to_serial(void *inbuf, int len); //#define PROGRESS(s) fprintf(stderr, s) #define PROGRESS(s) do { } while (0) -#define USAGE_STRING "usage: wcapslip6 -s siodev [-B baudrate] [-a ipaddress[/prefixlen]|-p 64bit-prefix] [-c channel] [-r] [-v] " -#define HELP_STRING "usage: wcapslip6 -s siodev [-B baudrate] [-a ipaddress[/prefixlen]|-p 64bit-prefix] [-c channel] [-r] [-v] \r\n\n\ -Options:\r\n\ --s siodev\tDevice that identifies the bridge.\r\n\ --B baudrate\tBaudrate of the serial port (default:115200).\r\n\ --a ipaddress/[prefixlen] The address to be assigned to the network\r\n\ -\t\tadapter.\r\n\ --p 64bit-prefix\tAutomatic assignment of the IPv6 address from the specified\r\n\ -\t\tsubnet prefix. It may be followed by the prefix length\r\n\ --c channel\t 802.15.4 radio channel.\r\n\ --r\t\t Set sniffer mode. \r\n\ --v\t\tVerbose. Print more infos.\r\n\ -\tMAC address of the local interface that will\r\n\ -\t\tbe used by wcapslip6.\r\n" - #define REQUEST_MAC_TIMEOUT 3 typedef enum { @@ -115,21 +101,35 @@ typedef enum { true = 1, } bool; -//char tundev[32] = { "tap0" }; -static const char *ipaddr = NULL; +const char *prog; +/* Local adapter IP address. */ +static const char *local_ipaddr = NULL; +/* Attached device's IP address. */ +static char rem_ipaddr[INET6_ADDRSTRLEN]; static char *ipprefix = NULL; -static char autoconf_addr[40] = {0}; +static char autoconf_addr[INET6_ADDRSTRLEN] = {0}; static bool autoconf = false; static bool verbose = false; -static bool tobecleaned = false; -static struct uip_eth_addr eth_addr; +static bool tun = false; +static bool clean_addr = false; +static bool clean_route = false; +static bool clean_neighb = false; +static struct uip_eth_addr adapter_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; +/* Fictitious Ethernet address of the attached device (used in tun mode). */ +#define DEV_MAC_ADDR "02-00-00-00-00-02" +static const struct uip_eth_addr dev_eth_addr = {{0x02,0x00,0x00,0x00,0x00,0x02}}; + + +static bool request_mac = true; +static bool send_mac = true; +static bool set_sniffer_mode = true; +static bool set_channel = true; +static bool send_prefix = false; +/* Network prefix for border router. */ +const char * br_prefix = NULL; static int sniffer_mode = 0; static int channel = 0; @@ -141,6 +141,37 @@ 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); +void addLoWPANRoute(const char * ifname, const char * net, const char * gw); +void delLoWPANRoute(const char * ifname, const char * net); +void addNeighbor(const char * ifname, const char * neighb, const char * neighb_mac); +void delNeighbor(const char * ifname, const char * neighb); +int IPAddrFromPrefix(char * ipaddr, const char * ipprefix, const char * mac); + +void print_help() +{ + fprintf(stderr, "usage: %s -s siodev [options] \r\n\n", prog); + fprintf(stderr, "Options:\r\n"); + fprintf(stderr, "-s siodev\tDevice that identifies the bridge or the boder router.\r\n"); + fprintf(stderr, "-B baudrate\tBaudrate of the serial port (default:115200).\r\n"); + fprintf(stderr, " One between:\n"); + fprintf(stderr, " -a ipaddress/[prefixlen] The address to be assigned to the local interface.\r\n"); + fprintf(stderr, "\t\tadapter.\r\n"); + fprintf(stderr, " -p 64bit-prefix Automatic assignment of the IPv6 address from the specified\r\n"); + fprintf(stderr, "\t\tsubnet prefix, based on bridge's MAC address. It may be\r\n"); + fprintf(stderr, "\t\tfollowed by the prefix length.\r\n"); + fprintf(stderr, "\t\tNot allowed in Border Router mode.\r\n"); + fprintf(stderr, "-c channel\t802.15.4 radio channel.\r\n"); + //fprintf(stderr, "-r\t\tSet sniffer mode. \r\n"); + fprintf(stderr, "-t\t\tUse tun interface, i.e., send bare IP packets to device.\r\n"); + fprintf(stderr, "-b 64bit-prefix\tAttached device is an RPL Border Router (-t option forced).\r\n"); + fprintf(stderr, "\t\t64bit-prefix is the prefix the border router has to announce.\r\n"); + fprintf(stderr, "-v\t\tVerbose. Print more info.\r\n"); + fprintf(stderr, "-h\t\tShow this help.\r\n"); + fprintf(stderr, "\r\n\tMAC address of the local interface that will\r\n"); + fprintf(stderr, "\t\tbe used by wcapslip6.\r\n"); + + exit(0); +} int ssystem(const char *fmt, ...) @@ -218,15 +249,16 @@ execProcess(LPDWORD exitCode,const char *fmt, ...) /*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 i; + printf("\n"); + for(i = 0; i < len; i++) { + printf("%02x", p[i]); + if ((i & 3) == 3) + printf(" "); + if ((i & 15) == 15) + printf("\n"); + } + printf("\n"); }*/ int @@ -248,31 +280,35 @@ is_sensible_string(const unsigned char *s, int len) * Read from serial, when we have a packet write it to tun. No output * buffering, input buffered by stdio. */ + +#define BUF_SIZE 2000 + void serial_to_wpcap(FILE *inslip) { - static union { - unsigned char inbuf[2000]; - } uip; - static int inbufptr = 0; + unsigned char buf[BUF_SIZE]; - int ret; + 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 + unsigned char * inpktbuf; + + if(tun){ + inpktbuf = buf + sizeof(struct uip_eth_hdr); + } + else { + inpktbuf = buf; + } + + read_more: - if(inbufptr >= sizeof(uip.inbuf)) { + if(inbufptr >= BUF_SIZE) { inbufptr = 0; } ret = fread(&c, 1, 1, inslip); -#ifdef linux -after_fread: -#endif + if(ret == -1) { err(1, "serial_to_tun: read"); } @@ -286,13 +322,13 @@ after_fread: switch(c) { case SLIP_END: if(inbufptr > 0) { - if(uip.inbuf[0] == '!') { - if (uip.inbuf[1] == 'M' && inbufptr == 18) { + if(inpktbuf[0] == '!') { + if (inpktbuf[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]; + macs[pos++] = inpktbuf[2 + i]; if ((i & 1) == 1 && i < 14) { macs[pos++] = ':'; } @@ -304,89 +340,66 @@ after_fread: 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"); + if(IPAddrFromPrefix(autoconf_addr, ipprefix, macs)!=0){ + fprintf(stderr, "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); + } + local_ipaddr = autoconf_addr; + addAddress(if_name,local_ipaddr); - - } + } + if(br_prefix != NULL){ + /* RPL Border Router mode. Add route towards LoWPAN. */ + + if(IPAddrFromPrefix(rem_ipaddr, br_prefix, macs)!=0){ + fprintf(stderr, "Invalid IPv6 address.\n"); + exit(1); + } + + addLoWPANRoute(if_name, br_prefix, rem_ipaddr); + addNeighbor(if_name, rem_ipaddr, DEV_MAC_ADDR); + } } #define DEBUG_LINE_MARKER '\r' } - else if(uip.inbuf[0] == '?') { - if (uip.inbuf[1] == 'M') { + else if(inpktbuf[0] == '?') { + if (inpktbuf[1] == 'M') { /* Send our MAC address. */ - send_mac = 1; - set_sniffer_mode = 1; - set_channel = 1; + send_mac = true; + set_sniffer_mode = true; + set_channel = true; + } + else if (inpktbuf[1] == 'P') { + /* Send LoWPAN network prefix to the border router. */ + send_prefix = true; } } - else if(uip.inbuf[0] == DEBUG_LINE_MARKER) { - fwrite(uip.inbuf + 1, inbufptr - 1, 1, stderr); + else if(inpktbuf[0] == DEBUG_LINE_MARKER) { + fwrite(inpktbuf + 1, inbufptr - 1, 1, stderr); } - else if(is_sensible_string(uip.inbuf, inbufptr)) { - fwrite(uip.inbuf, inbufptr, 1, stderr); + else if(is_sensible_string(inpktbuf, inbufptr)) { + fwrite(inpktbuf, 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("Sending to wpcap\n"); + + if(tun){ + + //Ethernet header to be inserted before IP packet + struct uip_eth_hdr * eth_hdr = (struct uip_eth_hdr *)buf; + + memcpy(ð_hdr->dest, &adapter_eth_addr, sizeof(struct uip_eth_addr)); + memcpy(ð_hdr->src, &dev_eth_addr, sizeof(struct uip_eth_addr)); + + eth_hdr->type = htons(UIP_ETHTYPE_IPV6); + inbufptr += sizeof(struct uip_eth_hdr); + } + //print_packet(inpktbuf, inbufptr); + + wpcap_send(buf, inbufptr); /* printf("After sending to wpcap\n");*/ } inbufptr = 0; @@ -411,7 +424,7 @@ after_fread: } /* FALLTHROUGH */ default: - uip.inbuf[inbufptr++] = c; + inpktbuf[inbufptr++] = c; break; } @@ -432,6 +445,24 @@ slip_send(unsigned char c) slip_end++; } /*---------------------------------------------------------------------------*/ +void +slip_send_char(unsigned char c) +{ + switch(c) { + 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(c); + break; + } +} +/*---------------------------------------------------------------------------*/ int slip_empty() { @@ -494,27 +525,6 @@ write_to_serial(void *inbuf, int len) 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 @@ -616,9 +626,15 @@ void cleanup(void) { wpcap_exit(); - if(tobecleaned){ - delAddress(if_name,ipaddr); + if(clean_addr){ + delAddress(if_name,local_ipaddr); } + if(clean_route){ + delLoWPANRoute(if_name,br_prefix); + } + if(clean_neighb){ + delNeighbor(if_name, rem_ipaddr); + } } void @@ -632,7 +648,7 @@ void sigalarm(int signo) { if(!mac_received){ - fprintf(stderr, "Bridge not found!\n"); + fprintf(stderr, "Bridge/Router not found!\n"); exit(2); } } @@ -662,13 +678,13 @@ void send_commands(void) slip_send('M'); for(i=0; i < 6; i++){ - sprintf(buf,"%02X",eth_addr.addr[i]); + sprintf(buf,"%02X",adapter_eth_addr.addr[i]); slip_send(buf[0]); slip_send(buf[1]); } slip_send(SLIP_END); - send_mac = 0; + send_mac = false; } else if(set_sniffer_mode && slip_empty()){ @@ -708,6 +724,30 @@ void send_commands(void) set_channel = 0; } + else if(send_prefix && br_prefix != NULL && slip_empty()){ + + struct in6_addr addr; + int i; + + inet_pton(AF_INET6, br_prefix, &addr); + + fprintf(stderr,"*** Address:%s => %02x%02x:%02x%02x:%02x%02x:%02x%02x\n", + br_prefix, + addr.s6_addr[0], addr.s6_addr[1], + addr.s6_addr[2], addr.s6_addr[3], + addr.s6_addr[4], addr.s6_addr[5], + addr.s6_addr[6], addr.s6_addr[7]); + slip_send('!'); + slip_send('P'); + for(i = 0; i < 8; i++) { + /* need to call the slip_send_char for stuffing */ + slip_send_char(addr.s6_addr[i]); + } + slip_send(SLIP_END); + + send_prefix = false; + + } } void addAddress(const char * ifname, const char * ipaddr) @@ -737,7 +777,7 @@ void addAddress(const char * ifname, const char * ipaddr) execProcess(&exitCode,"netsh interface ipv6 add address \"%s\" %s",if_name,ipaddr); } if(exitCode==0) - tobecleaned = true; + clean_addr = true; } void delAddress(const char * ifname, const char * ipaddr) @@ -769,6 +809,101 @@ void delAddress(const char * ifname, const char * ipaddr) } +void addLoWPANRoute(const char * ifname, const char * net, const char * gw) +{ + DWORD exitCode = -1; + + execProcess(&exitCode,"netsh interface ipv6 add route %s/64 \"%s\" %s", net, if_name, gw); + if(exitCode==0) + clean_route = true; +} + +void delLoWPANRoute(const char * ifname, const char * net) +{ + execProcess(NULL,"netsh interface ipv6 delete route %s/64 \"%s\"", net, if_name); +} + +void addNeighbor(const char * ifname, const char * neighb, const char * neighb_mac) +{ + DWORD exitCode = -1; + + if(osVersionInfo.dwMajorVersion < 6){ // < Windows Vista (i.e., Windows XP; check if this command is ok for Windows Server 2003 too). + + fprintf(stderr,"Bridge mode only supported on Windows Vista and later OSs.\r\n"); + exit(-1); + + } + else{ + execProcess(&exitCode,"netsh interface ipv6 add neighbor \"%s\" %s \"%s\"", if_name, neighb, neighb_mac); + if(exitCode==0) + clean_neighb = true; + } +} + +void delNeighbor(const char * ifname, const char * neighb) +{ + execProcess(NULL,"netsh interface ipv6 delete neighbor \"%s\" %s", if_name, neighb); +} + +int IPAddrFromPrefix(char * ipaddr, const char * ipprefix, const char * mac) +{ + struct in6_addr ipv6addr; + struct uip_802154_longaddr dev_addr; + char tmp_ipprefix[INET6_ADDRSTRLEN]; + char str_addr[INET6_ADDRSTRLEN] = {0}; + int addr_bytes[8]; + int i; + + strncpy(tmp_ipprefix, ipprefix, INET6_ADDRSTRLEN); + + // sscanf requires int instead of 8-bit for hexadecimal variables. + + sscanf(mac, "%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(tmp_ipprefix,"/"); + + if(inet_pton(AF_INET6, tmp_ipprefix, &ipv6addr)!=1){ + return 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,str_addr,INET6_ADDRSTRLEN); // To string format. + + char * substr = strtok(NULL,"/"); + if(substr!=NULL){ // Add the prefix length. + strcat(str_addr,"/"); + strcat(str_addr,substr); + } + strcpy(ipaddr, str_addr); + + return 0; + +} + + + int main(int argc, char **argv) { @@ -781,6 +916,8 @@ main(int argc, char **argv) int baudrate = -2; char buf[4000]; + + prog = argv[0]; setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */ @@ -788,7 +925,7 @@ main(int argc, char **argv) osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osVersionInfo); - while((c = getopt(argc, argv, "B:D:hs:c:ra:p:v")) != -1) { + while((c = getopt(argc, argv, "B:D:hs:c:ra:p:v:tb:")) != -1) { switch (c) { case 'B': baudrate = atoi(optarg); @@ -808,14 +945,6 @@ main(int argc, char **argv) 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); @@ -832,14 +961,14 @@ main(int argc, char **argv) case 'a': if(autoconf == true){ - errx(1, USAGE_STRING); + print_help(); } - ipaddr = optarg; + local_ipaddr = optarg; break; case 'p': - if(ipaddr !=NULL){ - errx(1, USAGE_STRING); + if(local_ipaddr !=NULL){ + print_help(); } autoconf = true; ipprefix = optarg; @@ -849,10 +978,21 @@ main(int argc, char **argv) verbose = true; break; + case 't': + tun = true; + break; + + case 'b': + br_prefix = optarg; + send_prefix = true; + send_mac = false; + tun = true; + break; + case '?': case 'h': default: - errx(1,HELP_STRING); + print_help(); break; } } @@ -860,16 +1000,23 @@ main(int argc, char **argv) argv += (optind - 1); if(argc != 2 || *siodev == '\0') { - errx(1, USAGE_STRING); + print_help(); } + if(autoconf == true && br_prefix != NULL){ + fprintf(stderr, "-p and -b options cannot be used together.\r\n"); + print_help(); + } + sscanf(argv[1],"%2X-%2X-%2X-%2X-%2X-%2X", - (int *)ð_addr.addr[0],(int *)ð_addr.addr[1],(int *)ð_addr.addr[2],(int *)ð_addr.addr[3],(int *)ð_addr.addr[4],(int *)ð_addr.addr[5]); - if_name = wpcap_start(ð_addr, verbose); + (int *)&adapter_eth_addr.addr[0],(int *)&adapter_eth_addr.addr[1], + (int *)&adapter_eth_addr.addr[2],(int *)&adapter_eth_addr.addr[3], + (int *)&adapter_eth_addr.addr[4],(int *)&adapter_eth_addr.addr[5]); + if_name = wpcap_start(&adapter_eth_addr, verbose); - if(ipaddr!=NULL){ - addAddress(if_name, ipaddr); + if(local_ipaddr!=NULL){ + addAddress(if_name, local_ipaddr); } @@ -897,15 +1044,12 @@ main(int argc, char **argv) } - //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"); - }*/ + + 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); + } + fprintf(stderr, "slip started on ``/dev/%s''\n", siodev); stty_telos(slipfd); slip_send(SLIP_END); @@ -950,6 +1094,13 @@ main(int argc, char **argv) if(eth_hdr->type == htons(UIP_ETHTYPE_IPV6)){ // We forward only IPv6 packet. + + if(tun){ + // Cut away ethernet header. + pbuf += sizeof(struct uip_eth_hdr); + ret -= sizeof(struct uip_eth_hdr); + } + write_to_serial(pbuf, ret); /*print_packet(pbuf, ret);*/ slip_flushbuf(slipfd); @@ -968,7 +1119,6 @@ main(int argc, char **argv) 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");*/ } diff --git a/tools/stm32w/wpcapslip6/wpcapslip6.exe b/tools/stm32w/wpcapslip6/wpcapslip6.exe index ddd618111cb916c3b0df047f108d156a5d395280..b14fd55821b304b281021a567d36df51767f3a94 100644 GIT binary patch literal 43214 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
  • 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