1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
7  *
8  * See the COPYRIGHT file distributed with this work for additional
9  * information regarding copyright ownership.
10  */
11 
12 #include <config.h>
13 
14 #if HAVE_CMOCKA
15 
16 #include <stdarg.h>
17 #include <stddef.h>
18 #include <setjmp.h>
19 
20 #include <sched.h> /* IWYU pragma: keep */
21 #include <stdbool.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 
26 #define UNIT_TESTING
27 #include <cmocka.h>
28 
29 #include <isc/print.h>
30 #include <isc/string.h>
31 #include <isc/types.h>
32 #include <isc/util.h>
33 
34 #include <dns/geoip.h>
35 
36 #include "dnstest.h"
37 
38 #if defined(HAVE_GEOIP2)
39 #include <maxminddb.h>
40 
41 #include "../geoip2.c"
42 
43 /* Use GeoIP2 databases from the 'geoip2' system test */
44 #define TEST_GEOIP_DATA "../../../bin/tests/system/geoip2/data"
45 #elif defined(HAVE_GEOIP)
46 #include <GeoIP.h>
47 
48 /* Use GeoIP databases from the 'geoip' system test */
49 #define TEST_GEOIP_DATA "../../../bin/tests/system/geoip/data"
50 #endif
51 
52 #if defined(HAVE_GEOIP) || defined(HAVE_GEOIP2)
53 static void load_geoip(const char *dir);
54 static void close_geoip(void);
55 
56 static int
_setup(void ** state)57 _setup(void **state) {
58 	isc_result_t result;
59 
60 	UNUSED(state);
61 
62 	result = dns_test_begin(NULL, false);
63 	assert_int_equal(result, ISC_R_SUCCESS);
64 
65 	/* Use databases from the geoip system test */
66 	load_geoip(TEST_GEOIP_DATA);
67 
68 	return (0);
69 }
70 
71 static int
_teardown(void ** state)72 _teardown(void **state) {
73 	UNUSED(state);
74 
75 	close_geoip();
76 
77 	dns_test_end();
78 
79 	return (0);
80 }
81 
82 static dns_geoip_databases_t geoip;
83 #endif /* HAVE_GEOIP || HAVE_GEOIP2 */
84 
85 #if defined(HAVE_GEOIP2)
86 static MMDB_s geoip_country, geoip_city, geoip_as, geoip_isp, geoip_domain;
87 
88 static MMDB_s *
open_geoip2(const char * dir,const char * dbfile,MMDB_s * mmdb)89 open_geoip2(const char *dir, const char *dbfile, MMDB_s *mmdb) {
90 	char pathbuf[PATH_MAX];
91 	int ret;
92 
93 	snprintf(pathbuf, sizeof(pathbuf), "%s/%s", dir, dbfile);
94 	ret = MMDB_open(pathbuf, MMDB_MODE_MMAP, mmdb);
95 	if (ret == MMDB_SUCCESS) {
96 		return (mmdb);
97 	}
98 
99 	return (NULL);
100 }
101 
102 static void
load_geoip(const char * dir)103 load_geoip(const char *dir) {
104 	geoip.country = open_geoip2(dir, "GeoIP2-Country.mmdb",
105 				     &geoip_country);
106 	geoip.city = open_geoip2(dir, "GeoIP2-City.mmdb", &geoip_city);
107 	geoip.as = open_geoip2(dir, "GeoLite2-ASN.mmdb", &geoip_as);
108 	geoip.isp = open_geoip2(dir, "GeoIP2-ISP.mmdb", &geoip_isp);
109 	geoip.domain = open_geoip2(dir, "GeoIP2-Domain.mmdb", &geoip_domain);
110 }
111 
112 static void
close_geoip(void)113 close_geoip(void) {
114 	MMDB_close(&geoip_country);
115 	MMDB_close(&geoip_city);
116 	MMDB_close(&geoip_as);
117 	MMDB_close(&geoip_isp);
118 	MMDB_close(&geoip_domain);
119 }
120 
121 #elif defined(HAVE_GEOIP)
122 /*
123  * Helper functions (mostly copied from bin/named/geoip.c)
124  */
125 
126 static void
init_geoip_db(void ** dbp,GeoIPDBTypes edition,GeoIPDBTypes fallback,GeoIPOptions method,const char * name)127 init_geoip_db(void **dbp, GeoIPDBTypes edition, GeoIPDBTypes fallback,
128 	      GeoIPOptions method, const char *name)
129 {
130 	GeoIP *db;
131 
132 	REQUIRE(dbp != NULL);
133 
134 	db = (GeoIP *)*dbp;
135 
136 	if (db != NULL) {
137 		GeoIP_delete(db);
138 		db = *dbp = NULL;
139 	}
140 
141 	if (! GeoIP_db_avail(edition)) {
142 		goto fail;
143 	}
144 
145 	db = GeoIP_open_type(edition, method);
146 	if (db == NULL) {
147 		goto fail;
148 	}
149 
150 	*dbp = db;
151 	return;
152 
153  fail:
154 	if (fallback != 0) {
155 		init_geoip_db(dbp, fallback, 0, method, name);
156 	}
157 }
158 
159 static void
load_geoip(const char * dir)160 load_geoip(const char *dir) {
161 	GeoIPOptions method;
162 
163 #ifdef _WIN32
164 	method = GEOIP_STANDARD;
165 #else
166 	method = GEOIP_MMAP_CACHE;
167 #endif
168 
169 	if (dir != NULL) {
170 		char *p;
171 		DE_CONST(dir, p);
172 		GeoIP_setup_custom_directory(p);
173 	}
174 
175 	init_geoip_db(&geoip.country_v4, GEOIP_COUNTRY_EDITION, 0,
176 		      method, "Country (IPv4)");
177 #ifdef HAVE_GEOIP_V6
178 	init_geoip_db(&geoip.country_v6, GEOIP_COUNTRY_EDITION_V6, 0,
179 		      method, "Country (IPv6)");
180 #endif
181 
182 	init_geoip_db(&geoip.city_v4, GEOIP_CITY_EDITION_REV1,
183 		      GEOIP_CITY_EDITION_REV0, method, "City (IPv4)");
184 #if defined(HAVE_GEOIP_V6) && defined(HAVE_GEOIP_CITY_V6)
185 	init_geoip_db(&geoip.city_v6, GEOIP_CITY_EDITION_REV1_V6,
186 		      GEOIP_CITY_EDITION_REV0_V6, method, "City (IPv6)");
187 #endif
188 
189 	init_geoip_db(&geoip.region, GEOIP_REGION_EDITION_REV1,
190 		      GEOIP_REGION_EDITION_REV0, method, "Region");
191 	init_geoip_db(&geoip.isp, GEOIP_ISP_EDITION, 0,
192 		      method, "ISP");
193 	init_geoip_db(&geoip.org, GEOIP_ORG_EDITION, 0,
194 		      method, "Org");
195 	init_geoip_db(&geoip.as, GEOIP_ASNUM_EDITION, 0,
196 		      method, "AS");
197 	init_geoip_db(&geoip.domain, GEOIP_DOMAIN_EDITION, 0,
198 		      method, "Domain");
199 	init_geoip_db(&geoip.netspeed, GEOIP_NETSPEED_EDITION, 0,
200 		      method, "NetSpeed");
201 }
202 
203 static void
close_geoip(void)204 close_geoip(void) {
205 	GeoIP_cleanup();
206 }
207 
208 static bool
do_lookup_int(const char * addr,uint8_t * scope,dns_geoip_subtype_t subtype,int id)209 do_lookup_int(const char *addr, uint8_t *scope,
210 	      dns_geoip_subtype_t subtype, int id)
211 {
212 	dns_geoip_elem_t elt;
213 	struct in_addr in4;
214 	isc_netaddr_t na;
215 
216 	inet_pton(AF_INET, addr, &in4);
217 	isc_netaddr_fromin(&na, &in4);
218 
219 	elt.subtype = subtype;
220 	elt.as_int = id;
221 
222 	return (dns_geoip_match(&na, scope, &geoip, &elt));
223 }
224 
225 #endif /* HAVE_GEOIP */
226 
227 #ifdef HAVE_GEOIP2
228 static bool
229 /* Check if an MMDB entry of a given subtype exists for the given IP */
entry_exists(dns_geoip_subtype_t subtype,const char * addr)230 entry_exists(dns_geoip_subtype_t subtype, const char *addr) {
231 	struct in6_addr in6;
232 	struct in_addr in4;
233 	isc_netaddr_t na;
234 	MMDB_s *db;
235 
236 	if (inet_pton(AF_INET6, addr, &in6) == 1) {
237 		isc_netaddr_fromin6(&na, &in6);
238 	} else if (inet_pton(AF_INET, addr, &in4) == 1) {
239 		isc_netaddr_fromin(&na, &in4);
240 	} else {
241 		INSIST(0);
242 		ISC_UNREACHABLE();
243 	}
244 
245 	db = geoip2_database(&geoip, fix_subtype(&geoip, subtype));
246 
247 	return (db != NULL && get_entry_for(db, &na) != NULL);
248 }
249 
250 /*
251  * Baseline test - check if get_entry_for() works as expected, i.e. that its
252  * return values are consistent with the contents of the test MMDBs found in
253  * bin/tests/system/geoip2/data/ (10.53.0.1 and fd92:7065:b8e:ffff::1 should be
254  * present in all databases, 192.0.2.128 should only be present in the country
255  * database, ::1 should be absent from all databases).
256  */
257 static void
baseline(void ** state)258 baseline(void **state) {
259 	dns_geoip_subtype_t subtype;
260 
261 	UNUSED(state);
262 
263 	subtype = dns_geoip_city_name;
264 
265 	assert_true(entry_exists(subtype, "10.53.0.1"));
266 	assert_false(entry_exists(subtype, "192.0.2.128"));
267 	assert_true(entry_exists(subtype, "fd92:7065:b8e:ffff::1"));
268 	assert_false(entry_exists(subtype, "::1"));
269 
270 	subtype = dns_geoip_country_name;
271 
272 	assert_true(entry_exists(subtype, "10.53.0.1"));
273 	assert_true(entry_exists(subtype, "192.0.2.128"));
274 	assert_true(entry_exists(subtype, "fd92:7065:b8e:ffff::1"));
275 	assert_false(entry_exists(subtype, "::1"));
276 
277 	subtype = dns_geoip_domain_name;
278 
279 	assert_true(entry_exists(subtype, "10.53.0.1"));
280 	assert_false(entry_exists(subtype, "192.0.2.128"));
281 	assert_true(entry_exists(subtype, "fd92:7065:b8e:ffff::1"));
282 	assert_false(entry_exists(subtype, "::1"));
283 
284 	subtype = dns_geoip_isp_name;
285 
286 	assert_true(entry_exists(subtype, "10.53.0.1"));
287 	assert_false(entry_exists(subtype, "192.0.2.128"));
288 	assert_true(entry_exists(subtype, "fd92:7065:b8e:ffff::1"));
289 	assert_false(entry_exists(subtype, "::1"));
290 
291 	subtype = dns_geoip_as_asnum;
292 
293 	assert_true(entry_exists(subtype, "10.53.0.1"));
294 	assert_false(entry_exists(subtype, "192.0.2.128"));
295 	assert_true(entry_exists(subtype, "fd92:7065:b8e:ffff::1"));
296 	assert_false(entry_exists(subtype, "::1"));
297 }
298 #endif /* HAVE_GEOIP2 */
299 
300 #if defined(HAVE_GEOIP) || defined(HAVE_GEOIP2)
301 static bool
do_lookup_string(const char * addr,uint8_t * scope,dns_geoip_subtype_t subtype,const char * string)302 do_lookup_string(const char *addr, uint8_t *scope,
303 		 dns_geoip_subtype_t subtype, const char *string)
304 {
305 	dns_geoip_elem_t elt;
306 	struct in_addr in4;
307 	isc_netaddr_t na;
308 	int n;
309 
310 	n = inet_pton(AF_INET, addr, &in4);
311 	assert_int_equal(n, 1);
312 	isc_netaddr_fromin(&na, &in4);
313 
314 	elt.subtype = subtype;
315 	strlcpy(elt.as_string, string, sizeof(elt.as_string));
316 
317 	return (dns_geoip_match(&na, scope, &geoip, &elt));
318 }
319 
320 static bool
do_lookup_string_v6(const char * addr,uint8_t * scope,dns_geoip_subtype_t subtype,const char * string)321 do_lookup_string_v6(const char *addr, uint8_t *scope,
322 		    dns_geoip_subtype_t subtype, const char *string)
323 {
324 	dns_geoip_elem_t elt;
325 	struct in6_addr in6;
326 	isc_netaddr_t na;
327 	int n;
328 
329 	n = inet_pton(AF_INET6, addr, &in6);
330 	assert_int_equal(n, 1);
331 	isc_netaddr_fromin6(&na, &in6);
332 
333 	elt.subtype = subtype;
334 	strlcpy(elt.as_string, string, sizeof(elt.as_string));
335 
336 	return (dns_geoip_match(&na, scope, &geoip, &elt));
337 }
338 
339 /* GeoIP country matching */
340 static void
country(void ** state)341 country(void **state) {
342 	bool match;
343 	uint8_t scope;
344 
345 	UNUSED(state);
346 
347 #ifdef HAVE_GEOIP2
348 	if (geoip.country == NULL) {
349 		skip();
350 	}
351 #else /* HAVE_GEOIP */
352 	if (geoip.country_v4 == NULL) {
353 		skip();
354 	}
355 #endif /* HAVE_GEOIP */
356 
357 	match = do_lookup_string("10.53.0.1", &scope,
358 				 dns_geoip_country_code, "AU");
359 	assert_true(match);
360 	assert_int_equal(scope, 32);
361 
362 	match = do_lookup_string("10.53.0.1", &scope,
363 				 dns_geoip_country_name, "Australia");
364 	assert_true(match);
365 	assert_int_equal(scope, 32);
366 
367 	match = do_lookup_string("192.0.2.128", &scope,
368 				 dns_geoip_country_code, "O1");
369 	assert_true(match);
370 	assert_int_equal(scope, 24);
371 
372 	match = do_lookup_string("192.0.2.128", &scope,
373 				 dns_geoip_country_name, "Other");
374 	assert_true(match);
375 	assert_int_equal(scope, 24);
376 }
377 
378 /* GeoIP country (ipv6) matching */
379 static void
country_v6(void ** state)380 country_v6(void **state) {
381 	bool match;
382 	uint8_t scope;
383 
384 	UNUSED(state);
385 
386 #ifdef HAVE_GEOIP2
387 	if (geoip.country == NULL) {
388 		skip();
389 	}
390 #else /* HAVE_GEOIP */
391 	if (geoip.country_v6 == NULL) {
392 		skip();
393 	}
394 #endif /* HAVE_GEOIP */
395 
396 	match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", &scope,
397 				    dns_geoip_country_code, "AU");
398 	assert_true(match);
399 	assert_int_equal(scope, 128);
400 
401 	match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", &scope,
402 				    dns_geoip_country_name, "Australia");
403 	assert_true(match);
404 	assert_int_equal(scope, 128);
405 }
406 
407 /* GeoIP city (ipv4) matching */
408 static void
city(void ** state)409 city(void **state) {
410 	bool match;
411 
412 	UNUSED(state);
413 
414 #ifdef HAVE_GEOIP2
415 	if (geoip.city == NULL) {
416 		skip();
417 	}
418 #else /* HAVE_GEOIP */
419 	if (geoip.city_v4 == NULL) {
420 		skip();
421 	}
422 #endif /* HAVE_GEOIP */
423 
424 	match = do_lookup_string("10.53.0.1", NULL,
425 				 dns_geoip_city_continentcode, "NA");
426 	assert_true(match);
427 
428 	match = do_lookup_string("10.53.0.1", NULL,
429 				 dns_geoip_city_countrycode, "US");
430 	assert_true(match);
431 
432 	match = do_lookup_string("10.53.0.1", NULL,
433 				 dns_geoip_city_countryname, "United States");
434 	assert_true(match);
435 
436 	match = do_lookup_string("10.53.0.1", NULL,
437 				 dns_geoip_city_region, "CA");
438 	assert_true(match);
439 
440 	match = do_lookup_string("10.53.0.1", NULL,
441 				 dns_geoip_city_regionname, "California");
442 	assert_true(match);
443 
444 	match = do_lookup_string("10.53.0.1", NULL,
445 				 dns_geoip_city_name, "Redwood City");
446 	assert_true(match);
447 
448 	match = do_lookup_string("10.53.0.1", NULL,
449 				 dns_geoip_city_postalcode, "94063");
450 	assert_true(match);
451 
452 #ifdef HAVE_GEOIP
453 	match = do_lookup_int("10.53.0.1", NULL, dns_geoip_city_areacode, 650);
454 	assert_true(match);
455 
456 	match = do_lookup_int("10.53.0.1", NULL, dns_geoip_city_metrocode, 807);
457 	assert_true(match);
458 #endif
459 }
460 
461 /* GeoIP city (ipv6) matching */
462 static void
city_v6(void ** state)463 city_v6(void **state) {
464 	bool match;
465 
466 	UNUSED(state);
467 
468 #ifdef HAVE_GEOIP2
469 	if (geoip.city == NULL) {
470 		skip();
471 	}
472 #else /* HAVE_GEOIP */
473 	if (geoip.city_v6 == NULL) {
474 		skip();
475 	}
476 #endif /* HAVE_GEOIP */
477 
478 	match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
479 				    dns_geoip_city_continentcode, "NA");
480 	assert_true(match);
481 
482 	match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
483 				    dns_geoip_city_countrycode, "US");
484 	assert_true(match);
485 
486 	match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
487 				    dns_geoip_city_countryname,
488 				    "United States");
489 	assert_true(match);
490 
491 	match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
492 				    dns_geoip_city_region, "CA");
493 	assert_true(match);
494 
495 	match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
496 				    dns_geoip_city_regionname, "California");
497 	assert_true(match);
498 
499 	match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
500 				    dns_geoip_city_name, "Redwood City");
501 	assert_true(match);
502 
503 	match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
504 				    dns_geoip_city_postalcode, "94063");
505 	assert_true(match);
506 }
507 
508 /* GeoIP asnum matching */
509 static void
asnum(void ** state)510 asnum(void **state) {
511 	bool match;
512 
513 	UNUSED(state);
514 
515 	if (geoip.as == NULL) {
516 		skip();
517 	}
518 
519 	match = do_lookup_string("10.53.0.3", NULL,
520 				 dns_geoip_as_asnum, "AS100003");
521 	assert_true(match);
522 }
523 
524 /* GeoIP isp matching */
525 static void
isp(void ** state)526 isp(void **state) {
527 	bool match;
528 
529 	UNUSED(state);
530 
531 	if (geoip.isp == NULL) {
532 		skip();
533 	}
534 
535 	match = do_lookup_string("10.53.0.1", NULL, dns_geoip_isp_name,
536 				 "One Systems, Inc.");
537 	assert_true(match);
538 }
539 
540 /* GeoIP org matching */
541 static void
org(void ** state)542 org(void **state) {
543 	bool match;
544 
545 	UNUSED(state);
546 
547 #ifdef HAVE_GEOIP2
548 	if (geoip.as == NULL) {
549 		skip();
550 	}
551 #else /* HAVE_GEOIP */
552 	if (geoip.org == NULL) {
553 		skip();
554 	}
555 #endif /* HAVE_GEOIP */
556 
557 	match = do_lookup_string("10.53.0.2", NULL, dns_geoip_org_name,
558 				 "Two Technology Ltd.");
559 	assert_true(match);
560 }
561 
562 /* GeoIP domain matching */
563 static void
domain(void ** state)564 domain(void **state) {
565 	bool match;
566 
567 	UNUSED(state);
568 
569 	if (geoip.domain == NULL) {
570 		skip();
571 	}
572 
573 	match = do_lookup_string("10.53.0.5", NULL,
574 				 dns_geoip_domain_name, "five.es");
575 	assert_true(match);
576 }
577 #endif /* HAVE_GEOIP || HAVE_GEOIP2 */
578 
579 #ifdef HAVE_GEOIP
580 /* GeoIP region matching */
581 static void
region(void ** state)582 region(void **state) {
583 	bool match;
584 
585 	UNUSED(state);
586 
587 	/* Use databases from the geoip system test */
588 	load_geoip(TEST_GEOIP_DATA);
589 
590 	if (geoip.region == NULL) {
591 		skip();
592 	}
593 
594 	match = do_lookup_string("10.53.0.1", NULL,
595 				 dns_geoip_region_code, "CA");
596 	assert_true(match);
597 
598 	match = do_lookup_string("10.53.0.1", NULL,
599 				 dns_geoip_region_name, "California");
600 	assert_true(match);
601 
602 	match = do_lookup_string("10.53.0.1", NULL,
603 				 dns_geoip_region_countrycode, "US");
604 	assert_true(match);
605 }
606 
607 /* GeoIP netspeed matching */
608 static void
netspeed(void ** state)609 netspeed(void **state) {
610 	bool match;
611 
612 	UNUSED(state);
613 
614 	/* Use databases from the geoip system test */
615 	load_geoip(TEST_GEOIP_DATA);
616 
617 	if (geoip.netspeed == NULL) {
618 		skip();
619 	}
620 
621 	match = do_lookup_int("10.53.0.1", NULL, dns_geoip_netspeed_id, 0);
622 	assert_true(match);
623 
624 	match = do_lookup_int("10.53.0.2", NULL, dns_geoip_netspeed_id, 1);
625 	assert_true(match);
626 
627 	match = do_lookup_int("10.53.0.3", NULL, dns_geoip_netspeed_id, 2);
628 	assert_true(match);
629 
630 	match = do_lookup_int("10.53.0.4", NULL, dns_geoip_netspeed_id, 3);
631 	assert_true(match);
632 }
633 
634 /*
635  * GeoIP best-database matching
636  * (With no specified database and a city database available, answers
637  * should come from city database.  With city database unavailable, region
638  * database.  Region database unavailable, country database.)
639  */
640 static void
best(void ** state)641 best(void **state) {
642 	bool match;
643 
644 	UNUSED(state);
645 
646 	/* Use databases from the geoip system test */
647 	load_geoip(TEST_GEOIP_DATA);
648 
649 	if (geoip.region == NULL) {
650 		skip();
651 	}
652 
653 	match = do_lookup_string("10.53.0.4", NULL,
654 				 dns_geoip_countrycode, "US");
655 	assert_true(match);
656 
657 	match = do_lookup_string("10.53.0.4", NULL,
658 				 dns_geoip_countrycode3, "USA");
659 	assert_true(match);
660 
661 	match = do_lookup_string("10.53.0.4", NULL,
662 				 dns_geoip_countryname, "United States");
663 	assert_true(match);
664 
665 	match = do_lookup_string("10.53.0.4", NULL,
666 				 dns_geoip_regionname, "Virginia");
667 	assert_true(match);
668 
669 	match = do_lookup_string("10.53.0.4", NULL,
670 				 dns_geoip_region, "VA");
671 	assert_true(match);
672 
673 	GeoIP_delete(geoip.city_v4);
674 	geoip.city_v4 = NULL;
675 
676 	match = do_lookup_string("10.53.0.4", NULL,
677 				 dns_geoip_countrycode, "AU");
678 	assert_true(match);
679 
680 	/*
681 	 * Note, region doesn't support code3 or countryname, so
682 	 * the next two would be answered from the country database instead
683 	 */
684 	match = do_lookup_string("10.53.0.4", NULL,
685 				 dns_geoip_countrycode3, "CAN");
686 	assert_true(match);
687 
688 	match = do_lookup_string("10.53.0.4", NULL,
689 				 dns_geoip_countryname, "Canada");
690 	assert_true(match);
691 
692 	GeoIP_delete(geoip.region);
693 	geoip.region = NULL;
694 
695 	match = do_lookup_string("10.53.0.4", NULL,
696 				 dns_geoip_countrycode, "CA");
697 	assert_true(match);
698 
699 	match = do_lookup_string("10.53.0.4", NULL,
700 				 dns_geoip_countrycode3, "CAN");
701 	assert_true(match);
702 
703 	match = do_lookup_string("10.53.0.4", NULL,
704 				 dns_geoip_countryname, "Canada");
705 	assert_true(match);
706 }
707 #endif /* HAVE_GEOIP */
708 
709 int
main(void)710 main(void) {
711 #if defined(HAVE_GEOIP) || defined(HAVE_GEOIP2)
712 	const struct CMUnitTest tests[] = {
713 #ifdef HAVE_GEOIP2
714 		cmocka_unit_test_setup_teardown(baseline, _setup, _teardown),
715 #endif /* HAVE_GEOIP2 */
716 		cmocka_unit_test_setup_teardown(country, _setup, _teardown),
717 		cmocka_unit_test_setup_teardown(country_v6, _setup, _teardown),
718 		cmocka_unit_test_setup_teardown(city, _setup, _teardown),
719 		cmocka_unit_test_setup_teardown(city_v6, _setup, _teardown),
720 		cmocka_unit_test_setup_teardown(asnum, _setup, _teardown),
721 		cmocka_unit_test_setup_teardown(isp, _setup, _teardown),
722 		cmocka_unit_test_setup_teardown(org, _setup, _teardown),
723 		cmocka_unit_test_setup_teardown(domain, _setup, _teardown),
724 #ifdef HAVE_GEOIP
725 		cmocka_unit_test_setup_teardown(region, _setup, _teardown),
726 		cmocka_unit_test_setup_teardown(netspeed, _setup, _teardown),
727 		cmocka_unit_test_setup_teardown(best, _setup, _teardown),
728 #endif /* HAVE_GEOIP */
729 	};
730 
731 	return (cmocka_run_group_tests(tests, dns_test_init, dns_test_final));
732 #else
733 	print_message("1..0 # Skip GeoIP not enabled\n");
734 #endif
735 }
736 
737 #else /* HAVE_CMOCKA */
738 
739 #include <stdio.h>
740 
741 int
main(void)742 main(void) {
743 	printf("1..0 # Skipped: cmocka not available\n");
744 	return (0);
745 }
746 
747 #endif /* HAVE_CMOCKA */
748