Ejemplo n.º 1
0
/**
 * Set argument defaults, read and validate command line options
 */
void process_args(int argc, char *argv[])
{
    int c, i, listidx;
    long tmpval;
    struct hostent *hp;
    struct in_addr addr, *paddr;
    char line[1000], *servername, *fingerprint, *p;
    FILE *serverfile;
    const char opts[] = "dv:nL:P:I:p:T:D:M:B:Q:EU:S:R:k:K:m";

    set_defaults();

    // read lettered arguments
    while ((c = getopt(argc, argv, opts)) != EOF) {
        switch (c) {
        case 'd':
            debug = 1;
            break;
        case 'n':
            noname = 1;
            break;
        case 'v':
            verbose = atoi(optarg);
            break;
        case 'L':
            strncpy(logfile, optarg, sizeof(logfile)-1);
            logfile[sizeof(logfile)-1] = '\x0';
            break;
        case 'P':
            strncpy(pidfile, optarg, sizeof(pidfile)-1);
            pidfile[sizeof(pidfile)-1] = '\x0';
            break;
        case 'I':
            p = strtok(optarg, ",");
            while (p != NULL) {
                if ((listidx = getifbyname(p, ifl, ifl_len)) != -1) {
                    m_interface[interface_count++] = ifl[listidx];
                    p = strtok(NULL, ",");
                    continue;
                }
                if (inet_addr(p) == INADDR_NONE) {
                    if ((hp = gethostbyname(p)) == NULL) {
                        fprintf(stderr, "Invalid host name: %s\n", p);
                        exit(1);
                    } else {
                        paddr = (struct in_addr *)hp->h_addr_list[0];
                    }
                } else {
                    addr.s_addr = inet_addr(p);
                    paddr = &addr;
                }
                if ((listidx = getifbyaddr(*paddr, ifl, ifl_len)) != -1) {
                    m_interface[interface_count++] = ifl[listidx];
                } else {
                    fprintf(stderr, "Interface %s not found\n", p);
                    exit(1);
                }
                p = strtok(NULL, ",");
            }
            break;
        case 'p':
            port = atoi(optarg);
            if (port == 0) {
                fprintf(stderr, "Invalid port\n");
                exit(1);
            }
            break;
        case 'T':
            strncpy(tempdir, optarg, sizeof(tempdir)-1);
            tempdir[sizeof(tempdir)-1] = '\x0';
            break;
        case 'D':
            strncpy(destdir, optarg, sizeof(destdir)-1);
            destdir[sizeof(destdir)-1] = '\x0';
            break;
        case 'M':
            p = strtok(optarg, ",");
            while (p != NULL) {
                pub_multi[pub_multi_count].s_addr = inet_addr(p);
                if ((pub_multi[pub_multi_count].s_addr == INADDR_NONE) ||
                        (!is_multicast(pub_multi[pub_multi_count], 0))) {
                    fprintf(stderr, "Invalid multicast address: %s\n", p);
                    exit(1);
                }
                pub_multi_count++;
                p = strtok(NULL, ",");
            }
            break;
        case 'B':
            buffer = atoi(optarg);
            if ((buffer < 65536) || (buffer > 104857600)) {
                fprintf(stderr, "Invalid buffer size\n");
                exit(1);
            }
            break;
        case 'Q':
            tmpval = strtol(optarg, NULL, 0);
            if ((tmpval < 0) || (tmpval > 63)) {
                fprintf(stderr, "Invalid dscp\n");
                exit(1);
            }
            dscp = (tmpval & 0xFF) << 2;
            break;
        case 'E':
            encrypted_only = 1;
            break;
        case 'U':
            if ((uid = inet_addr(optarg)) != 0) {
                if (ntohl(uid) > 0xffffff) {
                    fprintf(stderr, "Invalid UID\n");
                    exit(1);
                }
            } else {
                uid = strtol(optarg, NULL, 16);
                if ((uid > 0xffffff) || (uid <= 0)) {
                    fprintf(stderr, "Invalid UID\n");
                    exit(1);
                }
                uid = htonl(uid);
            }
            break;
        case 'S':
            if ((serverfile = fopen(optarg, "r")) == NULL) {
                fprintf(stderr, "Couldn't open server list %s: %s\n",
                        optarg, strerror(errno));
                exit(1);
            }
            while (fgets(line, sizeof(line), serverfile)) {
                while (line[strlen(line)-1] == '\r' ||
                       line[strlen(line)-1] == '\n') {
                    line[strlen(line)-1] = '\x0';
                }
                servername = strtok(line, " \t");
                if (!servername) continue;
                if (servername[0] == '#') continue;
                if (strlen(servername) > DESTNAME_LEN) {
                    fprintf(stderr, "Server list: name too long\n");
                    exit(1);
                }
                fingerprint = strtok(NULL, " \t");
                add_server_by_name(servername, fingerprint);
            }
            if (!feof(serverfile) && ferror(serverfile)) {
                perror("Failed to read from server list file");
                exit(1);
            }
            fclose(serverfile);
            break;
        case 'R':
            strncpy(line, optarg, sizeof(line));
            line[sizeof(line)-1] = '\x0';
            servername = strtok(line, "/");
            if (!servername) {
                fprintf(stderr, "Invalid host name\n");
                exit(1);
            }
            fingerprint = strtok(NULL, "/");
            if (inet_addr(servername) == INADDR_NONE) {
                if ((hp = gethostbyname(servername)) == NULL) {
                    fprintf(stderr, "Invalid host name: %s\n", servername);
                    exit(1);
                } else {
                    paddr = (struct in_addr *)hp->h_addr_list[0];
                    proxy_info.addr = *paddr;
                    proxy_info.has_fingerprint =
                            parse_fingerprint(proxy_info.fingerprint,
                                              fingerprint);
                    has_proxy = 1;
                }
            } else {
                proxy_info.addr.s_addr = inet_addr(servername);
                proxy_info.has_fingerprint =
                        parse_fingerprint(proxy_info.fingerprint, fingerprint);
                has_proxy = 1;
            }
            break;
        case 'k':
            p = strtok(optarg, ",");
            while (p != NULL) {
                strncpy(keyfile[keyfile_count], p, sizeof(keyfile[0])-1);
                keyfile[keyfile_count][sizeof(keyfile[0])-1] = '\x0';
                keyfile_count++;
                p = strtok(NULL, ",");
            }
            break;
        case 'K':
            newkeylen = atoi(optarg);
            if ((newkeylen < 512) || (newkeylen > 2048)) {
                fprintf(stderr, "Invalid new key length\n");
                exit(1);
            }
            break;
        case 'm':
            sys_keys = 1;
            break;
        case '?':
            fprintf(stderr, USAGE);
            exit(1);
        }
    }
    if (server_count) {
        for (i = 0; i < pub_multi_count; i++) {
            if (!is_multicast(pub_multi[i], 1)) {
                fprintf(stderr, "Invalid source specific "
                        "multicast address: %s\n", inet_ntoa(pub_multi[i]));
                exit(1);
            }
        }
        if (pub_multi_count == 0) {
            fprintf(stderr, "Default multicast address %s invalid "
                    "for source specific multicast\n", DEF_PUB_MULTI);
            exit(1);
        }
    }
}
Ejemplo n.º 2
0
/**
 * Set argument defaults, read and validate command line options
 */
