Browse Source

Merge branch 'bug1094_v2'

Nick Mathewson 15 years ago
parent
commit
4504640b10
3 changed files with 41 additions and 22 deletions
  1. 6 0
      changes/nowhereland
  2. 31 20
      src/or/geoip.c
  3. 4 2
      src/test/test.c

+ 6 - 0
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.
+
+

+ 31 - 20
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
  * <b>filename</b>. Return 0 on success, -1 on failure.
  *
@@ -190,17 +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();
-  }
+  if (!geoip_countries)
+    init_geoip_countries();
   if (geoip_entries) {
     SMARTLIST_FOREACH(geoip_entries, geoip_entry_t *, e, tor_free(e));
     smartlist_free(geoip_entries);
@@ -227,9 +237,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)
@@ -238,7 +249,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. */
@@ -417,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;

+ 4 - 2
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));