2 * Copyright (c) 2001, Adam Dunkels.
3 * Copyright (c) 2009, Joakim Eriksson, Niclas Finne.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote
15 * products derived from this software without specific prior
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
24 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * This file is part of the uIP TCP/IP stack.
32 * $Id: tapslip6.c,v 1.1 2010/10/25 10:42:41 salvopitru Exp $
37 * A driver for the uip6-bridge customized for STM32W. Thanks to
38 * Adam Dunkels, Joakim Eriksson, Niclas Finne for the original
41 * Salvatore Pitrulli <salvopitru@users.sourceforge.net>
49 #include <sys/types.h>
56 #include <sys/ioctl.h>
58 #include <sys/socket.h>
59 #include <netinet/in.h>
60 #include <arpa/inet.h>
64 int ssystem(const char *fmt
, ...)
65 __attribute__ ((__format__(__printf__
, 1, 2)));
66 void write_to_serial(void *inbuf
, int len
);
68 #define PRINTF(...) if(verbose)printf(__VA_ARGS__)
70 //#define PROGRESS(s) fprintf(stderr, s)
71 #define PROGRESS(s) do { } while (0)
73 #define USAGE_STRING "usage: tapslip6 [-B baudrate] [-s siodev] [-t tundev] [-a ipaddress[/prefixlen]|-p 64bit-prefix[/prefixlen]] [-c channel] [-r] [-v] [-h]"
74 #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\
76 -B baudrate\tBaudrate of the serial port (default:115200).\r\n\
77 -s siodev\tDevice that identifies the bridge (default: the first available\r\n\
78 \t\tamong ttyUSB0, cuaU0 and ucom0)\r\n\
79 -t tundev\tThe virtual network interface (default: tap0)\r\n\
80 -c channel\t802.15.4 radio channel.\r\n\
81 -r\t\tSet sniffer mode. \r\n\
82 -a ipaddress/[prefixlen] The address to be assigned to the virtual network\r\n\
84 -p 64bit-prefix\tAutomatic assignment of the IPv6 address from the specified\r\n\
85 \t\tsubnet prefix. It may be followed by the prefix length\r\n\
86 \t\tfor the on-link determination.\r\n\
87 -v\t\tVerbose. Print more infos.\r\n\
88 -h\t\tShow this help.\r\n"
95 char tundev
[32] = { "tap0" };
97 const char *ipaddr
= NULL
;
98 char *ipprefix
= NULL
;
99 char autoconf_addr
[44] = { 0 };
101 bool autoconf
= false;
102 bool verbose
= false;
104 struct uip_eth_addr
{
107 struct uip_802154_longaddr
{
111 static struct uip_eth_addr eth_addr
;
112 const struct uip_eth_addr eth_addr_null
= { {0} };
114 static int request_mac
= 1;
115 static int send_mac
= 1;
116 static int set_sniffer_mode
= 1;
117 static int set_channel
= 1;
119 static int sniffer_mode
= 0;
120 static int channel
= 0;
123 int ssystem(const char *fmt
, ...)
124 __attribute__ ((__format__(__printf__
, 1, 2)));
126 int ssystem(const char *fmt
, ...)
131 vsnprintf(cmd
, sizeof(cmd
), fmt
, ap
);
138 #define SLIP_END 0300
139 #define SLIP_ESC 0333
140 #define SLIP_ESC_END 0334
141 #define SLIP_ESC_ESC 0335
143 static void print_packet(u_int8_t
* p
, int len
)
146 for (i
= 0; i
< len
; i
++) {
147 printf("%02x", p
[i
]);
156 int is_sensible_string(const unsigned char *s
, int len
)
159 for (i
= 1; i
< len
; i
++) {
160 if (s
[i
] == 0 || s
[i
] == '\r' || s
[i
] == '\n' || s
[i
] == '\t') {
163 else if (s
[i
] < ' ' || '~' < s
[i
]) {
173 * Read from serial, when we have a packet write it to tun. No output
174 * buffering, input buffered by stdio.
176 void serial_to_tun(FILE * inslip
, int outfd
)
179 unsigned char inbuf
[2000];
181 static int inbufptr
= 0;
187 ret
= fread(&c
, 1, 1, inslip
);
188 if (ret
== -1 || ret
== 0)
189 err(1, "serial_to_tun: read");
194 if (inbufptr
>= sizeof(uip
.inbuf
)) {
197 ret
= fread(&c
, 1, 1, inslip
);
202 err(1, "serial_to_tun: read");
207 fprintf(stderr
, "serial_to_tun: EOF\n");
210 /* fprintf(stderr, "."); */
214 if (uip
.inbuf
[0] == '!') {
215 if (uip
.inbuf
[1] == 'M') {
216 /* Read gateway MAC address and autoconfigure tap0 interface */
219 struct uip_802154_longaddr dev_addr
= { {0} }; // Bridge EUI-64.
221 for (i
= 0, pos
= 0; i
< 16; i
++) {
222 macs
[pos
++] = uip
.inbuf
[2 + i
];
223 if ((i
& 1) == 1 && i
< 14) {
228 printf("*** Gateway's MAC address: %s\n", macs
);
232 int addr_bytes
[8]; // sscanf requires int instead of 8-bit for hexadecimal variables.
234 sscanf(macs
, "%2X:%2X:%2X:%2X:%2X:%2X:%2X:%2X",
245 dev_addr
.addr
[i
] = addr_bytes
[i
];
249 ////////////////////////////////////////
251 for (i = 0; i < 8; i++)
252 PRINTF("%02X ", dev_addr.addr[i]);
254 ////////////////////////////////////////
256 // Remember what will be our MAC address (two middle bytes will be elided).
257 memcpy(ð_addr
, &dev_addr
, 3);
258 memcpy(ð_addr
.addr
[3], &dev_addr
.addr
[5], 3);
262 struct in6_addr ipv6addr
;
264 dev_addr
.addr
[0] |= 0x02;
266 strtok(ipprefix
, "/");
268 if (inet_pton(AF_INET6
, ipprefix
, &ipv6addr
) != 1) {
269 printf("Invalid IPv6 address.\n");
273 // Copy modified EUI-64 to the last 64 bits of IPv6 address.
274 memcpy(&ipv6addr
.s6_addr
[8], &dev_addr
, 8);
276 inet_ntop(AF_INET6
, &ipv6addr
, autoconf_addr
, INET6_ADDRSTRLEN
); // To string format.
278 char *substr
= strtok(NULL
, "/");
279 if (substr
!= NULL
) { // Add the prefix length.
280 strcat(autoconf_addr
, "/");
281 strcat(autoconf_addr
, substr
);
283 ipaddr
= autoconf_addr
;
286 ssystem("ifconfig %s down", tundev
);
289 strcpy(&macs
[9], &macs
[15]); // Elide two middle bytes.
290 ssystem("ifconfig %s hw ether %s", tundev
, macs
);
291 ssystem("ifconfig %s inet6 up", tundev
);
293 ssystem("ifconfig %s inet6 add %s", tundev
, ipaddr
);
294 ssystem("sysctl -w net.ipv6.conf.all.forwarding=1");
296 ssystem("ifconfig %s\n", tundev
);
299 #define DEBUG_LINE_MARKER '\r'
301 else if (uip
.inbuf
[0] == '?') {
302 if (uip
.inbuf
[1] == 'M'
303 && memcmp(ð_addr
, ð_addr_null
, 6) != 0) {
304 /* Send our MAC address and other configuration options. */
306 set_sniffer_mode
= 1;
310 else if (uip
.inbuf
[0] == DEBUG_LINE_MARKER
) {
311 fwrite(uip
.inbuf
+ 1, inbufptr
- 1, 1, stdout
);
313 else if (is_sensible_string(uip
.inbuf
, inbufptr
)) {
314 fwrite(uip
.inbuf
, inbufptr
, 1, stdout
);
317 PRINTF("Writing to tun len: %d\n", inbufptr
);
318 /* print_packet(uip.inbuf, inbufptr); */
319 if (write(outfd
, uip
.inbuf
, inbufptr
) != inbufptr
) {
320 err(1, "serial_to_tun: write");
328 if (fread(&c
, 1, 1, inslip
) != 1) {
330 /* Put ESC back and give up! */
331 ungetc(SLIP_ESC
, inslip
);
345 uip
.inbuf
[inbufptr
++] = c
;
352 unsigned char slip_buf
[2000];
353 int slip_end
, slip_begin
;
356 void slip_send(unsigned char c
)
358 if (slip_end
>= sizeof(slip_buf
))
359 err(1, "slip_send overflow");
360 slip_buf
[slip_end
] = c
;
366 return slip_end
== 0;
369 void slip_flushbuf(int fd
)
376 n
= write(fd
, slip_buf
+ slip_begin
, (slip_end
- slip_begin
));
378 if (n
== -1 && errno
!= EAGAIN
) {
379 err(1, "slip_flushbuf write failed");
382 PROGRESS("Q"); /* Outqueueis full! */
386 if (slip_begin
== slip_end
) {
387 slip_begin
= slip_end
= 0;
392 void write_to_serial(void *inbuf
, int len
)
397 /* printf("Got packet of length %d - write SLIP\n", len); */
398 /* print_packet(p, len); */
400 /* It would be ``nice'' to send a SLIP_END here but it's not
403 /* slip_send(outfd, SLIP_END); */
404 PRINTF("Writing to serial len: %d\n", len
);
405 for (i
= 0; i
< len
; i
++) {
409 slip_send(SLIP_ESC_END
);
413 slip_send(SLIP_ESC_ESC
);
427 * Read from tun, write to slip.
429 void tun_to_serial(int infd
, int outfd
)
432 unsigned char inbuf
[2000];
436 if ((size
= read(infd
, uip
.inbuf
, 2000)) == -1)
437 err(1, "tun_to_serial: read");
439 write_to_serial(uip
.inbuf
, size
);
443 #define BAUDRATE B115200
445 speed_t b_rate
= BAUDRATE
;
447 void stty_telos(int fd
)
450 speed_t speed
= b_rate
;
453 if (tcflush(fd
, TCIOFLUSH
) == -1)
456 if (tcgetattr(fd
, &tty
) == -1)
461 /* Nonblocking read. */
464 tty
.c_cflag
&= ~CRTSCTS
;
465 tty
.c_cflag
&= ~HUPCL
;
466 tty
.c_cflag
&= ~CLOCAL
;
468 cfsetispeed(&tty
, speed
);
469 cfsetospeed(&tty
, speed
);
471 if (tcsetattr(fd
, TCSAFLUSH
, &tty
) == -1)
475 /* Nonblocking read and write. */
476 /* if(fcntl(fd, F_SETFL, O_NONBLOCK) == -1) err(1, "fcntl"); */
478 tty
.c_cflag
|= CLOCAL
;
479 if (tcsetattr(fd
, TCSAFLUSH
, &tty
) == -1)
483 if (ioctl(fd
, TIOCMBIS
, &i
) == -1)
487 usleep(10 * 1000); /* Wait for hardware 10ms. */
489 /* Flush input and output buffers. */
490 if (tcflush(fd
, TCIOFLUSH
) == -1)
494 int devopen(const char *dev
, int flags
)
499 return open(t
, flags
);
503 #include <linux/if.h>
504 #include <linux/if_tun.h>
506 int tun_alloc(char *dev
)
511 if ((fd
= open("/dev/net/tun", O_RDWR
)) < 0)
514 memset(&ifr
, 0, sizeof(ifr
));
516 /* Flags: IFF_TUN - TUN device (no Ethernet headers)
517 * IFF_TAP - TAP device
519 * IFF_NO_PI - Do not provide packet information
521 ifr
.ifr_flags
= IFF_TAP
| IFF_NO_PI
;
523 strncpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
525 if ((err
= ioctl(fd
, TUNSETIFF
, (void *) &ifr
)) < 0) {
529 strcpy(dev
, ifr
.ifr_name
);
533 int tun_alloc(char *dev
)
535 return devopen(dev
, O_RDWR
);
542 ssystem("ifconfig %s down", tundev
);
544 ssystem("sysctl -w net.ipv6.conf.all.forwarding=0");
548 void sigcleanup(int signo
)
550 fprintf(stderr
, "signal %d\n", signo
);
551 exit(0); /* exit(0) will call cleanup() */
555 static int request_mac
;
558 void send_commands(void)
569 /* Send our mac to the device. If it knows our address, it is not needed to change
570 the MAC address of our local interface (this can be also unsupported, especially under
573 else if(send_mac
&& memcmp(ð_addr
, ð_addr_null
, 6) != 0
576 PRINTF("Sending our MAC.\n");
581 for(i
=0; i
< 6; i
++){
582 sprintf(buf
,"%02X",eth_addr
.addr
[i
]);
590 else if(set_sniffer_mode
&& slip_empty()){
592 PRINTF("Setting sniffer mode to %d.\n", sniffer_mode
);
606 set_sniffer_mode
= 0;
609 else if(set_channel
&& slip_empty()){
612 PRINTF("Setting channel %02d.\n", channel
);
618 sprintf(buf
,"%02d",channel
);
631 int main(int argc
, char **argv
)
634 int tunfd
, slipfd
, maxfd
;
638 const char *siodev
= NULL
;
641 setvbuf(stdout
, NULL
, _IOLBF
, 0); /* Line buffered output. */
643 while ((c
= getopt(argc
, argv
, "B:D:hs:c:rt:a:p:v")) != -1) {
646 baudrate
= atoi(optarg
);
650 if (strncmp("/dev/", optarg
, 5) == 0) {
659 if (strncmp("/dev/", optarg
, 5) == 0) {
660 strcpy(tundev
, optarg
+ 5);
663 strcpy(tundev
, optarg
);
668 channel
= atoi(optarg
);
676 if (autoconf
== true) {
677 errx(1, USAGE_STRING
);
683 if (ipaddr
!= NULL
) {
684 errx(1, USAGE_STRING
);
697 errx(1, HELP_STRING
);
702 argc
-= (optind
- 1);
703 argv
+= (optind
- 1);
705 //if(argc != 3 && argc != 4) {
706 //if (autoconf == false && ipaddr == NULL ) {
707 errx(1, USAGE_STRING
);
714 break; /* Use default. */
731 err(1, "unknown baudrate %d", baudrate
);
736 if (siodev
!= NULL
) {
737 slipfd
= devopen(siodev
, O_RDWR
| O_NONBLOCK
);
739 err(1, "can't open siodev ``/dev/%s''", siodev
);
743 static const char *siodevs
[] = {
744 "ttyUSB0", "cuaU0", "ucom0" /* linux, fbsd6, fbsd5 */
747 for (i
= 0; i
< 3; i
++) {
749 slipfd
= devopen(siodev
, O_RDWR
| O_NONBLOCK
);
754 err(1, "can't open siodev");
757 fprintf(stderr
, "slip started on ``/dev/%s''\n", siodev
);
760 inslip
= fdopen(slipfd
, "r");
762 err(1, "main: fdopen");
764 tunfd
= tun_alloc(tundev
);
765 printf("opening: %s\n", tundev
);
767 err(1, "main: open");
768 fprintf(stderr
, "opened device ``/dev/%s''\n", tundev
);
771 signal(SIGHUP
, sigcleanup
);
772 signal(SIGTERM
, sigcleanup
);
773 signal(SIGINT
, sigcleanup
);
784 if (!slip_empty()) { /* Anything to flush? */
785 FD_SET(slipfd
, &wset
);
788 FD_SET(slipfd
, &rset
); /* Read from slip ASAP! */
792 /* We only have one packet at a time queued for slip output. */
794 FD_SET(tunfd
, &rset
);
799 ret
= select(maxfd
+ 1, &rset
, &wset
, NULL
, NULL
);
800 if (ret
== -1 && errno
!= EINTR
) {
804 if (FD_ISSET(slipfd
, &rset
)) {
805 serial_to_tun(inslip
, tunfd
);
808 if (FD_ISSET(slipfd
, &wset
)) {
809 slip_flushbuf(slipfd
);
812 if (slip_empty() && FD_ISSET(tunfd
, &rset
)) {
813 tun_to_serial(tunfd
, slipfd
);
814 slip_flushbuf(slipfd
);