void process_args(int argc, char *argv[])
{
    int c, i, listidx, hbport;
    long tmpval;
    struct hostent *hp;
    struct in_addr addr, *paddr;
    char line[1000], *servername, *fingerprint, *p, *p2, *hoststr, *portstr;
    FILE *serverfile;
    const char opts[] = "dx:nL:P:I:p:tT:D:A:M:B:Q:EU:S:R:k:K:mN:h:H:";

    set_defaults();

    // read lettered arguments
    while ((c = getopt(argc, argv, opts)) != EOF) {
        switch (c) {
        case 'd':
            debug = 1;
            break;
        case 'n':
            noname = 1;
            break;
        case 'x':
            log_level = atoi(optarg);
            if (log_level < 0) {
                fprintf(stderr, "Invalid log level\n");
                exit(1);
            }
            break;
        case 'L':
            strncpy(logfile, optarg, sizeof(logfile)-1);
            logfile[sizeof(logfile)-1] = '\x0';
            break;
        case 'P':
            strncpy(pidfile, optarg, sizeof(pidfile)-1);
            pidfile[sizeof(pidfile)-1] = '\x0';
            break;
        case 'I':
            p = strtok(optarg, ",");
            while (p != NULL) {
                if ((listidx = getifbyname(p, ifl, ifl_len)) != -1) {
                    m_interface[interface_count++] = ifl[listidx];
                    p = strtok(NULL, ",");
                    continue;
                }
                if (inet_addr(p) == INADDR_NONE) {
                    if ((hp = gethostbyname(p)) == NULL) {
                        fprintf(stderr, "Invalid host name: %s\n", p);
                        exit(1);
                    } else {
                        paddr = (struct in_addr *)hp->h_addr_list[0];
                    }
                } else {
                    addr.s_addr = inet_addr(p);
                    paddr = &addr;
                }
                if ((listidx = getifbyaddr(*paddr, ifl, ifl_len)) != -1) {
                    m_interface[interface_count++] = ifl[listidx];
                } else {
                    fprintf(stderr, "Interface %s not found\n", p);
                    exit(1);
                }
                p = strtok(NULL, ",");
            }
            break;
        case 'p':
            port = atoi(optarg);
            if (port == 0) {
                fprintf(stderr, "Invalid port\n");
                exit(1);
            }
            break;
        case 't':
            tempfile = 1;
            break;
        case 'T':
            strncpy(tempdir, optarg, sizeof(tempdir)-1);
            tempdir[sizeof(tempdir)-1] = '\x0';
            break;
        case 'D':
            p = strtok(optarg, ",");
            while (p != NULL) {
                strncpy(destdir[destdircnt], p, sizeof(destdir[destdircnt])-1);
                destdir[destdircnt][sizeof(destdir[destdircnt])-1] = '\x0';
                destdircnt++;
                p = strtok(NULL, ",");
            }
            break;
        case 'A':
            p = strtok(optarg, ",");
            while (p != NULL) {
                strncpy(backupdir[backupcnt],p,sizeof(backupdir[backupcnt])-1);
                backupdir[backupcnt][sizeof(backupdir[backupcnt])-1] = '\x0';
                backupcnt++;
                p = strtok(NULL, ",");
            }
            break;
        case 'M':
            p = strtok(optarg, ",");
            while (p != NULL) {
                pub_multi[pub_multi_count].s_addr = inet_addr(p);
                if ((pub_multi[pub_multi_count].s_addr == INADDR_NONE) ||
                        (!is_multicast(pub_multi[pub_multi_count], 0))) {
                    fprintf(stderr, "Invalid multicast address: %s\n", p);
                    exit(1);
                }
                pub_multi_count++;
                p = strtok(NULL, ",");
            }
            break;
        case 'B':
            buffer = atoi(optarg);
            if ((buffer < 65536) || (buffer > 104857600)) {
                fprintf(stderr, "Invalid buffer size\n");
                exit(1);
            }
            break;
        case 'Q':
            tmpval = strtol(optarg, NULL, 0);
            if ((tmpval < 0) || (tmpval > 63)) {
                fprintf(stderr, "Invalid dscp\n");
                exit(1);
            }
            dscp = (tmpval & 0xFF) << 2;
            break;
        case 'E':
            encrypted_only = 1;
            break;
        case 'U':
            if ((uid = inet_addr(optarg)) != 0) {
                if (ntohl(uid) > 0xffffff) {
                    fprintf(stderr, "Invalid UID\n");
                    exit(1);
                }
            } else {
                uid = strtol(optarg, NULL, 16);
                if ((uid > 0xffffff) || (uid <= 0)) {
                    fprintf(stderr, "Invalid UID\n");
                    exit(1);
                }
                uid = htonl(uid);
            }
            break;
        case 'S':
            if ((serverfile = fopen(optarg, "r")) == NULL) {
                fprintf(stderr, "Couldn't open server list %s: %s\n",
                        optarg, strerror(errno));
                exit(1);
            }
            while (fgets(line, sizeof(line), serverfile)) {
                while ((strlen(line) != 0) && ((line[strlen(line)-1] == '\r') ||
                       (line[strlen(line)-1] == '\n'))) {
                    line[strlen(line)-1] = '\x0';
                }
                servername = strtok(line, " \t");
                if (!servername) continue;
                if (servername[0] == '#') continue;
                if (strlen(servername) > DESTNAME_LEN) {
                    fprintf(stderr, "Server list: name too long\n");
                    exit(1);
                }
                fingerprint = strtok(NULL, " \t");
                add_server_by_name(servername, fingerprint);
            }
            if (!feof(serverfile) && ferror(serverfile)) {
                perror("Failed to read from server list file");
                exit(1);
            }
            fclose(serverfile);
            break;
        case 'R':
            strncpy(line, optarg, sizeof(line));
            line[sizeof(line)-1] = '\x0';
            servername = strtok(line, "/");
            if (!servername) {
                fprintf(stderr, "Invalid host name\n");
                exit(1);
            }
            fingerprint = strtok(NULL, "/");
            if (inet_addr(servername) == INADDR_NONE) {
                if ((hp = gethostbyname(servername)) == NULL) {
                    fprintf(stderr, "Invalid host name: %s\n", servername);
                    exit(1);
                } else {
                    paddr = (struct in_addr *)hp->h_addr_list[0];
                    proxy_info.addr = *paddr;
                    proxy_info.has_fingerprint =
                            parse_fingerprint(proxy_info.fingerprint,
                                              fingerprint);
                    has_proxy = 1;
                }
            } else {
                proxy_info.addr.s_addr = inet_addr(servername);
                proxy_info.has_fingerprint =
                        parse_fingerprint(proxy_info.fingerprint, fingerprint);
                has_proxy = 1;
            }
            break;
        case 'k':
            p = strtok(optarg, ",");
            while (p != NULL) {
                strncpy(keyfile[keyfile_count], p, sizeof(keyfile[0])-1);
                keyfile[keyfile_count][sizeof(keyfile[0])-1] = '\x0';
                keyfile_count++;
                p = strtok(NULL, ",");
            }
            break;
        case 'K':
            newkeylen = atoi(optarg);
            if ((newkeylen < 512) || (newkeylen > 2048)) {
                fprintf(stderr, "Invalid new key length\n");
                exit(1);
            }
            break;
        case 'm':
            sys_keys = 1;
            break;
        case 'N':
            priority = atoi(optarg);
            if (!valid_priority(priority)) {
                fprintf(stderr, "Invalid priority value\n");
                exit(1);
            }
            break;
        case 'H':
            p = strtok(optarg, ",");
            while (p != NULL) {
                p2 = strchr(p, ':');
                if (p2) {
                    hoststr = strdup(p);
                    hoststr[p2 - p] = '\x0';
                    portstr = p2 + 1;
                } else {
                    hoststr = p;
                    portstr = NULL;
                }
                hb_hosts[hbhost_count].sin_family = AF_INET;
                if (inet_addr(hoststr) == INADDR_NONE) {
                    if ((hp = gethostbyname(hoststr)) == NULL) {
                        fprintf(stderr, "Invalid host name: %s\n", hoststr);
                        exit(1);
                    } else {
                        paddr = (struct in_addr *)hp->h_addr_list[0];
                        hb_hosts[hbhost_count].sin_addr.s_addr = paddr->s_addr;
                    }
                } else {
                    hb_hosts[hbhost_count].sin_addr.s_addr = inet_addr(hoststr);
                }
                if (portstr) {
                    free(hoststr);
                    hbport = atoi(portstr);
                    if ((hbport <= 0) || (hbport > 65535)) {
                        hbport = DEF_PORT;
                    }
                } else {
                    hbport = DEF_PORT;
                }
                hb_hosts[hbhost_count++].sin_port = htons(hbport);
                p = strtok(NULL, ",");
            }
            break;
        case 'h':
            hb_interval = atoi(optarg);
            if ((hb_interval <= 0) || (hb_interval > 3600)) {
                fprintf(stderr, "Invalid hearbeat interval\n");
                exit(1);
            }
            break;
        case '?':
            fprintf(stderr, USAGE);
            exit(1);
        }
    }
    if (server_count) {
        for (i = 0; i < pub_multi_count; i++) {
            if (!is_multicast(pub_multi[i], 1)) {
                fprintf(stderr, "Invalid source specific "
                        "multicast address: %s\n", inet_ntoa(pub_multi[i]));
                exit(1);
            }
        }
        if (pub_multi_count == 0) {
            fprintf(stderr, "Default multicast address %s invalid "
                    "for source specific multicast\n", DEF_PUB_MULTI);
            exit(1);
        }
    }
    if (destdircnt == 0) {
        strncpy(destdir[0], DEF_DESTDIR, sizeof(destdir[0])-1);
        destdir[0][sizeof(destdir[0])-1] = '\x0';
        destdircnt++;
    }
    if ((backupcnt > 0) && (backupcnt != destdircnt)) {
        fprintf(stderr, "Must specify same number of backup directories "
                        "as destination directories\n");
        exit(1);
    }
    if (tempfile && (strcmp(tempdir, ""))) {
        fprintf(stderr, "Cannot specify both -t and -T\n");
        exit(1);
    }
}
Ejemplo n.º 3
0
/**
 * Set argument defaults, read and validate command line options
 */
