Add simple webserver for RPL status
[contiki-2.x.git] / tools / tunslip6.c
blob3ae75a17f9a290a75a2ef7a69e675d26d0ed248e
1 /*
2 * Copyright (c) 2001, Adam Dunkels.
3 * Copyright (c) 2009, 2010 Joakim Eriksson, Niclas Finne, Dogan Yazar.
4 * All rights reserved.
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.
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 $
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <stdarg.h>
39 #include <string.h>
40 #include <time.h>
41 #include <sys/types.h>
43 #include <unistd.h>
44 #include <errno.h>
45 #include <fcntl.h>
46 #include <signal.h>
47 #include <termios.h>
48 #include <sys/ioctl.h>
50 #include <sys/socket.h>
51 #include <netinet/in.h>
52 #include <arpa/inet.h>
53 #include <netdb.h>
55 #include <err.h>
57 int verbose = 1;
58 const char *ipaddr;
59 const char *netmask;
60 int slipfd = 0;
61 uint16_t basedelay=0,delaymsec=0;
62 uint32_t startsec,startmsec,delaystartsec,delaystartmsec;
63 int timestamp = 0;
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] = { "" };
76 int
77 ssystem(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2)));
79 int
80 ssystem(const char *fmt, ...)
82 char cmd[128];
83 va_list ap;
84 va_start(ap, fmt);
85 vsnprintf(cmd, sizeof(cmd), fmt, ap);
86 va_end(ap);
87 printf("%s\n", cmd);
88 fflush(stdout);
89 return system(cmd);
92 #define SLIP_END 0300
93 #define SLIP_ESC 0333
94 #define SLIP_ESC_END 0334
95 #define SLIP_ESC_ESC 0335
98 /* get sockaddr, IPv4 or IPv6: */
99 void *
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);
107 void
108 stamptime(void)
110 static long startsecs=0,startmsecs=0;
111 long secs,msecs;
112 struct timeval tv;
113 time_t t;
114 struct tm *tmp;
115 char timec[20];
117 gettimeofday(&tv, NULL) ;
118 msecs=tv.tv_usec/1000;
119 secs=tv.tv_sec;
120 if (startsecs) {
121 secs -=startsecs;
122 msecs-=startmsecs;
123 if (msecs<0) {secs--;msecs+=1000;}
124 fprintf(stderr,"%04lu.%03lu ", secs, msecs);
125 } else {
126 startsecs=secs;
127 startmsecs=msecs;
128 t=time(NULL);
129 tmp=localtime(&t);
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)
139 int i;
140 for(i = 1; i < len; i++) {
141 if(s[i] == 0 || s[i] == '\r' || s[i] == '\n' || s[i] == '\t') {
142 continue;
143 } else if(s[i] < ' ' || '~' < s[i]) {
144 return 0;
147 return 1;
151 * Read from serial, when we have a packet write it to tun. No output
152 * buffering, input buffered by stdio.
154 void
155 serial_to_tun(FILE *inslip, int outfd)
157 static union {
158 unsigned char inbuf[2000];
159 } uip;
160 static int inbufptr = 0;
161 int ret,i;
162 unsigned char c;
164 #ifdef linux
165 ret = fread(&c, 1, 1, inslip);
166 if(ret == -1 || ret == 0) err(1, "serial_to_tun: read");
167 goto after_fread;
168 #endif
170 read_more:
171 if(inbufptr >= sizeof(uip.inbuf)) {
172 inbufptr = 0;
173 if(timestamp) stamptime();
174 fprintf(stderr, "*** dropping too large packet\n");
176 ret = fread(&c, 1, 1, inslip);
177 #ifdef linux
178 after_fread:
179 #endif
180 if(ret == -1) {
181 err(1, "serial_to_tun: read");
183 if(ret == 0) {
184 clearerr(inslip);
185 return;
187 /* fprintf(stderr, ".");*/
188 switch(c) {
189 case SLIP_END:
190 if(inbufptr > 0) {
191 if(uip.inbuf[0] == '!') {
192 if(uip.inbuf[1] == 'M') {
193 /* Read gateway MAC address and autoconfigure tap0 interface */
194 char macs[24];
195 int i, pos;
196 for(i = 0, pos = 0; i < 16; i++) {
197 macs[pos++] = uip.inbuf[2 + i];
198 if((i & 1) == 1 && i < 14) {
199 macs[pos++] = ':';
202 if(timestamp) stamptime();
203 macs[pos] = '\0';
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;
215 int i;
216 char *s = strchr(ipaddr, '/');
217 if(s != NULL) {
218 *s = '\0';
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",
224 ipaddr,
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);
244 } else {
245 if(verbose>2) {
246 if (timestamp) stamptime();
247 printf("Packet from SLIP of length %d - write TUN\n", inbufptr);
248 if (verbose>4) {
249 printf(" ");
250 for(i = 0; i < inbufptr; i++) {
251 printf("%02x", uip.inbuf[i]);
252 if((i & 3) == 3) {
253 printf(" ");
255 if((i & 15) == 15)
256 printf("\n ");
258 printf("\n");
261 if(write(outfd, uip.inbuf, inbufptr) != inbufptr) {
262 err(1, "serial_to_tun: write");
265 inbufptr = 0;
267 break;
269 case SLIP_ESC:
270 if(fread(&c, 1, 1, inslip) != 1) {
271 clearerr(inslip);
272 /* Put ESC back and give up! */
273 ungetc(SLIP_ESC, inslip);
274 return;
277 switch(c) {
278 case SLIP_ESC_END:
279 c = SLIP_END;
280 break;
281 case SLIP_ESC_ESC:
282 c = SLIP_ESC;
283 break;
285 /* FALLTHROUGH */
286 default:
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)) {
292 if(c=='\n') {
293 if(is_sensible_string(uip.inbuf, inbufptr)) {
294 if (timestamp) stamptime();
295 fwrite(uip.inbuf, inbufptr, 1, stdout);
296 inbufptr=0;
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();
306 break;
309 goto read_more;
312 unsigned char slip_buf[2000];
313 int slip_end, slip_begin;
315 void
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;
322 slip_end++;
326 slip_empty()
328 return slip_end == 0;
331 void
332 slip_flushbuf(int fd)
334 int n;
336 if(slip_empty()) {
337 return;
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");
344 } else if(n == -1) {
345 PROGRESS("Q"); /* Outqueueis full! */
346 } else {
347 slip_begin += n;
348 if(slip_begin == slip_end) {
349 slip_begin = slip_end = 0;
354 void
355 write_to_serial(int outfd, void *inbuf, int len)
357 u_int8_t *p = inbuf;
358 int i;
360 if(verbose>2) {
361 if (timestamp) stamptime();
362 printf("Packet from TUN of length %d - write SLIP\n", len);
363 if (verbose>4) {
364 printf(" ");
365 for(i = 0; i < len; i++) {
366 printf("%02x", p[i]);
367 if((i & 3) == 3) {
368 printf(" ");
370 if((i & 15) == 15)
371 printf("\n ");
373 printf("\n");
377 /* It would be ``nice'' to send a SLIP_END here but it's not
378 * really necessary.
380 /* slip_send(outfd, SLIP_END); */
382 for(i = 0; i < len; i++) {
383 switch(p[i]) {
384 case SLIP_END:
385 slip_send(outfd, SLIP_ESC);
386 slip_send(outfd, SLIP_ESC_END);
387 break;
388 case SLIP_ESC:
389 slip_send(outfd, SLIP_ESC);
390 slip_send(outfd, SLIP_ESC_ESC);
391 break;
392 default:
393 slip_send(outfd, p[i]);
394 break;
397 slip_send(outfd, SLIP_END);
398 PROGRESS("t");
403 * Read from tun, write to slip.
406 tun_to_serial(int infd, int outfd)
408 struct {
409 unsigned char inbuf[2000];
410 } uip;
411 int size;
413 if((size = read(infd, uip.inbuf, 2000)) == -1) err(1, "tun_to_serial: read");
415 write_to_serial(outfd, uip.inbuf, size);
416 return size;
419 #ifndef BAUDRATE
420 #define BAUDRATE B115200
421 #endif
422 speed_t b_rate = BAUDRATE;
424 void
425 stty_telos(int fd)
427 struct termios tty;
428 speed_t speed = b_rate;
429 int i;
431 if(tcflush(fd, TCIOFLUSH) == -1) err(1, "tcflush");
433 if(tcgetattr(fd, &tty) == -1) err(1, "tcgetattr");
435 cfmakeraw(&tty);
437 /* Nonblocking read. */
438 tty.c_cc[VTIME] = 0;
439 tty.c_cc[VMIN] = 0;
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");
449 #if 1
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");
456 i = TIOCM_DTR;
457 if(ioctl(fd, TIOCMBIS, &i) == -1) err(1, "ioctl");
458 #endif
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)
469 char t[32];
470 strcpy(t, "/dev/");
471 strncat(t, dev, sizeof(t) - 5);
472 return open(t, flags);
475 #ifdef linux
476 #include <linux/if.h>
477 #include <linux/if_tun.h>
480 tun_alloc(char *dev, int tap)
482 struct ifreq ifr;
483 int fd, err;
485 if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
486 return -1;
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;
497 if(*dev != 0)
498 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
500 if((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) {
501 close(fd);
502 return err;
504 strcpy(dev, ifr.ifr_name);
505 return fd;
507 #else
509 tun_alloc(char *dev, int tap)
511 return devopen(dev, O_RDWR);
513 #endif
515 void
516 cleanup(void)
518 if (timestamp) stamptime();
519 ssystem("ifconfig %s down", tundev);
520 #ifndef linux
521 ssystem("sysctl -w net.ipv6.conf.all.forwarding=1");
522 #endif
523 /* ssystem("arp -d %s", ipaddr); */
524 if (timestamp) stamptime();
525 ssystem("netstat -nr"
526 " | awk '{ if ($2 == \"%s\") print \"route delete -net \"$1; }'"
527 " | sh",
528 tundev);
531 void
532 sigcleanup(int signo)
534 fprintf(stderr, "signal %d\n", signo);
535 exit(0); /* exit(0) will call cleanup() */
538 static int got_sigalarm;
540 void
541 sigalarm(int signo)
543 got_sigalarm = 1;
544 return;
547 void
548 sigalarm_reset()
550 #ifdef linux
551 #define TIMEOUT (997*1000)
552 #else
553 #define TIMEOUT (2451*1000)
554 #endif
555 ualarm(TIMEOUT, TIMEOUT);
556 got_sigalarm = 0;
559 void
560 ifconf(const char *tundev, const char *ipaddr)
562 #ifdef linux
563 if (timestamp) stamptime();
564 ssystem("ifconfig %s inet `hostname` up", tundev);
565 if (timestamp) stamptime();
566 ssystem("ifconfig %s add %s", tundev, ipaddr);
567 #else
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");
572 #endif /* !linux */
574 if (timestamp) stamptime();
575 ssystem("ifconfig %s\n", tundev);
579 main(int argc, char **argv)
581 int c;
582 int tunfd, maxfd;
583 int ret;
584 fd_set rset, wset;
585 FILE *inslip;
586 const char *siodev = NULL;
587 const char *host = NULL;
588 const char *port = NULL;
589 const char *prog;
590 int baudrate = -2;
591 int tap = 0;
592 slipfd = 0;
594 prog = argv[0];
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) {
598 switch(c) {
599 case 'B':
600 baudrate = atoi(optarg);
601 break;
603 case 'L':
604 timestamp=1;
605 break;
607 case 's':
608 if(strncmp("/dev/", optarg, 5) == 0) {
609 siodev = optarg + 5;
610 } else {
611 siodev = optarg;
613 break;
615 case 't':
616 if(strncmp("/dev/", optarg, 5) == 0) {
617 strncpy(tundev, optarg + 5, sizeof(tundev));
618 } else {
619 strncpy(tundev, optarg, sizeof(tundev));
621 break;
623 case 'a':
624 host = optarg;
625 break;
627 case 'p':
628 port = optarg;
629 break;
631 case 'd':
632 basedelay = 10;
633 if (optarg) basedelay = atoi(optarg);
634 break;
636 case 'v':
637 verbose = 2;
638 if (optarg) verbose = atoi(optarg);
639 break;
641 case 'T':
642 tap = 1;
643 break;
645 case '?':
646 case 'h':
647 default:
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");
669 exit(1);
670 break;
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);
679 ipaddr = argv[1];
681 switch(baudrate) {
682 case -2:
683 break; /* Use default. */
684 case 9600:
685 b_rate = B9600;
686 break;
687 case 19200:
688 b_rate = B19200;
689 break;
690 case 38400:
691 b_rate = B38400;
692 break;
693 case 57600:
694 b_rate = B57600;
695 break;
696 case 115200:
697 b_rate = B115200;
698 break;
699 default:
700 err(1, "unknown baudrate %d", baudrate);
701 break;
704 if(*tundev == '\0') {
705 /* Use default. */
706 if(tap) {
707 strcpy(tundev, "tap0");
708 } else {
709 strcpy(tundev, "tun0");
712 if(host != NULL) {
713 struct addrinfo hints, *servinfo, *p;
714 int rv;
715 char s[INET6_ADDRSTRLEN];
717 if(port == NULL) {
718 port = "60001";
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");
734 continue;
737 if(connect(slipfd, p->ai_addr, p->ai_addrlen) == -1) {
738 close(slipfd);
739 perror("client: connect");
740 continue;
742 break;
745 if(p == NULL) {
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),
752 s, sizeof(s));
753 fprintf(stderr, "slip connected to ``%s:%s''\n", s, port);
755 /* all done with this structure */
756 freeaddrinfo(servinfo);
758 } else {
759 if(siodev != NULL) {
760 slipfd = devopen(siodev, O_RDWR | O_NONBLOCK);
761 if(slipfd == -1) {
762 err(1, "can't open siodev ``/dev/%s''", siodev);
764 } else {
765 static const char *siodevs[] = {
766 "ttyUSB0", "cuaU0", "ucom0" /* linux, fbsd6, fbsd5 */
768 int i;
769 for(i = 0; i < 3; i++) {
770 siodev = siodevs[i];
771 slipfd = devopen(siodev, O_RDWR | O_NONBLOCK);
772 if(slipfd != -1) {
773 break;
776 if(slipfd == -1) {
777 err(1, "can't open siodev");
780 if (timestamp) stamptime();
781 fprintf(stderr, "********SLIP started on ``/dev/%s''\n", siodev);
782 stty_telos(slipfd);
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);
794 atexit(cleanup);
795 signal(SIGHUP, sigcleanup);
796 signal(SIGTERM, sigcleanup);
797 signal(SIGINT, sigcleanup);
798 signal(SIGALRM, sigalarm);
799 ifconf(tundev, ipaddr);
801 while(1) {
802 maxfd = 0;
803 FD_ZERO(&rset);
804 FD_ZERO(&wset);
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; */
815 /* } */
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. */
825 if(slip_empty()) {
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) {
832 err(1, "select");
833 } else if(ret > 0) {
834 if(FD_ISSET(slipfd, &rset)) {
835 serial_to_tun(inslip, tunfd);
838 if(FD_ISSET(slipfd, &wset)) {
839 slip_flushbuf(slipfd);
840 sigalarm_reset();
843 /* Optional delay between outgoing packets */
844 /* Base delay times number of 6lowpan fragments to be sent */
845 if(delaymsec) {
846 struct timeval tv;
847 int dmsec;
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;
853 if(delaymsec==0) {
854 int size;
855 if(slip_empty() && FD_ISSET(tunfd, &rset)) {
856 size=tun_to_serial(tunfd, slipfd);
857 slip_flushbuf(slipfd);
858 sigalarm_reset();
859 if(basedelay) {
860 struct timeval tv;
861 gettimeofday(&tv, NULL) ;
862 // delaymsec=basedelay*(1+(size/120));//multiply by # of 6lowpan packets?
863 delaymsec=basedelay;
864 delaystartsec =tv.tv_sec;
865 delaystartmsec=tv.tv_usec/1000;