Line data Source code
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 1 : test_geoip(void *arg)
48 : {
49 1 : int i, j;
50 1 : time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
51 1 : char *s = NULL, *v = NULL;
52 1 : 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 1 : *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 1 : *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 1 : *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 1 : *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 1 : *entry_stats_1 =
90 : "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n"
91 : "entry-ips ab=8\n",
92 1 : *entry_stats_2 =
93 : "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n"
94 : "entry-ips \n";
95 1 : tor_addr_t addr;
96 1 : struct in6_addr in6;
97 :
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 1 : (void)arg;
102 1 : tt_int_op(0,OP_EQ, geoip_parse_entry("10,50,AB", AF_INET));
103 1 : tt_int_op(0,OP_EQ, geoip_parse_entry("52,90,XY", AF_INET));
104 1 : tt_int_op(0,OP_EQ, geoip_parse_entry("95,100,AB", AF_INET));
105 1 : tt_int_op(0,OP_EQ, geoip_parse_entry("\"105\",\"140\",\"ZZ\"", AF_INET));
106 1 : tt_int_op(0,OP_EQ, geoip_parse_entry("\"150\",\"190\",\"XY\"", AF_INET));
107 1 : tt_int_op(0,OP_EQ, geoip_parse_entry("\"200\",\"250\",\"AB\"", AF_INET));
108 :
109 : /* Populate the IPv6 DB equivalently with fake IPs in the same range */
110 1 : tt_int_op(0,OP_EQ, geoip_parse_entry("::a,::32,AB", AF_INET6));
111 1 : tt_int_op(0,OP_EQ, geoip_parse_entry("::34,::5a,XY", AF_INET6));
112 1 : tt_int_op(0,OP_EQ, geoip_parse_entry("::5f,::64,AB", AF_INET6));
113 1 : tt_int_op(0,OP_EQ, geoip_parse_entry("::69,::8c,ZZ", AF_INET6));
114 1 : tt_int_op(0,OP_EQ, geoip_parse_entry("::96,::be,XY", AF_INET6));
115 1 : tt_int_op(0,OP_EQ, geoip_parse_entry("::c8,::fa,AB", AF_INET6));
116 :
117 : /* We should have 4 countries: ??, ab, xy, zz. */
118 1 : tt_int_op(4,OP_EQ, geoip_get_n_countries());
119 1 : memset(&in6, 0, sizeof(in6));
120 :
121 1 : CHECK_COUNTRY("??", 3);
122 1 : CHECK_COUNTRY("ab", 32);
123 1 : CHECK_COUNTRY("??", 5);
124 1 : CHECK_COUNTRY("??", 51);
125 1 : CHECK_COUNTRY("xy", 150);
126 1 : CHECK_COUNTRY("xy", 190);
127 1 : CHECK_COUNTRY("??", 2000);
128 :
129 1 : tt_int_op(0,OP_EQ, geoip_get_country_by_ipv4(3));
130 1 : SET_TEST_IPV6(3);
131 1 : tt_int_op(0,OP_EQ, geoip_get_country_by_ipv6(&in6));
132 :
133 1 : get_options_mutable()->BridgeRelay = 1;
134 1 : get_options_mutable()->BridgeRecordUsageByCountry = 1;
135 : /* Put 9 observations in AB... */
136 9 : for (i=32; i < 40; ++i) {
137 8 : SET_TEST_ADDRESS(i);
138 8 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200);
139 : }
140 1 : SET_TEST_ADDRESS(225);
141 1 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200);
142 : /* and 3 observations in XY, several times. */
143 12 : for (j=0; j < 10; ++j)
144 40 : for (i=52; i < 55; ++i) {
145 30 : SET_TEST_ADDRESS(i);
146 30 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-3600);
147 : }
148 : /* and 17 observations in ZZ... */
149 18 : for (i=110; i < 127; ++i) {
150 17 : SET_TEST_ADDRESS(i);
151 17 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
152 : }
153 1 : geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v);
154 1 : tt_assert(s);
155 1 : tt_assert(v);
156 1 : tt_str_op("zz=24,ab=16,xy=8",OP_EQ, s);
157 1 : tt_str_op("v4=16,v6=16",OP_EQ, v);
158 1 : tor_free(s);
159 1 : tor_free(v);
160 :
161 : /* Now clear out all the AB observations. */
162 1 : geoip_remove_old_clients(now-6000);
163 1 : geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v);
164 1 : tt_assert(s);
165 1 : tt_assert(v);
166 1 : tt_str_op("zz=24,xy=8",OP_EQ, s);
167 1 : tt_str_op("v4=16,v6=16",OP_EQ, v);
168 1 : tor_free(s);
169 1 : tor_free(v);
170 :
171 : /* Start testing bridge statistics by making sure that we don't output
172 : * bridge stats without initializing them. */
173 1 : s = geoip_format_bridge_stats(now + 86400);
174 1 : tt_ptr_op(s, OP_EQ, NULL);
175 :
176 : /* Initialize stats and generate the bridge-stats history string out of
177 : * the connecting clients added above. */
178 1 : geoip_bridge_stats_init(now);
179 1 : s = geoip_format_bridge_stats(now + 86400);
180 1 : tt_assert(s);
181 1 : tt_str_op(bridge_stats_1,OP_EQ, s);
182 1 : tor_free(s);
183 :
184 : /* Stop collecting bridge stats and make sure we don't write a history
185 : * string anymore. */
186 1 : geoip_bridge_stats_term();
187 1 : s = geoip_format_bridge_stats(now + 86400);
188 1 : tt_ptr_op(s, OP_EQ, NULL);
189 :
190 : /* Stop being a bridge and start being a directory mirror that gathers
191 : * directory request statistics. */
192 1 : geoip_bridge_stats_term();
193 1 : get_options_mutable()->BridgeRelay = 0;
194 1 : get_options_mutable()->BridgeRecordUsageByCountry = 0;
195 1 : get_options_mutable()->DirReqStatistics = 1;
196 :
197 : /* Start testing dirreq statistics by making sure that we don't collect
198 : * dirreq stats without initializing them. */
199 1 : SET_TEST_ADDRESS(100);
200 1 : geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
201 1 : s = geoip_format_dirreq_stats(now + 86400);
202 1 : tt_ptr_op(s, OP_EQ, NULL);
203 :
204 : /* Initialize stats, note one connecting client, and generate the
205 : * dirreq-stats history string. */
206 1 : geoip_dirreq_stats_init(now);
207 1 : SET_TEST_ADDRESS(100);
208 1 : geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
209 1 : s = geoip_format_dirreq_stats(now + 86400);
210 1 : tt_str_op(dirreq_stats_1,OP_EQ, s);
211 1 : tor_free(s);
212 :
213 : /* Stop collecting stats, add another connecting client, and ensure we
214 : * don't generate a history string. */
215 1 : geoip_dirreq_stats_term();
216 1 : SET_TEST_ADDRESS(101);
217 1 : geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
218 1 : s = geoip_format_dirreq_stats(now + 86400);
219 1 : tt_ptr_op(s, OP_EQ, NULL);
220 :
221 : /* Re-start stats, add a connecting client, reset stats, and make sure
222 : * that we get an all empty history string. */
223 1 : geoip_dirreq_stats_init(now);
224 1 : SET_TEST_ADDRESS(100);
225 1 : geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
226 1 : geoip_reset_dirreq_stats(now);
227 1 : s = geoip_format_dirreq_stats(now + 86400);
228 1 : tt_str_op(dirreq_stats_2,OP_EQ, s);
229 1 : tor_free(s);
230 :
231 : /* Note a successful network status response and make sure that it
232 : * appears in the history string. */
233 1 : geoip_note_ns_response(GEOIP_SUCCESS);
234 1 : s = geoip_format_dirreq_stats(now + 86400);
235 1 : tt_str_op(dirreq_stats_3,OP_EQ, s);
236 1 : tor_free(s);
237 :
238 : /* Start a tunneled directory request. */
239 1 : geoip_start_dirreq((uint64_t) 1, 1024, DIRREQ_TUNNELED);
240 1 : s = geoip_format_dirreq_stats(now + 86400);
241 1 : tt_str_op(dirreq_stats_4,OP_EQ, s);
242 1 : tor_free(s);
243 :
244 : /* Stop collecting directory request statistics and start gathering
245 : * entry stats. */
246 1 : geoip_dirreq_stats_term();
247 1 : get_options_mutable()->DirReqStatistics = 0;
248 1 : get_options_mutable()->EntryStatistics = 1;
249 :
250 : /* Start testing entry statistics by making sure that we don't collect
251 : * anything without initializing entry stats. */
252 1 : SET_TEST_ADDRESS(100);
253 1 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
254 1 : s = geoip_format_entry_stats(now + 86400);
255 1 : tt_ptr_op(s, OP_EQ, NULL);
256 :
257 : /* Initialize stats, note one connecting client, and generate the
258 : * entry-stats history string. */
259 1 : geoip_entry_stats_init(now);
260 1 : SET_TEST_ADDRESS(100);
261 1 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
262 1 : s = geoip_format_entry_stats(now + 86400);
263 1 : tt_str_op(entry_stats_1,OP_EQ, s);
264 1 : tor_free(s);
265 :
266 : /* Stop collecting stats, add another connecting client, and ensure we
267 : * don't generate a history string. */
268 1 : geoip_entry_stats_term();
269 1 : SET_TEST_ADDRESS(101);
270 1 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
271 1 : s = geoip_format_entry_stats(now + 86400);
272 1 : tt_ptr_op(s, OP_EQ, NULL);
273 :
274 : /* Re-start stats, add a connecting client, reset stats, and make sure
275 : * that we get an all empty history string. */
276 1 : geoip_entry_stats_init(now);
277 1 : SET_TEST_ADDRESS(100);
278 1 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
279 1 : geoip_reset_entry_stats(now);
280 1 : s = geoip_format_entry_stats(now + 86400);
281 1 : tt_str_op(entry_stats_2,OP_EQ, s);
282 1 : tor_free(s);
283 :
284 : /* Test the OOM handler. Add a client, run the OOM. */
285 1 : geoip_entry_stats_init(now);
286 1 : SET_TEST_ADDRESS(100);
287 1 : 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 1 : size_t bytes_removed = geoip_client_cache_handle_oom(now, 1000);
292 1 : tt_size_op(bytes_removed, OP_GT, 0);
293 :
294 : /* Do it again but this time with an entry with a lower cutoff. */
295 1 : geoip_entry_stats_init(now);
296 1 : SET_TEST_ADDRESS(100);
297 1 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL,
298 : now - (3 * 60 * 60));
299 1 : bytes_removed = geoip_client_cache_handle_oom(now, 1000);
300 1 : tt_size_op(bytes_removed, OP_EQ, 0);
301 :
302 : /* Stop collecting entry statistics. */
303 1 : geoip_entry_stats_term();
304 1 : get_options_mutable()->EntryStatistics = 0;
305 :
306 1 : done:
307 1 : tor_free(s);
308 1 : tor_free(v);
309 1 : }
310 :
311 : static void
312 1 : test_geoip_with_pt(void *arg)
313 : {
314 1 : time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
315 1 : char *s = NULL;
316 1 : int i;
317 1 : tor_addr_t addr;
318 1 : struct in6_addr in6;
319 :
320 1 : (void)arg;
321 1 : get_options_mutable()->BridgeRelay = 1;
322 1 : get_options_mutable()->BridgeRecordUsageByCountry = 1;
323 :
324 1 : memset(&in6, 0, sizeof(in6));
325 :
326 : /* No clients seen yet. */
327 1 : s = geoip_get_transport_history();
328 1 : tor_assert(!s);
329 :
330 : /* 4 connections without a pluggable transport */
331 5 : for (i=0; i < 4; ++i) {
332 4 : SET_TEST_ADDRESS(i);
333 4 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200);
334 : }
335 :
336 : /* 9 connections with "alpha" */
337 10 : for (i=4; i < 13; ++i) {
338 9 : SET_TEST_ADDRESS(i);
339 9 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "alpha", now-7200);
340 : }
341 :
342 : /* one connection with "beta" */
343 1 : SET_TEST_ADDRESS(13);
344 1 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "beta", now-7200);
345 :
346 : /* 14 connections with "charlie" */
347 16 : for (i=14; i < 28; ++i) {
348 14 : SET_TEST_ADDRESS(i);
349 14 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "charlie", now-7200);
350 : }
351 :
352 : /* 131 connections with "ddr" */
353 132 : for (i=28; i < 159; ++i) {
354 131 : SET_TEST_ADDRESS(i);
355 131 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "ddr", now-7200);
356 : }
357 :
358 : /* 8 connections with "entropy" */
359 9 : for (i=159; i < 167; ++i) {
360 8 : SET_TEST_ADDRESS(i);
361 8 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "entropy", now-7200);
362 : }
363 :
364 : /* 2 connections from the same IP with two different transports. */
365 1 : SET_TEST_ADDRESS(++i);
366 1 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "fire", now-7200);
367 1 : geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "google", now-7200);
368 :
369 : /* Test the transport history string. */
370 1 : s = geoip_get_transport_history();
371 1 : tor_assert(s);
372 1 : tt_str_op(s,OP_EQ, "<OR>=8,alpha=16,beta=8,charlie=16,ddr=136,"
373 : "entropy=8,fire=8,google=8");
374 :
375 : /* Stop collecting entry statistics. */
376 1 : geoip_entry_stats_term();
377 1 : get_options_mutable()->EntryStatistics = 0;
378 :
379 1 : done:
380 1 : tor_free(s);
381 1 : }
382 :
383 : #undef SET_TEST_ADDRESS
384 : #undef SET_TEST_IPV6
385 : #undef CHECK_COUNTRY
386 :
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";
397 :
398 : static void
399 1 : test_geoip_load_file(void *arg)
400 : {
401 1 : (void)arg;
402 1 : char *contents = NULL;
403 1 : char *dhex = NULL;
404 :
405 : /* A nonexistent filename should fail. */
406 1 : tt_int_op(-1, OP_EQ,
407 : geoip_load_file(AF_INET, "/you/did/not/put/a/file/here/I/hope",
408 : LOG_INFO));
409 :
410 : /* We start out with only "Ningunpartia" in the database. */
411 1 : tt_int_op(1, OP_EQ, geoip_get_n_countries());
412 1 : tt_str_op("??", OP_EQ, geoip_get_country_name(0));
413 : /* Any lookup attempt should say "-1" because we have no info */
414 1 : tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv4(0x01020304));
415 : /* There should be no 'digest' for a nonexistent file */
416 1 : tt_str_op("0000000000000000000000000000000000000000", OP_EQ,
417 : geoip_db_digest(AF_INET));
418 :
419 1 : const char *fname = get_fname("geoip");
420 1 : tt_int_op(0, OP_EQ, write_str_to_file(fname, GEOIP_CONTENT, 1));
421 :
422 1 : int rv = geoip_load_file(AF_INET, fname, LOG_WARN);
423 1 : if (rv != 0) {
424 0 : TT_GRIPE(("Unable to load geoip from %s", escaped(fname)));
425 : }
426 1 : tt_int_op(0, OP_EQ, rv);
427 :
428 : /* Check that we loaded some countries; this will fail if there are ever
429 : * fewer than 5 countries in our test above. */
430 1 : tt_int_op(geoip_get_n_countries(), OP_GE, 5);
431 :
432 : /* Let's see where 8.8.8.8 is. */
433 1 : int country = geoip_get_country_by_ipv4(0x08080808);
434 1 : tt_int_op(country, OP_GE, 1); /* It shouldn't be 'unknown' or 'nowhere' */
435 1 : const char *cc = geoip_get_country_name(country);
436 1 : tt_int_op(strlen(cc), OP_EQ, 2);
437 :
438 : /* The digest should be set.... */
439 1 : tt_str_op("0000000000000000000000000000000000000000", OP_NE,
440 : geoip_db_digest(AF_INET));
441 :
442 : /* And it should be set correctly */
443 1 : contents = read_file_to_str(fname, RFTS_BIN, NULL);
444 1 : uint8_t d[DIGEST_LEN];
445 1 : crypto_digest((char*)d, contents, strlen(contents));
446 1 : dhex = tor_strdup(hex_str((char*)d, DIGEST_LEN));
447 1 : tt_str_op(dhex, OP_EQ, geoip_db_digest(AF_INET));
448 :
449 : /* Make sure geoip_free_all() works. */
450 1 : geoip_free_all();
451 1 : tt_int_op(1, OP_EQ, geoip_get_n_countries());
452 1 : tt_str_op("??", OP_EQ, geoip_get_country_name(0));
453 1 : tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv4(0x01020304));
454 1 : tt_str_op("0000000000000000000000000000000000000000", OP_EQ,
455 : geoip_db_digest(AF_INET)); // <--- nick bets this will fail.
456 :
457 1 : done:
458 1 : tor_free(contents);
459 1 : tor_free(dhex);
460 1 : }
461 :
462 : static void
463 1 : test_geoip6_load_file(void *arg)
464 : {
465 1 : (void)arg;
466 1 : struct in6_addr iaddr6;
467 1 : char *contents = NULL;
468 1 : char *dhex = NULL;
469 :
470 : /* A nonexistent filename should fail. */
471 1 : tt_int_op(-1, OP_EQ,
472 : geoip_load_file(AF_INET6, "/you/did/not/put/a/file/here/I/hope",
473 : LOG_INFO));
474 :
475 : /* Any lookup attempt should say "-1" because we have no info */
476 1 : tor_inet_pton(AF_INET6, "2001:4860:4860::8888", &iaddr6);
477 1 : tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv6(&iaddr6));
478 :
479 : /* Load geiop6 file */
480 1 : const char *fname6 = get_fname("geoip6");
481 1 : 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 1 : tt_int_op(0, OP_EQ, write_str_to_file(fname6, CONTENT, 1));
498 :
499 1 : tt_int_op(0, OP_EQ, geoip_load_file(AF_INET6, fname6, LOG_WARN));
500 :
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 1 : tt_int_op(geoip_get_n_countries(), OP_GE, 5);
504 :
505 : /* Let's see where 2001:4860:4860::8888 (google dns) is. */
506 1 : const char *caddr6 = "2001:4860:4860::8888";
507 1 : tor_inet_pton(AF_INET6, caddr6, &iaddr6);
508 1 : int country6 = geoip_get_country_by_ipv6(&iaddr6);
509 1 : tt_int_op(country6, OP_GE, 1);
510 :
511 1 : const char *cc6 = geoip_get_country_name(country6);
512 1 : tt_int_op(strlen(cc6), OP_EQ, 2);
513 :
514 : /* The digest should be set.... */
515 1 : tt_str_op("0000000000000000000000000000000000000000", OP_NE,
516 : geoip_db_digest(AF_INET6));
517 :
518 : /* And it should be set correctly */
519 1 : contents = read_file_to_str(fname6, RFTS_BIN, NULL);
520 1 : uint8_t d[DIGEST_LEN];
521 1 : crypto_digest((char*)d, contents, strlen(contents));
522 1 : dhex = tor_strdup(hex_str((char*)d, DIGEST_LEN));
523 1 : tt_str_op(dhex, OP_EQ, geoip_db_digest(AF_INET6));
524 :
525 : /* Make sure geoip_free_all() works. */
526 1 : geoip_free_all();
527 1 : tt_int_op(1, OP_EQ, geoip_get_n_countries());
528 1 : tt_str_op("??", OP_EQ, geoip_get_country_name(0));
529 1 : tor_inet_pton(AF_INET6, "::1:2:3:4", &iaddr6);
530 1 : tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv6(&iaddr6));
531 1 : tt_str_op("0000000000000000000000000000000000000000", OP_EQ,
532 : geoip_db_digest(AF_INET6));
533 :
534 1 : done:
535 1 : tor_free(contents);
536 1 : tor_free(dhex);
537 1 : }
538 :
539 : static void
540 1 : test_geoip_load_2nd_file(void *arg)
541 : {
542 1 : (void)arg;
543 :
544 1 : char *fname_geoip = tor_strdup(get_fname("geoip_data"));
545 1 : char *fname_empty = tor_strdup(get_fname("geoip_empty"));
546 :
547 1 : tt_int_op(0, OP_EQ, write_str_to_file(fname_geoip, GEOIP_CONTENT, 1));
548 1 : tt_int_op(0, OP_EQ, write_str_to_file(fname_empty, "\n", 1));
549 :
550 : /* Load 1st geoip file */
551 1 : tt_int_op(0, OP_EQ, geoip_load_file(AF_INET, fname_geoip, LOG_WARN));
552 :
553 : /* Load 2nd geoip (empty) file */
554 : /* It has to be the same IP address family */
555 1 : tt_int_op(0, OP_EQ, geoip_load_file(AF_INET, fname_empty, LOG_WARN));
556 :
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 1 : int country = geoip_get_country_by_ipv4(0x08080808);
560 1 : tt_int_op(country, OP_EQ, 0);
561 :
562 1 : done:
563 1 : tor_free(fname_geoip);
564 1 : tor_free(fname_empty);
565 1 : }
566 :
567 : #define ENT(name) \
568 : { #name, test_ ## name , 0, NULL, NULL }
569 : #define FORK(name) \
570 : { #name, test_ ## name , TT_FORK, NULL, NULL }
571 :
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 },
578 :
579 : END_OF_TESTCASES
580 : };
|