Loading doc/tor.1.txt +4 −1 Original line number Diff line number Diff line Loading @@ -1458,7 +1458,10 @@ is non-zero): does on behalf of clients. (Default: 1) **GeoIPFile** __filename__:: A filename containing GeoIP data, for use with BridgeRecordUsageByCountry. A filename containing IPv4 GeoIP data, for use with BridgeRecordUsageByCountry. **GeoIPv6File** __filename__:: A filename containing IPv6 GeoIP data, for use with BridgeRecordUsageByCountry. **CellStatistics** **0**|**1**:: When this option is enabled, Tor writes statistics on the mean time that Loading src/config/geoip6 0 → 100644 +9752 −0 File added.Preview size limit exceeded, changes collapsed. Show changes src/or/config.c +23 −1 Original line number Diff line number Diff line Loading @@ -243,9 +243,12 @@ static config_var_t _option_vars[] = { V(FetchV2Networkstatus, BOOL, "0"), #ifdef _WIN32 V(GeoIPFile, FILENAME, "<default>"), V(GeoIPv6File, FILENAME, "<default>"), #else V(GeoIPFile, FILENAME, SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip"), V(GeoIPv6File, FILENAME, SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip6"), #endif OBSOLETE("GiveGuardFlagTo_CVE_2011_2768_VulnerableRelays"), OBSOLETE("Group"), Loading Loading @@ -1524,9 +1527,28 @@ options_act(const or_options_t *old_options) tor_asprintf(&actual_fname, "%s\\geoip", conf_root); } #endif geoip_load_file(actual_fname, options); geoip_load_file(AF_INET, actual_fname, options); tor_free(actual_fname); } /* And maybe load geoip ipv6 file */ if (options->GeoIPv6File && ((!old_options || !opt_streq(old_options->GeoIPv6File, options->GeoIPv6File)) || !geoip_is_loaded())) { /* XXXX Don't use this "<default>" junk; make our filename options * understand prefixes somehow. -NM */ /* XXXX023 Reload GeoIPFile on SIGHUP. -NM */ char *actual_fname = tor_strdup(options->GeoIPv6File); #ifdef _WIN32 if (!strcmp(actual_fname, "<default>")) { const char *conf_root = get_windows_conf_root(); tor_free(actual_fname); tor_asprintf(&actual_fname, "%s\\geoip6", conf_root); } #endif geoip_load_file(AF_INET6, actual_fname, options); tor_free(actual_fname); } if (options->CellStatistics || options->DirReqStatistics || options->EntryStatistics || options->ExitPortStatistics || Loading src/or/geoip.c +170 −15 Original line number Diff line number Diff line Loading @@ -28,6 +28,13 @@ typedef struct geoip_ipv4_entry_t { intptr_t country; /**< An index into geoip_countries */ } geoip_ipv4_entry_t; /** An entry from the GeoIP IPv6 file: maps an IPv6 range to a country. */ typedef struct geoip_ipv6_entry_t { struct in6_addr ip_low; /**< The lowest IP in the range, in host order */ struct in6_addr ip_high; /**< The highest IP in the range, in host order */ intptr_t country; /**< An index into geoip_countries */ } geoip_ipv6_entry_t; /** A per-country record for GeoIP request history. */ typedef struct geoip_country_t { char countrycode[3]; Loading @@ -42,7 +49,7 @@ static smartlist_t *geoip_countries = NULL; * not found. */ static strmap_t *country_idxplus1_by_lc_code = NULL; /** A list of all known geoip_ipv4_entry_t, sorted by ip_low. */ static smartlist_t *geoip_ipv4_entries = NULL; static smartlist_t *geoip_ipv4_entries = NULL, *geoip_ipv6_entries = NULL; /** SHA1 digest of the GeoIP file to include in extra-info descriptors. */ static char geoip_digest[DIGEST_LEN]; Loading Loading @@ -159,6 +166,116 @@ _geoip_ipv4_compare_key_to_entry(const void *_key, const void **_member) return 0; } /** Add an entry to the GeoIP IPv6 table, mapping all IPs between <b>low</b> and * <b>high</b>, inclusive, to the 2-letter country code <b>country</b>. */ static void geoip_ipv6_add_entry(struct in6_addr low, struct in6_addr high, const char *country) { intptr_t idx; geoip_ipv6_entry_t *ent; void *_idxplus1; if (memcmp(&high, &low, sizeof(struct in6_addr)) < 0) return; _idxplus1 = strmap_get_lc(country_idxplus1_by_lc_code, country); if (!_idxplus1) { geoip_country_t *c = tor_malloc_zero(sizeof(geoip_country_t)); strlcpy(c->countrycode, country, sizeof(c->countrycode)); tor_strlower(c->countrycode); smartlist_add(geoip_countries, c); idx = smartlist_len(geoip_countries) - 1; strmap_set_lc(country_idxplus1_by_lc_code, country, (void*)(idx+1)); } else { idx = ((uintptr_t)_idxplus1)-1; } { geoip_country_t *c = smartlist_get(geoip_countries, idx); tor_assert(!strcasecmp(c->countrycode, country)); } ent = tor_malloc_zero(sizeof(geoip_ipv6_entry_t)); ent->ip_low = low; ent->ip_high = high; ent->country = idx; smartlist_add(geoip_ipv6_entries, ent); } /** Add an entry to the GeoIP ipv6 table, parsing it from <b>line</b>. The * format is as for geoip_ipv6_load_file(). */ /*private*/ int geoip_ipv6_parse_entry(const char *line) { char buf[512]; char *low_str, *high_str, *country; struct in6_addr low, high; char *strtok_state; strlcpy(buf, line, sizeof(buf)); if (!geoip_countries) init_geoip_countries(); if (!geoip_ipv6_entries) geoip_ipv6_entries = smartlist_new(); while (TOR_ISSPACE(*line)) ++line; if (*line == '#') return 0; 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; if (tor_inet_pton(AF_INET6, high_str, &high) <= 0) goto fail; geoip_ipv6_add_entry(low, high, country); return 0; fail: log_warn(LD_GENERAL, "Unable to parse line from GEOIP IPV6 file: %s", escaped(line)); return -1; } /** Sorting helper: return -1, 1, or 0 based on comparison of two * geoip_ipv6_entry_t */ static int _geoip_ipv6_compare_entries(const void **_a, const void **_b) { const geoip_ipv6_entry_t *a = *_a, *b = *_b; return memcmp(&a->ip_low, &b->ip_low, sizeof(struct in6_addr)); } /** bsearch helper: return -1, 1, or 0 based on comparison of an IPv6 (a pointer * to a in6_addr in host order) to a geoip_ipv4_entry_t */ static int _geoip_ipv6_compare_key_to_entry(const void *_key, const void **_member) { /* No alignment issue here, since _key really is a pointer to uint32_t */ const struct in6_addr *addr = (struct in6_addr *)_key; const geoip_ipv6_entry_t *entry = *_member; if (memcmp(addr, &entry->ip_low, sizeof(struct in6_addr)) < 0) return -1; else if (memcmp(addr, &entry->ip_high, sizeof(struct in6_addr)) > 0) return 1; else return 0; } /** Return 1 if we should collect geoip stats on bridge users, and * include them in our extrainfo descriptor. Else return 0. */ int Loading Loading @@ -199,13 +316,15 @@ init_geoip_countries(void) * with '#' (comments). */ int geoip_load_file(const char *filename, const or_options_t *options) geoip_load_file(sa_family_t family, const char *filename, const or_options_t *options) { FILE *f; const char *msg = ""; int severity = options_need_geoip_info(options, &msg) ? LOG_WARN : LOG_INFO; crypto_digest_t *geoip_digest_env = NULL; clear_geoip_db(); tor_assert(family == AF_INET || family == AF_INET6); if (!(f = tor_fopen_cloexec(filename, "r"))) { log_fn(severity, LD_GENERAL, "Failed to open GEOIP file %s. %s", filename, msg); Loading @@ -213,25 +332,41 @@ geoip_load_file(const char *filename, const or_options_t *options) } if (!geoip_countries) init_geoip_countries(); if (family == AF_INET) { if (geoip_ipv4_entries) { SMARTLIST_FOREACH(geoip_ipv4_entries, geoip_ipv4_entry_t *, e, tor_free(e)); smartlist_free(geoip_ipv4_entries); } geoip_ipv4_entries = smartlist_new(); } else { /* AF_INET6 */ if (geoip_ipv6_entries) { SMARTLIST_FOREACH(geoip_ipv6_entries, geoip_ipv6_entry_t *, e, tor_free(e)); smartlist_free(geoip_ipv6_entries); } geoip_ipv6_entries = smartlist_new(); } geoip_digest_env = crypto_digest_new(); log_notice(LD_GENERAL, "Parsing GEOIP file %s.", filename); log_notice(LD_GENERAL, "Parsing GEOIP %s file %s.", (family == AF_INET) ? "ipv4" : "ipv6", filename); while (!feof(f)) { char buf[512]; if (fgets(buf, (int)sizeof(buf), f) == NULL) break; crypto_digest_add_bytes(geoip_digest_env, buf, strlen(buf)); /* FFFF track full country name. */ if (family == AF_INET) geoip_ipv4_parse_entry(buf); else /* AF_INET6 */ geoip_ipv6_parse_entry(buf); } /*XXXX abort and return -1 if no entries/illformed?*/ fclose(f); if (family == AF_INET) smartlist_sort(geoip_ipv4_entries, _geoip_ipv4_compare_entries); else /* AF_INET6 */ smartlist_sort(geoip_ipv6_entries, _geoip_ipv6_compare_entries); /* Okay, now we need to maybe change our mind about what is in which * country. */ Loading Loading @@ -261,6 +396,18 @@ geoip_get_country_by_ipv4(uint32_t ipaddr) return ent ? (int)ent->country : 0; } int geoip_get_country_by_ipv6(const struct in6_addr *addr) { geoip_ipv6_entry_t *ent; if (!geoip_ipv6_entries) return -1; ent = smartlist_bsearch(geoip_ipv6_entries, addr, _geoip_ipv6_compare_key_to_entry); return ent ? (int)ent->country : 0; } /** Given an IP address, return a number representing the country to which * that address belongs, -1 for "No geoip information available", or 0 for * the 'unknown country'. The return value will always be less than Loading @@ -269,11 +416,13 @@ geoip_get_country_by_ipv4(uint32_t ipaddr) int geoip_get_country_by_addr(const tor_addr_t *addr) { if (tor_addr_family(addr) != AF_INET) { /*XXXX IP6 support ipv6 geoip.*/ if (tor_addr_family(addr) == AF_INET) { return geoip_get_country_by_ipv4(tor_addr_to_ipv4h(addr)); } else if (tor_addr_family(addr) == AF_INET6) { return geoip_get_country_by_ipv6(tor_addr_to_in6(addr)); } else { return -1; } return geoip_get_country_by_ipv4(tor_addr_to_ipv4h(addr)); } /** Return the number of countries recognized by the GeoIP database. */ Loading Loading @@ -301,7 +450,7 @@ geoip_get_country_name(country_t num) int geoip_is_loaded(void) { return geoip_countries != NULL && geoip_ipv4_entries != NULL; return geoip_countries != NULL && (geoip_ipv4_entries != NULL || geoip_ipv6_entries != NULL); } /** Return the hex-encoded SHA1 digest of the loaded GeoIP file. The Loading Loading @@ -818,7 +967,8 @@ geoip_get_dirreq_history(geoip_client_action_t action, * bridge, directory server, or entry guard. The entry format is cc=num * where num is the number of IPs we've seen connecting from that country, * and cc is a lowercased country code. Returns NULL if we don't want * to export geoip data yet. */ * to export geoip data yet. This counts both IPv4 and IPv6 clients * since they're in the same clientmap list. */ char * geoip_get_client_history(geoip_client_action_t action) { Loading Loading @@ -1469,9 +1619,14 @@ clear_geoip_db(void) SMARTLIST_FOREACH(geoip_ipv4_entries, geoip_ipv4_entry_t *, ent, tor_free(ent)); smartlist_free(geoip_ipv4_entries); } if (geoip_ipv6_entries) { SMARTLIST_FOREACH(geoip_ipv6_entries, geoip_ipv6_entry_t *, ent, tor_free(ent)); smartlist_free(geoip_ipv6_entries); } geoip_countries = NULL; country_idxplus1_by_lc_code = NULL; geoip_ipv4_entries = NULL; geoip_ipv6_entries = NULL; } /** Release all storage held in this file. */ Loading src/or/geoip.h +4 −2 Original line number Diff line number Diff line Loading @@ -14,10 +14,12 @@ #ifdef GEOIP_PRIVATE int geoip_ipv4_parse_entry(const char *line); int geoip_ipv6_parse_entry(const char *line); int geoip_get_country_by_ipv4(uint32_t ipaddr); int geoip_get_country_by_ipv6(const struct in6_addr *addr); #endif int should_record_bridge_info(const or_options_t *options); int geoip_load_file(const char *filename, const or_options_t *options); int geoip_get_country_by_ipv4(uint32_t ipaddr); int geoip_load_file(sa_family_t family, const char *filename, const or_options_t *options); int geoip_get_country_by_addr(const tor_addr_t *addr); int geoip_get_n_countries(void); const char *geoip_get_country_name(country_t num); Loading Loading
doc/tor.1.txt +4 −1 Original line number Diff line number Diff line Loading @@ -1458,7 +1458,10 @@ is non-zero): does on behalf of clients. (Default: 1) **GeoIPFile** __filename__:: A filename containing GeoIP data, for use with BridgeRecordUsageByCountry. A filename containing IPv4 GeoIP data, for use with BridgeRecordUsageByCountry. **GeoIPv6File** __filename__:: A filename containing IPv6 GeoIP data, for use with BridgeRecordUsageByCountry. **CellStatistics** **0**|**1**:: When this option is enabled, Tor writes statistics on the mean time that Loading
src/config/geoip6 0 → 100644 +9752 −0 File added.Preview size limit exceeded, changes collapsed. Show changes
src/or/config.c +23 −1 Original line number Diff line number Diff line Loading @@ -243,9 +243,12 @@ static config_var_t _option_vars[] = { V(FetchV2Networkstatus, BOOL, "0"), #ifdef _WIN32 V(GeoIPFile, FILENAME, "<default>"), V(GeoIPv6File, FILENAME, "<default>"), #else V(GeoIPFile, FILENAME, SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip"), V(GeoIPv6File, FILENAME, SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip6"), #endif OBSOLETE("GiveGuardFlagTo_CVE_2011_2768_VulnerableRelays"), OBSOLETE("Group"), Loading Loading @@ -1524,9 +1527,28 @@ options_act(const or_options_t *old_options) tor_asprintf(&actual_fname, "%s\\geoip", conf_root); } #endif geoip_load_file(actual_fname, options); geoip_load_file(AF_INET, actual_fname, options); tor_free(actual_fname); } /* And maybe load geoip ipv6 file */ if (options->GeoIPv6File && ((!old_options || !opt_streq(old_options->GeoIPv6File, options->GeoIPv6File)) || !geoip_is_loaded())) { /* XXXX Don't use this "<default>" junk; make our filename options * understand prefixes somehow. -NM */ /* XXXX023 Reload GeoIPFile on SIGHUP. -NM */ char *actual_fname = tor_strdup(options->GeoIPv6File); #ifdef _WIN32 if (!strcmp(actual_fname, "<default>")) { const char *conf_root = get_windows_conf_root(); tor_free(actual_fname); tor_asprintf(&actual_fname, "%s\\geoip6", conf_root); } #endif geoip_load_file(AF_INET6, actual_fname, options); tor_free(actual_fname); } if (options->CellStatistics || options->DirReqStatistics || options->EntryStatistics || options->ExitPortStatistics || Loading
src/or/geoip.c +170 −15 Original line number Diff line number Diff line Loading @@ -28,6 +28,13 @@ typedef struct geoip_ipv4_entry_t { intptr_t country; /**< An index into geoip_countries */ } geoip_ipv4_entry_t; /** An entry from the GeoIP IPv6 file: maps an IPv6 range to a country. */ typedef struct geoip_ipv6_entry_t { struct in6_addr ip_low; /**< The lowest IP in the range, in host order */ struct in6_addr ip_high; /**< The highest IP in the range, in host order */ intptr_t country; /**< An index into geoip_countries */ } geoip_ipv6_entry_t; /** A per-country record for GeoIP request history. */ typedef struct geoip_country_t { char countrycode[3]; Loading @@ -42,7 +49,7 @@ static smartlist_t *geoip_countries = NULL; * not found. */ static strmap_t *country_idxplus1_by_lc_code = NULL; /** A list of all known geoip_ipv4_entry_t, sorted by ip_low. */ static smartlist_t *geoip_ipv4_entries = NULL; static smartlist_t *geoip_ipv4_entries = NULL, *geoip_ipv6_entries = NULL; /** SHA1 digest of the GeoIP file to include in extra-info descriptors. */ static char geoip_digest[DIGEST_LEN]; Loading Loading @@ -159,6 +166,116 @@ _geoip_ipv4_compare_key_to_entry(const void *_key, const void **_member) return 0; } /** Add an entry to the GeoIP IPv6 table, mapping all IPs between <b>low</b> and * <b>high</b>, inclusive, to the 2-letter country code <b>country</b>. */ static void geoip_ipv6_add_entry(struct in6_addr low, struct in6_addr high, const char *country) { intptr_t idx; geoip_ipv6_entry_t *ent; void *_idxplus1; if (memcmp(&high, &low, sizeof(struct in6_addr)) < 0) return; _idxplus1 = strmap_get_lc(country_idxplus1_by_lc_code, country); if (!_idxplus1) { geoip_country_t *c = tor_malloc_zero(sizeof(geoip_country_t)); strlcpy(c->countrycode, country, sizeof(c->countrycode)); tor_strlower(c->countrycode); smartlist_add(geoip_countries, c); idx = smartlist_len(geoip_countries) - 1; strmap_set_lc(country_idxplus1_by_lc_code, country, (void*)(idx+1)); } else { idx = ((uintptr_t)_idxplus1)-1; } { geoip_country_t *c = smartlist_get(geoip_countries, idx); tor_assert(!strcasecmp(c->countrycode, country)); } ent = tor_malloc_zero(sizeof(geoip_ipv6_entry_t)); ent->ip_low = low; ent->ip_high = high; ent->country = idx; smartlist_add(geoip_ipv6_entries, ent); } /** Add an entry to the GeoIP ipv6 table, parsing it from <b>line</b>. The * format is as for geoip_ipv6_load_file(). */ /*private*/ int geoip_ipv6_parse_entry(const char *line) { char buf[512]; char *low_str, *high_str, *country; struct in6_addr low, high; char *strtok_state; strlcpy(buf, line, sizeof(buf)); if (!geoip_countries) init_geoip_countries(); if (!geoip_ipv6_entries) geoip_ipv6_entries = smartlist_new(); while (TOR_ISSPACE(*line)) ++line; if (*line == '#') return 0; 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; if (tor_inet_pton(AF_INET6, high_str, &high) <= 0) goto fail; geoip_ipv6_add_entry(low, high, country); return 0; fail: log_warn(LD_GENERAL, "Unable to parse line from GEOIP IPV6 file: %s", escaped(line)); return -1; } /** Sorting helper: return -1, 1, or 0 based on comparison of two * geoip_ipv6_entry_t */ static int _geoip_ipv6_compare_entries(const void **_a, const void **_b) { const geoip_ipv6_entry_t *a = *_a, *b = *_b; return memcmp(&a->ip_low, &b->ip_low, sizeof(struct in6_addr)); } /** bsearch helper: return -1, 1, or 0 based on comparison of an IPv6 (a pointer * to a in6_addr in host order) to a geoip_ipv4_entry_t */ static int _geoip_ipv6_compare_key_to_entry(const void *_key, const void **_member) { /* No alignment issue here, since _key really is a pointer to uint32_t */ const struct in6_addr *addr = (struct in6_addr *)_key; const geoip_ipv6_entry_t *entry = *_member; if (memcmp(addr, &entry->ip_low, sizeof(struct in6_addr)) < 0) return -1; else if (memcmp(addr, &entry->ip_high, sizeof(struct in6_addr)) > 0) return 1; else return 0; } /** Return 1 if we should collect geoip stats on bridge users, and * include them in our extrainfo descriptor. Else return 0. */ int Loading Loading @@ -199,13 +316,15 @@ init_geoip_countries(void) * with '#' (comments). */ int geoip_load_file(const char *filename, const or_options_t *options) geoip_load_file(sa_family_t family, const char *filename, const or_options_t *options) { FILE *f; const char *msg = ""; int severity = options_need_geoip_info(options, &msg) ? LOG_WARN : LOG_INFO; crypto_digest_t *geoip_digest_env = NULL; clear_geoip_db(); tor_assert(family == AF_INET || family == AF_INET6); if (!(f = tor_fopen_cloexec(filename, "r"))) { log_fn(severity, LD_GENERAL, "Failed to open GEOIP file %s. %s", filename, msg); Loading @@ -213,25 +332,41 @@ geoip_load_file(const char *filename, const or_options_t *options) } if (!geoip_countries) init_geoip_countries(); if (family == AF_INET) { if (geoip_ipv4_entries) { SMARTLIST_FOREACH(geoip_ipv4_entries, geoip_ipv4_entry_t *, e, tor_free(e)); smartlist_free(geoip_ipv4_entries); } geoip_ipv4_entries = smartlist_new(); } else { /* AF_INET6 */ if (geoip_ipv6_entries) { SMARTLIST_FOREACH(geoip_ipv6_entries, geoip_ipv6_entry_t *, e, tor_free(e)); smartlist_free(geoip_ipv6_entries); } geoip_ipv6_entries = smartlist_new(); } geoip_digest_env = crypto_digest_new(); log_notice(LD_GENERAL, "Parsing GEOIP file %s.", filename); log_notice(LD_GENERAL, "Parsing GEOIP %s file %s.", (family == AF_INET) ? "ipv4" : "ipv6", filename); while (!feof(f)) { char buf[512]; if (fgets(buf, (int)sizeof(buf), f) == NULL) break; crypto_digest_add_bytes(geoip_digest_env, buf, strlen(buf)); /* FFFF track full country name. */ if (family == AF_INET) geoip_ipv4_parse_entry(buf); else /* AF_INET6 */ geoip_ipv6_parse_entry(buf); } /*XXXX abort and return -1 if no entries/illformed?*/ fclose(f); if (family == AF_INET) smartlist_sort(geoip_ipv4_entries, _geoip_ipv4_compare_entries); else /* AF_INET6 */ smartlist_sort(geoip_ipv6_entries, _geoip_ipv6_compare_entries); /* Okay, now we need to maybe change our mind about what is in which * country. */ Loading Loading @@ -261,6 +396,18 @@ geoip_get_country_by_ipv4(uint32_t ipaddr) return ent ? (int)ent->country : 0; } int geoip_get_country_by_ipv6(const struct in6_addr *addr) { geoip_ipv6_entry_t *ent; if (!geoip_ipv6_entries) return -1; ent = smartlist_bsearch(geoip_ipv6_entries, addr, _geoip_ipv6_compare_key_to_entry); return ent ? (int)ent->country : 0; } /** Given an IP address, return a number representing the country to which * that address belongs, -1 for "No geoip information available", or 0 for * the 'unknown country'. The return value will always be less than Loading @@ -269,11 +416,13 @@ geoip_get_country_by_ipv4(uint32_t ipaddr) int geoip_get_country_by_addr(const tor_addr_t *addr) { if (tor_addr_family(addr) != AF_INET) { /*XXXX IP6 support ipv6 geoip.*/ if (tor_addr_family(addr) == AF_INET) { return geoip_get_country_by_ipv4(tor_addr_to_ipv4h(addr)); } else if (tor_addr_family(addr) == AF_INET6) { return geoip_get_country_by_ipv6(tor_addr_to_in6(addr)); } else { return -1; } return geoip_get_country_by_ipv4(tor_addr_to_ipv4h(addr)); } /** Return the number of countries recognized by the GeoIP database. */ Loading Loading @@ -301,7 +450,7 @@ geoip_get_country_name(country_t num) int geoip_is_loaded(void) { return geoip_countries != NULL && geoip_ipv4_entries != NULL; return geoip_countries != NULL && (geoip_ipv4_entries != NULL || geoip_ipv6_entries != NULL); } /** Return the hex-encoded SHA1 digest of the loaded GeoIP file. The Loading Loading @@ -818,7 +967,8 @@ geoip_get_dirreq_history(geoip_client_action_t action, * bridge, directory server, or entry guard. The entry format is cc=num * where num is the number of IPs we've seen connecting from that country, * and cc is a lowercased country code. Returns NULL if we don't want * to export geoip data yet. */ * to export geoip data yet. This counts both IPv4 and IPv6 clients * since they're in the same clientmap list. */ char * geoip_get_client_history(geoip_client_action_t action) { Loading Loading @@ -1469,9 +1619,14 @@ clear_geoip_db(void) SMARTLIST_FOREACH(geoip_ipv4_entries, geoip_ipv4_entry_t *, ent, tor_free(ent)); smartlist_free(geoip_ipv4_entries); } if (geoip_ipv6_entries) { SMARTLIST_FOREACH(geoip_ipv6_entries, geoip_ipv6_entry_t *, ent, tor_free(ent)); smartlist_free(geoip_ipv6_entries); } geoip_countries = NULL; country_idxplus1_by_lc_code = NULL; geoip_ipv4_entries = NULL; geoip_ipv6_entries = NULL; } /** Release all storage held in this file. */ Loading
src/or/geoip.h +4 −2 Original line number Diff line number Diff line Loading @@ -14,10 +14,12 @@ #ifdef GEOIP_PRIVATE int geoip_ipv4_parse_entry(const char *line); int geoip_ipv6_parse_entry(const char *line); int geoip_get_country_by_ipv4(uint32_t ipaddr); int geoip_get_country_by_ipv6(const struct in6_addr *addr); #endif int should_record_bridge_info(const or_options_t *options); int geoip_load_file(const char *filename, const or_options_t *options); int geoip_get_country_by_ipv4(uint32_t ipaddr); int geoip_load_file(sa_family_t family, const char *filename, const or_options_t *options); int geoip_get_country_by_addr(const tor_addr_t *addr); int geoip_get_n_countries(void); const char *geoip_get_country_name(country_t num); Loading