test_geoip.c 21 KB

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