1 /*
2 * Copyright (c) 2001, Adam Dunkels.
3 * Copyright (c) 2009, 2010 Joakim Eriksson, Niclas Finne, Dogan Yazar.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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
16 * written permission.
17 *
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.
29 *
30 * This file is part of the uIP TCP/IP stack.
31 *
32 *
33 */
34
35 /* Below define allows importing saved output into Wireshark as "Raw IP" packet type */
36 #define WIRESHARK_IMPORT_FORMAT 1
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <stdarg.h>
41 #include <string.h>
42 #include <time.h>
43 #include <sys/time.h>
44 #include <sys/types.h>
45 #include <sys/wait.h>
46
47 #include <unistd.h>
48 #include <errno.h>
49 #include <fcntl.h>
50 #include <signal.h>
51 #include <termios.h>
52 #include <sys/ioctl.h>
53
54 #include <sys/socket.h>
55 #include <netinet/in.h>
56 #include <arpa/inet.h>
57 #include <netdb.h>
58
59 #include <err.h>
60
61 int verbose = 1;
62 int make = 1;
63 const char *ipaddr;
64 const char *netmask;
65 int slipfd = 0;
66 FILE *inslip = NULL;
67 uint16_t basedelay=0,delaymsec=0;
68 uint32_t startsec,startmsec,delaystartsec,delaystartmsec;
69 int timestamp = 0, flowcontrol=0;
70 unsigned int vnet_hdr=0;
71 const char *siodev = NULL;
72 const char *host = NULL;
73 const char *port = NULL;
74 #define VNET_HDR_LENGTH 10
75
76 int ssystem(const char *fmt, ...)
77 __attribute__((__format__ (__printf__, 1, 2)));
78 void write_to_serial(int outfd, void *inbuf, int len);
79
80 int devopen(const char *dev, int flags);
81 void stty_telos(int fd);
82
83 int get_slipfd();
84 void slip_send(int fd, unsigned char c);
85 void slip_send_char(int fd, unsigned char c);
86
87 //#define PROGRESS(s) fprintf(stderr, s)
88 #define PROGRESS(s) do { } while (0)
89
90 char tundev[1024] = { "" };
91
92 int
93 ssystem(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2)));
94
95 int
ssystem(const char * fmt,...)96 ssystem(const char *fmt, ...)
97 {
98 char cmd[128];
99 va_list ap;
100 va_start(ap, fmt);
101 vsnprintf(cmd, sizeof(cmd), fmt, ap);
102 va_end(ap);
103 printf("%s\n", cmd);
104 fflush(stdout);
105 return system(cmd);
106 }
107
108 #define SLIP_END 0300
109 #define SLIP_ESC 0333
110 #define SLIP_ESC_END 0334
111 #define SLIP_ESC_ESC 0335
112
113
114 /* get sockaddr, IPv4 or IPv6: */
115 void *
get_in_addr(struct sockaddr * sa)116 get_in_addr(struct sockaddr *sa)
117 {
118 if(sa->sa_family == AF_INET) {
119 return &(((struct sockaddr_in*)sa)->sin_addr);
120 }
121 return &(((struct sockaddr_in6*)sa)->sin6_addr);
122 }
123 void
stamptime(void)124 stamptime(void)
125 {
126 static long startsecs=0,startmsecs=0;
127 long secs,msecs;
128 struct timeval tv;
129 time_t t;
130 struct tm *tmp;
131 char timec[20];
132
133 gettimeofday(&tv, NULL) ;
134 msecs=tv.tv_usec/1000;
135 secs=tv.tv_sec;
136 if (startsecs) {
137 secs -=startsecs;
138 msecs-=startmsecs;
139 if (msecs<0) {secs--;msecs+=1000;}
140 fprintf(stderr,"%04lu.%03lu ", secs, msecs);
141 } else {
142 startsecs=secs;
143 startmsecs=msecs;
144 t=time(NULL);
145 tmp=localtime(&t);
146 strftime(timec,sizeof(timec),"%T",tmp);
147 // fprintf(stderr,"\n%s.%03lu ",timec,msecs);
148 fprintf(stderr,"\n%s ",timec);
149 }
150 }
151
152 int
is_sensible_string(const unsigned char * s,int len)153 is_sensible_string(const unsigned char *s, int len)
154 {
155 int i;
156 for(i = 1; i < len; i++) {
157 if(s[i] == 0 || s[i] == '\r' || s[i] == '\n' || s[i] == '\t') {
158 continue;
159 } else if(s[i] < ' ' || '~' < s[i]) {
160 return 0;
161 }
162 }
163 return 1;
164 }
165
166 /*
167 * Read from serial, when we have a packet write it to tun. No output
168 * buffering, input buffered by stdio.
169 */
170 void
serial_to_tun(FILE * inslip,int outfd)171 serial_to_tun(FILE *inslip, int outfd)
172 {
173 static struct {
174 unsigned char vnet_header[VNET_HDR_LENGTH];
175 unsigned char inbuf[2000];
176 } uip = { .vnet_header = { 0 } };
177 static int inbufptr = 0;
178 int ret,i;
179 unsigned char c;
180
181 #ifdef linux
182 ret = fread(&c, 1, 1, inslip);
183 if(ret == -1 || ret == 0) {
184 if (get_slipfd()) return;
185 err(1, "serial_to_tun: read");
186 }
187 goto after_fread;
188 #endif
189
190 read_more:
191 if(inbufptr >= sizeof(uip.inbuf)) {
192 if(timestamp) stamptime();
193 fprintf(stderr, "*** dropping large %d byte packet\n",inbufptr);
194 inbufptr = 0;
195 }
196 ret = fread(&c, 1, 1, inslip);
197 #ifdef linux
198 after_fread:
199 #endif
200 if(ret == -1 && errno == -EINTR) {
201 /* Can be QEMU or other restarting, retry */
202 ret = 0;
203 }
204 if(ret == -1) {
205 err(1, "serial_to_tun: read");
206 }
207 if(ret == 0) {
208 clearerr(inslip);
209 return;
210 }
211 /* fprintf(stderr, ".");*/
212 switch(c) {
213 case SLIP_END:
214 if(inbufptr > 0) {
215 if(uip.inbuf[0] == '!') {
216 if(uip.inbuf[1] == 'M') {
217 /* Read gateway MAC address and autoconfigure tap0 interface */
218 char macs[24];
219 int i, pos;
220 for(i = 0, pos = 0; i < 16; i++) {
221 macs[pos++] = uip.inbuf[2 + i];
222 if((i & 1) == 1 && i < 14) {
223 macs[pos++] = ':';
224 }
225 }
226 if(timestamp) stamptime();
227 macs[pos] = '\0';
228 // printf("*** Gateway's MAC address: %s\n", macs);
229 fprintf(stderr,"*** Gateway's MAC address: %s\n", macs);
230 if (make) {
231 if (timestamp) stamptime();
232 ssystem("ifconfig %s down", tundev);
233 if (timestamp) stamptime();
234 ssystem("ifconfig %s hw ether %s", tundev, &macs[6]);
235 if (timestamp) stamptime();
236 ssystem("ifconfig %s up", tundev);
237 }
238 }
239 } else if(uip.inbuf[0] == '?') {
240 if(uip.inbuf[1] == 'P') {
241 /* Prefix info requested */
242 struct in6_addr addr;
243 int i;
244 char *s = strchr(ipaddr, '/');
245 if(s != NULL) {
246 *s = '\0';
247 }
248 inet_pton(AF_INET6, ipaddr, &addr);
249 if(timestamp) stamptime();
250 fprintf(stderr,"*** Address:%s => %02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
251 // printf("*** Address:%s => %02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
252 ipaddr,
253 addr.s6_addr[0], addr.s6_addr[1],
254 addr.s6_addr[2], addr.s6_addr[3],
255 addr.s6_addr[4], addr.s6_addr[5],
256 addr.s6_addr[6], addr.s6_addr[7]);
257 slip_send(slipfd, '!');
258 slip_send(slipfd, 'P');
259 for(i = 0; i < 8; i++) {
260 /* need to call the slip_send_char for stuffing */
261 slip_send_char(slipfd, addr.s6_addr[i]);
262 }
263 slip_send(slipfd, SLIP_END);
264 }
265 #define DEBUG_LINE_MARKER '\r'
266 } else if(uip.inbuf[0] == DEBUG_LINE_MARKER) {
267 fwrite(uip.inbuf + 1, inbufptr - 1, 1, stdout);
268 } else if(is_sensible_string(uip.inbuf, inbufptr)) {
269 if(verbose==1) { /* strings already echoed below for verbose>1 */
270 if (timestamp) stamptime();
271 fwrite(uip.inbuf, inbufptr, 1, stdout);
272 }
273 } else {
274 if(verbose>2) {
275 if (timestamp) stamptime();
276 printf("%s: Packet from SLIP of length %d - write TUN\n",
277 tundev, inbufptr);
278 if (verbose>4) {
279 #if WIRESHARK_IMPORT_FORMAT
280 printf("%s: 0000", tundev);
281 if (vnet_hdr) {
282 for(i = 0; i < sizeof(uip.vnet_header); i++)
283 printf(" %02x",uip.vnet_header[i]);
284 }
285 for(i = 0; i < inbufptr; i++)
286 printf(" %02x",uip.inbuf[i]);
287 #else
288 printf(" ");
289 if (vnet_hdr) {
290 for(i = 0; i < sizeof(uip.vnet_header); i++) {
291 printf("%02x", uip.vnet_header[i]);
292 if((i & 3) == 3) printf(" ");
293 if((i & 15) == 15) printf("\n%s: ", tundev);
294 }
295 }
296 for(i = 0; i < inbufptr; i++) {
297 printf("%02x", uip.inbuf[i]);
298 if((i & 3) == 3) printf(" ");
299 if((i & 15) == 15) printf("\n%s: ", tundev);
300 }
301 #endif
302 printf("\n");
303 }
304 }
305 unsigned count_errs = 0;
306 struct timespec ts = { .tv_sec = 0, .tv_nsec = 500000000 };
307 size_t total_size = inbufptr;
308 if (vnet_hdr)
309 total_size += sizeof(uip.vnet_header);
310
311 while(1) {
312 if (vnet_hdr) {
313 if (write(outfd, (void *) &uip, total_size) == total_size)
314 break;
315 } else {
316 if(write(outfd, (void *) uip.inbuf, total_size) == total_size)
317 break;
318 }
319 if(count_errs > 10) {
320 err(1, "serial_to_tun: write");
321 break;
322 }
323 count_errs++;
324 if (0)
325 fprintf(stderr, "DEBUG: retrying %d\n", count_errs);
326 nanosleep(&ts, NULL);
327 }
328 }
329 inbufptr = 0;
330 }
331 break;
332
333 case SLIP_ESC:
334 if(fread(&c, 1, 1, inslip) != 1) {
335 clearerr(inslip);
336 /* Put ESC back and give up! */
337 ungetc(SLIP_ESC, inslip);
338 return;
339 }
340
341 switch(c) {
342 case SLIP_ESC_END:
343 c = SLIP_END;
344 break;
345 case SLIP_ESC_ESC:
346 c = SLIP_ESC;
347 break;
348 }
349 /* FALLTHROUGH */
350 default:
351 uip.inbuf[inbufptr++] = c;
352
353 /* Echo lines as they are received for verbose=2,3,5+ */
354 /* Echo all printable characters for verbose==4 */
355 if((verbose==2) || (verbose==3) || (verbose>4)) {
356 if(c=='\n') {
357 if(is_sensible_string(uip.inbuf, inbufptr)) {
358 if (timestamp) stamptime();
359 fwrite(uip.inbuf, inbufptr, 1, stdout);
360 }
361 }
362 } else if(verbose==4) {
363 if(c == 0 || c == '\r' || c == '\n' || c == '\t' || (c >= ' ' && c <= '~')) {
364 fwrite(&c, 1, 1, stdout);
365 if(c=='\n') if(timestamp) stamptime();
366 }
367 }
368
369 break;
370 }
371
372 goto read_more;
373 }
374
375 unsigned char slip_buf[3028];
376 int slip_end, slip_begin;
377
flush_neighbors(const char * tundev)378 static void flush_neighbors(const char *tundev)
379 {
380 ssystem("ip neigh flush dev %s", tundev);
381 }
382
383 int
get_slipfd()384 get_slipfd()
385 {
386 const int start_i = 20;
387 int status, i, fd = -1;
388 struct timeval sleep_for = {
389 .tv_sec = 0, /* seconds */
390 .tv_usec = 200000 /* microseconds */
391 };
392
393 /* Try to acquire slipfd a few times */
394 for (i = start_i; i > 0; --i) {
395 if (i != start_i) {
396 select(0, NULL, NULL, NULL, &sleep_for);
397 }
398
399 if(host != NULL) {
400 struct addrinfo hints, *servinfo, *p;
401 int rv;
402 char s[INET6_ADDRSTRLEN];
403
404 if(port == NULL) {
405 port = "60001";
406 }
407
408 memset(&hints, 0, sizeof hints);
409 hints.ai_family = AF_UNSPEC;
410 hints.ai_socktype = SOCK_STREAM;
411
412 if((rv = getaddrinfo(host, port, &hints, &servinfo)) != 0) {
413 fprintf(stderr, "getaddrinfo: %s", gai_strerror(rv));
414 continue;
415 }
416
417 /* loop through all the results and connect to the first we can */
418 for(p = servinfo; p != NULL; p = p->ai_next) {
419 if((fd = socket(p->ai_family, p->ai_socktype,
420 p->ai_protocol)) == -1) {
421 perror("client: socket");
422 continue;
423 }
424
425 if(connect(fd, p->ai_addr, p->ai_addrlen) == -1) {
426 close(fd);
427 perror("client: connect");
428 continue;
429 }
430 break;
431 }
432
433 if(p == NULL) {
434 fprintf(stderr, "can't connect to ``%s:%s''\n", host, port);
435 continue;
436 }
437
438 fcntl(fd, F_SETFL, O_NONBLOCK);
439
440 inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
441 s, sizeof(s));
442 fprintf(stderr, "slip connected to ``%s:%s''\n", s, port);
443
444 /* all done with this structure */
445 freeaddrinfo(servinfo);
446
447 } else {
448 if(siodev != NULL) {
449 fd = devopen(siodev, O_RDWR | O_NONBLOCK);
450 if(fd == -1) {
451 fprintf(stderr, "can't open siodev ``%s''\n", siodev);
452 continue;
453 }
454 } else {
455 static const char *siodevs[] = {
456 "ttyUSB0", "cuaU0", "ucom0" /* linux, fbsd6, fbsd5 */
457 };
458 int i;
459 for(i = 0; i < 3; i++) {
460 siodev = siodevs[i];
461 fd = devopen(siodev, O_RDWR | O_NONBLOCK);
462 if(fd != -1) {
463 break;
464 }
465 }
466 if(fd == -1) {
467 fprintf(stderr, "can't open siodev\n");
468 continue;
469 }
470 }
471 if (timestamp) stamptime();
472 if (siodev[0] != '/') {
473 fprintf(stderr, "********SLIP started on ``/dev/%s''\n", siodev);
474 } else {
475 fprintf(stderr, "********SLIP started on ``%s''\n", siodev);
476 }
477 stty_telos(fd);
478 }
479
480 slip_send(fd, SLIP_END);
481 inslip = fdopen(fd, "r");
482 if(inslip == NULL) {
483 printf("get_slipfd: fdopen failed\n");
484 continue;
485 }
486
487 slipfd = fd;
488
489 printf("slipfd and inslip reopened\n");
490 flush_neighbors(tundev);
491 return 1;
492 }
493
494 return 0;
495 }
496
497 void
slip_send_char(int fd,unsigned char c)498 slip_send_char(int fd, unsigned char c)
499 {
500 switch(c) {
501 case SLIP_END:
502 slip_send(fd, SLIP_ESC);
503 slip_send(fd, SLIP_ESC_END);
504 break;
505 case SLIP_ESC:
506 slip_send(fd, SLIP_ESC);
507 slip_send(fd, SLIP_ESC_ESC);
508 break;
509 default:
510 slip_send(fd, c);
511 break;
512 }
513 }
514
515 void
slip_send(int fd,unsigned char c)516 slip_send(int fd, unsigned char c)
517 {
518 if(slip_end >= sizeof(slip_buf)) {
519 err(1, "slip_send overflow");
520 }
521 slip_buf[slip_end] = c;
522 slip_end++;
523 }
524
525 int
slip_empty()526 slip_empty()
527 {
528 return slip_end == 0;
529 }
530
531 void
slip_flushbuf(int fd)532 slip_flushbuf(int fd)
533 {
534 int n;
535
536 if(slip_empty()) {
537 return;
538 }
539
540 slip_flushbuf_try_again:
541 n = write(fd, slip_buf + slip_begin, (slip_end - slip_begin));
542
543 if(n == -1 && errno != EAGAIN) {
544 if (get_slipfd()) goto slip_flushbuf_try_again;
545 err(1, "slip_flushbuf write failed");
546 } else if(n == -1) {
547 PROGRESS("Q"); /* Outqueueis full! */
548 } else {
549 slip_begin += n;
550 if(slip_begin == slip_end) {
551 slip_begin = slip_end = 0;
552 }
553 }
554 }
555
556 void
write_to_serial(int outfd,void * inbuf,int len)557 write_to_serial(int outfd, void *inbuf, int len)
558 {
559 u_int8_t *p = inbuf;
560 int i;
561
562 if(verbose>2) {
563 if (timestamp) stamptime();
564 printf("%s: Packet from TUN of length %d - write SLIP\n", tundev, len);
565 if (verbose>4) {
566 #if WIRESHARK_IMPORT_FORMAT
567 printf("%s: 0000", tundev);
568 for(i = 0; i < len; i++) printf(" %02x", p[i]);
569 #else
570 printf(" ");
571 for(i = 0; i < len; i++) {
572 printf("%02x", p[i]);
573 if((i & 3) == 3) printf(" ");
574 if((i & 15) == 15) printf("\n%s: ", tundev);
575 }
576 #endif
577 printf("\n");
578 }
579 }
580
581 /* It would be ``nice'' to send a SLIP_END here but it's not
582 * really necessary.
583 */
584 /* slip_send(outfd, SLIP_END); */
585 if (vnet_hdr) {
586 /* We don't even parse the VNET header, we just skip it */
587 i = VNET_HDR_LENGTH;
588 } else {
589 i = 0;
590 }
591
592 for(; i < len; i++) {
593 switch(p[i]) {
594 case SLIP_END:
595 slip_send(outfd, SLIP_ESC);
596 slip_send(outfd, SLIP_ESC_END);
597 break;
598 case SLIP_ESC:
599 slip_send(outfd, SLIP_ESC);
600 slip_send(outfd, SLIP_ESC_ESC);
601 break;
602 default:
603 slip_send(outfd, p[i]);
604 break;
605 }
606 }
607 slip_send(outfd, SLIP_END);
608 PROGRESS("t");
609 }
610
611
612 /*
613 * Read from tun, write to slip.
614 */
615 int
tun_to_serial(int infd,int outfd)616 tun_to_serial(int infd, int outfd)
617 {
618 struct {
619 unsigned char inbuf[2000];
620 } uip;
621 int size;
622
623 if((size = read(infd, uip.inbuf, 2000)) == -1) err(1, "tun_to_serial: read");
624
625 write_to_serial(outfd, uip.inbuf, size);
626 return size;
627 }
628
629 #ifndef BAUDRATE
630 #define BAUDRATE B115200
631 #endif
632 speed_t b_rate = BAUDRATE;
633
634 void
stty_telos(int fd)635 stty_telos(int fd)
636 {
637 struct termios tty;
638 speed_t speed = b_rate;
639 int i;
640
641 if(tcflush(fd, TCIOFLUSH) == -1) err(1, "tcflush");
642
643 if(tcgetattr(fd, &tty) == -1) err(1, "tcgetattr");
644
645 cfmakeraw(&tty);
646
647 /* Nonblocking read. */
648 tty.c_cc[VTIME] = 0;
649 tty.c_cc[VMIN] = 0;
650 if (flowcontrol)
651 tty.c_cflag |= CRTSCTS;
652 else
653 tty.c_cflag &= ~CRTSCTS;
654 tty.c_cflag &= ~HUPCL;
655 tty.c_cflag &= ~CLOCAL;
656
657 cfsetispeed(&tty, speed);
658 cfsetospeed(&tty, speed);
659
660 if(tcsetattr(fd, TCSAFLUSH, &tty) == -1) err(1, "tcsetattr");
661
662 #if 1
663 /* Nonblocking read and write. */
664 /* if(fcntl(fd, F_SETFL, O_NONBLOCK) == -1) err(1, "fcntl"); */
665
666 tty.c_cflag |= CLOCAL;
667 if(tcsetattr(fd, TCSAFLUSH, &tty) == -1) err(1, "tcsetattr");
668
669 i = TIOCM_DTR;
670
671 //if(ioctl(fd, TIOCMBIS, &i) == -1) err(1, "ioctl");
672 #endif
673
674 usleep(10*1000); /* Wait for hardware 10ms. */
675
676 /* Flush input and output buffers. */
677 if(tcflush(fd, TCIOFLUSH) == -1) err(1, "tcflush");
678 }
679
680 int
devopen_readlink(const char * dev,int flags)681 devopen_readlink(const char *dev, int flags)
682 {
683 int fd = open(dev, flags);
684 /* Failed to open, maybe its a symlink? Try readlink. */
685 if (fd < 0) {
686 const int buf_size = 255;
687 char buf[buf_size];
688 int i;
689 i = readlink(dev, buf, buf_size);
690 if (i < 0 || i >= buf_size) {
691 return fd; /* We failed to readlink, return original error code. */
692 }
693 buf[i] = '\0';
694 if (verbose > 2) {
695 printf("Trying to open: '%s'\n", buf);
696 }
697 return open(buf, flags);
698 }
699 return fd;
700 }
701
702 int
devopen(const char * dev,int flags)703 devopen(const char *dev, int flags)
704 {
705 if (dev[0] != '/') {
706 char t[1024];
707 strcpy(t, "/dev/");
708 strncat(t, dev, sizeof(t) - 5);
709 return devopen_readlink(t, flags);
710 } else {
711 return devopen_readlink(dev, flags);
712 }
713 }
714
715 #ifdef linux
716 #include <linux/if.h>
717 #include <linux/if_tun.h>
718
719 int
tun_alloc(char * dev,int tap,int make)720 tun_alloc(char *dev, int tap, int make)
721 {
722 struct ifreq ifr;
723 int fd, err;
724
725 if (!make)
726 return devopen(dev, O_RDWR);
727
728 if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
729 return -1;
730 }
731
732 memset(&ifr, 0, sizeof(ifr));
733
734 /* Flags: IFF_TUN - TUN device (no Ethernet headers)
735 * IFF_TAP - TAP device
736 *
737 * IFF_NO_PI - Do not provide packet information
738 */
739 ifr.ifr_flags = (tap ? IFF_TAP : IFF_TUN) | IFF_NO_PI;
740 if(*dev != 0)
741 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
742
743 if((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) {
744 close(fd);
745 return err;
746 }
747 strcpy(dev, ifr.ifr_name);
748 return fd;
749 }
750 #else
751 int
tun_alloc(char * dev,int tap,int make)752 tun_alloc(char *dev, int tap, int make)
753 {
754 return devopen(dev, O_RDWR);
755 }
756 #endif
757
758 void
cleanup(void)759 cleanup(void)
760 {
761 if (ipaddr == NULL) {
762 /* no configuration was done in this case by ifconf, we let the
763 * user take care of it */
764 return;
765 }
766 #ifndef __APPLE__
767 if (make) {
768 if (timestamp) stamptime();
769 ssystem("ifconfig %s down", tundev);
770 #ifndef linux
771 ssystem("sysctl -w net.ipv6.conf.all.forwarding=1");
772 #endif
773 /* ssystem("arp -d %s", ipaddr); */
774 if (timestamp) stamptime();
775 ssystem("netstat -nr"
776 " | awk '{ if ($2 == \"%s\") print \"route delete -net \"$1; }'"
777 " | sh",
778 tundev);
779 }
780 #else
781 if (make) {
782 char * itfaddr = strdup(ipaddr);
783 char * prefix = index(itfaddr, '/');
784 if (timestamp) stamptime();
785 ssystem("ifconfig %s inet6 %s remove", tundev, ipaddr);
786 if (timestamp) stamptime();
787 ssystem("ifconfig %s down", tundev);
788 if ( prefix != NULL ) *prefix = '\0';
789 ssystem("route delete -inet6 %s", itfaddr);
790 free(itfaddr);
791 }
792 #endif
793 }
794
795 void
sigcleanup(int signo)796 sigcleanup(int signo)
797 {
798 fprintf(stderr, "signal %d\n", signo);
799 exit(0); /* exit(0) will call cleanup() */
800 }
801
802 static int got_sigalarm;
803
804 void
sigalarm(int signo)805 sigalarm(int signo)
806 {
807 got_sigalarm = 1;
808 return;
809 }
810
811 void
sigalarm_reset()812 sigalarm_reset()
813 {
814 #ifdef linux
815 #define TIMEOUT (997*1000)
816 #else
817 #define TIMEOUT (2451*1000)
818 #endif
819 ualarm(TIMEOUT, TIMEOUT);
820 got_sigalarm = 0;
821 }
822
823 void
ifconf(const char * tundev,const char * ipaddr,int tap)824 ifconf(const char *tundev, const char *ipaddr, int tap)
825 {
826 if (!make)
827 return;
828 if (ipaddr == NULL) {
829 /* No ipaddr; the user will do it manually */
830 return;
831 }
832 #ifdef linux
833 if (timestamp) stamptime();
834 if (!tap) {
835 ssystem("ifconfig %s inet `hostname` up", tundev);
836 ssystem("ifconfig %s add %s", tundev, ipaddr);
837 } else {
838 ssystem("ifconfig %s up", tundev);
839 ssystem("ip -6 route add 2001:db8::/64 dev %s", tundev);
840 ssystem("ip -6 addr add 2001:db8::2/64 dev %s", tundev);
841 ssystem("ip route add 192.0.2.0/24 dev %s", tundev);
842 ssystem("ip addr add 192.0.2.2/24 dev %s", tundev);
843 }
844 if (timestamp) stamptime();
845
846 /* radvd needs a link local address for routing */
847 #if 0
848 /* fe80::1/64 is good enough */
849 ssystem("ifconfig %s add fe80::1/64", tundev);
850 #elif 1
851 /* Generate a link local address a la sixxs/aiccu */
852 /* First a full parse, stripping off the prefix length */
853 if (!tap) {
854 char lladdr[40];
855 char c, *ptr=(char *)ipaddr;
856 uint16_t digit,ai,a[8],cc,scc,i;
857 for(ai=0; ai<8; ai++) {
858 a[ai]=0;
859 }
860 ai=0;
861 cc=scc=0;
862 while(c=*ptr++) {
863 if(c=='/') break;
864 if(c==':') {
865 if(cc)
866 scc = ai;
867 cc = 1;
868 if(++ai>7) break;
869 } else {
870 cc=0;
871 digit = c-'0';
872 if (digit > 9)
873 digit = 10 + (c & 0xdf) - 'A';
874 a[ai] = (a[ai] << 4) + digit;
875 }
876 }
877 /* Get # elided and shift what's after to the end */
878 cc=8-ai;
879 for(i=0;i<cc;i++) {
880 if ((8-i-cc) <= scc) {
881 a[7-i] = 0;
882 } else {
883 a[7-i] = a[8-i-cc];
884 a[8-i-cc]=0;
885 }
886 }
887 sprintf(lladdr,"fe80::%x:%x:%x:%x",a[1]&0xfefd,a[2],a[3],a[7]);
888 if (timestamp) stamptime();
889 ssystem("ifconfig %s add %s/64", tundev, lladdr);
890 }
891 #endif /* link local */
892 #elif defined(__APPLE__)
893 {
894 char * itfaddr = strdup(ipaddr);
895 char * prefix = index(itfaddr, '/');
896 if ( prefix != NULL ) {
897 *prefix = '\0';
898 prefix++;
899 } else {
900 prefix = "64";
901 }
902 if (timestamp) stamptime();
903 ssystem("ifconfig %s inet6 up", tundev );
904 if (timestamp) stamptime();
905 ssystem("ifconfig %s inet6 %s add", tundev, ipaddr );
906 if (timestamp) stamptime();
907 ssystem("sysctl -w net.inet6.ip6.forwarding=1");
908 free(itfaddr);
909 }
910 #else
911 if (timestamp) stamptime();
912 ssystem("ifconfig %s inet `hostname` %s up", tundev, ipaddr);
913 if (timestamp) stamptime();
914 ssystem("sysctl -w net.inet.ip.forwarding=1");
915 #endif /* !linux */
916
917 if (timestamp) stamptime();
918 ssystem("ifconfig %s\n", tundev);
919 }
920
921 int
main(int argc,char ** argv)922 main(int argc, char **argv)
923 {
924 int c;
925 int tunfd, maxfd;
926 int ret;
927 fd_set rset, wset;
928 const char *prog;
929 int baudrate = -2;
930 int tap = 0;
931 slipfd = 0;
932
933 prog = argv[0];
934 setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */
935
936 while((c = getopt(argc, argv, "B:HNxLhs:t:v::d::a:p:T")) != -1) {
937 switch(c) {
938 case 'B':
939 baudrate = atoi(optarg);
940 break;
941
942 case 'H':
943 flowcontrol=1;
944 break;
945
946 case 'L':
947 timestamp=1;
948 break;
949
950 case 'x':
951 make=0;
952 break;
953
954 case 'N':
955 vnet_hdr=1;
956 break;
957
958 case 's':
959 if(strncmp("/dev/", optarg, 5) == 0) {
960 siodev = optarg + 5;
961 } else {
962 siodev = optarg;
963 }
964 break;
965
966 case 't':
967 if(strncmp("/dev/", optarg, 5) == 0) {
968 strncpy(tundev, optarg + 5, sizeof(tundev));
969 } else {
970 strncpy(tundev, optarg, sizeof(tundev));
971 }
972 break;
973
974 case 'a':
975 host = optarg;
976 break;
977
978 case 'p':
979 port = optarg;
980 break;
981
982 case 'd':
983 basedelay = 10;
984 if (optarg) basedelay = atoi(optarg);
985 break;
986
987 case 'v':
988 verbose = 2;
989 if (optarg) verbose = atoi(optarg);
990 break;
991
992 case 'T':
993 tap = 1;
994 break;
995
996 case '?':
997 case 'h':
998 default:
999 fprintf(stderr,"usage: %s [options] [ipaddress]\n", prog);
1000 fprintf(stderr,"example: tunslip6 -L -v2 -s ttyUSB1 2001:db8::1/64\n");
1001 fprintf(stderr,"Options are:\n");
1002 #ifndef __APPLE__
1003 fprintf(stderr," -B baudrate 9600,19200,38400,57600,115200 (default),230400,460800,921600\n");
1004 #else
1005 fprintf(stderr," -B baudrate 9600,19200,38400,57600,115200 (default),230400\n");
1006 #endif
1007 fprintf(stderr," -H Hardware CTS/RTS flow control (default disabled)\n");
1008 fprintf(stderr," -L Log output format (adds time stamps)\n");
1009 fprintf(stderr," -s siodev Serial device (default /dev/ttyUSB0)\n");
1010 fprintf(stderr," -T Make tap interface (default is tun interface)\n");
1011 fprintf(stderr," -x Reuse tun device instead of creating a new one;\n"
1012 " likewise do not attempt to configure the device\n");
1013 fprintf(stderr," -N add (and remove) a VNET header\n");
1014 fprintf(stderr," -t tundev Name of interface (default tap0 or tun0)\n");
1015 fprintf(stderr," -v[level] Verbosity level\n");
1016 fprintf(stderr," -v0 No messages\n");
1017 fprintf(stderr," -v1 Encapsulated SLIP debug messages (default)\n");
1018 fprintf(stderr," -v2 Printable strings after they are received\n");
1019 fprintf(stderr," -v3 Printable strings and SLIP packet notifications\n");
1020 fprintf(stderr," -v4 All printable characters as they are received\n");
1021 fprintf(stderr," -v5 All SLIP packets in hex\n");
1022 fprintf(stderr," -v Equivalent to -v3\n");
1023 fprintf(stderr," -d[basedelay] Minimum delay between outgoing SLIP packets.\n");
1024 fprintf(stderr," Actual delay is basedelay*(#6LowPAN fragments) milliseconds.\n");
1025 fprintf(stderr," -d is equivalent to -d10.\n");
1026 fprintf(stderr," -a serveraddr \n");
1027 fprintf(stderr," -p serverport \n");
1028 exit(1);
1029 break;
1030 }
1031 }
1032 argc -= (optind - 1);
1033 argv += (optind - 1);
1034
1035 if(argc > 3) {
1036 err(1, "usage: %s [-B baudrate] [-N] [-x] [-H] [-L] [-s siodev] [-t tundev] [-T] [-v verbosity] [-d delay] [-a serveraddress] [-p serverport] [ipaddress]", prog);
1037 }
1038 if (argc == 2)
1039 ipaddr = argv[1];
1040 else
1041 ipaddr = NULL;
1042
1043 switch(baudrate) {
1044 case -2:
1045 break; /* Use default. */
1046 case 9600:
1047 b_rate = B9600;
1048 break;
1049 case 19200:
1050 b_rate = B19200;
1051 break;
1052 case 38400:
1053 b_rate = B38400;
1054 break;
1055 case 57600:
1056 b_rate = B57600;
1057 break;
1058 case 115200:
1059 b_rate = B115200;
1060 break;
1061 case 230400:
1062 b_rate = B230400;
1063 break;
1064 #ifndef __APPLE__
1065 case 460800:
1066 b_rate = B460800;
1067 break;
1068 case 921600:
1069 b_rate = B921600;
1070 break;
1071 #endif
1072 default:
1073 err(1, "unknown baudrate %d", baudrate);
1074 break;
1075 }
1076
1077 if(*tundev == '\0') {
1078 /* Use default. */
1079 if(tap) {
1080 strcpy(tundev, "tap0");
1081 } else {
1082 strcpy(tundev, "tun0");
1083 }
1084 }
1085
1086 get_slipfd();
1087
1088 tunfd = tun_alloc(tundev, tap, make);
1089 if(tunfd == -1) err(1, "main: open");
1090 if (timestamp) stamptime();
1091 fprintf(stderr, "opened %s device ``/dev/%s''\n",
1092 tap ? "tap" : "tun", tundev);
1093
1094 atexit(cleanup);
1095 signal(SIGHUP, sigcleanup);
1096 signal(SIGTERM, sigcleanup);
1097 signal(SIGINT, sigcleanup);
1098 signal(SIGALRM, sigalarm);
1099 ifconf(tundev, ipaddr, tap);
1100
1101 while(1) {
1102 maxfd = 0;
1103 FD_ZERO(&rset);
1104 FD_ZERO(&wset);
1105
1106 /* do not send IPA all the time... - add get MAC later... */
1107 /* if(got_sigalarm) { */
1108 /* /\* Send "?IPA". *\/ */
1109 /* slip_send(slipfd, '?'); */
1110 /* slip_send(slipfd, 'I'); */
1111 /* slip_send(slipfd, 'P'); */
1112 /* slip_send(slipfd, 'A'); */
1113 /* slip_send(slipfd, SLIP_END); */
1114 /* got_sigalarm = 0; */
1115 /* } */
1116
1117 if(!slip_empty()) { /* Anything to flush? */
1118 FD_SET(slipfd, &wset);
1119 }
1120
1121 FD_SET(slipfd, &rset); /* Read from slip ASAP! */
1122 if(slipfd > maxfd) maxfd = slipfd;
1123
1124 /* We only have one packet at a time queued for slip output. */
1125 if(slip_empty()) {
1126 FD_SET(tunfd, &rset);
1127 if(tunfd > maxfd) maxfd = tunfd;
1128 }
1129
1130 ret = select(maxfd + 1, &rset, &wset, NULL, NULL);
1131 if(ret == -1 && errno != EINTR) {
1132 err(1, "select");
1133 } else if(ret > 0) {
1134 if(FD_ISSET(slipfd, &rset)) {
1135 serial_to_tun(inslip, tunfd);
1136 }
1137
1138 if(FD_ISSET(slipfd, &wset)) {
1139 slip_flushbuf(slipfd);
1140 sigalarm_reset();
1141 }
1142
1143 /* Optional delay between outgoing packets */
1144 /* Base delay times number of 6lowpan fragments to be sent */
1145 if(delaymsec) {
1146 struct timeval tv;
1147 int dmsec;
1148 gettimeofday(&tv, NULL) ;
1149 dmsec=(tv.tv_sec-delaystartsec)*1000+tv.tv_usec/1000-delaystartmsec;
1150 if(dmsec<0) delaymsec=0;
1151 if(dmsec>delaymsec) delaymsec=0;
1152 }
1153 if(delaymsec==0) {
1154 int size;
1155 if(slip_empty() && FD_ISSET(tunfd, &rset)) {
1156 size=tun_to_serial(tunfd, slipfd);
1157 slip_flushbuf(slipfd);
1158 sigalarm_reset();
1159 if(basedelay) {
1160 struct timeval tv;
1161 gettimeofday(&tv, NULL) ;
1162 // delaymsec=basedelay*(1+(size/120));//multiply by # of 6lowpan packets?
1163 delaymsec=basedelay;
1164 delaystartsec =tv.tv_sec;
1165 delaystartmsec=tv.tv_usec/1000;
1166 }
1167 }
1168 }
1169 }
1170 }
1171 }
1172