From abb886014e1ee35909e8876fe3361cbfd26cc27c Mon Sep 17 00:00:00 2001 From: nils Date: Wed, 29 Feb 2012 17:04:45 -0800 Subject: Add GeoIP database for IPv6 addresses --- src/or/config.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'src/or/config.c') diff --git a/src/or/config.c b/src/or/config.c index cfb76dcdab..fd6224e2c5 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -243,9 +243,12 @@ static config_var_t _option_vars[] = { V(FetchV2Networkstatus, BOOL, "0"), #ifdef _WIN32 V(GeoIPFile, FILENAME, ""), + V(GeoIPv6File, FILENAME, ""), #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"), @@ -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 "" 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, "")) { + 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 || -- cgit v1.2.3-54-g00ecf From c03e3d66a910d103d3cce50a3bc1b778f68c36f2 Mon Sep 17 00:00:00 2001 From: Karsten Loesing Date: Wed, 28 Mar 2012 15:52:33 +0200 Subject: Minor tweaks and comments to nils' geoip v6 code. --- doc/tor.1.txt | 4 ++-- src/config/geoip6 | 2 +- src/or/config.c | 5 +++-- src/or/geoip.c | 26 +++++++++++++++++++++++--- src/test/test.c | 4 +++- 5 files changed, 32 insertions(+), 9 deletions(-) (limited to 'src/or/config.c') diff --git a/doc/tor.1.txt b/doc/tor.1.txt index cd1fb90a31..6c02f45ee3 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -1458,10 +1458,10 @@ is non-zero): does on behalf of clients. (Default: 1) **GeoIPFile** __filename__:: - A filename containing IPv4 GeoIP data, for use with BridgeRecordUsageByCountry. + A filename containing IPv4 GeoIP data, for use with by-country statistics. **GeoIPv6File** __filename__:: - A filename containing IPv6 GeoIP data, for use with BridgeRecordUsageByCountry. + A filename containing IPv6 GeoIP data, for use with by-country statistics. **CellStatistics** **0**|**1**:: When this option is enabled, Tor writes statistics on the mean time that diff --git a/src/config/geoip6 b/src/config/geoip6 index fb9cce535f..a60868be78 100644 --- a/src/config/geoip6 +++ b/src/config/geoip6 @@ -1,6 +1,6 @@ # Last updated based on February 22 2012 Maxmind GeoLite IPv6 Country # wget http://geolite.maxmind.com/download/geoip/database/GeoIPv6.csv.gz -# cut -d, -f1,2,6 < GeoIPv6.csv|sed 's/[ "]//g' > geoip6 +# cut -d, -f1,2,5 < GeoIPv6.csv|sed 's/[ "]//g' > geoip6 2001:200::,2001:200:ffff:ffff:ffff:ffff:ffff:ffff,JP 2001:208::,2001:208:ffff:ffff:ffff:ffff:ffff:ffff,SG 2001:218::,2001:218:ffff:ffff:ffff:ffff:ffff:ffff,JP diff --git a/src/or/config.c b/src/or/config.c index fd6224e2c5..d5df5e73fb 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1535,8 +1535,9 @@ options_act(const or_options_t *old_options) ((!old_options || !opt_streq(old_options->GeoIPv6File, options->GeoIPv6File)) || !geoip_is_loaded())) { /* XXXX Don't use this "" junk; make our filename options - * understand prefixes somehow. -NM */ - /* XXXX023 Reload GeoIPFile on SIGHUP. -NM */ + * understand prefixes somehow. See also comment for GeoIPFile. */ + /* XXXX024 Reload GeoIPV6File on SIGHUP. See also comment for + * GeoIPFile. */ char *actual_fname = tor_strdup(options->GeoIPv6File); #ifdef _WIN32 if (!strcmp(actual_fname, "")) { diff --git a/src/or/geoip.c b/src/or/geoip.c index 4c28eebe59..e19b62ad50 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -48,7 +48,8 @@ static smartlist_t *geoip_countries = NULL; * The index is encoded in the pointer, and 1 is added so that NULL can mean * not found. */ static strmap_t *country_idxplus1_by_lc_code = NULL; -/** A list of all known geoip_ipv4_entry_t, sorted by ip_low. */ +/** Lists of all known geoip_ipv4_entry_t and geoip_ipv6_entry_t, sorted + * by their respective ip_low. */ static smartlist_t *geoip_ipv4_entries = NULL, *geoip_ipv6_entries = NULL; /** SHA1 digest of the GeoIP file to include in extra-info descriptors. */ @@ -203,7 +204,11 @@ geoip_ipv6_add_entry(struct in6_addr low, struct in6_addr high, const char *coun } /** Add an entry to the GeoIP ipv6 table, parsing it from line. The - * format is as for geoip_ipv6_load_file(). */ + * format is as for geoip_load_file(). */ +/* XXX5053 Should this code also support parsing Maxmind's GeoIPv6.csv + * format directly, similar to how their v4 format is also accepted? That + * would enable people to use their commercial IPv6 databases instead of + * our free one, if they wanted. -KL */ /*private*/ int geoip_ipv6_parse_entry(const char *line) { @@ -260,10 +265,13 @@ _geoip_ipv6_compare_entries(const void **_a, const void **_b) } /** 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 */ + * to a in6_addr in host order) to a geoip_ipv6_entry_t */ static int _geoip_ipv6_compare_key_to_entry(const void *_key, const void **_member) { + /* XXX5053 The following comment isn't correct anymore and I'm not 100% + * certain how to fix it, because I don't know what alignment issues + * there could be. -KL */ /* 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; @@ -374,6 +382,10 @@ geoip_load_file(sa_family_t family, const char *filename, const or_options_t *op /* Remember file digest so that we can include it in our extra-info * descriptors. */ + /* XXX5053 This is a bug! We overwrite geoip_digest with whichever file + * we parse last. We'll want to add a separate geoip6_digest and write + * a geoip6-db-digest line to our extra-info descriptor. Needs a + * dir-spec.txt patch, too. -KL */ crypto_digest_get_digest(geoip_digest_env, geoip_digest, DIGEST_LEN); crypto_digest_free(geoip_digest_env); @@ -396,6 +408,11 @@ geoip_get_country_by_ipv4(uint32_t ipaddr) return ent ? (int)ent->country : 0; } +/** Given an IPv6 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 + * geoip_get_n_countries(). To decode it, call geoip_get_country_name(). + */ int geoip_get_country_by_ipv6(const struct in6_addr *addr) { @@ -450,6 +467,9 @@ geoip_get_country_name(country_t num) int geoip_is_loaded(void) { + /* XXX5053 Saying that we have loaded a GeoIP database if have _either_ + * a v4 or v6 database might be problematic. Maybe we need to add an + * address parameter to this function? -KL */ return geoip_countries != NULL && (geoip_ipv4_entries != NULL || geoip_ipv6_entries != NULL); } diff --git a/src/test/test.c b/src/test/test.c index df0eddac75..a1806fc38c 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -1483,6 +1483,8 @@ test_geoip(void) test_eq(0, geoip_ipv6_parse_entry("::a,::32,AB")); test_eq(0, geoip_ipv6_parse_entry("::34,::5a,XY")); test_eq(0, geoip_ipv6_parse_entry("::5f,::64,AB")); + /* XXX5053 If we plan to support parsing Maxmind's GeoIPv6.csv format, + * we should test it here. If not, remove this comment. -KL */ test_eq(0, geoip_ipv6_parse_entry("::69,::8c,ZZ")); test_eq(0, geoip_ipv6_parse_entry("::96,::be,XY")); test_eq(0, geoip_ipv6_parse_entry("::c8,::fa,AB")); @@ -1535,7 +1537,7 @@ test_geoip(void) SET_TEST_ADDRESS(i); geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, now-7200); } - SET_TEST_ADDRESS(i); + SET_TEST_ADDRESS(225); geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, now-7200); /* and 3 observations in XY, several times. */ for (j=0; j < 10; ++j) -- cgit v1.2.3-54-g00ecf From e2313d8622aebc2704ce016dfef2be975fa535c3 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Wed, 17 Oct 2012 14:01:02 +0200 Subject: White space. --- src/or/config.c | 4 ++-- src/or/geoip.c | 58 ++++++++++++++++++++++++++++++++++----------------------- src/or/geoip.h | 6 ++++-- src/test/test.c | 30 +++++++++++++++-------------- 4 files changed, 57 insertions(+), 41 deletions(-) (limited to 'src/or/config.c') diff --git a/src/or/config.c b/src/or/config.c index d5df5e73fb..3b95909ed2 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1532,7 +1532,8 @@ options_act(const or_options_t *old_options) } /* And maybe load geoip ipv6 file */ if (options->GeoIPv6File && - ((!old_options || !opt_streq(old_options->GeoIPv6File, options->GeoIPv6File)) + ((!old_options || !opt_streq(old_options->GeoIPv6File, + options->GeoIPv6File)) || !geoip_is_loaded())) { /* XXXX Don't use this "" junk; make our filename options * understand prefixes somehow. See also comment for GeoIPFile. */ @@ -1549,7 +1550,6 @@ options_act(const or_options_t *old_options) geoip_load_file(AF_INET6, actual_fname, options); tor_free(actual_fname); } - if (options->CellStatistics || options->DirReqStatistics || options->EntryStatistics || options->ExitPortStatistics || diff --git a/src/or/geoip.c b/src/or/geoip.c index c037d327b4..7507918a6f 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -167,11 +167,12 @@ 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 low and - * high, inclusive, to the 2-letter country code country. - */ +/** Add an entry to the GeoIP IPv6 table, mapping all IPs between + * low and high, inclusive, to the 2-letter country code + * country. */ static void -geoip_ipv6_add_entry(struct in6_addr low, struct in6_addr high, const char *country) +geoip_ipv6_add_entry(struct in6_addr low, struct in6_addr high, + const char *country) { intptr_t idx; geoip_ipv6_entry_t *ent; @@ -264,8 +265,8 @@ geoip_ipv6_compare_entries_(const void **_a, const void **_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_ipv6_entry_t */ +/** 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_ipv6_entry_t */ static int geoip_ipv6_compare_key_to_entry_(const void *_key, const void **_member) { @@ -324,7 +325,8 @@ init_geoip_countries(void) * with '#' (comments). */ int -geoip_load_file(sa_family_t family, 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 = ""; @@ -343,20 +345,23 @@ geoip_load_file(sa_family_t family, const char *filename, const or_options_t *op if (family == AF_INET) { if (geoip_ipv4_entries) { - SMARTLIST_FOREACH(geoip_ipv4_entries, geoip_ipv4_entry_t *, e, tor_free(e)); + 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_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 %s file %s.", (family == AF_INET) ? "ipv4" : "ipv6", 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) @@ -404,7 +409,8 @@ geoip_get_country_by_ipv4(uint32_t ipaddr) geoip_ipv4_entry_t *ent; if (!geoip_ipv4_entries) return -1; - ent = smartlist_bsearch(geoip_ipv4_entries, &ipaddr, geoip_ipv4_compare_key_to_entry_); + ent = smartlist_bsearch(geoip_ipv4_entries, &ipaddr, + geoip_ipv4_compare_key_to_entry_); return ent ? (int)ent->country : 0; } @@ -420,11 +426,11 @@ geoip_get_country_by_ipv6(const struct in6_addr *addr) if (!geoip_ipv6_entries) return -1; - ent = smartlist_bsearch(geoip_ipv6_entries, addr, geoip_ipv6_compare_key_to_entry_); + 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 @@ -470,7 +476,8 @@ geoip_is_loaded(void) /* XXX5053 Saying that we have loaded a GeoIP database if have _either_ * a v4 or v6 database might be problematic. Maybe we need to add an * address parameter to this function? -KL */ - return geoip_countries != NULL && (geoip_ipv4_entries != NULL || geoip_ipv6_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 @@ -990,7 +997,8 @@ geoip_get_dirreq_history(geoip_client_action_t action, * 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, int *total_ipv4, int *total_ipv6) +geoip_get_client_history(geoip_client_action_t action, int *total_ipv4, + int *total_ipv6) { char *result = NULL; unsigned granularity = IP_GRANULARITY; @@ -1412,16 +1420,17 @@ geoip_format_bridge_stats(time_t now) return NULL; /* Not initialized. */ format_iso_time(written, now); - data = geoip_get_client_history(GEOIP_CLIENT_CONNECT, &total_ipv4, &total_ipv6); + data = geoip_get_client_history(GEOIP_CLIENT_CONNECT, &total_ipv4, + &total_ipv6); tor_asprintf(&out, "bridge-stats-end %s (%ld s)\n" "bridge-ips %s\n" - "bridge-ip-versions v4=%d,v6=%d\n", + "bridge-ip-versions v4=%d,v6=%d\n", written, duration, data ? data : "", - total_ipv4, - total_ipv6); + total_ipv4, + total_ipv6); tor_free(data); return out; @@ -1571,7 +1580,8 @@ geoip_format_entry_stats(time_t now) tor_assert(now >= start_of_entry_stats_interval); - data = geoip_get_client_history(GEOIP_CLIENT_CONNECT, &total_ipv4, &total_ipv6); + data = geoip_get_client_history(GEOIP_CLIENT_CONNECT, &total_ipv4, + &total_ipv6); format_iso_time(t, now); tor_asprintf(&result, "entry-stats-end %s (%u s)\n" @@ -1658,11 +1668,13 @@ clear_geoip_db(void) strmap_free(country_idxplus1_by_lc_code, NULL); if (geoip_ipv4_entries) { - SMARTLIST_FOREACH(geoip_ipv4_entries, geoip_ipv4_entry_t *, ent, tor_free(ent)); + 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_FOREACH(geoip_ipv6_entries, geoip_ipv6_entry_t *, ent, + tor_free(ent)); smartlist_free(geoip_ipv6_entries); } geoip_countries = NULL; diff --git a/src/or/geoip.h b/src/or/geoip.h index 4cde32ea22..38f1289867 100644 --- a/src/or/geoip.h +++ b/src/or/geoip.h @@ -19,7 +19,8 @@ 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(sa_family_t family, const char *filename, const or_options_t *options); +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); @@ -33,7 +34,8 @@ void geoip_remove_old_clients(time_t cutoff); void geoip_note_ns_response(geoip_client_action_t action, geoip_ns_response_t response); -char *geoip_get_client_history(geoip_client_action_t action, int *total_ipv4, int *total_ipv6); +char *geoip_get_client_history(geoip_client_action_t action, int *total_ipv4, + int *total_ipv6); char *geoip_get_request_history(geoip_client_action_t action); int getinfo_helper_geoip(control_connection_t *control_conn, const char *question, char **answer, diff --git a/src/test/test.c b/src/test/test.c index f34a22cad8..0c5e84ddbc 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -1485,13 +1485,15 @@ test_geoip(void) /* Make sure that country ID actually works. */ #define SET_TEST_IPV6(i) in6.s6_addr32[3] = htonl((uint32_t) i) -#define CHECK_COUNTRY(country, val) do { \ - /* test ipv4 country lookup */ \ - test_streq(country, geoip_get_country_name(geoip_get_country_by_ipv4(val))); \ - /* test ipv6 country lookup */ \ - SET_TEST_IPV6(val); \ - test_streq(country, geoip_get_country_name(geoip_get_country_by_ipv6(&in6))); \ - } while(0) +#define CHECK_COUNTRY(country, val) do { \ + /* test ipv4 country lookup */ \ + test_streq(country, \ + geoip_get_country_name(geoip_get_country_by_ipv4(val))); \ + /* test ipv6 country lookup */ \ + SET_TEST_IPV6(val); \ + test_streq(country, \ + geoip_get_country_name(geoip_get_country_by_ipv6(&in6))); \ + } while (0) CHECK_COUNTRY("??", 3); CHECK_COUNTRY("ab", 32); @@ -1511,14 +1513,14 @@ test_geoip(void) * using ipv4. Since our fake geoip database is the same between * ipv4 and ipv6, we should get the same result no matter which * address family we pick for each IP. */ -#define SET_TEST_ADDRESS(i) do { \ - if ((i) & 1) { \ - SET_TEST_IPV6(i); \ - tor_addr_from_in6(&addr, &in6); \ - } else { \ +#define SET_TEST_ADDRESS(i) do { \ + if ((i) & 1) { \ + SET_TEST_IPV6(i); \ + tor_addr_from_in6(&addr, &in6); \ + } else { \ tor_addr_from_ipv4h(&addr, (uint32_t) i); \ - } \ - } while(0) + } \ + } while (0) get_options_mutable()->BridgeRelay = 1; get_options_mutable()->BridgeRecordUsageByCountry = 1; -- cgit v1.2.3-54-g00ecf From 817ff962f830188ec4c1a907ebc389a856ea3288 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Sat, 20 Oct 2012 18:48:58 +0200 Subject: Separate IPv4 and IPv6 geoip file loading. Also add IPv6 geoip file digest to extra info. Also also, add support for IPv6 addresses in control command "ip-to-country". --- src/or/config.c | 12 ++++----- src/or/geoip.c | 78 ++++++++++++++++++++++++++++++------------------------ src/or/geoip.h | 4 +-- src/or/router.c | 9 ++++--- src/or/routerset.c | 2 +- 5 files changed, 59 insertions(+), 46 deletions(-) (limited to 'src/or/config.c') diff --git a/src/or/config.c b/src/or/config.c index 3b95909ed2..5b1f1eed6f 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1512,10 +1512,10 @@ options_act(const or_options_t *old_options) connection_or_update_token_buckets(get_connection_array(), options); } - /* Maybe load geoip file */ + /* Maybe load IPv4 geoip file */ if (options->GeoIPFile && ((!old_options || !opt_streq(old_options->GeoIPFile, options->GeoIPFile)) - || !geoip_is_loaded())) { + || !geoip_is_loaded(AF_INET))) { /* XXXX Don't use this "" junk; make our filename options * understand prefixes somehow. -NM */ /* XXXX024 Reload GeoIPFile on SIGHUP. -NM */ @@ -1530,11 +1530,11 @@ options_act(const or_options_t *old_options) geoip_load_file(AF_INET, actual_fname, options); tor_free(actual_fname); } - /* And maybe load geoip ipv6 file */ + /* And maybe load IPv6 geoip file */ if (options->GeoIPv6File && ((!old_options || !opt_streq(old_options->GeoIPv6File, options->GeoIPv6File)) - || !geoip_is_loaded())) { + || !geoip_is_loaded(AF_INET6))) { /* XXXX Don't use this "" junk; make our filename options * understand prefixes somehow. See also comment for GeoIPFile. */ /* XXXX024 Reload GeoIPV6File on SIGHUP. See also comment for @@ -1573,7 +1573,7 @@ options_act(const or_options_t *old_options) } if ((!old_options || !old_options->DirReqStatistics) && options->DirReqStatistics) { - if (geoip_is_loaded()) { + if (geoip_is_loaded(AF_INET)) { geoip_dirreq_stats_init(now); print_notice = 1; } else { @@ -1588,7 +1588,7 @@ options_act(const or_options_t *old_options) } if ((!old_options || !old_options->EntryStatistics) && options->EntryStatistics && !should_record_bridge_info(options)) { - if (geoip_is_loaded()) { + if (geoip_is_loaded(AF_INET) || geoip_is_loaded(AF_INET6)) { geoip_entry_stats_init(now); print_notice = 1; } else { diff --git a/src/or/geoip.c b/src/or/geoip.c index 7507918a6f..e1c0009cc3 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -52,8 +52,9 @@ static strmap_t *country_idxplus1_by_lc_code = NULL; * by their respective ip_low. */ static smartlist_t *geoip_ipv4_entries = NULL, *geoip_ipv6_entries = NULL; -/** SHA1 digest of the GeoIP file to include in extra-info descriptors. */ +/** SHA1 digest of the GeoIP files to include in extra-info descriptors. */ static char geoip_digest[DIGEST_LEN]; +static char geoip6_digest[DIGEST_LEN]; /** Return the index of the country's entry in the GeoIP DB * if it is a valid 2-letter country code, otherwise return -1. @@ -376,22 +377,20 @@ geoip_load_file(sa_family_t family, const char *filename, /*XXXX abort and return -1 if no entries/illformed?*/ fclose(f); - if (family == AF_INET) + /* Sort list and remember file digests so that we can include it in + * our extra-info descriptors. */ + if (family == AF_INET) { smartlist_sort(geoip_ipv4_entries, geoip_ipv4_compare_entries_); - else /* AF_INET6 */ + /* Okay, now we need to maybe change our mind about what is in + * which country. We do this for IPv4 only since that's what we + * store in node->country. */ + refresh_all_country_info(); + crypto_digest_get_digest(geoip_digest_env, geoip_digest, DIGEST_LEN); + } + 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. */ - refresh_all_country_info(); - - /* Remember file digest so that we can include it in our extra-info - * descriptors. */ - /* XXX5053 This is a bug! We overwrite geoip_digest with whichever file - * we parse last. We'll want to add a separate geoip6_digest and write - * a geoip6-db-digest line to our extra-info descriptor. Needs a - * dir-spec.txt patch, too. -KL */ - crypto_digest_get_digest(geoip_digest_env, geoip_digest, DIGEST_LEN); + crypto_digest_get_digest(geoip_digest_env, geoip6_digest, DIGEST_LEN); + } crypto_digest_free(geoip_digest_env); return 0; @@ -471,22 +470,28 @@ geoip_get_country_name(country_t num) /** Return true iff we have loaded a GeoIP database.*/ int -geoip_is_loaded(void) +geoip_is_loaded(sa_family_t family) { - /* XXX5053 Saying that we have loaded a GeoIP database if have _either_ - * a v4 or v6 database might be problematic. Maybe we need to add an - * address parameter to this function? -KL */ - return geoip_countries != NULL && - (geoip_ipv4_entries != NULL || geoip_ipv6_entries != NULL); + tor_assert(family == AF_INET || family == AF_INET6); + if (geoip_countries == NULL) + return 0; + if (family == AF_INET) + return geoip_ipv4_entries != NULL; + else /* AF_INET6 */ + return geoip_ipv6_entries != NULL; } /** Return the hex-encoded SHA1 digest of the loaded GeoIP file. The * result does not need to be deallocated, but will be overwritten by the * next call of hex_str(). */ const char * -geoip_db_digest(void) +geoip_db_digest(sa_family_t family) { - return hex_str(geoip_digest, DIGEST_LEN); + tor_assert(family == AF_INET || family == AF_INET6); + if (family == AF_INET) + return hex_str(geoip_digest, DIGEST_LEN); + else /* AF_INET6 */ + return hex_str(geoip6_digest, DIGEST_LEN); } /** Entry in a map from IP address to the last time we've seen an incoming @@ -1011,7 +1016,7 @@ geoip_get_client_history(geoip_client_action_t action, int *total_ipv4, unsigned total = 0; unsigned ipv4_count = 0, ipv6_count = 0; - if (!geoip_is_loaded()) + if (!geoip_is_loaded(AF_INET) && !geoip_is_loaded(AF_INET6)) return NULL; counts = tor_malloc_zero(sizeof(unsigned)*n_countries); @@ -1639,20 +1644,25 @@ getinfo_helper_geoip(control_connection_t *control_conn, const char **errmsg) { (void)control_conn; - if (!geoip_is_loaded()) { - *errmsg = "GeoIP data not loaded"; - return -1; - } if (!strcmpstart(question, "ip-to-country/")) { int c; - uint32_t ip; - struct in_addr in; + sa_family_t family; + tor_addr_t addr; question += strlen("ip-to-country/"); - if (tor_inet_aton(question, &in) != 0) { - ip = ntohl(in.s_addr); - c = geoip_get_country_by_ipv4(ip); - *answer = tor_strdup(geoip_get_country_name(c)); + family = tor_addr_parse(&addr, question); + if (family != AF_INET && family != AF_INET6) { + *errmsg = "Invalid address family"; + return -1; + } + if (!geoip_is_loaded(family)) { + *errmsg = "GeoIP data not loaded"; + return -1; } + if (family == AF_INET) + c = geoip_get_country_by_ipv4(tor_addr_to_ipv4h(&addr)); + else /* AF_INET6 */ + c = geoip_get_country_by_ipv6(tor_addr_to_in6(&addr)); + *answer = tor_strdup(geoip_get_country_name(c)); } return 0; } diff --git a/src/or/geoip.h b/src/or/geoip.h index 38f1289867..1d0012f857 100644 --- a/src/or/geoip.h +++ b/src/or/geoip.h @@ -24,8 +24,8 @@ int geoip_load_file(sa_family_t family, const char *filename, 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); -int geoip_is_loaded(void); -const char *geoip_db_digest(void); +int geoip_is_loaded(sa_family_t family); +const char *geoip_db_digest(sa_family_t family); country_t geoip_get_country(const char *countrycode); void geoip_note_client_seen(geoip_client_action_t action, diff --git a/src/or/router.c b/src/or/router.c index 2e80c54680..926bf26c18 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -2313,9 +2313,12 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, tor_free(bandwidth_usage); smartlist_add(chunks, pre); - if (geoip_is_loaded()) { - smartlist_add_asprintf(chunks, "geoip-db-digest %s\n", geoip_db_digest()); - } + if (geoip_is_loaded(AF_INET)) + smartlist_add_asprintf(chunks, "geoip-db-digest %s\n", + geoip_db_digest(AF_INET)); + if (geoip_is_loaded(AF_INET6)) + smartlist_add_asprintf(chunks, "geoip6-db-digest %s\n", + geoip_db_digest(AF_INET6)); if (options->ExtraInfoStatistics && write_stats_to_extrainfo) { log_info(LD_GENERAL, "Adding stats to extra-info descriptor."); diff --git a/src/or/routerset.c b/src/or/routerset.c index f3cd592aea..f9e3c9a495 100644 --- a/src/or/routerset.c +++ b/src/or/routerset.c @@ -82,7 +82,7 @@ routerset_refresh_countries(routerset_t *target) int cc; bitarray_free(target->countries); - if (!geoip_is_loaded()) { + if (!geoip_is_loaded(AF_INET)) { target->countries = NULL; target->n_countries = 0; return; -- cgit v1.2.3-54-g00ecf From af175fa7e4ee3ffd1d91d463ba77a3c10d95c654 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Sat, 20 Oct 2012 19:35:00 +0200 Subject: Duplicate less code. --- src/or/config.c | 76 ++++++++++++++++++++++++++++----------------------------- src/or/geoip.c | 4 +-- src/or/geoip.h | 3 +-- 3 files changed, 41 insertions(+), 42 deletions(-) (limited to 'src/or/config.c') diff --git a/src/or/config.c b/src/or/config.c index 5b1f1eed6f..b83b6f7222 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -482,6 +482,8 @@ static void init_libevent(const or_options_t *options); static int opt_streq(const char *s1, const char *s2); static int parse_outbound_addresses(or_options_t *options, int validate_only, char **msg); +static void config_maybe_load_geoip_files_(const or_options_t *options, + const or_options_t *old_options); /** Magic value for or_options_t. */ #define OR_OPTIONS_MAGIC 9090909 @@ -1512,44 +1514,7 @@ options_act(const or_options_t *old_options) connection_or_update_token_buckets(get_connection_array(), options); } - /* Maybe load IPv4 geoip file */ - if (options->GeoIPFile && - ((!old_options || !opt_streq(old_options->GeoIPFile, options->GeoIPFile)) - || !geoip_is_loaded(AF_INET))) { - /* XXXX Don't use this "" junk; make our filename options - * understand prefixes somehow. -NM */ - /* XXXX024 Reload GeoIPFile on SIGHUP. -NM */ - char *actual_fname = tor_strdup(options->GeoIPFile); -#ifdef _WIN32 - if (!strcmp(actual_fname, "")) { - const char *conf_root = get_windows_conf_root(); - tor_free(actual_fname); - tor_asprintf(&actual_fname, "%s\\geoip", conf_root); - } -#endif - geoip_load_file(AF_INET, actual_fname, options); - tor_free(actual_fname); - } - /* And maybe load IPv6 geoip file */ - if (options->GeoIPv6File && - ((!old_options || !opt_streq(old_options->GeoIPv6File, - options->GeoIPv6File)) - || !geoip_is_loaded(AF_INET6))) { - /* XXXX Don't use this "" junk; make our filename options - * understand prefixes somehow. See also comment for GeoIPFile. */ - /* XXXX024 Reload GeoIPV6File on SIGHUP. See also comment for - * GeoIPFile. */ - char *actual_fname = tor_strdup(options->GeoIPv6File); -#ifdef _WIN32 - if (!strcmp(actual_fname, "")) { - 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); - } + config_maybe_load_geoip_files_(options, old_options); if (options->CellStatistics || options->DirReqStatistics || options->EntryStatistics || options->ExitPortStatistics || @@ -5599,3 +5564,38 @@ parse_outbound_addresses(or_options_t *options, int validate_only, char **msg) return 0; } +static void +config_load_geoip_file_(sa_family_t family, + char *fname, /* will be freed */ + const char *default_fname) +{ + (void)default_fname; + /* XXXX Don't use this "" junk; make our filename options + * understand prefixes somehow. -NM */ + /* XXXX024 Reload GeoIPFile on SIGHUP. -NM */ +#ifdef _WIN32 + if (!strcmp(fname, "")) { + const char *conf_root = get_windows_conf_root(); + tor_free(fname); + tor_asprintf(&fname, "%s\\%s", conf_root, default_fname); + } +#endif + geoip_load_file(family, fname); + tor_free(fname); +} + +static void +config_maybe_load_geoip_files_(const or_options_t *options, + const or_options_t *old_options) +{ + if (options->GeoIPFile && + ((!old_options || !opt_streq(old_options->GeoIPFile, + options->GeoIPFile)) + || !geoip_is_loaded(AF_INET))) + config_load_geoip_file_(AF_INET, tor_strdup(options->GeoIPFile), "geoip"); + if (options->GeoIPv6File && + ((!old_options || !opt_streq(old_options->GeoIPv6File, + options->GeoIPv6File)) + || !geoip_is_loaded(AF_INET6))) + config_load_geoip_file_(AF_INET6, tor_strdup(options->GeoIPv6File), "geoip6"); +} diff --git a/src/or/geoip.c b/src/or/geoip.c index e1c0009cc3..5459b5504b 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -326,11 +326,11 @@ init_geoip_countries(void) * with '#' (comments). */ int -geoip_load_file(sa_family_t family, const char *filename, - const or_options_t *options) +geoip_load_file(sa_family_t family, const char *filename) { FILE *f; const char *msg = ""; + const or_options_t *options = get_options(); int severity = options_need_geoip_info(options, &msg) ? LOG_WARN : LOG_INFO; crypto_digest_t *geoip_digest_env = NULL; diff --git a/src/or/geoip.h b/src/or/geoip.h index 1d0012f857..3c91617c6e 100644 --- a/src/or/geoip.h +++ b/src/or/geoip.h @@ -19,8 +19,7 @@ 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(sa_family_t family, const char *filename, - const or_options_t *options); +int geoip_load_file(sa_family_t family, const char *filename); 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); -- cgit v1.2.3-54-g00ecf From 9d71d97e9dc32789693df135c06574a16d1ebfea Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Fri, 19 Oct 2012 23:23:04 +0200 Subject: Document two functions. --- src/or/config.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/or/config.c') diff --git a/src/or/config.c b/src/or/config.c index b83b6f7222..b81f319206 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -5564,6 +5564,10 @@ parse_outbound_addresses(or_options_t *options, int validate_only, char **msg) return 0; } +/** Load one of the geoip files, family determining which + * one. Note that fname will be freed by this + * function. default_fname is used if on Windows and + * fname equals "". */ static void config_load_geoip_file_(sa_family_t family, char *fname, /* will be freed */ @@ -5584,6 +5588,8 @@ config_load_geoip_file_(sa_family_t family, tor_free(fname); } +/** Load geoip files for IPv4 and IPv6 if options and + * old_options indicate we should. */ static void config_maybe_load_geoip_files_(const or_options_t *options, const or_options_t *old_options) -- cgit v1.2.3-54-g00ecf