/*---------------------------------------------------------------------------*/ void slip_handle_fd(fd_set *rset, fd_set *wset) { if(FD_ISSET(slipfd, rset)) { serial_input(inslip); } if(FD_ISSET(slipfd, wset)) { slip_flushbuf(slipfd); } }
void slip_send(int fd, unsigned char c) { if (slip_end >= sizeof(slip_buf)) { err(1, "slip_send overflow"); } slip_buf[slip_end] = c; slip_end++; if (slip_end >= sizeof(slip_buf)) { /* attempt to flush what is in the buffer */ slip_flushbuf(fd); } }
/*---------------------------------------------------------------------------*/ void cleanup(void) { if(slip_config_ifdown_script != NULL) { if(access(slip_config_ifdown_script, R_OK | X_OK) == 0) { LOG6LBR_INFO("Running 6lbr-ifup script '%s'\n", slip_config_ifdown_script); ssystem("%s %s %s 2>&1", slip_config_ifdown_script, use_raw_ethernet ? "raw" : "tap", slip_config_tundev); } else { LOG6LBR_ERROR("Could not access %s : %s\n", slip_config_ifdown_script, strerror(errno)); } } else { LOG6LBR_INFO("No 6lbr-ifup script specified\n"); } #if !CETIC_6LBR_ONE_ITF slip_set_mac(&linkaddr_null); slip_flushbuf(slipfd); #endif }
/*---------------------------------------------------------------------------*/ static void cleanup(void) { if(sixlbr_config_ifdown_script != NULL) { if(access(sixlbr_config_ifdown_script, R_OK | X_OK) == 0) { LOG6LBR_INFO("Running 6lbr-ifdown script '%s'\n", sixlbr_config_ifdown_script); int status = ssystem("%s %s %s 2>&1", sixlbr_config_ifdown_script, sixlbr_config_use_raw_ethernet ? "raw" : "tap", sixlbr_config_eth_device); if(status != 0) { LOG6LBR_ERROR("6lbr-ifdown script returned an error\n"); } } else { LOG6LBR_ERROR("Could not access %s : %s\n", sixlbr_config_ifdown_script, strerror(errno)); } } else { LOG6LBR_INFO("No 6lbr-ifdown script specified\n"); } cetic_6lbr_clear_ip(); #if !CETIC_6LBR_ONE_ITF slip_set_mac(&linkaddr_null); slip_flushbuf(slipfd); #endif }
int main(int argc, char **argv) { int c; int slipfd, maxfd; int ret; fd_set rset, wset; FILE *inslip; char siodev[10] = ""; int baudrate = -2; char buf[4000]; prog = argv[0]; setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */ memset(&osVersionInfo,0,sizeof(OSVERSIONINFO)); osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osVersionInfo); while((c = getopt(argc, argv, "B:D:L:hs:c:ra:p:vtb:")) != -1) { switch (c) { case 'B': baudrate = atoi(optarg); break; case 'L': if(strncmp("0", optarg, 1) == 0) { timestamp = 0; } else { timestamp = atoi(optarg); if (timestamp==0) timestamp=1; } break; case 's': if(strncmp("/dev/", optarg, 5) == 0) { strncpy(siodev,optarg + 5,sizeof(siodev)-1); } else if(strncmp("COM", optarg, 3) == 0) { int portnum; portnum = atoi(optarg+3); if(portnum == 0){ err(1,"port number is invalid"); } sprintf(siodev,"ttyS%d",portnum-1); } else { strncpy(siodev,optarg,sizeof(siodev)-1); } break; case 'c': channel = atoi(optarg); set_channel = 1; break; case 'r': sniffer_mode = 1; break; case 'a': if(autoconf == true){ print_help(); } local_ipaddr = optarg; if (!validIPAddr(local_ipaddr, 0)){ if (timestamp) stamptime(); fprintf(stderr, "Invalid IPv6 address: %s", local_ipaddr); exit(1); } break; case 'p': if(local_ipaddr !=NULL){ print_help(); } autoconf = true; ipprefix = optarg; if (!validIPAddr(ipprefix, 0)){ if (timestamp) stamptime(); fprintf(stderr, "Invalid IPv6 prefix: %s", ipprefix); exit(1); } break; case 'v': verbose = true; break; case 't': tun = true; break; case 'b': br_prefix = optarg; send_prefix = true; send_mac = false; tun = true; if (!validIPAddr(br_prefix, 64)){ if (timestamp) stamptime(); fprintf(stderr, "Invalid IPv6 64-bit prefix: %s", br_prefix); exit(1); } strtok(br_prefix,"/"); // Remove prefix length if it is present. break; case '?': case 'h': default: print_help(); break; } } argc -= (optind - 1); argv += (optind - 1); if(argc != 2 || *siodev == '\0') { print_help(); } if(autoconf == true && br_prefix != NULL){ if (timestamp) stamptime(); fprintf(stderr, "-p and -b options cannot be used together.\r\n"); print_help(); } sscanf(argv[1],"%2X-%2X-%2X-%2X-%2X-%2X", (int *)&adapter_eth_addr.addr[0],(int *)&adapter_eth_addr.addr[1], (int *)&adapter_eth_addr.addr[2],(int *)&adapter_eth_addr.addr[3], (int *)&adapter_eth_addr.addr[4],(int *)&adapter_eth_addr.addr[5]); if_name = wpcap_start(&adapter_eth_addr, verbose); if(local_ipaddr!=NULL){ addAddress(if_name, local_ipaddr); } 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; case 230400: b_rate = B230400; break; case 460800: b_rate = B460800; break; case 921600: b_rate = B921600; break; default: err(1, "unknown baudrate %d", baudrate); break; } slipfd = devopen(siodev, O_RDWR | O_NONBLOCK | O_NOCTTY | O_NDELAY | O_DIRECT | O_SYNC ); if(slipfd == -1) { err(1, "can't open siodev ``/dev/%s''", siodev); } if (timestamp) stamptime(); fprintf(stderr, "wpcapslip6 started on ``/dev/%s''\n", siodev); stty_telos(slipfd); slip_send(SLIP_END); inslip = fdopen(slipfd, "r"); if(inslip == NULL) err(1, "main: fdopen"); atexit(cleanup); signal(SIGHUP, sigcleanup); signal(SIGTERM, sigcleanup); signal(SIGINT, sigcleanup); signal(SIGALRM, sigalarm); /* Request mac address from gateway. It may be useful for setting the best IPv6 address of the local interface. */ while(1) { maxfd = 0; FD_ZERO(&rset); FD_ZERO(&wset); send_commands(); if(!slip_empty()) { /* Anything to flush? */ FD_SET(slipfd, &wset); } FD_SET(slipfd, &rset); /* Read from slip ASAP! */ if(slipfd > maxfd) maxfd = slipfd; #ifdef WITH_STDIN FD_SET(STDIN_FILENO, &rset); /* Read from stdin too. */ if(STDIN_FILENO > maxfd) maxfd = STDIN_FILENO; /* This would not be necessary, since we know STDIN_FILENO is 0. */ #endif if(slip_empty()) { char *pbuf = buf; ret = wpcap_poll(pbuf); if( ret > 0 ){ struct uip_eth_hdr * eth_hdr = (struct uip_eth_hdr *)pbuf; if(eth_hdr->type == htons(UIP_ETHTYPE_IPV6)){ // We forward only IPv6 packet. if(tun){ // Cut away ethernet header. pbuf += sizeof(struct uip_eth_hdr); ret -= sizeof(struct uip_eth_hdr); } write_to_serial(pbuf, ret); /*print_packet(pbuf, ret);*/ slip_flushbuf(slipfd); } } } { struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 10; ret = select(maxfd + 1, &rset, &wset, NULL, &tv); } if(ret == -1 && errno != EINTR && errno != EAGAIN) { err(1, "select"); } else if(ret > 0) { if(FD_ISSET(slipfd, &rset)) { /* printf("serial_to_wpcap\n"); */ serial_to_wpcap(inslip); /* printf("End of serial_to_wpcap\n");*/ } if(FD_ISSET(slipfd, &wset)) { slip_flushbuf(slipfd); } #ifdef WITH_STDIN if(FD_ISSET(STDIN_FILENO, &rset)) { char inbuf; if(fread(&inbuf,1,1,stdin)){ if(inbuf=='q'){ exit(0); } } } #endif } } }
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 tap = 0; slipfd = 0; prog = argv[0]; setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */ while((c = getopt(argc, argv, "B:D:Lhs:t:v::d::a:p:T")) != -1) { switch(c) { case 'B': baudrate = atoi(optarg); break; case 'L': timestamp=1; break; case 's': if(strncmp("/dev/", optarg, 5) == 0) { siodev = optarg + 5; } else { siodev = optarg; } 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"); fprintf(stderr," -B baudrate 9600,19200,38400,57600,115200 (default)\n"); fprintf(stderr," -L Log output format (adds time stamps)\n"); fprintf(stderr," -s siodev Serial device (default /dev/ttyUSB0)\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," -t tundev Name of interface\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] [-L] [-s siodev] [-t tundev] [-T] [-v verbosity] [-d delay] [-a serveraddress] [-p serverport] ipaddress", prog); } ipaddr = argv[1]; 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 0 if(*tundev == '\0') { /* Use default. */ if(tap) { strcpy(tundev, "tap0"); } else { strcpy(tundev, "tun0"); } } #endif 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"); 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); /* do not send IPA all the time... - add get MAC later... */ /* 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(); } /* 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); tun_to_serial(tunfd, slipfd); slip_flushbuf(slipfd); 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; } } } } } }
/* * 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 int i; 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 read_more: if(inbufptr >= sizeof(uip.inbuf)) { inbufptr = 0; if(timestamp) stamptime(); fprintf(stderr, "*** dropping too large packet\n"); } 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]; int i, pos; for(i = 0, pos = 0; i < 16; i++) { macs[pos++] = uip.inbuf[2 + i]; if ((i & 1) == 1 && i < 14) { macs[pos++] = ':'; } } if(timestamp) stamptime(); macs[pos] = '\0'; // printf("*** Gateway's MAC address: %s\n", macs); 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[1] == 'P') { /* Prefix info requested */ struct in6_addr addr; int i; 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 (i = 0; i < 8; i++) { //slip_send(slipfd, addr.s6_addr[i]); switch (addr.s6_addr[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, addr.s6_addr[i]); break; } } slip_send(slipfd, SLIP_END); slip_flushbuf(slipfd); // DEBUG } #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) { printf(" "); for(i = 0; i < inbufptr; i++) { printf("%02x", uip.inbuf[i]); if((i & 3) == 3) { printf(" "); } if((i & 15) == 15) printf("\n "); } 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; } goto read_more; }
int main(int argc, char **argv) { int c; int tunfd, slipfd, maxfd; int ret; fd_set rset, wset; unsigned short dst_port = DST_PORT + 1; ip_id = getpid() * time(NULL); setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */ while ((c = getopt(argc, argv, "n:t:")) != -1) { switch (c) { case 'n': dst_port = DST_PORT + atoi(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_STRING); break; } } argc -= (optind - 1); argv += (optind - 1); if (argc != 1) { err(1, USAGE_STRING); } ipaddr = "172.16.0.0"; netmask = "255.255.0.0"; circuit_addr = inet_addr(ipaddr); netaddr = inet_addr(ipaddr) & inet_addr(netmask); slipfd = devopen(dst_port); if (slipfd == -1) { err(1, "can't open port %u", dst_port); } fprintf(stderr, "slip sending to port %u\n", dst_port); stty_telos(slipfd); slip_send(slipfd, SLIP_END); 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(slipfd, 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); } } } }
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); } } } }