2 * Copyright (c) 2001, Adam Dunkels.
3 * Copyright (c) 2009, 2010 Joakim Eriksson, Niclas Finne, Dogan Yazar.
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: tunslip6.c,v 1.5 2010/07/30 20:44:24 dak664 Exp $
41 #include <sys/types.h>
48 #include <sys/ioctl.h>
50 #include <sys/socket.h>
51 #include <netinet/in.h>
52 #include <arpa/inet.h>
61 uint16_t basedelay
=0,delaymsec
=0;
62 uint32_t startsec
,startmsec
,delaystartsec
,delaystartmsec
;
65 int ssystem(const char *fmt
, ...)
66 __attribute__((__format__ (__printf__
, 1, 2)));
67 void write_to_serial(int outfd
, void *inbuf
, int len
);
69 void slip_send(int fd
, unsigned char c
);
71 //#define PROGRESS(s) fprintf(stderr, s)
72 #define PROGRESS(s) do { } while (0)
74 char tundev
[32] = { "" };
77 ssystem(const char *fmt
, ...) __attribute__((__format__ (__printf__
, 1, 2)));
80 ssystem(const char *fmt
, ...)
85 vsnprintf(cmd
, sizeof(cmd
), fmt
, ap
);
94 #define SLIP_ESC_END 0334
95 #define SLIP_ESC_ESC 0335
98 /* get sockaddr, IPv4 or IPv6: */
100 get_in_addr(struct sockaddr
*sa
)
102 if(sa
->sa_family
== AF_INET
) {
103 return &(((struct sockaddr_in
*)sa
)->sin_addr
);
105 return &(((struct sockaddr_in6
*)sa
)->sin6_addr
);
110 static long startsecs
=0,startmsecs
=0;
117 gettimeofday(&tv
, NULL
) ;
118 msecs
=tv
.tv_usec
/1000;
123 if (msecs
<0) {secs
--;msecs
+=1000;}
124 fprintf(stderr
,"%04lu.%03lu ", secs
, msecs
);
130 strftime(timec
,sizeof(timec
),"%T",tmp
);
131 // fprintf(stderr,"\n%s.%03lu ",timec,msecs);
132 fprintf(stderr
,"\n%s ",timec
);
137 is_sensible_string(const unsigned char *s
, int len
)
140 for(i
= 1; i
< len
; i
++) {
141 if(s
[i
] == 0 || s
[i
] == '\r' || s
[i
] == '\n' || s
[i
] == '\t') {
143 } else if(s
[i
] < ' ' || '~' < s
[i
]) {
151 * Read from serial, when we have a packet write it to tun. No output
152 * buffering, input buffered by stdio.
155 serial_to_tun(FILE *inslip
, int outfd
)
158 unsigned char inbuf
[2000];
160 static int inbufptr
= 0;
165 ret
= fread(&c
, 1, 1, inslip
);
166 if(ret
== -1 || ret
== 0) err(1, "serial_to_tun: read");
171 if(inbufptr
>= sizeof(uip
.inbuf
)) {
173 if(timestamp
) stamptime();
174 fprintf(stderr
, "*** dropping too large packet\n");
176 ret
= fread(&c
, 1, 1, inslip
);
181 err(1, "serial_to_tun: read");
187 /* fprintf(stderr, ".");*/
191 if(uip
.inbuf
[0] == '!') {
192 if(uip
.inbuf
[1] == 'M') {
193 /* Read gateway MAC address and autoconfigure tap0 interface */
196 for(i
= 0, pos
= 0; i
< 16; i
++) {
197 macs
[pos
++] = uip
.inbuf
[2 + i
];
198 if((i
& 1) == 1 && i
< 14) {
202 if(timestamp
) stamptime();
204 // printf("*** Gateway's MAC address: %s\n", macs);
205 fprintf(stderr
,"*** Gateway's MAC address: %s\n", macs
);
206 if (timestamp
) stamptime();
207 ssystem("ifconfig %s down", tundev
);
208 if (timestamp
) stamptime();
209 ssystem("ifconfig %s hw ether %s", tundev
, &macs
[6]);
210 if (timestamp
) stamptime();
211 ssystem("ifconfig %s up", tundev
);
212 } else if(uip
.inbuf
[1] == 'P') {
213 /* Prefix info requested */
214 struct in6_addr addr
;
216 char *s
= strchr(ipaddr
, '/');
220 inet_pton(AF_INET6
, ipaddr
, &addr
);
221 if(timestamp
) stamptime();
222 fprintf(stderr
,"*** Address:%s => %02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
223 // printf("*** Address:%s => %02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
225 addr
.s6_addr
[0], addr
.s6_addr
[1],
226 addr
.s6_addr
[2], addr
.s6_addr
[3],
227 addr
.s6_addr
[4], addr
.s6_addr
[5],
228 addr
.s6_addr
[6], addr
.s6_addr
[7]);
229 slip_send(slipfd
, '!');
230 slip_send(slipfd
, 'P');
231 for(i
= 0; i
< 8; i
++) {
232 slip_send(slipfd
, addr
.s6_addr
[i
]);
234 slip_send(slipfd
, SLIP_END
);
236 #define DEBUG_LINE_MARKER '\r'
237 } else if(uip
.inbuf
[0] == DEBUG_LINE_MARKER
) {
238 fwrite(uip
.inbuf
+ 1, inbufptr
- 1, 1, stdout
);
239 } else if(is_sensible_string(uip
.inbuf
, inbufptr
)) {
240 if(verbose
==1) { /* strings already echoed below for verbose>1 */
241 if (timestamp
) stamptime();
242 fwrite(uip
.inbuf
, inbufptr
, 1, stdout
);
246 if (timestamp
) stamptime();
247 printf("Packet from SLIP of length %d - write TUN\n", inbufptr
);
250 for(i
= 0; i
< inbufptr
; i
++) {
251 printf("%02x", uip
.inbuf
[i
]);
261 if(write(outfd
, uip
.inbuf
, inbufptr
) != inbufptr
) {
262 err(1, "serial_to_tun: write");
270 if(fread(&c
, 1, 1, inslip
) != 1) {
272 /* Put ESC back and give up! */
273 ungetc(SLIP_ESC
, inslip
);
287 uip
.inbuf
[inbufptr
++] = c
;
289 /* Echo lines as they are received for verbose=2,3,5+ */
290 /* Echo all printable characters for verbose==4 */
291 if((verbose
==2) || (verbose
==3) || (verbose
>4)) {
293 if(is_sensible_string(uip
.inbuf
, inbufptr
)) {
294 if (timestamp
) stamptime();
295 fwrite(uip
.inbuf
, inbufptr
, 1, stdout
);
299 } else if(verbose
==4) {
300 if(c
== 0 || c
== '\r' || c
== '\n' || c
== '\t' || (c
>= ' ' && c
<= '~')) {
301 fwrite(&c
, 1, 1, stdout
);
302 if(c
=='\n') if(timestamp
) stamptime();
312 unsigned char slip_buf
[2000];
313 int slip_end
, slip_begin
;
316 slip_send(int fd
, unsigned char c
)
318 if(slip_end
>= sizeof(slip_buf
)) {
319 err(1, "slip_send overflow");
321 slip_buf
[slip_end
] = c
;
328 return slip_end
== 0;
332 slip_flushbuf(int fd
)
340 n
= write(fd
, slip_buf
+ slip_begin
, (slip_end
- slip_begin
));
342 if(n
== -1 && errno
!= EAGAIN
) {
343 err(1, "slip_flushbuf write failed");
345 PROGRESS("Q"); /* Outqueueis full! */
348 if(slip_begin
== slip_end
) {
349 slip_begin
= slip_end
= 0;
355 write_to_serial(int outfd
, void *inbuf
, int len
)
361 if (timestamp
) stamptime();
362 printf("Packet from TUN of length %d - write SLIP\n", len
);
365 for(i
= 0; i
< len
; i
++) {
366 printf("%02x", p
[i
]);
377 /* It would be ``nice'' to send a SLIP_END here but it's not
380 /* slip_send(outfd, SLIP_END); */
382 for(i
= 0; i
< len
; i
++) {
385 slip_send(outfd
, SLIP_ESC
);
386 slip_send(outfd
, SLIP_ESC_END
);
389 slip_send(outfd
, SLIP_ESC
);
390 slip_send(outfd
, SLIP_ESC_ESC
);
393 slip_send(outfd
, p
[i
]);
397 slip_send(outfd
, SLIP_END
);
403 * Read from tun, write to slip.
406 tun_to_serial(int infd
, int outfd
)
409 unsigned char inbuf
[2000];
413 if((size
= read(infd
, uip
.inbuf
, 2000)) == -1) err(1, "tun_to_serial: read");
415 write_to_serial(outfd
, uip
.inbuf
, size
);
420 #define BAUDRATE B115200
422 speed_t b_rate
= BAUDRATE
;
428 speed_t speed
= b_rate
;
431 if(tcflush(fd
, TCIOFLUSH
) == -1) err(1, "tcflush");
433 if(tcgetattr(fd
, &tty
) == -1) err(1, "tcgetattr");
437 /* Nonblocking read. */
440 tty
.c_cflag
&= ~CRTSCTS
;
441 tty
.c_cflag
&= ~HUPCL
;
442 tty
.c_cflag
&= ~CLOCAL
;
444 cfsetispeed(&tty
, speed
);
445 cfsetospeed(&tty
, speed
);
447 if(tcsetattr(fd
, TCSAFLUSH
, &tty
) == -1) err(1, "tcsetattr");
450 /* Nonblocking read and write. */
451 /* if(fcntl(fd, F_SETFL, O_NONBLOCK) == -1) err(1, "fcntl"); */
453 tty
.c_cflag
|= CLOCAL
;
454 if(tcsetattr(fd
, TCSAFLUSH
, &tty
) == -1) err(1, "tcsetattr");
457 if(ioctl(fd
, TIOCMBIS
, &i
) == -1) err(1, "ioctl");
460 usleep(10*1000); /* Wait for hardware 10ms. */
462 /* Flush input and output buffers. */
463 if(tcflush(fd
, TCIOFLUSH
) == -1) err(1, "tcflush");
467 devopen(const char *dev
, int flags
)
471 strncat(t
, dev
, sizeof(t
) - 5);
472 return open(t
, flags
);
476 #include <linux/if.h>
477 #include <linux/if_tun.h>
480 tun_alloc(char *dev
, int tap
)
485 if( (fd
= open("/dev/net/tun", O_RDWR
)) < 0 ) {
489 memset(&ifr
, 0, sizeof(ifr
));
491 /* Flags: IFF_TUN - TUN device (no Ethernet headers)
492 * IFF_TAP - TAP device
494 * IFF_NO_PI - Do not provide packet information
496 ifr
.ifr_flags
= (tap
? IFF_TAP
: IFF_TUN
) | IFF_NO_PI
;
498 strncpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
500 if((err
= ioctl(fd
, TUNSETIFF
, (void *) &ifr
)) < 0 ) {
504 strcpy(dev
, ifr
.ifr_name
);
509 tun_alloc(char *dev
, int tap
)
511 return devopen(dev
, O_RDWR
);
518 if (timestamp
) stamptime();
519 ssystem("ifconfig %s down", tundev
);
521 ssystem("sysctl -w net.ipv6.conf.all.forwarding=1");
523 /* ssystem("arp -d %s", ipaddr); */
524 if (timestamp
) stamptime();
525 ssystem("netstat -nr"
526 " | awk '{ if ($2 == \"%s\") print \"route delete -net \"$1; }'"
532 sigcleanup(int signo
)
534 fprintf(stderr
, "signal %d\n", signo
);
535 exit(0); /* exit(0) will call cleanup() */
538 static int got_sigalarm
;
551 #define TIMEOUT (997*1000)
553 #define TIMEOUT (2451*1000)
555 ualarm(TIMEOUT
, TIMEOUT
);
560 ifconf(const char *tundev
, const char *ipaddr
)
563 if (timestamp
) stamptime();
564 ssystem("ifconfig %s inet `hostname` up", tundev
);
565 if (timestamp
) stamptime();
566 ssystem("ifconfig %s add %s", tundev
, ipaddr
);
568 if (timestamp
) stamptime();
569 ssystem("ifconfig %s inet `hostname` %s up", tundev
, ipaddr
);
570 if (timestamp
) stamptime();
571 ssystem("sysctl -w net.inet.ip.forwarding=1");
574 if (timestamp
) stamptime();
575 ssystem("ifconfig %s\n", tundev
);
579 main(int argc
, char **argv
)
586 const char *siodev
= NULL
;
587 const char *host
= NULL
;
588 const char *port
= NULL
;
595 setvbuf(stdout
, NULL
, _IOLBF
, 0); /* Line buffered output. */
597 while((c
= getopt(argc
, argv
, "B:D:Lhs:t:v::d::a:p:T")) != -1) {
600 baudrate
= atoi(optarg
);
608 if(strncmp("/dev/", optarg
, 5) == 0) {
616 if(strncmp("/dev/", optarg
, 5) == 0) {
617 strncpy(tundev
, optarg
+ 5, sizeof(tundev
));
619 strncpy(tundev
, optarg
, sizeof(tundev
));
633 if (optarg
) basedelay
= atoi(optarg
);
638 if (optarg
) verbose
= atoi(optarg
);
648 fprintf(stderr
,"usage: %s [options] ipaddress\n", prog
);
649 fprintf(stderr
,"example: tunslip6 -L -v2 -s ttyUSB1 aaaa::1/64\n");
650 fprintf(stderr
,"Options are:\n");
651 fprintf(stderr
," -B baudrate 9600,19200,38400,57600,115200 (default)\n");
652 fprintf(stderr
," -L Log output format (adds time stamps)\n");
653 fprintf(stderr
," -s siodev Serial device (default /dev/ttyUSB0)\n");
654 fprintf(stderr
," -T Make tap interface (default is tun interface)\n");
655 fprintf(stderr
," -t tundev Name of interface (default tap0 or tun0)\n");
656 fprintf(stderr
," -v[level] Verbosity level\n");
657 fprintf(stderr
," -v0 No messages\n");
658 fprintf(stderr
," -v1 Encapsulated SLIP debug messages (default)\n");
659 fprintf(stderr
," -v2 Printable strings after they are received\n");
660 fprintf(stderr
," -v3 Printable strings and SLIP packet notifications\n");
661 fprintf(stderr
," -v4 All printable characters as they are received\n");
662 fprintf(stderr
," -v5 All SLIP packets in hex\n");
663 fprintf(stderr
," -v Equivalent to -v3\n");
664 fprintf(stderr
," -d[basedelay] Minimum delay between outgoing SLIP packets.\n");
665 fprintf(stderr
," Actual delay is basedelay*(#6LowPAN fragments) milliseconds.\n");
666 fprintf(stderr
," -d is equivalent to -d10.\n");
667 fprintf(stderr
," -a serveraddr \n");
668 fprintf(stderr
," -p serverport \n");
673 argc
-= (optind
- 1);
674 argv
+= (optind
- 1);
676 if(argc
!= 2 && argc
!= 3) {
677 err(1, "usage: %s [-B baudrate] [-L] [-s siodev] [-t tundev] [-T] [-v verbosity] [-d delay] [-a serveraddress] [-p serverport] ipaddress", prog
);
683 break; /* Use default. */
700 err(1, "unknown baudrate %d", baudrate
);
704 if(*tundev
== '\0') {
707 strcpy(tundev
, "tap0");
709 strcpy(tundev
, "tun0");
713 struct addrinfo hints
, *servinfo
, *p
;
715 char s
[INET6_ADDRSTRLEN
];
721 memset(&hints
, 0, sizeof hints
);
722 hints
.ai_family
= AF_UNSPEC
;
723 hints
.ai_socktype
= SOCK_STREAM
;
725 if((rv
= getaddrinfo(host
, port
, &hints
, &servinfo
)) != 0) {
726 err(1, "getaddrinfo: %s", gai_strerror(rv
));
729 /* loop through all the results and connect to the first we can */
730 for(p
= servinfo
; p
!= NULL
; p
= p
->ai_next
) {
731 if((slipfd
= socket(p
->ai_family
, p
->ai_socktype
,
732 p
->ai_protocol
)) == -1) {
733 perror("client: socket");
737 if(connect(slipfd
, p
->ai_addr
, p
->ai_addrlen
) == -1) {
739 perror("client: connect");
746 err(1, "can't connect to ``%s:%s''", host
, port
);
749 fcntl(slipfd
, F_SETFL
, O_NONBLOCK
);
751 inet_ntop(p
->ai_family
, get_in_addr((struct sockaddr
*)p
->ai_addr
),
753 fprintf(stderr
, "slip connected to ``%s:%s''\n", s
, port
);
755 /* all done with this structure */
756 freeaddrinfo(servinfo
);
760 slipfd
= devopen(siodev
, O_RDWR
| O_NONBLOCK
);
762 err(1, "can't open siodev ``/dev/%s''", siodev
);
765 static const char *siodevs
[] = {
766 "ttyUSB0", "cuaU0", "ucom0" /* linux, fbsd6, fbsd5 */
769 for(i
= 0; i
< 3; i
++) {
771 slipfd
= devopen(siodev
, O_RDWR
| O_NONBLOCK
);
777 err(1, "can't open siodev");
780 if (timestamp
) stamptime();
781 fprintf(stderr
, "********SLIP started on ``/dev/%s''\n", siodev
);
784 slip_send(slipfd
, SLIP_END
);
785 inslip
= fdopen(slipfd
, "r");
786 if(inslip
== NULL
) err(1, "main: fdopen");
788 tunfd
= tun_alloc(tundev
, tap
);
789 if(tunfd
== -1) err(1, "main: open");
790 if (timestamp
) stamptime();
791 fprintf(stderr
, "opened %s device ``/dev/%s''\n",
792 tap
? "tap" : "tun", tundev
);
795 signal(SIGHUP
, sigcleanup
);
796 signal(SIGTERM
, sigcleanup
);
797 signal(SIGINT
, sigcleanup
);
798 signal(SIGALRM
, sigalarm
);
799 ifconf(tundev
, ipaddr
);
806 /* do not send IPA all the time... - add get MAC later... */
807 /* if(got_sigalarm) { */
808 /* /\* Send "?IPA". *\/ */
809 /* slip_send(slipfd, '?'); */
810 /* slip_send(slipfd, 'I'); */
811 /* slip_send(slipfd, 'P'); */
812 /* slip_send(slipfd, 'A'); */
813 /* slip_send(slipfd, SLIP_END); */
814 /* got_sigalarm = 0; */
817 if(!slip_empty()) { /* Anything to flush? */
818 FD_SET(slipfd
, &wset
);
821 FD_SET(slipfd
, &rset
); /* Read from slip ASAP! */
822 if(slipfd
> maxfd
) maxfd
= slipfd
;
824 /* We only have one packet at a time queued for slip output. */
826 FD_SET(tunfd
, &rset
);
827 if(tunfd
> maxfd
) maxfd
= tunfd
;
830 ret
= select(maxfd
+ 1, &rset
, &wset
, NULL
, NULL
);
831 if(ret
== -1 && errno
!= EINTR
) {
834 if(FD_ISSET(slipfd
, &rset
)) {
835 serial_to_tun(inslip
, tunfd
);
838 if(FD_ISSET(slipfd
, &wset
)) {
839 slip_flushbuf(slipfd
);
843 /* Optional delay between outgoing packets */
844 /* Base delay times number of 6lowpan fragments to be sent */
848 gettimeofday(&tv
, NULL
) ;
849 dmsec
=(tv
.tv_sec
-delaystartsec
)*1000+tv
.tv_usec
/1000-delaystartmsec
;
850 if(dmsec
<0) delaymsec
=0;
851 if(dmsec
>delaymsec
) delaymsec
=0;
855 if(slip_empty() && FD_ISSET(tunfd
, &rset
)) {
856 size
=tun_to_serial(tunfd
, slipfd
);
857 slip_flushbuf(slipfd
);
861 gettimeofday(&tv
, NULL
) ;
862 // delaymsec=basedelay*(1+(size/120));//multiply by # of 6lowpan packets?
864 delaystartsec
=tv
.tv_sec
;
865 delaystartmsec
=tv
.tv_usec
/1000;