void process_args(int argc, char *argv[])
{
    int c, i, listidx, read_restart, rval;
    long tmpval;
    char line[1000], *dest, *destname, filename[MAXPATHNAME], *fingerprint, *p;
    char keylenstr[50];
    struct addrinfo ai_hints, *ai_rval;
    FILE *destfile, *excludefile, *listfile;
    const char opts[] = "x:R:L:B:g:n:m:Y:h:w:e:ck:K:lTb:t:Q:"
                        "zZI:p:u:j:qfyU:H:F:X:M:P:C:D:oE:S:r:s:i:W:N:";

    set_defaults();
    memset(keylenstr, 0, sizeof(keylenstr));
    read_restart = 0;

    // read lettered arguments
    while ((c = getopt(argc, argv, opts)) != EOF) {
        switch (c) {
        case 'x':
            log_level = atoi(optarg);
            if (log_level < 0) {
                fprintf(stderr,"Invalid log level\n");
                exit(ERR_PARAM);
            }
            break;
        case 'R':
            // Expecting rate as Kbps, translate to B/s
            rate = atoi(optarg);
            if ((rate <= 0) && (rate != -1)) {
                fprintf(stderr,"Invalid rate\n");
                exit(ERR_PARAM);
            }
            if (rate != -1) {
                rate = rate * 1024 / 8;
            }
            break;
        case 'L':
            strncpy(logfile, optarg, sizeof(logfile)-1);
            logfile[sizeof(logfile)-1] = '\x0';
            break;
        case 'B':
            rcvbuf = atoi(optarg);
            if ((rcvbuf < 65536) || (rcvbuf > 104857600)) {
                fprintf(stderr, "Invalid receive buffer size\n");
                exit(ERR_PARAM);
            }
            break;
        case 'g':
            max_log_size = atoi(optarg);
            if ((max_log_size < 1) || (max_log_size > 1024)) {
                fprintf(stderr, "Invalid max log size\n");
                exit(ERR_PARAM);
            }
            max_log_size *= 1000000;
            break;
        case 'n':
            max_log_count = atoi(optarg);
            if ((max_log_count < 1) || (max_log_count > 1000)) {
                fprintf(stderr, "Invalid max log count\n");
                exit(ERR_PARAM);
            }
            break;
        case 'm':
            max_nak_cnt = atoi(optarg);
            if ((max_nak_cnt < 1) || (max_nak_cnt > 1000)) {
                fprintf(stderr, "Invalid max nak count\n");
                exit(ERR_PARAM);
            }
            break;
        case 'Y':
            if ((keytype = get_keytype(optarg)) == -1) {
                fprintf(stderr, "Invalid keytype\n");
                exit(ERR_PARAM);
            }
            if (keytype != KEY_NONE && !cipher_supported(keytype)) {
                fprintf(stderr, "Keytype not supported\n");
                exit(ERR_PARAM);
            }
            break;
        case 'h':
            if ((hashtype = get_hashtype(optarg)) == -1) {
                fprintf(stderr, "Invalid hashtype\n");
                exit(ERR_PARAM);
            }
            if (!hash_supported(hashtype)) {
                fprintf(stderr, "Hashtype not supported\n");
                exit(ERR_PARAM);
            }
            break;
        case 'w':
            if (!strcmp(optarg, "hmac")) {
                sigtype = SIG_HMAC;
            } else if (!strcmp(optarg, "keyex")) {
                sigtype = SIG_KEYEX;
            } else {
                fprintf(stderr, "Invalid sigtype\n");
                exit(ERR_PARAM);
            }
            break;
        case 'e':
            p = strtok(optarg, ":");
            if (!p) {
                fprintf(stderr, "Error reading keyextype\n");
                exit(ERR_PARAM);
            }
            if (!strcmp(p, "rsa")) {
                keyextype = KEYEX_RSA;
            } else if (!strcmp(p, "ecdh_rsa")) {
                keyextype = KEYEX_ECDH_RSA;
            } else if (!strcmp(p, "ecdh_ecdsa")) {
                keyextype = KEYEX_ECDH_ECDSA;
            } else {
                fprintf(stderr, "Invalid keyextype\n");
                exit(ERR_PARAM);
            }
            if ((keyextype == KEYEX_ECDH_RSA) ||
                    (keyextype == KEYEX_ECDH_ECDSA)) {
                p = strtok(NULL, ":");
                if (p) {
                    ecdh_curve = get_curve(p);
                    if (ecdh_curve == 0) {
                        fprintf(stderr, "Invalid curve\n");
                        exit(ERR_PARAM);
                    }
                } else {
                    ecdh_curve = DEF_CURVE;
                }
            }
            break;
        case 'c':
            client_auth = 1;
            break;
        case 'k':
            strncpy(keyfile, optarg, sizeof(keyfile)-1);
            keyfile[sizeof(keyfile)-1] = '\x0';
            break;
        case 'K':
            strncpy(keylenstr, optarg, sizeof(keylenstr)-1);
            keylenstr[sizeof(keylenstr)-1] = '\x0';
            break;
        case 'l':
            follow_links = 1;
            break;
        case 'T':
            showtime = 1;
            break;
        case 'b':
            blocksize = atoi(optarg); 
            if ((blocksize < 512) || (blocksize > (MAXMTU - 200))) {
                fprintf(stderr, "Invalid blocksize\n");
                exit(ERR_PARAM);
            }
            break;
        case 't':
            tmpval = atoi(optarg);
            if ((tmpval <= 0) || (tmpval > 255)) {
                fprintf(stderr, "Invalid ttl\n");
                exit(ERR_PARAM);
            }
            ttl = (char)tmpval;
            break;
        case 'Q':
            tmpval = strtol(optarg, NULL, 0);
            if ((tmpval < 0) || (tmpval > 63)) {
                fprintf(stderr, "Invalid dscp\n");
                exit(ERR_PARAM);
            }
            dscp = (tmpval & 0xFF) << 2; 
            break;
        case 'I':
            if ((listidx = getifbyname(optarg, ifl, ifl_len)) != -1) {
                out_if = ifl[listidx];
                break;
            }
            memset(&ai_hints, 0, sizeof(ai_hints));
            ai_hints.ai_family = AF_UNSPEC;
            ai_hints.ai_socktype = SOCK_DGRAM;
            ai_hints.ai_protocol = 0;
            ai_hints.ai_flags = 0;
            if ((rval = getaddrinfo(optarg, NULL, &ai_hints, &ai_rval)) != 0) {
                fprintf(stderr, "Invalid name/address %s: %s\n",
                        optarg, gai_strerror(rval));
                exit(ERR_PARAM);
            }
            // Just use the first addrinfo entry
            if ((listidx = getifbyaddr((union sockaddr_u *)ai_rval->ai_addr,
                    ifl, ifl_len)) == -1) {
                fprintf(stderr, "Interface %s not found", optarg);
                exit(ERR_PARAM);
            }
            out_if = ifl[listidx];
            freeaddrinfo(ai_rval);
            break;
        case 'z':
            sync_mode = 1;
            break;
        case 'Z':
            sync_preview = 1;
            sync_mode = 1;
            break;
        case 'p':
            strncpy(port, optarg, sizeof(port)-1);
            port[sizeof(port)-1] = '\x0';
            break;
        case 'u':
            strncpy(srcport, optarg, sizeof(srcport)-1);
            srcport[sizeof(srcport)-1] = '\x0';
            break;
        case 'j':
            if (read_restart) {
                fprintf(stderr,"Can't specify both -j and -F\n");
                exit(ERR_PARAM);
            }
            if ((destfile = fopen(optarg, "rt")) == NULL) {
                fprintf(stderr,"Couldn't open proxy list %s: %s\n",
                        optarg, strerror(errno));
                exit(ERR_PARAM);
            }
            while (fgets(line, sizeof(line), destfile)) {
                while ((strlen(line) > 0) && ((line[strlen(line)-1] == '\r') ||
                       (line[strlen(line)-1] == '\n'))) {
                    line[strlen(line)-1] = '\x0';
                }
                destname = strtok(line, "|");
                if (!destname) continue;
                if (destname[0] == '#') continue;
                if (strlen(destname) >= DESTNAME_LEN) {
                    fprintf(stderr, "Proxylist: name too long\n");
                    exit(ERR_PARAM);
                }
                fingerprint = strtok(NULL, " \t");
                add_dest_by_name(destname, fingerprint, 1);
            }
            if (!feof(destfile) && ferror(destfile)) {
                perror("Failed to read from proxylist file");
                exit(ERR_PARAM);
            }
            fclose(destfile);
            break;
        case 'q':
            quit_on_error = 1;
            break;
        case 'f':
            save_fail = 1;
            break;
        case 'y':
            sys_keys = 1;
            break;
        case 'U':
            errno = 0;
            server_id = strtoul(optarg, NULL, 16);
            if (errno) {
                perror("Invalid UID\n");
                exit(ERR_PARAM);
            }
            server_id = htonl(server_id);
            break;
        case 'H':
            if (read_restart) {
                fprintf(stderr,"Can't specify both -H and -F\n");
                exit(ERR_PARAM);
            }
            if (optarg[0] == '@') {
                dest = &optarg[1];
                if ((destfile = fopen(dest, "rt")) == NULL) {
                    fprintf(stderr,"Couldn't open destination list %s: %s\n",
                            dest, strerror(errno));
                    exit(ERR_PARAM);
                }
                while (fgets(line, sizeof(line), destfile)) {
                    while ((strlen(line) > 0) &&
                           ((line[strlen(line)-1] == '\r') ||
                            (line[strlen(line)-1] == '\n'))) {
                        line[strlen(line)-1] = '\x0';
                    }
                    destname = strtok(line, "|");
                    if (!destname) continue;
                    if (destname[0] == '#') continue;
                    if (strlen(destname) >= DESTNAME_LEN) {
                        fprintf(stderr, "Hostlist: name too long\n");
                        exit(ERR_PARAM);
                    }
                    fingerprint = strtok(NULL, " \t");
                    add_dest_by_name(destname, fingerprint, 0);
                }
                if (!feof(destfile) && ferror(destfile)) {
                    perror("Failed to read from hostlist file");
                    exit(ERR_PARAM);
                }
                fclose(destfile);
            } else {
                dest = strtok(optarg, ",");
                while (dest != NULL) {
                    add_dest_by_name(dest, NULL, 0);
                    dest = strtok(NULL, ",");
                }
            }
            break;
        case 'F':
            if (destcount != 0) {
                fprintf(stderr,"Can't specify both -H and -F\n");
                exit(ERR_PARAM);
            }
            read_restart = 1;
            save_fail = 1;
            read_restart_file(optarg);
            break;
        case 'X':
            if ((excludefile = fopen(optarg, "rt")) == NULL) {
                fprintf(stderr,"Couldn't open exclude list %s: %s\n",
                        optarg, strerror(errno));
                exit(ERR_PARAM);
            }
            while (fgets(filename, sizeof(filename), excludefile)) {
                while ((strlen(filename) > 0) &&
                       ((filename[strlen(filename)-1] == '\r') ||
                        (filename[strlen(filename)-1] == '\n'))) {
                    filename[strlen(filename)-1] = '\x0';
                }
                if (strlen(filename) == 0) continue;
                if (excludecount == MAXEXCLUDE) {
                    fprintf(stderr,"Exceeded maximum exclude file count\n");
                    exit(ERR_PARAM);
                }
                strncpy(exclude[excludecount], filename, sizeof(exclude[0]));
                exclude[excludecount][sizeof(exclude[0])-1] = '\x0';
                excludecount++;
            }
            if (!feof(excludefile) && ferror(excludefile)) {
                perror("Failed to read from exclude file");
                exit(ERR_PARAM);
            }
            fclose(excludefile);
            break;
        case 'M':
            strncpy(pub_multi, optarg, sizeof(pub_multi)-1);
            pub_multi[sizeof(pub_multi)-1] = '\x0';
            break;
        case 'P':
            strncpy(priv_multi, optarg, sizeof(priv_multi)-1);
            priv_multi[sizeof(priv_multi)-1] = '\x0';
            break;
        case 'C':
            p = strtok(optarg, ":");
            if (!p) {
                fprintf(stderr, "Error reading cc_type\n");
                exit(ERR_PARAM);
            }
            if (!strcmp(p, "none")) {
                cc_type = CC_NONE;
            } else if (!strcmp(p, "tfmcc")) {
                cc_type = CC_TFMCC;
                p = strtok(NULL, ":");
                if (p) {
                    max_rate = atoi(p);
                    if (max_rate <= 0) {
                        fprintf(stderr,"Invalid max rate\n");
                        exit(ERR_PARAM);
                    }
                    max_rate = max_rate * 1024 / 8;
                }
            } else {
                // PGMCC not currently supported
                fprintf(stderr, "Invalid congestion control type\n");
                exit(ERR_PARAM);
            }
            break;
        case 'D':
            strncpy(destfname, optarg, sizeof(destfname)-1);
            destfname[sizeof(destfname)-1] = '\x0';
            while (destfname[strlen(destfname)-1] == PATH_SEP) {
                destfname[strlen(destfname)-1] = '\x0';
            }
            break;
        case 'o':
            dest_is_dir = 1;
            break;
        case 'E':
            p = strtok(optarg, ",");
            while (p != NULL) {
                strncpy(basedir[basedircount], p,
                        sizeof(basedir[basedircount])-1);
                basedir[basedircount][sizeof(basedir[basedircount])-1] = '\x0';
                basedircount++;
                p = strtok(NULL, ",");
            }
            break;
        case 'S':
            strncpy(statusfilename, optarg, sizeof(statusfilename)-1);
            statusfilename[sizeof(statusfilename)-1] = '\x0';
            break;
        case 'r':
            p = strtok(optarg, ":");
            if (!p) {
                fprintf(stderr, "Error reading cc_type\n");
                exit(ERR_PARAM);
            }
            errno = 0;
            grtt = atof(p);
            if (errno) {
                perror("Invalid grtt");
                exit(ERR_PARAM);
            } else if ((grtt < CLIENT_RTT_MIN) || (grtt > 1000)) {
                fprintf(stderr, "Invalid grtt\n");
                exit(ERR_PARAM);
            }
            p = strtok(NULL, ":");
            if (p) {
                errno = 0;
                min_grtt = atof(p);
                if (errno) {
                    perror("Invalid min_grtt");
                    exit(ERR_PARAM);
                } else if ((min_grtt < CLIENT_RTT_MIN) || (min_grtt > 1000)) {
                    fprintf(stderr, "Invalid min_grtt\n");
                    exit(ERR_PARAM);
                }
                p = strtok(NULL, ":");
                if (!p) {
                    fprintf(stderr, "Missing max_grtt\n");
                    exit(ERR_PARAM);
                }
                errno = 0;
                max_grtt = atof(p);
                if (errno) {
                    perror("Invalid max_grtt");
                    exit(ERR_PARAM);
                } else if ((max_grtt < CLIENT_RTT_MIN) || (max_grtt > 1000)) {
                    fprintf(stderr, "Invalid max_grtt\n");
                    exit(ERR_PARAM);
                }
                if (min_grtt > max_grtt) {
                    fprintf(stderr, "Invalid min_grtt/max_grtt\n");
                    exit(ERR_PARAM);
                } else if ((grtt > max_grtt) || (grtt < min_grtt)) {
                    fprintf(stderr, "Invalid grtt\n");
                    exit(ERR_PARAM);
                }
            }
            break;
        case 's':
            robust = atoi(optarg);
            if ((robust < 10) || (robust > 50)) {
                fprintf(stderr,"Invalid robustness factor\n");
                exit(ERR_PARAM);
            }
            break;
        case 'i':
            if (filecount != 0) {
                fprintf(stderr,"Can't specify both -i and -F\n");
                exit(ERR_PARAM);
            }
            if (strcmp(optarg, "-") == 0) {
                listfile = stdin;
            } else if ((listfile = fopen(optarg, "rt")) == NULL) {
                fprintf(stderr,"Couldn't open file list %s: %s\n",
                        optarg, strerror(errno));
                exit(ERR_PARAM);
            }
            while (fgets(filename, sizeof(filename), listfile)) {
                if (filecount == MAXFILES) {
                    fprintf(stderr, "Exceeded maximum file count\n");
                    exit(ERR_PARAM);
                }
                while ((strlen(filename) > 0) &&
                       ((filename[strlen(filename)-1] == '\r') ||
                        (filename[strlen(filename)-1] == '\n'))) {
                    filename[strlen(filename)-1] = '\x0';
                }
                if (strlen(filename) == 0) continue;
                strncpy(filelist[filecount], filename, sizeof(filelist[0])-1);
                filelist[filecount][sizeof(filelist[0])-1] = '\x0';
                filecount++;
            }
            if (!feof(listfile) && ferror(listfile)) {
                perror("Failed to read from file list");
                exit(ERR_PARAM);
            }
            fclose(listfile);
            break;
        case 'W':
            txweight = atoi(optarg);
            if ((txweight < 110) || (txweight > 10000)) {
                fprintf(stderr, "Invalid txweight\n");
                exit(ERR_PARAM);
            }
            break;
        case 'N':
            max_nak_pct = atoi(optarg);
            if ((max_nak_pct < 0) || (max_nak_pct > 100)) {
                fprintf(stderr, "Invalid max_nak_pct\n");
                exit(ERR_PARAM);
            }
            break;
        case '?':
            fprintf(stderr, USAGE);
            exit(ERR_PARAM);
        }
    }
    argc -= optind;
    argv += optind;
    if ((argc == 0) && (filecount == 0)) {
        fprintf(stderr, USAGE);
        exit(ERR_PARAM);
    }

    if (save_fail && sync_mode) {
        fprintf(stderr, "Error: Cannot use restart mode "
                        "and sync mode together\n");
        exit(ERR_PARAM);
    }

    if (keytype == KEY_NONE) {
        hashtype = HASH_NONE;
        sigtype = SIG_NONE;
        keyextype = KEYEX_NONE;
    }
    if (is_auth_enc(keytype)) {
        sigtype = SIG_AUTHENC;
    }
    if (strcmp(keylenstr, "")) {
        if (keyextype == KEYEX_ECDH_ECDSA) {
            ecdsa_curve = get_curve(keylenstr);
            if (ecdsa_curve == 0) {
                fprintf(stderr, "Invalid curve\n");
                exit(ERR_PARAM);
            }
        } else if ((keyextype == KEYEX_RSA) || (keyextype == KEYEX_ECDH_RSA)) {
            newkeylen = atoi(keylenstr);
            if ((newkeylen < 512) || (newkeylen > 2048)) {
                fprintf(stderr, "Invalid new key length\n");
                exit(ERR_PARAM);
            }
        }
    }

    if (filecount != 0) {
        if (argc > 0) {
            fprintf(stderr, "Warning: ignoring paths "
                            "specified on command line\n");
        }
        return;
    }
    // Read list of files.
    for (i = 0; i < argc; i++) {
        if (filecount == MAXFILES) {
            fprintf(stderr, "Exceeded maximum file count\n");
            exit(ERR_PARAM);
        }
        strncpy(filelist[filecount], argv[i], sizeof(filelist[0])-1);
        filelist[filecount][sizeof(filelist[0])-1] = '\x0';
        filecount++;
    }
}
Ejemplo n.º 4
0
/**
 * Set argument defaults, read and validate command line options
 */
