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