From 501941f0b6cce74c2ff75b10aff3f230d5d37e4c Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Wed, 27 Feb 2013 17:19:39 -0800 Subject: [PATCH] [master] add geoip support 3504. [func] Add support for ACLs based on geographic location, using MaxMind GeoIP databases. Based on code contributed by Ken Brownfield . [RT #30681] --- CHANGES | 5 + bin/named/Makefile.in | 4 +- bin/named/geoip.c | 161 ++++ bin/named/include/named/geoip.h | 14 + bin/named/include/named/globals.h | 5 + bin/named/interfacemgr.c | 3 + bin/named/server.c | 38 +- bin/tests/system/Makefile.in | 2 +- bin/tests/system/geoip/.gitignore | 1 + bin/tests/system/geoip/Makefile.in | 55 ++ bin/tests/system/geoip/clean.sh | 19 + bin/tests/system/geoip/data/GeoIP.csv | 7 + bin/tests/system/geoip/data/GeoIP.dat | Bin 0 -> 243 bytes bin/tests/system/geoip/data/GeoIPASNum.csv | 7 + bin/tests/system/geoip/data/GeoIPASNum.dat | Bin 0 -> 433 bytes bin/tests/system/geoip/data/GeoIPASNumv6.csv | 7 + bin/tests/system/geoip/data/GeoIPASNumv6.dat | Bin 0 -> 1003 bytes bin/tests/system/geoip/data/GeoIPCity.csv | 7 + bin/tests/system/geoip/data/GeoIPCity.dat | Bin 0 -> 457 bytes bin/tests/system/geoip/data/GeoIPCityv6.csv | 7 + bin/tests/system/geoip/data/GeoIPCityv6.dat | Bin 0 -> 1023 bytes bin/tests/system/geoip/data/GeoIPDomain.csv | 7 + bin/tests/system/geoip/data/GeoIPDomain.dat | Bin 0 -> 382 bytes bin/tests/system/geoip/data/GeoIPISP.csv | 7 + bin/tests/system/geoip/data/GeoIPISP.dat | Bin 0 -> 442 bytes bin/tests/system/geoip/data/GeoIPNetSpeed.csv | 7 + bin/tests/system/geoip/data/GeoIPNetSpeed.dat | Bin 0 -> 241 bytes bin/tests/system/geoip/data/GeoIPOrg.csv | 7 + bin/tests/system/geoip/data/GeoIPOrg.dat | Bin 0 -> 442 bytes bin/tests/system/geoip/data/GeoIPRegion.csv | 7 + bin/tests/system/geoip/data/GeoIPRegion.dat | Bin 0 -> 250 bytes bin/tests/system/geoip/data/GeoIPv6.csv | 7 + bin/tests/system/geoip/data/GeoIPv6.dat | Bin 0 -> 826 bytes bin/tests/system/geoip/data/README | 29 + bin/tests/system/geoip/geoip.c | 31 + bin/tests/system/geoip/ns2/example.db.in | 24 + bin/tests/system/geoip/ns2/named1.conf | 104 +++ bin/tests/system/geoip/ns2/named10.conf | 104 +++ bin/tests/system/geoip/ns2/named11.conf | 80 ++ bin/tests/system/geoip/ns2/named2.conf | 104 +++ bin/tests/system/geoip/ns2/named3.conf | 104 +++ bin/tests/system/geoip/ns2/named4.conf | 96 +++ bin/tests/system/geoip/ns2/named5.conf | 104 +++ bin/tests/system/geoip/ns2/named6.conf | 104 +++ bin/tests/system/geoip/ns2/named7.conf | 104 +++ bin/tests/system/geoip/ns2/named8.conf | 104 +++ bin/tests/system/geoip/ns2/named9.conf | 104 +++ bin/tests/system/geoip/prereq.sh | 23 + bin/tests/system/geoip/setup.sh | 24 + bin/tests/system/geoip/tests.sh | 233 ++++++ config.h.in | 9 + configure | 258 +++++- configure.in | 89 ++ doc/arm/Bv9ARM-book.xml | 56 ++ lib/dns/Makefile.in | 10 +- lib/dns/acl.c | 13 +- lib/dns/geoip.c | 775 ++++++++++++++++++ lib/dns/include/dns/Makefile.in | 15 +- lib/dns/include/dns/acl.h | 18 +- lib/dns/include/dns/geoip.h | 119 +++ lib/dns/tests/Makefile.in | 13 +- lib/dns/tests/geoip_test.c | 703 ++++++++++++++++ lib/export/dns/Makefile.in | 12 +- lib/isccfg/aclconf.c | 313 ++++++- lib/isccfg/include/isccfg/aclconf.h | 2 + lib/isccfg/namedconf.c | 119 ++- 66 files changed, 4337 insertions(+), 47 deletions(-) create mode 100644 bin/named/geoip.c create mode 100644 bin/named/include/named/geoip.h create mode 100644 bin/tests/system/geoip/.gitignore create mode 100644 bin/tests/system/geoip/Makefile.in create mode 100644 bin/tests/system/geoip/clean.sh create mode 100644 bin/tests/system/geoip/data/GeoIP.csv create mode 100644 bin/tests/system/geoip/data/GeoIP.dat create mode 100644 bin/tests/system/geoip/data/GeoIPASNum.csv create mode 100644 bin/tests/system/geoip/data/GeoIPASNum.dat create mode 100644 bin/tests/system/geoip/data/GeoIPASNumv6.csv create mode 100644 bin/tests/system/geoip/data/GeoIPASNumv6.dat create mode 100644 bin/tests/system/geoip/data/GeoIPCity.csv create mode 100644 bin/tests/system/geoip/data/GeoIPCity.dat create mode 100644 bin/tests/system/geoip/data/GeoIPCityv6.csv create mode 100644 bin/tests/system/geoip/data/GeoIPCityv6.dat create mode 100644 bin/tests/system/geoip/data/GeoIPDomain.csv create mode 100644 bin/tests/system/geoip/data/GeoIPDomain.dat create mode 100644 bin/tests/system/geoip/data/GeoIPISP.csv create mode 100644 bin/tests/system/geoip/data/GeoIPISP.dat create mode 100644 bin/tests/system/geoip/data/GeoIPNetSpeed.csv create mode 100644 bin/tests/system/geoip/data/GeoIPNetSpeed.dat create mode 100644 bin/tests/system/geoip/data/GeoIPOrg.csv create mode 100644 bin/tests/system/geoip/data/GeoIPOrg.dat create mode 100644 bin/tests/system/geoip/data/GeoIPRegion.csv create mode 100644 bin/tests/system/geoip/data/GeoIPRegion.dat create mode 100644 bin/tests/system/geoip/data/GeoIPv6.csv create mode 100644 bin/tests/system/geoip/data/GeoIPv6.dat create mode 100644 bin/tests/system/geoip/data/README create mode 100644 bin/tests/system/geoip/geoip.c create mode 100644 bin/tests/system/geoip/ns2/example.db.in create mode 100644 bin/tests/system/geoip/ns2/named1.conf create mode 100644 bin/tests/system/geoip/ns2/named10.conf create mode 100644 bin/tests/system/geoip/ns2/named11.conf create mode 100644 bin/tests/system/geoip/ns2/named2.conf create mode 100644 bin/tests/system/geoip/ns2/named3.conf create mode 100644 bin/tests/system/geoip/ns2/named4.conf create mode 100644 bin/tests/system/geoip/ns2/named5.conf create mode 100644 bin/tests/system/geoip/ns2/named6.conf create mode 100644 bin/tests/system/geoip/ns2/named7.conf create mode 100644 bin/tests/system/geoip/ns2/named8.conf create mode 100644 bin/tests/system/geoip/ns2/named9.conf create mode 100644 bin/tests/system/geoip/prereq.sh create mode 100644 bin/tests/system/geoip/setup.sh create mode 100644 bin/tests/system/geoip/tests.sh create mode 100644 lib/dns/geoip.c create mode 100644 lib/dns/include/dns/geoip.h create mode 100644 lib/dns/tests/geoip_test.c diff --git a/CHANGES b/CHANGES index 61e37731e9..4107d6f504 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +3504. [func] Add support for ACLs based on geographic location, + using MaxMind GeoIP databases. Based on code + contributed by Ken Brownfield . + [RT #30681] + 3503. [doc] Clarify size_spec syntax. [RT #32449] 3502. [func] zone-statistics: "no" is now a synonym for "none", diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in index 449cdca3c3..775cd03d02 100644 --- a/bin/named/Makefile.in +++ b/bin/named/Makefile.in @@ -82,7 +82,7 @@ SUBDIRS = unix TARGETS = named@EXEEXT@ lwresd@EXEEXT@ OBJS = builtin.@O@ client.@O@ config.@O@ control.@O@ \ - controlconf.@O@ interfacemgr.@O@ \ + controlconf.@O@ geoip.@O@ interfacemgr.@O@ \ listenlist.@O@ log.@O@ logconf.@O@ main.@O@ notify.@O@ \ query.@O@ server.@O@ sortlist.@O@ statschannel.@O@ \ tkeyconf.@O@ tsigconf.@O@ update.@O@ xfrout.@O@ \ @@ -96,7 +96,7 @@ UOBJS = unix/os.@O@ unix/dlz_dlopen_driver.@O@ SYMOBJS = symtbl.@O@ SRCS = builtin.c client.c config.c control.c \ - controlconf.c interfacemgr.c \ + controlconf.c geoip.c interfacemgr.c \ listenlist.c log.c logconf.c main.c notify.c \ query.c server.c sortlist.c statschannel.c symtbl.c symtbl-empty.c \ tkeyconf.c tsigconf.c update.c xfrout.c \ diff --git a/bin/named/geoip.c b/bin/named/geoip.c new file mode 100644 index 0000000000..fc863d823a --- /dev/null +++ b/bin/named/geoip.c @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/*! \file */ + +#include + +#ifdef HAVE_GEOIP +#include +#include + +#include + +#include + +static dns_geoip_databases_t geoip_table = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static void +init_geoip_db(GeoIP **dbp, GeoIPDBTypes edition, + 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)) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "GeoIP %s DB not available", name); + return; + } + + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "initializing GeoIP %s DB", name); + + db = GeoIP_open_type(edition, method); + if (db == NULL) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed to initialize GeoIP %s DB; " + "geoip matches using this database will fail", + name); + return; + } + + info = GeoIP_database_info(db); + if (info != NULL) + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "%s", info); + + *dbp = db; +} + +static GeoIPDBTypes +choose_rev(GeoIPDBTypes primary, GeoIPDBTypes secondary, const char *name) { + if (GeoIP_db_avail(primary)) + return (primary); + if (GeoIP_db_avail(secondary)) + return (secondary); + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "GeoIP %s DB: neither revision available", name); + return (0); +} +#endif /* HAVE_GEOIP */ + +void +ns_geoip_init(void) { +#ifndef HAVE_GEOIP + return; +#else + if (ns_g_geoip == NULL) + ns_g_geoip = &geoip_table; +#endif +} + +void +ns_geoip_load(char *dir) { +#ifndef HAVE_GEOIP + return; +#else + GeoIPOptions method; + GeoIPDBTypes edition; + +#ifdef _WIN32 + method = GEOIP_STANDARD; +#else + method = GEOIP_MMAP_CACHE; +#endif + + ns_geoip_init(); + if (dir != NULL) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "using \"%s\" as GeoIP directory", dir); + GeoIP_setup_custom_directory(dir); + } + + init_geoip_db(&ns_g_geoip->country_v4, GEOIP_COUNTRY_EDITION, + method, "Country (IPv4)"); +#ifdef HAVE_GEOIP_V6 + init_geoip_db(&ns_g_geoip->country_v6, GEOIP_COUNTRY_EDITION_V6, + method, "Country (IPv6)"); +#endif + + edition = choose_rev(GEOIP_CITY_EDITION_REV0, + GEOIP_CITY_EDITION_REV1, "City (IPv4)"); + if (edition != 0) + init_geoip_db(&ns_g_geoip->city_v4, edition, + method, "City (IPv4)"); +#if defined(HAVE_GEOIP_V6) && defined(HAVE_GEOIP_CITY_V6) + edition = choose_rev(GEOIP_CITY_EDITION_REV0_V6, + GEOIP_CITY_EDITION_REV1_V6, "City (IPv6)"); + if (edition != 0) + init_geoip_db(&ns_g_geoip->city_v6, edition, + method, "City (IPv6)"); +#endif + + + edition = choose_rev(GEOIP_REGION_EDITION_REV0, + GEOIP_REGION_EDITION_REV1, "Region"); + if (edition != 0) + init_geoip_db(&ns_g_geoip->region, edition, method, "Region"); + + init_geoip_db(&ns_g_geoip->isp, GEOIP_ISP_EDITION, + method, "ISP"); + init_geoip_db(&ns_g_geoip->org, GEOIP_ORG_EDITION, + method, "Org"); + init_geoip_db(&ns_g_geoip->as, GEOIP_ASNUM_EDITION, + method, "AS"); + init_geoip_db(&ns_g_geoip->domain, GEOIP_DOMAIN_EDITION, + method, "Domain"); + init_geoip_db(&ns_g_geoip->netspeed, GEOIP_NETSPEED_EDITION, + method, "NetSpeed"); +#endif /* HAVE_GEOIP */ +} diff --git a/bin/named/include/named/geoip.h b/bin/named/include/named/geoip.h new file mode 100644 index 0000000000..d9e88e5872 --- /dev/null +++ b/bin/named/include/named/geoip.h @@ -0,0 +1,14 @@ +#ifndef _GEOIP_H +#define _GEOIP_H + +#ifdef HAVE_GEOIP +#include +#include + +void ns_geoip_init(void); +void ns_geoip_load(char *dir); + +extern dns_geoip_databases_t *ns_g_geoip; + +#endif /* HAVE_GEOIP */ +#endif diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h index 7ac6632e2a..6d11859301 100644 --- a/bin/named/include/named/globals.h +++ b/bin/named/include/named/globals.h @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -161,6 +162,10 @@ EXTERN isc_boolean_t ns_g_noaa INIT(ISC_FALSE); EXTERN unsigned int ns_g_delay INIT(0); EXTERN isc_boolean_t ns_g_nonearest INIT(ISC_FALSE); +#ifdef HAVE_GEOIP +EXTERN dns_geoip_databases_t *ns_g_geoip INIT(NULL); +#endif + #undef EXTERN #undef INIT diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c index f07258fc76..eee1499651 100644 --- a/bin/named/interfacemgr.c +++ b/bin/named/interfacemgr.c @@ -106,6 +106,9 @@ ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, result = dns_aclenv_init(mctx, &mgr->aclenv); if (result != ISC_R_SUCCESS) goto cleanup_listenon; +#ifdef HAVE_GEOIP + mgr->aclenv.geoip = ns_g_geoip; +#endif mgr->references = 1; mgr->magic = IFMGR_MAGIC; diff --git a/bin/named/server.c b/bin/named/server.c index 3a785bbce0..25ae1bfa33 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -95,6 +95,7 @@ #include #include #include +#include #include #include #include @@ -110,6 +111,9 @@ #include #include #endif +#ifdef HAVE_GEOIP +#include +#endif /* HAVE_GEOIP */ #ifndef PATH_MAX #define PATH_MAX 1024 @@ -3762,6 +3766,10 @@ create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, if (result != ISC_R_SUCCESS) return (result); +#ifdef HAVE_GEOIP + view->aclenv.geoip = ns_g_geoip; +#endif + ISC_LIST_APPEND(*viewlist, view, link); dns_view_attach(view, viewp); return (ISC_R_SUCCESS); @@ -5083,6 +5091,24 @@ load_configuration(const char *filename, ns_server_t *server, } isc__socketmgr_setreserved(ns_g_socketmgr, reserved); +#ifdef HAVE_GEOIP + /* + * Initialize GeoIP databases from the configured location. + * This should happen before configuring any ACLs, so that we + * know what databases are available and can reject any GeoIP + * ACLs that can't work. + */ + obj = NULL; + result = ns_config_get(maps, "geoip-directory", &obj); + if (result == ISC_R_SUCCESS && cfg_obj_isstring(obj)) { + char *dir; + DE_CONST(cfg_obj_asstring(obj), dir); + ns_geoip_load(dir); + } else + ns_geoip_load(NULL); + ns_g_aclconfctx->geoip = ns_g_geoip; +#endif /* HAVE_GEOIP */ + /* * Configure various server options. */ @@ -6069,6 +6095,10 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { if (server->blackholeacl != NULL) dns_acl_detach(&server->blackholeacl); +#ifdef HAVE_GEOIP + dns_geoip_shutdown(); +#endif + dns_db_detach(&server->in_roothints); isc_task_endexclusive(server->task); @@ -6090,7 +6120,6 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { server->task = NULL; /* Initialize configuration data with default values. */ - result = isc_quota_init(&server->xfroutquota, 10); RUNTIME_CHECK(result == ISC_R_SUCCESS); result = isc_quota_init(&server->tcpquota, 10); @@ -6098,9 +6127,16 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { result = isc_quota_init(&server->recursionquota, 100); RUNTIME_CHECK(result == ISC_R_SUCCESS); + result = dns_aclenv_init(mctx, &server->aclenv); RUNTIME_CHECK(result == ISC_R_SUCCESS); +#ifdef HAVE_GEOIP + /* Initialize GeoIP before using ACL environment */ + ns_geoip_init(); + server->aclenv.geoip = ns_g_geoip; +#endif + /* Initialize server data structures. */ server->zonemgr = NULL; server->interfacemgr = NULL; diff --git a/bin/tests/system/Makefile.in b/bin/tests/system/Makefile.in index 1f9f41fdd0..9ee9e6e2f5 100644 --- a/bin/tests/system/Makefile.in +++ b/bin/tests/system/Makefile.in @@ -21,7 +21,7 @@ top_srcdir = @top_srcdir@ @BIND9_MAKE_INCLUDES@ -SUBDIRS = dlzexternal filter-aaaa lwresd rpz rsabigexponent tkey tsiggss +SUBDIRS = dlzexternal filter-aaaa geoip lwresd rpz rsabigexponent tkey tsiggss TARGETS = @BIND9_MAKE_RULES@ diff --git a/bin/tests/system/geoip/.gitignore b/bin/tests/system/geoip/.gitignore new file mode 100644 index 0000000000..e4aa6867c1 --- /dev/null +++ b/bin/tests/system/geoip/.gitignore @@ -0,0 +1 @@ +geoip diff --git a/bin/tests/system/geoip/Makefile.in b/bin/tests/system/geoip/Makefile.in new file mode 100644 index 0000000000..aa7f18447a --- /dev/null +++ b/bin/tests/system/geoip/Makefile.in @@ -0,0 +1,55 @@ +# Copyright (C) 2010-2012 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.4 2011/07/28 23:47:58 tbox Exp $ + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = ${ISC_INCLUDES} + +CDEFINES = +CWARNINGS = + +DNSLIBS = +ISCLIBS = . + +DNSDEPLIBS = +ISCDEPLIBS = + +DEPLIBS = + +LIBS = @LIBS@ + +TARGETS = geoip@EXEEXT@ + +FILTEROBJS = geoip.@O@ + +SRCS = geoip.c + +@BIND9_MAKE_RULES@ + +all: geoip@EXEEXT@ + +geoip@EXEEXT@: ${FILTEROBJS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${FILTEROBJS} ${LIBS} + +clean distclean:: + rm -f ${TARGETS} + diff --git a/bin/tests/system/geoip/clean.sh b/bin/tests/system/geoip/clean.sh new file mode 100644 index 0000000000..5a0f707c98 --- /dev/null +++ b/bin/tests/system/geoip/clean.sh @@ -0,0 +1,19 @@ +#!/bin/sh +# +# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +rm -f ns2/named.conf +rm -f ns2/example[1234567].db +rm -f dig.out.* diff --git a/bin/tests/system/geoip/data/GeoIP.csv b/bin/tests/system/geoip/data/GeoIP.csv new file mode 100644 index 0000000000..f158a5b494 --- /dev/null +++ b/bin/tests/system/geoip/data/GeoIP.csv @@ -0,0 +1,7 @@ +10.53.0.1/32 AU +10.53.0.2/32 US +10.53.0.3/32 GB +10.53.0.4/32 CA +10.53.0.5/32 CL +10.53.0.6/32 DE +10.53.0.7/32 EH diff --git a/bin/tests/system/geoip/data/GeoIP.dat b/bin/tests/system/geoip/data/GeoIP.dat new file mode 100644 index 0000000000000000000000000000000000000000..027c1757c159e3a9d0e0dddae16689e8fa71bd28 GIT binary patch literal 243 zcmXxZxeCHi6olb%-!<;LIT}bQ*lDTQSm-+h3}U6=#rO3|#xQW3kDr+w05UHNvM95$ z1eASOfU3GC>wa%2nn24hZJ^^j0J`d)?8|{1%8?w)iJZ!roXdq=$`ud-2CRV%5NQm^ iA9*EXa!c;XBbhy?%k6xyNBVlc&7~h__rxXk-TeVEtyUud literal 0 HcmV?d00001 diff --git a/bin/tests/system/geoip/data/GeoIPASNum.csv b/bin/tests/system/geoip/data/GeoIPASNum.csv new file mode 100644 index 0000000000..774edd1076 --- /dev/null +++ b/bin/tests/system/geoip/data/GeoIPASNum.csv @@ -0,0 +1,7 @@ +10.53.0.1/32 AS100001 One Systems, Inc. +10.53.0.2/32 AS100002 Two Technology Ltd. +10.53.0.3/32 AS100003 Three Network Labs +10.53.0.4/32 AS100004 Four University +10.53.0.5/32 AS100005 Five Telecom +10.53.0.6/32 AS100006 Six Company +10.53.0.7/32 AS100007 Seven Communications diff --git a/bin/tests/system/geoip/data/GeoIPASNum.dat b/bin/tests/system/geoip/data/GeoIPASNum.dat new file mode 100644 index 0000000000000000000000000000000000000000..2fd3938a2b5b23eea41e12cfb19b193d270a31d9 GIT binary patch literal 433 zcmX}p$xg#C6a~=BOqu6-cuX6F5MdNMCRM6bl|{<3i;!BaMPpa7o08w)EBFb%Etn_V zw>Y}G&-TVcz%ek)j;h1lB$j<5!H5f%vc5^usA@j`MN-UF`h zc(Om9dFR_U!?24|LRyqo;7VMDt8tCAmWZ!eN354N5F6dTN!meIEX_yj3YRT7jO(O;w8L{SMVxc!|T#GF@cjfg*PyTH}Muu<88cyX}pUW zoWXl|A0J>Ab2y6+@ew}8C-@Yf;d6X}FYy(=Mi1vOj|H^&28&oiAK&6Uma&2XhFHaS zSi?F-*uW;XZ~@!+9zWnm{DhySFVa`(oAh1!!T3}9CHT51Zu!O`lL{L( zGaL9#TdVs~+uby5Qt=c&vTXBV#jPVI>o1teuu}Dc}@~Kkr3;7{ot~ eG%=l-8Z$*3`c)IzdSnV-(^`VXOO8E%UV@OTxKkZ@Tzq16m(w-_NFu9&V*}_ znVd+X@*ukI0~~^_=CEzmYG&Q4BFz%1Bu=iRJJa{p@Y$IxvIZ{{&5~Ayq9`ne=f7yW j;JG%PHDhgSXI&AG49h$gxl!k$t~rly#M4&P)hpM3Lwo|$JdnOTs^qy=dOuEbTi8rMkWgtsR^R7h)y zN`D@d*3nh|WWBV3-sn#@5u0&~w3VpFZMYqGpm)|zVwY4y?Dpri(jLDJDMatZI^5^4 z?w1bueULbWhoySr2sWU1;!)xlHcF;H4--uo!6?Qsj?I`r3y-E# zn8yb=fP-k`Lma|k9KixQIErIf#Bp?S0w-|_AK^64;A4D(Pw|;FD?OK9NORIW!goSc!e-Dz1-Gak|B#!%n)z|WrG@_KK!;AV|fabiYR z%#54rt_^+o5qP&4EM?Nl3=L-ooe^)t^5xBuaFeO(-^RDs!Norn3A0%pj_Z2w>D5@> z?8ll?TT)4Pc=?Wsn2~5qBkzqBZ>wAdN~w%Gonp}*cM3|F(RfT_bD=kO<=4r|QZlV{ z-t8Z>hq47(mSu+Z>2F=4zkJ^I{!g{EcePr^K;E%O4L3jT8o8|Z$dlovrKQ>h=|9N1 Bu|NO- literal 0 HcmV?d00001 diff --git a/bin/tests/system/geoip/data/GeoIPDomain.csv b/bin/tests/system/geoip/data/GeoIPDomain.csv new file mode 100644 index 0000000000..8611d656f1 --- /dev/null +++ b/bin/tests/system/geoip/data/GeoIPDomain.csv @@ -0,0 +1,7 @@ +10.53.0.1/32 one.de +10.53.0.2/32 two.com +10.53.0.3/32 three.com +10.53.0.4/32 four.com +10.53.0.5/32 five.es +10.53.0.6/32 six.it +10.53.0.7/32 seven.org diff --git a/bin/tests/system/geoip/data/GeoIPDomain.dat b/bin/tests/system/geoip/data/GeoIPDomain.dat new file mode 100644 index 0000000000000000000000000000000000000000..e63629b0942d7ae75456361727838634a8c7cda3 GIT binary patch literal 382 zcmYk%O;5r=6ougd5y1*7iui#rey|~C5)(IUSQrz+MtANTdZ}H&kj_~A_vIANqKh}r zy)&6Ktth3QQI#Ih8ZGV)QN6SuVQz45(&N&7!1)BWO6P6Nr=|T2^Evkpy`Y!0ORs2; zUeg_Ts#bLLchvHP7<^pWXq|geUU= literal 0 HcmV?d00001 diff --git a/bin/tests/system/geoip/data/GeoIPISP.csv b/bin/tests/system/geoip/data/GeoIPISP.csv new file mode 100644 index 0000000000..3d5b4fa2e9 --- /dev/null +++ b/bin/tests/system/geoip/data/GeoIPISP.csv @@ -0,0 +1,7 @@ +10.53.0.1/32 One Systems, Inc. +10.53.0.2/32 Two Technology Ltd. +10.53.0.3/32 Three Network Labs +10.53.0.4/32 Four University +10.53.0.5/32 Five Telecom +10.53.0.6/32 Six Company +10.53.0.7/32 Seven Communications diff --git a/bin/tests/system/geoip/data/GeoIPISP.dat b/bin/tests/system/geoip/data/GeoIPISP.dat new file mode 100644 index 0000000000000000000000000000000000000000..3b1761c2aec60791db8131a417ac448c6177ff90 GIT binary patch literal 442 zcmYk1OG^VW6osSK_uKk@ULV~QDYz21DurUHi>X^7PA_e+laxt1b?^uHv&S=V7qj^I z&bgP6WKJn{2j;~K;+nYJErO*=Uq)V$zA9d;?AIl4z?+r%7V>tb?;!6=-xJrx`{D!f zq4-FAEItvRiqFL7;tTO5d<6(xgBx%Q%KtUMBX|R!z=B`!2b%AeDaw7|#NSiL#x2#K zIqGvfvTp2#Id#JTvr)=SJq|OMep6R}dDV8)ls>GNT!#OT+i7Q;=2DiAA_L7qh(h)oUDrTd-CEdK)loKq(N literal 0 HcmV?d00001 diff --git a/bin/tests/system/geoip/data/GeoIPOrg.csv b/bin/tests/system/geoip/data/GeoIPOrg.csv new file mode 100644 index 0000000000..3d5b4fa2e9 --- /dev/null +++ b/bin/tests/system/geoip/data/GeoIPOrg.csv @@ -0,0 +1,7 @@ +10.53.0.1/32 One Systems, Inc. +10.53.0.2/32 Two Technology Ltd. +10.53.0.3/32 Three Network Labs +10.53.0.4/32 Four University +10.53.0.5/32 Five Telecom +10.53.0.6/32 Six Company +10.53.0.7/32 Seven Communications diff --git a/bin/tests/system/geoip/data/GeoIPOrg.dat b/bin/tests/system/geoip/data/GeoIPOrg.dat new file mode 100644 index 0000000000000000000000000000000000000000..9fcc25dbc3ecb2e0dd13dee6b5a8a4869760e831 GIT binary patch literal 442 zcmYk1OG^VW6opf@zTdA}pV!w$L~tc;RSLz@E~ajUIK8yNPEsc6)WIL%&mPafUCiR+ zJLg_PlA2QL2F!`)#S7wcR|kugzJ$CieMP)l*{?}nhc_zoP2{ag-$ve%zAN4n?~4z_ zhvJ6#NZb@3i%-O-;xq9%d;thtf-7(h%KzPhC-4qFfd#+d58U-EQT@jX8FSip&qax@4kl qt|HFZmMxiD6YF4{^|)ERw7YN5G-PKc6xatE=%6WkEQ+FzXa56o6h1!y literal 0 HcmV?d00001 diff --git a/bin/tests/system/geoip/data/GeoIPRegion.csv b/bin/tests/system/geoip/data/GeoIPRegion.csv new file mode 100644 index 0000000000..0bcd872fef --- /dev/null +++ b/bin/tests/system/geoip/data/GeoIPRegion.csv @@ -0,0 +1,7 @@ +10.53.0.1/32 US CA +10.53.0.2/32 CA BC +10.53.0.3/32 US OK +10.53.0.4/32 AU +10.53.0.5/32 US CO +10.53.0.6/32 CA ON +10.53.0.7/32 NL diff --git a/bin/tests/system/geoip/data/GeoIPRegion.dat b/bin/tests/system/geoip/data/GeoIPRegion.dat new file mode 100644 index 0000000000000000000000000000000000000000..8e2d12caedc672378568b4fe6976efb9a2e6cc0c GIT binary patch literal 250 zcmXxZyAAZ9@9X^br#66^R(c0pHT!#ZYcv5*Hxg#uG0o>(iUyg4(-w&?b87r(h&`SF`$46 wFa>5D*IGUcdCld!mA#f=DR2K5KfB}Uuu+%jcD*YTJ&ZbsCRERrwbs+XAN_4PPyhe` literal 0 HcmV?d00001 diff --git a/bin/tests/system/geoip/data/GeoIPv6.csv b/bin/tests/system/geoip/data/GeoIPv6.csv new file mode 100644 index 0000000000..919bf860a5 --- /dev/null +++ b/bin/tests/system/geoip/data/GeoIPv6.csv @@ -0,0 +1,7 @@ +"fd92:7065:b8e:ffff::1/128",AU +"fd92:7065:b8e:ffff::2/128",US +"fd92:7065:b8e:ffff::3/128",GB +"fd92:7065:b8e:ffff::4/128",CA +"fd92:7065:b8e:ffff::5/128",CL +"fd92:7065:b8e:ffff::6/128",DE +"fd92:7065:b8e:ffff::7/128",EH diff --git a/bin/tests/system/geoip/data/GeoIPv6.dat b/bin/tests/system/geoip/data/GeoIPv6.dat new file mode 100644 index 0000000000000000000000000000000000000000..6781a8563dd3996ae3a44f996750c4ff33b76eff GIT binary patch literal 826 zcmXxd=TcKq7=__Ql`ci3!$Bz)q=-O5(}XA>B#Nj=Q3xakqy-X!bOdhHEBQF{&YVBb zytDS6y=9gq$t)XlFc?sxd?y8nAWmQi-{S|I#3`J{k2r&~7{&;G!p}H|UvM73 z;y3(`3-|*UaS4}k1%Ki%T*Wnv;yP|%4CDA46S#?6_y@Of2X}D~_c4hFc!()X;}K@? z82{o4p5hsv;{{$ySJJigPr8wA8OzQ7n}y9f%(~5dW&tzzBsd)j`JF_3e=F&v9Marq9eu?xcI1L^w|X literal 0 HcmV?d00001 diff --git a/bin/tests/system/geoip/data/README b/bin/tests/system/geoip/data/README new file mode 100644 index 0000000000..b2108db447 --- /dev/null +++ b/bin/tests/system/geoip/data/README @@ -0,0 +1,29 @@ +The data data files in this directory are sample GeoIP databases, +generated from the corresponding CSV files. Thanks to MaxMind, Inc. +for assitance with producing these files. + +Unless otherwise noted, the databases only support IPv4: + +GeoIP.dat: Country (IPv4) +GeoIPv6.dat: Country (IPv6) +GeoIPCity.dat: City (IPv4) +GeoIPCityv6.dat: City (IPv6) +GeoIPRegion.dat: Region +GeoIPISP.dat: ISP +GeoIPOrg.dat: Organization +GeoIPDoain.dat: Domain Name +GeoIPASNum.dat: AS Number +GeoIPNetSpeed.dat: Net Speed + +GeoIP.dat can also be egenerated using the open source 'geoip-csv-to-dat' +utility: + +$ geoip-csv-to-dat -i "BIND9 geoip test data v1" -o GeoIP.dat << EOF +"10.53.0.1","10.53.0.1","171245569","171245569","AU","Australia" +"10.53.0.2","10.53.0.2","171245570","171245570","US","United States" +"10.53.0.3","10.53.0.3","171245571","171245571","GB","United Kingdom" +"10.53.0.4","10.53.0.4","171245572","171245572","CA","Canada" +"10.53.0.5","10.53.0.5","171245573","171245573","CL","Chile" +"10.53.0.6","10.53.0.6","171245574","171245574","DE","Germany" +"10.53.0.7","10.53.0.7","171245575","171245575","EH","Western Sahara" +EOF diff --git a/bin/tests/system/geoip/geoip.c b/bin/tests/system/geoip/geoip.c new file mode 100644 index 0000000000..e0dadadafa --- /dev/null +++ b/bin/tests/system/geoip/geoip.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +int +main(int argc, char **argv) { + + UNUSED(argc); + UNUSED(argv); + +#ifdef HAVE_GEOIP + return (0); +#else + return (1); +#endif +} diff --git a/bin/tests/system/geoip/ns2/example.db.in b/bin/tests/system/geoip/ns2/example.db.in new file mode 100644 index 0000000000..52a233bd55 --- /dev/null +++ b/bin/tests/system/geoip/ns2/example.db.in @@ -0,0 +1,24 @@ +; Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") +; +; Permission to use, copy, modify, and/or distribute this software for any +; purpose with or without fee is hereby granted, provided that the above +; copyright notice and this permission notice appear in all copies. +; +; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +; PERFORMANCE OF THIS SOFTWARE. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 diff --git a/bin/tests/system/geoip/ns2/named1.conf b/bin/tests/system/geoip/ns2/named1.conf new file mode 100644 index 0000000000..b741b6f81f --- /dev/null +++ b/bin/tests/system/geoip/ns2/named1.conf @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +// NS2 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port 5300; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-md5; +}; + +controls { + inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip db country country AU; }; + zone "example" { + type master; + file "example1.db"; + }; +}; + +view two { + match-clients { geoip db country country US; }; + zone "example" { + type master; + file "example2.db"; + }; +}; + +view three { + match-clients { geoip db country country GB; }; + zone "example" { + type master; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip db country country CA; }; + zone "example" { + type master; + file "example4.db"; + }; +}; + +view five { + match-clients { geoip db country country CL; }; + zone "example" { + type master; + file "example5.db"; + }; +}; + +view six { + match-clients { geoip db country country DE; }; + zone "example" { + type master; + file "example6.db"; + }; +}; + +view seven { + match-clients { geoip db country country EH; }; + zone "example" { + type master; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type master; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip/ns2/named10.conf b/bin/tests/system/geoip/ns2/named10.conf new file mode 100644 index 0000000000..8814e73b5c --- /dev/null +++ b/bin/tests/system/geoip/ns2/named10.conf @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +// NS2 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port 5300; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-md5; +}; + +controls { + inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip domain one.de; }; + zone "example" { + type master; + file "example1.db"; + }; +}; + +view two { + match-clients { geoip domain two.com; }; + zone "example" { + type master; + file "example2.db"; + }; +}; + +view three { + match-clients { geoip domain three.com; }; + zone "example" { + type master; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip domain four.com; }; + zone "example" { + type master; + file "example4.db"; + }; +}; + +view five { + match-clients { geoip domain five.es; }; + zone "example" { + type master; + file "example5.db"; + }; +}; + +view six { + match-clients { geoip domain six.it; }; + zone "example" { + type master; + file "example6.db"; + }; +}; + +view seven { + match-clients { geoip domain seven.org; }; + zone "example" { + type master; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type master; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip/ns2/named11.conf b/bin/tests/system/geoip/ns2/named11.conf new file mode 100644 index 0000000000..a704735f7f --- /dev/null +++ b/bin/tests/system/geoip/ns2/named11.conf @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +// NS2 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port 5300; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-md5; +}; + +controls { + inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip netspeed 0; }; + zone "example" { + type master; + file "example1.db"; + }; +}; + +view two { + match-clients { geoip netspeed 1; }; + zone "example" { + type master; + file "example2.db"; + }; +}; + +view three { + match-clients { geoip netspeed 2; }; + zone "example" { + type master; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip netspeed 3; }; + zone "example" { + type master; + file "example4.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type master; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip/ns2/named2.conf b/bin/tests/system/geoip/ns2/named2.conf new file mode 100644 index 0000000000..504f89f210 --- /dev/null +++ b/bin/tests/system/geoip/ns2/named2.conf @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +// NS2 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port 5300; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-md5; +}; + +controls { + inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip db country country AUS; }; + zone "example" { + type master; + file "example1.db"; + }; +}; + +view two { + match-clients { geoip db country country USA; }; + zone "example" { + type master; + file "example2.db"; + }; +}; + +view three { + match-clients { geoip db country country GBR; }; + zone "example" { + type master; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip db country country CAN; }; + zone "example" { + type master; + file "example4.db"; + }; +}; + +view five { + match-clients { geoip db country country CHL; }; + zone "example" { + type master; + file "example5.db"; + }; +}; + +view six { + match-clients { geoip db country country DEU; }; + zone "example" { + type master; + file "example6.db"; + }; +}; + +view seven { + match-clients { geoip db country country ESH; }; + zone "example" { + type master; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type master; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip/ns2/named3.conf b/bin/tests/system/geoip/ns2/named3.conf new file mode 100644 index 0000000000..81644807c5 --- /dev/null +++ b/bin/tests/system/geoip/ns2/named3.conf @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +// NS2 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port 5300; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-md5; +}; + +controls { + inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip db country country Australia; }; + zone "example" { + type master; + file "example1.db"; + }; +}; + +view two { + match-clients { geoip db country country "United States"; }; + zone "example" { + type master; + file "example2.db"; + }; +}; + +view three { + match-clients { geoip db country country "United Kingdom"; }; + zone "example" { + type master; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip db country country Canada; }; + zone "example" { + type master; + file "example4.db"; + }; +}; + +view five { + match-clients { geoip db country country Chile; }; + zone "example" { + type master; + file "example5.db"; + }; +}; + +view six { + match-clients { geoip db country country Germany; }; + zone "example" { + type master; + file "example6.db"; + }; +}; + +view seven { + match-clients { geoip db country country "Western Sahara"; }; + zone "example" { + type master; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type master; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip/ns2/named4.conf b/bin/tests/system/geoip/ns2/named4.conf new file mode 100644 index 0000000000..24f5735a4a --- /dev/null +++ b/bin/tests/system/geoip/ns2/named4.conf @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +// NS2 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port 5300; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-md5; +}; + +controls { + inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip region CA; }; + zone "example" { + type master; + file "example1.db"; + }; +}; + +view three { + match-clients { geoip region OK; }; + zone "example" { + type master; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip region VA; }; + zone "example" { + type master; + file "example4.db"; + }; +}; + +view five { + match-clients { geoip region GA; }; + zone "example" { + type master; + file "example5.db"; + }; +}; + +view six { + match-clients { geoip region CO; }; + zone "example" { + type master; + file "example6.db"; + }; +}; + +view seven { + match-clients { geoip region AK; }; + zone "example" { + type master; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type master; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip/ns2/named5.conf b/bin/tests/system/geoip/ns2/named5.conf new file mode 100644 index 0000000000..2a91e7f2ba --- /dev/null +++ b/bin/tests/system/geoip/ns2/named5.conf @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +// NS2 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port 5300; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-md5; +}; + +controls { + inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip db region region "California"; }; + zone "example" { + type master; + file "example1.db"; + }; +}; + +view two { + match-clients { geoip db region region "British Columbia"; }; + zone "example" { + type master; + file "example2.db"; + }; +}; + +view three { + match-clients { geoip db region region "Oklahoma"; }; + zone "example" { + type master; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip db region country AU; }; + zone "example" { + type master; + file "example4.db"; + }; +}; + +view five { + match-clients { geoip db region region "Colorado"; }; + zone "example" { + type master; + file "example5.db"; + }; +}; + +view six { + match-clients { geoip db region region "Ontario"; }; + zone "example" { + type master; + file "example6.db"; + }; +}; + +view seven { + match-clients { geoip db region country NL; }; + zone "example" { + type master; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type master; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip/ns2/named6.conf b/bin/tests/system/geoip/ns2/named6.conf new file mode 100644 index 0000000000..c2b27d7dd1 --- /dev/null +++ b/bin/tests/system/geoip/ns2/named6.conf @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +// NS2 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port 5300; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-md5; +}; + +controls { + inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip city "Redwood City"; }; + zone "example" { + type master; + file "example1.db"; + }; +}; + +view two { + match-clients { geoip city "Santa Cruz"; }; + zone "example" { + type master; + file "example2.db"; + }; +}; + +view three { + match-clients { geoip city "Oklahoma City"; }; + zone "example" { + type master; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip city "Ashland"; }; + zone "example" { + type master; + file "example4.db"; + }; +}; + +view five { + match-clients { geoip city "Atlanta"; }; + zone "example" { + type master; + file "example5.db"; + }; +}; + +view six { + match-clients { geoip city "Morrison"; }; + zone "example" { + type master; + file "example6.db"; + }; +}; + +view seven { + match-clients { geoip city "Ketchikan"; }; + zone "example" { + type master; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type master; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip/ns2/named7.conf b/bin/tests/system/geoip/ns2/named7.conf new file mode 100644 index 0000000000..6877c02013 --- /dev/null +++ b/bin/tests/system/geoip/ns2/named7.conf @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +// NS2 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port 5300; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-md5; +}; + +controls { + inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip isp "One Systems, Inc."; }; + zone "example" { + type master; + file "example1.db"; + }; +}; + +view two { + match-clients { geoip isp "Two Technology Ltd."; }; + zone "example" { + type master; + file "example2.db"; + }; +}; + +view three { + match-clients { geoip isp "Three Network Labs"; }; + zone "example" { + type master; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip isp "Four University"; }; + zone "example" { + type master; + file "example4.db"; + }; +}; + +view five { + match-clients { geoip isp "Five Telecom"; }; + zone "example" { + type master; + file "example5.db"; + }; +}; + +view six { + match-clients { geoip isp "Six Company"; }; + zone "example" { + type master; + file "example6.db"; + }; +}; + +view seven { + match-clients { geoip isp "Seven Communications"; }; + zone "example" { + type master; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type master; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip/ns2/named8.conf b/bin/tests/system/geoip/ns2/named8.conf new file mode 100644 index 0000000000..fff2bb4d34 --- /dev/null +++ b/bin/tests/system/geoip/ns2/named8.conf @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +// NS2 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port 5300; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-md5; +}; + +controls { + inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip org "One Systems, Inc."; }; + zone "example" { + type master; + file "example1.db"; + }; +}; + +view two { + match-clients { geoip org "Two Technology Ltd."; }; + zone "example" { + type master; + file "example2.db"; + }; +}; + +view three { + match-clients { geoip org "Three Network Labs"; }; + zone "example" { + type master; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip org "Four University"; }; + zone "example" { + type master; + file "example4.db"; + }; +}; + +view five { + match-clients { geoip org "Five Telecom"; }; + zone "example" { + type master; + file "example5.db"; + }; +}; + +view six { + match-clients { geoip org "Six Company"; }; + zone "example" { + type master; + file "example6.db"; + }; +}; + +view seven { + match-clients { geoip org "Seven Communications"; }; + zone "example" { + type master; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type master; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip/ns2/named9.conf b/bin/tests/system/geoip/ns2/named9.conf new file mode 100644 index 0000000000..d3cb0e6a80 --- /dev/null +++ b/bin/tests/system/geoip/ns2/named9.conf @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +// NS2 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port 5300; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-md5; +}; + +controls { + inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip asnum "AS100001 One Systems, Inc."; }; + zone "example" { + type master; + file "example1.db"; + }; +}; + +view two { + match-clients { geoip asnum "AS100002 Two Technology Ltd."; }; + zone "example" { + type master; + file "example2.db"; + }; +}; + +view three { + match-clients { geoip asnum "AS100003 Three Network Labs"; }; + zone "example" { + type master; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip asnum "AS100004 Four University"; }; + zone "example" { + type master; + file "example4.db"; + }; +}; + +view five { + match-clients { geoip asnum "AS100005 Five Telecom"; }; + zone "example" { + type master; + file "example5.db"; + }; +}; + +view six { + match-clients { geoip asnum "AS100006 Six Company"; }; + zone "example" { + type master; + file "example6.db"; + }; +}; + +view seven { + match-clients { geoip asnum "AS100007 Seven Communications"; }; + zone "example" { + type master; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type master; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip/prereq.sh b/bin/tests/system/geoip/prereq.sh new file mode 100644 index 0000000000..b78be4123d --- /dev/null +++ b/bin/tests/system/geoip/prereq.sh @@ -0,0 +1,23 @@ +#!/bin/sh +# +# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +if ./geoip +then + : +else + echo "I:This test requires GeoIP support." >&2 + exit 1 +fi diff --git a/bin/tests/system/geoip/setup.sh b/bin/tests/system/geoip/setup.sh new file mode 100644 index 0000000000..458695270b --- /dev/null +++ b/bin/tests/system/geoip/setup.sh @@ -0,0 +1,24 @@ +#!/bin/sh +# +# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +sh clean.sh + +cp ns2/named1.conf ns2/named.conf + +for i in 1 2 3 4 5 6 7; do + cp ns2/example.db.in ns2/example${i}.db + echo "@ IN TXT \"$i\"" >> ns2/example$i.db +done diff --git a/bin/tests/system/geoip/tests.sh b/bin/tests/system/geoip/tests.sh new file mode 100644 index 0000000000..42e4f54702 --- /dev/null +++ b/bin/tests/system/geoip/tests.sh @@ -0,0 +1,233 @@ +#!/bin/sh +# +# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +SYSTEMTESTTOP=.. +. $SYSTEMTESTTOP/conf.sh + +status=0 +n=0 + +rm -f dig.out.* + +DIGOPTS="+tcp +short -p 5300 @10.53.0.2" + +n=`expr $n + 1` +echo "I:checking GeoIP country database by code" +ret=0 +lret=0 +for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 + j=`cat dig.out.ns2.test$n.$i | tr -d '"'` + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo "I:failed" +status=`expr $status + $ret` + +echo "I:reloading server" +cp -f ns2/named2.conf ns2/named.conf +$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' +sleep 3 + +n=`expr $n + 1` +echo "I:checking GeoIP country database by three-letter code" +ret=0 +lret=0 +for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 + j=`cat dig.out.ns2.test$n.$i | tr -d '"'` + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo "I:failed" +status=`expr $status + $ret` + +echo "I:reloading server" +cp -f ns2/named3.conf ns2/named.conf +$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' +sleep 3 + +n=`expr $n + 1` +echo "I:checking GeoIP country database by name" +ret=0 +lret=0 +for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 + j=`cat dig.out.ns2.test$n.$i | tr -d '"'` + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo "I:failed" +status=`expr $status + $ret` + +echo "I:reloading server" +cp -f ns2/named4.conf ns2/named.conf +$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' +sleep 3 + +n=`expr $n + 1` +echo "I:checking GeoIP region code, no specified database" +ret=0 +lret=0 +# skipping 2 on purpose here; it has the same region code as 1 +for i in 1 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 + j=`cat dig.out.ns2.test$n.$i | tr -d '"'` + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo "I:failed" +status=`expr $status + $ret` + +echo "I:reloading server" +cp -f ns2/named5.conf ns2/named.conf +$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' +sleep 3 + +n=`expr $n + 1` +echo "I:checking GeoIP region database by region name and country code" +ret=0 +lret=0 +for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 + j=`cat dig.out.ns2.test$n.$i | tr -d '"'` + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo "I:failed" +status=`expr $status + $ret` + +echo "I:reloading server" +cp -f ns2/named6.conf ns2/named.conf +$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' +sleep 3 + +n=`expr $n + 1` +echo "I:checking GeoIP city database by city name" +ret=0 +lret=0 +for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 + j=`cat dig.out.ns2.test$n.$i | tr -d '"'` + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo "I:failed" +status=`expr $status + $ret` + +echo "I:reloading server" +cp -f ns2/named7.conf ns2/named.conf +$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' +sleep 3 + +n=`expr $n + 1` +echo "I:checking GeoIP isp database" +ret=0 +lret=0 +for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 + j=`cat dig.out.ns2.test$n.$i | tr -d '"'` + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo "I:failed" +status=`expr $status + $ret` + +echo "I:reloading server" +cp -f ns2/named8.conf ns2/named.conf +$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' +sleep 3 + +n=`expr $n + 1` +echo "I:checking GeoIP org database" +ret=0 +lret=0 +for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 + j=`cat dig.out.ns2.test$n.$i | tr -d '"'` + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo "I:failed" +status=`expr $status + $ret` + +echo "I:reloading server" +cp -f ns2/named9.conf ns2/named.conf +$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' +sleep 3 + +n=`expr $n + 1` +echo "I:checking GeoIP asnum database" +ret=0 +lret=0 +for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 + j=`cat dig.out.ns2.test$n.$i | tr -d '"'` + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo "I:failed" +status=`expr $status + $ret` + +echo "I:reloading server" +cp -f ns2/named10.conf ns2/named.conf +$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' +sleep 3 + +n=`expr $n + 1` +echo "I:checking GeoIP domain database" +ret=0 +lret=0 +for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 + j=`cat dig.out.ns2.test$n.$i | tr -d '"'` + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo "I:failed" +status=`expr $status + $ret` + +echo "I:reloading server" +cp -f ns2/named11.conf ns2/named.conf +$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' +sleep 3 + +n=`expr $n + 1` +echo "I:checking GeoIP netspeed database" +ret=0 +lret=0 +for i in 1 2 3 4; do + $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 + j=`cat dig.out.ns2.test$n.$i | tr -d '"'` + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo "I:failed" +status=`expr $status + $ret` + +echo "I:exit status: $status" +exit $status diff --git a/config.h.in b/config.h.in index a96d270f7b..f714808ff5 100644 --- a/config.h.in +++ b/config.h.in @@ -215,6 +215,15 @@ int sigwait(const unsigned int *set, int *sig); /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H +/* Build with GeoIP support */ +#undef HAVE_GEOIP + +/* Build with GeoIP City IPv6 support */ +#undef HAVE_GEOIP_CITY_V6 + +/* Build with GeoIP Country IPv6 support */ +#undef HAVE_GEOIP_V6 + /* Define to 1 if you have the header file. */ #undef HAVE_GSSAPI_GSSAPI_H diff --git a/configure b/configure index 6e016dbdb0..6290188f2a 100755 --- a/configure +++ b/configure @@ -1459,6 +1459,7 @@ with_ecdsa with_gost enable_openssl_hash with_pkcs11 +with_geoip with_gssapi with_randomdev enable_threads @@ -2169,6 +2170,7 @@ Optional Packages: --with-gost OpenSSL GOST --with-pkcs11=PATH Build with PKCS11 support yes|no|path (PATH is for the PKCS11 provider) + --with-geoip=PATH Build with GeoIP support (yes|no|path) --with-gssapi=PATH Specify path for system-supplied GSSAPI [default=yes] --with-randomdev=PATH Specify path for random device --with-libxml2=PATH Build with libxml2 library yes|no|path @@ -14471,6 +14473,259 @@ $as_echo "PKCS11 provider is \"$use_pkcs11\"" >&6; } esac + +# Check whether --with-geoip was given. +if test "${with_geoip+set}" = set; then : + withval=$with_geoip; use_geoip="$withval" +else + use_geoip="no" +fi + + +if test "$use_geoip" = "yes" +then + for d in /usr /usr/local + do + if test -f $d/include/GeoIP.h + then + use_geoip=$d + break + fi + done +fi + +case "$use_geoip" in + no|'') + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GeoIP support" >&5 +$as_echo_n "checking for GeoIP support... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 +$as_echo "disabled" >&6; } + ;; + *) + if test -d "$use_geoip" -o -L "$use_geoip" + then + CFLAGS="$CFLAGS -I$use_geoip/include" + CPPFLAGS="$CPPFLAGS -I$use_geoip/include" + case "$host_os" in + netbsd*|openbsd*|solaris*) + LIBS="$LIBS -Wl,-rpath=$use_geoip/lib" + ;; + *) + LIBS="$LIBS -L$use_geoip/lib" + esac + elif test "$use_geoip" = "yes" + then + as_fn_error $? "GeoIP path not found" "$LINENO" 5 + else + as_fn_error $? "GeoIP path $use_geoip does not exist" "$LINENO" 5 + fi + ac_fn_c_check_header_mongrel "$LINENO" "GeoIP.h" "ac_cv_header_GeoIP_h" "$ac_includes_default" +if test "x$ac_cv_header_GeoIP_h" = xyes; then : + +else + as_fn_error $? "GeoIP header file not found" "$LINENO" 5 + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing GeoIP_open" >&5 +$as_echo_n "checking for library containing GeoIP_open... " >&6; } +if ${ac_cv_search_GeoIP_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char GeoIP_open (); +int +main () +{ +return GeoIP_open (); + ; + return 0; +} +_ACEOF +for ac_lib in '' GeoIP; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_GeoIP_open=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_GeoIP_open+:} false; then : + break +fi +done +if ${ac_cv_search_GeoIP_open+:} false; then : + +else + ac_cv_search_GeoIP_open=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_GeoIP_open" >&5 +$as_echo "$ac_cv_search_GeoIP_open" >&6; } +ac_res=$ac_cv_search_GeoIP_open +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +else + as_fn_error $? "GeoIP library not found" "$LINENO" 5 + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing fabsf" >&5 +$as_echo_n "checking for library containing fabsf... " >&6; } +if ${ac_cv_search_fabsf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char fabsf (); +int +main () +{ +return fabsf (); + ; + return 0; +} +_ACEOF +for ac_lib in '' m; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_fabsf=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_fabsf+:} false; then : + break +fi +done +if ${ac_cv_search_fabsf+:} false; then : + +else + ac_cv_search_fabsf=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_fabsf" >&5 +$as_echo "$ac_cv_search_fabsf" >&6; } +ac_res=$ac_cv_search_fabsf +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +else + as_fn_error $? "Math library not found" "$LINENO" 5 + +fi + + +$as_echo "#define HAVE_GEOIP 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GeoIP support" >&5 +$as_echo_n "checking for GeoIP support... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GeoIP Country IPv6 support" >&5 +$as_echo_n "checking for GeoIP Country IPv6 support... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + +int +main () +{ + + struct in6_addr in6; + GeoIP_country_name_by_ipnum_v6(NULL, in6); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_GEOIP_V6 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GeoIP City IPv6 support" >&5 +$as_echo_n "checking for GeoIP City IPv6 support... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + #include + +int +main () +{ + + struct in6_addr in6; + int i = GEOIP_CITY_EDITION_REV0_V6; + GeoIP_record_by_ipnum_v6(NULL, in6); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_GEOIP_CITY_V6 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GSSAPI library" >&5 $as_echo_n "checking for GSSAPI library... " >&6; } @@ -20518,7 +20773,7 @@ ac_config_commands="$ac_config_commands chmod" # elsewhere if there's a good reason for doing so. # -ac_config_files="$ac_config_files make/Makefile make/mkdep Makefile bin/Makefile bin/check/Makefile bin/confgen/Makefile bin/confgen/unix/Makefile bin/dig/Makefile bin/dnssec/Makefile bin/named/Makefile bin/named/unix/Makefile bin/nsupdate/Makefile bin/pkcs11/Makefile bin/python/Makefile bin/python/dnssec-checkds.py bin/rndc/Makefile bin/tests/Makefile bin/tests/atomic/Makefile bin/tests/db/Makefile bin/tests/dst/Makefile bin/tests/hashes/Makefile bin/tests/headerdep_test.sh bin/tests/master/Makefile bin/tests/mem/Makefile bin/tests/names/Makefile bin/tests/net/Makefile bin/tests/rbt/Makefile bin/tests/resolver/Makefile bin/tests/sockaddr/Makefile bin/tests/system/Makefile bin/tests/system/conf.sh bin/tests/system/dlz/prereq.sh bin/tests/system/dlzexternal/Makefile bin/tests/system/dlzexternal/ns1/named.conf bin/tests/system/dsdigest/prereq.sh bin/tests/system/ecdsa/prereq.sh bin/tests/system/dlzredir/prereq.sh bin/tests/system/filter-aaaa/Makefile bin/tests/system/gost/prereq.sh bin/tests/system/lwresd/Makefile bin/tests/system/rpz/Makefile bin/tests/system/rsabigexponent/Makefile bin/tests/system/tkey/Makefile bin/tests/system/tsiggss/Makefile bin/tests/tasks/Makefile bin/tests/timers/Makefile bin/tests/virtual-time/Makefile bin/tests/virtual-time/conf.sh bin/tools/Makefile contrib/check-secure-delegation.pl contrib/zone-edit.sh doc/Makefile doc/arm/Makefile doc/doxygen/Doxyfile doc/doxygen/Makefile doc/doxygen/doxygen-input-filter doc/misc/Makefile doc/xsl/Makefile doc/xsl/isc-docbook-chunk.xsl doc/xsl/isc-docbook-html.xsl doc/xsl/isc-docbook-latex.xsl doc/xsl/isc-manpage.xsl isc-config.sh lib/Makefile lib/bind9/Makefile lib/bind9/include/Makefile lib/bind9/include/bind9/Makefile lib/dns/Makefile lib/dns/include/Makefile lib/dns/include/dns/Makefile lib/dns/include/dst/Makefile lib/dns/tests/Makefile lib/export/Makefile lib/export/dns/Makefile lib/export/dns/include/Makefile lib/export/dns/include/dns/Makefile lib/export/dns/include/dst/Makefile lib/export/irs/Makefile lib/export/irs/include/Makefile lib/export/irs/include/irs/Makefile lib/export/isc/$thread_dir/Makefile lib/export/isc/$thread_dir/include/Makefile lib/export/isc/$thread_dir/include/isc/Makefile lib/export/isc/Makefile lib/export/isc/include/Makefile lib/export/isc/include/isc/Makefile lib/export/isc/nls/Makefile lib/export/isc/unix/Makefile lib/export/isc/unix/include/Makefile lib/export/isc/unix/include/isc/Makefile lib/export/isccfg/Makefile lib/export/isccfg/include/Makefile lib/export/isccfg/include/isccfg/Makefile lib/export/samples/Makefile lib/export/samples/Makefile-postinstall lib/irs/Makefile lib/irs/include/Makefile lib/irs/include/irs/Makefile lib/irs/include/irs/netdb.h lib/irs/include/irs/platform.h lib/isc/$arch/Makefile lib/isc/$arch/include/Makefile lib/isc/$arch/include/isc/Makefile lib/isc/$thread_dir/Makefile lib/isc/$thread_dir/include/Makefile lib/isc/$thread_dir/include/isc/Makefile lib/isc/Makefile lib/isc/include/Makefile lib/isc/include/isc/Makefile lib/isc/include/isc/platform.h lib/isc/tests/Makefile lib/isc/nls/Makefile lib/isc/unix/Makefile lib/isc/unix/include/Makefile lib/isc/unix/include/isc/Makefile lib/isccc/Makefile lib/isccc/include/Makefile lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile lib/lwres/Makefile lib/lwres/include/Makefile lib/lwres/include/lwres/Makefile lib/lwres/include/lwres/netdb.h lib/lwres/include/lwres/platform.h lib/lwres/man/Makefile lib/lwres/unix/Makefile lib/lwres/unix/include/Makefile lib/lwres/unix/include/lwres/Makefile lib/tests/Makefile lib/tests/include/Makefile lib/tests/include/tests/Makefile unit/Makefile unit/unittest.sh" +ac_config_files="$ac_config_files make/Makefile make/mkdep Makefile bin/Makefile bin/check/Makefile bin/confgen/Makefile bin/confgen/unix/Makefile bin/dig/Makefile bin/dnssec/Makefile bin/named/Makefile bin/named/unix/Makefile bin/nsupdate/Makefile bin/pkcs11/Makefile bin/python/Makefile bin/python/dnssec-checkds.py bin/rndc/Makefile bin/tests/Makefile bin/tests/atomic/Makefile bin/tests/db/Makefile bin/tests/dst/Makefile bin/tests/hashes/Makefile bin/tests/headerdep_test.sh bin/tests/master/Makefile bin/tests/mem/Makefile bin/tests/names/Makefile bin/tests/net/Makefile bin/tests/rbt/Makefile bin/tests/resolver/Makefile bin/tests/sockaddr/Makefile bin/tests/system/Makefile bin/tests/system/conf.sh bin/tests/system/dlz/prereq.sh bin/tests/system/dlzexternal/Makefile bin/tests/system/dlzexternal/ns1/named.conf bin/tests/system/dsdigest/prereq.sh bin/tests/system/ecdsa/prereq.sh bin/tests/system/dlzredir/prereq.sh bin/tests/system/filter-aaaa/Makefile bin/tests/system/geoip/Makefile bin/tests/system/gost/prereq.sh bin/tests/system/lwresd/Makefile bin/tests/system/rpz/Makefile bin/tests/system/rsabigexponent/Makefile bin/tests/system/tkey/Makefile bin/tests/system/tsiggss/Makefile bin/tests/tasks/Makefile bin/tests/timers/Makefile bin/tests/virtual-time/Makefile bin/tests/virtual-time/conf.sh bin/tools/Makefile contrib/check-secure-delegation.pl contrib/zone-edit.sh doc/Makefile doc/arm/Makefile doc/doxygen/Doxyfile doc/doxygen/Makefile doc/doxygen/doxygen-input-filter doc/misc/Makefile doc/xsl/Makefile doc/xsl/isc-docbook-chunk.xsl doc/xsl/isc-docbook-html.xsl doc/xsl/isc-docbook-latex.xsl doc/xsl/isc-manpage.xsl isc-config.sh lib/Makefile lib/bind9/Makefile lib/bind9/include/Makefile lib/bind9/include/bind9/Makefile lib/dns/Makefile lib/dns/include/Makefile lib/dns/include/dns/Makefile lib/dns/include/dst/Makefile lib/dns/tests/Makefile lib/export/Makefile lib/export/dns/Makefile lib/export/dns/include/Makefile lib/export/dns/include/dns/Makefile lib/export/dns/include/dst/Makefile lib/export/irs/Makefile lib/export/irs/include/Makefile lib/export/irs/include/irs/Makefile lib/export/isc/$thread_dir/Makefile lib/export/isc/$thread_dir/include/Makefile lib/export/isc/$thread_dir/include/isc/Makefile lib/export/isc/Makefile lib/export/isc/include/Makefile lib/export/isc/include/isc/Makefile lib/export/isc/nls/Makefile lib/export/isc/unix/Makefile lib/export/isc/unix/include/Makefile lib/export/isc/unix/include/isc/Makefile lib/export/isccfg/Makefile lib/export/isccfg/include/Makefile lib/export/isccfg/include/isccfg/Makefile lib/export/samples/Makefile lib/export/samples/Makefile-postinstall lib/irs/Makefile lib/irs/include/Makefile lib/irs/include/irs/Makefile lib/irs/include/irs/netdb.h lib/irs/include/irs/platform.h lib/isc/$arch/Makefile lib/isc/$arch/include/Makefile lib/isc/$arch/include/isc/Makefile lib/isc/$thread_dir/Makefile lib/isc/$thread_dir/include/Makefile lib/isc/$thread_dir/include/isc/Makefile lib/isc/Makefile lib/isc/include/Makefile lib/isc/include/isc/Makefile lib/isc/include/isc/platform.h lib/isc/tests/Makefile lib/isc/nls/Makefile lib/isc/unix/Makefile lib/isc/unix/include/Makefile lib/isc/unix/include/isc/Makefile lib/isccc/Makefile lib/isccc/include/Makefile lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile lib/lwres/Makefile lib/lwres/include/Makefile lib/lwres/include/lwres/Makefile lib/lwres/include/lwres/netdb.h lib/lwres/include/lwres/platform.h lib/lwres/man/Makefile lib/lwres/unix/Makefile lib/lwres/unix/include/Makefile lib/lwres/unix/include/lwres/Makefile lib/tests/Makefile lib/tests/include/Makefile lib/tests/include/tests/Makefile unit/Makefile unit/unittest.sh" # @@ -21549,6 +21804,7 @@ do "bin/tests/system/ecdsa/prereq.sh") CONFIG_FILES="$CONFIG_FILES bin/tests/system/ecdsa/prereq.sh" ;; "bin/tests/system/dlzredir/prereq.sh") CONFIG_FILES="$CONFIG_FILES bin/tests/system/dlzredir/prereq.sh" ;; "bin/tests/system/filter-aaaa/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/filter-aaaa/Makefile" ;; + "bin/tests/system/geoip/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/geoip/Makefile" ;; "bin/tests/system/gost/prereq.sh") CONFIG_FILES="$CONFIG_FILES bin/tests/system/gost/prereq.sh" ;; "bin/tests/system/lwresd/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/lwresd/Makefile" ;; "bin/tests/system/rpz/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/rpz/Makefile" ;; diff --git a/configure.in b/configure.in index d0507de9e9..8cb26e7ba7 100644 --- a/configure.in +++ b/configure.in @@ -972,6 +972,94 @@ case "$use_pkcs11" in esac AC_SUBST(PKCS11_PROVIDER) +AC_ARG_WITH(geoip, +[ --with-geoip=PATH Build with GeoIP support (yes|no|path)], + use_geoip="$withval", use_geoip="no") + +if test "$use_geoip" = "yes" +then + for d in /usr /usr/local + do + if test -f $d/include/GeoIP.h + then + use_geoip=$d + break + fi + done +fi + +case "$use_geoip" in + no|'') + AC_MSG_CHECKING([for GeoIP support]) + AC_MSG_RESULT([disabled]) + ;; + *) + if test -d "$use_geoip" -o -L "$use_geoip" + then + CFLAGS="$CFLAGS -I$use_geoip/include" + CPPFLAGS="$CPPFLAGS -I$use_geoip/include" + case "$host_os" in + netbsd*|openbsd*|solaris*) + LIBS="$LIBS -Wl,-rpath=$use_geoip/lib" + ;; + *) + LIBS="$LIBS -L$use_geoip/lib" + esac + elif test "$use_geoip" = "yes" + then + AC_MSG_ERROR([GeoIP path not found]) + else + AC_MSG_ERROR([GeoIP path $use_geoip does not exist]) + fi + AC_CHECK_HEADER(GeoIP.h, [], + [AC_MSG_ERROR([GeoIP header file not found])] + ) + AC_SEARCH_LIBS(GeoIP_open, GeoIP, [], + [AC_MSG_ERROR([GeoIP library not found])] + ) + AC_SEARCH_LIBS(fabsf, m, [], + [AC_MSG_ERROR([Math library not found])] + ) + AC_DEFINE(HAVE_GEOIP, 1, Build with GeoIP support) + AC_MSG_CHECKING([for GeoIP support]) + AC_MSG_RESULT([yes]) + + AC_MSG_CHECKING([for GeoIP Country IPv6 support]) + AC_COMPILE_IFELSE( + AC_LANG_PROGRAM([[ + #include + #include + ]], [[ + struct in6_addr in6; + GeoIP_country_name_by_ipnum_v6(NULL, in6); + ]]), + [ + AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_GEOIP_V6, 1, Build with GeoIP Country IPv6 support) + ], + [AC_MSG_RESULT([no])] + ) + + AC_MSG_CHECKING([for GeoIP City IPv6 support]) + AC_COMPILE_IFELSE( + AC_LANG_PROGRAM([[ + #include + #include + #include + ]], [[ + struct in6_addr in6; + int i = GEOIP_CITY_EDITION_REV0_V6; + GeoIP_record_by_ipnum_v6(NULL, in6); + ]]), + [ + AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_GEOIP_CITY_V6, 1, Build with GeoIP City IPv6 support) + ], + [AC_MSG_RESULT([no])] + ) + ;; +esac + AC_MSG_CHECKING(for GSSAPI library) AC_ARG_WITH(gssapi, [ --with-gssapi=PATH Specify path for system-supplied GSSAPI [[default=yes]]], @@ -3663,6 +3751,7 @@ AC_CONFIG_FILES([ bin/tests/system/ecdsa/prereq.sh bin/tests/system/dlzredir/prereq.sh bin/tests/system/filter-aaaa/Makefile + bin/tests/system/geoip/Makefile bin/tests/system/gost/prereq.sh bin/tests/system/lwresd/Makefile bin/tests/system/rpz/Makefile diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 7a8e3da7a7..ae05be870f 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -3957,6 +3957,62 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. + + When BIND 9 is built with GeoIP support, + ACLs can also be used for geographic access restrictions. + This is done by specifying an ACL element of the form: + geoip db database field value + + + The field indicates which field + to search for a match. Available fields are "country", + "region", "city", "continent", "postal" (postal code), + "metro" (metro code), "area" (area code), "tz" (timezone), + "isp", "org", "asnum", "domain" and "netspeed". + + + value is the value to searched for + within the database. A string may be quoted if it contains + spaces or other special characters. If this is a "country" + search and the string is two characters long, then it must be a + standard ISO-3166-1 two-letter country code, and if it is three + characters long then it must be an ISO-3166-1 three-letter + country code; otherwise it is the full name of the country. + Similarly, if this is a "region" search and the string is + two characters long, then it must be a standard two-letter state + or province abbreviation; otherwise it is the full name of the + state or province. + + + The database field indicates which + GeoIP database to search for a match. In most cases this is + unnecessary, because most search fields can only be found in + a single database. However, searches for country can be + answered from the "city", "region", or "country" databases, + and searches for region (i.e., state or provice) can be + answered from the "city" or "region" databases. For these + search types, specifying a database + will force the query to be answered from that database and no + other. If database is not + specified, then these queries will be answered from the "city", + database if it is installed, or the "region" database if it is + installed, or the "country" database, in that order. + + + Some example GeoIP ACLs: + + geoip country US; +geoip country JAP; +geoip db country country Canada; +geoip db region region WA; +geoip city "San Francisco"; +geoip region Oklahoma; +geoip postal 95062; +geoip tz "America/Los_Angeles"; +geoip org "Internet Systems Consortium"; + + + <command>controls</command> Statement Grammar diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in index 6903babc98..dc810ef42e 100644 --- a/lib/dns/Makefile.in +++ b/lib/dns/Makefile.in @@ -62,8 +62,8 @@ DSTOBJS = @DST_EXTRA_OBJS@ @OPENSSLLINKOBJS@ \ DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \ cache.@O@ callbacks.@O@ clientinfo.@O@ compress.@O@ \ db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \ - dlz.@O@ dns64.@O@ dnssec.@O@ ds.@O@ forward.@O@ iptable.@O@ \ - journal.@O@ keydata.@O@ keytable.@O@ \ + dlz.@O@ dns64.@O@ dnssec.@O@ ds.@O@ forward.@O@ geoip.@O@\ + iptable.@O@ journal.@O@ keydata.@O@ keytable.@O@ \ lib.@O@ log.@O@ lookup.@O@ \ master.@O@ masterdump.@O@ message.@O@ \ name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ order.@O@ peer.@O@ \ @@ -92,9 +92,9 @@ DSTSRCS = @DST_EXTRA_SRCS@ @OPENSSLLINKSRCS@ \ DNSSRCS = acache.c acl.c adb.c byaddr.c \ cache.c callbacks.c clientinfo.c compress.c \ db.c dbiterator.c dbtable.c diff.c dispatch.c \ - dlz.c dns64.c dnssec.c ds.c forward.c iptable.c journal.c \ - keydata.c keytable.c lib.c log.c lookup.c \ - master.c masterdump.c message.c \ + dlz.c dns64.c dnssec.c ds.c forward.c geoip.c \ + iptable.c journal.c keydata.c keytable.c lib.c log.c \ + lookup.c master.c masterdump.c message.c \ name.c ncache.c nsec.c nsec3.c order.c peer.c portlist.c \ rbt.c rbtdb.c rbtdb64.c rcode.c rdata.c rdatalist.c \ rdataset.c rdatasetiter.c rdataslab.c request.c \ diff --git a/lib/dns/acl.c b/lib/dns/acl.c index 3221d30c2b..78b0929aa6 100644 --- a/lib/dns/acl.c +++ b/lib/dns/acl.c @@ -29,6 +29,7 @@ #include #include + /* * Create a new ACL, including an IP table and an array with room * for 'n' ACL elements. The elements are uninitialized and the @@ -386,9 +387,8 @@ dns_aclelement_match(const isc_netaddr_t *reqaddr, if (matchelt != NULL) *matchelt = e; return (ISC_TRUE); - } else { + } else return (ISC_FALSE); - } case dns_aclelementtype_nestedacl: inner = e->nestedacl; @@ -406,6 +406,10 @@ dns_aclelement_match(const isc_netaddr_t *reqaddr, inner = env->localnets; break; +#ifdef HAVE_GEOIP + case dns_aclelementtype_geoip: + return (dns_geoip_match(reqaddr, env->geoip, &e->geoip_elem)); +#endif default: /* Should be impossible. */ INSIST(0); @@ -560,7 +564,7 @@ dns_acl_isinsecure(const dns_acl_t *a) { insecure = insecure_prefix_found; UNLOCK(&insecure_prefix_lock); if (insecure) - return(ISC_TRUE); + return (ISC_TRUE); /* Now check non-radix elements */ for (i = 0; i < a->length; i++) { @@ -609,6 +613,9 @@ dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env) { if (result != ISC_R_SUCCESS) goto cleanup_localhost; env->match_mapped = ISC_FALSE; +#ifdef HAVE_GEOIP + env->geoip = NULL; +#endif return (ISC_R_SUCCESS); cleanup_localhost: diff --git a/lib/dns/geoip.c b/lib/dns/geoip.c new file mode 100644 index 0000000000..ef3bb10134 --- /dev/null +++ b/lib/dns/geoip.c @@ -0,0 +1,775 @@ +/* + * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/*! \file */ + +#include + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#ifdef HAVE_GEOIP +#include +#include + +/* + * This structure preserves state from the previous GeoIP lookup, + * so that successive lookups for the same data from the same IP + * address will not require repeated calls into the GeoIP library + * to look up data in the database. This should improve performance + * somwhat. + * + * For lookups in the City and Region databases, we preserve pointers + * to the GeoIPRecord and GeoIPregion structures; these will need to be + * freed by GeoIPRecord_delete() and GeoIPRegion_delete(). + * + * for lookups in ISP, AS, Org and Domain we prserve a pointer to + * the returned name; these must be freed by free(). + * + * For lookups in Country we preserve a pointer to the text of + * the country code, name, etc (we use a different pointer for this + * than for the names returned by Org, ISP, etc, because those need + * to be freed but country lookups do not). + * + * For lookups in Netspeed we preserve the returned ID. + * + * XXX: Currently this mechanism is only used for IPv4 lookups; the + * family and addr6 fields are to be used IPv6 is added. + */ +typedef struct geoip_state { + isc_uint16_t subtype; + unsigned int family; + isc_uint32_t ipnum; + geoipv6_t ipnum6; + GeoIPRecord *record; + GeoIPRegion *region; + const char *text; + char *name; + int id; + isc_mem_t *mctx; +} geoip_state_t; + +#ifdef ISC_PLATFORM_USETHREADS +static isc_mutex_t key_mutex; +static isc_boolean_t state_key_initialized = ISC_FALSE; +static isc_thread_key_t state_key; +static isc_once_t mutex_once = ISC_ONCE_INIT; +static isc_mem_t *state_mctx = NULL; + +static void +key_mutex_init(void) { + RUNTIME_CHECK(isc_mutex_init(&key_mutex) == ISC_R_SUCCESS); +} + +static void +free_state(void *arg) { + geoip_state_t *state = arg; + if (state != NULL && state->record != NULL) + GeoIPRecord_delete(state->record); + if (state != NULL) + isc_mem_putanddetach(&state->mctx, + state, sizeof(geoip_state_t)); + isc_thread_key_setspecific(state_key, NULL); +} + +static isc_result_t +state_key_init(void) { + isc_result_t result; + + result = isc_once_do(&mutex_once, key_mutex_init); + if (result != ISC_R_SUCCESS) + return (result); + + if (!state_key_initialized) { + LOCK(&key_mutex); + if (!state_key_initialized) { + if (state_mctx == NULL) + result = isc_mem_create2(0, 0, &state_mctx, 0); + if (result != ISC_R_SUCCESS) + goto unlock; + isc_mem_setname(state_mctx, "geoip_state", NULL); + isc_mem_setdestroycheck(state_mctx, ISC_FALSE); + + int ret = isc_thread_key_create(&state_key, free_state); + if (ret == 0) + state_key_initialized = ISC_TRUE; + else + result = ISC_R_FAILURE; + } + unlock: + UNLOCK(&key_mutex); + } + + return (result); +} +#else +geoip_state_t prev_state; +#endif + +static void +clean_state(geoip_state_t *state) { + if (state == NULL) + return; + + if (state->record != NULL) + GeoIPRecord_delete(state->record); + if (state->region != NULL) + GeoIPRegion_delete(state->region); + if (state->name != NULL) + free (state->name); + state->ipnum = 0; + state->text = NULL; + state->id = 0; +} + +static isc_result_t +set_state(unsigned int family, isc_uint32_t ipnum, const geoipv6_t *ipnum6, + dns_geoip_subtype_t subtype, GeoIPRecord *record, + GeoIPRegion *region, char *name, const char *text, int id) +{ + isc_result_t result; + geoip_state_t *state = NULL; + +#ifdef ISC_PLATFORM_USETHREADS + result = state_key_init(); + if (result != ISC_R_SUCCESS) + return (result); + + state = (geoip_state_t *) isc_thread_key_getspecific(state_key); + if (state == NULL) { + state = (geoip_state_t *) isc_mem_get(state_mctx, + sizeof(geoip_state_t)); + if (state == NULL) + return (ISC_R_NOMEMORY); + memset(state, 0, sizeof(*state)); + + result = isc_thread_key_setspecific(state_key, state); + if (result != ISC_R_SUCCESS) { + isc_mem_put(state_mctx, state, sizeof(geoip_state_t)); + return (result); + } + + isc_mem_attach(state_mctx, &state->mctx); + } else + clean_state(state); +#else + state = &prev_state; + if (state->ipnum != ipnum) + clean_state(state); +#endif + + if (family == AF_INET) + state->ipnum = ipnum; + else + state->ipnum6 = *ipnum6; + + state->family = family; + state->subtype = subtype; + state->record = record; + state->region = region; + state->name = name; + state->text = text; + state->id = id; + + return (ISC_R_SUCCESS); +} + +static geoip_state_t * +get_state() { +#ifdef ISC_PLATFORM_USETHREADS + isc_result_t result; + geoip_state_t *state; + + result = state_key_init(); + if (result != ISC_R_SUCCESS) + return (NULL); + + state = (geoip_state_t *) isc_thread_key_getspecific(state_key); + return (state); +#else + return (&prev_state); +#endif +} + +/* + * Country lookups are performed if the previous lookup was from a + * different IP address than the current, or was for a search of a + * different subtype. + */ +static const char * +country_lookup(GeoIP *db, dns_geoip_subtype_t subtype, + unsigned int family, + isc_uint32_t ipnum, const geoipv6_t *ipnum6) +{ + geoip_state_t *prev_state = NULL; + const char *text = NULL; + + REQUIRE(db != NULL); + +#ifndef HAVE_GEOIP_V6 + /* no IPv6 support? give up now */ + if (family == AF_INET6) + return (NULL); +#endif + + prev_state = get_state(); + + if (prev_state != NULL && + prev_state->subtype == subtype && + ((prev_state->family == AF_INET && prev_state->ipnum == ipnum) || + (prev_state->family == AF_INET6 && + memcmp(prev_state->ipnum6.s6_addr, ipnum6->s6_addr, 16) == 0))) + text = prev_state->text; + + if (text == NULL) { + switch (subtype) { + case dns_geoip_country_code: + if (family == AF_INET) + text = GeoIP_country_code_by_ipnum(db, ipnum); +#ifdef HAVE_GEOIP_V6 + else + text = GeoIP_country_code_by_ipnum_v6(db, + *ipnum6); +#endif + break; + case dns_geoip_country_code3: + if (family == AF_INET) + text = GeoIP_country_code3_by_ipnum(db, ipnum); +#ifdef HAVE_GEOIP_V6 + else + text = GeoIP_country_code3_by_ipnum_v6(db, + *ipnum6); +#endif + break; + case dns_geoip_country_name: + if (family == AF_INET) + text = GeoIP_country_name_by_ipnum(db, ipnum); +#ifdef HAVE_GEOIP_V6 + else + text = GeoIP_country_name_by_ipnum_v6(db, + *ipnum6); +#endif + break; + default: + INSIST(0); + } + + set_state(family, ipnum, ipnum6, subtype, + NULL, NULL, NULL, text, 0); + } + + return (text); +} + +static char * +city_string(GeoIPRecord *record, dns_geoip_subtype_t subtype, int *maxlen) { + const char *s; + char *deconst; + + REQUIRE(record != NULL); + REQUIRE(maxlen != NULL); + + /* Set '*maxlen' to the maximum length of this subtype, if any */ + switch (subtype) { + case dns_geoip_city_countrycode: + case dns_geoip_city_region: + case dns_geoip_city_continentcode: + *maxlen = 2; + break; + + case dns_geoip_city_countrycode3: + *maxlen = 3; + break; + + default: + /* No fixed length; just use strcasecmp() for comparison */ + *maxlen = 255; + } + + switch (subtype) { + case dns_geoip_city_countrycode: + return (record->country_code); + case dns_geoip_city_countrycode3: + return (record->country_code3); + case dns_geoip_city_countryname: + return (record->country_name); + case dns_geoip_city_region: + return (record->region); + case dns_geoip_city_regionname: + s = GeoIP_region_name_by_code(record->country_code, + record->region); + DE_CONST(s, deconst); + return (deconst); + case dns_geoip_city_name: + return (record->city); + case dns_geoip_city_postalcode: + return (record->postal_code); + case dns_geoip_city_continentcode: + return (record->continent_code); + case dns_geoip_city_timezonecode: + s = GeoIP_time_zone_by_country_and_region(record->country_code, + record->region); + DE_CONST(s, deconst); + return (deconst); + default: + INSIST(0); + } +} + +static isc_boolean_t +is_city(dns_geoip_subtype_t subtype) { + switch (subtype) { + case dns_geoip_city_countrycode: + case dns_geoip_city_countrycode3: + case dns_geoip_city_countryname: + case dns_geoip_city_region: + case dns_geoip_city_regionname: + case dns_geoip_city_name: + case dns_geoip_city_postalcode: + case dns_geoip_city_continentcode: + case dns_geoip_city_timezonecode: + case dns_geoip_city_metrocode: + case dns_geoip_city_areacode: + return (ISC_TRUE); + default: + return (ISC_FALSE); + } +} + +/* + * GeoIPRecord lookups are performed if the previous lookup was + * from a different IP address than the current, or was for a search + * outside the City database. + */ +static GeoIPRecord * +city_lookup(GeoIP *db, dns_geoip_subtype_t subtype, + unsigned int family, isc_uint32_t ipnum, const geoipv6_t *ipnum6) +{ + GeoIPRecord *record = NULL; + geoip_state_t *prev_state = NULL; + + REQUIRE(db != NULL); + +#ifndef HAVE_GEOIP_V6 + /* no IPv6 support? give up now */ + if (family == AF_INET6) + return (NULL); +#endif + + prev_state = get_state(); + + if (prev_state != NULL && + is_city(prev_state->subtype) && + ((prev_state->family == AF_INET && prev_state->ipnum == ipnum) || + (prev_state->family == AF_INET6 && + memcmp(prev_state->ipnum6.s6_addr, ipnum6->s6_addr, 16) == 0))) + record = prev_state->record; + + if (record == NULL) { + if (family == AF_INET) + record = GeoIP_record_by_ipnum(db, ipnum); +#ifdef HAVE_GEOIP_V6 + else + record = GeoIP_record_by_ipnum_v6(db, *ipnum6); +#endif + if (record == NULL) + return (NULL); + + set_state(family, ipnum, ipnum6, subtype, + record, NULL, NULL, NULL, 0); + } + + return (record); +} + +static char * +region_string(GeoIPRegion *region, dns_geoip_subtype_t subtype, int *maxlen) { + const char *s; + char *deconst; + + REQUIRE(region != NULL); + REQUIRE(maxlen != NULL); + + switch (subtype) { + case dns_geoip_region_countrycode: + *maxlen = 2; + return (region->country_code); + case dns_geoip_region_code: + *maxlen = 2; + return (region->region); + case dns_geoip_region_name: + *maxlen = 255; + s = GeoIP_region_name_by_code(region->country_code, + region->region); + DE_CONST(s, deconst); + return (deconst); + default: + INSIST(0); + } +} + +static isc_boolean_t +is_region(dns_geoip_subtype_t subtype) { + switch (subtype) { + case dns_geoip_region_countrycode: + case dns_geoip_region_code: + return (ISC_TRUE); + default: + return (ISC_FALSE); + } +} + +/* + * GeoIPRegion lookups are performed if the previous lookup was + * from a different IP address than the current, or was for a search + * outside the Region database. + */ +static GeoIPRegion * +region_lookup(GeoIP *db, dns_geoip_subtype_t subtype, isc_uint32_t ipnum) { + GeoIPRegion *region = NULL; + geoip_state_t *prev_state = NULL; + + REQUIRE(db != NULL); + + prev_state = get_state(); + + if (prev_state != NULL && prev_state->ipnum == ipnum && + is_region(prev_state->subtype)) + region = prev_state->region; + + if (region == NULL) { + region = GeoIP_region_by_ipnum(db, ipnum); + if (region == NULL) + return (NULL); + + set_state(AF_INET, ipnum, NULL, + subtype, NULL, region, NULL, NULL, 0); + } + + return (region); +} + +/* + * ISP, Organization, AS Number and Domain lookups are performed if + * the previous lookup was from a different IP address than the current, + * or was for a search of a different subtype. + */ +static char * +name_lookup(GeoIP *db, dns_geoip_subtype_t subtype, isc_uint32_t ipnum) { + char *name = NULL; + geoip_state_t *prev_state = NULL; + + REQUIRE(db != NULL); + + prev_state = get_state(); + + if (prev_state != NULL && prev_state->ipnum == ipnum && + prev_state->subtype == subtype) + name = prev_state->name; + + if (name == NULL) { + name = GeoIP_name_by_ipnum(db, ipnum); + if (name == NULL) + return (NULL); + + set_state(AF_INET, ipnum, NULL, + subtype, NULL, NULL, name, NULL, 0); + } + + return (name); +} + +/* + * Netspeed lookups are performed if the previous lookup was from a + * different IP address than the current, or was for a search of a + * different subtype. + */ +static int +netspeed_lookup(GeoIP *db, dns_geoip_subtype_t subtype, isc_uint32_t ipnum) { + geoip_state_t *prev_state = NULL; + isc_boolean_t found = ISC_FALSE; + int id; + + REQUIRE(db != NULL); + + prev_state = get_state(); + + if (prev_state != NULL && prev_state->ipnum == ipnum && + prev_state->subtype == subtype) { + id = prev_state->id; + found = ISC_TRUE; + } + + if (!found) { + id = GeoIP_id_by_ipnum(db, ipnum); + set_state(AF_INET, ipnum, NULL, + subtype, NULL, NULL, NULL, NULL, id); + } + + return (id); +} +#endif /* HAVE_GEOIP */ + +#define DB46(addr, geoip, name) \ + ((addr->family == AF_INET) ? (geoip->name##_v4) : (geoip->name##_v6)) + +/* + * Find the best database to answer a generic subtype + */ +static dns_geoip_subtype_t +fix_subtype(const isc_netaddr_t *reqaddr, const dns_geoip_databases_t *geoip, + dns_geoip_subtype_t subtype) +{ + dns_geoip_subtype_t ret = subtype; + + switch (subtype) { + case dns_geoip_countrycode: + if (DB46(reqaddr, geoip, city) != NULL) + ret = dns_geoip_city_countrycode; + else if (reqaddr->family == AF_INET && geoip->region != NULL) + ret = dns_geoip_region_countrycode; + else if (DB46(reqaddr, geoip, country) != NULL) + ret = dns_geoip_country_code; + break; + case dns_geoip_countrycode3: + if (DB46(reqaddr, geoip, city) != NULL) + ret = dns_geoip_city_countrycode3; + else if (DB46(reqaddr, geoip, country) != NULL) + ret = dns_geoip_country_code3; + break; + case dns_geoip_countryname: + if (DB46(reqaddr, geoip, city) != NULL) + ret = dns_geoip_city_countryname; + else if (DB46(reqaddr, geoip, country) != NULL) + ret = dns_geoip_country_name; + break; + case dns_geoip_region: + if (DB46(reqaddr, geoip, city) != NULL) + ret = dns_geoip_city_region; + else if (reqaddr->family == AF_INET && geoip->region != NULL) + ret = dns_geoip_region_code; + break; + case dns_geoip_regionname: + if (DB46(reqaddr, geoip, city) != NULL) + ret = dns_geoip_city_regionname; + else if (reqaddr->family == AF_INET && geoip->region != NULL) + ret = dns_geoip_region_name; + break; + default: + break; + } + + return (ret); +} + +isc_boolean_t +dns_geoip_match(const isc_netaddr_t *reqaddr, + const dns_geoip_databases_t *geoip, + const dns_geoip_elem_t *elt) +{ +#ifndef HAVE_GEOIP + UNUSED(reqaddr); + UNUSED(geoip); + UNUSED(elt); + + return (ISC_FALSE); +#else + GeoIP *db; + GeoIPRecord *record; + GeoIPRegion *region; + dns_geoip_subtype_t subtype; + isc_uint32_t ipnum = 0; + int maxlen = 0, id; + const char *cs; + char *s; +#ifdef HAVE_GEOIP_V6 + const geoipv6_t *ipnum6 = NULL; +#else + const void *ipnum6 = NULL; +#endif + + INSIST(geoip != NULL); + + switch (reqaddr->family) { + case AF_INET: + ipnum = ntohl(reqaddr->type.in.s_addr); + break; + case AF_INET6: +#ifdef HAVE_GEOIP_V6 + ipnum6 = &reqaddr->type.in6; + break; +#else + return (ISC_FALSE); +#endif + default: + return (ISC_FALSE); + } + + subtype = fix_subtype(reqaddr, geoip, elt->subtype); + + switch (subtype) { + case dns_geoip_country_code: + maxlen = 2; + goto getcountry; + + case dns_geoip_country_code3: + maxlen = 3; + goto getcountry; + + case dns_geoip_country_name: + maxlen = 255; + getcountry: + db = DB46(reqaddr, geoip, country); + INSIST(db != NULL); + INSIST(elt->as_string != NULL); + cs = country_lookup(db, subtype, reqaddr->family, + ipnum, ipnum6); + if (cs != NULL && strncasecmp(elt->as_string, cs, maxlen) == 0) + return (ISC_TRUE); + break; + + case dns_geoip_city_countrycode: + case dns_geoip_city_countrycode3: + case dns_geoip_city_countryname: + case dns_geoip_city_region: + case dns_geoip_city_regionname: + case dns_geoip_city_name: + case dns_geoip_city_postalcode: + case dns_geoip_city_continentcode: + case dns_geoip_city_timezonecode: + INSIST(elt->as_string != NULL); + + db = DB46(reqaddr, geoip, city); + record = city_lookup(db, subtype, + reqaddr->family, ipnum, ipnum6); + if (record == NULL) + break; + + s = city_string(record, subtype, &maxlen); + INSIST(maxlen != 0); + if (s != NULL && strncasecmp(elt->as_string, s, maxlen) == 0) + return (ISC_TRUE); + break; + + case dns_geoip_city_metrocode: + db = DB46(reqaddr, geoip, city); + record = city_lookup(db, subtype, + reqaddr->family, ipnum, ipnum6); + if (record == NULL) + break; + + if (elt->as_int == record->metro_code) + return (ISC_TRUE); + break; + + case dns_geoip_city_areacode: + db = DB46(reqaddr, geoip, city); + record = city_lookup(db, subtype, + reqaddr->family, ipnum, ipnum6); + if (record == NULL) + break; + + if (elt->as_int == record->area_code) + return (ISC_TRUE); + break; + + case dns_geoip_region_countrycode: + case dns_geoip_region_code: + case dns_geoip_region_name: + INSIST(geoip->region != NULL); + INSIST(elt->as_string != NULL); + + /* Region DB is not supported for IPv6 */ + if (reqaddr->family == AF_INET6) + return (ISC_FALSE); + + region = region_lookup(geoip->region, subtype, ipnum); + if (region == NULL) + break; + + s = region_string(region, subtype, &maxlen); + INSIST(maxlen != 0); + if (s != NULL && strncasecmp(elt->as_string, s, maxlen) == 0) + return (ISC_TRUE); + break; + + case dns_geoip_isp_name: + db = geoip->isp; + goto getname; + + case dns_geoip_org_name: + db = geoip->org; + goto getname; + + case dns_geoip_as_asnum: + db = geoip->as; + goto getname; + + case dns_geoip_domain_name: + db = geoip->domain; + + getname: + INSIST(db != NULL); + INSIST(elt->as_string != NULL); + /* ISP, Org, AS, and Domain are not supported for IPv6 */ + if (reqaddr->family == AF_INET6) + return (ISC_FALSE); + + s = name_lookup(db, subtype, ipnum); + if (s != NULL && strcasecmp(elt->as_string, s) == 0) + return (ISC_TRUE); + break; + + case dns_geoip_netspeed_id: + INSIST(geoip->netspeed != NULL); + + /* Netspeed DB is not supported for IPv6 */ + if (reqaddr->family == AF_INET6) + return (ISC_FALSE); + + id = netspeed_lookup(geoip->netspeed, subtype, ipnum); + if (id == elt->as_int) + return (ISC_TRUE); + break; + + default: + INSIST(0); + } + + return (ISC_FALSE); +#endif +} + +void +dns_geoip_shutdown(void) { +#if defined(HAVE_GEOIP) && defined(ISC_PLATFORM_USETHREADS) + if (state_mctx != NULL) + isc_mem_detach(&state_mctx); +#else + return; +#endif +} diff --git a/lib/dns/include/dns/Makefile.in b/lib/dns/include/dns/Makefile.in index 113e187a4c..19a5be19f0 100644 --- a/lib/dns/include/dns/Makefile.in +++ b/lib/dns/include/dns/Makefile.in @@ -23,13 +23,14 @@ top_srcdir = @top_srcdir@ HEADERS = acl.h adb.h byaddr.h cache.h callbacks.h cert.h compress.h \ clientinfo.h db.h dbiterator.h dbtable.h diff.h dispatch.h \ - dlz.h dnssec.h ds.h dsdigest.h events.h fixedname.h iptable.h \ - journal.h keyflags.h keytable.h keyvalues.h lib.h log.h \ - master.h masterdump.h message.h name.h ncache.h nsec.h \ - peer.h portlist.h private.h rbt.h rcode.h \ - rdata.h rdataclass.h rdatalist.h rdataset.h rdatasetiter.h \ - rdataslab.h rdatatype.h request.h resolver.h result.h \ - rootns.h rpz.h sdb.h sdlz.h secalg.h secproto.h soa.h ssu.h \ + dlz.h dnssec.h ds.h dsdigest.h events.h fixedname.h geoip.h \ + iptable.h journal.h keyflags.h keytable.h keyvalues.h \ + lib.h log.h master.h masterdump.h message.h \ + name.h ncache.h nsec.h peer.h portlist.h private.h \ + rbt.h rcode.h rdata.h rdataclass.h rdatalist.h \ + rdataset.h rdatasetiter.h rdataslab.h rdatatype.h \ + request.h resolver.h result.h rootns.h rpz.h \ + sdb.h sdlz.h secalg.h secproto.h soa.h ssu.h \ tcpmsg.h time.h tkey.h tsig.h ttl.h types.h \ validator.h version.h view.h xfrin.h zone.h zonekey.h zt.h diff --git a/lib/dns/include/dns/acl.h b/lib/dns/include/dns/acl.h index f4fc4a3bf9..5ce3dc49e3 100644 --- a/lib/dns/include/dns/acl.h +++ b/lib/dns/include/dns/acl.h @@ -38,10 +38,15 @@ #include #include +#include #include #include #include +#ifdef HAVE_GEOIP +#include +#endif + /*** *** Types ***/ @@ -52,8 +57,11 @@ typedef enum { dns_aclelementtype_nestedacl, dns_aclelementtype_localhost, dns_aclelementtype_localnets, +#ifdef HAVE_GEOIP + dns_aclelementtype_geoip, +#endif /* HAVE_GEOIP */ dns_aclelementtype_any -} dns_aclelemettype_t; +} dns_aclelementtype_t; typedef struct dns_aclipprefix dns_aclipprefix_t; @@ -63,9 +71,12 @@ struct dns_aclipprefix { }; struct dns_aclelement { - dns_aclelemettype_t type; + dns_aclelementtype_t type; isc_boolean_t negative; dns_name_t keyname; +#ifdef HAVE_GEOIP + dns_geoip_elem_t geoip_elem; +#endif /* HAVE_GEOIP */ dns_acl_t *nestedacl; int node_num; }; @@ -88,6 +99,9 @@ struct dns_aclenv { dns_acl_t *localhost; dns_acl_t *localnets; isc_boolean_t match_mapped; +#ifdef HAVE_GEOIP + dns_geoip_databases_t *geoip; +#endif }; #define DNS_ACL_MAGIC ISC_MAGIC('D','a','c','l') diff --git a/lib/dns/include/dns/geoip.h b/lib/dns/include/dns/geoip.h new file mode 100644 index 0000000000..bad94856f0 --- /dev/null +++ b/lib/dns/include/dns/geoip.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DNS_GEOIP_H +#define DNS_GEOIP_H 1 + +/***** + ***** Module Info + *****/ + +/*! \file dns/acl.h + * \brief + * Address match list handling. + */ + +/*** + *** Imports + ***/ + +#include +#include +#include +#include + +#include +#include +#include + +#ifdef HAVE_GEOIP +#include +#else +typedef void GeoIP; +#endif + +/*** + *** Types + ***/ + +typedef enum { + dns_geoip_countrycode, + dns_geoip_countrycode3, + dns_geoip_countryname, + dns_geoip_region, + dns_geoip_regionname, + dns_geoip_country_code, + dns_geoip_country_code3, + dns_geoip_country_name, + dns_geoip_region_countrycode, + dns_geoip_region_code, + dns_geoip_region_name, + dns_geoip_city_countrycode, + dns_geoip_city_countrycode3, + dns_geoip_city_countryname, + dns_geoip_city_region, + dns_geoip_city_regionname, + dns_geoip_city_name, + dns_geoip_city_postalcode, + dns_geoip_city_metrocode, + dns_geoip_city_areacode, + dns_geoip_city_continentcode, + dns_geoip_city_timezonecode, + dns_geoip_isp_name, + dns_geoip_org_name, + dns_geoip_as_asnum, + dns_geoip_domain_name, + dns_geoip_netspeed_id +} dns_geoip_subtype_t; + +typedef struct dns_geoip_elem { + dns_geoip_subtype_t subtype; + GeoIP *db; + union { + char as_string[256]; + int as_int; + }; +} dns_geoip_elem_t; + +typedef struct dns_geoip_databases { + GeoIP *country_v4; /* DB 1 */ + GeoIP *city_v4; /* DB 2 or 6 */ + GeoIP *region; /* DB 3 or 7 */ + GeoIP *isp; /* DB 4 */ + GeoIP *org; /* DB 5 */ + GeoIP *as; /* DB 9 */ + GeoIP *netspeed; /* DB 10 */ + GeoIP *domain; /* DB 11 */ + GeoIP *country_v6; /* DB 12 */ + GeoIP *city_v6; /* DB 30 or 31 */ +} dns_geoip_databases_t; + +/*** + *** Functions + ***/ + +ISC_LANG_BEGINDECLS + +isc_boolean_t +dns_geoip_match(const isc_netaddr_t *reqaddr, + const dns_geoip_databases_t *geoip, + const dns_geoip_elem_t *elt); + +void +dns_geoip_shutdown(void); + +ISC_LANG_ENDDECLS +#endif /* DNS_GEOIP_H */ diff --git a/lib/dns/tests/Makefile.in b/lib/dns/tests/Makefile.in index ddf07ba617..3c13901173 100644 --- a/lib/dns/tests/Makefile.in +++ b/lib/dns/tests/Makefile.in @@ -39,15 +39,15 @@ LIBS = @LIBS@ @ATFLIBS@ OBJS = dnstest.@O@ SRCS = dnstest.c master_test.c dbiterator_test.c time_test.c \ private_test.c update_test.c zonemgr_test.c zt_test.c \ - dbdiff_test.c nsec3_test.c dispatch_test.c rbt_test.c \ - rdata_test.c rdataset_test.c rdatasetstats_test.c + dbdiff_test.c geoip_test.c nsec3_test.c dispatch_test.c \ + rbt_test.c rdata_test.c rdataset_test.c rdatasetstats_test.c SUBDIRS = TARGETS = master_test@EXEEXT@ dbiterator_test@EXEEXT@ time_test@EXEEXT@ \ private_test@EXEEXT@ update_test@EXEEXT@ zonemgr_test@EXEEXT@ \ zt_test@EXEEXT@ dbversion_test@EXEEXT@ dbdiff_test@EXEEXT@ \ - nsec3_test@EXEEXT@ dispatch_test@EXEEXT@ rbt_test@EXEEXT@ \ - rdata_test@EXEEXT@ rdataset_test@EXEEXT@ \ + geoip_test@EXEEXT@ nsec3_test@EXEEXT@ dispatch_test@EXEEXT@ \ + rbt_test@EXEEXT@ rdata_test@EXEEXT@ rdataset_test@EXEEXT@ \ rdatasetstats_test@EXEEXT@ @BIND9_MAKE_RULES@ @@ -134,6 +134,11 @@ rdata_test@EXEEXT@: rdata_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ rdata_test.@O@ ${DNSLIBS} ${ISCLIBS} ${LIBS} +geoip_test@EXEEXT@: geoip_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + geoip_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + unit:: sh ${top_srcdir}/unit/unittest.sh diff --git a/lib/dns/tests/geoip_test.c b/lib/dns/tests/geoip_test.c new file mode 100644 index 0000000000..e2ddf18c33 --- /dev/null +++ b/lib/dns/tests/geoip_test.c @@ -0,0 +1,703 @@ +/* + * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id$ */ + +/*! \file */ + +#include + +#include + +#include + +#include + +#include + +#include "dnstest.h" + +#ifdef HAVE_GEOIP +#include + +/* We use GeoIP databases from the 'geoip' system test */ +#define 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, + 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 DB not available\n", name); + return; + } + + fprintf(stderr, "initializing GeoIP %s DB\n", name); + + db = GeoIP_open_type(edition, method); + if (db == NULL) { + fprintf(stderr, "failed to initialize GeoIP %s DB; " + "geoip matches using this database will fail\n", + name); + return; + } + + info = GeoIP_database_info(db); + if (info != NULL) + fprintf(stderr, "%s\n", info); + + *dbp = db; +} + +static GeoIPDBTypes +choose_rev(GeoIPDBTypes primary, GeoIPDBTypes secondary, const char *name) { + if (GeoIP_db_avail(primary)) + return (primary); + if (GeoIP_db_avail(secondary)) + return (secondary); + fprintf(stderr, "GeoIP %s DB: neither revision available\n", name); + return (0); +} + +static void +load_geoip(const char *dir) { + GeoIPOptions method; + GeoIPDBTypes edition; + +#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, + method, "Country (IPv4)"); +#ifdef HAVE_GEOIP_V6 + init_geoip_db(&geoip.country_v6, GEOIP_COUNTRY_EDITION_V6, + method, "Country (IPv6)"); +#endif + + edition = choose_rev(GEOIP_CITY_EDITION_REV0, + GEOIP_CITY_EDITION_REV1, "City (IPv4)"); + if (edition != 0) + init_geoip_db(&geoip.city_v4, edition, method, "City (IPv4)"); +#if defined(HAVE_GEOIP_V6) && defined(HAVE_GEOIP_CITY_V6) + edition = choose_rev(GEOIP_CITY_EDITION_REV0_V6, + GEOIP_CITY_EDITION_REV1_V6, "City (IPv6)"); + if (edition != 0) + init_geoip_db(&geoip.city_v6, edition, method, "City (IPv6)"); +#endif + + edition = choose_rev(GEOIP_REGION_EDITION_REV0, + GEOIP_REGION_EDITION_REV1, "Region"); + if (edition != 0) + init_geoip_db(&geoip.region, edition, method, "Region"); + + init_geoip_db(&geoip.isp, GEOIP_ISP_EDITION, + method, "ISP"); + init_geoip_db(&geoip.org, GEOIP_ORG_EDITION, + method, "Org"); + init_geoip_db(&geoip.as, GEOIP_ASNUM_EDITION, + method, "AS"); + init_geoip_db(&geoip.domain, GEOIP_DOMAIN_EDITION, + method, "Domain"); + init_geoip_db(&geoip.netspeed, GEOIP_NETSPEED_EDITION, + method, "NetSpeed"); +} + +static isc_boolean_t +do_lookup_string(const char *addr, 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; + strcpy(elt.as_string, string); + + return (dns_geoip_match(&na, &geoip, &elt)); +} + +static isc_boolean_t +do_lookup_string_v6(const char *addr, 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; + strcpy(elt.as_string, string); + + return (dns_geoip_match(&na, &geoip, &elt)); +} + +static isc_boolean_t +do_lookup_int(const char *addr, 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, &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; + isc_boolean_t match; + + UNUSED(tc); + + result = dns_test_begin(NULL, ISC_TRUE); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(GEOIP_DATA); + + if (geoip.country_v4 == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + match = do_lookup_string("10.53.0.1", dns_geoip_country_code, "AU"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", + dns_geoip_country_code3, "AUS"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", + dns_geoip_country_name, "Australia"); + ATF_CHECK(match); + + 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; + isc_boolean_t match; + + UNUSED(tc); + + result = dns_test_begin(NULL, ISC_TRUE); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(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", + dns_geoip_country_code, "AU"); + ATF_CHECK(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", + dns_geoip_country_code3, "AUS"); + ATF_CHECK(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", + dns_geoip_country_name, "Australia"); + ATF_CHECK(match); + + 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; + isc_boolean_t match; + + UNUSED(tc); + + result = dns_test_begin(NULL, ISC_TRUE); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(GEOIP_DATA); + + if (geoip.city_v4 == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + match = do_lookup_string("10.53.0.1", + dns_geoip_city_continentcode, "NA"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", + dns_geoip_city_countrycode, "US"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", + dns_geoip_city_countrycode3, "USA"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", + dns_geoip_city_countryname, "United States"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", + dns_geoip_city_region, "CA"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", + dns_geoip_city_regionname, "California"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", + dns_geoip_city_name, "Redwood City"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", + dns_geoip_city_postalcode, "94063"); + ATF_CHECK(match); + + match = do_lookup_int("10.53.0.1", dns_geoip_city_areacode, 650); + ATF_CHECK(match); + + match = do_lookup_int("10.53.0.1", 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; + isc_boolean_t match; + + UNUSED(tc); + + result = dns_test_begin(NULL, ISC_TRUE); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(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", + dns_geoip_city_continentcode, "NA"); + ATF_CHECK(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", + dns_geoip_city_countrycode, "US"); + ATF_CHECK(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", + dns_geoip_city_countrycode3, "USA"); + ATF_CHECK(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", + dns_geoip_city_countryname, + "United States"); + ATF_CHECK(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", + dns_geoip_city_region, "CA"); + ATF_CHECK(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", + dns_geoip_city_regionname, "California"); + ATF_CHECK(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", + dns_geoip_city_name, "Redwood City"); + ATF_CHECK(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", + 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; + isc_boolean_t match; + + UNUSED(tc); + + result = dns_test_begin(NULL, ISC_TRUE); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(GEOIP_DATA); + + if (geoip.region == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + match = do_lookup_string("10.53.0.1", + dns_geoip_region_code, "CA"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", + dns_geoip_region_name, "California"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", + 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; + isc_boolean_t match; + + UNUSED(tc); + + result = dns_test_begin(NULL, ISC_TRUE); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(GEOIP_DATA); + + if (geoip.region == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + match = do_lookup_string("10.53.0.4", + dns_geoip_countrycode, "US"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.4", + dns_geoip_countrycode3, "USA"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.4", + dns_geoip_countryname, "United States"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.4", + dns_geoip_regionname, "Virginia"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.4", + dns_geoip_region, "VA"); + ATF_CHECK(match); + + GeoIP_delete(geoip.city_v4); + geoip.city_v4 = NULL; + + match = do_lookup_string("10.53.0.4", + 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", + dns_geoip_countrycode3, "CAN"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.4", + dns_geoip_countryname, "Canada"); + ATF_CHECK(match); + + GeoIP_delete(geoip.region); + geoip.region = NULL; + + match = do_lookup_string("10.53.0.4", + dns_geoip_countrycode, "CA"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.4", + dns_geoip_countrycode3, "CAN"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.4", + 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; + isc_boolean_t match; + + UNUSED(tc); + + result = dns_test_begin(NULL, ISC_TRUE); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(GEOIP_DATA); + + if (geoip.as == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + + match = do_lookup_string("10.53.0.3", 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; + isc_boolean_t match; + + UNUSED(tc); + + result = dns_test_begin(NULL, ISC_TRUE); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(GEOIP_DATA); + + if (geoip.isp == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + match = do_lookup_string("10.53.0.1", 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; + isc_boolean_t match; + + UNUSED(tc); + + result = dns_test_begin(NULL, ISC_TRUE); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(GEOIP_DATA); + + if (geoip.org == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + match = do_lookup_string("10.53.0.2", 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; + isc_boolean_t match; + + UNUSED(tc); + + result = dns_test_begin(NULL, ISC_TRUE); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(GEOIP_DATA); + + if (geoip.domain == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + match = do_lookup_string("10.53.0.4", + 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; + isc_boolean_t match; + + UNUSED(tc); + + result = dns_test_begin(NULL, ISC_TRUE); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(GEOIP_DATA); + + if (geoip.netspeed == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + match = do_lookup_int("10.53.0.1", dns_geoip_netspeed_id, 0); + ATF_CHECK(match); + + match = do_lookup_int("10.53.0.2", dns_geoip_netspeed_id, 1); + ATF_CHECK(match); + + match = do_lookup_int("10.53.0.3", dns_geoip_netspeed_id, 2); + ATF_CHECK(match); + + match = do_lookup_int("10.53.0.4", 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()); +} + diff --git a/lib/export/dns/Makefile.in b/lib/export/dns/Makefile.in index 41d69ddf91..48a42f47ef 100644 --- a/lib/export/dns/Makefile.in +++ b/lib/export/dns/Makefile.in @@ -58,10 +58,8 @@ DNSOBJS = acl.@O@ adb.@O@ byaddr.@O@ \ cache.@O@ callbacks.@O@ client.@O@ compress.@O@ \ db.@O@ dbiterator.@O@ diff.@O@ dispatch.@O@ dlz.@O@ dnssec.@O@ \ ds.@O@ \ - forward.@O@ iptable.@O@ \ - keytable.@O@ \ - lib.@O@ log.@O@ \ - master.@O@ masterdump.@O@ message.@O@ \ + forward.@O@ geoip.@O@ iptable.@O@ keytable.@O@ \ + lib.@O@ log.@O@ master.@O@ masterdump.@O@ message.@O@ \ name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ \ peer.@O@ portlist.@O@ \ rbt.@O@ rbtdb.@O@ rcode.@O@ rdata.@O@ \ @@ -87,10 +85,8 @@ DSTSRCS = @OPENSSLLINKSRCS@ \ DNSSRCS = acl.c adb.c byaddr.c \ cache.c callbacks.c client.c compress.c \ db.c dbiterator.c diff.c dispatch.c dlz.c dnssec.c ds.c \ - forward.c iptable.c \ - keytable.c \ - lib.c log.c \ - master.c masterdump.c message.c \ + forward.c geoip.c iptable.c keytable.c \ + lib.c log.c master.c masterdump.c message.c \ name.c ncache.c nsec.c nsec3.c \ peer.c portlist.c \ rbt.c rbtdb.c rcode.c rdata.c \ diff --git a/lib/isccfg/aclconf.c b/lib/isccfg/aclconf.c index af5659909e..0df81ac604 100644 --- a/lib/isccfg/aclconf.c +++ b/lib/isccfg/aclconf.c @@ -31,6 +31,11 @@ #include #include +#ifdef HAVE_GEOIP +#include +#include +#endif /* HAVE_GEOIP */ + #define LOOP_MAGIC ISC_MAGIC('L','O','O','P') isc_result_t @@ -53,6 +58,8 @@ cfg_aclconfctx_create(isc_mem_t *mctx, cfg_aclconfctx_t **ret) { isc_mem_attach(mctx, &actx->mctx); ISC_LIST_INIT(actx->named_acl_cache); + actx->geoip = NULL; + *ret = actx; return (ISC_R_SUCCESS); @@ -230,11 +237,15 @@ count_acl_elements(const cfg_obj_t *caml, const cfg_obj_t *cctx, elt = cfg_list_next(elt)) { const cfg_obj_t *ce = cfg_listelt_value(elt); - /* negated element; just get the value. */ + /* might be a negated element, in which case get the value. */ if (cfg_obj_istuple(ce)) { - ce = cfg_tuple_get(ce, "value"); - if (has_negative != NULL) - *has_negative = ISC_TRUE; + const cfg_obj_t *negated = + cfg_tuple_get(ce, "negated"); + if (! cfg_obj_isvoid(negated)) { + ce = negated; + if (has_negative != NULL) + *has_negative = ISC_TRUE; + } } if (cfg_obj_istype(ce, &cfg_type_keyref)) { @@ -244,6 +255,12 @@ count_acl_elements(const cfg_obj_t *caml, const cfg_obj_t *cctx, n += count_acl_elements(ce, cctx, &negative); if (negative) n++; +#ifdef HAVE_GEOIP + } else if (cfg_obj_istuple(ce) && + cfg_obj_isvoid(cfg_tuple_get(ce, "negated"))) + { + n++; +#endif /* HAVE_GEOIP */ } else if (cfg_obj_isstring(ce)) { const char *name = cfg_obj_asstring(ce); if (strcasecmp(name, "localhost") == 0 || @@ -262,6 +279,267 @@ count_acl_elements(const cfg_obj_t *caml, const cfg_obj_t *cctx, return n; } +#ifdef HAVE_GEOIP +static dns_geoip_subtype_t +get_subtype(const cfg_obj_t *obj, isc_log_t *lctx, + dns_geoip_subtype_t subtype, const char *dbname) +{ + if (dbname == NULL) + return (subtype); + + switch (subtype) { + case dns_geoip_countrycode: + if (strcasecmp(dbname, "city") == 0) + return (dns_geoip_city_countrycode); + else if (strcasecmp(dbname, "region") == 0) + return (dns_geoip_region_countrycode); + else if (strcasecmp(dbname, "country") == 0) + return (dns_geoip_country_code); + cfg_obj_log(obj, lctx, ISC_LOG_ERROR, + "invalid GeoIP DB specified for " + "country search: ignored"); + return (subtype); + case dns_geoip_countrycode3: + if (strcasecmp(dbname, "city") == 0) + return (dns_geoip_city_countrycode3); + else if (strcasecmp(dbname, "country") == 0) + return (dns_geoip_country_code3); + cfg_obj_log(obj, lctx, ISC_LOG_ERROR, + "invalid GeoIP DB specified for " + "country search: ignored"); + return (subtype); + case dns_geoip_countryname: + if (strcasecmp(dbname, "city") == 0) + return (dns_geoip_city_countryname); + else if (strcasecmp(dbname, "country") == 0) + return (dns_geoip_country_name); + cfg_obj_log(obj, lctx, ISC_LOG_ERROR, + "invalid GeoIP DB specified for " + "country search: ignored"); + return (subtype); + case dns_geoip_region: + if (strcasecmp(dbname, "city") == 0) + return (dns_geoip_city_region); + else if (strcasecmp(dbname, "region") == 0) + return (dns_geoip_region_code); + cfg_obj_log(obj, lctx, ISC_LOG_ERROR, + "invalid GeoIP DB specified for " + "region search: ignored"); + return (subtype); + case dns_geoip_regionname: + if (strcasecmp(dbname, "city") == 0) + return (dns_geoip_city_region); + else if (strcasecmp(dbname, "region") == 0) + return (dns_geoip_region_name); + cfg_obj_log(obj, lctx, ISC_LOG_ERROR, + "invalid GeoIP DB specified for " + "region search: ignored"); + return (subtype); + + /* + * Log a warning if the wrong database was specified + * on an unambiguous query + */ + case dns_geoip_city_name: + case dns_geoip_city_postalcode: + case dns_geoip_city_metrocode: + case dns_geoip_city_areacode: + case dns_geoip_city_continentcode: + case dns_geoip_city_timezonecode: + if (strcasecmp(dbname, "city") != 0) + cfg_obj_log(obj, lctx, ISC_LOG_WARNING, + "invalid GeoIP DB specified for " + "a 'city'-only search type: ignoring"); + return (subtype); + case dns_geoip_isp_name: + if (strcasecmp(dbname, "isp") != 0) + cfg_obj_log(obj, lctx, ISC_LOG_WARNING, + "invalid GeoIP DB specified for " + "an 'isp' search: ignoring"); + return (subtype); + case dns_geoip_org_name: + if (strcasecmp(dbname, "org") != 0) + cfg_obj_log(obj, lctx, ISC_LOG_WARNING, + "invalid GeoIP DB specified for " + "an 'org' search: ignoring"); + return (subtype); + case dns_geoip_as_asnum: + if (strcasecmp(dbname, "asnum") != 0) + cfg_obj_log(obj, lctx, ISC_LOG_WARNING, + "invalid GeoIP DB specified for " + "an 'asnum' search: ignoring"); + return (subtype); + case dns_geoip_domain_name: + if (strcasecmp(dbname, "domain") != 0) + cfg_obj_log(obj, lctx, ISC_LOG_WARNING, + "invalid GeoIP DB specified for " + "a 'domain' search: ignoring"); + return (subtype); + case dns_geoip_netspeed_id: + if (strcasecmp(dbname, "netspeed") != 0) + cfg_obj_log(obj, lctx, ISC_LOG_WARNING, + "invalid GeoIP DB specified for " + "a 'netspeed' search: ignoring"); + return (subtype); + default: + INSIST(0); + } +} + +static isc_boolean_t +geoip_can_answer(dns_aclelement_t *elt, cfg_aclconfctx_t *ctx) { + if (ctx->geoip == NULL) + return (ISC_TRUE); + + switch (elt->geoip_elem.subtype) { + case dns_geoip_countrycode: + case dns_geoip_countrycode3: + case dns_geoip_countryname: + if (ctx->geoip->city_v4 != NULL || + ctx->geoip->city_v6 != NULL || + ctx->geoip->country_v4 != NULL || + ctx->geoip->country_v6 != NULL || + ctx->geoip->region != NULL) + return (ISC_TRUE); + case dns_geoip_region: + case dns_geoip_regionname: + if (ctx->geoip->city_v4 != NULL || + ctx->geoip->city_v6 != NULL || + ctx->geoip->region != NULL) + return (ISC_TRUE); + case dns_geoip_country_code: + case dns_geoip_country_code3: + case dns_geoip_country_name: + if (ctx->geoip->country_v4 != NULL || + ctx->geoip->country_v6 != NULL) + return (ISC_TRUE); + case dns_geoip_region_countrycode: + case dns_geoip_region_code: + case dns_geoip_region_name: + if (ctx->geoip->region != NULL) + return (ISC_TRUE); + case dns_geoip_city_countrycode: + case dns_geoip_city_countrycode3: + case dns_geoip_city_countryname: + case dns_geoip_city_region: + case dns_geoip_city_regionname: + case dns_geoip_city_name: + case dns_geoip_city_postalcode: + case dns_geoip_city_metrocode: + case dns_geoip_city_areacode: + case dns_geoip_city_continentcode: + case dns_geoip_city_timezonecode: + if (ctx->geoip->city_v4 != NULL || + ctx->geoip->city_v6 != NULL) + return (ISC_TRUE); + case dns_geoip_isp_name: + if (ctx->geoip->isp != NULL) + return (ISC_TRUE); + case dns_geoip_org_name: + if (ctx->geoip->org != NULL) + return (ISC_TRUE); + case dns_geoip_as_asnum: + if (ctx->geoip->as != NULL) + return (ISC_TRUE); + case dns_geoip_domain_name: + if (ctx->geoip->domain != NULL) + return (ISC_TRUE); + case dns_geoip_netspeed_id: + if (ctx->geoip->netspeed != NULL) + return (ISC_TRUE); + } + + return (ISC_FALSE); +} + +static isc_result_t +parse_geoip_element(const cfg_obj_t *obj, isc_log_t *lctx, + cfg_aclconfctx_t *ctx, dns_aclelement_t *de) +{ + const cfg_obj_t *ge; + const char *dbname = NULL; + const char *stype, *search; + dns_geoip_subtype_t subtype; + + ge = cfg_tuple_get(obj, "db"); + if (!cfg_obj_isvoid(ge)) + dbname = cfg_obj_asstring(ge); + + stype = cfg_obj_asstring(cfg_tuple_get(obj, "subtype")); + search = cfg_obj_asstring(cfg_tuple_get(obj, "search")); + + if (strcasecmp(stype, "country") == 0 && strlen(search) == 2) { + /* Two-letter country code */ + subtype = dns_geoip_countrycode; + strncpy(de->geoip_elem.as_string, search, 2); + } else if (strcasecmp(stype, "country") == 0 && strlen(search) == 3) { + /* Three-letter country code */ + subtype = dns_geoip_countrycode3; + strncpy(de->geoip_elem.as_string, search, 3); + } else if (strcasecmp(stype, "country") == 0) { + /* Country name */ + subtype = dns_geoip_countryname; + strncpy(de->geoip_elem.as_string, search, 255); + } else if (strcasecmp(stype, "region") == 0 && strlen(search) == 2) { + /* Two-letter region code */ + subtype = dns_geoip_region; + strncpy(de->geoip_elem.as_string, search, 2); + } else if (strcasecmp(stype, "region") == 0) { + /* Region name */ + subtype = dns_geoip_regionname; + strncpy(de->geoip_elem.as_string, search, 255); + } else if (strcasecmp(stype, "city") == 0) { + /* City name */ + subtype = dns_geoip_city_name; + strncpy(de->geoip_elem.as_string, search, 255); + } else if (strcasecmp(stype, "postal") == 0 && strlen(search) < 7) { + subtype = dns_geoip_city_postalcode; + strncpy(de->geoip_elem.as_string, search, 6); + de->geoip_elem.as_string[6] = '\0'; + } else if (strcasecmp(stype, "metro") == 0) { + subtype = dns_geoip_city_metrocode; + de->geoip_elem.as_int = atoi(search); + } else if (strcasecmp(stype, "area") == 0) { + subtype = dns_geoip_city_areacode; + de->geoip_elem.as_int = atoi(search); + } else if (strcasecmp(stype, "tz") == 0) { + subtype = dns_geoip_city_timezonecode; + strncpy(de->geoip_elem.as_string, search, 255); + } else if (strcasecmp(stype, "continent") == 0 && strlen(search) == 2) { + /* Two-letter continent code */ + subtype = dns_geoip_city_continentcode; + strncpy(de->geoip_elem.as_string, search, 2); + } else if (strcasecmp(stype, "isp") == 0) { + subtype = dns_geoip_isp_name; + strncpy(de->geoip_elem.as_string, search, 255); + } else if (strcasecmp(stype, "asnum") == 0) { + subtype = dns_geoip_as_asnum; + strncpy(de->geoip_elem.as_string, search, 255); + } else if (strcasecmp(stype, "org") == 0) { + subtype = dns_geoip_org_name; + strncpy(de->geoip_elem.as_string, search, 255); + } else if (strcasecmp(stype, "domain") == 0) { + subtype = dns_geoip_domain_name; + strncpy(de->geoip_elem.as_string, search, 255); + } else if (strcasecmp(stype, "netspeed") == 0) { + subtype = dns_geoip_netspeed_id; + de->geoip_elem.as_int = atoi(search); + } else + INSIST(0); + + de->geoip_elem.subtype = get_subtype(obj, lctx, subtype, dbname); + + if (! geoip_can_answer(de, ctx)) { + cfg_obj_log(obj, lctx, ISC_LOG_ERROR, + "no GeoIP database installed which can answer " + "queries of type '%s'", stype); + return (ISC_R_FAILURE); + } + + return (ISC_R_SUCCESS); +} +#endif + isc_result_t cfg_acl_fromconfig(const cfg_obj_t *caml, const cfg_obj_t *cctx, @@ -317,15 +595,18 @@ cfg_acl_fromconfig(const cfg_obj_t *caml, elt != NULL; elt = cfg_list_next(elt)) { const cfg_obj_t *ce = cfg_listelt_value(elt); - isc_boolean_t neg; + isc_boolean_t neg = ISC_FALSE; if (cfg_obj_istuple(ce)) { - /* This must be a negated element. */ - ce = cfg_tuple_get(ce, "value"); - neg = ISC_TRUE; - dacl->has_negatives = ISC_TRUE; - } else - neg = ISC_FALSE; + /* Might be a negated element */ + const cfg_obj_t *negated = + cfg_tuple_get(ce, "negated"); + if (! cfg_obj_isvoid(negated)) { + neg = ISC_TRUE; + dacl->has_negatives = ISC_TRUE; + ce = negated; + } + } /* * If nest_level is nonzero, then every element is @@ -405,6 +686,16 @@ nested_acl: &de->keyname); if (result != ISC_R_SUCCESS) goto cleanup; +#ifdef HAVE_GEOIP + } else if (cfg_obj_istuple(ce) && + cfg_obj_isvoid(cfg_tuple_get(ce, "negated"))) + { + result = parse_geoip_element(ce, lctx, ctx, de); + if (result != ISC_R_SUCCESS) + goto cleanup; + de->type = dns_aclelementtype_geoip; + de->negative = neg; +#endif /* HAVE_GEOIP */ } else if (cfg_obj_isstring(ce)) { /* ACL name. */ const char *name = cfg_obj_asstring(ce); diff --git a/lib/isccfg/include/isccfg/aclconf.h b/lib/isccfg/include/isccfg/aclconf.h index 38ab9f696f..b532e8c16d 100644 --- a/lib/isccfg/include/isccfg/aclconf.h +++ b/lib/isccfg/include/isccfg/aclconf.h @@ -24,11 +24,13 @@ #include +#include #include typedef struct cfg_aclconfctx { ISC_LIST(dns_acl_t) named_acl_cache; isc_mem_t *mctx; + dns_geoip_databases_t *geoip; isc_refcount_t references; } cfg_aclconfctx_t; diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 68cdd9c3b4..cf4e6ba8b4 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -82,6 +82,15 @@ doc_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type); static void doc_optional_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type); +static isc_result_t +parse_geoip(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); + +static void +print_geoip(cfg_printer_t *pctx, const cfg_obj_t *obj); + +static void +doc_geoip(cfg_printer_t *pctx, const cfg_type_t *type); + static cfg_type_t cfg_type_acl; static cfg_type_t cfg_type_addrmatchelt; static cfg_type_t cfg_type_bracketed_aml; @@ -927,6 +936,7 @@ options_clauses[] = { { "fake-iquery", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, { "files", &cfg_type_size, 0 }, { "flush-zones-on-shutdown", &cfg_type_boolean, 0 }, + { "geoip-directory", &cfg_type_qstringornone, 0 }, { "has-old-clients", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, { "heartbeat-interval", &cfg_type_uint32, 0 }, { "host-statistics", &cfg_type_boolean, CFG_CLAUSEFLAG_NOTIMP }, @@ -2103,6 +2113,99 @@ static cfg_type_t cfg_type_optional_keyref = { doc_optional_keyvalue, &cfg_rep_string, &key_kw }; +/* + * "geoip" ACL element: + * geoip [ db ] search-type + */ +static const char *geoiptype_enums[] = { + "country", "country3", "countryname", "region", "regionname", + "city", "postal", "metrocode", "areacode", "timezone", "continent", + "isp", "domain", "asnum", "org", "netspeed", NULL +}; +static cfg_type_t cfg_type_geoiptype = { + "geoiptype", cfg_parse_enum, cfg_print_ustring, + cfg_doc_enum, &cfg_rep_string, &geoiptype_enums +}; + +static const char *geoipdb_enums[] = { + "country", "region", "city", + "isp", "domain", "asnum", "org", "netspeed", NULL +}; +static cfg_type_t cfg_type_geoipdb = { + "geoipdb", cfg_parse_enum, cfg_print_ustring, + cfg_doc_enum, &cfg_rep_string, &geoipdb_enums +}; + +static cfg_tuplefielddef_t geoip_fields[] = { + { "negated", &cfg_type_void, 0}, + { "db", &cfg_type_geoipdb, 0}, + { "subtype", &cfg_type_geoiptype, 0 }, + { "search", &cfg_type_astring, 0 }, + { NULL, NULL, 0 } +}; + +static cfg_type_t cfg_type_geoip = { + "geoip", parse_geoip, print_geoip, doc_geoip, + &cfg_rep_tuple, geoip_fields +}; + +static isc_result_t +parse_geoip(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { + isc_result_t result; + cfg_obj_t *obj = NULL; + const cfg_tuplefielddef_t *fields = type->of; + + CHECK(cfg_create_tuple(pctx, type, &obj)); + CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[0])); + + /* Parse the optional "db" field. */ + CHECK(cfg_peektoken(pctx, 0)); + if (pctx->token.type == isc_tokentype_string) { + CHECK(cfg_gettoken(pctx, 0)); + if (strcasecmp(TOKEN_STRING(pctx), "db") == 0 && + obj->value.tuple[1] == NULL) { + CHECK(cfg_parse_obj(pctx, fields[1].type, + &obj->value.tuple[1])); + } else { + CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[1])); + cfg_ungettoken(pctx); + } + } + + CHECK(cfg_parse_obj(pctx, fields[2].type, &obj->value.tuple[2])); + CHECK(cfg_parse_obj(pctx, fields[3].type, &obj->value.tuple[3])); + + *ret = obj; + return (ISC_R_SUCCESS); + + cleanup: + CLEANUP_OBJ(obj); + return (result); +} + +static void +print_geoip(cfg_printer_t *pctx, const cfg_obj_t *obj) { + if (obj->value.tuple[1]->type->print != cfg_print_void) { + cfg_print_cstr(pctx, " db "); + cfg_print_obj(pctx, obj->value.tuple[1]); + } + cfg_print_obj(pctx, obj->value.tuple[2]); + cfg_print_obj(pctx, obj->value.tuple[3]); +} + + +static void +doc_geoip(cfg_printer_t *pctx, const cfg_type_t *type) { + UNUSED(type); + cfg_print_cstr(pctx, "[ db "); + cfg_doc_enum(pctx, &cfg_type_geoipdb); + cfg_print_cstr(pctx, " ]"); + cfg_print_chars(pctx, " ", 1); + cfg_doc_enum(pctx, &cfg_type_geoiptype); + cfg_print_chars(pctx, " ", 1); + cfg_print_cstr(pctx, ""); +} + /*% * A "controls" statement is represented as a map with the multivalued * "inet" and "unix" clauses. @@ -2246,7 +2349,9 @@ static cfg_type_t cfg_type_statschannels = { * An optional class, as used in view and zone statements. */ static isc_result_t -parse_optional_class(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { +parse_optional_class(cfg_parser_t *pctx, const cfg_type_t *type, + cfg_obj_t **ret) +{ isc_result_t result; UNUSED(type); CHECK(cfg_peektoken(pctx, 0)); @@ -2369,6 +2474,16 @@ parse_addrmatchelt(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) if (pctx->token.type == isc_tokentype_string && (strcasecmp(TOKEN_STRING(pctx), "key") == 0)) { CHECK(cfg_parse_obj(pctx, &cfg_type_keyref, ret)); + } else if (pctx->token.type == isc_tokentype_string && + (strcasecmp(TOKEN_STRING(pctx), "geoip") == 0)) { +#ifdef HAVE_GEOIP + CHECK(cfg_gettoken(pctx, 0)); + CHECK(cfg_parse_obj(pctx, &cfg_type_geoip, ret)); +#else + cfg_parser_error(pctx, CFG_LOG_NEAR, + "'geoip' not supported in this build"); + return (ISC_R_UNEXPECTEDTOKEN); +#endif } else { if (cfg_lookingat_netaddr(pctx, CFG_ADDR_V4OK | CFG_ADDR_V4PREFIXOK | @@ -2406,7 +2521,7 @@ parse_addrmatchelt(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) */ static cfg_tuplefielddef_t negated_fields[] = { - { "value", &cfg_type_addrmatchelt, 0 }, + { "negated", &cfg_type_addrmatchelt, 0 }, { NULL, NULL, 0 } };