Example #1
0
int main(int argc, char **argv)
{
    char buf[BUF_SIZE], dev[IFNAMSIZ]="/dev/net/tun", tapdev[IFNAMSIZ], *progname;
    int tap, r, tun = IFF_TUN;
    int c, verbose = 0, interval = 0, keep = 0, keep_count = 0;
    time_t last_keep;
    struct timeval tv;
    struct rlimit rlim;
    fd_set rfd;

    while ( (c=getopt(argc,argv,"vi:k:")) != -1 ) {
        switch (c) {
            case 'v':
                verbose++;
                break;
            case 'i':
                interval = atoi(optarg);
                break;
            case 'k':
                keep = atoi(optarg);
                break;
        }
    }

    if ((progname = strrchr(argv[0], '/')) == NULL) {
        progname = argv[0];
    } else {
        progname++;
    }

    if (keep && !interval) {
        write_str(STDERR_FILENO, progname);
        write_cstr(STDERR_FILENO, ": keep alive need interval value.\n");
        return 1;
    }

    signal(SIGPIPE,signalHandler);

    if (strcmp("tunio", progname)) tun = IFF_TAP;

    if (argc>optind) {
        if (!strncmp(argv[optind],"/dev/",5)) argv[optind] += 5;
        if (verbose) {
            write_str(STDERR_FILENO, progname);
            write_cstr(STDERR_FILENO, ": Forced to ");
            write_str(STDERR_FILENO,argv[optind]);
            write_cstr(STDERR_FILENO, "\n");
        }
        strstart(tapdev);
        strarray(tapdev);
        strannex(tapdev,argv[optind]);
        tap = tap_alloc (dev, tapdev, tun);
    } else {
        strstart(tapdev);
        for (r=0 ; r<1000 ; r++) {
            strarray(tapdev);
            if (tun == IFF_TUN) {
                strannex(tapdev, "tun");
            } else {
                strannex(tapdev, "tap");
            }
            strannex_uint(tapdev, r);
            tap = tap_alloc (dev, tapdev, tun);
            if (tap > 0) break; // success
        }
    }
    if (tap <= 0) {
        write_str(STDERR_FILENO, progname);
        if (tun == IFF_TUN) {
            write_cstr(STDERR_FILENO, ": Cannot open TUN\n");
        } else {
            write_cstr(STDERR_FILENO, ": Cannot open TAP\n");
        }
        return 1;
    }

    gettimeofday(&tv, NULL);
    last_keep = tv.tv_sec;

    rlim.rlim_cur = 0;
    setrlimit(RLIMIT_NOFILE, &rlim);

    /* ------------ main loop without length ---------- */
    for (;;) {
        FD_ZERO(&rfd);
        FD_SET(STDIN_FILENO, &rfd);
        FD_SET(tap,          &rfd);
        tv.tv_sec  = 1;
        tv.tv_usec = 0;
        r = select(tap+1,&rfd,NULL,NULL,&tv);
        if(r == -1) {
            write_str(STDERR_FILENO, progname);
            write_cstr(STDERR_FILENO, ": select() error.\n");
            return errno;
        }
        if (interval) {
            gettimeofday(&tv, NULL);
            if (verbose && (tv.tv_sec % 10)==0) {
                write_str(STDERR_FILENO, progname);
                write_str_uint(STDERR_FILENO, ": keep count: ", keep_count);
                writeln_str_uint(STDERR_FILENO, ", keep: ", keep);
            }
            if (tv.tv_sec >= (last_keep+interval)) {
                write(STDOUT_FILENO, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20);
                if (verbose) {
                    write_str(STDERR_FILENO, progname);
                    write_cstr(STDERR_FILENO, ": Sent a keep alive.\n");
                }
                last_keep = tv.tv_sec;
            }
        }
        if (keep) {
            keep_count++;
            if (verbose) {
                write_str(STDERR_FILENO, progname);
                writeln_str_uint(STDERR_FILENO, ": keep count increased: ", keep_count);
            }
        }

        if (FD_ISSET(STDIN_FILENO,&rfd)) {
            r = read(STDIN_FILENO, buf, BUF_SIZE);
            if (r > 0 && keep) { // reset count on read.
                keep_count = 0;
                if (verbose) {
                    write_str(STDERR_FILENO, progname);
                    write_cstr(STDERR_FILENO, ": data received, keep count reseted.\n");
                }
            }
            if (r > 20) { // ignore packet inferior to 21 bytes, keep alive
                write(tap, buf, r);
            } else if (r <= 0) {
                if (verbose) {
                    write_str(STDERR_FILENO, progname);
                    write_cstr(STDERR_FILENO, ": stdin error.\n");
                }
                return 1;
            }
        }
        if (FD_ISSET(tap,&rfd)) {
            r = read(tap, buf, BUF_SIZE);
            if (r > 0) {
                write(STDOUT_FILENO, buf, r);
            } else if (r <= 0) {
                if (verbose) {
                    write_str(STDERR_FILENO, progname);
                    write_cstr(STDERR_FILENO, ": stdout error.\n");
                }
                return 2;
            }
        }
        if (keep && keep_count >= keep) {
            write_str(STDERR_FILENO, progname);
            writeln_str_uint(STDERR_FILENO, ": Keep count exceeded ", keep_count);
            kill(getppid(), SIGPIPE);
            return 0;
        }
    }
    return 0;
}
Example #2
0
void rbenv_print_usage(char *command) {
  redirect_stdout_to_stderr();
  run("rbenv-help", strarray("--usage", command, NULL));
}