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