/* * Read from serial, when we have a packet write it to tun. No output * buffering, input buffered by stdio. */ void serial_to_tun(FILE *inslip, int outfd) { static union { unsigned char inbuf[2000]; } uip; static unsigned int inbufptr = 0; int ret; unsigned char c; #ifdef __linux__ ret = fread(&c, 1, 1, inslip); if (ret == -1 || ret == 0) { err(1, "serial_to_tun: read"); } goto after_fread; #endif while (1) { if (inbufptr >= sizeof(uip.inbuf)) { if (timestamp) { stamptime(); } fprintf(stderr, "*** dropping large %d byte packet\n", inbufptr); inbufptr = 0; } ret = fread(&c, 1, 1, inslip); #ifdef __linux__ after_fread: #endif if (ret == -1) { err(1, "serial_to_tun: read"); } if (ret == 0) { clearerr(inslip); return; } /* fprintf(stderr, ".");*/ switch (c) { case SLIP_END: if (inbufptr > 0) { if (uip.inbuf[0] == '!') { if (uip.inbuf[1] == 'M') { /* Read gateway MAC address and autoconfigure tap0 interface */ char macs[24]; unsigned int pos = 0; for (unsigned int i = 0; i < 16; i++) { macs[pos++] = uip.inbuf[2 + i]; if ((i & 1) == 1 && i < 14) { macs[pos++] = ':'; } } if (timestamp) { stamptime(); } macs[pos] = '\0'; fprintf(stderr, "*** Gateway's MAC address: %s\n", macs); if (timestamp) { stamptime(); } ssystem("ifconfig %s down", tundev); if (timestamp) { stamptime(); } ssystem("ifconfig %s hw ether %s", tundev, &macs[6]); if (timestamp) { stamptime(); } ssystem("ifconfig %s up", tundev); } } else if (uip.inbuf[0] == '?') { if (uip.inbuf[1] == 'P') { /* Prefix info requested */ struct in6_addr addr; char *s = strchr(ipaddr, '/'); if (s != NULL) { *s = '\0'; } inet_pton(AF_INET6, ipaddr, &addr); if (timestamp) { stamptime(); } fprintf(stderr, "*** Address:%s => %02x%02x:%02x%02x:%02x%02x:%02x%02x\n", ipaddr, addr.s6_addr[0], addr.s6_addr[1], addr.s6_addr[2], addr.s6_addr[3], addr.s6_addr[4], addr.s6_addr[5], addr.s6_addr[6], addr.s6_addr[7]); slip_send(slipfd, '!'); slip_send(slipfd, 'P'); for (unsigned int i = 0; i < 8; i++) { /* need to call the slip_send_char for stuffing */ slip_send_char(slipfd, addr.s6_addr[i]); } slip_send(slipfd, SLIP_END); } #define DEBUG_LINE_MARKER '\r' } else if (uip.inbuf[0] == DEBUG_LINE_MARKER) { fwrite(uip.inbuf + 1, inbufptr - 1, 1, stdout); } else if (is_sensible_string(uip.inbuf, inbufptr)) { if (verbose == 1) { /* strings already echoed below for verbose>1 */ if (timestamp) { stamptime(); } fwrite(uip.inbuf, inbufptr, 1, stdout); } } else { if (verbose > 2) { if (timestamp) { stamptime(); } printf("Packet from SLIP of length %d - write TUN\n", inbufptr); if (verbose > 4) { #if WIRESHARK_IMPORT_FORMAT printf("0000"); for (unsigned int i = 0; i < inbufptr; i++) { printf(" %02x", uip.inbuf[i]); } #else printf(" "); for (unsigned int i = 0; i < inbufptr; i++) { printf("%02x", uip.inbuf[i]); if ((i & 3) == 3) { printf(" "); } if ((i & 15) == 15) { printf("\n "); } } #endif printf("\n"); } } if (write(outfd, uip.inbuf, inbufptr) != inbufptr) { err(1, "serial_to_tun: write"); } } inbufptr = 0; } break; case SLIP_ESC: if (fread(&c, 1, 1, inslip) != 1) { clearerr(inslip); /* Put ESC back and give up! */ ungetc(SLIP_ESC, inslip); return; } switch (c) { case SLIP_ESC_END: c = SLIP_END; break; case SLIP_ESC_ESC: c = SLIP_ESC; break; } /* FALLTHROUGH */ default: uip.inbuf[inbufptr++] = c; /* Echo lines as they are received for verbose=2,3,5+ */ /* Echo all printable characters for verbose==4 */ if ((verbose == 2) || (verbose == 3) || (verbose > 4)) { if (c == '\n') { if (is_sensible_string(uip.inbuf, inbufptr)) { if (timestamp) { stamptime(); } fwrite(uip.inbuf, inbufptr, 1, stdout); inbufptr = 0; } } } else if (verbose == 4) { if (c == 0 || c == '\r' || c == '\n' || c == '\t' || (c >= ' ' && c <= '~')) { fwrite(&c, 1, 1, stdout); if (c == '\n') if (timestamp) { stamptime(); } } } break; } } }
void write_to_serial(int outfd, void *inbuf, int len) { u_int8_t *p = inbuf; int i; if (verbose > 2) { if (timestamp) { stamptime(); } printf("Packet from TUN of length %d - write SLIP\n", len); if (verbose > 4) { #if WIRESHARK_IMPORT_FORMAT printf("0000"); for (i = 0; i < len; i++) { printf(" %02x", p[i]); } #else printf(" "); for (i = 0; i < len; i++) { printf("%02x", p[i]); if ((i & 3) == 3) { printf(" "); } if ((i & 15) == 15) { printf("\n "); } } #endif printf("\n"); } } /* It would be ``nice'' to send a SLIP_END here but it's not * really necessary. */ /* slip_send(outfd, SLIP_END); */ for (i = 0; i < len; i++) { switch (p[i]) { case SLIP_END: slip_send(outfd, SLIP_ESC); slip_send(outfd, SLIP_ESC_END); break; case SLIP_ESC: slip_send(outfd, SLIP_ESC); slip_send(outfd, SLIP_ESC_ESC); break; default: slip_send(outfd, p[i]); break; } } slip_send(outfd, SLIP_END); PROGRESS("t"); }
void slip_send_char(int fd, unsigned char c) { switch(c) { case SLIP_END: slip_send(fd, SLIP_ESC); slip_send(fd, SLIP_ESC_END); break; case SLIP_ESC: slip_send(fd, SLIP_ESC); slip_send(fd, SLIP_ESC_ESC); break; case XON: if(flowcontrol_xonxoff) { slip_send(fd, SLIP_ESC); slip_send(fd, SLIP_ESC_XON); } else { slip_send(fd, c); } break; case XOFF: if(flowcontrol_xonxoff) { slip_send(fd, SLIP_ESC); slip_send(fd, SLIP_ESC_XOFF); } else { slip_send(fd, c); } break; default: slip_send(fd, c); break; } }
int main(int argc, char **argv) { int c; int tunfd, maxfd; int ret; fd_set rset, wset; FILE *inslip; const char *siodev = NULL; const char *host = NULL; const char *port = NULL; const char *prog; int baudrate = -2; int ipa_enable = 0; int tap = 0; slipfd = 0; prog = argv[0]; setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */ while((c = getopt(argc, argv, "B:HILPhXM:s:t:v::d::a:p:T")) != -1) { switch(c) { case 'B': baudrate = atoi(optarg); break; case 'H': flowcontrol=1; break; case 'X': flowcontrol_xonxoff=1; break; case 'L': timestamp=1; break; case 'M': devmtu=atoi(optarg); if(devmtu < MIN_DEVMTU) { devmtu = MIN_DEVMTU; } case 'P': showprogress=1; break; case 's': if(strncmp("/dev/", optarg, 5) == 0) { siodev = optarg + 5; } else { siodev = optarg; } break; case 'I': ipa_enable = 1; fprintf(stderr, "Will inquire about IP address using IPA=\n"); break; case 't': if(strncmp("/dev/", optarg, 5) == 0) { strncpy(tundev, optarg + 5, sizeof(tundev)); } else { strncpy(tundev, optarg, sizeof(tundev)); } break; case 'a': host = optarg; break; case 'p': port = optarg; break; case 'd': basedelay = 10; if (optarg) basedelay = atoi(optarg); break; case 'v': verbose = 2; if (optarg) verbose = atoi(optarg); break; case 'T': tap = 1; break; case '?': case 'h': default: fprintf(stderr,"usage: %s [options] ipaddress\n", prog); fprintf(stderr,"example: tunslip6 -L -v2 -s ttyUSB1 aaaa::1/64\n"); fprintf(stderr,"Options are:\n"); #ifndef __APPLE__ fprintf(stderr," -B baudrate 9600,19200,38400,57600,115200 (default),230400,460800,921600\n"); #else fprintf(stderr," -B baudrate 9600,19200,38400,57600,115200 (default),230400\n"); #endif fprintf(stderr," -H Hardware CTS/RTS flow control (default disabled)\n"); fprintf(stderr," -I Inquire IP address\n"); fprintf(stderr," -X Software XON/XOFF flow control (default disabled)\n"); fprintf(stderr," -L Log output format (adds time stamps)\n"); fprintf(stderr," -s siodev Serial device (default /dev/ttyUSB0)\n"); fprintf(stderr," -M Interface MTU (default and min: 1280)\n"); fprintf(stderr," -T Make tap interface (default is tun interface)\n"); fprintf(stderr," -t tundev Name of interface (default tap0 or tun0)\n"); fprintf(stderr," -v[level] Verbosity level\n"); fprintf(stderr," -v0 No messages\n"); fprintf(stderr," -v1 Encapsulated SLIP debug messages (default)\n"); fprintf(stderr," -v2 Printable strings after they are received\n"); fprintf(stderr," -v3 Printable strings and SLIP packet notifications\n"); fprintf(stderr," -v4 All printable characters as they are received\n"); fprintf(stderr," -v5 All SLIP packets in hex\n"); fprintf(stderr," -v Equivalent to -v3\n"); fprintf(stderr," -d[basedelay] Minimum delay between outgoing SLIP packets.\n"); fprintf(stderr," Actual delay is basedelay*(#6LowPAN fragments) milliseconds.\n"); fprintf(stderr," -d is equivalent to -d10.\n"); fprintf(stderr," -a serveraddr \n"); fprintf(stderr," -p serverport \n"); exit(1); break; } } argc -= (optind - 1); argv += (optind - 1); if(argc != 2 && argc != 3) { err(1, "usage: %s [-B baudrate] [-H] [-L] [-s siodev] [-t tundev] [-T] [-v verbosity] [-d delay] [-a serveraddress] [-p serverport] ipaddress", prog); } ipaddr = argv[1]; if(baudrate != -2) { /* -2: use default baudrate */ b_rate = select_baudrate(baudrate); if(b_rate == 0) { err(1, "unknown baudrate %d", baudrate); } } if(*tundev == '\0') { /* Use default. */ if(tap) { strcpy(tundev, "tap0"); } else { strcpy(tundev, "tun0"); } } if(host != NULL) { struct addrinfo hints, *servinfo, *p; int rv; char s[INET6_ADDRSTRLEN]; if(port == NULL) { port = "60001"; } memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if((rv = getaddrinfo(host, port, &hints, &servinfo)) != 0) { err(1, "getaddrinfo: %s", gai_strerror(rv)); } /* loop through all the results and connect to the first we can */ for(p = servinfo; p != NULL; p = p->ai_next) { if((slipfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { perror("client: socket"); continue; } if(connect(slipfd, p->ai_addr, p->ai_addrlen) == -1) { close(slipfd); perror("client: connect"); continue; } break; } if(p == NULL) { err(1, "can't connect to ``%s:%s''", host, port); } fcntl(slipfd, F_SETFL, O_NONBLOCK); inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), s, sizeof(s)); fprintf(stderr, "slip connected to ``%s:%s''\n", s, port); /* all done with this structure */ freeaddrinfo(servinfo); } else { if(siodev != NULL) { slipfd = devopen(siodev, O_RDWR | O_NONBLOCK); if(slipfd == -1) { err(1, "can't open siodev ``/dev/%s''", siodev); } } else { static const char *siodevs[] = { "ttyUSB0", "cuaU0", "ucom0" /* linux, fbsd6, fbsd5 */ }; int i; for(i = 0; i < 3; i++) { siodev = siodevs[i]; slipfd = devopen(siodev, O_RDWR | O_NONBLOCK); if(slipfd != -1) { break; } } if(slipfd == -1) { err(1, "can't open siodev"); } } if (timestamp) stamptime(); fprintf(stderr, "********SLIP started on ``/dev/%s''\n", siodev); stty_telos(slipfd); } slip_send(slipfd, SLIP_END); inslip = fdopen(slipfd, "r"); if(inslip == NULL) err(1, "main: fdopen"); tunfd = tun_alloc(tundev, tap); if(tunfd == -1) err(1, "main: open /dev/tun"); if (timestamp) stamptime(); fprintf(stderr, "opened %s device ``/dev/%s''\n", tap ? "tap" : "tun", tundev); atexit(cleanup); signal(SIGHUP, sigcleanup); signal(SIGTERM, sigcleanup); signal(SIGINT, sigcleanup); signal(SIGALRM, sigalarm); ifconf(tundev, ipaddr); while(1) { maxfd = 0; FD_ZERO(&rset); FD_ZERO(&wset); if(got_sigalarm && ipa_enable) { /* Send "?IPA". */ slip_send(slipfd, '?'); slip_send(slipfd, 'I'); slip_send(slipfd, 'P'); slip_send(slipfd, 'A'); slip_send(slipfd, SLIP_END); got_sigalarm = 0; } if(!slip_empty()) { /* Anything to flush? */ FD_SET(slipfd, &wset); } FD_SET(slipfd, &rset); /* Read from slip ASAP! */ if(slipfd > maxfd) maxfd = slipfd; /* We only have one packet at a time queued for slip output. */ if(slip_empty()) { FD_SET(tunfd, &rset); if(tunfd > maxfd) maxfd = tunfd; } ret = select(maxfd + 1, &rset, &wset, NULL, NULL); if(ret == -1 && errno != EINTR) { err(1, "select"); } else if(ret > 0) { if(FD_ISSET(slipfd, &rset)) { serial_to_tun(inslip, tunfd); } if(FD_ISSET(slipfd, &wset)) { slip_flushbuf(slipfd); if(ipa_enable) sigalarm_reset(); } /* Optional delay between outgoing packets */ /* Base delay times number of 6lowpan fragments to be sent */ if(delaymsec) { struct timeval tv; int dmsec; gettimeofday(&tv, NULL) ; dmsec=(tv.tv_sec-delaystartsec)*1000+tv.tv_usec/1000-delaystartmsec; if(dmsec<0) delaymsec=0; if(dmsec>delaymsec) delaymsec=0; } if(delaymsec==0) { int size; if(slip_empty() && FD_ISSET(tunfd, &rset)) { size=tun_to_serial(tunfd, slipfd); slip_flushbuf(slipfd); if(ipa_enable) sigalarm_reset(); if(basedelay) { struct timeval tv; gettimeofday(&tv, NULL) ; // delaymsec=basedelay*(1+(size/120));//multiply by # of 6lowpan packets? delaymsec=basedelay; delaystartsec =tv.tv_sec; delaystartmsec=tv.tv_usec/1000; } } } } } }
static int net_driver_slip_send(struct net_buf *buf) { NET_DBG("Sending %d bytes\n", buf->len); return slip_send(buf); }
int main(int argc, char **argv) { int c; int tunfd, slipfd, maxfd; int ret; fd_set rset, wset; FILE *inslip; const char *siodev = NULL; int baudrate = -2; request_mac = 1; setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */ while((c = getopt(argc, argv, "B:D:hs:t:")) != -1) { switch (c) { case 'B': baudrate = atoi(optarg); break; case 's': if(strncmp("/dev/", optarg, 5) == 0) { siodev = optarg + 5; } else { siodev = optarg; } break; case 't': if(strncmp("/dev/", optarg, 5) == 0) { strcpy(tundev, optarg + 5); } else { strcpy(tundev, optarg); } break; case '?': case 'h': default: errx(1, USAGE_STRING); break; } } argc -= (optind - 1); argv += (optind - 1); if(argc != 3 && argc != 4) { errx(1, USAGE_STRING); } ipaddr = argv[1]; netmask = argv[2]; circuit_addr = inet_addr(ipaddr); netaddr = inet_addr(ipaddr) & inet_addr(netmask); switch(baudrate) { case -2: break; /* Use default. */ case 9600: b_rate = B9600; break; case 19200: b_rate = B19200; break; case 38400: b_rate = B38400; break; case 57600: b_rate = B57600; break; case 115200: b_rate = B115200; break; default: err(1, "unknown baudrate %d", baudrate); break; } if(siodev != NULL) { slipfd = devopen(siodev, O_RDWR | O_NONBLOCK); if(slipfd == -1) { err(1, "can't open siodev ``/dev/%s''", siodev); } } else { static const char *siodevs[] = { "ttyUSB0", "cuaU0", "ucom0" /* linux, fbsd6, fbsd5 */ }; int i; for(i = 0; i < 3; i++) { siodev = siodevs[i]; slipfd = devopen(siodev, O_RDWR | O_NONBLOCK); if (slipfd != -1) break; } if(slipfd == -1) { err(1, "can't open siodev"); } } fprintf(stderr, "slip started on ``/dev/%s''\n", siodev); stty_telos(slipfd); slip_send(slipfd, SLIP_END); inslip = fdopen(slipfd, "r"); if(inslip == NULL) err(1, "main: fdopen"); tunfd = tun_alloc(tundev); printf("opening: %s", tundev); if(tunfd == -1) err(1, "main: open"); fprintf(stderr, "opened device ``/dev/%s''\n", tundev); atexit(cleanup); signal(SIGHUP, sigcleanup); signal(SIGTERM, sigcleanup); signal(SIGINT, sigcleanup); signal(SIGALRM, sigalarm); ifconf(tundev, ipaddr, netmask); while(1) { maxfd = 0; FD_ZERO(&rset); FD_ZERO(&wset); /* request mac address from gateway node for autoconfiguration of ethernet interface tap0 */ if (request_mac) { slip_send(slipfd, '?'); slip_send(slipfd, 'M'); slip_send(slipfd, SLIP_END); request_mac = 0; } if(got_sigalarm) { /* Send "?IPA". */ slip_send(slipfd, '?'); slip_send(slipfd, 'I'); slip_send(slipfd, 'P'); slip_send(slipfd, 'A'); slip_send(slipfd, SLIP_END); got_sigalarm = 0; } if(!slip_empty()) { /* Anything to flush? */ FD_SET(slipfd, &wset); } FD_SET(slipfd, &rset); /* Read from slip ASAP! */ if(slipfd > maxfd) maxfd = slipfd; /* We only have one packet at a time queued for slip output. */ if(slip_empty()) { FD_SET(tunfd, &rset); if(tunfd > maxfd) maxfd = tunfd; } ret = select(maxfd + 1, &rset, &wset, NULL, NULL); if(ret == -1 && errno != EINTR) { err(1, "select"); } else if(ret > 0) { if(FD_ISSET(slipfd, &rset)) { serial_to_tun(inslip, tunfd); } if(FD_ISSET(slipfd, &wset)) { slip_flushbuf(slipfd); sigalarm_reset(); } if(slip_empty() && FD_ISSET(tunfd, &rset)) { tun_to_serial(tunfd, slipfd); slip_flushbuf(slipfd); sigalarm_reset(); } } } }
int main(int argc, char **argv) { int c; int tunfd, slipfd, maxfd; int ret; fd_set rset, wset; FILE *inslip; const char *siodev = NULL; const char *dhcp_server = NULL; u_int16_t myport = BOOTPS, dhport = BOOTPS; int baudrate = -2; ip_id = getpid() * time(NULL); setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */ while ((c = getopt(argc, argv, "B:D:hs:t:")) != -1) { switch (c) { case 'B': baudrate = atoi(optarg); break; case 'D': dhcp_server = optarg; break; case 's': if (strncmp("/dev/", optarg, 5) == 0) { siodev = optarg + 5; } else { siodev = optarg; } break; case 't': if (strncmp("/dev/", optarg, 5) == 0) { strcpy(tundev, optarg + 5); } else { strcpy(tundev, optarg); } break; case '?': case 'h': default: err(1, "usage: tunslip [-B baudrate] [-s siodev] [-t tundev] [-D dhcp-server] ipaddress netmask [dhcp-server]"); break; } } argc -= (optind - 1); argv += (optind - 1); if (argc != 3 && argc != 4) { err(1, "usage: tunslip [-s siodev] [-t tundev] [-D dhcp-server] ipaddress netmask [dhcp-server]"); } ipaddr = argv[1]; netmask = argv[2]; circuit_addr = inet_addr(ipaddr); netaddr = inet_addr(ipaddr) & inet_addr(netmask); switch (baudrate) { case -2: break; /* Use default. */ case 9600: b_rate = B9600; break; case 19200: b_rate = B19200; break; case 38400: b_rate = B38400; break; case 57600: b_rate = B57600; break; case 115200: b_rate = B115200; break; default: err(1, "unknown baudrate %d", baudrate); break; } /* * Set up DHCP relay agent socket and find the address of this relay * agent. */ if (argc == 4) { dhcp_server = argv[3]; } if (dhcp_server != NULL) { struct sockaddr_in myaddr; socklen_t len; in_addr_t a; if (strchr(dhcp_server, ':') != NULL) { dhport = atoi(strchr(dhcp_server, ':') + 1); myport = dhport + 1; *strchr(dhcp_server, ':') = '\0'; } a = inet_addr(dhcp_server); if (a == -1) { err(1, "illegal dhcp-server address"); } #ifndef linux dhaddr.sin_len = sizeof(dhaddr); #endif dhaddr.sin_family = AF_INET; dhaddr.sin_port = htons(dhport); dhaddr.sin_addr.s_addr = a; dhsock = socket(AF_INET, SOCK_DGRAM, 0); if (dhsock < 0) { err(1, "socket"); } memset(&myaddr, 0x0, sizeof(myaddr)); #ifndef linux myaddr.sin_len = sizeof(myaddr); #endif myaddr.sin_family = AF_INET; myaddr.sin_addr.s_addr = INADDR_ANY; myaddr.sin_port = htons(myport); if (bind(dhsock, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) { err(1, "bind dhcp-relay"); } if (connect(dhsock, (struct sockaddr *)&dhaddr, sizeof(dhaddr)) < 0) { err(1, "connect to dhcp-server"); } len = sizeof(myaddr); if (getsockname(dhsock, (struct sockaddr *)&myaddr, &len) < 0) { err(1, "getsockname dhsock"); } giaddr = myaddr.sin_addr.s_addr; /* * Don't want connected socket. */ close(dhsock); dhsock = socket(AF_INET, SOCK_DGRAM, 0); if (dhsock < 0) { err(1, "socket"); } myaddr.sin_family = AF_INET; myaddr.sin_addr.s_addr = INADDR_ANY; myaddr.sin_port = htons(myport); if (bind(dhsock, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) { err(1, "bind dhcp-relay"); } fprintf(stderr, "DHCP server at %s:%d\n", dhcp_server, dhport); } if (siodev != NULL) { slipfd = devopen(siodev, O_RDWR | O_NONBLOCK); if (slipfd == -1) { err(1, "can't open siodev ``/dev/%s''", siodev); } } else { static const char *siodevs[] = { "ttyUSB0", "cuaU0", "ucom0" /* linux, fbsd6, fbsd5 */ }; int i; for (i = 0; i < 3; i++) { siodev = siodevs[i]; slipfd = devopen(siodev, O_RDWR | O_NONBLOCK); if (slipfd != -1) { break; } } if (slipfd == -1) { err(1, "can't open siodev"); } } fprintf(stderr, "slip started on ``/dev/%s''\n", siodev); stty_telos(slipfd); slip_send(slipfd, SLIP_END); inslip = fdopen(slipfd, "r"); if (inslip == NULL) { err(1, "main: fdopen"); } tunfd = tun_alloc(tundev); if (tunfd == -1) { err(1, "main: open"); } fprintf(stderr, "opened device ``/dev/%s''\n", tundev); atexit(cleanup); signal(SIGHUP, sigcleanup); signal(SIGTERM, sigcleanup); signal(SIGINT, sigcleanup); signal(SIGALRM, sigalarm); ifconf(tundev, ipaddr, netmask); while (1) { maxfd = 0; FD_ZERO(&rset); FD_ZERO(&wset); if (got_sigalarm) { /* Send "?IPA". */ slip_send(slipfd, '?'); slip_send(slipfd, 'I'); slip_send(slipfd, 'P'); slip_send(slipfd, 'A'); slip_send(slipfd, SLIP_END); got_sigalarm = 0; } if (!slip_empty()) { /* Anything to flush? */ FD_SET(slipfd, &wset); } FD_SET(slipfd, &rset); /* Read from slip ASAP! */ if (slipfd > maxfd) { maxfd = slipfd; } /* We only have one packet at a time queued for slip output. */ if (slip_empty()) { FD_SET(tunfd, &rset); if (tunfd > maxfd) { maxfd = tunfd; } if (dhsock != -1) { FD_SET(dhsock, &rset); if (dhsock > maxfd) { maxfd = dhsock; } } } ret = select(maxfd + 1, &rset, &wset, NULL, NULL); if (ret == -1 && errno != EINTR) { err(1, "select"); } else if (ret > 0) { if (FD_ISSET(slipfd, &rset)) { serial_to_tun(inslip, tunfd); } if (FD_ISSET(slipfd, &wset)) { slip_flushbuf(slipfd); sigalarm_reset(); } if (slip_empty() && FD_ISSET(tunfd, &rset)) { tun_to_serial(tunfd, slipfd); slip_flushbuf(slipfd); sigalarm_reset(); } if (dhsock != -1 && slip_empty() && FD_ISSET(dhsock, &rset)) { relay_dhcp_to_client(slipfd); slip_flushbuf(slipfd); } } } }
void write_to_serial(int outfd, void *inbuf, int len) { u_int8_t *p = inbuf; int i, ecode; struct ip *iphdr = inbuf; /* * Sanity checks. */ ecode = check_ip(inbuf, len); if (ecode < 0) { fprintf(stderr, "tun_to_serial: drop packet %d\n", ecode); return; } if (iphdr->ip_id == 0 && iphdr->ip_off & IP_DF) { uint16_t nid = htons(ip_id++); iphdr->ip_id = nid; nid = ~nid; /* negate */ iphdr->ip_sum += nid; /* add */ if (iphdr->ip_sum < nid) { /* 1-complement overflow? */ iphdr->ip_sum++; } ecode = check_ip(inbuf, len); if (ecode < 0) { fprintf(stderr, "tun_to_serial: drop packet %d\n", ecode); return; } } /* It would be ``nice'' to send a SLIP_END here but it's not * really necessary. */ /* slip_send(outfd, SLIP_END); */ for (i = 0; i < len; i++) { switch (p[i]) { case SLIP_END: slip_send(outfd, SLIP_ESC); slip_send(outfd, SLIP_ESC_END); break; case SLIP_ESC: slip_send(outfd, SLIP_ESC); slip_send(outfd, SLIP_ESC_ESC); break; default: slip_send(outfd, p[i]); break; } } slip_send(outfd, SLIP_END); PROGRESS("t"); }
/*---------------------------------------------------------------------------*/ void slip_init(void) { setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */ if(slip_config_host != NULL) { if(slip_config_port == NULL) { slip_config_port = "60001"; } slipfd = connect_to_server(slip_config_host, slip_config_port); if(slipfd == -1) { LOG6LBR_FATAL("can't connect to %s:%s\n", slip_config_host, slip_config_port); exit(1); } } else if(slip_config_siodev != NULL) { if(strcmp(slip_config_siodev, "null") == 0) { /* Disable slip */ return; } slipfd = devopen(slip_config_siodev, O_RDWR | O_NONBLOCK); if(slipfd == -1) { LOG6LBR_FATAL( "can't open siodev /dev/%s : %s\n", slip_config_siodev, strerror(errno)); exit(1); } } else { static const char *siodevs[] = { "ttyUSB0", "cuaU0", "ucom0" /* linux, fbsd6, fbsd5 */ }; int i; for(i = 0; i < 3; i++) { slip_config_siodev = siodevs[i]; slipfd = devopen(slip_config_siodev, O_RDWR | O_NONBLOCK); if(slipfd != -1) { break; } } if(slipfd == -1) { LOG6LBR_FATAL("can't open siodev : %s\n", strerror(errno)); exit(1); } } select_set_callback(slipfd, &slip_callback); if(slip_config_host != NULL) { LOG6LBR_INFO("SLIP opened to %s:%s\n", slip_config_host, slip_config_port); } else { LOG6LBR_INFO("SLIP started on /dev/%s\n", slip_config_siodev); stty_telos(slipfd); } timer_set(&send_delay_timer, 0); slip_send(slipfd, SLIP_END); inslip = fdopen(slipfd, "r"); if(inslip == NULL) { LOG6LBR_FATAL("main: fdopen: %s\n", strerror(errno)); exit(1); } }