tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

test_geoip.c (21268B)


      1 /* Copyright (c) 2001-2004, Roger Dingledine.
      2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
      3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
      4 /* See LICENSE for licensing information */
      5 
      6 #include "orconfig.h"
      7 
      8 /* These macros pull in declarations for some functions and structures that
      9 * are typically file-private. */
     10 #define GEOIP_PRIVATE
     11 #include "core/or/or.h"
     12 #include "app/config/config.h"
     13 #include "lib/geoip/geoip.h"
     14 #include "feature/stats/geoip_stats.h"
     15 #include "test/test.h"
     16 
     17  /* Record odd numbered fake-IPs using ipv6, even numbered fake-IPs
     18   * using ipv4.  Since our fake geoip database is the same between
     19   * ipv4 and ipv6, we should get the same result no matter which
     20   * address family we pick for each IP. */
     21 #define SET_TEST_ADDRESS(i) do {                \
     22    if ((i) & 1) {                              \
     23      SET_TEST_IPV6(i);                         \
     24      tor_addr_from_in6(&addr, &in6);           \
     25    } else {                                    \
     26      tor_addr_from_ipv4h(&addr, (uint32_t) i); \
     27    }                                           \
     28  } while (0)
     29 
     30  /* Make sure that country ID actually works. */
     31 #define SET_TEST_IPV6(i) \
     32  do {                                                          \
     33    set_uint32(in6.s6_addr + 12, htonl((uint32_t) (i)));        \
     34  } while (0)
     35 #define CHECK_COUNTRY(country, val) do {                                \
     36    /* test ipv4 country lookup */                                      \
     37    tt_str_op(country, OP_EQ,                                              \
     38               geoip_get_country_name(geoip_get_country_by_ipv4(val))); \
     39    /* test ipv6 country lookup */                                      \
     40    SET_TEST_IPV6(val);                                                 \
     41    tt_str_op(country, OP_EQ,                                              \
     42               geoip_get_country_name(geoip_get_country_by_ipv6(&in6))); \
     43  } while (0)
     44 
     45 /** Run unit tests for GeoIP code. */
     46 static void
     47 test_geoip(void *arg)
     48 {
     49  int i, j;
     50  time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
     51  char *s = NULL, *v = NULL;
     52  const char *bridge_stats_1 =
     53      "bridge-stats-end 2010-08-12 13:27:30 (86400 s)\n"
     54      "bridge-ips zz=24,xy=8\n"
     55      "bridge-ip-versions v4=16,v6=16\n"
     56      "bridge-ip-transports <OR>=24\n",
     57  *dirreq_stats_1 =
     58      "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
     59      "dirreq-v3-ips ab=8\n"
     60      "dirreq-v3-reqs ab=8\n"
     61      "dirreq-v3-resp "
     62          "served=0,ok=0,not-enough-sigs=0,unavailable=0,not-found=0,"
     63          "not-modified=0,busy=0\n"
     64      "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
     65      "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n",
     66  *dirreq_stats_2 =
     67      "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
     68      "dirreq-v3-ips \n"
     69      "dirreq-v3-reqs \n"
     70      "dirreq-v3-resp "
     71          "served=0,ok=0,not-enough-sigs=0,unavailable=0,not-found=0,"
     72          "not-modified=0,busy=0\n"
     73      "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
     74      "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n",
     75  *dirreq_stats_3 =
     76      "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
     77      "dirreq-v3-ips \n"
     78      "dirreq-v3-reqs \n"
     79      "dirreq-v3-resp "
     80          "served=8,ok=8,not-enough-sigs=0,unavailable=0,not-found=0,"
     81          "not-modified=0,busy=0\n"
     82      "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
     83      "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n",
     84  *dirreq_stats_4 =
     85      "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
     86      "dirreq-v3-ips \n"
     87      "dirreq-v3-reqs \n"
     88      "dirreq-v3-resp "
     89          "served=8,ok=8,not-enough-sigs=0,unavailable=0,not-found=0,"
     90          "not-modified=0,busy=0\n"
     91      "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
     92      "dirreq-v3-tunneled-dl complete=0,timeout=0,running=4\n",
     93  *entry_stats_1 =
     94      "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n"
     95      "entry-ips ab=8\n",
     96  *entry_stats_2 =
     97      "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n"
     98      "entry-ips \n";
     99  tor_addr_t addr;
    100  struct in6_addr in6;
    101 
    102  /* Populate the DB a bit.  Add these in order, since we can't do the final
    103   * 'sort' step.  These aren't very good IP addresses, but they're perfectly
    104   * fine uint32_t values. */
    105  (void)arg;
    106  tt_int_op(0,OP_EQ, geoip_parse_entry("10,50,AB", AF_INET));
    107  tt_int_op(0,OP_EQ, geoip_parse_entry("52,90,XY", AF_INET));
    108  tt_int_op(0,OP_EQ, geoip_parse_entry("95,100,AB", AF_INET));
    109  tt_int_op(0,OP_EQ, geoip_parse_entry("\"105\",\"140\",\"ZZ\"", AF_INET));
    110  tt_int_op(0,OP_EQ, geoip_parse_entry("\"150\",\"190\",\"XY\"", AF_INET));
    111  tt_int_op(0,OP_EQ, geoip_parse_entry("\"200\",\"250\",\"AB\"", AF_INET));
    112 
    113  /* Populate the IPv6 DB equivalently with fake IPs in the same range */
    114  tt_int_op(0,OP_EQ, geoip_parse_entry("::a,::32,AB", AF_INET6));
    115  tt_int_op(0,OP_EQ, geoip_parse_entry("::34,::5a,XY", AF_INET6));
    116  tt_int_op(0,OP_EQ, geoip_parse_entry("::5f,::64,AB", AF_INET6));
    117  tt_int_op(0,OP_EQ, geoip_parse_entry("::69,::8c,ZZ", AF_INET6));
    118  tt_int_op(0,OP_EQ, geoip_parse_entry("::96,::be,XY", AF_INET6));
    119  tt_int_op(0,OP_EQ, geoip_parse_entry("::c8,::fa,AB", AF_INET6));
    120 
    121  /* We should have 4 countries: ??, ab, xy, zz. */
    122  tt_int_op(4,OP_EQ, geoip_get_n_countries());
    123  memset(&in6, 0, sizeof(in6));
    124 
    125  CHECK_COUNTRY("??", 3);
    126  CHECK_COUNTRY("ab", 32);
    127  CHECK_COUNTRY("??", 5);
    128  CHECK_COUNTRY("??", 51);
    129  CHECK_COUNTRY("xy", 150);
    130  CHECK_COUNTRY("xy", 190);
    131  CHECK_COUNTRY("??", 2000);
    132 
    133  tt_int_op(0,OP_EQ, geoip_get_country_by_ipv4(3));
    134  SET_TEST_IPV6(3);
    135  tt_int_op(0,OP_EQ, geoip_get_country_by_ipv6(&in6));
    136 
    137  get_options_mutable()->BridgeRelay = 1;
    138  get_options_mutable()->BridgeRecordUsageByCountry = 1;
    139  /* Put 9 observations in AB... */
    140  for (i=32; i < 40; ++i) {
    141    SET_TEST_ADDRESS(i);
    142    geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200);
    143  }
    144  SET_TEST_ADDRESS(225);
    145  geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200);
    146  /* and 3 observations in XY, several times. */
    147  for (j=0; j < 10; ++j)
    148    for (i=52; i < 55; ++i) {
    149      SET_TEST_ADDRESS(i);
    150      geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-3600);
    151    }
    152  /* and 17 observations in ZZ... */
    153  for (i=110; i < 127; ++i) {
    154    SET_TEST_ADDRESS(i);
    155    geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
    156  }
    157  geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v);
    158  tt_assert(s);
    159  tt_assert(v);
    160  tt_str_op("zz=24,ab=16,xy=8",OP_EQ, s);
    161  tt_str_op("v4=16,v6=16",OP_EQ, v);
    162  tor_free(s);
    163  tor_free(v);
    164 
    165  /* Now clear out all the AB observations. */
    166  geoip_remove_old_clients(now-6000);
    167  geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v);
    168  tt_assert(s);
    169  tt_assert(v);
    170  tt_str_op("zz=24,xy=8",OP_EQ, s);
    171  tt_str_op("v4=16,v6=16",OP_EQ, v);
    172  tor_free(s);
    173  tor_free(v);
    174 
    175  /* Start testing bridge statistics by making sure that we don't output
    176   * bridge stats without initializing them. */
    177  s = geoip_format_bridge_stats(now + 86400);
    178  tt_ptr_op(s, OP_EQ, NULL);
    179 
    180  /* Initialize stats and generate the bridge-stats history string out of
    181   * the connecting clients added above. */
    182  geoip_bridge_stats_init(now);
    183  s = geoip_format_bridge_stats(now + 86400);
    184  tt_assert(s);
    185  tt_str_op(bridge_stats_1,OP_EQ, s);
    186  tor_free(s);
    187 
    188  /* Stop collecting bridge stats and make sure we don't write a history
    189   * string anymore. */
    190  geoip_bridge_stats_term();
    191  s = geoip_format_bridge_stats(now + 86400);
    192  tt_ptr_op(s, OP_EQ, NULL);
    193 
    194  /* Stop being a bridge and start being a directory mirror that gathers
    195   * directory request statistics. */
    196  geoip_bridge_stats_term();
    197  get_options_mutable()->BridgeRelay = 0;
    198  get_options_mutable()->BridgeRecordUsageByCountry = 0;
    199  get_options_mutable()->DirReqStatistics = 1;
    200 
    201  /* Start testing dirreq statistics by making sure that we don't collect
    202   * dirreq stats without initializing them. */
    203  SET_TEST_ADDRESS(100);
    204  geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
    205  s = geoip_format_dirreq_stats(now + 86400);
    206  tt_ptr_op(s, OP_EQ, NULL);
    207 
    208  /* Initialize stats, note one connecting client, and generate the
    209   * dirreq-stats history string. */
    210  geoip_dirreq_stats_init(now);
    211  SET_TEST_ADDRESS(100);
    212  geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
    213  s = geoip_format_dirreq_stats(now + 86400);
    214  tt_str_op(dirreq_stats_1,OP_EQ, s);
    215  tor_free(s);
    216 
    217  /* Stop collecting stats, add another connecting client, and ensure we
    218   * don't generate a history string. */
    219  geoip_dirreq_stats_term();
    220  SET_TEST_ADDRESS(101);
    221  geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
    222  s = geoip_format_dirreq_stats(now + 86400);
    223  tt_ptr_op(s, OP_EQ, NULL);
    224 
    225  /* Re-start stats, add a connecting client, reset stats, and make sure
    226   * that we get an all empty history string. */
    227  geoip_dirreq_stats_init(now);
    228  SET_TEST_ADDRESS(100);
    229  geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
    230  geoip_reset_dirreq_stats(now);
    231  s = geoip_format_dirreq_stats(now + 86400);
    232  tt_str_op(dirreq_stats_2,OP_EQ, s);
    233  tor_free(s);
    234 
    235  /* Note a successful network status response and make sure that it
    236   * appears in the history string. */
    237  geoip_note_ns_response(GEOIP_SERVED);
    238  geoip_note_ns_response(GEOIP_SUCCESS);
    239  s = geoip_format_dirreq_stats(now + 86400);
    240  tt_str_op(dirreq_stats_3,OP_EQ, s);
    241  tor_free(s);
    242 
    243  /* Start a tunneled directory request. */
    244  geoip_start_dirreq((uint64_t) 1, 1024, DIRREQ_TUNNELED);
    245  s = geoip_format_dirreq_stats(now + 86400);
    246  tt_str_op(dirreq_stats_4,OP_EQ, s);
    247  tor_free(s);
    248 
    249  /* Stop collecting directory request statistics and start gathering
    250   * entry stats. */
    251  geoip_dirreq_stats_term();
    252  get_options_mutable()->DirReqStatistics = 0;
    253  get_options_mutable()->EntryStatistics = 1;
    254 
    255  /* Start testing entry statistics by making sure that we don't collect
    256   * anything without initializing entry stats. */
    257  SET_TEST_ADDRESS(100);
    258  geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
    259  s = geoip_format_entry_stats(now + 86400);
    260  tt_ptr_op(s, OP_EQ, NULL);
    261 
    262  /* Initialize stats, note one connecting client, and generate the
    263   * entry-stats history string. */
    264  geoip_entry_stats_init(now);
    265  SET_TEST_ADDRESS(100);
    266  geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
    267  s = geoip_format_entry_stats(now + 86400);
    268  tt_str_op(entry_stats_1,OP_EQ, s);
    269  tor_free(s);
    270 
    271  /* Stop collecting stats, add another connecting client, and ensure we
    272   * don't generate a history string. */
    273  geoip_entry_stats_term();
    274  SET_TEST_ADDRESS(101);
    275  geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
    276  s = geoip_format_entry_stats(now + 86400);
    277  tt_ptr_op(s, OP_EQ, NULL);
    278 
    279  /* Re-start stats, add a connecting client, reset stats, and make sure
    280   * that we get an all empty history string. */
    281  geoip_entry_stats_init(now);
    282  SET_TEST_ADDRESS(100);
    283  geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
    284  geoip_reset_entry_stats(now);
    285  s = geoip_format_entry_stats(now + 86400);
    286  tt_str_op(entry_stats_2,OP_EQ, s);
    287  tor_free(s);
    288 
    289  /* Test the OOM handler. Add a client, run the OOM. */
    290  geoip_entry_stats_init(now);
    291  SET_TEST_ADDRESS(100);
    292  geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL,
    293                         now - (12 * 60 * 60));
    294  /* We've seen this 12 hours ago. Run the OOM, it should clean the entry
    295   * because it is above the minimum cutoff of 4 hours. */
    296  size_t bytes_removed = geoip_client_cache_handle_oom(now, 1000);
    297  tt_size_op(bytes_removed, OP_GT, 0);
    298 
    299  /* Do it again but this time with an entry with a lower cutoff. */
    300  geoip_entry_stats_init(now);
    301  SET_TEST_ADDRESS(100);
    302  geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL,
    303                         now - (3 * 60 * 60));
    304  bytes_removed = geoip_client_cache_handle_oom(now, 1000);
    305  tt_size_op(bytes_removed, OP_EQ, 0);
    306 
    307  /* Stop collecting entry statistics. */
    308  geoip_entry_stats_term();
    309  get_options_mutable()->EntryStatistics = 0;
    310 
    311 done:
    312  tor_free(s);
    313  tor_free(v);
    314 }
    315 
    316 static void
    317 test_geoip_with_pt(void *arg)
    318 {
    319  time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
    320  char *s = NULL;
    321  int i;
    322  tor_addr_t addr;
    323  struct in6_addr in6;
    324 
    325  (void)arg;
    326  get_options_mutable()->BridgeRelay = 1;
    327  get_options_mutable()->BridgeRecordUsageByCountry = 1;
    328 
    329  memset(&in6, 0, sizeof(in6));
    330 
    331  /* No clients seen yet. */
    332  s = geoip_get_transport_history();
    333  tor_assert(!s);
    334 
    335  /* 4 connections without a pluggable transport */
    336  for (i=0; i < 4; ++i) {
    337    SET_TEST_ADDRESS(i);
    338    geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200);
    339  }
    340 
    341  /* 9 connections with "alpha" */
    342  for (i=4; i < 13; ++i) {
    343    SET_TEST_ADDRESS(i);
    344    geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "alpha", now-7200);
    345  }
    346 
    347  /* one connection with "beta" */
    348  SET_TEST_ADDRESS(13);
    349  geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "beta", now-7200);
    350 
    351  /* 14 connections with "charlie" */
    352  for (i=14; i < 28; ++i) {
    353    SET_TEST_ADDRESS(i);
    354    geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "charlie", now-7200);
    355  }
    356 
    357  /* 131 connections with "ddr" */
    358  for (i=28; i < 159; ++i) {
    359    SET_TEST_ADDRESS(i);
    360    geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "ddr", now-7200);
    361  }
    362 
    363  /* 8 connections with "entropy" */
    364  for (i=159; i < 167; ++i) {
    365    SET_TEST_ADDRESS(i);
    366    geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "entropy", now-7200);
    367  }
    368 
    369  /* 2 connections from the same IP with two different transports. */
    370  SET_TEST_ADDRESS(++i);
    371  geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "fire", now-7200);
    372  geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "google", now-7200);
    373 
    374  /* Test the transport history string. */
    375  s = geoip_get_transport_history();
    376  tor_assert(s);
    377  tt_str_op(s,OP_EQ, "<OR>=8,alpha=16,beta=8,charlie=16,ddr=136,"
    378             "entropy=8,fire=8,google=8");
    379 
    380  /* Stop collecting entry statistics. */
    381  geoip_entry_stats_term();
    382  get_options_mutable()->EntryStatistics = 0;
    383 
    384 done:
    385  tor_free(s);
    386 }
    387 
    388 #undef SET_TEST_ADDRESS
    389 #undef SET_TEST_IPV6
    390 #undef CHECK_COUNTRY
    391 
    392 static const char GEOIP_CONTENT[] =
    393  "134445936,134445939,MP\n"
    394  "134445940,134447103,GU\n"
    395  "134447104,134738943,US\n"
    396  "134738944,134739199,CA\n"
    397  "134739200,135192575,US\n"
    398  "135192576,135200767,MX\n"
    399  "135200768,135430143,US\n"
    400  "135430144,135430399,CA\n"
    401  "135430400,135432191,US\n";
    402 
    403 static void
    404 test_geoip_load_file(void *arg)
    405 {
    406  (void)arg;
    407  char *contents = NULL;
    408  char *dhex = NULL;
    409 
    410  /* A nonexistent filename should fail. */
    411  tt_int_op(-1, OP_EQ,
    412            geoip_load_file(AF_INET, "/you/did/not/put/a/file/here/I/hope",
    413                            LOG_INFO));
    414 
    415  /* We start out with only "Ningunpartia" in the database. */
    416  tt_int_op(1, OP_EQ, geoip_get_n_countries());
    417  tt_str_op("??", OP_EQ, geoip_get_country_name(0));
    418  /* Any lookup attempt should say "-1" because we have no info */
    419  tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv4(0x01020304));
    420  /* There should be no 'digest' for a nonexistent file */
    421  tt_str_op("0000000000000000000000000000000000000000", OP_EQ,
    422            geoip_db_digest(AF_INET));
    423 
    424  const char *fname = get_fname("geoip");
    425  tt_int_op(0, OP_EQ, write_str_to_file(fname, GEOIP_CONTENT, 1));
    426 
    427  int rv = geoip_load_file(AF_INET, fname, LOG_WARN);
    428  if (rv != 0) {
    429    TT_GRIPE(("Unable to load geoip from %s", escaped(fname)));
    430  }
    431  tt_int_op(0, OP_EQ, rv);
    432 
    433  /* Check that we loaded some countries; this will fail if there are ever
    434   * fewer than 5 countries in our test above. */
    435  tt_int_op(geoip_get_n_countries(), OP_GE, 5);
    436 
    437  /* Let's see where 8.8.8.8 is. */
    438  int country = geoip_get_country_by_ipv4(0x08080808);
    439  tt_int_op(country, OP_GE, 1); /* It shouldn't be 'unknown' or 'nowhere' */
    440  const char *cc = geoip_get_country_name(country);
    441  tt_int_op(strlen(cc), OP_EQ, 2);
    442 
    443  /* The digest should be set.... */
    444  tt_str_op("0000000000000000000000000000000000000000", OP_NE,
    445            geoip_db_digest(AF_INET));
    446 
    447  /* And it should be set correctly */
    448  contents = read_file_to_str(fname, RFTS_BIN, NULL);
    449  uint8_t d[DIGEST_LEN];
    450  crypto_digest((char*)d, contents, strlen(contents));
    451  dhex = tor_strdup(hex_str((char*)d, DIGEST_LEN));
    452  tt_str_op(dhex, OP_EQ, geoip_db_digest(AF_INET));
    453 
    454  /* Make sure geoip_free_all() works. */
    455  geoip_free_all();
    456  tt_int_op(1, OP_EQ, geoip_get_n_countries());
    457  tt_str_op("??", OP_EQ, geoip_get_country_name(0));
    458  tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv4(0x01020304));
    459  tt_str_op("0000000000000000000000000000000000000000", OP_EQ,
    460            geoip_db_digest(AF_INET)); // <--- nick bets this will fail.
    461 
    462 done:
    463  tor_free(contents);
    464  tor_free(dhex);
    465 }
    466 
    467 static void
    468 test_geoip6_load_file(void *arg)
    469 {
    470  (void)arg;
    471  struct in6_addr iaddr6;
    472  char *contents = NULL;
    473  char *dhex = NULL;
    474 
    475  /* A nonexistent filename should fail. */
    476  tt_int_op(-1, OP_EQ,
    477            geoip_load_file(AF_INET6, "/you/did/not/put/a/file/here/I/hope",
    478                            LOG_INFO));
    479 
    480  /* Any lookup attempt should say "-1" because we have no info */
    481  tor_inet_pton(AF_INET6, "2001:4860:4860::8888", &iaddr6);
    482  tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv6(&iaddr6));
    483 
    484  /* Load geiop6 file */
    485  const char *fname6 = get_fname("geoip6");
    486  const char CONTENT[] =
    487    "2001:4830:6010::,2001:4830:601f:ffff:ffff:ffff:ffff:ffff,GB\n"
    488    "2001:4830:6020::,2001:4830:ffff:ffff:ffff:ffff:ffff:ffff,US\n"
    489    "2001:4838::,2001:4838:ffff:ffff:ffff:ffff:ffff:ffff,US\n"
    490    "2001:4840::,2001:4840:ffff:ffff:ffff:ffff:ffff:ffff,XY\n"
    491    "2001:4848::,2001:4848:ffff:ffff:ffff:ffff:ffff:ffff,ZD\n"
    492    "2001:4850::,2001:4850:ffff:ffff:ffff:ffff:ffff:ffff,RO\n"
    493    "2001:4858::,2001:4858:ffff:ffff:ffff:ffff:ffff:ffff,TC\n"
    494    "2001:4860::,2001:4860:ffff:ffff:ffff:ffff:ffff:ffff,US\n"
    495    "2001:4868::,2001:4868:ffff:ffff:ffff:ffff:ffff:ffff,US\n"
    496    "2001:4870::,2001:4871:ffff:ffff:ffff:ffff:ffff:ffff,NB\n"
    497    "2001:4878::,2001:4878:128:ffff:ffff:ffff:ffff:ffff,US\n"
    498    "2001:4878:129::,2001:4878:129:ffff:ffff:ffff:ffff:ffff,CR\n"
    499    "2001:4878:12a::,2001:4878:203:ffff:ffff:ffff:ffff:ffff,US\n"
    500    "2001:4878:204::,2001:4878:204:ffff:ffff:ffff:ffff:ffff,DE\n"
    501    "2001:4878:205::,2001:4878:214:ffff:ffff:ffff:ffff:ffff,US\n";
    502  tt_int_op(0, OP_EQ, write_str_to_file(fname6, CONTENT, 1));
    503 
    504  tt_int_op(0, OP_EQ, geoip_load_file(AF_INET6, fname6, LOG_WARN));
    505 
    506  /* Check that we loaded some countries; this will fail if there are ever
    507   * fewer than 5 countries in our test data above. */
    508  tt_int_op(geoip_get_n_countries(), OP_GE, 5);
    509 
    510  /* Let's see where 2001:4860:4860::8888 (google dns) is. */
    511  const char *caddr6 = "2001:4860:4860::8888";
    512  tor_inet_pton(AF_INET6, caddr6, &iaddr6);
    513  int country6 = geoip_get_country_by_ipv6(&iaddr6);
    514  tt_int_op(country6, OP_GE, 1);
    515 
    516  const char *cc6 = geoip_get_country_name(country6);
    517  tt_int_op(strlen(cc6), OP_EQ, 2);
    518 
    519  /* The digest should be set.... */
    520  tt_str_op("0000000000000000000000000000000000000000", OP_NE,
    521            geoip_db_digest(AF_INET6));
    522 
    523  /* And it should be set correctly */
    524  contents = read_file_to_str(fname6, RFTS_BIN, NULL);
    525  uint8_t d[DIGEST_LEN];
    526  crypto_digest((char*)d, contents, strlen(contents));
    527  dhex = tor_strdup(hex_str((char*)d, DIGEST_LEN));
    528  tt_str_op(dhex, OP_EQ, geoip_db_digest(AF_INET6));
    529 
    530  /* Make sure geoip_free_all() works. */
    531  geoip_free_all();
    532  tt_int_op(1, OP_EQ, geoip_get_n_countries());
    533  tt_str_op("??", OP_EQ, geoip_get_country_name(0));
    534  tor_inet_pton(AF_INET6, "::1:2:3:4", &iaddr6);
    535  tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv6(&iaddr6));
    536  tt_str_op("0000000000000000000000000000000000000000", OP_EQ,
    537            geoip_db_digest(AF_INET6));
    538 
    539 done:
    540  tor_free(contents);
    541  tor_free(dhex);
    542 }
    543 
    544 static void
    545 test_geoip_load_2nd_file(void *arg)
    546 {
    547  (void)arg;
    548 
    549  char *fname_geoip = tor_strdup(get_fname("geoip_data"));
    550  char *fname_empty = tor_strdup(get_fname("geoip_empty"));
    551 
    552  tt_int_op(0, OP_EQ, write_str_to_file(fname_geoip, GEOIP_CONTENT, 1));
    553  tt_int_op(0, OP_EQ, write_str_to_file(fname_empty, "\n", 1));
    554 
    555  /* Load 1st geoip file */
    556  tt_int_op(0, OP_EQ, geoip_load_file(AF_INET, fname_geoip, LOG_WARN));
    557 
    558  /* Load 2nd geoip (empty) file */
    559  /* It has to be the same IP address family */
    560  tt_int_op(0, OP_EQ, geoip_load_file(AF_INET, fname_empty, LOG_WARN));
    561 
    562  /* Check that there is no geoip information for 8.8.8.8, */
    563  /* since loading the empty 2nd file should have delete it. */
    564  int country = geoip_get_country_by_ipv4(0x08080808);
    565  tt_int_op(country, OP_EQ, 0);
    566 
    567 done:
    568  tor_free(fname_geoip);
    569  tor_free(fname_empty);
    570 }
    571 
    572 #define ENT(name)                                                       \
    573  { #name, test_ ## name , 0, NULL, NULL }
    574 #define FORK(name)                                                      \
    575  { #name, test_ ## name , TT_FORK, NULL, NULL }
    576 
    577 struct testcase_t geoip_tests[] = {
    578  { "geoip", test_geoip, TT_FORK, NULL, NULL },
    579  { "geoip_with_pt", test_geoip_with_pt, TT_FORK, NULL, NULL },
    580  { "load_file", test_geoip_load_file, TT_FORK, NULL, NULL },
    581  { "load_file6", test_geoip6_load_file, TT_FORK, NULL, NULL },
    582  { "load_2nd_file", test_geoip_load_2nd_file, TT_FORK, NULL, NULL },
    583 
    584  END_OF_TESTCASES
    585 };