summaryrefslogtreecommitdiffstats
path: root/lib/dns/tests/geoip_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dns/tests/geoip_test.c')
-rw-r--r--lib/dns/tests/geoip_test.c711
1 files changed, 711 insertions, 0 deletions
diff --git a/lib/dns/tests/geoip_test.c b/lib/dns/tests/geoip_test.c
new file mode 100644
index 0000000..4e8a5f0
--- /dev/null
+++ b/lib/dns/tests/geoip_test.c
@@ -0,0 +1,711 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*! \file */
+
+#include <config.h>
+
+#include <atf-c.h>
+
+#include <stdbool.h>
+#include <unistd.h>
+
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/types.h>
+
+#include <dns/geoip.h>
+
+#include "dnstest.h"
+
+#ifdef HAVE_GEOIP
+#include <GeoIP.h>
+
+/* We use GeoIP databases from the 'geoip' system test */
+#define TEST_GEOIP_DATA "../../../bin/tests/system/geoip/data"
+
+/*
+ * Helper functions
+ * (Mostly copied from bin/named/geoip.c)
+ */
+static dns_geoip_databases_t geoip = {
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static void
+init_geoip_db(GeoIP **dbp, GeoIPDBTypes edition, GeoIPDBTypes fallback,
+ GeoIPOptions method, const char *name)
+{
+ char *info;
+ GeoIP *db;
+
+ REQUIRE(dbp != NULL);
+
+ db = *dbp;
+
+ if (db != NULL) {
+ GeoIP_delete(db);
+ db = *dbp = NULL;
+ }
+
+ if (! GeoIP_db_avail(edition)) {
+ fprintf(stderr, "GeoIP %s (type %d) DB not available\n",
+ name, edition);
+ goto fail;
+ }
+
+ fprintf(stderr, "initializing GeoIP %s (type %d) DB\n",
+ name, edition);
+
+ db = GeoIP_open_type(edition, method);
+ if (db == NULL) {
+ fprintf(stderr,
+ "failed to initialize GeoIP %s (type %d) DB%s\n",
+ name, edition, fallback == 0
+ ? "; geoip matches using this database will fail"
+ : "");
+ goto fail;
+ }
+
+ info = GeoIP_database_info(db);
+ if (info != NULL)
+ fprintf(stderr, "%s\n", info);
+
+ *dbp = db;
+ return;
+
+ fail:
+ if (fallback != 0)
+ init_geoip_db(dbp, fallback, 0, method, name);
+}
+
+static void
+load_geoip(const char *dir) {
+ GeoIPOptions method;
+
+#ifdef _WIN32
+ method = GEOIP_STANDARD;
+#else
+ method = GEOIP_MMAP_CACHE;
+#endif
+
+ if (dir != NULL) {
+ char *p;
+ DE_CONST(dir, p);
+ GeoIP_setup_custom_directory(p);
+ }
+
+ init_geoip_db(&geoip.country_v4, GEOIP_COUNTRY_EDITION, 0,
+ method, "Country (IPv4)");
+#ifdef HAVE_GEOIP_V6
+ init_geoip_db(&geoip.country_v6, GEOIP_COUNTRY_EDITION_V6, 0,
+ method, "Country (IPv6)");
+#endif
+
+ init_geoip_db(&geoip.city_v4, GEOIP_CITY_EDITION_REV1,
+ GEOIP_CITY_EDITION_REV0, method, "City (IPv4)");
+#if defined(HAVE_GEOIP_V6) && defined(HAVE_GEOIP_CITY_V6)
+ init_geoip_db(&geoip.city_v6, GEOIP_CITY_EDITION_REV1_V6,
+ GEOIP_CITY_EDITION_REV0_V6, method, "City (IPv6)");
+#endif
+
+ init_geoip_db(&geoip.region, GEOIP_REGION_EDITION_REV1,
+ GEOIP_REGION_EDITION_REV0, method, "Region");
+ init_geoip_db(&geoip.isp, GEOIP_ISP_EDITION, 0,
+ method, "ISP");
+ init_geoip_db(&geoip.org, GEOIP_ORG_EDITION, 0,
+ method, "Org");
+ init_geoip_db(&geoip.as, GEOIP_ASNUM_EDITION, 0,
+ method, "AS");
+ init_geoip_db(&geoip.domain, GEOIP_DOMAIN_EDITION, 0,
+ method, "Domain");
+ init_geoip_db(&geoip.netspeed, GEOIP_NETSPEED_EDITION, 0,
+ method, "NetSpeed");
+}
+
+static bool
+do_lookup_string(const char *addr, uint8_t *scope,
+ dns_geoip_subtype_t subtype, const char *string)
+{
+ dns_geoip_elem_t elt;
+ struct in_addr in4;
+ isc_netaddr_t na;
+
+ inet_pton(AF_INET, addr, &in4);
+ isc_netaddr_fromin(&na, &in4);
+
+ elt.subtype = subtype;
+ strlcpy(elt.as_string, string, sizeof(elt.as_string));
+
+ return (dns_geoip_match(&na, scope, &geoip, &elt));
+}
+
+static bool
+do_lookup_string_v6(const char *addr, uint8_t *scope,
+ dns_geoip_subtype_t subtype, const char *string)
+{
+ dns_geoip_elem_t elt;
+ struct in6_addr in6;
+ isc_netaddr_t na;
+
+ inet_pton(AF_INET6, addr, &in6);
+ isc_netaddr_fromin6(&na, &in6);
+
+ elt.subtype = subtype;
+ strlcpy(elt.as_string, string, sizeof(elt.as_string));
+
+ return (dns_geoip_match(&na, scope, &geoip, &elt));
+}
+
+static bool
+do_lookup_int(const char *addr, uint8_t *scope,
+ dns_geoip_subtype_t subtype, int id)
+{
+ dns_geoip_elem_t elt;
+ struct in_addr in4;
+ isc_netaddr_t na;
+
+ inet_pton(AF_INET, addr, &in4);
+ isc_netaddr_fromin(&na, &in4);
+
+ elt.subtype = subtype;
+ elt.as_int = id;
+
+ return (dns_geoip_match(&na, scope, &geoip, &elt));
+}
+
+/*
+ * Individual unit tests
+ */
+
+/* GeoIP country matching */
+ATF_TC(country);
+ATF_TC_HEAD(country, tc) {
+ atf_tc_set_md_var(tc, "descr", "test country database matching");
+}
+ATF_TC_BODY(country, tc) {
+ isc_result_t result;
+ bool match;
+ uint8_t scope;
+
+ UNUSED(tc);
+
+ result = dns_test_begin(NULL, true);
+ ATF_REQUIRE(result == ISC_R_SUCCESS);
+
+ /* Use databases from the geoip system test */
+ load_geoip(TEST_GEOIP_DATA);
+
+ if (geoip.country_v4 == NULL) {
+ dns_test_end();
+ atf_tc_skip("Database not available");
+ }
+
+ match = do_lookup_string("10.53.0.1", &scope,
+ dns_geoip_country_code, "AU");
+ ATF_CHECK(match);
+ ATF_CHECK_EQ(scope, 32);
+
+ match = do_lookup_string("10.53.0.1", &scope,
+ dns_geoip_country_code3, "AUS");
+ ATF_CHECK(match);
+ ATF_CHECK_EQ(scope, 32);
+
+ match = do_lookup_string("10.53.0.1", &scope,
+ dns_geoip_country_name, "Australia");
+ ATF_CHECK(match);
+ ATF_CHECK_EQ(scope, 32);
+
+ match = do_lookup_string("192.0.2.128", &scope,
+ dns_geoip_country_code, "O1");
+ ATF_CHECK(match);
+ ATF_CHECK_EQ(scope, 24);
+
+ match = do_lookup_string("192.0.2.128", &scope,
+ dns_geoip_country_name, "Other");
+ ATF_CHECK(match);
+ ATF_CHECK_EQ(scope, 24);
+
+ dns_test_end();
+}
+
+/* GeoIP country (ipv6) matching */
+ATF_TC(country_v6);
+ATF_TC_HEAD(country_v6, tc) {
+ atf_tc_set_md_var(tc, "descr", "test country (ipv6) database matching");
+}
+ATF_TC_BODY(country_v6, tc) {
+ isc_result_t result;
+ bool match;
+ uint8_t scope;
+
+ UNUSED(tc);
+
+ result = dns_test_begin(NULL, true);
+ ATF_REQUIRE(result == ISC_R_SUCCESS);
+
+ /* Use databases from the geoip system test */
+ load_geoip(TEST_GEOIP_DATA);
+
+ if (geoip.country_v6 == NULL) {
+ dns_test_end();
+ atf_tc_skip("Database not available");
+ }
+
+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", &scope,
+ dns_geoip_country_code, "AU");
+ ATF_CHECK(match);
+ ATF_CHECK_EQ(scope, 128);
+
+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", &scope,
+ dns_geoip_country_code3, "AUS");
+ ATF_CHECK(match);
+ ATF_CHECK_EQ(scope, 128);
+
+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", &scope,
+ dns_geoip_country_name, "Australia");
+ ATF_CHECK(match);
+ ATF_CHECK_EQ(scope, 128);
+
+ dns_test_end();
+}
+
+/* GeoIP city (ipv4) matching */
+ATF_TC(city);
+ATF_TC_HEAD(city, tc) {
+ atf_tc_set_md_var(tc, "descr", "test city database matching");
+}
+ATF_TC_BODY(city, tc) {
+ isc_result_t result;
+ bool match;
+
+ UNUSED(tc);
+
+ result = dns_test_begin(NULL, true);
+ ATF_REQUIRE(result == ISC_R_SUCCESS);
+
+ /* Use databases from the geoip system test */
+ load_geoip(TEST_GEOIP_DATA);
+
+ if (geoip.city_v4 == NULL) {
+ dns_test_end();
+ atf_tc_skip("Database not available");
+ }
+
+ match = do_lookup_string("10.53.0.1", NULL,
+ dns_geoip_city_continentcode, "NA");
+ ATF_CHECK(match);
+
+ match = do_lookup_string("10.53.0.1", NULL,
+ dns_geoip_city_countrycode, "US");
+ ATF_CHECK(match);
+
+ match = do_lookup_string("10.53.0.1", NULL,
+ dns_geoip_city_countrycode3, "USA");
+ ATF_CHECK(match);
+
+ match = do_lookup_string("10.53.0.1", NULL,
+ dns_geoip_city_countryname, "United States");
+ ATF_CHECK(match);
+
+ match = do_lookup_string("10.53.0.1", NULL,
+ dns_geoip_city_region, "CA");
+ ATF_CHECK(match);
+
+ match = do_lookup_string("10.53.0.1", NULL,
+ dns_geoip_city_regionname, "California");
+ ATF_CHECK(match);
+
+ match = do_lookup_string("10.53.0.1", NULL,
+ dns_geoip_city_name, "Redwood City");
+ ATF_CHECK(match);
+
+ match = do_lookup_string("10.53.0.1", NULL,
+ dns_geoip_city_postalcode, "94063");
+ ATF_CHECK(match);
+
+ match = do_lookup_int("10.53.0.1", NULL, dns_geoip_city_areacode, 650);
+ ATF_CHECK(match);
+
+ match = do_lookup_int("10.53.0.1", NULL, dns_geoip_city_metrocode, 807);
+ ATF_CHECK(match);
+
+ dns_test_end();
+}
+
+/* GeoIP city (ipv6) matching */
+ATF_TC(city_v6);
+ATF_TC_HEAD(city_v6, tc) {
+ atf_tc_set_md_var(tc, "descr", "test city (ipv6) database matching");
+}
+ATF_TC_BODY(city_v6, tc) {
+ isc_result_t result;
+ bool match;
+
+ UNUSED(tc);
+
+ result = dns_test_begin(NULL, true);
+ ATF_REQUIRE(result == ISC_R_SUCCESS);
+
+ /* Use databases from the geoip system test */
+ load_geoip(TEST_GEOIP_DATA);
+
+ if (geoip.city_v6 == NULL) {
+ dns_test_end();
+ atf_tc_skip("Database not available");
+ }
+
+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
+ dns_geoip_city_continentcode, "NA");
+ ATF_CHECK(match);
+
+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
+ dns_geoip_city_countrycode, "US");
+ ATF_CHECK(match);
+
+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
+ dns_geoip_city_countrycode3, "USA");
+ ATF_CHECK(match);
+
+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
+ dns_geoip_city_countryname,
+ "United States");
+ ATF_CHECK(match);
+
+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
+ dns_geoip_city_region, "CA");
+ ATF_CHECK(match);
+
+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
+ dns_geoip_city_regionname, "California");
+ ATF_CHECK(match);
+
+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
+ dns_geoip_city_name, "Redwood City");
+ ATF_CHECK(match);
+
+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
+ dns_geoip_city_postalcode, "94063");
+ ATF_CHECK(match);
+
+ dns_test_end();
+}
+
+
+/* GeoIP region matching */
+ATF_TC(region);
+ATF_TC_HEAD(region, tc) {
+ atf_tc_set_md_var(tc, "descr", "test region database matching");
+}
+ATF_TC_BODY(region, tc) {
+ isc_result_t result;
+ bool match;
+
+ UNUSED(tc);
+
+ result = dns_test_begin(NULL, true);
+ ATF_REQUIRE(result == ISC_R_SUCCESS);
+
+ /* Use databases from the geoip system test */
+ load_geoip(TEST_GEOIP_DATA);
+
+ if (geoip.region == NULL) {
+ dns_test_end();
+ atf_tc_skip("Database not available");
+ }
+
+ match = do_lookup_string("10.53.0.1", NULL,
+ dns_geoip_region_code, "CA");
+ ATF_CHECK(match);
+
+ match = do_lookup_string("10.53.0.1", NULL,
+ dns_geoip_region_name, "California");
+ ATF_CHECK(match);
+
+ match = do_lookup_string("10.53.0.1", NULL,
+ dns_geoip_region_countrycode, "US");
+ ATF_CHECK(match);
+
+ dns_test_end();
+}
+
+/*
+ * GeoIP best-database matching
+ * (With no specified databse and a city database available, answers
+ * should come from city database. With city database unavailable, region
+ * database. Region database unavailable, country database.)
+ */
+ATF_TC(best);
+ATF_TC_HEAD(best, tc) {
+ atf_tc_set_md_var(tc, "descr", "test best database matching");
+}
+ATF_TC_BODY(best, tc) {
+ isc_result_t result;
+ bool match;
+
+ UNUSED(tc);
+
+ result = dns_test_begin(NULL, true);
+ ATF_REQUIRE(result == ISC_R_SUCCESS);
+
+ /* Use databases from the geoip system test */
+ load_geoip(TEST_GEOIP_DATA);
+
+ if (geoip.region == NULL) {
+ dns_test_end();
+ atf_tc_skip("Database not available");
+ }
+
+ match = do_lookup_string("10.53.0.4", NULL,
+ dns_geoip_countrycode, "US");
+ ATF_CHECK(match);
+
+ match = do_lookup_string("10.53.0.4", NULL,
+ dns_geoip_countrycode3, "USA");
+ ATF_CHECK(match);
+
+ match = do_lookup_string("10.53.0.4", NULL,
+ dns_geoip_countryname, "United States");
+ ATF_CHECK(match);
+
+ match = do_lookup_string("10.53.0.4", NULL,
+ dns_geoip_regionname, "Virginia");
+ ATF_CHECK(match);
+
+ match = do_lookup_string("10.53.0.4", NULL,
+ dns_geoip_region, "VA");
+ ATF_CHECK(match);
+
+ GeoIP_delete(geoip.city_v4);
+ geoip.city_v4 = NULL;
+
+ match = do_lookup_string("10.53.0.4", NULL,
+ dns_geoip_countrycode, "AU");
+ ATF_CHECK(match);
+
+ /*
+ * Note, region doesn't support code3 or countryname, so
+ * the next two would be answered from the country database instead
+ */
+ match = do_lookup_string("10.53.0.4", NULL,
+ dns_geoip_countrycode3, "CAN");
+ ATF_CHECK(match);
+
+ match = do_lookup_string("10.53.0.4", NULL,
+ dns_geoip_countryname, "Canada");
+ ATF_CHECK(match);
+
+ GeoIP_delete(geoip.region);
+ geoip.region = NULL;
+
+ match = do_lookup_string("10.53.0.4", NULL,
+ dns_geoip_countrycode, "CA");
+ ATF_CHECK(match);
+
+ match = do_lookup_string("10.53.0.4", NULL,
+ dns_geoip_countrycode3, "CAN");
+ ATF_CHECK(match);
+
+ match = do_lookup_string("10.53.0.4", NULL,
+ dns_geoip_countryname, "Canada");
+ ATF_CHECK(match);
+
+ dns_test_end();
+}
+
+
+/* GeoIP asnum matching */
+ATF_TC(asnum);
+ATF_TC_HEAD(asnum, tc) {
+ atf_tc_set_md_var(tc, "descr", "test asnum database matching");
+}
+ATF_TC_BODY(asnum, tc) {
+ isc_result_t result;
+ bool match;
+
+ UNUSED(tc);
+
+ result = dns_test_begin(NULL, true);
+ ATF_REQUIRE(result == ISC_R_SUCCESS);
+
+ /* Use databases from the geoip system test */
+ load_geoip(TEST_GEOIP_DATA);
+
+ if (geoip.as == NULL) {
+ dns_test_end();
+ atf_tc_skip("Database not available");
+ }
+
+
+ match = do_lookup_string("10.53.0.3", NULL, dns_geoip_as_asnum,
+ "AS100003 Three Network Labs");
+ ATF_CHECK(match);
+
+ dns_test_end();
+}
+
+/* GeoIP isp matching */
+ATF_TC(isp);
+ATF_TC_HEAD(isp, tc) {
+ atf_tc_set_md_var(tc, "descr", "test isp database matching");
+}
+ATF_TC_BODY(isp, tc) {
+ isc_result_t result;
+ bool match;
+
+ UNUSED(tc);
+
+ result = dns_test_begin(NULL, true);
+ ATF_REQUIRE(result == ISC_R_SUCCESS);
+
+ /* Use databases from the geoip system test */
+ load_geoip(TEST_GEOIP_DATA);
+
+ if (geoip.isp == NULL) {
+ dns_test_end();
+ atf_tc_skip("Database not available");
+ }
+
+ match = do_lookup_string("10.53.0.1", NULL, dns_geoip_isp_name,
+ "One Systems, Inc.");
+ ATF_CHECK(match);
+
+ dns_test_end();
+}
+
+/* GeoIP org matching */
+ATF_TC(org);
+ATF_TC_HEAD(org, tc) {
+ atf_tc_set_md_var(tc, "descr", "test org database matching");
+}
+ATF_TC_BODY(org, tc) {
+ isc_result_t result;
+ bool match;
+
+ UNUSED(tc);
+
+ result = dns_test_begin(NULL, true);
+ ATF_REQUIRE(result == ISC_R_SUCCESS);
+
+ /* Use databases from the geoip system test */
+ load_geoip(TEST_GEOIP_DATA);
+
+ if (geoip.org == NULL) {
+ dns_test_end();
+ atf_tc_skip("Database not available");
+ }
+
+ match = do_lookup_string("10.53.0.2", NULL, dns_geoip_org_name,
+ "Two Technology Ltd.");
+ ATF_CHECK(match);
+
+ dns_test_end();
+}
+
+/* GeoIP domain matching */
+ATF_TC(domain);
+ATF_TC_HEAD(domain, tc) {
+ atf_tc_set_md_var(tc, "descr", "test domain database matching");
+}
+ATF_TC_BODY(domain, tc) {
+ isc_result_t result;
+ bool match;
+
+ UNUSED(tc);
+
+ result = dns_test_begin(NULL, true);
+ ATF_REQUIRE(result == ISC_R_SUCCESS);
+
+ /* Use databases from the geoip system test */
+ load_geoip(TEST_GEOIP_DATA);
+
+ if (geoip.domain == NULL) {
+ dns_test_end();
+ atf_tc_skip("Database not available");
+ }
+
+ match = do_lookup_string("10.53.0.4", NULL,
+ dns_geoip_domain_name, "four.com");
+ ATF_CHECK(match);
+
+ dns_test_end();
+}
+
+/* GeoIP netspeed matching */
+ATF_TC(netspeed);
+ATF_TC_HEAD(netspeed, tc) {
+ atf_tc_set_md_var(tc, "descr", "test netspeed database matching");
+}
+ATF_TC_BODY(netspeed, tc) {
+ isc_result_t result;
+ bool match;
+
+ UNUSED(tc);
+
+ result = dns_test_begin(NULL, true);
+ ATF_REQUIRE(result == ISC_R_SUCCESS);
+
+ /* Use databases from the geoip system test */
+ load_geoip(TEST_GEOIP_DATA);
+
+ if (geoip.netspeed == NULL) {
+ dns_test_end();
+ atf_tc_skip("Database not available");
+ }
+
+ match = do_lookup_int("10.53.0.1", NULL, dns_geoip_netspeed_id, 0);
+ ATF_CHECK(match);
+
+ match = do_lookup_int("10.53.0.2", NULL, dns_geoip_netspeed_id, 1);
+ ATF_CHECK(match);
+
+ match = do_lookup_int("10.53.0.3", NULL, dns_geoip_netspeed_id, 2);
+ ATF_CHECK(match);
+
+ match = do_lookup_int("10.53.0.4", NULL, dns_geoip_netspeed_id, 3);
+ ATF_CHECK(match);
+
+ dns_test_end();
+}
+#else
+ATF_TC(untested);
+ATF_TC_HEAD(untested, tc) {
+ atf_tc_set_md_var(tc, "descr", "skipping geoip test");
+}
+ATF_TC_BODY(untested, tc) {
+ UNUSED(tc);
+ atf_tc_skip("GeoIP not available");
+}
+#endif
+
+/*
+ * Main
+ */
+ATF_TP_ADD_TCS(tp) {
+#ifdef HAVE_GEOIP
+ ATF_TP_ADD_TC(tp, country);
+ ATF_TP_ADD_TC(tp, country_v6);
+ ATF_TP_ADD_TC(tp, city);
+ ATF_TP_ADD_TC(tp, city_v6);
+ ATF_TP_ADD_TC(tp, region);
+ ATF_TP_ADD_TC(tp, best);
+ ATF_TP_ADD_TC(tp, asnum);
+ ATF_TP_ADD_TC(tp, isp);
+ ATF_TP_ADD_TC(tp, org);
+ ATF_TP_ADD_TC(tp, domain);
+ ATF_TP_ADD_TC(tp, netspeed);
+#else
+ ATF_TP_ADD_TC(tp, untested);
+#endif
+
+ return (atf_no_error());
+}