Commit 4504640b authored by Nick Mathewson's avatar Nick Mathewson 🤹
Browse files

Merge branch 'bug1094_v2'

parents 1470eb2e 49b0eb7a
Loading
Loading
Loading
Loading

changes/nowhereland

0 → 100644
+6 −0
Original line number Diff line number Diff line
  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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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));