1 /* $NetBSD: geoip_test.c,v 1.3 2015/07/08 17:28:59 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2013, 2014 Internet Systems Consortium, Inc. ("ISC") 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* Id */ 20 21 /*! \file */ 22 23 #include <config.h> 24 25 #include <atf-c.h> 26 27 #include <unistd.h> 28 29 #include <isc/types.h> 30 31 #include <dns/geoip.h> 32 33 #include "dnstest.h" 34 35 #ifdef HAVE_GEOIP 36 #include <GeoIP.h> 37 38 /* We use GeoIP databases from the 'geoip' system test */ 39 #define TEST_GEOIP_DATA "../../../bin/tests/system/geoip/data" 40 41 /* 42 * Helper functions 43 * (Mostly copied from bin/named/geoip.c) 44 */ 45 static dns_geoip_databases_t geoip = { 46 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL 47 }; 48 49 static void 50 init_geoip_db(GeoIP **dbp, GeoIPDBTypes edition, GeoIPDBTypes fallback, 51 GeoIPOptions method, const char *name) 52 { 53 char *info; 54 GeoIP *db; 55 56 REQUIRE(dbp != NULL); 57 58 db = *dbp; 59 60 if (db != NULL) { 61 GeoIP_delete(db); 62 db = *dbp = NULL; 63 } 64 65 if (! GeoIP_db_avail(edition)) { 66 fprintf(stderr, "GeoIP %s (type %d) DB not available\n", 67 name, edition); 68 goto fail; 69 } 70 71 fprintf(stderr, "initializing GeoIP %s (type %d) DB\n", 72 name, edition); 73 74 db = GeoIP_open_type(edition, method); 75 if (db == NULL) { 76 fprintf(stderr, 77 "failed to initialize GeoIP %s (type %d) DB%s\n", 78 name, edition, fallback == 0 79 ? "; geoip matches using this database will fail" 80 : ""); 81 goto fail; 82 } 83 84 info = GeoIP_database_info(db); 85 if (info != NULL) 86 fprintf(stderr, "%s\n", info); 87 88 *dbp = db; 89 return; 90 91 fail: 92 if (fallback != 0) 93 init_geoip_db(dbp, fallback, 0, method, name); 94 } 95 96 static void 97 load_geoip(const char *dir) { 98 GeoIPOptions method; 99 100 #ifdef _WIN32 101 method = GEOIP_STANDARD; 102 #else 103 method = GEOIP_MMAP_CACHE; 104 #endif 105 106 if (dir != NULL) { 107 char *p; 108 DE_CONST(dir, p); 109 GeoIP_setup_custom_directory(p); 110 } 111 112 init_geoip_db(&geoip.country_v4, GEOIP_COUNTRY_EDITION, 0, 113 method, "Country (IPv4)"); 114 #ifdef HAVE_GEOIP_V6 115 init_geoip_db(&geoip.country_v6, GEOIP_COUNTRY_EDITION_V6, 0, 116 method, "Country (IPv6)"); 117 #endif 118 119 init_geoip_db(&geoip.city_v4, GEOIP_CITY_EDITION_REV1, 120 GEOIP_CITY_EDITION_REV0, method, "City (IPv4)"); 121 #if defined(HAVE_GEOIP_V6) && defined(HAVE_GEOIP_CITY_V6) 122 init_geoip_db(&geoip.city_v6, GEOIP_CITY_EDITION_REV1_V6, 123 GEOIP_CITY_EDITION_REV0_V6, method, "City (IPv6)"); 124 #endif 125 126 init_geoip_db(&geoip.region, GEOIP_REGION_EDITION_REV1, 127 GEOIP_REGION_EDITION_REV0, method, "Region"); 128 init_geoip_db(&geoip.isp, GEOIP_ISP_EDITION, 0, 129 method, "ISP"); 130 init_geoip_db(&geoip.org, GEOIP_ORG_EDITION, 0, 131 method, "Org"); 132 init_geoip_db(&geoip.as, GEOIP_ASNUM_EDITION, 0, 133 method, "AS"); 134 init_geoip_db(&geoip.domain, GEOIP_DOMAIN_EDITION, 0, 135 method, "Domain"); 136 init_geoip_db(&geoip.netspeed, GEOIP_NETSPEED_EDITION, 0, 137 method, "NetSpeed"); 138 } 139 140 static isc_boolean_t 141 do_lookup_string(const char *addr, dns_geoip_subtype_t subtype, 142 const char *string) 143 { 144 dns_geoip_elem_t elt; 145 struct in_addr in4; 146 isc_netaddr_t na; 147 148 inet_pton(AF_INET, addr, &in4); 149 isc_netaddr_fromin(&na, &in4); 150 151 elt.subtype = subtype; 152 strcpy(elt.as_string, string); 153 154 return (dns_geoip_match(&na, &geoip, &elt)); 155 } 156 157 static isc_boolean_t 158 do_lookup_string_v6(const char *addr, dns_geoip_subtype_t subtype, 159 const char *string) 160 { 161 dns_geoip_elem_t elt; 162 struct in6_addr in6; 163 isc_netaddr_t na; 164 165 inet_pton(AF_INET6, addr, &in6); 166 isc_netaddr_fromin6(&na, &in6); 167 168 elt.subtype = subtype; 169 strcpy(elt.as_string, string); 170 171 return (dns_geoip_match(&na, &geoip, &elt)); 172 } 173 174 static isc_boolean_t 175 do_lookup_int(const char *addr, dns_geoip_subtype_t subtype, int id) { 176 dns_geoip_elem_t elt; 177 struct in_addr in4; 178 isc_netaddr_t na; 179 180 inet_pton(AF_INET, addr, &in4); 181 isc_netaddr_fromin(&na, &in4); 182 183 elt.subtype = subtype; 184 elt.as_int = id; 185 186 return (dns_geoip_match(&na, &geoip, &elt)); 187 } 188 189 /* 190 * Individual unit tests 191 */ 192 193 /* GeoIP country matching */ 194 ATF_TC(country); 195 ATF_TC_HEAD(country, tc) { 196 atf_tc_set_md_var(tc, "descr", "test country database matching"); 197 } 198 ATF_TC_BODY(country, tc) { 199 isc_result_t result; 200 isc_boolean_t match; 201 202 UNUSED(tc); 203 204 result = dns_test_begin(NULL, ISC_TRUE); 205 ATF_REQUIRE(result == ISC_R_SUCCESS); 206 207 /* Use databases from the geoip system test */ 208 load_geoip(TEST_GEOIP_DATA); 209 210 if (geoip.country_v4 == NULL) { 211 dns_test_end(); 212 atf_tc_skip("Database not available"); 213 } 214 215 match = do_lookup_string("10.53.0.1", dns_geoip_country_code, "AU"); 216 ATF_CHECK(match); 217 218 match = do_lookup_string("10.53.0.1", 219 dns_geoip_country_code3, "AUS"); 220 ATF_CHECK(match); 221 222 match = do_lookup_string("10.53.0.1", 223 dns_geoip_country_name, "Australia"); 224 ATF_CHECK(match); 225 226 dns_test_end(); 227 } 228 229 /* GeoIP country (ipv6) matching */ 230 ATF_TC(country_v6); 231 ATF_TC_HEAD(country_v6, tc) { 232 atf_tc_set_md_var(tc, "descr", "test country (ipv6) database matching"); 233 } 234 ATF_TC_BODY(country_v6, tc) { 235 isc_result_t result; 236 isc_boolean_t match; 237 238 UNUSED(tc); 239 240 result = dns_test_begin(NULL, ISC_TRUE); 241 ATF_REQUIRE(result == ISC_R_SUCCESS); 242 243 /* Use databases from the geoip system test */ 244 load_geoip(TEST_GEOIP_DATA); 245 246 if (geoip.country_v6 == NULL) { 247 dns_test_end(); 248 atf_tc_skip("Database not available"); 249 } 250 251 match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", 252 dns_geoip_country_code, "AU"); 253 ATF_CHECK(match); 254 255 match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", 256 dns_geoip_country_code3, "AUS"); 257 ATF_CHECK(match); 258 259 match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", 260 dns_geoip_country_name, "Australia"); 261 ATF_CHECK(match); 262 263 dns_test_end(); 264 } 265 266 /* GeoIP city (ipv4) matching */ 267 ATF_TC(city); 268 ATF_TC_HEAD(city, tc) { 269 atf_tc_set_md_var(tc, "descr", "test city database matching"); 270 } 271 ATF_TC_BODY(city, tc) { 272 isc_result_t result; 273 isc_boolean_t match; 274 275 UNUSED(tc); 276 277 result = dns_test_begin(NULL, ISC_TRUE); 278 ATF_REQUIRE(result == ISC_R_SUCCESS); 279 280 /* Use databases from the geoip system test */ 281 load_geoip(TEST_GEOIP_DATA); 282 283 if (geoip.city_v4 == NULL) { 284 dns_test_end(); 285 atf_tc_skip("Database not available"); 286 } 287 288 match = do_lookup_string("10.53.0.1", 289 dns_geoip_city_continentcode, "NA"); 290 ATF_CHECK(match); 291 292 match = do_lookup_string("10.53.0.1", 293 dns_geoip_city_countrycode, "US"); 294 ATF_CHECK(match); 295 296 match = do_lookup_string("10.53.0.1", 297 dns_geoip_city_countrycode3, "USA"); 298 ATF_CHECK(match); 299 300 match = do_lookup_string("10.53.0.1", 301 dns_geoip_city_countryname, "United States"); 302 ATF_CHECK(match); 303 304 match = do_lookup_string("10.53.0.1", 305 dns_geoip_city_region, "CA"); 306 ATF_CHECK(match); 307 308 match = do_lookup_string("10.53.0.1", 309 dns_geoip_city_regionname, "California"); 310 ATF_CHECK(match); 311 312 match = do_lookup_string("10.53.0.1", 313 dns_geoip_city_name, "Redwood City"); 314 ATF_CHECK(match); 315 316 match = do_lookup_string("10.53.0.1", 317 dns_geoip_city_postalcode, "94063"); 318 ATF_CHECK(match); 319 320 match = do_lookup_int("10.53.0.1", dns_geoip_city_areacode, 650); 321 ATF_CHECK(match); 322 323 match = do_lookup_int("10.53.0.1", dns_geoip_city_metrocode, 807); 324 ATF_CHECK(match); 325 326 dns_test_end(); 327 } 328 329 /* GeoIP city (ipv6) matching */ 330 ATF_TC(city_v6); 331 ATF_TC_HEAD(city_v6, tc) { 332 atf_tc_set_md_var(tc, "descr", "test city (ipv6) database matching"); 333 } 334 ATF_TC_BODY(city_v6, tc) { 335 isc_result_t result; 336 isc_boolean_t match; 337 338 UNUSED(tc); 339 340 result = dns_test_begin(NULL, ISC_TRUE); 341 ATF_REQUIRE(result == ISC_R_SUCCESS); 342 343 /* Use databases from the geoip system test */ 344 load_geoip(TEST_GEOIP_DATA); 345 346 if (geoip.city_v6 == NULL) { 347 dns_test_end(); 348 atf_tc_skip("Database not available"); 349 } 350 351 match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", 352 dns_geoip_city_continentcode, "NA"); 353 ATF_CHECK(match); 354 355 match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", 356 dns_geoip_city_countrycode, "US"); 357 ATF_CHECK(match); 358 359 match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", 360 dns_geoip_city_countrycode3, "USA"); 361 ATF_CHECK(match); 362 363 match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", 364 dns_geoip_city_countryname, 365 "United States"); 366 ATF_CHECK(match); 367 368 match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", 369 dns_geoip_city_region, "CA"); 370 ATF_CHECK(match); 371 372 match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", 373 dns_geoip_city_regionname, "California"); 374 ATF_CHECK(match); 375 376 match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", 377 dns_geoip_city_name, "Redwood City"); 378 ATF_CHECK(match); 379 380 match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", 381 dns_geoip_city_postalcode, "94063"); 382 ATF_CHECK(match); 383 384 dns_test_end(); 385 } 386 387 388 /* GeoIP region matching */ 389 ATF_TC(region); 390 ATF_TC_HEAD(region, tc) { 391 atf_tc_set_md_var(tc, "descr", "test region database matching"); 392 } 393 ATF_TC_BODY(region, tc) { 394 isc_result_t result; 395 isc_boolean_t match; 396 397 UNUSED(tc); 398 399 result = dns_test_begin(NULL, ISC_TRUE); 400 ATF_REQUIRE(result == ISC_R_SUCCESS); 401 402 /* Use databases from the geoip system test */ 403 load_geoip(TEST_GEOIP_DATA); 404 405 if (geoip.region == NULL) { 406 dns_test_end(); 407 atf_tc_skip("Database not available"); 408 } 409 410 match = do_lookup_string("10.53.0.1", 411 dns_geoip_region_code, "CA"); 412 ATF_CHECK(match); 413 414 match = do_lookup_string("10.53.0.1", 415 dns_geoip_region_name, "California"); 416 ATF_CHECK(match); 417 418 match = do_lookup_string("10.53.0.1", 419 dns_geoip_region_countrycode, "US"); 420 ATF_CHECK(match); 421 422 dns_test_end(); 423 } 424 425 /* 426 * GeoIP best-database matching 427 * (With no specified databse and a city database available, answers 428 * should come from city database. With city database unavailable, region 429 * database. Region database unavailable, country database.) 430 */ 431 ATF_TC(best); 432 ATF_TC_HEAD(best, tc) { 433 atf_tc_set_md_var(tc, "descr", "test best database matching"); 434 } 435 ATF_TC_BODY(best, tc) { 436 isc_result_t result; 437 isc_boolean_t match; 438 439 UNUSED(tc); 440 441 result = dns_test_begin(NULL, ISC_TRUE); 442 ATF_REQUIRE(result == ISC_R_SUCCESS); 443 444 /* Use databases from the geoip system test */ 445 load_geoip(TEST_GEOIP_DATA); 446 447 if (geoip.region == NULL) { 448 dns_test_end(); 449 atf_tc_skip("Database not available"); 450 } 451 452 match = do_lookup_string("10.53.0.4", 453 dns_geoip_countrycode, "US"); 454 ATF_CHECK(match); 455 456 match = do_lookup_string("10.53.0.4", 457 dns_geoip_countrycode3, "USA"); 458 ATF_CHECK(match); 459 460 match = do_lookup_string("10.53.0.4", 461 dns_geoip_countryname, "United States"); 462 ATF_CHECK(match); 463 464 match = do_lookup_string("10.53.0.4", 465 dns_geoip_regionname, "Virginia"); 466 ATF_CHECK(match); 467 468 match = do_lookup_string("10.53.0.4", 469 dns_geoip_region, "VA"); 470 ATF_CHECK(match); 471 472 GeoIP_delete(geoip.city_v4); 473 geoip.city_v4 = NULL; 474 475 match = do_lookup_string("10.53.0.4", 476 dns_geoip_countrycode, "AU"); 477 ATF_CHECK(match); 478 479 /* 480 * Note, region doesn't support code3 or countryname, so 481 * the next two would be answered from the country database instead 482 */ 483 match = do_lookup_string("10.53.0.4", 484 dns_geoip_countrycode3, "CAN"); 485 ATF_CHECK(match); 486 487 match = do_lookup_string("10.53.0.4", 488 dns_geoip_countryname, "Canada"); 489 ATF_CHECK(match); 490 491 GeoIP_delete(geoip.region); 492 geoip.region = NULL; 493 494 match = do_lookup_string("10.53.0.4", 495 dns_geoip_countrycode, "CA"); 496 ATF_CHECK(match); 497 498 match = do_lookup_string("10.53.0.4", 499 dns_geoip_countrycode3, "CAN"); 500 ATF_CHECK(match); 501 502 match = do_lookup_string("10.53.0.4", 503 dns_geoip_countryname, "Canada"); 504 ATF_CHECK(match); 505 506 dns_test_end(); 507 } 508 509 510 /* GeoIP asnum matching */ 511 ATF_TC(asnum); 512 ATF_TC_HEAD(asnum, tc) { 513 atf_tc_set_md_var(tc, "descr", "test asnum database matching"); 514 } 515 ATF_TC_BODY(asnum, tc) { 516 isc_result_t result; 517 isc_boolean_t match; 518 519 UNUSED(tc); 520 521 result = dns_test_begin(NULL, ISC_TRUE); 522 ATF_REQUIRE(result == ISC_R_SUCCESS); 523 524 /* Use databases from the geoip system test */ 525 load_geoip(TEST_GEOIP_DATA); 526 527 if (geoip.as == NULL) { 528 dns_test_end(); 529 atf_tc_skip("Database not available"); 530 } 531 532 533 match = do_lookup_string("10.53.0.3", dns_geoip_as_asnum, 534 "AS100003 Three Network Labs"); 535 ATF_CHECK(match); 536 537 dns_test_end(); 538 } 539 540 /* GeoIP isp matching */ 541 ATF_TC(isp); 542 ATF_TC_HEAD(isp, tc) { 543 atf_tc_set_md_var(tc, "descr", "test isp database matching"); 544 } 545 ATF_TC_BODY(isp, tc) { 546 isc_result_t result; 547 isc_boolean_t match; 548 549 UNUSED(tc); 550 551 result = dns_test_begin(NULL, ISC_TRUE); 552 ATF_REQUIRE(result == ISC_R_SUCCESS); 553 554 /* Use databases from the geoip system test */ 555 load_geoip(TEST_GEOIP_DATA); 556 557 if (geoip.isp == NULL) { 558 dns_test_end(); 559 atf_tc_skip("Database not available"); 560 } 561 562 match = do_lookup_string("10.53.0.1", dns_geoip_isp_name, 563 "One Systems, Inc."); 564 ATF_CHECK(match); 565 566 dns_test_end(); 567 } 568 569 /* GeoIP org matching */ 570 ATF_TC(org); 571 ATF_TC_HEAD(org, tc) { 572 atf_tc_set_md_var(tc, "descr", "test org database matching"); 573 } 574 ATF_TC_BODY(org, tc) { 575 isc_result_t result; 576 isc_boolean_t match; 577 578 UNUSED(tc); 579 580 result = dns_test_begin(NULL, ISC_TRUE); 581 ATF_REQUIRE(result == ISC_R_SUCCESS); 582 583 /* Use databases from the geoip system test */ 584 load_geoip(TEST_GEOIP_DATA); 585 586 if (geoip.org == NULL) { 587 dns_test_end(); 588 atf_tc_skip("Database not available"); 589 } 590 591 match = do_lookup_string("10.53.0.2", dns_geoip_org_name, 592 "Two Technology Ltd."); 593 ATF_CHECK(match); 594 595 dns_test_end(); 596 } 597 598 /* GeoIP domain matching */ 599 ATF_TC(domain); 600 ATF_TC_HEAD(domain, tc) { 601 atf_tc_set_md_var(tc, "descr", "test domain database matching"); 602 } 603 ATF_TC_BODY(domain, tc) { 604 isc_result_t result; 605 isc_boolean_t match; 606 607 UNUSED(tc); 608 609 result = dns_test_begin(NULL, ISC_TRUE); 610 ATF_REQUIRE(result == ISC_R_SUCCESS); 611 612 /* Use databases from the geoip system test */ 613 load_geoip(TEST_GEOIP_DATA); 614 615 if (geoip.domain == NULL) { 616 dns_test_end(); 617 atf_tc_skip("Database not available"); 618 } 619 620 match = do_lookup_string("10.53.0.4", 621 dns_geoip_domain_name, "four.com"); 622 ATF_CHECK(match); 623 624 dns_test_end(); 625 } 626 627 /* GeoIP netspeed matching */ 628 ATF_TC(netspeed); 629 ATF_TC_HEAD(netspeed, tc) { 630 atf_tc_set_md_var(tc, "descr", "test netspeed database matching"); 631 } 632 ATF_TC_BODY(netspeed, tc) { 633 isc_result_t result; 634 isc_boolean_t match; 635 636 UNUSED(tc); 637 638 result = dns_test_begin(NULL, ISC_TRUE); 639 ATF_REQUIRE(result == ISC_R_SUCCESS); 640 641 /* Use databases from the geoip system test */ 642 load_geoip(TEST_GEOIP_DATA); 643 644 if (geoip.netspeed == NULL) { 645 dns_test_end(); 646 atf_tc_skip("Database not available"); 647 } 648 649 match = do_lookup_int("10.53.0.1", dns_geoip_netspeed_id, 0); 650 ATF_CHECK(match); 651 652 match = do_lookup_int("10.53.0.2", dns_geoip_netspeed_id, 1); 653 ATF_CHECK(match); 654 655 match = do_lookup_int("10.53.0.3", dns_geoip_netspeed_id, 2); 656 ATF_CHECK(match); 657 658 match = do_lookup_int("10.53.0.4", dns_geoip_netspeed_id, 3); 659 ATF_CHECK(match); 660 661 dns_test_end(); 662 } 663 #else 664 ATF_TC(untested); 665 ATF_TC_HEAD(untested, tc) { 666 atf_tc_set_md_var(tc, "descr", "skipping geoip test"); 667 } 668 ATF_TC_BODY(untested, tc) { 669 UNUSED(tc); 670 atf_tc_skip("GeoIP not available"); 671 } 672 #endif 673 674 /* 675 * Main 676 */ 677 ATF_TP_ADD_TCS(tp) { 678 #ifdef HAVE_GEOIP 679 ATF_TP_ADD_TC(tp, country); 680 ATF_TP_ADD_TC(tp, country_v6); 681 ATF_TP_ADD_TC(tp, city); 682 ATF_TP_ADD_TC(tp, city_v6); 683 ATF_TP_ADD_TC(tp, region); 684 ATF_TP_ADD_TC(tp, best); 685 ATF_TP_ADD_TC(tp, asnum); 686 ATF_TP_ADD_TC(tp, isp); 687 ATF_TP_ADD_TC(tp, org); 688 ATF_TP_ADD_TC(tp, domain); 689 ATF_TP_ADD_TC(tp, netspeed); 690 #else 691 ATF_TP_ADD_TC(tp, untested); 692 #endif 693 694 return (atf_no_error()); 695 } 696 697