From 8fca6fb2aa569cf4f09b6b4aaa887f3b434d759e Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 15 Sep 2009 13:41:36 -0400 Subject: [PATCH 1/4] Make "Nowhere" explicitly listable in torrc. We already had the country code ?? indicating an unknown country, so all we needed to do to make unknown countries excludable was to make the ?? code discoverable. --- changes/nowhereland | 6 ++++++ src/or/geoip.c | 1 + src/or/routerlist.c | 4 ++++ 3 files changed, 11 insertions(+) create mode 100644 changes/nowhereland diff --git a/changes/nowhereland b/changes/nowhereland new file mode 100644 index 0000000000..5435e965e9 --- /dev/null +++ b/changes/nowhereland @@ -0,0 +1,6 @@ + o Minor features: + - Add support for the country code "{??}" in torrc options like + ExcludeNodes, to indicate all routers of unknown country. Fixes bug + 1094. + + diff --git a/src/or/geoip.c b/src/or/geoip.c index eae927522a..6bb76ae4da 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -200,6 +200,7 @@ geoip_load_file(const char *filename, or_options_t *options) sizeof(geoip_unresolved->countrycode)); smartlist_add(geoip_countries, geoip_unresolved); country_idxplus1_by_lc_code = strmap_new(); + strmap_set_lc(country_idxplus1_by_lc_code, "??", (void*)(1)); } if (geoip_entries) { SMARTLIST_FOREACH(geoip_entries, geoip_entry_t *, e, tor_free(e)); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 5f98abe01b..7be98bd1a5 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -5335,6 +5335,10 @@ routerset_contains(const routerset_t *set, const tor_addr_t *addr, if (country < 0 && addr) country = geoip_get_country_by_ip(tor_addr_to_ipv4h(addr)); + /* XXXX can we safely move this into geoip_get_country_by_ip? */ + if (country < 0) + country = 0; + if (country >= 0 && country < set->n_countries && bitarray_is_set(set->countries, country)) return 2; From 4dd4d240b76c5c7ae47a1049e5deafc8b13d4f21 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Sat, 31 Jul 2010 15:06:55 -0400 Subject: [PATCH 2/4] Move the "nowhereland" logic into geoip.c --- src/or/geoip.c | 9 +++++---- src/or/routerlist.c | 4 ---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/or/geoip.c b/src/or/geoip.c index 6bb76ae4da..adbad8af73 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -228,9 +228,10 @@ geoip_load_file(const char *filename, or_options_t *options) } /** Given an IP address in host order, return a number representing the - * country to which that address belongs, or -1 for unknown. The return value - * will always be less than geoip_get_n_countries(). To decode it, - * call geoip_get_country_name(). + * 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_ip(uint32_t ipaddr) @@ -239,7 +240,7 @@ geoip_get_country_by_ip(uint32_t ipaddr) if (!geoip_entries) return -1; ent = smartlist_bsearch(geoip_entries, &ipaddr, _geoip_compare_key_to_entry); - return ent ? (int)ent->country : -1; + return ent ? (int)ent->country : 0; } /** Return the number of countries recognized by the GeoIP database. */ diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 7be98bd1a5..5f98abe01b 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -5335,10 +5335,6 @@ routerset_contains(const routerset_t *set, const tor_addr_t *addr, if (country < 0 && addr) country = geoip_get_country_by_ip(tor_addr_to_ipv4h(addr)); - /* XXXX can we safely move this into geoip_get_country_by_ip? */ - if (country < 0) - country = 0; - if (country >= 0 && country < set->n_countries && bitarray_is_set(set->countries, country)) return 2; From b175c584d579da9eeb92dc619451820f89d1979d Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Sat, 31 Jul 2010 15:14:48 -0400 Subject: [PATCH 3/4] Set up the geoip country table right even if not called normally --- src/or/geoip.c | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/or/geoip.c b/src/or/geoip.c index adbad8af73..8c218ef27f 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -17,6 +17,7 @@ #include "routerlist.h" static void clear_geoip_db(void); +static void init_geoip_countries(void); /** An entry from the GeoIP file: maps an IP range to a country. */ typedef struct geoip_entry_t { @@ -106,11 +107,11 @@ geoip_parse_entry(const char *line) { unsigned int low, high; char b[3]; - if (!geoip_countries) { - geoip_countries = smartlist_create(); + if (!geoip_countries) + init_geoip_countries(); + if (!geoip_entries) geoip_entries = smartlist_create(); - country_idxplus1_by_lc_code = strmap_new(); - } + while (TOR_ISSPACE(*line)) ++line; if (*line == '#') @@ -165,6 +166,24 @@ should_record_bridge_info(or_options_t *options) return options->BridgeRelay && options->BridgeRecordUsageByCountry; } +/** Set up a new list of geoip countries with no countries (yet) set in it, + * except for the unknown country. + */ +static void +init_geoip_countries(void) +{ + geoip_country_t *geoip_unresolved; + geoip_countries = smartlist_create(); + /* Add a geoip_country_t for requests that could not be resolved to a + * country as first element (index 0) to geoip_countries. */ + geoip_unresolved = tor_malloc_zero(sizeof(geoip_country_t)); + strlcpy(geoip_unresolved->countrycode, "??", + sizeof(geoip_unresolved->countrycode)); + smartlist_add(geoip_countries, geoip_unresolved); + country_idxplus1_by_lc_code = strmap_new(); + strmap_set_lc(country_idxplus1_by_lc_code, "??", (void*)(1)); +} + /** Clear the GeoIP database and reload it from the file * filename. Return 0 on success, -1 on failure. * @@ -190,18 +209,8 @@ geoip_load_file(const char *filename, or_options_t *options) filename, msg); return -1; } - if (!geoip_countries) { - geoip_country_t *geoip_unresolved; - geoip_countries = smartlist_create(); - /* Add a geoip_country_t for requests that could not be resolved to a - * country as first element (index 0) to geoip_countries. */ - geoip_unresolved = tor_malloc_zero(sizeof(geoip_country_t)); - strlcpy(geoip_unresolved->countrycode, "??", - sizeof(geoip_unresolved->countrycode)); - smartlist_add(geoip_countries, geoip_unresolved); - country_idxplus1_by_lc_code = strmap_new(); - strmap_set_lc(country_idxplus1_by_lc_code, "??", (void*)(1)); - } + if (!geoip_countries) + init_geoip_countries(); if (geoip_entries) { SMARTLIST_FOREACH(geoip_entries, geoip_entry_t *, e, tor_free(e)); smartlist_free(geoip_entries); @@ -419,7 +428,7 @@ geoip_note_client_seen(geoip_client_action_t action, if (options->BridgeRelay) { while (current_request_period_starts + REQUEST_HIST_PERIOD < now) { if (!geoip_countries) - geoip_countries = smartlist_create(); + init_geoip_countries(); if (!current_request_period_starts) { current_request_period_starts = now; break; From 49b0eb7a329224e53c3e24192a59e7c89d7e4ea4 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Sat, 31 Jul 2010 15:20:28 -0400 Subject: [PATCH 4/4] Fix up geoip unit tests to know about ?? --- src/test/test.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/test.c b/src/test/test.c index 755d1233f6..0830f57946 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -1108,10 +1108,12 @@ test_geoip(void) test_eq(0, geoip_parse_entry("\"150\",\"190\",\"XY\"")); test_eq(0, geoip_parse_entry("\"200\",\"250\",\"AB\"")); - /* We should have 3 countries: ab, xy, zz. */ - test_eq(3, geoip_get_n_countries()); + /* We should have 4 countries: ??, ab, xy, zz. */ + test_eq(4, geoip_get_n_countries()); /* Make sure that country ID actually works. */ #define NAMEFOR(x) geoip_get_country_name(geoip_get_country_by_ip(x)) + test_streq("??", NAMEFOR(3)); + test_eq(0, geoip_get_country_by_ip(3)); test_streq("ab", NAMEFOR(32)); test_streq("??", NAMEFOR(5)); test_streq("??", NAMEFOR(51));