test_geoip.c 20 KB

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