/** * Adds a server and its fingerprint to the list of approved servers */ void add_server_by_name(const char *server, const char *fingerprint) { struct hostent *hp; struct in_addr *addr; if (inet_addr(server) == INADDR_NONE) { if ((hp = gethostbyname(server)) == NULL) { fprintf(stderr, "Invalid host name: %s\n", server); exit(1); } else { addr = (struct in_addr *)hp->h_addr_list[0]; server_keys[server_count].addr = *addr; server_keys[server_count].has_fingerprint = parse_fingerprint(server_keys[server_count].fingerprint, fingerprint); server_count++; } } else { server_keys[server_count].addr.s_addr = inet_addr(server); server_keys[server_count].has_fingerprint = parse_fingerprint(server_keys[server_count].fingerprint, fingerprint); server_count++; } }
/** * Add a destination or proxy to the list as specified by -H or -j */ void add_dest_by_name(const char *destname, const char *fingerprint, int proxy) { struct addrinfo ai_hints, *ai_rval; uint32_t uid; int rval; if (destcount == MAXDEST) { fprintf(stderr,"Exceeded maximum destination count\n"); exit(ERR_PARAM); } // Check if the client is specified by an IPv4 name/address ai_hints.ai_family = AF_INET; ai_hints.ai_socktype = SOCK_DGRAM; ai_hints.ai_protocol = 0; ai_hints.ai_flags = 0; if ((rval = getaddrinfo(destname, NULL, &ai_hints, &ai_rval)) != 0) { uid = strtoul(destname, NULL, 16); if ((uid == 0xffffffff) || (uid == 0)) { fprintf(stderr, "Invalid UID %s\n", destname); exit(ERR_PARAM); } destlist[destcount].id = htonl(uid); } else { destlist[destcount].id = ((struct sockaddr_in *)ai_rval->ai_addr)->sin_addr.s_addr; freeaddrinfo(ai_rval); } snprintf(destlist[destcount].name, sizeof(destlist[destcount].name), "%s", destname); destlist[destcount].proxyidx = -1; destlist[destcount].isproxy = proxy; destlist[destcount].has_fingerprint = parse_fingerprint(destlist[destcount].keyfingerprint, fingerprint); destcount++; }
/** * 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); } } }
/** * 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); } }
/** * Adds a host and its fingerprint to the given list */ void add_hosts_by_name(struct fp_list_t *list, int *list_count, const char *filename, int expect_ip) { char line[1000], *hostid, *ipstr, *fingerprint; FILE *hostfile; struct addrinfo ai_hints, *ai_rval; uint32_t remote_uid; int rval; if ((hostfile = fopen(filename, "r")) == NULL) { fprintf(stderr,"Couldn't open server/client list %s: %s\n", filename, strerror(errno)); exit(ERR_PARAM); } while (fgets(line, sizeof(line), hostfile)) { while (line[strlen(line)-1] == '\r' || line[strlen(line)-1] == '\n') { line[strlen(line)-1] = '\x0'; } if ((line[0] == '#') || (line[0] == '\x0')) { continue; } hostid = line; ipstr = strchr(hostid, '|'); if (ipstr) { *ipstr = '\x0'; ipstr++; if (expect_ip) { fingerprint = strchr(ipstr, '|'); if (fingerprint) { *fingerprint = '\x0'; fingerprint++; } } else { fingerprint = ipstr; ipstr = NULL; } } else { fingerprint = NULL; } if (strlen(hostid) >= DESTNAME_LEN) { fprintf(stderr, "Server/Client list %s: name too long\n", filename); exit(ERR_PARAM); } remote_uid = strtoul(hostid, NULL, 16); if ((remote_uid == 0xffffffff) || (remote_uid == 0)) { fprintf(stderr, "Invalid UID %s\n", hostid); exit(ERR_PARAM); } list[*list_count].uid = htonl(remote_uid); if (expect_ip) { 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(ipstr, NULL, &ai_hints, &ai_rval)) != 0) { fprintf(stderr, "Invalid host name/address %s: %s\n", ipstr, gai_strerror(rval)); exit(ERR_PARAM); } memcpy(&list[*list_count].addr, ai_rval->ai_addr, ai_rval->ai_addrlen); freeaddrinfo(ai_rval); } list[*list_count].has_fingerprint = parse_fingerprint(list[*list_count].fingerprint, fingerprint); (*list_count)++; } if (!feof(hostfile) && ferror(hostfile)) { perror("Failed to read from server/client list file"); exit(ERR_PARAM); } fclose(hostfile); }
/** * 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); } } }