void process_args(int argc, char *argv[])
{
    struct addrinfo ai_hints, *ai_rval;
    int c, i, listidx, rval;
    long tmpval;
    char *p, *p2, *hoststr, *portstr, pubname[INET6_ADDRSTRLEN];
    const char opts[] = "s:crdx:p:t:Q:N:O:U:q:mh:H:g:n:B:L:P:C:S:e:k:K:I:M:";

    set_defaults();
    srand((unsigned int)time(NULL) ^ getpid());

    // read lettered arguments
    while ((c = getopt(argc, argv, opts)) != EOF) {
        switch (c) {
        case 's':
            if (proxy_type != UNDEF_PROXY) {
                fprintf(stderr, "Only one of -s, -c, -r may be specified\n");
                exit(ERR_PARAM);
            }
            proxy_type = SERVER_PROXY;
            memset(&down_addr, 0, sizeof(down_addr));
            if (!strncmp(optarg, "fp=", 3)) {
                have_down_fingerprint =
                    parse_fingerprint(down_fingerprint, optarg + 3);
                if (!have_down_fingerprint) {
                    fprintf(stderr, "Failed to parse downstream fingerprint\n");
                    exit(ERR_PARAM);
                }
                down_nonce = rand32();
            } else {
                have_down_fingerprint = 0;
                memset(&ai_hints, 0, sizeof(ai_hints));
                ai_hints.ai_family = AF_UNSPEC;
                ai_hints.ai_socktype = SOCK_DGRAM;
                ai_hints.ai_protocol = 0;
                ai_hints.ai_flags = 0;
                if ((rval = getaddrinfo(optarg, NULL, &ai_hints,
                                        &ai_rval)) != 0) {
                    fprintf(stderr, "Invalid host name: %s: %s\n",
                            optarg, gai_strerror(rval));
                    exit(ERR_PARAM);
                }
                memcpy(&down_addr, ai_rval->ai_addr, ai_rval->ai_addrlen);
                freeaddrinfo(ai_rval);
            }
            break;
        case 'c':
            if (proxy_type != UNDEF_PROXY) {
                fprintf(stderr, "Only one of -s, -c, -r may be specified\n");
                exit(ERR_PARAM);
            }
            proxy_type = CLIENT_PROXY;
            break;
        case 'r':
            if (proxy_type != UNDEF_PROXY) {
                fprintf(stderr, "Only one of -s, -c, -r may be specified\n");
                exit(ERR_PARAM);
            }
            proxy_type = RESPONSE_PROXY;
            break;
        case 'd':
            debug = 1;
            break;
        case 'x':
            log_level = atoi(optarg);
            if (log_level < 0) {
                fprintf(stderr, "Invalid log level\n");
                exit(ERR_PARAM);
            }
            break;
        case 'p':
            strncpy(portname, optarg, sizeof(portname)-1);
            portname[sizeof(portname)-1] = '\x0';
            port = atoi(portname);
            if (port == 0) {
                fprintf(stderr, "Invalid port\n");
                exit(ERR_PARAM);
            }
            break;
        case 't':
            tmpval = atoi(optarg);
            if ((tmpval <= 0) || (tmpval > 255)) {
                fprintf(stderr, "Invalid ttl\n");
                exit(ERR_PARAM);
            }
            ttl = (char)tmpval;
            break;
        case 'Q':
            tmpval = strtol(optarg, NULL, 0);
            if ((tmpval < 0) || (tmpval > 63)) {
                fprintf(stderr, "Invalid dscp\n");
                exit(ERR_PARAM);
            }
            dscp = (tmpval & 0xFF) << 2;
            break;
        case 'N':
            priority = atoi(optarg);
            if (!valid_priority(priority)) {
                fprintf(stderr, "Invalid priority value\n");
                exit(ERR_PARAM);
            }
            break;
        case 'O':
            if ((listidx = getifbyname(optarg, ifl, ifl_len)) != -1) {
                out_if = ifl[listidx];
                break;
            }
            memset(&ai_hints, 0, sizeof(ai_hints));
            ai_hints.ai_family = AF_UNSPEC;
            ai_hints.ai_socktype = SOCK_DGRAM;
            ai_hints.ai_protocol = 0;
            ai_hints.ai_flags = 0;
            if ((rval = getaddrinfo(optarg, NULL, &ai_hints, &ai_rval)) != 0) {
                fprintf(stderr, "Invalid name/address %s: %s\n",
                        optarg, gai_strerror(rval));
                exit(ERR_PARAM);
            }
            // Just use the first addrinfo entry
            if ((listidx = getifbyaddr((union sockaddr_u *)ai_rval->ai_addr,
                                       ifl, ifl_len)) == -1) {
                fprintf(stderr, "Interface %s not found", optarg);
                exit(ERR_PARAM);
            }
            out_if = ifl[listidx];
            freeaddrinfo(ai_rval);
            break;
        case 'U':
            errno = 0;
            uid = strtoul(optarg, NULL, 16);
            if (errno) {
                perror("Invalid UID\n");
                exit(ERR_PARAM);
            }
            uid = htonl(uid);
            break;
        case 'q':
            strncpy(out_portname, optarg, sizeof(out_portname)-1);
            out_portname[sizeof(out_portname)-1] = '\x0';
            out_port = atoi(out_portname);
            if (out_port == 0) {
                fprintf(stderr, "Invalid outgoing port\n");
                exit(ERR_PARAM);
            }
            break;
        case 'm':
            sys_keys = 1;
            break;
        case 'H':
            p = strtok(optarg, ",");
            while (p != NULL) {
                p2 = strchr(p, ':');
                if (p2) {
                    hoststr = strdup(p);
                    hoststr[p2 - p] = '\x0';
                    portstr = p2 + 1;
                } else {
                    hoststr = p;
                    portstr = NULL;
                }
                memset(&ai_hints, 0, sizeof(ai_hints));
                ai_hints.ai_family = AF_UNSPEC;
                ai_hints.ai_socktype = SOCK_DGRAM;
                ai_hints.ai_protocol = 0;
                ai_hints.ai_flags = 0;
                if ((rval = getaddrinfo(hoststr, portstr ? portstr : DEF_PORT,
                                        &ai_hints, &ai_rval)) != 0) {
                    fprintf(stderr, "Invalid name/address %s: %s\n",
                            hoststr, gai_strerror(rval));
                    exit(ERR_PARAM);
                }
                memcpy(&hb_hosts[hbhost_count++], ai_rval->ai_addr,
                       ai_rval->ai_addrlen);
                p = strtok(NULL, ",");
            }
            break;
        case 'h':
            hb_interval = atoi(optarg);
            if ((hb_interval <= 0) || (hb_interval > 3600)) {
                fprintf(stderr, "Invalid heartbeat interval\n");
                exit(ERR_PARAM);
            }
            break;
        case 'g':
            max_log_size = atoi(optarg);
            if ((max_log_size < 1) || (max_log_size > 1024)) {
                fprintf(stderr, "Invalid max log size\n");
                exit(ERR_PARAM);
            }
            max_log_size *= 1000000;
            break;
        case 'n':
            max_log_count = atoi(optarg);
            if ((max_log_count < 1) || (max_log_count > 1000)) {
                fprintf(stderr, "Invalid max log count\n");
                exit(ERR_PARAM);
            }
            break;
        case 'B':
            rcvbuf = atoi(optarg);
            if ((rcvbuf < 65536) || (rcvbuf > 104857600)) {
                fprintf(stderr, "Invalid buffer size\n");
                exit(ERR_PARAM);
            }
            break;
        case 'L':
            strncpy(logfile, optarg, sizeof(logfile)-1);
            logfile[sizeof(logfile)-1] = '\x0';
            break;
        case 'P':
            strncpy(pidfile, optarg, sizeof(pidfile)-1);
            pidfile[sizeof(pidfile)-1] = '\x0';
            break;
        case 'C':
            add_hosts_by_name(client_fp, &client_fp_count, optarg, 0);
            break;
        case 'S':
            add_hosts_by_name(server_fp, &server_fp_count, optarg, 1);
            break;
        case 'e':
            ecdh_curve = get_curve(optarg);
            if (ecdh_curve == 0) {
                fprintf(stderr, "Invalid curve\n");
                exit(ERR_PARAM);
            }
            break;
        case 'k':
            p = strtok(optarg, ",");
            while (p != NULL) {
                strncpy(keyfile[keyfile_count], p, sizeof(keyfile[0])-1);
                keyfile[keyfile_count][sizeof(keyfile[0])-1] = '\x0';
                keyfile_count++;
                p = strtok(NULL, ",");
            }
            break;
        case 'K':
            p = strtok(optarg, ",");
            while (p != NULL) {
                strncpy(keyinfo[keyinfo_count], p, sizeof(keyinfo[0])-1);
                keyinfo[keyinfo_count][sizeof(keyinfo[0])-1] = '\x0';
                keyinfo_count++;
                p = strtok(NULL, ",");
            }
            break;
        case 'I':
            p = strtok(optarg, ",");
            while (p != NULL) {
                if ((listidx = getifbyname(p, ifl, ifl_len)) != -1) {
                    m_interface[interface_count++] = ifl[listidx];
                    p = strtok(NULL, ",");
                    continue;
                }
                memset(&ai_hints, 0, sizeof(ai_hints));
                ai_hints.ai_family = AF_UNSPEC;
                ai_hints.ai_socktype = SOCK_DGRAM;
                ai_hints.ai_protocol = 0;
                ai_hints.ai_flags = 0;
                if ((rval = getaddrinfo(p, NULL,
                                        &ai_hints, &ai_rval)) != 0) {
                    fprintf(stderr, "Invalid name/address %s: %s\n",
                            p, gai_strerror(rval));
                    exit(ERR_PARAM);
                }
                if ((listidx = getifbyaddr((union sockaddr_u *)ai_rval->ai_addr,
                                           ifl, ifl_len)) == -1) {
                    fprintf(stderr, "Interface %s not found\n", p);
                    exit(ERR_PARAM);
                }
                m_interface[interface_count++] = ifl[listidx];
                freeaddrinfo(ai_rval);
                p = strtok(NULL, ",");
            }
            break;
        case 'M':
            p = strtok(optarg, ",");
            while (p != NULL) {
                memset(&ai_hints, 0, sizeof(ai_hints));
                ai_hints.ai_family = AF_UNSPEC;
                ai_hints.ai_socktype = SOCK_DGRAM;
                ai_hints.ai_protocol = 0;
                ai_hints.ai_flags = 0;
                if ((rval = getaddrinfo(p, NULL,
                                        &ai_hints, &ai_rval)) != 0) {
                    fprintf(stderr, "Invalid multicast address %s: %s\n",
                            p, gai_strerror(rval));
                    exit(ERR_PARAM);
                }
                memcpy(&pub_multi[pub_multi_count], ai_rval->ai_addr,
                       ai_rval->ai_addrlen);
                pub_multi_count++;
                freeaddrinfo(ai_rval);
                p = strtok(NULL, ",");
            }
            break;
        case '?':
            fprintf(stderr, USAGE);
            exit(ERR_PARAM);
        }
    }

    if (proxy_type == UNDEF_PROXY) {
        fprintf(stderr, "Either -s, -c, or -r must be specified\n");
        fprintf(stderr, USAGE);
        exit(ERR_PARAM);
    }
    if (proxy_type == RESPONSE_PROXY) {
        out_port = port;
    }
    if (proxy_type == SERVER_PROXY) {
        if (down_addr.ss.ss_family == AF_INET6) {
            down_addr.sin6.sin6_port = htons(out_port);
        } else {
            down_addr.sin.sin_port = htons(out_port);
        }
    }
    if (proxy_type != CLIENT_PROXY) {
        if (server_fp_count) {
            for (i = 0; i < pub_multi_count; i++) {
                if (!is_multicast(&pub_multi[i], 1)) {
                    if ((rval = getnameinfo((struct sockaddr *)&pub_multi[i],
                                            family_len(pub_multi[i]), pubname, sizeof(pubname),
                                            NULL, 0, NI_NUMERICHOST)) != 0) {
                        fprintf(stderr,"getnameinfo failed: %s",
                                gai_strerror(rval));
                    }
                    fprintf(stderr, "Invalid source specific "
                            "multicast address: %s\n", pubname);
                    exit(ERR_PARAM);
                }
            }
            if (pub_multi_count == 0) {
                fprintf(stderr, "Default multicast address %s invalid "
                        "for source specific multicast\n", DEF_PUB_MULTI);
                exit(ERR_PARAM);
            }
        }
    }
    if ((keyfile_count != 0) && (keyinfo_count != 0) &&
            (keyfile_count != keyinfo_count)) {
        fprintf(stderr, "Must list same number of items for -k and -K\n");
        exit(ERR_PARAM);
    }
    for (i = 0; i < pub_multi_count; i++) {
        if (pub_multi[i].ss.ss_family == AF_INET6) {
            pub_multi[i].sin6.sin6_port = htons(out_port);
        } else {
            pub_multi[i].sin.sin_port = htons(out_port);
        }
    }
}