/** Add an entry to the GeoIP table indicated by <b>family</b>, * parsing it from <b>line</b>. The format is as for geoip_load_file(). */ /*private*/ int geoip_parse_entry(const char *line, sa_family_t family) { tor_addr_t low_addr, high_addr; char c[3]; char *country = NULL; if (!geoip_countries) init_geoip_countries(); if (family == AF_INET) { if (!geoip_ipv4_entries) geoip_ipv4_entries = smartlist_new(); } else if (family == AF_INET6) { if (!geoip_ipv6_entries) geoip_ipv6_entries = smartlist_new(); } else { log_warn(LD_GENERAL, "Unsupported family: %d", family); return -1; } while (TOR_ISSPACE(*line)) ++line; if (*line == '#') return 0; if (family == AF_INET) { unsigned int low, high; if (tor_sscanf(line,"%u,%u,%2s", &low, &high, c) == 3 || tor_sscanf(line,"\"%u\",\"%u\",\"%2s\",", &low, &high, c) == 3) { tor_addr_from_ipv4h(&low_addr, low); tor_addr_from_ipv4h(&high_addr, high); } else goto fail; country = c; } else { /* AF_INET6 */ char buf[512]; char *low_str, *high_str; struct in6_addr low, high; char *strtok_state; strlcpy(buf, line, sizeof(buf)); low_str = tor_strtok_r(buf, ",", &strtok_state); if (!low_str) goto fail; high_str = tor_strtok_r(NULL, ",", &strtok_state); if (!high_str) goto fail; country = tor_strtok_r(NULL, "\n", &strtok_state); if (!country) goto fail; if (strlen(country) != 2) goto fail; if (tor_inet_pton(AF_INET6, low_str, &low) <= 0) goto fail; tor_addr_from_in6(&low_addr, &low); if (tor_inet_pton(AF_INET6, high_str, &high) <= 0) goto fail; tor_addr_from_in6(&high_addr, &high); } geoip_add_entry(&low_addr, &high_addr, country); return 0; fail: log_warn(LD_GENERAL, "Unable to parse line from GEOIP %s file: %s", family == AF_INET ? "IPv4" : "IPv6", escaped(line)); return -1; }
/** * Helper function to parse out a line in the measured bandwidth file * into a measured_bw_line_t output structure. * * If <b>line_is_after_headers</b> is true, then if we encounter an incomplete * bw line, return -1 and warn, since we are after the headers and we should * only parse bw lines. Return 0 otherwise. * * If <b>line_is_after_headers</b> is false then it means that we are not past * the header block yet. If we encounter an incomplete bw line, return -1 but * don't warn since there could be additional header lines coming. If we * encounter a proper bw line, return 0 (and we got past the headers). * * If the line contains "vote=0", stop parsing it, and return -1, so that the * line is ignored during voting. */ STATIC int measured_bw_line_parse(measured_bw_line_t *out, const char *orig_line, int line_is_after_headers) { char *line = tor_strdup(orig_line); char *cp = line; int got_bw = 0; int got_node_id = 0; char *strtok_state; /* lame sauce d'jour */ if (strlen(line) == 0) { log_warn(LD_DIRSERV, "Empty line in bandwidth file"); tor_free(line); return -1; } /* Remove end of line character, so that is not part of the token */ if (line[strlen(line) - 1] == '\n') { line[strlen(line) - 1] = '\0'; } cp = tor_strtok_r(cp, " \t", &strtok_state); if (!cp) { log_warn(LD_DIRSERV, "Invalid line in bandwidth file: %s", escaped(orig_line)); tor_free(line); return -1; } if (orig_line[strlen(orig_line)-1] != '\n') { log_warn(LD_DIRSERV, "Incomplete line in bandwidth file: %s", escaped(orig_line)); tor_free(line); return -1; } do { // If the line contains vote=0, ignore it. if (strcmpstart(cp, "vote=0") == 0) { log_debug(LD_DIRSERV, "Ignoring bandwidth file line that contains " "vote=0: %s",escaped(orig_line)); tor_free(line); return -1; } else if (strcmpstart(cp, "bw=") == 0) { int parse_ok = 0; char *endptr; if (got_bw) { log_warn(LD_DIRSERV, "Double bw= in bandwidth file line: %s", escaped(orig_line)); tor_free(line); return -1; } cp+=strlen("bw="); out->bw_kb = tor_parse_long(cp, 10, 0, LONG_MAX, &parse_ok, &endptr); if (!parse_ok || (*endptr && !TOR_ISSPACE(*endptr))) { log_warn(LD_DIRSERV, "Invalid bandwidth in bandwidth file line: %s", escaped(orig_line)); tor_free(line); return -1; } got_bw=1; } else if (strcmpstart(cp, "node_id=$") == 0) { if (got_node_id) { log_warn(LD_DIRSERV, "Double node_id= in bandwidth file line: %s", escaped(orig_line)); tor_free(line); return -1; } cp+=strlen("node_id=$"); if (strlen(cp) != HEX_DIGEST_LEN || base16_decode(out->node_id, DIGEST_LEN, cp, HEX_DIGEST_LEN) != DIGEST_LEN) { log_warn(LD_DIRSERV, "Invalid node_id in bandwidth file line: %s", escaped(orig_line)); tor_free(line); return -1; } strlcpy(out->node_hex, cp, sizeof(out->node_hex)); got_node_id=1; } } while ((cp = tor_strtok_r(NULL, " \t", &strtok_state))); if (got_bw && got_node_id) { tor_free(line); return 0; } else if (line_is_after_headers == 0) { /* There could be additional header lines, therefore do not give warnings * but returns -1 since it's not a complete bw line. */ log_debug(LD_DIRSERV, "Missing bw or node_id in bandwidth file line: %s", escaped(orig_line)); tor_free(line); return -1; } else { log_warn(LD_DIRSERV, "Incomplete line in bandwidth file: %s", escaped(orig_line)); tor_free(line); return -1; } }